@jupyter-notebook/application 7.0.0-alpha.8 → 7.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/app.js +6 -6
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/panelhandler.d.ts +217 -0
- package/lib/panelhandler.js +324 -0
- package/lib/shell.d.ts +13 -112
- package/lib/shell.js +39 -278
- package/package.json +17 -18
- package/style/base.css +12 -3
package/lib/app.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Copyright (c) Jupyter Development Team.
|
|
2
2
|
// Distributed under the terms of the Modified BSD License.
|
|
3
|
-
import { JupyterFrontEnd } from '@jupyterlab/application';
|
|
3
|
+
import { JupyterFrontEnd, } from '@jupyterlab/application';
|
|
4
4
|
import { Base64ModelFactory } from '@jupyterlab/docregistry';
|
|
5
5
|
import { createRendermimePlugins } from '@jupyterlab/application/lib/mimerenderers';
|
|
6
6
|
import { LabStatus } from '@jupyterlab/application/lib/status';
|
|
@@ -65,7 +65,7 @@ export class NotebookApp extends JupyterFrontEnd {
|
|
|
65
65
|
hubHost: PageConfig.getOption('hubHost') || undefined,
|
|
66
66
|
hubPrefix: PageConfig.getOption('hubPrefix') || undefined,
|
|
67
67
|
hubUser: PageConfig.getOption('hubUser') || undefined,
|
|
68
|
-
hubServerName: PageConfig.getOption('hubServerName') || undefined
|
|
68
|
+
hubServerName: PageConfig.getOption('hubServerName') || undefined,
|
|
69
69
|
},
|
|
70
70
|
directories: {
|
|
71
71
|
appSettings: PageConfig.getOption('appSettingsDir'),
|
|
@@ -75,8 +75,8 @@ export class NotebookApp extends JupyterFrontEnd {
|
|
|
75
75
|
themes: PageConfig.getOption('themesDir'),
|
|
76
76
|
userSettings: PageConfig.getOption('userSettingsDir'),
|
|
77
77
|
serverRoot: PageConfig.getOption('serverRoot'),
|
|
78
|
-
workspaces: PageConfig.getOption('workspacesDir')
|
|
79
|
-
}
|
|
78
|
+
workspaces: PageConfig.getOption('workspacesDir'),
|
|
79
|
+
},
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
/**
|
|
@@ -104,7 +104,7 @@ export class NotebookApp extends JupyterFrontEnd {
|
|
|
104
104
|
if (!Array.isArray(data)) {
|
|
105
105
|
data = [data];
|
|
106
106
|
}
|
|
107
|
-
data.forEach(item => {
|
|
107
|
+
data.forEach((item) => {
|
|
108
108
|
try {
|
|
109
109
|
this.registerPlugin(item);
|
|
110
110
|
}
|
|
@@ -119,7 +119,7 @@ export class NotebookApp extends JupyterFrontEnd {
|
|
|
119
119
|
* @param mods - The plugin modules to register.
|
|
120
120
|
*/
|
|
121
121
|
registerPluginModules(mods) {
|
|
122
|
-
mods.forEach(mod => {
|
|
122
|
+
mods.forEach((mod) => {
|
|
123
123
|
this.registerPluginModule(mod);
|
|
124
124
|
});
|
|
125
125
|
}
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { ICommandPalette } from '@jupyterlab/apputils';
|
|
2
|
+
import { IDisposable } from '@lumino/disposable';
|
|
3
|
+
import { ISignal } from '@lumino/signaling';
|
|
4
|
+
import { Panel, Widget } from '@lumino/widgets';
|
|
5
|
+
/**
|
|
6
|
+
* A class which manages a panel and sorts its widgets by rank.
|
|
7
|
+
*/
|
|
8
|
+
export declare class PanelHandler {
|
|
9
|
+
constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Get the panel managed by the handler.
|
|
12
|
+
*/
|
|
13
|
+
get panel(): Panel;
|
|
14
|
+
/**
|
|
15
|
+
* Add a widget to the panel.
|
|
16
|
+
*
|
|
17
|
+
* If the widget is already added, it will be moved.
|
|
18
|
+
*/
|
|
19
|
+
addWidget(widget: Widget, rank: number): void;
|
|
20
|
+
/**
|
|
21
|
+
* A message hook for child remove messages on the panel handler.
|
|
22
|
+
*/
|
|
23
|
+
private _panelChildHook;
|
|
24
|
+
protected _items: Private.IRankItem[];
|
|
25
|
+
protected _panel: Panel;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A class which manages a side panel that can show at most one widget at a time.
|
|
29
|
+
*/
|
|
30
|
+
export declare class SidePanelHandler extends PanelHandler {
|
|
31
|
+
/**
|
|
32
|
+
* Construct a new side panel handler.
|
|
33
|
+
*/
|
|
34
|
+
constructor(area: SidePanel.Area);
|
|
35
|
+
/**
|
|
36
|
+
* Get the current widget in the sidebar panel.
|
|
37
|
+
*/
|
|
38
|
+
get currentWidget(): Widget | null;
|
|
39
|
+
/**
|
|
40
|
+
* Get the area of the side panel
|
|
41
|
+
*/
|
|
42
|
+
get area(): SidePanel.Area;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the panel is visible
|
|
45
|
+
*/
|
|
46
|
+
get isVisible(): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Get the stacked panel managed by the handler
|
|
49
|
+
*/
|
|
50
|
+
get panel(): Panel;
|
|
51
|
+
/**
|
|
52
|
+
* Get the widgets list.
|
|
53
|
+
*/
|
|
54
|
+
get widgets(): Readonly<Widget[]>;
|
|
55
|
+
/**
|
|
56
|
+
* Signal fired when a widget is added to the panel
|
|
57
|
+
*/
|
|
58
|
+
get widgetAdded(): ISignal<SidePanelHandler, Widget>;
|
|
59
|
+
/**
|
|
60
|
+
* Signal fired when a widget is removed from the panel
|
|
61
|
+
*/
|
|
62
|
+
get widgetRemoved(): ISignal<SidePanelHandler, Widget>;
|
|
63
|
+
/**
|
|
64
|
+
* Get the close button element.
|
|
65
|
+
*/
|
|
66
|
+
get closeButton(): HTMLButtonElement;
|
|
67
|
+
/**
|
|
68
|
+
* Expand the sidebar.
|
|
69
|
+
*
|
|
70
|
+
* #### Notes
|
|
71
|
+
* This will open the most recently used widget, or the first widget
|
|
72
|
+
* if there is no most recently used.
|
|
73
|
+
*/
|
|
74
|
+
expand(id?: string): void;
|
|
75
|
+
/**
|
|
76
|
+
* Activate a widget residing in the stacked panel by ID.
|
|
77
|
+
*
|
|
78
|
+
* @param id - The widget's unique ID.
|
|
79
|
+
*/
|
|
80
|
+
activate(id: string): void;
|
|
81
|
+
/**
|
|
82
|
+
* Test whether the sidebar has the given widget by id.
|
|
83
|
+
*/
|
|
84
|
+
has(id: string): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Collapse the sidebar so no items are expanded.
|
|
87
|
+
*/
|
|
88
|
+
collapse(): void;
|
|
89
|
+
/**
|
|
90
|
+
* Add a widget and its title to the stacked panel.
|
|
91
|
+
*
|
|
92
|
+
* If the widget is already added, it will be moved.
|
|
93
|
+
*/
|
|
94
|
+
addWidget(widget: Widget, rank: number): void;
|
|
95
|
+
/**
|
|
96
|
+
* Hide the side panel
|
|
97
|
+
*/
|
|
98
|
+
hide(): void;
|
|
99
|
+
/**
|
|
100
|
+
* Show the side panel
|
|
101
|
+
*/
|
|
102
|
+
show(): void;
|
|
103
|
+
/**
|
|
104
|
+
* Find the insertion index for a rank item.
|
|
105
|
+
*/
|
|
106
|
+
private _findInsertIndex;
|
|
107
|
+
/**
|
|
108
|
+
* Find the index of the item with the given widget, or `-1`.
|
|
109
|
+
*/
|
|
110
|
+
private _findWidgetIndex;
|
|
111
|
+
/**
|
|
112
|
+
* Find the widget with the given id, or `null`.
|
|
113
|
+
*/
|
|
114
|
+
private _findWidgetByID;
|
|
115
|
+
/**
|
|
116
|
+
* Refresh the visibility of the stacked panel.
|
|
117
|
+
*/
|
|
118
|
+
private _refreshVisibility;
|
|
119
|
+
private _onWidgetRemoved;
|
|
120
|
+
private _area;
|
|
121
|
+
private _isHiddenByUser;
|
|
122
|
+
private _widgetPanel;
|
|
123
|
+
private _currentWidget;
|
|
124
|
+
private _lastCurrentWidget;
|
|
125
|
+
private _closeButton;
|
|
126
|
+
private _widgetAdded;
|
|
127
|
+
private _widgetRemoved;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* A name space for SideBarPanel functions.
|
|
131
|
+
*/
|
|
132
|
+
export declare namespace SidePanel {
|
|
133
|
+
/**
|
|
134
|
+
* The areas of the sidebar panel
|
|
135
|
+
*/
|
|
136
|
+
type Area = 'left' | 'right';
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* A class to manages the palette entries associated to the side panels.
|
|
140
|
+
*/
|
|
141
|
+
export declare class SidePanelPalette {
|
|
142
|
+
/**
|
|
143
|
+
* Construct a new side panel palette.
|
|
144
|
+
*/
|
|
145
|
+
constructor(options: SidePanelPaletteOption);
|
|
146
|
+
/**
|
|
147
|
+
* Get a command palette item from the widget id and the area.
|
|
148
|
+
*/
|
|
149
|
+
getItem(widget: Readonly<Widget>, area: 'left' | 'right'): SidePanelPaletteItem | null;
|
|
150
|
+
/**
|
|
151
|
+
* Add an item to the command palette.
|
|
152
|
+
*/
|
|
153
|
+
addItem(widget: Readonly<Widget>, area: 'left' | 'right'): void;
|
|
154
|
+
/**
|
|
155
|
+
* Remove an item from the command palette.
|
|
156
|
+
*/
|
|
157
|
+
removeItem(widget: Readonly<Widget>, area: 'left' | 'right'): void;
|
|
158
|
+
_command: string;
|
|
159
|
+
_commandPalette: ICommandPalette;
|
|
160
|
+
_items: SidePanelPaletteItem[];
|
|
161
|
+
}
|
|
162
|
+
type SidePanelPaletteItem = {
|
|
163
|
+
/**
|
|
164
|
+
* The ID of the widget associated to the command palette.
|
|
165
|
+
*/
|
|
166
|
+
widgetId: string;
|
|
167
|
+
/**
|
|
168
|
+
* The area of the panel associated to the command palette.
|
|
169
|
+
*/
|
|
170
|
+
area: 'left' | 'right';
|
|
171
|
+
/**
|
|
172
|
+
* The disposable object to remove the item from command palette.
|
|
173
|
+
*/
|
|
174
|
+
disposable: IDisposable;
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* An interface for the options to include in SideBarPalette constructor.
|
|
178
|
+
*/
|
|
179
|
+
type SidePanelPaletteOption = {
|
|
180
|
+
/**
|
|
181
|
+
* The commands palette.
|
|
182
|
+
*/
|
|
183
|
+
commandPalette: ICommandPalette;
|
|
184
|
+
/**
|
|
185
|
+
* The command to call from each side panel menu entry.
|
|
186
|
+
*
|
|
187
|
+
* ### Notes
|
|
188
|
+
* That command required 3 args :
|
|
189
|
+
* side: 'left' | 'right', the area to toggle
|
|
190
|
+
* title: string, label of the command
|
|
191
|
+
* id: string, id of the widget to activate
|
|
192
|
+
*/
|
|
193
|
+
command: string;
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* A namespace for private module data.
|
|
197
|
+
*/
|
|
198
|
+
declare namespace Private {
|
|
199
|
+
/**
|
|
200
|
+
* An object which holds a widget and its sort rank.
|
|
201
|
+
*/
|
|
202
|
+
interface IRankItem {
|
|
203
|
+
/**
|
|
204
|
+
* The widget for the item.
|
|
205
|
+
*/
|
|
206
|
+
widget: Widget;
|
|
207
|
+
/**
|
|
208
|
+
* The sort rank of the widget.
|
|
209
|
+
*/
|
|
210
|
+
rank: number;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* A less-than comparison function for side bar rank items.
|
|
214
|
+
*/
|
|
215
|
+
function itemCmp(first: IRankItem, second: IRankItem): number;
|
|
216
|
+
}
|
|
217
|
+
export {};
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
import { closeIcon } from '@jupyterlab/ui-components';
|
|
4
|
+
import { ArrayExt, find } from '@lumino/algorithm';
|
|
5
|
+
import { MessageLoop } from '@lumino/messaging';
|
|
6
|
+
import { Signal } from '@lumino/signaling';
|
|
7
|
+
import { Panel, StackedPanel, Widget } from '@lumino/widgets';
|
|
8
|
+
/**
|
|
9
|
+
* A class which manages a panel and sorts its widgets by rank.
|
|
10
|
+
*/
|
|
11
|
+
export class PanelHandler {
|
|
12
|
+
constructor() {
|
|
13
|
+
/**
|
|
14
|
+
* A message hook for child remove messages on the panel handler.
|
|
15
|
+
*/
|
|
16
|
+
this._panelChildHook = (handler, msg) => {
|
|
17
|
+
switch (msg.type) {
|
|
18
|
+
case 'child-removed':
|
|
19
|
+
{
|
|
20
|
+
const widget = msg.child;
|
|
21
|
+
ArrayExt.removeFirstWhere(this._items, (v) => v.widget === widget);
|
|
22
|
+
}
|
|
23
|
+
break;
|
|
24
|
+
default:
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
};
|
|
29
|
+
this._items = new Array();
|
|
30
|
+
this._panel = new Panel();
|
|
31
|
+
MessageLoop.installMessageHook(this._panel, this._panelChildHook);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the panel managed by the handler.
|
|
35
|
+
*/
|
|
36
|
+
get panel() {
|
|
37
|
+
return this._panel;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Add a widget to the panel.
|
|
41
|
+
*
|
|
42
|
+
* If the widget is already added, it will be moved.
|
|
43
|
+
*/
|
|
44
|
+
addWidget(widget, rank) {
|
|
45
|
+
widget.parent = null;
|
|
46
|
+
const item = { widget, rank };
|
|
47
|
+
const index = ArrayExt.upperBound(this._items, item, Private.itemCmp);
|
|
48
|
+
ArrayExt.insert(this._items, index, item);
|
|
49
|
+
this._panel.insertWidget(index, widget);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A class which manages a side panel that can show at most one widget at a time.
|
|
54
|
+
*/
|
|
55
|
+
export class SidePanelHandler extends PanelHandler {
|
|
56
|
+
/**
|
|
57
|
+
* Construct a new side panel handler.
|
|
58
|
+
*/
|
|
59
|
+
constructor(area) {
|
|
60
|
+
super();
|
|
61
|
+
this._isHiddenByUser = false;
|
|
62
|
+
this._widgetAdded = new Signal(this);
|
|
63
|
+
this._widgetRemoved = new Signal(this);
|
|
64
|
+
this._area = area;
|
|
65
|
+
this._panel.hide();
|
|
66
|
+
this._currentWidget = null;
|
|
67
|
+
this._lastCurrentWidget = null;
|
|
68
|
+
this._widgetPanel = new StackedPanel();
|
|
69
|
+
this._widgetPanel.widgetRemoved.connect(this._onWidgetRemoved, this);
|
|
70
|
+
this._closeButton = document.createElement('button');
|
|
71
|
+
closeIcon.element({
|
|
72
|
+
container: this._closeButton,
|
|
73
|
+
height: '16px',
|
|
74
|
+
width: 'auto',
|
|
75
|
+
});
|
|
76
|
+
this._closeButton.onclick = () => {
|
|
77
|
+
this.collapse();
|
|
78
|
+
this.hide();
|
|
79
|
+
};
|
|
80
|
+
this._closeButton.className = 'jp-Button jp-SidePanel-collapse';
|
|
81
|
+
this._closeButton.title = 'Collapse side panel';
|
|
82
|
+
const icon = new Widget({ node: this._closeButton });
|
|
83
|
+
this._panel.addWidget(icon);
|
|
84
|
+
this._panel.addWidget(this._widgetPanel);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get the current widget in the sidebar panel.
|
|
88
|
+
*/
|
|
89
|
+
get currentWidget() {
|
|
90
|
+
return (this._currentWidget ||
|
|
91
|
+
this._lastCurrentWidget ||
|
|
92
|
+
(this._items.length > 0 ? this._items[0].widget : null));
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get the area of the side panel
|
|
96
|
+
*/
|
|
97
|
+
get area() {
|
|
98
|
+
return this._area;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Whether the panel is visible
|
|
102
|
+
*/
|
|
103
|
+
get isVisible() {
|
|
104
|
+
return this._panel.isVisible;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get the stacked panel managed by the handler
|
|
108
|
+
*/
|
|
109
|
+
get panel() {
|
|
110
|
+
return this._panel;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get the widgets list.
|
|
114
|
+
*/
|
|
115
|
+
get widgets() {
|
|
116
|
+
return this._items.map((obj) => obj.widget);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Signal fired when a widget is added to the panel
|
|
120
|
+
*/
|
|
121
|
+
get widgetAdded() {
|
|
122
|
+
return this._widgetAdded;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Signal fired when a widget is removed from the panel
|
|
126
|
+
*/
|
|
127
|
+
get widgetRemoved() {
|
|
128
|
+
return this._widgetRemoved;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Get the close button element.
|
|
132
|
+
*/
|
|
133
|
+
get closeButton() {
|
|
134
|
+
return this._closeButton;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Expand the sidebar.
|
|
138
|
+
*
|
|
139
|
+
* #### Notes
|
|
140
|
+
* This will open the most recently used widget, or the first widget
|
|
141
|
+
* if there is no most recently used.
|
|
142
|
+
*/
|
|
143
|
+
expand(id) {
|
|
144
|
+
if (this._currentWidget) {
|
|
145
|
+
this.collapse();
|
|
146
|
+
}
|
|
147
|
+
if (id) {
|
|
148
|
+
this.activate(id);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
const visibleWidget = this.currentWidget;
|
|
152
|
+
if (visibleWidget) {
|
|
153
|
+
this._currentWidget = visibleWidget;
|
|
154
|
+
this.activate(visibleWidget.id);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Activate a widget residing in the stacked panel by ID.
|
|
160
|
+
*
|
|
161
|
+
* @param id - The widget's unique ID.
|
|
162
|
+
*/
|
|
163
|
+
activate(id) {
|
|
164
|
+
const widget = this._findWidgetByID(id);
|
|
165
|
+
if (widget) {
|
|
166
|
+
this._currentWidget = widget;
|
|
167
|
+
widget.show();
|
|
168
|
+
widget.activate();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Test whether the sidebar has the given widget by id.
|
|
173
|
+
*/
|
|
174
|
+
has(id) {
|
|
175
|
+
return this._findWidgetByID(id) !== null;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Collapse the sidebar so no items are expanded.
|
|
179
|
+
*/
|
|
180
|
+
collapse() {
|
|
181
|
+
var _a;
|
|
182
|
+
(_a = this._currentWidget) === null || _a === void 0 ? void 0 : _a.hide();
|
|
183
|
+
this._currentWidget = null;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Add a widget and its title to the stacked panel.
|
|
187
|
+
*
|
|
188
|
+
* If the widget is already added, it will be moved.
|
|
189
|
+
*/
|
|
190
|
+
addWidget(widget, rank) {
|
|
191
|
+
widget.parent = null;
|
|
192
|
+
widget.hide();
|
|
193
|
+
const item = { widget, rank };
|
|
194
|
+
const index = this._findInsertIndex(item);
|
|
195
|
+
ArrayExt.insert(this._items, index, item);
|
|
196
|
+
this._widgetPanel.insertWidget(index, widget);
|
|
197
|
+
this._refreshVisibility();
|
|
198
|
+
this._widgetAdded.emit(widget);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Hide the side panel
|
|
202
|
+
*/
|
|
203
|
+
hide() {
|
|
204
|
+
this._isHiddenByUser = true;
|
|
205
|
+
this._refreshVisibility();
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Show the side panel
|
|
209
|
+
*/
|
|
210
|
+
show() {
|
|
211
|
+
this._isHiddenByUser = false;
|
|
212
|
+
this._refreshVisibility();
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Find the insertion index for a rank item.
|
|
216
|
+
*/
|
|
217
|
+
_findInsertIndex(item) {
|
|
218
|
+
return ArrayExt.upperBound(this._items, item, Private.itemCmp);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Find the index of the item with the given widget, or `-1`.
|
|
222
|
+
*/
|
|
223
|
+
_findWidgetIndex(widget) {
|
|
224
|
+
return ArrayExt.findFirstIndex(this._items, (i) => i.widget === widget);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Find the widget with the given id, or `null`.
|
|
228
|
+
*/
|
|
229
|
+
_findWidgetByID(id) {
|
|
230
|
+
const item = find(this._items, (value) => value.widget.id === id);
|
|
231
|
+
return item ? item.widget : null;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Refresh the visibility of the stacked panel.
|
|
235
|
+
*/
|
|
236
|
+
_refreshVisibility() {
|
|
237
|
+
this._panel.setHidden(this._isHiddenByUser);
|
|
238
|
+
}
|
|
239
|
+
/*
|
|
240
|
+
* Handle the `widgetRemoved` signal from the panel.
|
|
241
|
+
*/
|
|
242
|
+
_onWidgetRemoved(sender, widget) {
|
|
243
|
+
if (widget === this._lastCurrentWidget) {
|
|
244
|
+
this._lastCurrentWidget = null;
|
|
245
|
+
}
|
|
246
|
+
ArrayExt.removeAt(this._items, this._findWidgetIndex(widget));
|
|
247
|
+
this._refreshVisibility();
|
|
248
|
+
this._widgetRemoved.emit(widget);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* A class to manages the palette entries associated to the side panels.
|
|
253
|
+
*/
|
|
254
|
+
export class SidePanelPalette {
|
|
255
|
+
/**
|
|
256
|
+
* Construct a new side panel palette.
|
|
257
|
+
*/
|
|
258
|
+
constructor(options) {
|
|
259
|
+
this._items = [];
|
|
260
|
+
this._commandPalette = options.commandPalette;
|
|
261
|
+
this._command = options.command;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Get a command palette item from the widget id and the area.
|
|
265
|
+
*/
|
|
266
|
+
getItem(widget, area) {
|
|
267
|
+
const itemList = this._items;
|
|
268
|
+
for (let i = 0; i < itemList.length; i++) {
|
|
269
|
+
const item = itemList[i];
|
|
270
|
+
if (item.widgetId === widget.id && item.area === area) {
|
|
271
|
+
return item;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Add an item to the command palette.
|
|
278
|
+
*/
|
|
279
|
+
addItem(widget, area) {
|
|
280
|
+
// Check if the item does not already exist.
|
|
281
|
+
if (this.getItem(widget, area)) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
// Add a new item in command palette.
|
|
285
|
+
const disposableDelegate = this._commandPalette.addItem({
|
|
286
|
+
command: this._command,
|
|
287
|
+
category: 'View',
|
|
288
|
+
args: {
|
|
289
|
+
side: area,
|
|
290
|
+
title: `Show ${widget.title.caption}`,
|
|
291
|
+
id: widget.id,
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
// Keep the disposableDelegate objet to be able to dispose of the item if the widget
|
|
295
|
+
// is remove from the side panel.
|
|
296
|
+
this._items.push({
|
|
297
|
+
widgetId: widget.id,
|
|
298
|
+
area: area,
|
|
299
|
+
disposable: disposableDelegate,
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Remove an item from the command palette.
|
|
304
|
+
*/
|
|
305
|
+
removeItem(widget, area) {
|
|
306
|
+
const item = this.getItem(widget, area);
|
|
307
|
+
if (item) {
|
|
308
|
+
item.disposable.dispose();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* A namespace for private module data.
|
|
314
|
+
*/
|
|
315
|
+
var Private;
|
|
316
|
+
(function (Private) {
|
|
317
|
+
/**
|
|
318
|
+
* A less-than comparison function for side bar rank items.
|
|
319
|
+
*/
|
|
320
|
+
function itemCmp(first, second) {
|
|
321
|
+
return first.rank - second.rank;
|
|
322
|
+
}
|
|
323
|
+
Private.itemCmp = itemCmp;
|
|
324
|
+
})(Private || (Private = {}));
|
package/lib/shell.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { JupyterFrontEnd } from '@jupyterlab/application';
|
|
2
2
|
import { DocumentRegistry } from '@jupyterlab/docregistry';
|
|
3
|
+
import { ITranslator } from '@jupyterlab/translation';
|
|
3
4
|
import { Token } from '@lumino/coreutils';
|
|
4
5
|
import { ISignal } from '@lumino/signaling';
|
|
5
|
-
import {
|
|
6
|
+
import { Widget } from '@lumino/widgets';
|
|
7
|
+
import { SidePanelHandler } from './panelhandler';
|
|
6
8
|
/**
|
|
7
9
|
* The Jupyter Notebook application shell token.
|
|
8
10
|
*/
|
|
@@ -36,11 +38,11 @@ export declare class NotebookShell extends Widget implements JupyterFrontEnd.ISh
|
|
|
36
38
|
/**
|
|
37
39
|
* Get the left area handler
|
|
38
40
|
*/
|
|
39
|
-
get leftHandler():
|
|
41
|
+
get leftHandler(): SidePanelHandler;
|
|
40
42
|
/**
|
|
41
43
|
* Get the right area handler
|
|
42
44
|
*/
|
|
43
|
-
get rightHandler():
|
|
45
|
+
get rightHandler(): SidePanelHandler;
|
|
44
46
|
/**
|
|
45
47
|
* Is the left sidebar visible?
|
|
46
48
|
*/
|
|
@@ -53,6 +55,11 @@ export declare class NotebookShell extends Widget implements JupyterFrontEnd.ISh
|
|
|
53
55
|
* Promise that resolves when the main widget is loaded
|
|
54
56
|
*/
|
|
55
57
|
get restored(): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Getter and setter for the translator.
|
|
60
|
+
*/
|
|
61
|
+
get translator(): ITranslator;
|
|
62
|
+
set translator(value: ITranslator);
|
|
56
63
|
/**
|
|
57
64
|
* Activate a widget in its area.
|
|
58
65
|
*/
|
|
@@ -105,8 +112,10 @@ export declare class NotebookShell extends Widget implements JupyterFrontEnd.ISh
|
|
|
105
112
|
private _menuHandler;
|
|
106
113
|
private _leftHandler;
|
|
107
114
|
private _rightHandler;
|
|
108
|
-
private
|
|
115
|
+
private _spacer_top;
|
|
116
|
+
private _spacer_bottom;
|
|
109
117
|
private _main;
|
|
118
|
+
private _translator;
|
|
110
119
|
private _currentChanged;
|
|
111
120
|
private _mainWidgetLoaded;
|
|
112
121
|
}
|
|
@@ -119,111 +128,3 @@ export declare namespace Shell {
|
|
|
119
128
|
*/
|
|
120
129
|
type Area = 'main' | 'top' | 'left' | 'right' | 'menu';
|
|
121
130
|
}
|
|
122
|
-
/**
|
|
123
|
-
* A name space for SideBarPanel functions.
|
|
124
|
-
*/
|
|
125
|
-
export declare namespace SideBarPanel {
|
|
126
|
-
/**
|
|
127
|
-
* The areas of the sidebar panel
|
|
128
|
-
*/
|
|
129
|
-
type Area = 'left' | 'right';
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* A class which manages a side bar that can show at most one widget at a time.
|
|
133
|
-
*/
|
|
134
|
-
export declare class SideBarHandler {
|
|
135
|
-
/**
|
|
136
|
-
* Construct a new side bar handler.
|
|
137
|
-
*/
|
|
138
|
-
constructor(area: SideBarPanel.Area);
|
|
139
|
-
/**
|
|
140
|
-
* Get the current widget in the sidebar panel.
|
|
141
|
-
*/
|
|
142
|
-
get currentWidget(): Widget | null;
|
|
143
|
-
/**
|
|
144
|
-
* Get the area of the side panel
|
|
145
|
-
*/
|
|
146
|
-
get area(): SideBarPanel.Area;
|
|
147
|
-
/**
|
|
148
|
-
* Whether the panel is visible
|
|
149
|
-
*/
|
|
150
|
-
get isVisible(): boolean;
|
|
151
|
-
/**
|
|
152
|
-
* Get the stacked panel managed by the handler
|
|
153
|
-
*/
|
|
154
|
-
get panel(): Panel;
|
|
155
|
-
/**
|
|
156
|
-
* Get the widgets list.
|
|
157
|
-
*/
|
|
158
|
-
get widgets(): Readonly<Widget[]>;
|
|
159
|
-
/**
|
|
160
|
-
* Signal fired when a widget is added to the panel
|
|
161
|
-
*/
|
|
162
|
-
get widgetAdded(): ISignal<SideBarHandler, Widget>;
|
|
163
|
-
/**
|
|
164
|
-
* Signal fired when a widget is removed from the panel
|
|
165
|
-
*/
|
|
166
|
-
get widgetRemoved(): ISignal<SideBarHandler, Widget>;
|
|
167
|
-
/**
|
|
168
|
-
* Expand the sidebar.
|
|
169
|
-
*
|
|
170
|
-
* #### Notes
|
|
171
|
-
* This will open the most recently used widget, or the first widget
|
|
172
|
-
* if there is no most recently used.
|
|
173
|
-
*/
|
|
174
|
-
expand(id?: string): void;
|
|
175
|
-
/**
|
|
176
|
-
* Activate a widget residing in the stacked panel by ID.
|
|
177
|
-
*
|
|
178
|
-
* @param id - The widget's unique ID.
|
|
179
|
-
*/
|
|
180
|
-
activate(id: string): void;
|
|
181
|
-
/**
|
|
182
|
-
* Test whether the sidebar has the given widget by id.
|
|
183
|
-
*/
|
|
184
|
-
has(id: string): boolean;
|
|
185
|
-
/**
|
|
186
|
-
* Collapse the sidebar so no items are expanded.
|
|
187
|
-
*/
|
|
188
|
-
collapse(): void;
|
|
189
|
-
/**
|
|
190
|
-
* Add a widget and its title to the stacked panel.
|
|
191
|
-
*
|
|
192
|
-
* If the widget is already added, it will be moved.
|
|
193
|
-
*/
|
|
194
|
-
addWidget(widget: Widget, rank: number): void;
|
|
195
|
-
/**
|
|
196
|
-
* Hide the side panel
|
|
197
|
-
*/
|
|
198
|
-
hide(): void;
|
|
199
|
-
/**
|
|
200
|
-
* Show the side panel
|
|
201
|
-
*/
|
|
202
|
-
show(): void;
|
|
203
|
-
/**
|
|
204
|
-
* Find the insertion index for a rank item.
|
|
205
|
-
*/
|
|
206
|
-
private _findInsertIndex;
|
|
207
|
-
/**
|
|
208
|
-
* Find the index of the item with the given widget, or `-1`.
|
|
209
|
-
*/
|
|
210
|
-
private _findWidgetIndex;
|
|
211
|
-
/**
|
|
212
|
-
* Find the widget with the given id, or `null`.
|
|
213
|
-
*/
|
|
214
|
-
private _findWidgetByID;
|
|
215
|
-
/**
|
|
216
|
-
* Refresh the visibility of the stacked panel.
|
|
217
|
-
*/
|
|
218
|
-
private _refreshVisibility;
|
|
219
|
-
private _onWidgetRemoved;
|
|
220
|
-
private _area;
|
|
221
|
-
private _isHiddenByUser;
|
|
222
|
-
private _items;
|
|
223
|
-
private _panel;
|
|
224
|
-
private _widgetPanel;
|
|
225
|
-
private _currentWidget;
|
|
226
|
-
private _lastCurrentWidget;
|
|
227
|
-
private _widgetAdded;
|
|
228
|
-
private _widgetRemoved;
|
|
229
|
-
}
|
package/lib/shell.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// Copyright (c) Jupyter Development Team.
|
|
2
2
|
// Distributed under the terms of the Modified BSD License.
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { nullTranslator } from '@jupyterlab/translation';
|
|
4
|
+
import { find } from '@lumino/algorithm';
|
|
5
5
|
import { PromiseDelegate, Token } from '@lumino/coreutils';
|
|
6
|
-
import { MessageLoop } from '@lumino/messaging';
|
|
7
6
|
import { Signal } from '@lumino/signaling';
|
|
8
|
-
import { BoxLayout, Panel, SplitPanel,
|
|
7
|
+
import { BoxLayout, Panel, SplitPanel, Widget } from '@lumino/widgets';
|
|
8
|
+
import { PanelHandler, SidePanelHandler } from './panelhandler';
|
|
9
9
|
/**
|
|
10
10
|
* The Jupyter Notebook application shell token.
|
|
11
11
|
*/
|
|
@@ -20,21 +20,27 @@ const DEFAULT_RANK = 900;
|
|
|
20
20
|
export class NotebookShell extends Widget {
|
|
21
21
|
constructor() {
|
|
22
22
|
super();
|
|
23
|
+
this._translator = nullTranslator;
|
|
23
24
|
this._currentChanged = new Signal(this);
|
|
24
25
|
this._mainWidgetLoaded = new PromiseDelegate();
|
|
25
26
|
this.id = 'main';
|
|
26
|
-
this._topHandler = new
|
|
27
|
-
this._menuHandler = new
|
|
28
|
-
this._leftHandler = new
|
|
29
|
-
this._rightHandler = new
|
|
27
|
+
this._topHandler = new PanelHandler();
|
|
28
|
+
this._menuHandler = new PanelHandler();
|
|
29
|
+
this._leftHandler = new SidePanelHandler('left');
|
|
30
|
+
this._rightHandler = new SidePanelHandler('right');
|
|
30
31
|
this._main = new Panel();
|
|
31
32
|
const topWrapper = (this._topWrapper = new Panel());
|
|
32
33
|
const menuWrapper = (this._menuWrapper = new Panel());
|
|
33
34
|
this._topHandler.panel.id = 'top-panel';
|
|
35
|
+
this._topHandler.panel.node.setAttribute('role', 'banner');
|
|
34
36
|
this._menuHandler.panel.id = 'menu-panel';
|
|
37
|
+
this._menuHandler.panel.node.setAttribute('role', 'navigation');
|
|
35
38
|
this._main.id = 'main-panel';
|
|
36
|
-
this.
|
|
37
|
-
this.
|
|
39
|
+
this._main.node.setAttribute('role', 'main');
|
|
40
|
+
this._spacer_top = new Widget();
|
|
41
|
+
this._spacer_top.id = 'spacer-widget-top';
|
|
42
|
+
this._spacer_bottom = new Widget();
|
|
43
|
+
this._spacer_bottom.id = 'spacer-widget-bottom';
|
|
38
44
|
// create wrappers around the top and menu areas
|
|
39
45
|
topWrapper.id = 'top-panel-wrapper';
|
|
40
46
|
topWrapper.addWidget(this._topHandler.panel);
|
|
@@ -44,13 +50,15 @@ export class NotebookShell extends Widget {
|
|
|
44
50
|
const leftHandler = this._leftHandler;
|
|
45
51
|
const rightHandler = this._rightHandler;
|
|
46
52
|
leftHandler.panel.id = 'jp-left-stack';
|
|
53
|
+
leftHandler.panel.node.setAttribute('role', 'complementary');
|
|
47
54
|
rightHandler.panel.id = 'jp-right-stack';
|
|
55
|
+
rightHandler.panel.node.setAttribute('role', 'complementary');
|
|
48
56
|
// Hide the side panels by default.
|
|
49
57
|
leftHandler.hide();
|
|
50
58
|
rightHandler.hide();
|
|
51
59
|
const middleLayout = new BoxLayout({
|
|
52
60
|
spacing: 0,
|
|
53
|
-
direction: 'top-to-bottom'
|
|
61
|
+
direction: 'top-to-bottom',
|
|
54
62
|
});
|
|
55
63
|
BoxLayout.setStretch(this._topWrapper, 0);
|
|
56
64
|
BoxLayout.setStretch(this._menuWrapper, 0);
|
|
@@ -58,8 +66,9 @@ export class NotebookShell extends Widget {
|
|
|
58
66
|
const middlePanel = new Panel({ layout: middleLayout });
|
|
59
67
|
middlePanel.addWidget(this._topWrapper);
|
|
60
68
|
middlePanel.addWidget(this._menuWrapper);
|
|
61
|
-
middlePanel.addWidget(this.
|
|
69
|
+
middlePanel.addWidget(this._spacer_top);
|
|
62
70
|
middlePanel.addWidget(this._main);
|
|
71
|
+
middlePanel.addWidget(this._spacer_bottom);
|
|
63
72
|
middlePanel.layout = middleLayout;
|
|
64
73
|
// TODO: Consider storing this as an attribute this._hsplitPanel if saving/restoring layout needed
|
|
65
74
|
const hsplitPanel = new SplitPanel();
|
|
@@ -135,13 +144,28 @@ export class NotebookShell extends Widget {
|
|
|
135
144
|
get restored() {
|
|
136
145
|
return this._mainWidgetLoaded.promise;
|
|
137
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Getter and setter for the translator.
|
|
149
|
+
*/
|
|
150
|
+
get translator() {
|
|
151
|
+
var _a;
|
|
152
|
+
return (_a = this._translator) !== null && _a !== void 0 ? _a : nullTranslator;
|
|
153
|
+
}
|
|
154
|
+
set translator(value) {
|
|
155
|
+
if (value !== this._translator) {
|
|
156
|
+
this._translator = value;
|
|
157
|
+
const trans = value.load('notebook');
|
|
158
|
+
this._leftHandler.closeButton.title = trans.__('Collapse %1 side panel', this._leftHandler.area);
|
|
159
|
+
this._rightHandler.closeButton.title = trans.__('Collapse %1 side panel', this._rightHandler.area);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
138
162
|
/**
|
|
139
163
|
* Activate a widget in its area.
|
|
140
164
|
*/
|
|
141
165
|
activateById(id) {
|
|
142
166
|
// Search all areas that can have widgets for this widget, starting with main.
|
|
143
167
|
for (const area of ['main', 'top', 'left', 'right', 'menu']) {
|
|
144
|
-
const widget = find(this.widgets(area), w => w.id === id);
|
|
168
|
+
const widget = find(this.widgets(area), (w) => w.id === id);
|
|
145
169
|
if (widget) {
|
|
146
170
|
if (area === 'left') {
|
|
147
171
|
this.expandLeft(id);
|
|
@@ -198,14 +222,14 @@ export class NotebookShell extends Widget {
|
|
|
198
222
|
*/
|
|
199
223
|
collapseTop() {
|
|
200
224
|
this._topWrapper.setHidden(true);
|
|
201
|
-
this.
|
|
225
|
+
this._spacer_top.setHidden(true);
|
|
202
226
|
}
|
|
203
227
|
/**
|
|
204
228
|
* Expand the top area to show the header and the spacer.
|
|
205
229
|
*/
|
|
206
230
|
expandTop() {
|
|
207
231
|
this._topWrapper.setHidden(false);
|
|
208
|
-
this.
|
|
232
|
+
this._spacer_top.setHidden(false);
|
|
209
233
|
}
|
|
210
234
|
/**
|
|
211
235
|
* Return the list of widgets for the given area.
|
|
@@ -263,266 +287,3 @@ export class NotebookShell extends Widget {
|
|
|
263
287
|
this._rightHandler.panel.hide();
|
|
264
288
|
}
|
|
265
289
|
}
|
|
266
|
-
/**
|
|
267
|
-
* A class which manages a side bar that can show at most one widget at a time.
|
|
268
|
-
*/
|
|
269
|
-
export class SideBarHandler {
|
|
270
|
-
/**
|
|
271
|
-
* Construct a new side bar handler.
|
|
272
|
-
*/
|
|
273
|
-
constructor(area) {
|
|
274
|
-
this._isHiddenByUser = false;
|
|
275
|
-
this._items = new Array();
|
|
276
|
-
this._widgetAdded = new Signal(this);
|
|
277
|
-
this._widgetRemoved = new Signal(this);
|
|
278
|
-
this._area = area;
|
|
279
|
-
this._panel = new Panel();
|
|
280
|
-
this._panel.hide();
|
|
281
|
-
this._currentWidget = null;
|
|
282
|
-
this._lastCurrentWidget = null;
|
|
283
|
-
this._widgetPanel = new StackedPanel();
|
|
284
|
-
this._widgetPanel.widgetRemoved.connect(this._onWidgetRemoved, this);
|
|
285
|
-
const closeButton = document.createElement('button');
|
|
286
|
-
closeIcon.element({
|
|
287
|
-
container: closeButton,
|
|
288
|
-
height: '16px',
|
|
289
|
-
width: 'auto'
|
|
290
|
-
});
|
|
291
|
-
closeButton.onclick = () => {
|
|
292
|
-
this.collapse();
|
|
293
|
-
this.hide();
|
|
294
|
-
};
|
|
295
|
-
closeButton.className = 'jp-Button jp-SidePanel-collapse';
|
|
296
|
-
const icon = new Widget({ node: closeButton });
|
|
297
|
-
this._panel.addWidget(icon);
|
|
298
|
-
this._panel.addWidget(this._widgetPanel);
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Get the current widget in the sidebar panel.
|
|
302
|
-
*/
|
|
303
|
-
get currentWidget() {
|
|
304
|
-
return (this._currentWidget ||
|
|
305
|
-
this._lastCurrentWidget ||
|
|
306
|
-
(this._items.length > 0 ? this._items[0].widget : null));
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* Get the area of the side panel
|
|
310
|
-
*/
|
|
311
|
-
get area() {
|
|
312
|
-
return this._area;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Whether the panel is visible
|
|
316
|
-
*/
|
|
317
|
-
get isVisible() {
|
|
318
|
-
return this._panel.isVisible;
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* Get the stacked panel managed by the handler
|
|
322
|
-
*/
|
|
323
|
-
get panel() {
|
|
324
|
-
return this._panel;
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Get the widgets list.
|
|
328
|
-
*/
|
|
329
|
-
get widgets() {
|
|
330
|
-
return this._items.map(obj => obj.widget);
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Signal fired when a widget is added to the panel
|
|
334
|
-
*/
|
|
335
|
-
get widgetAdded() {
|
|
336
|
-
return this._widgetAdded;
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* Signal fired when a widget is removed from the panel
|
|
340
|
-
*/
|
|
341
|
-
get widgetRemoved() {
|
|
342
|
-
return this._widgetRemoved;
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Expand the sidebar.
|
|
346
|
-
*
|
|
347
|
-
* #### Notes
|
|
348
|
-
* This will open the most recently used widget, or the first widget
|
|
349
|
-
* if there is no most recently used.
|
|
350
|
-
*/
|
|
351
|
-
expand(id) {
|
|
352
|
-
if (this._currentWidget) {
|
|
353
|
-
this.collapse();
|
|
354
|
-
}
|
|
355
|
-
if (id) {
|
|
356
|
-
this.activate(id);
|
|
357
|
-
}
|
|
358
|
-
else {
|
|
359
|
-
const visibleWidget = this.currentWidget;
|
|
360
|
-
if (visibleWidget) {
|
|
361
|
-
this._currentWidget = visibleWidget;
|
|
362
|
-
this.activate(visibleWidget.id);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* Activate a widget residing in the stacked panel by ID.
|
|
368
|
-
*
|
|
369
|
-
* @param id - The widget's unique ID.
|
|
370
|
-
*/
|
|
371
|
-
activate(id) {
|
|
372
|
-
const widget = this._findWidgetByID(id);
|
|
373
|
-
if (widget) {
|
|
374
|
-
this._currentWidget = widget;
|
|
375
|
-
widget.show();
|
|
376
|
-
widget.activate();
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
/**
|
|
380
|
-
* Test whether the sidebar has the given widget by id.
|
|
381
|
-
*/
|
|
382
|
-
has(id) {
|
|
383
|
-
return this._findWidgetByID(id) !== null;
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* Collapse the sidebar so no items are expanded.
|
|
387
|
-
*/
|
|
388
|
-
collapse() {
|
|
389
|
-
var _a;
|
|
390
|
-
(_a = this._currentWidget) === null || _a === void 0 ? void 0 : _a.hide();
|
|
391
|
-
this._currentWidget = null;
|
|
392
|
-
}
|
|
393
|
-
/**
|
|
394
|
-
* Add a widget and its title to the stacked panel.
|
|
395
|
-
*
|
|
396
|
-
* If the widget is already added, it will be moved.
|
|
397
|
-
*/
|
|
398
|
-
addWidget(widget, rank) {
|
|
399
|
-
widget.parent = null;
|
|
400
|
-
widget.hide();
|
|
401
|
-
const item = { widget, rank };
|
|
402
|
-
const index = this._findInsertIndex(item);
|
|
403
|
-
ArrayExt.insert(this._items, index, item);
|
|
404
|
-
this._widgetPanel.insertWidget(index, widget);
|
|
405
|
-
this._refreshVisibility();
|
|
406
|
-
this._widgetAdded.emit(widget);
|
|
407
|
-
}
|
|
408
|
-
/**
|
|
409
|
-
* Hide the side panel
|
|
410
|
-
*/
|
|
411
|
-
hide() {
|
|
412
|
-
this._isHiddenByUser = true;
|
|
413
|
-
this._refreshVisibility();
|
|
414
|
-
}
|
|
415
|
-
/**
|
|
416
|
-
* Show the side panel
|
|
417
|
-
*/
|
|
418
|
-
show() {
|
|
419
|
-
this._isHiddenByUser = false;
|
|
420
|
-
this._refreshVisibility();
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Find the insertion index for a rank item.
|
|
424
|
-
*/
|
|
425
|
-
_findInsertIndex(item) {
|
|
426
|
-
return ArrayExt.upperBound(this._items, item, Private.itemCmp);
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Find the index of the item with the given widget, or `-1`.
|
|
430
|
-
*/
|
|
431
|
-
_findWidgetIndex(widget) {
|
|
432
|
-
return ArrayExt.findFirstIndex(this._items, i => i.widget === widget);
|
|
433
|
-
}
|
|
434
|
-
/**
|
|
435
|
-
* Find the widget with the given id, or `null`.
|
|
436
|
-
*/
|
|
437
|
-
_findWidgetByID(id) {
|
|
438
|
-
const item = find(this._items, value => value.widget.id === id);
|
|
439
|
-
return item ? item.widget : null;
|
|
440
|
-
}
|
|
441
|
-
/**
|
|
442
|
-
* Refresh the visibility of the stacked panel.
|
|
443
|
-
*/
|
|
444
|
-
_refreshVisibility() {
|
|
445
|
-
this._panel.setHidden(this._isHiddenByUser);
|
|
446
|
-
}
|
|
447
|
-
/*
|
|
448
|
-
* Handle the `widgetRemoved` signal from the panel.
|
|
449
|
-
*/
|
|
450
|
-
_onWidgetRemoved(sender, widget) {
|
|
451
|
-
if (widget === this._lastCurrentWidget) {
|
|
452
|
-
this._lastCurrentWidget = null;
|
|
453
|
-
}
|
|
454
|
-
ArrayExt.removeAt(this._items, this._findWidgetIndex(widget));
|
|
455
|
-
this._refreshVisibility();
|
|
456
|
-
this._widgetRemoved.emit(widget);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* A namespace for private module data.
|
|
461
|
-
*/
|
|
462
|
-
var Private;
|
|
463
|
-
(function (Private) {
|
|
464
|
-
/**
|
|
465
|
-
* A less-than comparison function for side bar rank items.
|
|
466
|
-
*/
|
|
467
|
-
function itemCmp(first, second) {
|
|
468
|
-
return first.rank - second.rank;
|
|
469
|
-
}
|
|
470
|
-
Private.itemCmp = itemCmp;
|
|
471
|
-
/**
|
|
472
|
-
* A class which manages a panel and sorts its widgets by rank.
|
|
473
|
-
*/
|
|
474
|
-
class PanelHandler {
|
|
475
|
-
constructor() {
|
|
476
|
-
/**
|
|
477
|
-
* A message hook for child add/remove messages on the main area dock panel.
|
|
478
|
-
*/
|
|
479
|
-
this._panelChildHook = (handler, msg) => {
|
|
480
|
-
switch (msg.type) {
|
|
481
|
-
case 'child-added':
|
|
482
|
-
{
|
|
483
|
-
const widget = msg.child;
|
|
484
|
-
// If we already know about this widget, we're done
|
|
485
|
-
if (this._items.find(v => v.widget === widget)) {
|
|
486
|
-
break;
|
|
487
|
-
}
|
|
488
|
-
// Otherwise, add to the end by default
|
|
489
|
-
const rank = this._items[this._items.length - 1].rank;
|
|
490
|
-
this._items.push({ widget, rank });
|
|
491
|
-
}
|
|
492
|
-
break;
|
|
493
|
-
case 'child-removed':
|
|
494
|
-
{
|
|
495
|
-
const widget = msg.child;
|
|
496
|
-
ArrayExt.removeFirstWhere(this._items, v => v.widget === widget);
|
|
497
|
-
}
|
|
498
|
-
break;
|
|
499
|
-
default:
|
|
500
|
-
break;
|
|
501
|
-
}
|
|
502
|
-
return true;
|
|
503
|
-
};
|
|
504
|
-
this._items = new Array();
|
|
505
|
-
this._panel = new Panel();
|
|
506
|
-
MessageLoop.installMessageHook(this._panel, this._panelChildHook);
|
|
507
|
-
}
|
|
508
|
-
/**
|
|
509
|
-
* Get the panel managed by the handler.
|
|
510
|
-
*/
|
|
511
|
-
get panel() {
|
|
512
|
-
return this._panel;
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
* Add a widget to the panel.
|
|
516
|
-
*
|
|
517
|
-
* If the widget is already added, it will be moved.
|
|
518
|
-
*/
|
|
519
|
-
addWidget(widget, rank) {
|
|
520
|
-
widget.parent = null;
|
|
521
|
-
const item = { widget, rank };
|
|
522
|
-
const index = ArrayExt.upperBound(this._items, item, Private.itemCmp);
|
|
523
|
-
ArrayExt.insert(this._items, index, item);
|
|
524
|
-
this._panel.insertWidget(index, widget);
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
Private.PanelHandler = PanelHandler;
|
|
528
|
-
})(Private || (Private = {}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyter-notebook/application",
|
|
3
|
-
"version": "7.0.0-
|
|
3
|
+
"version": "7.0.0-beta.0",
|
|
4
4
|
"description": "Jupyter Notebook - Application",
|
|
5
5
|
"homepage": "https://github.com/jupyter/notebook",
|
|
6
6
|
"bugs": {
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
"build:test": "tsc --build tsconfig.test.json",
|
|
36
36
|
"clean": "rimraf lib && rimraf tsconfig.tsbuildinfo",
|
|
37
37
|
"docs": "typedoc src",
|
|
38
|
-
"prepublishOnly": "npm run build",
|
|
39
38
|
"test": "jest",
|
|
40
39
|
"test:cov": "jest --collect-coverage",
|
|
41
40
|
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
|
|
@@ -43,27 +42,27 @@
|
|
|
43
42
|
"watch": "tsc -b --watch"
|
|
44
43
|
},
|
|
45
44
|
"dependencies": {
|
|
46
|
-
"@jupyterlab/application": "^4.0.0-
|
|
47
|
-
"@jupyterlab/coreutils": "^6.0.0-
|
|
48
|
-
"@jupyterlab/docregistry": "^4.0.0-
|
|
49
|
-
"@jupyterlab/rendermime-interfaces": "^3.8.0-
|
|
50
|
-
"@jupyterlab/ui-components": "^4.0.0-
|
|
51
|
-
"@lumino/algorithm": "^2.0.0
|
|
52
|
-
"@lumino/coreutils": "^2.0.0
|
|
53
|
-
"@lumino/messaging": "^2.0.0
|
|
54
|
-
"@lumino/polling": "^2.0.0
|
|
55
|
-
"@lumino/signaling": "^2.0.0
|
|
56
|
-
"@lumino/widgets": "^2.0.
|
|
45
|
+
"@jupyterlab/application": "^4.0.0-beta.0",
|
|
46
|
+
"@jupyterlab/coreutils": "^6.0.0-beta.0",
|
|
47
|
+
"@jupyterlab/docregistry": "^4.0.0-beta.0",
|
|
48
|
+
"@jupyterlab/rendermime-interfaces": "^3.8.0-beta.0",
|
|
49
|
+
"@jupyterlab/ui-components": "^4.0.0-beta.0",
|
|
50
|
+
"@lumino/algorithm": "^2.0.0",
|
|
51
|
+
"@lumino/coreutils": "^2.0.0",
|
|
52
|
+
"@lumino/messaging": "^2.0.0",
|
|
53
|
+
"@lumino/polling": "^2.0.0",
|
|
54
|
+
"@lumino/signaling": "^2.0.0",
|
|
55
|
+
"@lumino/widgets": "^2.0.1"
|
|
57
56
|
},
|
|
58
57
|
"devDependencies": {
|
|
59
58
|
"@babel/core": "^7.11.6",
|
|
60
59
|
"@babel/preset-env": "^7.12.1",
|
|
61
|
-
"@jupyterlab/testutils": "^4.0.0-
|
|
62
|
-
"@types/jest": "^
|
|
63
|
-
"jest": "^
|
|
60
|
+
"@jupyterlab/testutils": "^4.0.0-beta.0",
|
|
61
|
+
"@types/jest": "^29.2.5",
|
|
62
|
+
"jest": "^29.3.1",
|
|
64
63
|
"rimraf": "^3.0.2",
|
|
65
|
-
"ts-jest": "^
|
|
66
|
-
"typescript": "~
|
|
64
|
+
"ts-jest": "^29.0.3",
|
|
65
|
+
"typescript": "~5.0.2"
|
|
67
66
|
},
|
|
68
67
|
"publishConfig": {
|
|
69
68
|
"access": "public"
|
package/style/base.css
CHANGED
|
@@ -59,24 +59,33 @@ body {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
#main-panel {
|
|
62
|
-
box-shadow: var(--jp-elevation-z4);
|
|
63
62
|
margin-left: auto;
|
|
64
63
|
margin-right: auto;
|
|
65
64
|
max-width: var(--jp-notebook-max-width);
|
|
66
65
|
}
|
|
67
66
|
|
|
68
|
-
#spacer-widget {
|
|
67
|
+
#spacer-widget-top {
|
|
68
|
+
min-height: 16px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Only edit pages should have a bottom space */
|
|
72
|
+
|
|
73
|
+
body[data-notebook='edit'] #spacer-widget-bottom {
|
|
69
74
|
min-height: 16px;
|
|
70
75
|
}
|
|
71
76
|
|
|
72
77
|
/* Special case notebooks as document oriented pages */
|
|
73
78
|
|
|
79
|
+
[data-notebook]:not(body[data-notebook='notebooks']) #main-panel {
|
|
80
|
+
box-shadow: var(--jp-elevation-z4);
|
|
81
|
+
}
|
|
82
|
+
|
|
74
83
|
body[data-notebook='notebooks'] #main-panel {
|
|
75
84
|
margin-left: unset;
|
|
76
85
|
margin-right: unset;
|
|
77
86
|
max-width: unset;
|
|
78
87
|
}
|
|
79
88
|
|
|
80
|
-
body[data-notebook='notebooks'] #spacer-widget {
|
|
89
|
+
body[data-notebook='notebooks'] #spacer-widget-top {
|
|
81
90
|
min-height: unset;
|
|
82
91
|
}
|