New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

phosphor-tabs

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

phosphor-tabs - npm Package Compare versions

Comparing version 0.9.8 to 1.0.0-beta

1

lib/index.d.ts

@@ -1,3 +0,2 @@

export * from './tab';
export * from './tabbar';
export * from './tabpanel';

@@ -12,3 +12,2 @@ /*-----------------------------------------------------------------------------

}
__export(require('./tab'));
__export(require('./tabbar'));

@@ -15,0 +14,0 @@ __export(require('./tabpanel'));

422

lib/tabbar.d.ts
import { Message } from 'phosphor-messaging';
import { Property } from 'phosphor-properties';
import { IObservableList } from 'phosphor-observablelist';
import { IChangedArgs, Property } from 'phosphor-properties';
import { ISignal, Signal } from 'phosphor-signaling';
import { Widget } from 'phosphor-widget';
import { Tab } from './tab';
import { Title, Widget } from 'phosphor-widget';
/**
* The arguments object for the [[tabDetachRequestedSignal]].
* An object which can be added to a tab bar.
*/
export interface ITabDetachArgs {
export interface ITabItem {
/**
* The tab of interest.
* The title object which provides data for the item's tab.
*
* #### Notes
* This should be a read-only property.
*/
tab: Tab;
/**
* The index of the tab.
*/
index: number;
/**
* The current mouse client X position.
*/
clientX: number;
/**
* The current mouse client Y position.
*/
clientY: number;
title: Title;
}
/**
* The arguments object for various tab bar signals
* A widget which displays a list of tab items as a row of tabs.
*/
export interface ITabIndexArgs {
export declare class TabBar<T extends ITabItem> extends Widget {
/**
* The index associated with the tab.
*/
index: number;
/**
* The tab associated with the signal.
*/
tab: Tab;
}
/**
* The arguments object for the [[tabMovedSignal]].
*/
export interface ITabMoveArgs {
/**
* The previous index of the tab.
*/
fromIndex: number;
/**
* The current index of the tab.
*/
toIndex: number;
}
/**
* A widget which displays a row of tabs.
*
* #### Notes
* A `TabBar` widget does not support child widgets. Adding children
* to a `TabBar` will result in undefined behavior.
*/
export declare class TabBar extends Widget {
/**
* Create the DOM node for a tab bar.

@@ -66,50 +27,25 @@ */

/**
* A signal emitted when a tab is moved.
* A signal emitted when the user clicks a tab item's close icon.
*
* **See also:** [[tabMoved]]
* **See also:** [[itemCloseRequested]]
*/
static tabMovedSignal: Signal<TabBar, ITabMoveArgs>;
static itemCloseRequestedSignal: Signal<TabBar<ITabItem>, ITabItem>;
/**
* A signal emitted when a tab is selected.
* The property descriptor for the currently selected tab item.
*
* **See also:** [[tabSelected]]
* **See also:** [[currentItem]]
*/
static tabSelectedSignal: Signal<TabBar, ITabIndexArgs>;
static currentItemProperty: Property<TabBar<ITabItem>, ITabItem>;
/**
* A signal emitted when the user clicks a tab close icon.
* The property descriptor for the observable list of tab items.
*
* **See also:** [[tabCloseRequested]
* **See also:** [[items]]
*/
static tabCloseRequestedSignal: Signal<TabBar, ITabIndexArgs>;
static itemsProperty: Property<TabBar<ITabItem>, IObservableList<ITabItem>>;
/**
* A signal emitted when a tab is dragged beyond the detach threshold.
* The property descriptor for whether the tabs are user-movable.
*
* **See also:** [[tabDetachRequested]]
*/
static tabDetachRequestedSignal: Signal<TabBar, ITabDetachArgs>;
/**
* The property descriptor for the previous tab.
*
* This controls which tab is selected after if selected tab is
* removed. It is typically updated automatically.
*
* **See also:** [[previousTab]]
*/
static previousTabProperty: Property<TabBar, Tab>;
/**
* The property descriptor for the selected tab.
*
* This controls which tab is selected in the tab bar.
*
* **See also:** [[selectedTab]]
*/
static selectedTabProperty: Property<TabBar, Tab>;
/**
* The property descriptor for the tabs movable property
*
* This controls whether tabs are movable by the user.
*
* **See also:** [[tabsMovable]]
*/
static tabsMovableProperty: Property<TabBar, boolean>;
static tabsMovableProperty: Property<TabBar<ITabItem>, boolean>;
/**

@@ -124,56 +60,42 @@ * Construct a new tab bar.

/**
* A signal emitted when a tab is moved.
* A signal emitted when the user clicks a tab item's close icon.
*
* #### Notes
* This is a pure delegate to the [[tabMovedSignal]].
* This is a pure delegate to the [[itemCloseRequestedSignal]].
*/
tabMoved: ISignal<TabBar, ITabMoveArgs>;
itemCloseRequested: ISignal<TabBar<T>, T>;
/**
* A signal emitted when a tab is selected.
* Get the currently selected tab item.
*
* #### Notes
* This is a pure delegate to the [[tabSelectedSignal]].
* This is a pure delegate to the [[currentItemProperty]].
*/
tabSelected: ISignal<TabBar, ITabIndexArgs>;
/**
* A signal emitted when the user clicks a tab close icon.
* Set the currently selected tab item.
*
* #### Notes
* This is a pure delegate to the [[tabCloseRequestedSignal]].
* This is a pure delegate to the [[currentItemProperty]].
*/
tabCloseRequested: ISignal<TabBar, ITabIndexArgs>;
currentItem: T;
/**
* A signal emitted when a tab is dragged beyond the detach threshold.
* A signal emitted when the current tab item is changed.
*
* #### Notes
* This is a pure delegate to the [[tabDetachRequestedSignal]].
* This is the notify signal for the [[currentItemProperty]].
*/
tabDetachRequested: ISignal<TabBar, ITabDetachArgs>;
currentItemChanged: ISignal<TabBar<T>, IChangedArgs<T>>;
/**
* Get the previously selected tab.
* Get the list of tab items for the tab bar.
*
* #### Notes
* This is a pure delegate to the [[previousTabProperty]].
* This is a pure delegate to the [[itemsProperty]].
*/
/**
* Set the previously selected tab.
* Set the list tab items for the tab bar.
*
* #### Notes
* This is a pure delegate to the [[previousTabProperty]].
* This is a pure delegate to the [[itemsProperty]].
*/
previousTab: Tab;
items: IObservableList<T>;
/**
* Get the selected tab.
*
* #### Notes
* This is a pure delegate to the [[selectedTabProperty]].
*/
/**
* Set the selected tab.
*
* #### Notes
* This is a pure delegate to the [[selectedTabProperty]].
*/
selectedTab: Tab;
/**
* Get whether the tabs are movable by the user.

@@ -192,161 +114,78 @@ *

/**
* Get a shallow copy of the array of tabs.
* Get the tab bar header node.
*
* #### Notes
* When only iterating over the tabs, it can be faster to use
* the tab query methods, which do not perform a copy.
*
* **See also:** [[tabCount]], [[tabAt]]
* This can be used to add extra header content.
*/
headerNode: HTMLElement;
/**
* Set the tabs for the tab bar.
* Get the tab bar body node.
*
* #### Notes
* This will clear the current tabs and add the specified tabs.
* Depending on the desired outcome, it can be more efficient to
* use one of the tab manipulation methods.
*
* **See also:** [[addTab]], [[insertTab]], [[removeTab]]
* This can be used to add extra body content.
*/
tabs: Tab[];
bodyNode: HTMLElement;
/**
* Get the number of tabs in the tab bar.
* Get the tab bar content node.
*
* #### Notes
* This is a read-only property.
*
* **See also:** [[tabs]], [[tabAt]]
* This is the node which holds the tab nodes. Modifying the content
* of this node indiscriminately can lead to undesired behavior.
*/
tabCount: number;
contentNode: HTMLElement;
/**
* Get the tab at a specific index.
* Get the tab bar footer node.
*
* @param index - The index of the tab of interest.
*
* @returns The tab at the specified index, or `undefined` if the
* index is out of range.
*
* **See also:** [[tabCount]], [[tabIndex]]
* #### Notes
* This can be used to add extra footer content.
*/
tabAt(index: number): Tab;
footerNode: HTMLElement;
/**
* Get the index of a specific tab.
* Handle the DOM events for the tab bar.
*
* @param tab - The tab of interest.
* @param event - The DOM event sent to the tab bar.
*
* @returns The index of the specified tab, or `-1` if the tab is
* not contained within the tab bar.
*
* **See also:** [[tabCount]], [[tabAt]]
*/
tabIndex(tab: Tab): number;
/**
* Add a tab to the end of the tab bar.
*
* @param tab - The tab to add to the tab bar.
*
* @returns The new index of the tab.
*
* #### Notes
* If the tab is already contained within the tab bar, it will first
* be removed.
*
* The tab *must not* be contained by any other tab bar.
*
* **See also:** [[insertTab]], [[moveTab]]
* This method implements the DOM `EventListener` interface and is
* called in response to events on the tab bar's DOM node. It should
* not be called directly by user code.
*/
addTab(tab: Tab): number;
handleEvent(event: Event): void;
/**
* Insert a tab into the tab bar at the given index.
* Process a message sent to the tab bar.
*
* @param index - The index at which to insert the tab. This will be
* clamped to the bounds of the tabs.
* @param msg - The message sent to the tab bar.
*
* @param tab - The tab to add to the tab bar.
*
* @returns The new index of the tab.
*
* #### Notes
* If the tab is already contained within the tab bar, it will first
* be removed.
*
* The tab *must not* be contained by any other tab bar.
*
* **See also:** [[addTab]], [[moveTab]]
* Subclasses may reimplement this method as needed.
*/
insertTab(index: number, tab: Tab): number;
processMessage(msg: Message): void;
/**
* Move a tab from one index to another.
* Release the mouse and restore the non-dragged tab positions.
*
* @param fromIndex - The index of the tab to move.
*
* @param toIndex - The target index of the tab.
*
* @returns `true` if the move was successful, or `false` if either
* index is out of range.
*
* #### Notes
* This can be more efficient than re-inserting an existing tab.
*
* **See also:** [[addTab]], [[insertTab]]
* This will cause the tab bar to stop handling mouse events and to
* restore the tabs their non-dragged positions. It is intended to
* be called by subclasses which implement [[onTearOffRequest]].
*/
moveTab(fromIndex: number, toIndex: number): boolean;
protected releaseMouse(): void;
/**
* Remove the tab at a specific index.
* A message handler invoked on a `'tear-off-request'` message.
*
* @param index - The index of the tab of interest.
*
* @returns The removed tab, or `undefined` if the index is out
* of range.
*
* **See also:** [[removeTab]], [[clearTabs]]
*/
removeTabAt(index: number): Tab;
/**
* Remove a specific tab from the tab bar.
*
* @param tab - The tab of interest.
*
* @returns The index occupied by the tab, or `-1` if the tab is
* not contained by the tab bar.
*
* **See also:** [[removeTabAt]], [[clearTabs]]
*/
removeTab(tab: Tab): number;
/**
* Remove all tabs from the tab bar.
*
* **See also:** [[removeTab]], [[removeTabAt]]
*/
clearTabs(): void;
/**
* Add a tab to the tab bar at the given client X position.
*
* @param tab - The tab to attach to the tab bar.
*
* @param clientX - The current client X mouse position.
*
* @returns `true` if the tab was attached, `false` otherwise.
*
* #### Notes
* This method is intended for use by code which supports tear-off
* tab interfaces. It will insert the tab at the specified location
* and grab the mouse to continue the tab drag. It assumes that the
* left mouse button is currently pressed.
* This may be reimplemented by subclasses to support tear-off tabs.
*
* This is a no-op if the tab is already contained by the tab bar,
* if the tabs are not movable, or if a tab drag is in progress.
*/
attachTab(tab: Tab, clientX: number): boolean;
/**
* Handle the DOM events for the tab bar.
* The reimplementation should take whatever action is necessary for
* its use case to continue the drag from the given client position.
* This will typically involve creating a new DOM node to represent
* the drag item, and may or may not include removing the specified
* item from the tab bar.
*
* @param event - The DOM event sent to the tab bar.
* If the reimplementation handles the tear-off, it should call the
* [[releaseMouse]] method so that the tab bar ceases its handling
* of mouse events.
*
* #### Notes
* This method implements the DOM `EventListener` interface and is
* called in response to events on the tab bar's DOM node. It should
* not be called directly by user code.
* The default implementation of this handler is a no-op.
*/
handleEvent(event: Event): void;
protected onTearOffRequest(msg: TearOffMessage<T>): void;
/**

@@ -357,6 +196,12 @@ * A message handler invoked on an `'after-attach'` message.

/**
* A message handler invoked on a `'before-dettach'` message.
* A message handler invoked on a `'before-detach'` message.
*/
protected onBeforeDetach(msg: Message): void;
/**
* A message handler invoked on an `'update-request'` message.
*
* This handler updates the flex order and z-index of the tabs.
*/
protected onUpdateRequest(msg: Message): void;
/**
* Handle the `'click'` event for the tab bar.

@@ -378,41 +223,86 @@ */

/**
* Update the drag tab position for the given mouse X position.
*
* This method is a no-op if an active drag is not in progress.
* Release the mouse and restore the non-dragged tab positions.
*/
private _updateDragPosition(clientX);
private _releaseMouse();
/**
* Release the mouse grab and restore the tab positions.
* The coerce handler for the [[currentItemProperty]].
*/
private _releaseMouse();
private _coerceCurrentItem(item);
/**
* Insert a new tab into the tab bar at the given index.
*
* The tab should not already be contained in the tab bar.
*
* The mouse should be released before calling this method.
* The change handler for the [[currentItemProperty]].
*/
private _insertTab(index, tab);
private _onCurrentItemChanged(oldItem, newItem);
/**
* Move a tab to a new index in the tab bar.
*
* The mouse should be released before calling this method.
* The change handler for the [[itemsProperty]].
*/
private _moveTab(fromIndex, toIndex);
private _onItemsChanged(oldList, newList);
/**
* Remove and return the tab at the given index.
*
* The mouse should be released before calling this method.
* The change handler for the items list `changed` signal.
*/
private _removeTab(index);
private _onItemsListChanged(sender, args);
/**
* Update the Z-index and flex order of the tabs.
* The handler invoked on a items list change of type `Add`.
*/
private _updateTabOrdering();
private _onItemsListAdd(args);
/**
* The change handler for the [[selectedTabProperty]].
* The handler invoked on a items list change of type `Move`.
*/
private _onSelectedTabChanged(old, tab);
private _onItemsListMove(args);
/**
* The handler invoked on a items list change of type `Remove`.
*/
private _onItemsListRemove(args);
/**
* The handler invoked on a items list change of type `Replace`.
*/
private _onItemsListReplace(args);
/**
* The handler invoked on a items list change of type `Set`.
*/
private _onItemsListSet(args);
private _tabs;
private _dragData;
}
/**
* A message class for `'tear-off-request'` messages.
*
* #### Notes
* A message of this type is sent to a tab bar when the user drags
* a tab beyond the tear-off threshold which surrounds the tab bar.
*/
export declare class TearOffMessage<T extends ITabItem> extends Message {
/**
* Construct a new tear off request message.
*
* @param item - The tab item being dragged by the user.
*
* @param clientX - The current client X position of the mouse.
*
* @param clientY - The current client Y position of the mouse.
*/
constructor(item: T, clientX: number, clientY: number);
/**
* The tab item being dragged by the user.
*
* #### Notes
* This is a read-only property.
*/
item: T;
/**
* The current client X position of the mouse.
*
* #### Notes
* This is a read-only property.
*/
clientX: number;
/**
* The current client Y position of the mouse.
*
* #### Notes
* This is a read-only property.
*/
clientY: number;
private _item;
private _clientX;
private _clientY;
}

@@ -16,2 +16,5 @@ /*-----------------------------------------------------------------------------

var phosphor_domutil_1 = require('phosphor-domutil');
var phosphor_messaging_1 = require('phosphor-messaging');
var phosphor_nodewrapper_1 = require('phosphor-nodewrapper');
var phosphor_observablelist_1 = require('phosphor-observablelist');
var phosphor_properties_1 = require('phosphor-properties');

@@ -25,22 +28,46 @@ var phosphor_signaling_1 = require('phosphor-signaling');

/**
* The class name added to the tab bar header div.
* The class name added to the tab bar header node.
*/
var HEADER_CLASS = 'p-TabBar-header';
/**
* The class name added to the tab bar content div.
* The class name added to the tab bar body node.
*/
var BODY_CLASS = 'p-TabBar-body';
/**
* The class name added to the tab bar content node.
*/
var CONTENT_CLASS = 'p-TabBar-content';
/**
* The class name added to the tab bar footer div.
* The class name added to the tab bar footer node.
*/
var FOOTER_CLASS = 'p-TabBar-footer';
/**
* A class name added to the tab bar when dragging.
* The class name added to Tab instances.
*/
var TAB_CLASS = 'p-Tab';
/**
* The class name added to a tab text node.
*/
var TEXT_CLASS = 'p-Tab-text';
/**
* The class name added to a tab icon node.
*/
var ICON_CLASS = 'p-Tab-icon';
/**
* The class name added to a tab close node.
*/
var CLOSE_CLASS = 'p-Tab-close';
/**
* The class name added to a tab bar and tab when dragging.
*/
var DRAGGING_CLASS = 'p-mod-dragging';
/**
* A class name added to the active drag tab.
* The class name added to the current tab.
*/
var ACTIVE_CLASS = 'p-mod-active';
var CURRENT_CLASS = 'p-mod-current';
/**
* The class name added to a closable tab.
*/
var CLOSABLE_CLASS = 'p-mod-closable';
/**
* A class name added to the first tab in the tab bar.

@@ -50,3 +77,3 @@ */

/**
* A class name adde to the last tab in the tab bar.
* A class name added to the last tab in the tab bar.
*/

@@ -59,15 +86,11 @@ var LAST_CLASS = 'p-mod-last';

/**
* The detach distance threshold.
* The tear-off distance threshold.
*/
var DETACH_THRESHOLD = 20;
var TEAR_OFF_THRESHOLD = 20;
/**
* The tab transition duration. Keep in sync with CSS.
* The tab transition duration.
*/
var TRANSITION_DURATION = 150;
var TRANSITION_DURATION = 150; // Keep in sync with CSS.
/**
* A widget which displays a row of tabs.
*
* #### Notes
* A `TabBar` widget does not support child widgets. Adding children
* to a `TabBar` will result in undefined behavior.
* A widget which displays a list of tab items as a row of tabs.
*/

@@ -91,9 +114,12 @@ var TabBar = (function (_super) {

var header = document.createElement('div');
var content = document.createElement('div');
var body = document.createElement('div');
var content = document.createElement('ul');
var footer = document.createElement('div');
header.className = HEADER_CLASS;
body.className = BODY_CLASS;
content.className = CONTENT_CLASS;
footer.className = FOOTER_CLASS;
body.appendChild(content);
node.appendChild(header);
node.appendChild(content);
node.appendChild(body);
node.appendChild(footer);

@@ -107,14 +133,15 @@ return node;

this._releaseMouse();
this._tabs.forEach(function (tab) { tab.dispose(); });
this._tabs.length = 0;
_super.prototype.dispose.call(this);
};
Object.defineProperty(TabBar.prototype, "tabMoved", {
Object.defineProperty(TabBar.prototype, "itemCloseRequested", {
/**
* A signal emitted when a tab is moved.
* A signal emitted when the user clicks a tab item's close icon.
*
* #### Notes
* This is a pure delegate to the [[tabMovedSignal]].
* This is a pure delegate to the [[itemCloseRequestedSignal]].
*/
get: function () {
return TabBar.tabMovedSignal.bind(this);
return TabBar.itemCloseRequestedSignal.bind(this);
},

@@ -124,24 +151,20 @@ enumerable: true,

});
Object.defineProperty(TabBar.prototype, "tabSelected", {
Object.defineProperty(TabBar.prototype, "currentItem", {
/**
* A signal emitted when a tab is selected.
* Get the currently selected tab item.
*
* #### Notes
* This is a pure delegate to the [[tabSelectedSignal]].
* This is a pure delegate to the [[currentItemProperty]].
*/
get: function () {
return TabBar.tabSelectedSignal.bind(this);
return TabBar.currentItemProperty.get(this);
},
enumerable: true,
configurable: true
});
Object.defineProperty(TabBar.prototype, "tabCloseRequested", {
/**
* A signal emitted when the user clicks a tab close icon.
* Set the currently selected tab item.
*
* #### Notes
* This is a pure delegate to the [[tabCloseRequestedSignal]].
* This is a pure delegate to the [[currentItemProperty]].
*/
get: function () {
return TabBar.tabCloseRequestedSignal.bind(this);
set: function (value) {
TabBar.currentItemProperty.set(this, value);
},

@@ -151,11 +174,11 @@ enumerable: true,

});
Object.defineProperty(TabBar.prototype, "tabDetachRequested", {
Object.defineProperty(TabBar.prototype, "currentItemChanged", {
/**
* A signal emitted when a tab is dragged beyond the detach threshold.
* A signal emitted when the current tab item is changed.
*
* #### Notes
* This is a pure delegate to the [[tabDetachRequestedSignal]].
* This is the notify signal for the [[currentItemProperty]].
*/
get: function () {
return TabBar.tabDetachRequestedSignal.bind(this);
return TabBar.currentItemProperty.notify.bind(this);
},

@@ -165,20 +188,20 @@ enumerable: true,

});
Object.defineProperty(TabBar.prototype, "previousTab", {
Object.defineProperty(TabBar.prototype, "items", {
/**
* Get the previously selected tab.
* Get the list of tab items for the tab bar.
*
* #### Notes
* This is a pure delegate to the [[previousTabProperty]].
* This is a pure delegate to the [[itemsProperty]].
*/
get: function () {
return TabBar.previousTabProperty.get(this);
return TabBar.itemsProperty.get(this);
},
/**
* Set the previously selected tab.
* Set the list tab items for the tab bar.
*
* #### Notes
* This is a pure delegate to the [[previousTabProperty]].
* This is a pure delegate to the [[itemsProperty]].
*/
set: function (value) {
TabBar.previousTabProperty.set(this, value);
TabBar.itemsProperty.set(this, value);
},

@@ -188,20 +211,20 @@ enumerable: true,

});
Object.defineProperty(TabBar.prototype, "selectedTab", {
Object.defineProperty(TabBar.prototype, "tabsMovable", {
/**
* Get the selected tab.
* Get whether the tabs are movable by the user.
*
* #### Notes
* This is a pure delegate to the [[selectedTabProperty]].
* This is a pure delegate to the [[tabsMovableProperty]].
*/
get: function () {
return TabBar.selectedTabProperty.get(this);
return TabBar.tabsMovableProperty.get(this);
},
/**
* Set the selected tab.
* Set whether the tabs are movable by the user.
*
* #### Notes
* This is a pure delegate to the [[selectedTabProperty]].
* This is a pure delegate to the [[tabsMovableProperty]].
*/
set: function (value) {
TabBar.selectedTabProperty.set(this, value);
TabBar.tabsMovableProperty.set(this, value);
},

@@ -211,20 +234,24 @@ enumerable: true,

});
Object.defineProperty(TabBar.prototype, "tabsMovable", {
Object.defineProperty(TabBar.prototype, "headerNode", {
/**
* Get whether the tabs are movable by the user.
* Get the tab bar header node.
*
* #### Notes
* This is a pure delegate to the [[tabsMovableProperty]].
* This can be used to add extra header content.
*/
get: function () {
return TabBar.tabsMovableProperty.get(this);
return this.node.getElementsByClassName(HEADER_CLASS)[0];
},
enumerable: true,
configurable: true
});
Object.defineProperty(TabBar.prototype, "bodyNode", {
/**
* Set whether the tabs are movable by the user.
* Get the tab bar body node.
*
* #### Notes
* This is a pure delegate to the [[tabsMovableProperty]].
* This can be used to add extra body content.
*/
set: function (value) {
TabBar.tabsMovableProperty.set(this, value);
get: function () {
return this.node.getElementsByClassName(BODY_CLASS)[0];
},

@@ -234,44 +261,25 @@ enumerable: true,

});
Object.defineProperty(TabBar.prototype, "tabs", {
Object.defineProperty(TabBar.prototype, "contentNode", {
/**
* Get a shallow copy of the array of tabs.
* Get the tab bar content node.
*
* #### Notes
* When only iterating over the tabs, it can be faster to use
* the tab query methods, which do not perform a copy.
*
* **See also:** [[tabCount]], [[tabAt]]
* This is the node which holds the tab nodes. Modifying the content
* of this node indiscriminately can lead to undesired behavior.
*/
get: function () {
return this._tabs.slice();
return this.node.getElementsByClassName(CONTENT_CLASS)[0];
},
/**
* Set the tabs for the tab bar.
*
* #### Notes
* This will clear the current tabs and add the specified tabs.
* Depending on the desired outcome, it can be more efficient to
* use one of the tab manipulation methods.
*
* **See also:** [[addTab]], [[insertTab]], [[removeTab]]
*/
set: function (tabs) {
var _this = this;
this.clearTabs();
tabs.forEach(function (tab) { return _this.addTab(tab); });
},
enumerable: true,
configurable: true
});
Object.defineProperty(TabBar.prototype, "tabCount", {
Object.defineProperty(TabBar.prototype, "footerNode", {
/**
* Get the number of tabs in the tab bar.
* Get the tab bar footer node.
*
* #### Notes
* This is a read-only property.
*
* **See also:** [[tabs]], [[tabAt]]
* This can be used to add extra footer content.
*/
get: function () {
return this._tabs.length;
return this.node.getElementsByClassName(FOOTER_CLASS)[0];
},

@@ -282,184 +290,2 @@ enumerable: true,

/**
* Get the tab at a specific index.
*
* @param index - The index of the tab of interest.
*
* @returns The tab at the specified index, or `undefined` if the
* index is out of range.
*
* **See also:** [[tabCount]], [[tabIndex]]
*/
TabBar.prototype.tabAt = function (index) {
return this._tabs[index | 0];
};
/**
* Get the index of a specific tab.
*
* @param tab - The tab of interest.
*
* @returns The index of the specified tab, or `-1` if the tab is
* not contained within the tab bar.
*
* **See also:** [[tabCount]], [[tabAt]]
*/
TabBar.prototype.tabIndex = function (tab) {
return this._tabs.indexOf(tab);
};
/**
* Add a tab to the end of the tab bar.
*
* @param tab - The tab to add to the tab bar.
*
* @returns The new index of the tab.
*
* #### Notes
* If the tab is already contained within the tab bar, it will first
* be removed.
*
* The tab *must not* be contained by any other tab bar.
*
* **See also:** [[insertTab]], [[moveTab]]
*/
TabBar.prototype.addTab = function (tab) {
return this.insertTab(this._tabs.length, tab);
};
/**
* Insert a tab into the tab bar at the given index.
*
* @param index - The index at which to insert the tab. This will be
* clamped to the bounds of the tabs.
*
* @param tab - The tab to add to the tab bar.
*
* @returns The new index of the tab.
*
* #### Notes
* If the tab is already contained within the tab bar, it will first
* be removed.
*
* The tab *must not* be contained by any other tab bar.
*
* **See also:** [[addTab]], [[moveTab]]
*/
TabBar.prototype.insertTab = function (index, tab) {
this.removeTab(tab);
return this._insertTab(index, tab);
};
/**
* Move a tab from one index to another.
*
* @param fromIndex - The index of the tab to move.
*
* @param toIndex - The target index of the tab.
*
* @returns `true` if the move was successful, or `false` if either
* index is out of range.
*
* #### Notes
* This can be more efficient than re-inserting an existing tab.
*
* **See also:** [[addTab]], [[insertTab]]
*/
TabBar.prototype.moveTab = function (fromIndex, toIndex) {
this._releaseMouse();
return this._moveTab(fromIndex, toIndex);
};
/**
* Remove the tab at a specific index.
*
* @param index - The index of the tab of interest.
*
* @returns The removed tab, or `undefined` if the index is out
* of range.
*
* **See also:** [[removeTab]], [[clearTabs]]
*/
TabBar.prototype.removeTabAt = function (index) {
this._releaseMouse();
return this._removeTab(index);
};
/**
* Remove a specific tab from the tab bar.
*
* @param tab - The tab of interest.
*
* @returns The index occupied by the tab, or `-1` if the tab is
* not contained by the tab bar.
*
* **See also:** [[removeTabAt]], [[clearTabs]]
*/
TabBar.prototype.removeTab = function (tab) {
this._releaseMouse();
var i = this._tabs.indexOf(tab);
if (i !== -1)
this._removeTab(i);
return i;
};
/**
* Remove all tabs from the tab bar.
*
* **See also:** [[removeTab]], [[removeTabAt]]
*/
TabBar.prototype.clearTabs = function () {
while (this._tabs.length > 0) {
this.removeTabAt(this._tabs.length - 1);
}
};
/**
* Add a tab to the tab bar at the given client X position.
*
* @param tab - The tab to attach to the tab bar.
*
* @param clientX - The current client X mouse position.
*
* @returns `true` if the tab was attached, `false` otherwise.
*
* #### Notes
* This method is intended for use by code which supports tear-off
* tab interfaces. It will insert the tab at the specified location
* and grab the mouse to continue the tab drag. It assumes that the
* left mouse button is currently pressed.
*
* This is a no-op if the tab is already contained by the tab bar,
* if the tabs are not movable, or if a tab drag is in progress.
*/
TabBar.prototype.attachTab = function (tab, clientX) {
// Bail if there is a drag in progress or the tabs aren't movable.
if (this._dragData || !this.tabsMovable) {
return false;
}
// Bail if the tab is already part of the tab bar.
if (this._tabs.indexOf(tab) !== -1) {
return false;
}
// Insert and select the new tab.
var index = this._tabs.length;
this._insertTab(index, tab);
this.selectedTab = tab;
// Setup the drag data object.
var content = this.node.firstChild.nextSibling;
var tabRect = tab.node.getBoundingClientRect();
var data = this._dragData = new DragData();
data.tab = tab;
data.tabIndex = index;
data.tabLeft = tab.node.offsetLeft;
data.tabWidth = tabRect.width;
data.pressX = tabRect.left + Math.floor(0.4 * tabRect.width);
data.pressY = tabRect.top + (tabRect.height >> 1);
data.tabPressX = Math.floor(0.4 * tabRect.width);
data.tabLayout = snapTabLayout(this._tabs);
data.contentRect = content.getBoundingClientRect();
data.cursorGrab = phosphor_domutil_1.overrideCursor('default');
data.dragActive = true;
// Add the extra mouse event listeners.
document.addEventListener('mouseup', this, true);
document.addEventListener('mousemove', this, true);
// Add the dragging style classes.
tab.addClass(ACTIVE_CLASS);
this.addClass(DRAGGING_CLASS);
// Update the drag tab position.
this._updateDragPosition(clientX);
return true;
};
/**
* Handle the DOM events for the tab bar.

@@ -491,16 +317,82 @@ *

/**
* Process a message sent to the tab bar.
*
* @param msg - The message sent to the tab bar.
*
* #### Notes
* Subclasses may reimplement this method as needed.
*/
TabBar.prototype.processMessage = function (msg) {
if (msg.type === 'tear-off-request') {
this.onTearOffRequest(msg);
}
else {
_super.prototype.processMessage.call(this, msg);
}
};
/**
* Release the mouse and restore the non-dragged tab positions.
*
* #### Notes
* This will cause the tab bar to stop handling mouse events and to
* restore the tabs their non-dragged positions. It is intended to
* be called by subclasses which implement [[onTearOffRequest]].
*/
TabBar.prototype.releaseMouse = function () {
this._releaseMouse();
};
/**
* A message handler invoked on a `'tear-off-request'` message.
*
* #### Notes
* This may be reimplemented by subclasses to support tear-off tabs.
*
* The reimplementation should take whatever action is necessary for
* its use case to continue the drag from the given client position.
* This will typically involve creating a new DOM node to represent
* the drag item, and may or may not include removing the specified
* item from the tab bar.
*
* If the reimplementation handles the tear-off, it should call the
* [[releaseMouse]] method so that the tab bar ceases its handling
* of mouse events.
*
* The default implementation of this handler is a no-op.
*/
TabBar.prototype.onTearOffRequest = function (msg) { };
/**
* A message handler invoked on an `'after-attach'` message.
*/
TabBar.prototype.onAfterAttach = function (msg) {
this.node.addEventListener('click', this);
this.node.addEventListener('mousedown', this);
this.node.addEventListener('click', this);
};
/**
* A message handler invoked on a `'before-dettach'` message.
* A message handler invoked on a `'before-detach'` message.
*/
TabBar.prototype.onBeforeDetach = function (msg) {
this.node.removeEventListener('click', this);
this.node.removeEventListener('mousedown', this);
this.node.removeEventListener('click', this);
};
/**
* A message handler invoked on an `'update-request'` message.
*
* This handler updates the flex order and z-index of the tabs.
*/
TabBar.prototype.onUpdateRequest = function (msg) {
for (var i = 0, n = this._tabs.length, k = n - 1; i < n; ++i) {
var tab = this._tabs[i];
var style = tab.node.style;
if (tab.hasClass(CURRENT_CLASS)) {
style.zIndex = n + '';
}
else {
style.zIndex = k-- + '';
}
style.order = i + '';
tab.toggleClass(FIRST_CLASS, i === 0);
tab.toggleClass(LAST_CLASS, i === n - 1);
}
};
/**
* Handle the `'click'` event for the tab bar.

@@ -521,8 +413,6 @@ */

event.stopPropagation();
// If the click was on a node contained by the close icon node
// of a closable tab, emit the `tabCloseRequested` signal.
// Emit the close requested signal if the close icon was clicked.
var tab = this._tabs[index];
var target = event.target;
if (tab.closable && tab.closeIconNode.contains(target)) {
this.tabCloseRequested.emit({ index: index, tab: tab });
if (tab.closeNode.contains(event.target)) {
this.itemCloseRequested.emit(tab.item);
}

@@ -542,3 +432,3 @@ };

}
// Do nothing of the press is not on a tab.
// Do nothing if the press is not on a tab.
var index = hitTestTabs(this._tabs, event.clientX, event.clientY);

@@ -551,5 +441,5 @@ if (index < 0) {

event.stopPropagation();
// Do nothing further if the press was on the tab close icon.
// Do nothing if the press was on a close icon node.
var tab = this._tabs[index];
if (tab.closeIconNode.contains(event.target)) {
if (tab.closeNode.contains(event.target)) {
return;

@@ -571,4 +461,4 @@ }

}
// Update the selected tab to the pressed tab.
this.selectedTab = tab;
// Update the current item to the pressed item.
this.currentItem = tab.item;
};

@@ -584,8 +474,8 @@ /**

// Bail if there is no drag in progress.
if (!this._dragData) {
var data = this._dragData;
if (!data) {
return;
}
// Check to see if the drag threshold has been exceeded, and
// start the tab drag operation the first time that occurrs.
var data = this._dragData;
// start the tab drag operation the first time that occurs.
if (!data.dragActive) {

@@ -598,22 +488,20 @@ var dx = Math.abs(event.clientX - data.pressX);

// Fill in the remaining drag data.
var content = this.node.firstChild.nextSibling;
data.contentRect = this.contentNode.getBoundingClientRect();
data.tabLayout = snapTabLayout(this._tabs);
data.contentRect = content.getBoundingClientRect();
data.cursorGrab = phosphor_domutil_1.overrideCursor('default');
data.dragActive = true;
// Add the dragging style classes.
data.tab.addClass(ACTIVE_CLASS);
data.tab.addClass(DRAGGING_CLASS);
this.addClass(DRAGGING_CLASS);
}
// Check to see if the detach threshold has been exceeded, and
// emit the detach request signal the first time that occurrs.
// If the drag data gets set to null, the mouse was released.
if (!data.detachRequested && shouldDetach(data.contentRect, event)) {
data.detachRequested = true;
this.tabDetachRequested.emit({
tab: data.tab,
index: data.tabIndex,
clientX: event.clientX,
clientY: event.clientY,
});
// Check to see if the tear-off threshold has been exceeded.
if (!data.tearOffRequested && tearOffExceeded(data.contentRect, event)) {
// Only make the tear-off request once per drag action.
data.tearOffRequested = true;
// Send the tear-off request message to the tab bar.
var item = data.tab.item;
var clientX = event.clientX;
var clientY = event.clientY;
phosphor_messaging_1.sendMessage(this, new TearOffMessage(item, clientX, clientY));
// Do nothing further if the mouse has been released.
if (!this._dragData) {

@@ -623,4 +511,31 @@ return;

}
// Compute the target bounds of the drag tab.
var offsetLeft = event.clientX - data.contentRect.left;
var targetLeft = offsetLeft - data.tabPressX;
var targetRight = targetLeft + data.tabWidth;
// Reset the target tab index.
data.tabTargetIndex = data.tabIndex;
// Update the non-drag tab positions and the tab target index.
var tabs = this._tabs;
for (var i = 0, n = tabs.length; i < n; ++i) {
var style = tabs[i].node.style;
var layout = data.tabLayout[i];
var threshold = layout.left + (layout.width >> 1);
if (i < data.tabIndex && targetLeft < threshold) {
style.left = data.tabWidth + data.tabLayout[i + 1].margin + 'px';
data.tabTargetIndex = Math.min(data.tabTargetIndex, i);
}
else if (i > data.tabIndex && targetRight > threshold) {
style.left = -data.tabWidth - layout.margin + 'px';
data.tabTargetIndex = i;
}
else if (i !== data.tabIndex) {
style.left = '';
}
}
// Update the drag tab position.
this._updateDragPosition(event.clientX);
var idealLeft = event.clientX - data.pressX;
var maxLeft = data.contentRect.width - (data.tabLeft + data.tabWidth);
var adjustedLeft = Math.max(-data.tabLeft, Math.min(idealLeft, maxLeft));
data.tab.node.style.left = adjustedLeft + 'px';
};

@@ -641,3 +556,4 @@ /**

// Bail if there is no drag in progress.
if (!this._dragData) {
var data = this._dragData;
if (!data) {
return;

@@ -648,4 +564,2 @@ }

document.removeEventListener('mousemove', this, true);
// Store a local reference to the drag data.
var data = this._dragData;
// If the drag is not active, clear the reference and bail.

@@ -673,4 +587,4 @@ if (!data.dragActive) {

data.tab.node.style.left = adjustedLeft + 'px';
// Remove the active class from the tab so it can be transitioned.
data.tab.removeClass(ACTIVE_CLASS);
// Remove the dragging class from the tab so it can be transitioned.
data.tab.removeClass(DRAGGING_CLASS);
// Complete the release on a timer to allow the tab to transition.

@@ -690,7 +604,10 @@ setTimeout(function () {

data.cursorGrab.dispose();
data.tab.removeClass(ACTIVE_CLASS);
_this.removeClass(DRAGGING_CLASS);
// Finally, move the drag tab to its final index location.
if (data.tabTargetIndex !== -1) {
_this._moveTab(data.tabIndex, data.tabTargetIndex);
// Finally, move the tab item to the new location.
var fromIndex = data.tabIndex;
var toIndex = data.tabTargetIndex;
if (toIndex !== -1 && fromIndex !== toIndex) {
_this.items.move(fromIndex, toIndex);
// Force an update to prevent flicker on IE.
phosphor_messaging_1.sendMessage(_this, phosphor_widget_1.Widget.MsgUpdateRequest);
}

@@ -700,55 +617,15 @@ }, TRANSITION_DURATION);

/**
* Update the drag tab position for the given mouse X position.
*
* This method is a no-op if an active drag is not in progress.
* Release the mouse and restore the non-dragged tab positions.
*/
TabBar.prototype._updateDragPosition = function (clientX) {
// Bail if there is not an active drag.
var data = this._dragData;
if (!data || !data.dragActive) {
return;
}
// Compute the target bounds of the drag tab.
var offsetLeft = clientX - data.contentRect.left;
var targetLeft = offsetLeft - data.tabPressX;
var targetRight = targetLeft + data.tabWidth;
// Reset the target tab index.
data.tabTargetIndex = data.tabIndex;
// Update the non-drag tab positions and the tab target index.
for (var i = 0, n = this._tabs.length; i < n; ++i) {
var style = this._tabs[i].node.style;
var layout = data.tabLayout[i];
var threshold = layout.left + (layout.width >> 1);
if (i < data.tabIndex && targetLeft < threshold) {
style.left = data.tabWidth + data.tabLayout[i + 1].margin + 'px';
data.tabTargetIndex = Math.min(data.tabTargetIndex, i);
}
else if (i > data.tabIndex && targetRight > threshold) {
style.left = -data.tabWidth - layout.margin + 'px';
data.tabTargetIndex = i;
}
else if (i !== data.tabIndex) {
style.left = '';
}
}
// Update the drag tab position
var idealLeft = clientX - data.pressX;
var maxLeft = data.contentRect.width - (data.tabLeft + data.tabWidth);
var adjustedLeft = Math.max(-data.tabLeft, Math.min(idealLeft, maxLeft));
data.tab.node.style.left = adjustedLeft + 'px';
};
/**
* Release the mouse grab and restore the tab positions.
*/
TabBar.prototype._releaseMouse = function () {
// Bail early if there is no drag in progress.
if (!this._dragData) {
var data = this._dragData;
if (!data) {
return;
}
// Clear the drag data reference.
this._dragData = null;
// Remove the extra mouse listeners.
document.removeEventListener('mouseup', this, true);
document.removeEventListener('mousemove', this, true);
// Clear the drag data reference.
var data = this._dragData;
this._dragData = null;
// If the drag is not active, there's nothing left to do.

@@ -764,175 +641,225 @@ if (!data.dragActive) {

data.cursorGrab.dispose();
data.tab.removeClass(ACTIVE_CLASS);
data.tab.removeClass(DRAGGING_CLASS);
this.removeClass(DRAGGING_CLASS);
};
/**
* Insert a new tab into the tab bar at the given index.
*
* The tab should not already be contained in the tab bar.
*
* The mouse should be released before calling this method.
* The coerce handler for the [[currentItemProperty]].
*/
TabBar.prototype._insertTab = function (index, tab) {
tab.selected = false;
var i = arrays.insert(this._tabs, index, tab);
var content = this.node.firstChild.nextSibling;
content.appendChild(tab.node);
if (!this.selectedTab) {
this.selectedTab = tab;
}
else {
this._updateTabOrdering();
}
return i;
TabBar.prototype._coerceCurrentItem = function (item) {
var list = this.items;
return (item && list && list.contains(item)) ? item : null;
};
/**
* Move a tab to a new index in the tab bar.
*
* The mouse should be released before calling this method.
* The change handler for the [[currentItemProperty]].
*/
TabBar.prototype._moveTab = function (fromIndex, toIndex) {
var i = fromIndex | 0;
var j = toIndex | 0;
if (!arrays.move(this._tabs, i, j)) {
return false;
}
if (i === j) {
return true;
}
this._updateTabOrdering();
this.tabMoved.emit({ fromIndex: i, toIndex: j });
return true;
TabBar.prototype._onCurrentItemChanged = function (oldItem, newItem) {
var oldTab = arrays.find(this._tabs, function (tab) { return tab.item === oldItem; });
var newTab = arrays.find(this._tabs, function (tab) { return tab.item === newItem; });
if (oldTab)
oldTab.removeClass(CURRENT_CLASS);
if (newTab)
newTab.addClass(CURRENT_CLASS);
this.update();
};
/**
* Remove and return the tab at the given index.
*
* The mouse should be released before calling this method.
* The change handler for the [[itemsProperty]].
*/
TabBar.prototype._removeTab = function (index) {
// Bail if the index is invalid.
var i = index | 0;
var tab = arrays.removeAt(this._tabs, i);
if (!tab) {
return void 0;
TabBar.prototype._onItemsChanged = function (oldList, newList) {
// Ensure the mouse is released.
this._releaseMouse();
// Disconnect the old list and dispose the old tabs.
if (oldList) {
oldList.changed.disconnect(this._onItemsListChanged, this);
var content = this.contentNode;
while (this._tabs.length) {
var tab = this._tabs.pop();
content.removeChild(tab.node);
tab.dispose();
}
}
// Remove the tab from the DOM and reset its style.
var content = this.node.firstChild.nextSibling;
content.removeChild(tab.node);
tab.selected = false;
tab.node.style.left = '';
tab.node.style.zIndex = '';
tab.removeClass(ACTIVE_CLASS);
tab.removeClass(FIRST_CLASS);
tab.removeClass(LAST_CLASS);
// Update the selected tab. If the removed tab was the selected tab,
// select the next best tab by starting with the previous tab, then
// the next sibling, and finally the previous sibling. Otherwise,
// update the state and tab ordering as appropriate.
if (tab === this.selectedTab) {
var next = this.previousTab || this._tabs[i] || this._tabs[i - 1];
this.selectedTab = next;
this.previousTab = null;
// Create the new tabs and connect the new list.
if (newList) {
var content = this.contentNode;
for (var i = 0, n = newList.length; i < n; ++i) {
var tab = new Tab(newList.get(i));
content.appendChild(tab.node);
this._tabs.push(tab);
}
newList.changed.connect(this._onItemsListChanged, this);
}
else if (tab === this.previousTab) {
this.previousTab = null;
this._updateTabOrdering();
}
else {
this._updateTabOrdering();
}
return tab;
// Update the current item.
this.currentItem = newList && newList.get(0);
// Update the tab node order.
this.update();
};
/**
* Update the Z-index and flex order of the tabs.
* The change handler for the items list `changed` signal.
*/
TabBar.prototype._updateTabOrdering = function () {
if (this._tabs.length === 0) {
return;
TabBar.prototype._onItemsListChanged = function (sender, args) {
switch (args.type) {
case phosphor_observablelist_1.ListChangeType.Add:
this._onItemsListAdd(args);
break;
case phosphor_observablelist_1.ListChangeType.Move:
this._onItemsListMove(args);
break;
case phosphor_observablelist_1.ListChangeType.Remove:
this._onItemsListRemove(args);
break;
case phosphor_observablelist_1.ListChangeType.Replace:
this._onItemsListReplace(args);
break;
case phosphor_observablelist_1.ListChangeType.Set:
this._onItemsListSet(args);
break;
}
var selectedTab = this.selectedTab;
for (var i = 0, n = this._tabs.length, k = n - 1; i < n; ++i) {
var tab = this._tabs[i];
var style = tab.node.style;
tab.removeClass(FIRST_CLASS);
tab.removeClass(LAST_CLASS);
style.order = i + '';
if (tab === selectedTab) {
style.zIndex = n + '';
}
else {
style.zIndex = k-- + '';
}
}
this._tabs[0].addClass(FIRST_CLASS);
this._tabs[this._tabs.length - 1].addClass(LAST_CLASS);
};
/**
* The change handler for the [[selectedTabProperty]].
* The handler invoked on a items list change of type `Add`.
*/
TabBar.prototype._onSelectedTabChanged = function (old, tab) {
if (old)
old.selected = false;
if (tab)
tab.selected = true;
this.previousTab = old;
this._updateTabOrdering();
this.tabSelected.emit({ index: this.tabIndex(tab), tab: tab });
TabBar.prototype._onItemsListAdd = function (args) {
// Ensure the mouse is released.
this._releaseMouse();
// Create the tab for the new tab item.
var tab = new Tab(args.newValue);
// Add the tab to the same location in the internal array.
arrays.insert(this._tabs, args.newIndex, tab);
// Add the tab node to the DOM. The position is irrelevant.
this.contentNode.appendChild(tab.node);
// Select the tab if no tab is currently selected.
if (!this.currentItem)
this.currentItem = tab.item;
// Update the tab node order.
this.update();
};
/**
* A signal emitted when a tab is moved.
*
* **See also:** [[tabMoved]]
* The handler invoked on a items list change of type `Move`.
*/
TabBar.tabMovedSignal = new phosphor_signaling_1.Signal();
TabBar.prototype._onItemsListMove = function (args) {
// Ensure the mouse is released.
this._releaseMouse();
// Move the tab in the array. DOM position is irrelevant.
arrays.move(this._tabs, args.oldIndex, args.newIndex);
// Update the tab node order.
this.update();
};
/**
* A signal emitted when a tab is selected.
*
* **See also:** [[tabSelected]]
* The handler invoked on a items list change of type `Remove`.
*/
TabBar.tabSelectedSignal = new phosphor_signaling_1.Signal();
TabBar.prototype._onItemsListRemove = function (args) {
// Ensure the mouse is released.
this._releaseMouse();
// Remove the tab from the internal array.
var tab = arrays.removeAt(this._tabs, args.oldIndex);
// Remove the tab node from the DOM.
this.contentNode.removeChild(tab.node);
// Patch up the current item if needed.
if (this.currentItem === tab.item) {
var list = this.items;
this.currentItem = list.get(args.oldIndex) || list.get(-1);
}
// Dispose of the old tab.
tab.dispose();
// Update the tab node order.
this.update();
};
/**
* A signal emitted when the user clicks a tab close icon.
*
* **See also:** [[tabCloseRequested]
* The handler invoked on a items list change of type `Replace`.
*/
TabBar.tabCloseRequestedSignal = new phosphor_signaling_1.Signal();
TabBar.prototype._onItemsListReplace = function (args) {
// Ensure the mouse is released.
this._releaseMouse();
// Create the new tabs for the new tab items.
var newItems = args.newValue;
var newTabs = newItems.map(function (item) { return new Tab(item); });
// Replace the tabs in the internal array.
var oldItems = args.oldValue;
var oldTabs = (_a = this._tabs).splice.apply(_a, [args.newIndex, oldItems.length].concat(newTabs));
// Remove the old tabs from the DOM.
var content = this.contentNode;
oldTabs.forEach(function (tab) { content.removeChild(tab.node); });
// Add the new tabs to the DOM. Their position is irrelevant.
newTabs.forEach(function (tab) { content.appendChild(tab.node); });
// Patch up the current item if needed.
var curr = this.currentItem;
if (oldItems.indexOf(curr) !== -1) {
this.currentItem = null;
if (newItems.indexOf(curr) !== -1) {
this.currentItem = curr;
}
else {
var list = this.items;
this.currentItem = list.get(args.newIndex) || list.get(-1);
}
}
// Dispose of the old tabs.
oldTabs.forEach(function (tab) { tab.dispose(); });
// Update the tab node order.
this.update();
var _a;
};
/**
* A signal emitted when a tab is dragged beyond the detach threshold.
* The handler invoked on a items list change of type `Set`.
*/
TabBar.prototype._onItemsListSet = function (args) {
// If the item was not actually changed, there is nothing to do.
if (args.oldValue === args.newValue) {
return;
}
// Ensure the mouse is released.
this._releaseMouse();
// Create the tab for the new tab item.
var newTab = new Tab(args.newValue);
// Swap the new tab in the internal array.
var oldTab = this._tabs[args.newIndex];
this._tabs[args.newIndex] = newTab;
// Swap the new tab node in the DOM.
this.contentNode.replaceChild(newTab.node, oldTab.node);
// Patch up the current item if needed.
if (this.currentItem === oldTab.item) {
this.currentItem = newTab.item;
}
// Dispose of the old tab.
oldTab.dispose();
// Update the tab node order.
this.update();
};
/**
* A signal emitted when the user clicks a tab item's close icon.
*
* **See also:** [[tabDetachRequested]]
* **See also:** [[itemCloseRequested]]
*/
TabBar.tabDetachRequestedSignal = new phosphor_signaling_1.Signal();
TabBar.itemCloseRequestedSignal = new phosphor_signaling_1.Signal();
/**
* The property descriptor for the previous tab.
* The property descriptor for the currently selected tab item.
*
* This controls which tab is selected after if selected tab is
* removed. It is typically updated automatically.
*
* **See also:** [[previousTab]]
* **See also:** [[currentItem]]
*/
TabBar.previousTabProperty = new phosphor_properties_1.Property({
TabBar.currentItemProperty = new phosphor_properties_1.Property({
name: 'currentItem',
value: null,
coerce: function (owner, val) { return (val && owner.tabIndex(val) !== -1) ? val : null; },
coerce: function (owner, value) { return owner._coerceCurrentItem(value); },
changed: function (owner, old, value) { owner._onCurrentItemChanged(old, value); },
notify: new phosphor_signaling_1.Signal(),
});
/**
* The property descriptor for the selected tab.
* The property descriptor for the observable list of tab items.
*
* This controls which tab is selected in the tab bar.
*
* **See also:** [[selectedTab]]
* **See also:** [[items]]
*/
TabBar.selectedTabProperty = new phosphor_properties_1.Property({
TabBar.itemsProperty = new phosphor_properties_1.Property({
name: 'items',
value: null,
coerce: function (owner, val) { return (val && owner.tabIndex(val) !== -1) ? val : null; },
changed: function (owner, old, val) { return owner._onSelectedTabChanged(old, val); },
coerce: function (owner, value) { return value || null; },
changed: function (owner, old, value) { owner._onItemsChanged(old, value); },
});
/**
* The property descriptor for the tabs movable property
* The property descriptor for whether the tabs are user-movable.
*
* This controls whether tabs are movable by the user.
*
* **See also:** [[tabsMovable]]
*/
TabBar.tabsMovableProperty = new phosphor_properties_1.Property({
value: true,
name: 'tabsMovable',
value: false,
changed: function (owner) { owner._releaseMouse(); },
});

@@ -943,2 +870,229 @@ return TabBar;

/**
* A message class for `'tear-off-request'` messages.
*
* #### Notes
* A message of this type is sent to a tab bar when the user drags
* a tab beyond the tear-off threshold which surrounds the tab bar.
*/
var TearOffMessage = (function (_super) {
__extends(TearOffMessage, _super);
/**
* Construct a new tear off request message.
*
* @param item - The tab item being dragged by the user.
*
* @param clientX - The current client X position of the mouse.
*
* @param clientY - The current client Y position of the mouse.
*/
function TearOffMessage(item, clientX, clientY) {
_super.call(this, 'tear-off-request');
this._item = item;
this._clientX = clientX;
this._clientY = clientY;
}
Object.defineProperty(TearOffMessage.prototype, "item", {
/**
* The tab item being dragged by the user.
*
* #### Notes
* This is a read-only property.
*/
get: function () {
return this._item;
},
enumerable: true,
configurable: true
});
Object.defineProperty(TearOffMessage.prototype, "clientX", {
/**
* The current client X position of the mouse.
*
* #### Notes
* This is a read-only property.
*/
get: function () {
return this._clientX;
},
enumerable: true,
configurable: true
});
Object.defineProperty(TearOffMessage.prototype, "clientY", {
/**
* The current client Y position of the mouse.
*
* #### Notes
* This is a read-only property.
*/
get: function () {
return this._clientY;
},
enumerable: true,
configurable: true
});
return TearOffMessage;
})(phosphor_messaging_1.Message);
exports.TearOffMessage = TearOffMessage;
/**
* An object which manages a tab node for a tab bar.
*/
var Tab = (function (_super) {
__extends(Tab, _super);
/**
* Construct a new tab.
*
* @param item - The tab item to associate with the tab.
*/
function Tab(item) {
_super.call(this);
this.addClass(TAB_CLASS);
this._item = item;
var title = item.title;
this.textNode.textContent = title.text;
this.toggleClass(CLOSABLE_CLASS, title.closable);
if (title.icon)
exAddClass(this.iconNode, title.icon);
if (title.className)
exAddClass(this.node, title.className);
title.changed.connect(this._onTitleChanged, this);
}
/**
* Create the DOM node for a tab.
*/
Tab.createNode = function () {
var node = document.createElement('li');
var icon = document.createElement('span');
var text = document.createElement('span');
var close = document.createElement('span');
icon.className = ICON_CLASS;
text.className = TEXT_CLASS;
close.className = CLOSE_CLASS;
node.appendChild(icon);
node.appendChild(text);
node.appendChild(close);
return node;
};
/**
* Dispose of the resources held by the tab.
*/
Tab.prototype.dispose = function () {
this._item = null;
phosphor_signaling_1.clearSignalData(this);
};
Object.defineProperty(Tab.prototype, "isDisposed", {
/**
* Test whether the tab is disposed.
*/
get: function () {
return this._item === null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Tab.prototype, "iconNode", {
/**
* Get the icon node for the tab.
*
* #### Notes
* This is a read-only property.
*/
get: function () {
return this.node.childNodes[0];
},
enumerable: true,
configurable: true
});
Object.defineProperty(Tab.prototype, "textNode", {
/**
* Get the text node for the tab.
*
* #### Notes
* This is a read-only property.
*/
get: function () {
return this.node.childNodes[1];
},
enumerable: true,
configurable: true
});
Object.defineProperty(Tab.prototype, "closeNode", {
/**
* Get the close icon node for the tab.
*
* #### Notes
* This is a read-only property.
*/
get: function () {
return this.node.childNodes[2];
},
enumerable: true,
configurable: true
});
Object.defineProperty(Tab.prototype, "item", {
/**
* Get the tab item associated with the tab.
*
* #### Notes
* This is a read-only property.
*/
get: function () {
return this._item;
},
enumerable: true,
configurable: true
});
/**
* The handler for the title `changed` signal.
*/
Tab.prototype._onTitleChanged = function (sender, args) {
switch (args.name) {
case 'text':
this._onTitleTextChanged(args);
break;
case 'icon':
this._onTitleIconChanged(args);
break;
case 'closable':
this._onTitleClosableChanged(args);
break;
case 'className':
this._onTitleClassNameChanged(args);
break;
}
};
/**
* A method invoked when the title text changes.
*/
Tab.prototype._onTitleTextChanged = function (args) {
this.textNode.textContent = args.newValue;
};
/**
* A method invoked when the title icon changes.
*/
Tab.prototype._onTitleIconChanged = function (args) {
var node = this.iconNode;
if (args.oldValue)
exRemClass(node, args.oldValue);
if (args.newValue)
exAddClass(node, args.newValue);
};
/**
* A method invoked when the title closable flag changes.
*/
Tab.prototype._onTitleClosableChanged = function (args) {
this.toggleClass(CLOSABLE_CLASS, args.newValue);
};
/**
* A method invoked when the title class name changes.
*/
Tab.prototype._onTitleClassNameChanged = function (args) {
var node = this.node;
if (args.oldValue)
exRemClass(node, args.oldValue);
if (args.newValue)
exAddClass(node, args.newValue);
};
return Tab;
})(phosphor_nodewrapper_1.NodeWrapper);
/**
* A struct which holds the drag data for a tab bar.

@@ -949,6 +1103,10 @@ */

/**
* The tab being dragged.
* The tab object being dragged.
*/
this.tab = null;
/**
* The index of the tab being dragged.
*/
this.tabIndex = -1;
/**
* The offset left of the tab being dragged.

@@ -962,8 +1120,4 @@ */

/**
* The index of the tab being dragged.
* The original mouse X position in tab coordinates.
*/
this.tabIndex = -1;
/**
* The orgian mouse X position in tab coordinates.
*/
this.tabPressX = -1;

@@ -999,5 +1153,5 @@ /**

/**
* Whether the detach request signal has been emitted.
* Whether a tear-off request as been made.
*/
this.detachRequested = false;
this.tearOffRequested = false;
}

@@ -1007,18 +1161,32 @@ return DragData;

/**
* Test if a mouse position lies outside the detach bound of a rect.
* Add a whitespace separated class name to the given node.
*/
function shouldDetach(rect, event) {
return ((event.clientX < rect.left - DETACH_THRESHOLD) ||
(event.clientX >= rect.right + DETACH_THRESHOLD) ||
(event.clientY < rect.top - DETACH_THRESHOLD) ||
(event.clientY >= rect.bottom + DETACH_THRESHOLD));
function exAddClass(node, name) {
var list = node.classList;
var parts = name.split(/\s+/);
for (var i = 0, n = parts.length; i < n; ++i) {
if (parts[i])
list.add(parts[i]);
}
}
/**
* Get the index of the tab which intersect the client point, or -1.
* Remove a whitespace separated class name to the given node.
*/
function exRemClass(node, name) {
var list = node.classList;
var parts = name.split(/\s+/);
for (var i = 0, n = parts.length; i < n; ++i) {
if (parts[i])
list.remove(parts[i]);
}
}
/**
* Perform a client position hit test an array of tabs.
*
* Returns the index of the first matching node, or `-1`.
*/
function hitTestTabs(tabs, clientX, clientY) {
for (var i = 0, n = tabs.length; i < n; ++i) {
if (phosphor_domutil_1.hitTest(tabs[i].node, clientX, clientY)) {
if (phosphor_domutil_1.hitTest(tabs[i].node, clientX, clientY))
return i;
}
}

@@ -1028,3 +1196,3 @@ return -1;

/**
* Snap an array of the current tab layout values.
* Get a snapshot of the current tab layout values.
*/

@@ -1037,3 +1205,3 @@ function snapTabLayout(tabs) {

var width = node.offsetWidth;
var cstyle = window.getComputedStyle(tabs[i].node);
var cstyle = window.getComputedStyle(node);
var margin = parseInt(cstyle.marginLeft, 10) || 0;

@@ -1044,2 +1212,11 @@ layout[i] = { margin: margin, left: left, width: width };

}
/**
* Test if a mouse position exceeds the tear-off threshold.
*/
function tearOffExceeded(rect, event) {
return ((event.clientX < rect.left - TEAR_OFF_THRESHOLD) ||
(event.clientX >= rect.right + TEAR_OFF_THRESHOLD) ||
(event.clientY < rect.top - TEAR_OFF_THRESHOLD) ||
(event.clientY >= rect.bottom + TEAR_OFF_THRESHOLD));
}
//# sourceMappingURL=tabbar.js.map
import { BoxPanel } from 'phosphor-boxpanel';
import { Property } from 'phosphor-properties';
import { ISignal, Signal } from 'phosphor-signaling';
import { IWidgetIndexArgs } from 'phosphor-stackedpanel';
import { Widget } from 'phosphor-widget';
import { Tab } from './tab';
import { IChangedArgs } from 'phosphor-properties';
import { StackedPanel } from 'phosphor-stackedpanel';
import { IChildWidgetList, Widget } from 'phosphor-widget';
import { TabBar } from './tabbar';
/**
* A panel which provides a tabbed layout for child widgets.
* A panel which combines a `TabBar` and a `StackedPanel`.
*
* The `TabPanel` provides a convenient combination of a `TabBar` and
* a `StackedPanel` which allows the user to toggle between widgets by
* selecting the tab associated with a widget.
*
* #### Notes
* Widgets should be added to a `TabPanel` using the `<prefix>Widget`
* methods, **not** the `<prefix>Child` methods. The children of a
* `TabPanel` should **not** be manipulated directly by user code.
* Children for this panel should be added to the [[widgets]] list.
*/
export declare class TabPanel extends BoxPanel {
/**
* A signal emitted when the current widget is changed.
*
* **See also:** [[currentChanged]]
*/
static currentChangedSignal: Signal<TabPanel, IWidgetIndexArgs>;
/**
* The property descriptor for the tab attached property.
*
* This controls the tab used for a widget in a tab panel.
*
* #### Notes
* If the tab for a widget is changed, the new tab will not be
* reflected until the widget is re-inserted into the tab panel.
* However, in-place changes to the tab's properties **will** be
* reflected.
*
* **See also:** [[getTab]], [[setTab]]
*/
static tabProperty: Property<Widget, Tab>;
/**
* Get the tab for the given widget.
*
* @param widget - The widget of interest.
*
* @returns The tab for the given widget.
*
* #### Notes
* This is a pure delegate for the [[tabProperty]].
*/
static getTab(widget: Widget): Tab;
/**
* Set the tab for the given widget.
*
* @param widget - The widget of interest.
*
* @param tab - The tab to use for the widget.
*
* #### Notes
* This is a pure delegate for the [[tabProperty]].
*/
static setTab(widget: Widget, tab: Tab): void;
/**
* Construct a new tab panel.

@@ -71,13 +22,14 @@ */

/**
* A signal emitted when the current widget is changed.
* Get the currently selected widget.
*
* #### Notes
* This is a pure delegate to the [[currentChangedSignal]].
* This is a convenience alias to the `currentItem` property of the
* tab bar.
*/
currentChanged: ISignal<TabPanel, IWidgetIndexArgs>;
/**
* Get the currently selected widget.
*/
/**
* Set the currently selected widget.
*
* #### Notes
* This is a convenience alias to the `currentItem` property of the
* tab bar.
*/

@@ -87,169 +39,67 @@ currentWidget: Widget;

* Get whether the tabs are movable by the user.
*
* #### Notes
* This is a convenience alias to the `tabsMovable` property of the
* tab bar.
*/
/**
* Set whether the tabs are movable by the user.
*
* #### Notes
* This is a convenience alias to the `tabsMovable` property of the
* tab bar.
*/
tabsMovable: boolean;
/**
* Get a shallow copy of the array of widgets.
* Get the observable list of widgets for the tab panel.
*
* #### Notes
* When only iterating over the widgets, it can be faster to use
* the widget query methods, which do not perform a copy.
* Widgets to arrange in the tab panel should be added to this list.
*
* **See also:** [[widgetCount]], [[widgetAt]]
* This is a read-only alias of the `children` property of the
* stacked panel.
*/
widgets: IChildWidgetList;
/**
* Set the widgets for the tab panel.
* Get the tab bar associated with the tab panel.
*
* #### Notes
* This will clear the current widgets and add the specified widgets.
* Depending on the desired outcome, it can be more efficient to use
* one of the widget manipulation methods.
* The items in the tab bar are automatically synchronized with the
* children of the stacked panel.
*
* **See also:** [[addWidget]], [[insertWidget]], [[removeWidget]]
*/
widgets: Widget[];
/**
* Get the number of widgets in the tab panel.
*
* #### Notes
* This is a read-only property.
*
* **See also:** [[widgets]], [[widgetAt]]
*/
widgetCount: number;
tabs: TabBar<Widget>;
/**
* Get the widget at a specific index.
* Get the stacked panel associated with the tab panel.
*
* @param index - The index of the widget of interest.
*
* @returns The widget widget at the specified index, or `undefined`
* if the index is out of range.
*
* **See also:** [[widgetCount]], [[widgetIndex]]
*/
widgetAt(index: number): Widget;
/**
* Get the index of a specific widget.
*
* @param widget - The widget of interest.
*
* @returns The index of the specified widget, or `-1` if the widget
* is not contained in the tab panel.
*
* **See also:** [[widgetCount]], [[widgetAt]]
*/
widgetIndex(widget: Widget): number;
/**
* Add a widget to the end of the panel.
*
* @param widget - The widget to add to the panel.
*
* @returns The new index of the widget.
*
* #### Notes
* If the widget already exists in the panel, it will first be
* removed.
* The children of the stacked panel are automatically synchronized
* with the items in the tab bar.
*
* The `TabPanel.tab` attached property *must* be set with the
* tab to use for the widget, or an error will be thrown. This
* can be set via `TabPanel.setTab`.
*
* The `TabPanel.tab` attached property is assumed to remain
* constant while the widget is contained by the tab panel.
*
* **See also:** [[insertWidget]], [[moveWidget]]
* This is a read-only property.
*/
addWidget(widget: Widget): number;
stack: StackedPanel;
/**
* Insert a widget into the panel at the given index.
* Handle the `currentItemChanged` signal from the tab bar.
*
* @param index - The target index for the widget. This will be
* clamped to the bounds of the widgets.
*
* @param widget - The widget to insert into the panel.
*
* @returns The new index of the widget.
*
* #### Notes
* If the widget already exists in the panel, it will first be
* removed.
* This can be reimplemented by subclasses as needed.
*
* The `TabPanel.tab` attached property *must* be set with the
* tab to use for the widget, or an error will be thrown. This
* can be set via `TabPanel.setTab`.
*
* The `TabPanel.tab` attached property is assumed to remain
* constant while the widget is contained by the tab panel.
*
* **See also:** [[addWidget]], [[moveWidget]]
* The default implementation of this method synchronizes the current
* tab item with current widget of the stacked panel.
*/
insertWidget(index: number, widget: Widget): number;
protected onCurrentItemChanged(sender: TabBar<Widget>, args: IChangedArgs<Widget>): void;
/**
* Move a widget from one index to another.
* Handle the `itemCloseRequested` signal from the tab bar.
*
* @param fromIndex - The index of the widget of interest.
*
* @param toIndex - The target index for the widget.
*
* @returns 'true' if the widget was moved, or `false` if either
* of the given indices are out of range.
*
* #### Notes
* This can be more efficient than re-inserting an existing widget.
* This can be reimplemented by subclasses as needed.
*
* **See also:** [[addWidget]], [[insertWidget]]
* The default implementation of this method closes the widget if the
* widget's title object has its `closable` flag set to `true`.
*/
moveWidget(fromIndex: number, toIndex: number): boolean;
/**
* Remove the widget at a specific index.
*
* @param index - The index of the widget of interest.
*
* @returns The removed widget, or `undefined` if the index
* is out of range.
*
* **See also:** [[removeWidget]], [[clearWidgets]]
*/
removeWidgetAt(index: number): Widget;
/**
* Remove a specific widget from the panel.
*
* @param child - The widget of interest.
*
* @returns The index which the widget occupied, or `-1` if the
* widget is not contained in the tab panel.
*
* **See also:** [[removeWidgetAt]], [[clearWidgets]]
*/
removeWidget(widget: Widget): number;
/**
* Remove all widgets from the tab panel.
*
* **See also:** [[removeWidget]], [[removeWidgetAt]]
*/
clearWidgets(): void;
/**
* Handle the `tabMoved` signal from the tab bar.
*/
private _onTabMoved(sender, args);
/**
* Handle the `tabSelected` signal from the tab bar.
*/
private _onTabSelected(sender, args);
/**
* Handle the `tabCloseRequested` signal from the tab bar.
*/
private _onTabCloseRequested(sender, args);
/**
* Handle the `currentChanged` signal from the stacked panel.
*/
private _onCurrentChanged(sender, args);
/**
* Handle the `widgetRemoved` signal from the stacked panel.
*/
private _onWidgetRemoved(sender, args);
protected onItemCloseRequested(sender: TabBar<Widget>, args: Widget): void;
private _tabs;
private _stack;
}

@@ -15,4 +15,2 @@ /*-----------------------------------------------------------------------------

var phosphor_boxpanel_1 = require('phosphor-boxpanel');
var phosphor_properties_1 = require('phosphor-properties');
var phosphor_signaling_1 = require('phosphor-signaling');
var phosphor_stackedpanel_1 = require('phosphor-stackedpanel');

@@ -25,12 +23,6 @@ var tabbar_1 = require('./tabbar');

/**
* A panel which provides a tabbed layout for child widgets.
* A panel which combines a `TabBar` and a `StackedPanel`.
*
* The `TabPanel` provides a convenient combination of a `TabBar` and
* a `StackedPanel` which allows the user to toggle between widgets by
* selecting the tab associated with a widget.
*
* #### Notes
* Widgets should be added to a `TabPanel` using the `<prefix>Widget`
* methods, **not** the `<prefix>Child` methods. The children of a
* `TabPanel` should **not** be manipulated directly by user code.
* Children for this panel should be added to the [[widgets]] list.
*/

@@ -47,7 +39,5 @@ var TabPanel = (function (_super) {

this.addClass(TAB_PANEL_CLASS);
this._tabs.tabMoved.connect(this._onTabMoved, this);
this._tabs.tabSelected.connect(this._onTabSelected, this);
this._tabs.tabCloseRequested.connect(this._onTabCloseRequested, this);
this._stack.currentChanged.connect(this._onCurrentChanged, this);
this._stack.widgetRemoved.connect(this._onWidgetRemoved, this);
this._tabs.items = this._stack.children;
this._tabs.currentItemChanged.connect(this.onCurrentItemChanged, this);
this._tabs.itemCloseRequested.connect(this.onItemCloseRequested, this);
phosphor_boxpanel_1.BoxPanel.setStretch(this._tabs, 0);

@@ -57,32 +47,6 @@ phosphor_boxpanel_1.BoxPanel.setStretch(this._stack, 1);

this.spacing = 0;
this.addChild(this._tabs);
this.addChild(this._stack);
this.children.add(this._tabs);
this.children.add(this._stack);
}
/**
* Get the tab for the given widget.
*
* @param widget - The widget of interest.
*
* @returns The tab for the given widget.
*
* #### Notes
* This is a pure delegate for the [[tabProperty]].
*/
TabPanel.getTab = function (widget) {
return TabPanel.tabProperty.get(widget);
};
/**
* Set the tab for the given widget.
*
* @param widget - The widget of interest.
*
* @param tab - The tab to use for the widget.
*
* #### Notes
* This is a pure delegate for the [[tabProperty]].
*/
TabPanel.setTab = function (widget, tab) {
TabPanel.tabProperty.set(widget, tab);
};
/**
* Dispose of the resources held by the widget.

@@ -95,28 +59,22 @@ */

};
Object.defineProperty(TabPanel.prototype, "currentChanged", {
Object.defineProperty(TabPanel.prototype, "currentWidget", {
/**
* A signal emitted when the current widget is changed.
* Get the currently selected widget.
*
* #### Notes
* This is a pure delegate to the [[currentChangedSignal]].
* This is a convenience alias to the `currentItem` property of the
* tab bar.
*/
get: function () {
return TabPanel.currentChangedSignal.bind(this);
return this._tabs.currentItem;
},
enumerable: true,
configurable: true
});
Object.defineProperty(TabPanel.prototype, "currentWidget", {
/**
* Get the currently selected widget.
*/
get: function () {
return this._stack.currentWidget;
},
/**
* Set the currently selected widget.
*
* #### Notes
* This is a convenience alias to the `currentItem` property of the
* tab bar.
*/
set: function (widget) {
var i = this._stack.childIndex(widget);
this._tabs.selectedTab = this._tabs.tabAt(i);
this._tabs.currentItem = widget;
},

@@ -129,2 +87,6 @@ enumerable: true,

* Get whether the tabs are movable by the user.
*
* #### Notes
* This is a convenience alias to the `tabsMovable` property of the
* tab bar.
*/

@@ -136,2 +98,6 @@ get: function () {

* Set whether the tabs are movable by the user.
*
* #### Notes
* This is a convenience alias to the `tabsMovable` property of the
* tab bar.
*/

@@ -146,9 +112,9 @@ set: function (movable) {

/**
* Get a shallow copy of the array of widgets.
* Get the observable list of widgets for the tab panel.
*
* #### Notes
* When only iterating over the widgets, it can be faster to use
* the widget query methods, which do not perform a copy.
* Widgets to arrange in the tab panel should be added to this list.
*
* **See also:** [[widgetCount]], [[widgetAt]]
* This is a read-only alias of the `children` property of the
* stacked panel.
*/

@@ -158,16 +124,17 @@ get: function () {

},
enumerable: true,
configurable: true
});
Object.defineProperty(TabPanel.prototype, "tabs", {
/**
* Set the widgets for the tab panel.
* Get the tab bar associated with the tab panel.
*
* #### Notes
* This will clear the current widgets and add the specified widgets.
* Depending on the desired outcome, it can be more efficient to use
* one of the widget manipulation methods.
* The items in the tab bar are automatically synchronized with the
* children of the stacked panel.
*
* **See also:** [[addWidget]], [[insertWidget]], [[removeWidget]]
* This is a read-only property.
*/
set: function (widgets) {
var _this = this;
this.clearWidgets();
widgets.forEach(function (widget) { return _this.addWidget(widget); });
get: function () {
return this._tabs;
},

@@ -177,13 +144,14 @@ enumerable: true,

});
Object.defineProperty(TabPanel.prototype, "widgetCount", {
Object.defineProperty(TabPanel.prototype, "stack", {
/**
* Get the number of widgets in the tab panel.
* Get the stacked panel associated with the tab panel.
*
* #### Notes
* The children of the stacked panel are automatically synchronized
* with the items in the tab bar.
*
* This is a read-only property.
*
* **See also:** [[widgets]], [[widgetAt]]
*/
get: function () {
return this._stack.childCount;
return this._stack;
},

@@ -194,185 +162,26 @@ enumerable: true,

/**
* Get the widget at a specific index.
* Handle the `currentItemChanged` signal from the tab bar.
*
* @param index - The index of the widget of interest.
*
* @returns The widget widget at the specified index, or `undefined`
* if the index is out of range.
*
* **See also:** [[widgetCount]], [[widgetIndex]]
*/
TabPanel.prototype.widgetAt = function (index) {
return this._stack.childAt(index);
};
/**
* Get the index of a specific widget.
*
* @param widget - The widget of interest.
*
* @returns The index of the specified widget, or `-1` if the widget
* is not contained in the tab panel.
*
* **See also:** [[widgetCount]], [[widgetAt]]
*/
TabPanel.prototype.widgetIndex = function (widget) {
return this._stack.childIndex(widget);
};
/**
* Add a widget to the end of the panel.
*
* @param widget - The widget to add to the panel.
*
* @returns The new index of the widget.
*
* #### Notes
* If the widget already exists in the panel, it will first be
* removed.
* This can be reimplemented by subclasses as needed.
*
* The `TabPanel.tab` attached property *must* be set with the
* tab to use for the widget, or an error will be thrown. This
* can be set via `TabPanel.setTab`.
*
* The `TabPanel.tab` attached property is assumed to remain
* constant while the widget is contained by the tab panel.
*
* **See also:** [[insertWidget]], [[moveWidget]]
* The default implementation of this method synchronizes the current
* tab item with current widget of the stacked panel.
*/
TabPanel.prototype.addWidget = function (widget) {
return this.insertWidget(this.widgetCount, widget);
TabPanel.prototype.onCurrentItemChanged = function (sender, args) {
this._stack.currentWidget = args.newValue;
};
/**
* Insert a widget into the panel at the given index.
* Handle the `itemCloseRequested` signal from the tab bar.
*
* @param index - The target index for the widget. This will be
* clamped to the bounds of the widgets.
*
* @param widget - The widget to insert into the panel.
*
* @returns The new index of the widget.
*
* #### Notes
* If the widget already exists in the panel, it will first be
* removed.
* This can be reimplemented by subclasses as needed.
*
* The `TabPanel.tab` attached property *must* be set with the
* tab to use for the widget, or an error will be thrown. This
* can be set via `TabPanel.setTab`.
*
* The `TabPanel.tab` attached property is assumed to remain
* constant while the widget is contained by the tab panel.
*
* **See also:** [[addWidget]], [[moveWidget]]
* The default implementation of this method closes the widget if the
* widget's title object has its `closable` flag set to `true`.
*/
TabPanel.prototype.insertWidget = function (index, widget) {
var tab = TabPanel.getTab(widget);
if (!tab)
throw new Error('`TabPanel.tab` property not set');
var i = this._stack.insertChild(index, widget);
return this._tabs.insertTab(i, tab);
TabPanel.prototype.onItemCloseRequested = function (sender, args) {
if (args.title.closable)
args.close();
};
/**
* Move a widget from one index to another.
*
* @param fromIndex - The index of the widget of interest.
*
* @param toIndex - The target index for the widget.
*
* @returns 'true' if the widget was moved, or `false` if either
* of the given indices are out of range.
*
* #### Notes
* This can be more efficient than re-inserting an existing widget.
*
* **See also:** [[addWidget]], [[insertWidget]]
*/
TabPanel.prototype.moveWidget = function (fromIndex, toIndex) {
return this._tabs.moveTab(fromIndex, toIndex);
};
/**
* Remove the widget at a specific index.
*
* @param index - The index of the widget of interest.
*
* @returns The removed widget, or `undefined` if the index
* is out of range.
*
* **See also:** [[removeWidget]], [[clearWidgets]]
*/
TabPanel.prototype.removeWidgetAt = function (index) {
return this._stack.removeChildAt(index);
};
/**
* Remove a specific widget from the panel.
*
* @param child - The widget of interest.
*
* @returns The index which the widget occupied, or `-1` if the
* widget is not contained in the tab panel.
*
* **See also:** [[removeWidgetAt]], [[clearWidgets]]
*/
TabPanel.prototype.removeWidget = function (widget) {
return this._stack.removeChild(widget);
};
/**
* Remove all widgets from the tab panel.
*
* **See also:** [[removeWidget]], [[removeWidgetAt]]
*/
TabPanel.prototype.clearWidgets = function () {
this._stack.clearChildren();
};
/**
* Handle the `tabMoved` signal from the tab bar.
*/
TabPanel.prototype._onTabMoved = function (sender, args) {
this._stack.moveChild(args.fromIndex, args.toIndex);
};
/**
* Handle the `tabSelected` signal from the tab bar.
*/
TabPanel.prototype._onTabSelected = function (sender, args) {
this._stack.currentWidget = this._stack.childAt(args.index);
};
/**
* Handle the `tabCloseRequested` signal from the tab bar.
*/
TabPanel.prototype._onTabCloseRequested = function (sender, args) {
this._stack.childAt(args.index).close();
};
/**
* Handle the `currentChanged` signal from the stacked panel.
*/
TabPanel.prototype._onCurrentChanged = function (sender, args) {
this.currentChanged.emit(args);
};
/**
* Handle the `widgetRemoved` signal from the stacked panel.
*/
TabPanel.prototype._onWidgetRemoved = function (sender, args) {
this._tabs.removeTabAt(args.index);
};
/**
* A signal emitted when the current widget is changed.
*
* **See also:** [[currentChanged]]
*/
TabPanel.currentChangedSignal = new phosphor_signaling_1.Signal();
/**
* The property descriptor for the tab attached property.
*
* This controls the tab used for a widget in a tab panel.
*
* #### Notes
* If the tab for a widget is changed, the new tab will not be
* reflected until the widget is re-inserted into the tab panel.
* However, in-place changes to the tab's properties **will** be
* reflected.
*
* **See also:** [[getTab]], [[setTab]]
*/
TabPanel.tabProperty = new phosphor_properties_1.Property({
value: null,
coerce: function (owner, value) { return value || null; },
});
return TabPanel;

@@ -379,0 +188,0 @@ })(phosphor_boxpanel_1.BoxPanel);

{
"name": "phosphor-tabs",
"version": "0.9.8",
"version": "1.0.0-beta",
"description": "Phosphor widgets for creating tab bars and tab panels.",

@@ -8,12 +8,13 @@ "main": "lib/index.js",

"dependencies": {
"phosphor-arrays": "^1.0.5",
"phosphor-boxpanel": "^0.9.7",
"phosphor-disposable": "^1.0.4",
"phosphor-domutil": "^0.9.5",
"phosphor-arrays": "^1.0.6",
"phosphor-boxpanel": "^1.0.0-beta",
"phosphor-disposable": "^1.0.5",
"phosphor-domutil": "^1.0.1",
"phosphor-messaging": "^1.0.5",
"phosphor-nodewrapper": "^1.0.4",
"phosphor-properties": "^1.3.0",
"phosphor-observablelist": "^1.0.0-beta",
"phosphor-properties": "^2.0.0",
"phosphor-signaling": "^1.1.2",
"phosphor-stackedpanel": "^0.9.6",
"phosphor-widget": "^0.9.13"
"phosphor-stackedpanel": "^1.0.0-beta.1",
"phosphor-widget": "^1.0.0-beta.1"
},

@@ -62,11 +63,5 @@ "devDependencies": {

"files": [
"lib/index.css",
"lib/index.d.ts",
"lib/index.js",
"lib/tab.d.ts",
"lib/tab.js",
"lib/tabbar.d.ts",
"lib/tabbar.js",
"lib/tabpanel.d.ts",
"lib/tabpanel.js"
"lib/*.css",
"lib/*.d.ts",
"lib/*.js"
],

@@ -73,0 +68,0 @@ "browserify": {

@@ -111,1 +111,32 @@ phosphor-tabs

omit the type declarations when using a language other than TypeScript.
```typescript
import {
TabPanel
} from 'phosphor-tabs';
import {
Widget
} from 'phosphor-widget';
function main(): void {
let one = new Widget();
one.title.text = 'One';
let two = new Widget();
two.title.text = 'Two';
let three = new Widget();
three.title.text = 'Three';
// Note: A `TabBar` can also be used independently of a `TabPanel`.
let panel = new TabPanel();
panel.tabsMovable = true;
panel.widgets.assign([one, two, three]);
Widget.attach(panel, document.body);
window.onresize = () => panel.update();
}
```

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc