@jupyter-notebook/application 7.0.0-alpha.6 → 7.0.0-alpha.8
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.d.ts +4 -0
- package/lib/app.js +4 -0
- package/lib/shell.d.ts +149 -2
- package/lib/shell.js +340 -31
- package/package.json +7 -7
- package/style/index.css +1 -0
- package/style/index.js +1 -0
- package/style/sidepanel.css +48 -0
package/lib/app.d.ts
CHANGED
|
@@ -24,6 +24,10 @@ export declare class NotebookApp extends JupyterFrontEnd<INotebookShell> {
|
|
|
24
24
|
* The application busy and dirty status signals and flags.
|
|
25
25
|
*/
|
|
26
26
|
readonly status: LabStatus;
|
|
27
|
+
/**
|
|
28
|
+
* Promise that resolves when the state is first restored
|
|
29
|
+
*/
|
|
30
|
+
readonly restored: Promise<void>;
|
|
27
31
|
/**
|
|
28
32
|
* The version of the application.
|
|
29
33
|
*/
|
package/lib/app.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Jupyter Development Team.
|
|
2
2
|
// Distributed under the terms of the Modified BSD License.
|
|
3
3
|
import { JupyterFrontEnd } from '@jupyterlab/application';
|
|
4
|
+
import { Base64ModelFactory } from '@jupyterlab/docregistry';
|
|
4
5
|
import { createRendermimePlugins } from '@jupyterlab/application/lib/mimerenderers';
|
|
5
6
|
import { LabStatus } from '@jupyterlab/application/lib/status';
|
|
6
7
|
import { PageConfig } from '@jupyterlab/coreutils';
|
|
@@ -37,11 +38,14 @@ export class NotebookApp extends JupyterFrontEnd {
|
|
|
37
38
|
this._formatter = new Throttler(() => {
|
|
38
39
|
Private.setFormat(this);
|
|
39
40
|
}, 250);
|
|
41
|
+
// Add initial model factory.
|
|
42
|
+
this.docRegistry.addModelFactory(new Base64ModelFactory());
|
|
40
43
|
if (options.mimeExtensions) {
|
|
41
44
|
for (const plugin of createRendermimePlugins(options.mimeExtensions)) {
|
|
42
45
|
this.registerPlugin(plugin);
|
|
43
46
|
}
|
|
44
47
|
}
|
|
48
|
+
this.restored = this.shell.restored;
|
|
45
49
|
this.restored.then(() => this._formatter.invoke());
|
|
46
50
|
}
|
|
47
51
|
/**
|
package/lib/shell.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { JupyterFrontEnd } from '@jupyterlab/application';
|
|
|
2
2
|
import { DocumentRegistry } from '@jupyterlab/docregistry';
|
|
3
3
|
import { Token } from '@lumino/coreutils';
|
|
4
4
|
import { ISignal } from '@lumino/signaling';
|
|
5
|
-
import { Widget } from '@lumino/widgets';
|
|
5
|
+
import { Panel, Widget } from '@lumino/widgets';
|
|
6
6
|
/**
|
|
7
7
|
* The Jupyter Notebook application shell token.
|
|
8
8
|
*/
|
|
@@ -33,6 +33,26 @@ export declare class NotebookShell extends Widget implements JupyterFrontEnd.ISh
|
|
|
33
33
|
* Get the menu area wrapper panel
|
|
34
34
|
*/
|
|
35
35
|
get menu(): Widget;
|
|
36
|
+
/**
|
|
37
|
+
* Get the left area handler
|
|
38
|
+
*/
|
|
39
|
+
get leftHandler(): SideBarHandler;
|
|
40
|
+
/**
|
|
41
|
+
* Get the right area handler
|
|
42
|
+
*/
|
|
43
|
+
get rightHandler(): SideBarHandler;
|
|
44
|
+
/**
|
|
45
|
+
* Is the left sidebar visible?
|
|
46
|
+
*/
|
|
47
|
+
get leftCollapsed(): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Is the right sidebar visible?
|
|
50
|
+
*/
|
|
51
|
+
get rightCollapsed(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Promise that resolves when the main widget is loaded
|
|
54
|
+
*/
|
|
55
|
+
get restored(): Promise<void>;
|
|
36
56
|
/**
|
|
37
57
|
* Activate a widget in its area.
|
|
38
58
|
*/
|
|
@@ -63,13 +83,32 @@ export declare class NotebookShell extends Widget implements JupyterFrontEnd.ISh
|
|
|
63
83
|
* @param area The area
|
|
64
84
|
*/
|
|
65
85
|
widgets(area: Shell.Area): IterableIterator<Widget>;
|
|
86
|
+
/**
|
|
87
|
+
* Expand the left panel to show the sidebar with its widget.
|
|
88
|
+
*/
|
|
89
|
+
expandLeft(id?: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* Collapse the left panel
|
|
92
|
+
*/
|
|
93
|
+
collapseLeft(): void;
|
|
94
|
+
/**
|
|
95
|
+
* Expand the right panel to show the sidebar with its widget.
|
|
96
|
+
*/
|
|
97
|
+
expandRight(id?: string): void;
|
|
98
|
+
/**
|
|
99
|
+
* Collapse the right panel
|
|
100
|
+
*/
|
|
101
|
+
collapseRight(): void;
|
|
66
102
|
private _topWrapper;
|
|
67
103
|
private _topHandler;
|
|
68
104
|
private _menuWrapper;
|
|
69
105
|
private _menuHandler;
|
|
106
|
+
private _leftHandler;
|
|
107
|
+
private _rightHandler;
|
|
70
108
|
private _spacer;
|
|
71
109
|
private _main;
|
|
72
110
|
private _currentChanged;
|
|
111
|
+
private _mainWidgetLoaded;
|
|
73
112
|
}
|
|
74
113
|
/**
|
|
75
114
|
* A namespace for Shell statics
|
|
@@ -78,5 +117,113 @@ export declare namespace Shell {
|
|
|
78
117
|
/**
|
|
79
118
|
* The areas of the application shell where widgets can reside.
|
|
80
119
|
*/
|
|
81
|
-
type Area = 'main' | 'top' | 'menu';
|
|
120
|
+
type Area = 'main' | 'top' | 'left' | 'right' | 'menu';
|
|
121
|
+
}
|
|
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;
|
|
82
229
|
}
|
package/lib/shell.js
CHANGED
|
@@ -1,10 +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 { closeIcon } from '@jupyterlab/ui-components';
|
|
4
|
+
import { ArrayExt, find } from '@lumino/algorithm';
|
|
5
|
+
import { PromiseDelegate, Token } from '@lumino/coreutils';
|
|
5
6
|
import { MessageLoop } from '@lumino/messaging';
|
|
6
7
|
import { Signal } from '@lumino/signaling';
|
|
7
|
-
import { Panel,
|
|
8
|
+
import { BoxLayout, Panel, SplitPanel, StackedPanel, Widget } from '@lumino/widgets';
|
|
8
9
|
/**
|
|
9
10
|
* The Jupyter Notebook application shell token.
|
|
10
11
|
*/
|
|
@@ -20,31 +21,63 @@ export class NotebookShell extends Widget {
|
|
|
20
21
|
constructor() {
|
|
21
22
|
super();
|
|
22
23
|
this._currentChanged = new Signal(this);
|
|
24
|
+
this._mainWidgetLoaded = new PromiseDelegate();
|
|
23
25
|
this.id = 'main';
|
|
24
|
-
const rootLayout = new BoxLayout();
|
|
25
26
|
this._topHandler = new Private.PanelHandler();
|
|
26
27
|
this._menuHandler = new Private.PanelHandler();
|
|
28
|
+
this._leftHandler = new SideBarHandler('left');
|
|
29
|
+
this._rightHandler = new SideBarHandler('right');
|
|
27
30
|
this._main = new Panel();
|
|
31
|
+
const topWrapper = (this._topWrapper = new Panel());
|
|
32
|
+
const menuWrapper = (this._menuWrapper = new Panel());
|
|
28
33
|
this._topHandler.panel.id = 'top-panel';
|
|
29
34
|
this._menuHandler.panel.id = 'menu-panel';
|
|
30
35
|
this._main.id = 'main-panel';
|
|
36
|
+
this._spacer = new Widget();
|
|
37
|
+
this._spacer.id = 'spacer-widget';
|
|
31
38
|
// create wrappers around the top and menu areas
|
|
32
|
-
const topWrapper = (this._topWrapper = new Panel());
|
|
33
39
|
topWrapper.id = 'top-panel-wrapper';
|
|
34
40
|
topWrapper.addWidget(this._topHandler.panel);
|
|
35
|
-
const menuWrapper = (this._menuWrapper = new Panel());
|
|
36
41
|
menuWrapper.id = 'menu-panel-wrapper';
|
|
37
42
|
menuWrapper.addWidget(this._menuHandler.panel);
|
|
38
|
-
BoxLayout
|
|
39
|
-
|
|
43
|
+
const rootLayout = new BoxLayout();
|
|
44
|
+
const leftHandler = this._leftHandler;
|
|
45
|
+
const rightHandler = this._rightHandler;
|
|
46
|
+
leftHandler.panel.id = 'jp-left-stack';
|
|
47
|
+
rightHandler.panel.id = 'jp-right-stack';
|
|
48
|
+
// Hide the side panels by default.
|
|
49
|
+
leftHandler.hide();
|
|
50
|
+
rightHandler.hide();
|
|
51
|
+
const middleLayout = new BoxLayout({
|
|
52
|
+
spacing: 0,
|
|
53
|
+
direction: 'top-to-bottom'
|
|
54
|
+
});
|
|
55
|
+
BoxLayout.setStretch(this._topWrapper, 0);
|
|
56
|
+
BoxLayout.setStretch(this._menuWrapper, 0);
|
|
40
57
|
BoxLayout.setStretch(this._main, 1);
|
|
41
|
-
|
|
42
|
-
this.
|
|
58
|
+
const middlePanel = new Panel({ layout: middleLayout });
|
|
59
|
+
middlePanel.addWidget(this._topWrapper);
|
|
60
|
+
middlePanel.addWidget(this._menuWrapper);
|
|
61
|
+
middlePanel.addWidget(this._spacer);
|
|
62
|
+
middlePanel.addWidget(this._main);
|
|
63
|
+
middlePanel.layout = middleLayout;
|
|
64
|
+
// TODO: Consider storing this as an attribute this._hsplitPanel if saving/restoring layout needed
|
|
65
|
+
const hsplitPanel = new SplitPanel();
|
|
66
|
+
hsplitPanel.id = 'main-split-panel';
|
|
67
|
+
hsplitPanel.spacing = 1;
|
|
68
|
+
BoxLayout.setStretch(hsplitPanel, 1);
|
|
69
|
+
SplitPanel.setStretch(leftHandler.panel, 0);
|
|
70
|
+
SplitPanel.setStretch(rightHandler.panel, 0);
|
|
71
|
+
SplitPanel.setStretch(middlePanel, 1);
|
|
72
|
+
hsplitPanel.addWidget(leftHandler.panel);
|
|
73
|
+
hsplitPanel.addWidget(middlePanel);
|
|
74
|
+
hsplitPanel.addWidget(rightHandler.panel);
|
|
75
|
+
// Use relative sizing to set the width of the side panels.
|
|
76
|
+
// This will still respect the min-size of children widget in the stacked
|
|
77
|
+
// panel.
|
|
78
|
+
hsplitPanel.setRelativeSizes([1, 2.5, 1]);
|
|
43
79
|
rootLayout.spacing = 0;
|
|
44
|
-
rootLayout.addWidget(
|
|
45
|
-
rootLayout.addWidget(menuWrapper);
|
|
46
|
-
rootLayout.addWidget(this._spacer);
|
|
47
|
-
rootLayout.addWidget(this._main);
|
|
80
|
+
rootLayout.addWidget(hsplitPanel);
|
|
48
81
|
this.layout = rootLayout;
|
|
49
82
|
}
|
|
50
83
|
/**
|
|
@@ -72,13 +105,54 @@ export class NotebookShell extends Widget {
|
|
|
72
105
|
get menu() {
|
|
73
106
|
return this._menuWrapper;
|
|
74
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Get the left area handler
|
|
110
|
+
*/
|
|
111
|
+
get leftHandler() {
|
|
112
|
+
return this._leftHandler;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get the right area handler
|
|
116
|
+
*/
|
|
117
|
+
get rightHandler() {
|
|
118
|
+
return this._rightHandler;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Is the left sidebar visible?
|
|
122
|
+
*/
|
|
123
|
+
get leftCollapsed() {
|
|
124
|
+
return !(this._leftHandler.isVisible && this._leftHandler.panel.isVisible);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Is the right sidebar visible?
|
|
128
|
+
*/
|
|
129
|
+
get rightCollapsed() {
|
|
130
|
+
return !(this._rightHandler.isVisible && this._rightHandler.panel.isVisible);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Promise that resolves when the main widget is loaded
|
|
134
|
+
*/
|
|
135
|
+
get restored() {
|
|
136
|
+
return this._mainWidgetLoaded.promise;
|
|
137
|
+
}
|
|
75
138
|
/**
|
|
76
139
|
* Activate a widget in its area.
|
|
77
140
|
*/
|
|
78
141
|
activateById(id) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
widget.
|
|
142
|
+
// Search all areas that can have widgets for this widget, starting with main.
|
|
143
|
+
for (const area of ['main', 'top', 'left', 'right', 'menu']) {
|
|
144
|
+
const widget = find(this.widgets(area), w => w.id === id);
|
|
145
|
+
if (widget) {
|
|
146
|
+
if (area === 'left') {
|
|
147
|
+
this.expandLeft(id);
|
|
148
|
+
}
|
|
149
|
+
else if (area === 'right') {
|
|
150
|
+
this.expandRight(id);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
widget.activate();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
82
156
|
}
|
|
83
157
|
}
|
|
84
158
|
/**
|
|
@@ -95,20 +169,28 @@ export class NotebookShell extends Widget {
|
|
|
95
169
|
add(widget, area, options) {
|
|
96
170
|
var _a;
|
|
97
171
|
const rank = (_a = options === null || options === void 0 ? void 0 : options.rank) !== null && _a !== void 0 ? _a : DEFAULT_RANK;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
172
|
+
switch (area) {
|
|
173
|
+
case 'top':
|
|
174
|
+
return this._topHandler.addWidget(widget, rank);
|
|
175
|
+
case 'menu':
|
|
176
|
+
return this._menuHandler.addWidget(widget, rank);
|
|
177
|
+
case 'main':
|
|
178
|
+
case undefined:
|
|
179
|
+
if (this._main.widgets.length > 0) {
|
|
180
|
+
// do not add the widget if there is already one
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
this._main.addWidget(widget);
|
|
184
|
+
this._main.update();
|
|
185
|
+
this._currentChanged.emit(void 0);
|
|
186
|
+
this._mainWidgetLoaded.resolve();
|
|
187
|
+
break;
|
|
188
|
+
case 'left':
|
|
189
|
+
return this._leftHandler.addWidget(widget, rank);
|
|
190
|
+
case 'right':
|
|
191
|
+
return this._rightHandler.addWidget(widget, rank);
|
|
192
|
+
default:
|
|
193
|
+
console.warn(`Cannot add widget to area: ${area}`);
|
|
112
194
|
}
|
|
113
195
|
}
|
|
114
196
|
/**
|
|
@@ -141,11 +223,238 @@ export class NotebookShell extends Widget {
|
|
|
141
223
|
case 'main':
|
|
142
224
|
yield* this._main.widgets;
|
|
143
225
|
return;
|
|
226
|
+
case 'left':
|
|
227
|
+
yield* this._leftHandler.widgets;
|
|
228
|
+
return;
|
|
229
|
+
case 'right':
|
|
230
|
+
yield* this._rightHandler.widgets;
|
|
231
|
+
return;
|
|
144
232
|
default:
|
|
145
233
|
console.error(`This shell has no area called "${area}"`);
|
|
146
234
|
return;
|
|
147
235
|
}
|
|
148
236
|
}
|
|
237
|
+
/**
|
|
238
|
+
* Expand the left panel to show the sidebar with its widget.
|
|
239
|
+
*/
|
|
240
|
+
expandLeft(id) {
|
|
241
|
+
this._leftHandler.panel.show();
|
|
242
|
+
this._leftHandler.expand(id); // Show the current widget, if any
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Collapse the left panel
|
|
246
|
+
*/
|
|
247
|
+
collapseLeft() {
|
|
248
|
+
this._leftHandler.collapse();
|
|
249
|
+
this._leftHandler.panel.hide();
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Expand the right panel to show the sidebar with its widget.
|
|
253
|
+
*/
|
|
254
|
+
expandRight(id) {
|
|
255
|
+
this._rightHandler.panel.show();
|
|
256
|
+
this._rightHandler.expand(id); // Show the current widget, if any
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Collapse the right panel
|
|
260
|
+
*/
|
|
261
|
+
collapseRight() {
|
|
262
|
+
this._rightHandler.collapse();
|
|
263
|
+
this._rightHandler.panel.hide();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
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
|
+
}
|
|
149
458
|
}
|
|
150
459
|
/**
|
|
151
460
|
* A namespace for private module data.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyter-notebook/application",
|
|
3
|
-
"version": "7.0.0-alpha.
|
|
3
|
+
"version": "7.0.0-alpha.8",
|
|
4
4
|
"description": "Jupyter Notebook - Application",
|
|
5
5
|
"homepage": "https://github.com/jupyter/notebook",
|
|
6
6
|
"bugs": {
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
"watch": "tsc -b --watch"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@jupyterlab/application": "^4.0.0-alpha.
|
|
47
|
-
"@jupyterlab/coreutils": "^6.0.0-alpha.
|
|
48
|
-
"@jupyterlab/docregistry": "^4.0.0-alpha.
|
|
49
|
-
"@jupyterlab/rendermime-interfaces": "^3.8.0-alpha.
|
|
50
|
-
"@jupyterlab/ui-components": "^4.0.0-alpha.
|
|
46
|
+
"@jupyterlab/application": "^4.0.0-alpha.15",
|
|
47
|
+
"@jupyterlab/coreutils": "^6.0.0-alpha.15",
|
|
48
|
+
"@jupyterlab/docregistry": "^4.0.0-alpha.15",
|
|
49
|
+
"@jupyterlab/rendermime-interfaces": "^3.8.0-alpha.15",
|
|
50
|
+
"@jupyterlab/ui-components": "^4.0.0-alpha.30",
|
|
51
51
|
"@lumino/algorithm": "^2.0.0-alpha.6",
|
|
52
52
|
"@lumino/coreutils": "^2.0.0-alpha.6",
|
|
53
53
|
"@lumino/messaging": "^2.0.0-alpha.6",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@babel/core": "^7.11.6",
|
|
60
60
|
"@babel/preset-env": "^7.12.1",
|
|
61
|
-
"@jupyterlab/testutils": "^4.0.0-alpha.
|
|
61
|
+
"@jupyterlab/testutils": "^4.0.0-alpha.15",
|
|
62
62
|
"@types/jest": "^26.0.10",
|
|
63
63
|
"jest": "^26.4.2",
|
|
64
64
|
"rimraf": "^3.0.2",
|
package/style/index.css
CHANGED
package/style/index.js
CHANGED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/*-----------------------------------------------------------------------------
|
|
2
|
+
| Copyright (c) Jupyter Development Team.
|
|
3
|
+
| Distributed under the terms of the Modified BSD License.
|
|
4
|
+
|
|
|
5
|
+
| Adapted from JupyterLab's packages/application/style/sidepanel.css.
|
|
6
|
+
|----------------------------------------------------------------------------*/
|
|
7
|
+
|
|
8
|
+
/*-----------------------------------------------------------------------------
|
|
9
|
+
| Variables
|
|
10
|
+
|----------------------------------------------------------------------------*/
|
|
11
|
+
|
|
12
|
+
:root {
|
|
13
|
+
--jp-private-sidebar-tab-width: 32px;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/*-----------------------------------------------------------------------------
|
|
17
|
+
| SideBar
|
|
18
|
+
|----------------------------------------------------------------------------*/
|
|
19
|
+
|
|
20
|
+
/* Stack panels */
|
|
21
|
+
|
|
22
|
+
#jp-right-stack,
|
|
23
|
+
#jp-left-stack {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
min-width: var(--jp-sidebar-min-width);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#jp-left-stack .jp-SidePanel-collapse,
|
|
30
|
+
#jp-right-stack .jp-SidePanel-collapse {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex: 0 0 auto;
|
|
33
|
+
min-height: 0;
|
|
34
|
+
padding: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#jp-left-stack .jp-SidePanel-collapse {
|
|
38
|
+
justify-content: right;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
#jp-right-stack .jp-SidePanel-collapse {
|
|
42
|
+
justify-content: left;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
#jp-left-stack .lm-StackedPanel,
|
|
46
|
+
#jp-right-stack .lm-StackedPanel {
|
|
47
|
+
flex: 1 1 auto;
|
|
48
|
+
}
|