xtralab 0.15.0 → 0.15.1
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/README.md +10 -0
- package/lib/about/icons.d.ts +0 -5
- package/lib/about/icons.js +0 -5
- package/lib/about/index.d.ts +4 -8
- package/lib/about/index.js +6 -17
- package/lib/agentSessions.d.ts +9 -29
- package/lib/agentSessions.js +2 -7
- package/lib/askAgent/editorSelection.d.ts +20 -26
- package/lib/askAgent/editorSelection.js +11 -26
- package/lib/askAgent/icons.d.ts +2 -3
- package/lib/askAgent/icons.js +2 -3
- package/lib/askAgent/index.d.ts +4 -26
- package/lib/askAgent/index.js +54 -158
- package/lib/askAgent/popup.d.ts +12 -16
- package/lib/askAgent/popup.js +18 -37
- package/lib/askAgent/prompt.d.ts +3 -5
- package/lib/askAgent/prompt.js +6 -19
- package/lib/askAgent/queue.d.ts +11 -21
- package/lib/askAgent/queue.js +9 -19
- package/lib/askAgent/queuePanel.d.ts +13 -18
- package/lib/askAgent/queuePanel.js +15 -37
- package/lib/askAgent/targetPicker.d.ts +2 -9
- package/lib/askAgent/targetPicker.js +6 -11
- package/lib/askAgent/tokens.d.ts +32 -46
- package/lib/askAgent/tokens.js +4 -6
- package/lib/commandBar/index.d.ts +4 -13
- package/lib/commandBar/index.js +21 -39
- package/lib/customPanel/index.js +15 -0
- package/lib/editorBreadcrumbs/index.d.ts +3 -6
- package/lib/editorBreadcrumbs/index.js +10 -6
- package/lib/editorBreadcrumbs/widget.d.ts +17 -4
- package/lib/editorBreadcrumbs/widget.js +11 -17
- package/lib/editorIndent/index.d.ts +4 -12
- package/lib/editorIndent/index.js +8 -23
- package/lib/fileBrowser/commands.d.ts +28 -19
- package/lib/fileBrowser/commands.js +39 -98
- package/lib/fileBrowser/contents.d.ts +3 -0
- package/lib/fileBrowser/dragAndDrop.d.ts +17 -4
- package/lib/fileBrowser/dragAndDrop.js +2 -7
- package/lib/fileBrowser/fileBrowser.d.ts +19 -9
- package/lib/fileBrowser/fileBrowser.js +68 -216
- package/lib/fileBrowser/gitStatus.d.ts +4 -9
- package/lib/fileBrowser/gitStatus.js +7 -17
- package/lib/fileBrowser/gitignore.d.ts +4 -17
- package/lib/fileBrowser/gitignore.js +4 -25
- package/lib/fileBrowser/icons.d.ts +7 -17
- package/lib/fileBrowser/icons.js +25 -80
- package/lib/fileBrowser/index.js +2 -4
- package/lib/fileBrowser/widget.d.ts +126 -48
- package/lib/fileBrowser/widget.js +89 -4
- package/lib/fileTypeIcons/index.js +0 -10
- package/lib/git/api.d.ts +5 -13
- package/lib/git/api.js +10 -36
- package/lib/git/askRequest.d.ts +4 -8
- package/lib/git/askRequest.js +6 -20
- package/lib/git/commands.d.ts +40 -5
- package/lib/git/commands.js +16 -10
- package/lib/git/diffModel.js +4 -0
- package/lib/git/diffSurface.d.ts +41 -55
- package/lib/git/diffSurface.js +42 -117
- package/lib/git/diffWidget.d.ts +81 -2
- package/lib/git/diffWidget.js +62 -12
- package/lib/git/imageDiff.d.ts +5 -6
- package/lib/git/imageDiff.js +18 -48
- package/lib/git/index.d.ts +0 -3
- package/lib/git/index.js +3 -8
- package/lib/git/notebookDiff.d.ts +110 -33
- package/lib/git/notebookDiff.js +52 -195
- package/lib/git/tokens.d.ts +73 -31
- package/lib/git/tokens.js +2 -3
- package/lib/highlight/index.d.ts +4 -10
- package/lib/highlight/index.js +10 -41
- package/lib/index.d.ts +0 -9
- package/lib/index.js +0 -9
- package/lib/launcher/agents.d.ts +55 -51
- package/lib/launcher/agents.js +15 -57
- package/lib/launcher/availability.d.ts +3 -9
- package/lib/launcher/availability.js +3 -9
- package/lib/launcher/commands.d.ts +7 -32
- package/lib/launcher/commands.js +14 -45
- package/lib/launcher/dashboard.d.ts +19 -24
- package/lib/launcher/dashboard.js +21 -67
- package/lib/launcher/editorRegistry.d.ts +10 -22
- package/lib/launcher/editorRegistry.js +14 -18
- package/lib/launcher/editors.d.ts +39 -45
- package/lib/launcher/editors.js +8 -34
- package/lib/launcher/icons.d.ts +0 -12
- package/lib/launcher/icons.js +5 -39
- package/lib/launcher/index.js +12 -55
- package/lib/launcher/invocation.d.ts +4 -10
- package/lib/launcher/invocation.js +7 -22
- package/lib/launcher/registry.d.ts +9 -7
- package/lib/launcher/registry.js +9 -7
- package/lib/launcher/tokens.d.ts +10 -22
- package/lib/launcher/tokens.js +5 -8
- package/lib/menuBar/index.d.ts +3 -10
- package/lib/menuBar/index.js +11 -28
- package/lib/menus/index.d.ts +3 -9
- package/lib/menus/index.js +14 -30
- package/lib/omnibox/files.d.ts +2 -4
- package/lib/omnibox/files.js +5 -11
- package/lib/omnibox/index.d.ts +4 -14
- package/lib/omnibox/index.js +9 -27
- package/lib/omnibox/model.d.ts +38 -10
- package/lib/omnibox/model.js +15 -33
- package/lib/omnibox/recents.d.ts +15 -17
- package/lib/omnibox/recents.js +12 -17
- package/lib/omnibox/tokens.d.ts +5 -10
- package/lib/omnibox/tokens.js +2 -6
- package/lib/omnibox/widget.d.ts +11 -7
- package/lib/omnibox/widget.js +8 -16
- package/lib/searchReplace/index.d.ts +4 -20
- package/lib/searchReplace/index.js +7 -27
- package/lib/showOutput/index.d.ts +3 -12
- package/lib/showOutput/index.js +6 -22
- package/lib/sidebar/index.d.ts +4 -7
- package/lib/sidebar/index.js +5 -12
- package/lib/terminalNotifications/index.d.ts +4 -10
- package/lib/terminalNotifications/index.js +6 -20
- package/lib/terminals/agentTerminals.d.ts +12 -5
- package/lib/terminals/agentTerminals.js +25 -44
- package/lib/terminals/detection.d.ts +4 -8
- package/lib/terminals/detection.js +4 -8
- package/lib/terminals/index.d.ts +0 -35
- package/lib/terminals/index.js +12 -101
- package/lib/terminals/model.d.ts +64 -139
- package/lib/terminals/model.js +80 -220
- package/lib/terminals/tokens.d.ts +11 -22
- package/lib/terminals/tokens.js +2 -2
- package/lib/terminals/widget.d.ts +43 -13
- package/lib/terminals/widget.js +33 -18
- package/lib/topBar/icons.d.ts +3 -8
- package/lib/topBar/icons.js +3 -8
- package/lib/topBar/index.d.ts +4 -11
- package/lib/topBar/index.js +10 -38
- package/lib/walkthrough/index.d.ts +4 -9
- package/lib/walkthrough/index.js +6 -20
- package/lib/walkthrough/panel.d.ts +40 -9
- package/lib/walkthrough/panel.js +4 -10
- package/package.json +2 -2
- package/src/about/icons.ts +0 -5
- package/src/about/index.tsx +6 -17
- package/src/agentSessions.ts +9 -29
- package/src/askAgent/editorSelection.ts +22 -29
- package/src/askAgent/icons.ts +2 -3
- package/src/askAgent/index.ts +54 -158
- package/src/askAgent/popup.tsx +23 -45
- package/src/askAgent/prompt.ts +6 -19
- package/src/askAgent/queue.ts +13 -24
- package/src/askAgent/queuePanel.tsx +21 -46
- package/src/askAgent/targetPicker.tsx +5 -15
- package/src/askAgent/tokens.ts +32 -46
- package/src/commandBar/index.ts +24 -39
- package/src/customPanel/index.ts +15 -0
- package/src/editorBreadcrumbs/index.ts +10 -6
- package/src/editorBreadcrumbs/widget.ts +23 -17
- package/src/editorIndent/index.ts +17 -23
- package/src/fileBrowser/commands.ts +57 -98
- package/src/fileBrowser/contents.ts +3 -0
- package/src/fileBrowser/dragAndDrop.ts +17 -7
- package/src/fileBrowser/fileBrowser.tsx +84 -223
- package/src/fileBrowser/gitStatus.ts +7 -17
- package/src/fileBrowser/gitignore.ts +4 -25
- package/src/fileBrowser/icons.ts +25 -80
- package/src/fileBrowser/index.ts +2 -4
- package/src/fileBrowser/widget.tsx +149 -50
- package/src/fileTypeIcons/index.ts +0 -10
- package/src/git/api.ts +10 -36
- package/src/git/askRequest.ts +6 -20
- package/src/git/commands.ts +70 -10
- package/src/git/diffModel.ts +25 -0
- package/src/git/diffSurface.tsx +71 -159
- package/src/git/diffWidget.tsx +104 -14
- package/src/git/imageDiff.tsx +45 -51
- package/src/git/index.ts +3 -8
- package/src/git/notebookDiff.tsx +211 -238
- package/src/git/tokens.ts +73 -31
- package/src/highlight/index.ts +10 -41
- package/src/index.ts +0 -9
- package/src/launcher/agents.ts +64 -95
- package/src/launcher/availability.ts +3 -9
- package/src/launcher/commands.ts +14 -51
- package/src/launcher/dashboard.tsx +49 -88
- package/src/launcher/editorRegistry.ts +21 -29
- package/src/launcher/editors.ts +39 -58
- package/src/launcher/icons.ts +5 -39
- package/src/launcher/index.ts +12 -55
- package/src/launcher/invocation.ts +7 -22
- package/src/launcher/registry.ts +9 -7
- package/src/launcher/tokens.ts +10 -22
- package/src/menuBar/index.ts +11 -28
- package/src/menus/index.ts +14 -30
- package/src/omnibox/files.ts +10 -14
- package/src/omnibox/index.ts +9 -27
- package/src/omnibox/model.ts +50 -38
- package/src/omnibox/recents.ts +17 -22
- package/src/omnibox/tokens.ts +5 -10
- package/src/omnibox/widget.tsx +14 -19
- package/src/searchReplace/index.ts +7 -27
- package/src/showOutput/index.ts +6 -22
- package/src/sidebar/index.ts +20 -12
- package/src/terminalNotifications/index.ts +42 -25
- package/src/terminals/agentTerminals.ts +25 -49
- package/src/terminals/detection.ts +4 -8
- package/src/terminals/index.ts +12 -101
- package/src/terminals/model.ts +130 -246
- package/src/terminals/tokens.ts +11 -22
- package/src/terminals/widget.tsx +48 -31
- package/src/topBar/icons.ts +3 -8
- package/src/topBar/index.ts +21 -44
- package/src/walkthrough/index.ts +6 -20
- package/src/walkthrough/panel.ts +40 -10
- package/style/about.css +2 -7
- package/style/askAgent.css +8 -40
- package/style/base.css +9 -45
- package/style/chrome.css +108 -308
- package/style/commandBar.css +4 -20
- package/style/customPanel.css +1 -4
- package/style/git.css +22 -184
- package/style/highlight.css +1 -3
- package/style/launcher.css +6 -70
- package/style/omnibox.css +2 -14
- package/style/showOutput.css +0 -6
- package/style/sidebar.css +29 -9
- package/style/tabs.css +5 -13
- package/style/terminals.css +6 -53
- package/style/topBar.css +2 -22
- package/style/walkthrough.css +0 -8
package/src/commandBar/index.ts
CHANGED
|
@@ -12,25 +12,13 @@ import { IOmnibox, OMNIBOX_OPEN_COMMAND } from '../omnibox/tokens';
|
|
|
12
12
|
|
|
13
13
|
const PLUGIN_ID = 'xtralab:command-bar';
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
* Factory name of JupyterLab's settings-driven top bar toolbar (`#jp-top-bar`,
|
|
17
|
-
* built by `@jupyterlab/application-extension:top-bar`).
|
|
18
|
-
*/
|
|
19
15
|
const TOPBAR_FACTORY = 'TopBar';
|
|
20
16
|
|
|
21
|
-
/**
|
|
22
|
-
* Name of the pill item within that toolbar. Its placement is declared under
|
|
23
|
-
* `jupyter.lab.toolbars` in this plugin's settings schema
|
|
24
|
-
* (schema/command-bar.json): the core toolbar ships a spacer at rank 50, so
|
|
25
|
-
* the pill's higher rank lands it at the trailing end of the toolbar, next to
|
|
26
|
-
* the right-sidebar toggle button.
|
|
27
|
-
*/
|
|
28
17
|
const ITEM_NAME = 'omnibox';
|
|
29
18
|
|
|
30
19
|
/**
|
|
31
|
-
* A search-bar-styled launcher pill
|
|
32
|
-
*
|
|
33
|
-
* which opens the omnibox.
|
|
20
|
+
* A search-bar-styled launcher pill with no input of its own: activating it
|
|
21
|
+
* runs `onActivate`, which opens the omnibox.
|
|
34
22
|
*/
|
|
35
23
|
class CommandBar extends Widget {
|
|
36
24
|
constructor(options: CommandBar.IOptions) {
|
|
@@ -45,19 +33,26 @@ class CommandBar extends Widget {
|
|
|
45
33
|
this._onActivate = options.onActivate;
|
|
46
34
|
}
|
|
47
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Handle the DOM events for the command bar.
|
|
38
|
+
*/
|
|
48
39
|
handleEvent(event: Event): void {
|
|
49
40
|
if (event.type === 'click') {
|
|
50
41
|
this._onActivate();
|
|
51
42
|
}
|
|
52
43
|
}
|
|
53
44
|
|
|
45
|
+
/**
|
|
46
|
+
* A message handler invoked on an `'after-attach'` message.
|
|
47
|
+
*/
|
|
54
48
|
protected onAfterAttach(): void {
|
|
55
|
-
//
|
|
56
|
-
// listened on here; keyboard Enter/Space on the focused button raises the
|
|
57
|
-
// same synthetic click.
|
|
49
|
+
// Keyboard Enter/Space on the focused button raises the same synthetic click.
|
|
58
50
|
this.node.addEventListener('click', this);
|
|
59
51
|
}
|
|
60
52
|
|
|
53
|
+
/**
|
|
54
|
+
* A message handler invoked on a `'before-detach'` message.
|
|
55
|
+
*/
|
|
61
56
|
protected onBeforeDetach(): void {
|
|
62
57
|
this.node.removeEventListener('click', this);
|
|
63
58
|
}
|
|
@@ -66,6 +61,9 @@ class CommandBar extends Widget {
|
|
|
66
61
|
}
|
|
67
62
|
|
|
68
63
|
namespace CommandBar {
|
|
64
|
+
/**
|
|
65
|
+
* The options used to create a `CommandBar`.
|
|
66
|
+
*/
|
|
69
67
|
export interface IOptions {
|
|
70
68
|
/**
|
|
71
69
|
* Placeholder-style text shown inside the pill.
|
|
@@ -85,15 +83,16 @@ namespace CommandBar {
|
|
|
85
83
|
onActivate: () => void;
|
|
86
84
|
}
|
|
87
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Create the DOM node for a command bar.
|
|
88
|
+
*/
|
|
88
89
|
export function createNode(
|
|
89
90
|
label: string,
|
|
90
91
|
caption: string,
|
|
91
92
|
shortcut?: string
|
|
92
93
|
): HTMLElement {
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
// which would otherwise stretch the pill itself; the button inside keeps
|
|
96
|
-
// its own compact pill height.
|
|
94
|
+
// Plain wrapper: the core `.jp-Toolbar-item` sizing would otherwise
|
|
95
|
+
// stretch the pill itself.
|
|
97
96
|
const wrapper = document.createElement('div');
|
|
98
97
|
|
|
99
98
|
const button = document.createElement('button');
|
|
@@ -118,7 +117,6 @@ namespace CommandBar {
|
|
|
118
117
|
const hint = document.createElement('span');
|
|
119
118
|
hint.className = 'jp-xtralab-CommandBar-shortcut';
|
|
120
119
|
hint.textContent = shortcut;
|
|
121
|
-
// Decorative: the button's aria-label already names the action.
|
|
122
120
|
hint.setAttribute('aria-hidden', 'true');
|
|
123
121
|
button.appendChild(hint);
|
|
124
122
|
}
|
|
@@ -129,19 +127,10 @@ namespace CommandBar {
|
|
|
129
127
|
}
|
|
130
128
|
|
|
131
129
|
/**
|
|
132
|
-
* Contribute a search-bar-styled
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* The pill is a regular settings-driven toolbar item: this plugin registers a
|
|
137
|
-
* widget factory for it on the `IToolbarWidgetRegistry` and declares its rank
|
|
138
|
-
* in schema/command-bar.json, so users can move or disable it from the Top
|
|
139
|
-
* Bar settings like any other toolbar item.
|
|
140
|
-
*
|
|
141
|
-
* The factory is only registered when the omnibox is available — the
|
|
142
|
-
* `IOmnibox` token is provided by `xtralab:omnibox` — so the pill never
|
|
143
|
-
* appears with nothing to open (without a factory, the toolbar item resolves
|
|
144
|
-
* to an empty command button that renders nothing).
|
|
130
|
+
* Contribute a search-bar-styled pill to the top bar toolbar that opens the
|
|
131
|
+
* omnibox. It is a settings-driven toolbar item (factory here, rank in
|
|
132
|
+
* schema/command-bar.json) registered only when `IOmnibox` is provided —
|
|
133
|
+
* without a factory the item resolves to an empty button that renders nothing.
|
|
145
134
|
*/
|
|
146
135
|
const plugin: JupyterFrontEndPlugin<void> = {
|
|
147
136
|
id: PLUGIN_ID,
|
|
@@ -163,10 +152,6 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|
|
163
152
|
const trans = (translator ?? nullTranslator).load('jupyterlab');
|
|
164
153
|
|
|
165
154
|
toolbarRegistry.addFactory(TOPBAR_FACTORY, ITEM_NAME, () => {
|
|
166
|
-
// Show the omnibox's keyboard shortcut as a hint in the pill, derived
|
|
167
|
-
// from the live binding (registered by xtralab:omnibox, which activates
|
|
168
|
-
// first as the IOmnibox provider) so it stays correct and uses the
|
|
169
|
-
// platform's modifier symbols. Empty when no binding is registered.
|
|
170
155
|
const binding = app.commands.keyBindings.find(
|
|
171
156
|
keyBinding => keyBinding.command === OMNIBOX_OPEN_COMMAND
|
|
172
157
|
);
|
package/src/customPanel/index.ts
CHANGED
|
@@ -31,23 +31,38 @@ class CustomPanel extends SidePanel implements IMovableSectionDestination {
|
|
|
31
31
|
this.addClass('jp-xtralab-CustomPanel');
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* The accordion panel hosting the sections.
|
|
36
|
+
*/
|
|
34
37
|
get accordionPanel(): AccordionPanel {
|
|
35
38
|
return this.content as AccordionPanel;
|
|
36
39
|
}
|
|
37
40
|
|
|
41
|
+
/**
|
|
42
|
+
* The section widgets currently hosted by the panel.
|
|
43
|
+
*/
|
|
38
44
|
get sections(): ReadonlyArray<Widget> {
|
|
39
45
|
return this.content.widgets;
|
|
40
46
|
}
|
|
41
47
|
|
|
48
|
+
/**
|
|
49
|
+
* A signal emitted with the new count when the number of sections changes.
|
|
50
|
+
*/
|
|
42
51
|
get sectionCountChanged(): ISignal<this, number> {
|
|
43
52
|
return this._sectionCountChanged;
|
|
44
53
|
}
|
|
45
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Add a section widget to the panel.
|
|
57
|
+
*/
|
|
46
58
|
addSection(widget: Widget): void {
|
|
47
59
|
this.addWidget(widget);
|
|
48
60
|
this._sectionCountChanged.emit(this.content.widgets.length);
|
|
49
61
|
}
|
|
50
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Remove a section widget from the panel, if it is hosted here.
|
|
65
|
+
*/
|
|
51
66
|
removeSectionWidget(widget: Widget): void {
|
|
52
67
|
if (widget.parent !== this.content) {
|
|
53
68
|
return;
|
|
@@ -21,6 +21,10 @@ const PLUGIN_ID = 'xtralab:editor-breadcrumbs';
|
|
|
21
21
|
const EDITOR_FACTORY = 'Editor';
|
|
22
22
|
const TOOLBAR_ITEM_NAME = 'xtralab-editor-breadcrumbs';
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* A widget extension that adds an `EditorBreadcrumbs` item to the toolbar of
|
|
26
|
+
* each new editor widget.
|
|
27
|
+
*/
|
|
24
28
|
class EditorBreadcrumbsExtension implements DocumentRegistry.IWidgetExtension<
|
|
25
29
|
IDocumentWidget<Widget, DocumentRegistry.IModel>,
|
|
26
30
|
DocumentRegistry.IModel
|
|
@@ -30,6 +34,9 @@ class EditorBreadcrumbsExtension implements DocumentRegistry.IWidgetExtension<
|
|
|
30
34
|
this._trans = trans;
|
|
31
35
|
}
|
|
32
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Create the breadcrumbs toolbar item for a new editor widget.
|
|
39
|
+
*/
|
|
33
40
|
createNew(
|
|
34
41
|
widget: IDocumentWidget<Widget, DocumentRegistry.IModel>,
|
|
35
42
|
context: DocumentRegistry.IContext<DocumentRegistry.IModel>
|
|
@@ -56,12 +63,9 @@ class EditorBreadcrumbsExtension implements DocumentRegistry.IWidgetExtension<
|
|
|
56
63
|
}
|
|
57
64
|
|
|
58
65
|
/**
|
|
59
|
-
* Adds a
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* underlying folder or file. The breadcrumbs plugin therefore does not
|
|
63
|
-
* import the file browser at all — the JupyterLab command registry is
|
|
64
|
-
* the only seam between them.
|
|
66
|
+
* Adds a clickable path breadcrumb to text editor toolbars. Clicks dispatch
|
|
67
|
+
* `xtralab:reveal-path`; the command registry is the only seam with the file
|
|
68
|
+
* browser.
|
|
65
69
|
*/
|
|
66
70
|
const plugin: JupyterFrontEndPlugin<void> = {
|
|
67
71
|
id: PLUGIN_ID,
|
|
@@ -15,15 +15,25 @@ const CURRENT_ITEM_CLASS = 'jp-mod-current';
|
|
|
15
15
|
const SEPARATOR_CLASS = 'jp-BreadCrumbs-separator';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
* Registered by the file browser plugin; the breadcrumbs only know
|
|
20
|
-
* the name so they stay decoupled from the file browser internals.
|
|
18
|
+
* Registered by the file browser plugin; only the name is shared here.
|
|
21
19
|
*/
|
|
22
20
|
const REVEAL_COMMAND = 'xtralab:reveal-path';
|
|
23
21
|
|
|
22
|
+
/**
|
|
23
|
+
* The options used to create an `EditorBreadcrumbs` widget.
|
|
24
|
+
*/
|
|
24
25
|
interface IEditorBreadcrumbsOptions {
|
|
26
|
+
/**
|
|
27
|
+
* The document context whose path is rendered.
|
|
28
|
+
*/
|
|
25
29
|
context: DocumentRegistry.IContext<DocumentRegistry.IModel>;
|
|
30
|
+
/**
|
|
31
|
+
* The command registry used to dispatch the reveal command.
|
|
32
|
+
*/
|
|
26
33
|
commands: CommandRegistry;
|
|
34
|
+
/**
|
|
35
|
+
* The application translation bundle.
|
|
36
|
+
*/
|
|
27
37
|
trans: TranslationBundle;
|
|
28
38
|
}
|
|
29
39
|
|
|
@@ -38,9 +48,8 @@ export class EditorBreadcrumbs extends Widget {
|
|
|
38
48
|
this._commands = options.commands;
|
|
39
49
|
this._trans = options.trans;
|
|
40
50
|
this.addClass(EDITOR_BREADCRUMBS_CLASS);
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
// stretched clientWidth they would evict every item into the popup.
|
|
51
|
+
// ReactiveToolbar must count the stretched breadcrumbs as a spacer (2px);
|
|
52
|
+
// measured at clientWidth they would evict every item into the popup.
|
|
44
53
|
this.addClass(TOOLBAR_SPACER_CLASS);
|
|
45
54
|
this.node.setAttribute('aria-label', this._trans.__('Editor file path'));
|
|
46
55
|
|
|
@@ -55,6 +64,9 @@ export class EditorBreadcrumbs extends Widget {
|
|
|
55
64
|
this._render();
|
|
56
65
|
}
|
|
57
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Dispose of the resources held by the widget.
|
|
69
|
+
*/
|
|
58
70
|
dispose(): void {
|
|
59
71
|
if (this.isDisposed) {
|
|
60
72
|
return;
|
|
@@ -81,9 +93,7 @@ export class EditorBreadcrumbs extends Widget {
|
|
|
81
93
|
parts.forEach((part, index) => {
|
|
82
94
|
const isLast = index === parts.length - 1;
|
|
83
95
|
const subPath = parts.slice(0, index + 1).join('/');
|
|
84
|
-
// Canonical
|
|
85
|
-
// slash, files do not. Every part except the last names a folder
|
|
86
|
-
// along the way to the open file.
|
|
96
|
+
// Canonical @pierre/trees paths: directories carry a trailing slash.
|
|
87
97
|
const canonical = isLast ? subPath : `${subPath}/`;
|
|
88
98
|
|
|
89
99
|
const item = document.createElement('span');
|
|
@@ -117,19 +127,15 @@ export class EditorBreadcrumbs extends Widget {
|
|
|
117
127
|
item.dataset.path = '/';
|
|
118
128
|
item.tabIndex = 0;
|
|
119
129
|
item.setAttribute('role', 'button');
|
|
120
|
-
// Empty
|
|
121
|
-
//
|
|
122
|
-
// selection, and scroll back to the top. The tree has no row for
|
|
123
|
-
// the workspace root itself.
|
|
130
|
+
// Empty path is the workspace-root gesture; the tree has no row for
|
|
131
|
+
// the root itself.
|
|
124
132
|
this._attachReveal(item, '');
|
|
125
133
|
return item;
|
|
126
134
|
}
|
|
127
135
|
|
|
128
136
|
/**
|
|
129
|
-
* Bind click and keyboard activation on a crumb
|
|
130
|
-
*
|
|
131
|
-
* resolve or execute the command is logged but never thrown into
|
|
132
|
-
* the editor's toolbar.
|
|
137
|
+
* Bind click and keyboard activation on a crumb to the reveal command;
|
|
138
|
+
* dispatch failures are logged, never thrown into the toolbar.
|
|
133
139
|
*/
|
|
134
140
|
private _attachReveal(element: HTMLElement, canonicalPath: string): void {
|
|
135
141
|
const fire = (event: Event): void => {
|
|
@@ -14,10 +14,8 @@ import detectIndent from 'detect-indent';
|
|
|
14
14
|
const PLUGIN_ID = 'xtralab:editor-indent';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* types not listed here inherit whatever the user has set in JupyterLab.
|
|
20
|
-
* Covers .ts/.tsx/.jsx/.js variants registered by `@jupyterlab/codemirror`.
|
|
17
|
+
* 2-space fallback for new or undetectable files, matching Prettier's
|
|
18
|
+
* web-language defaults; unlisted mime types keep the user's setting.
|
|
21
19
|
*/
|
|
22
20
|
const FALLBACK_INDENT_BY_MIME: Record<string, number> = {
|
|
23
21
|
'application/ecmascript': 2,
|
|
@@ -38,15 +36,20 @@ const FALLBACK_INDENT_BY_MIME: Record<string, number> = {
|
|
|
38
36
|
'text/yaml': 2
|
|
39
37
|
};
|
|
40
38
|
|
|
39
|
+
/**
|
|
40
|
+
* The indentation resolved for a document.
|
|
41
|
+
*/
|
|
41
42
|
interface IResolvedIndent {
|
|
43
|
+
/**
|
|
44
|
+
* The string inserted per indent level (spaces or a tab), for `indentUnit`.
|
|
45
|
+
*/
|
|
42
46
|
unit: string;
|
|
47
|
+
/**
|
|
48
|
+
* The indent width in columns, for `EditorState.tabSize`.
|
|
49
|
+
*/
|
|
43
50
|
width: number;
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
/**
|
|
47
|
-
* Run `detect-indent` against the file's content and convert its result into
|
|
48
|
-
* something we can hand to CodeMirror.
|
|
49
|
-
*/
|
|
50
53
|
function detectFromContent(text: string): IResolvedIndent | null {
|
|
51
54
|
if (text.length === 0) {
|
|
52
55
|
return null;
|
|
@@ -76,9 +79,8 @@ function resolveIndent(text: string, mimeType: string): IResolvedIndent | null {
|
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
function buildExtension(resolved: IResolvedIndent): Extension {
|
|
79
|
-
// `Prec.highest`
|
|
80
|
-
//
|
|
81
|
-
// both of which JupyterLab registers at default precedence.
|
|
82
|
+
// `Prec.highest` beats both `defaultConfig` and per-editor
|
|
83
|
+
// `editorConfig.indentUnit`, which JupyterLab registers at default precedence.
|
|
82
84
|
return Prec.highest([
|
|
83
85
|
indentUnit.of(resolved.unit),
|
|
84
86
|
EditorState.tabSize.of(resolved.width)
|
|
@@ -86,18 +88,10 @@ function buildExtension(resolved: IResolvedIndent): Extension {
|
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
/**
|
|
89
|
-
* Sniff each
|
|
90
|
-
* `
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
* detecting from the file's own content sidesteps that without forcing every
|
|
94
|
-
* project to share the same convention.
|
|
95
|
-
*
|
|
96
|
-
* Detection runs at editor-construction time and again on the first content
|
|
97
|
-
* change — that second pass exists because JupyterLab's collaborative document
|
|
98
|
-
* loader can settle the file body into the shared model after the editor view
|
|
99
|
-
* already exists, in which case the factory would otherwise have only seen an
|
|
100
|
-
* empty string.
|
|
91
|
+
* Sniff each document's indentation and configure CodeMirror's `indentUnit` /
|
|
92
|
+
* `tabSize` to match, since JupyterLab only has one global indent setting.
|
|
93
|
+
* Detection reruns on the first content change: the collaborative loader can
|
|
94
|
+
* settle the file body after the editor view exists, so the factory may see ''.
|
|
101
95
|
*/
|
|
102
96
|
const plugin: JupyterFrontEndPlugin<void> = {
|
|
103
97
|
id: PLUGIN_ID,
|
|
@@ -32,11 +32,9 @@ import { toCanonicalPath, toServerPath } from './contents';
|
|
|
32
32
|
import { FILE_BROWSER_ID, IXtralabFileBrowser } from './widget';
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
* Command
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* via `IFileBrowserFactory.tracker` — our widget is not a `FileBrowser`, so
|
|
39
|
-
* those handlers would never see it.
|
|
35
|
+
* Command ids for the xtralab browser. Namespaced `xtralab:` rather than
|
|
36
|
+
* reusing the `filebrowser:` ids: the core handlers resolve their target via
|
|
37
|
+
* `IFileBrowserFactory.tracker`, which never sees this widget.
|
|
40
38
|
*/
|
|
41
39
|
export namespace CommandIDs {
|
|
42
40
|
export const open = 'xtralab:open';
|
|
@@ -56,27 +54,40 @@ export namespace CommandIDs {
|
|
|
56
54
|
}
|
|
57
55
|
|
|
58
56
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* core's populator does not try to fill ours with items derived from the
|
|
62
|
-
* default file browser's selection.
|
|
57
|
+
* "Open With" submenu id. Distinct from the core `jp-contextmenu-open-with`
|
|
58
|
+
* so the core's populator does not fill ours from its own selection.
|
|
63
59
|
*/
|
|
64
60
|
const OPEN_WITH_SUBMENU_ID = 'jp-contextmenu-xtralab-open-with';
|
|
65
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Options for registering the xtralab file browser commands.
|
|
64
|
+
*/
|
|
66
65
|
interface IRegisterCommandsOptions {
|
|
66
|
+
/**
|
|
67
|
+
* The JupyterLab application the commands are registered on.
|
|
68
|
+
*/
|
|
67
69
|
app: JupyterFrontEnd;
|
|
70
|
+
/**
|
|
71
|
+
* The file browser widget the commands act on.
|
|
72
|
+
*/
|
|
68
73
|
browser: IXtralabFileBrowser;
|
|
74
|
+
/**
|
|
75
|
+
* The document manager used to resolve the current widget's file path.
|
|
76
|
+
*/
|
|
69
77
|
docManager: IDocumentManager;
|
|
78
|
+
/**
|
|
79
|
+
* The command palette the commands are added to, or `null` when unavailable.
|
|
80
|
+
*/
|
|
70
81
|
palette: ICommandPalette | null;
|
|
82
|
+
/**
|
|
83
|
+
* The translator for user-facing strings; `null` falls back to English.
|
|
84
|
+
*/
|
|
71
85
|
translator: ITranslator | null;
|
|
72
86
|
}
|
|
73
87
|
|
|
74
88
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* items match a selector — and fall back to the first item in the tree's
|
|
78
|
-
* selection if the command was invoked without an active contextmenu event
|
|
79
|
-
* (e.g. from the command palette).
|
|
89
|
+
* Path of the right-clicked item, from the contextmenu event's target;
|
|
90
|
+
* falls back to the tree selection when invoked without one (the palette).
|
|
80
91
|
*/
|
|
81
92
|
function getTargetPath(
|
|
82
93
|
app: JupyterFrontEnd,
|
|
@@ -92,11 +103,6 @@ function getTargetPath(
|
|
|
92
103
|
return browser.selectedPaths[0];
|
|
93
104
|
}
|
|
94
105
|
|
|
95
|
-
/**
|
|
96
|
-
* Resolve the kind of the item that was right-clicked, based on the data
|
|
97
|
-
* attributes emitted by `@pierre/trees` rows. Returns `undefined` if no
|
|
98
|
-
* contextmenu event is active or the target is not a tree item.
|
|
99
|
-
*/
|
|
100
106
|
function getTargetKind(app: JupyterFrontEnd): 'file' | 'folder' | undefined {
|
|
101
107
|
const node = app.contextMenuHitTest(
|
|
102
108
|
n => n.dataset !== undefined && n.dataset.type === 'item'
|
|
@@ -106,14 +112,9 @@ function getTargetKind(app: JupyterFrontEnd): 'file' | 'folder' | undefined {
|
|
|
106
112
|
}
|
|
107
113
|
|
|
108
114
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* "Open" on any file in a multi-selection opens them all. If the
|
|
113
|
-
* right-clicked row is *not* in the selection, only that row is opened.
|
|
114
|
-
*
|
|
115
|
-
* Folders are always filtered out: there is no "current directory" in
|
|
116
|
-
* this tree, so opening a folder via "Open" is a no-op.
|
|
115
|
+
* Canonical paths "Open" acts on: the whole selection when the right-clicked
|
|
116
|
+
* row is part of it (matching the default browser), else just that row.
|
|
117
|
+
* Folders are filtered out — this tree has no "current directory".
|
|
117
118
|
*/
|
|
118
119
|
function getOpenPaths(
|
|
119
120
|
app: JupyterFrontEnd,
|
|
@@ -134,9 +135,6 @@ function getOpenPaths(
|
|
|
134
135
|
return candidates.filter(path => !path.endsWith('/'));
|
|
135
136
|
}
|
|
136
137
|
|
|
137
|
-
/**
|
|
138
|
-
* True iff there is an actionable target for a command on the right-click.
|
|
139
|
-
*/
|
|
140
138
|
function hasTarget(
|
|
141
139
|
app: JupyterFrontEnd,
|
|
142
140
|
browser: IXtralabFileBrowser
|
|
@@ -145,11 +143,9 @@ function hasTarget(
|
|
|
145
143
|
}
|
|
146
144
|
|
|
147
145
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
* when the tree has no selection — that matches the contents API's
|
|
152
|
-
* convention for "the root directory".
|
|
146
|
+
* Working directory for create actions: a selected folder is its own cwd, a
|
|
147
|
+
* file falls back to its parent; empty string (the contents-API root) when
|
|
148
|
+
* nothing is selected.
|
|
153
149
|
*/
|
|
154
150
|
function getWorkingDirectory(browser: IXtralabFileBrowser): string {
|
|
155
151
|
const first = browser.selectedPaths[0];
|
|
@@ -164,14 +160,10 @@ function getWorkingDirectory(browser: IXtralabFileBrowser): string {
|
|
|
164
160
|
}
|
|
165
161
|
|
|
166
162
|
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
* Valid only during a context-menu invocation: `contextMenuHitTest` reads the
|
|
173
|
-
* last context-menu event, which is not cleared when the menu closes, so
|
|
174
|
-
* {@link documentPathToReveal} gates this to avoid resolving a stale tab.
|
|
163
|
+
* Main-area widget whose tab is the target of the current context-menu
|
|
164
|
+
* event, or `null`. `contextMenuHitTest` reads the last context-menu event,
|
|
165
|
+
* which is not cleared when the menu closes, so callers must gate against
|
|
166
|
+
* resolving a stale tab.
|
|
175
167
|
*/
|
|
176
168
|
function contextMenuTabWidget(app: JupyterFrontEnd): Widget | null {
|
|
177
169
|
const node = app.contextMenuHitTest(
|
|
@@ -190,10 +182,9 @@ function contextMenuTabWidget(app: JupyterFrontEnd): Widget | null {
|
|
|
190
182
|
}
|
|
191
183
|
|
|
192
184
|
/**
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
* `path` is already canonical. Returns `undefined` when nothing resolves.
|
|
185
|
+
* Canonical path of the document to reveal: the right-clicked tab when
|
|
186
|
+
* `fromContextMenu` is true (the file-tab menu), else the active main-area
|
|
187
|
+
* widget (the palette).
|
|
197
188
|
*/
|
|
198
189
|
function documentPathToReveal(
|
|
199
190
|
app: JupyterFrontEnd,
|
|
@@ -211,14 +202,10 @@ function documentPathToReveal(
|
|
|
211
202
|
}
|
|
212
203
|
|
|
213
204
|
/**
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
* `@jupyterlab/filebrowser-extension:open-with` pattern: the schema declares
|
|
217
|
-
* an empty submenu by id, and we look it up on the open context menu and
|
|
218
|
-
* fill it before the user can hover.
|
|
219
|
-
*
|
|
205
|
+
* Build the populator that fills the "Open With" submenu on every
|
|
206
|
+
* context-menu open, mirroring `filebrowser-extension:open-with`.
|
|
220
207
|
* `preferredWidgetFactories(path)` is path-only, so the populator stays
|
|
221
|
-
* synchronous and the submenu is ready before the user can hover
|
|
208
|
+
* synchronous and the submenu is ready before the user can hover.
|
|
222
209
|
*/
|
|
223
210
|
function makeOpenWithUpdater(
|
|
224
211
|
app: JupyterFrontEnd,
|
|
@@ -259,13 +246,9 @@ function makeOpenWithUpdater(
|
|
|
259
246
|
}
|
|
260
247
|
|
|
261
248
|
/**
|
|
262
|
-
* Register
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
* @returns A function that detaches the menu items and signal listener.
|
|
267
|
-
* The commands themselves are owned by the registry for the lifetime of
|
|
268
|
-
* the plugin.
|
|
249
|
+
* Register the xtralab commands, context-menu wiring, and the dynamic
|
|
250
|
+
* "Open With" populator. Returns a detach function; the commands themselves
|
|
251
|
+
* stay owned by the registry.
|
|
269
252
|
*/
|
|
270
253
|
export function registerCommands(opts: IRegisterCommandsOptions): () => void {
|
|
271
254
|
const { app, browser, docManager, palette, translator } = opts;
|
|
@@ -496,23 +479,16 @@ export function registerCommands(opts: IRegisterCommandsOptions): () => void {
|
|
|
496
479
|
}
|
|
497
480
|
});
|
|
498
481
|
|
|
499
|
-
//
|
|
500
|
-
//
|
|
501
|
-
// the tree focused opens a search session.
|
|
482
|
+
// The filter can also auto-show when typing with the tree focused, so
|
|
483
|
+
// track visibility changes rather than the command's own executions.
|
|
502
484
|
const onFilterVisibleChanged = (): void => {
|
|
503
485
|
commands.notifyCommandChanged(CommandIDs.toggleFileFilter);
|
|
504
486
|
};
|
|
505
487
|
browser.fileFilterVisibleChanged.connect(onFilterVisibleChanged);
|
|
506
488
|
|
|
507
|
-
// Public reveal seam
|
|
508
|
-
//
|
|
509
|
-
//
|
|
510
|
-
// of the contract: the tree is hidden behind a tab and a reveal that
|
|
511
|
-
// does not surface the panel would silently no-op from the user's
|
|
512
|
-
// point of view. An empty path is the "workspace root" gesture —
|
|
513
|
-
// there is no tree row for the root itself, so the browser is asked
|
|
514
|
-
// to scroll back to the top and clear its selection instead.
|
|
515
|
-
// The tree is movable, so surface whichever sidebar widget holds it.
|
|
489
|
+
// Public reveal seam for other plugins; an empty path is the workspace-root
|
|
490
|
+
// gesture (the root has no tree row of its own). The tree is movable, so
|
|
491
|
+
// surface whichever sidebar widget holds it.
|
|
516
492
|
const activateTreeHost = (): void => {
|
|
517
493
|
for (const area of ['left', 'right']) {
|
|
518
494
|
for (const widget of app.shell.widgets(area)) {
|
|
@@ -538,8 +514,6 @@ export function registerCommands(opts: IRegisterCommandsOptions): () => void {
|
|
|
538
514
|
}
|
|
539
515
|
});
|
|
540
516
|
|
|
541
|
-
// Reveal the resolved document in the tree browser via the reveal-path
|
|
542
|
-
// command, which surfaces the sidebar and scrolls to the target.
|
|
543
517
|
commands.addCommand(CommandIDs.revealInFileTree, {
|
|
544
518
|
label: trans.__('Show in File Tree'),
|
|
545
519
|
caption: trans.__('Show this file in the xtralab file browser'),
|
|
@@ -579,10 +553,8 @@ export function registerCommands(opts: IRegisterCommandsOptions): () => void {
|
|
|
579
553
|
commands.addCommand(CommandIDs.newLauncher, {
|
|
580
554
|
label: trans.__('New Launcher'),
|
|
581
555
|
caption: trans.__('Open a new launcher'),
|
|
582
|
-
//
|
|
583
|
-
//
|
|
584
|
-
// styling expects the raw `jp-icon3` paths from `addIcon` so it can
|
|
585
|
-
// recolor them against the brand background.
|
|
556
|
+
// Raw `addIcon`, no `menuItem` bindprops: the launcher-extension's blue
|
|
557
|
+
// toolbar-button styling recolors the raw `jp-icon3` paths.
|
|
586
558
|
icon: addIcon,
|
|
587
559
|
execute: () => {
|
|
588
560
|
const cwd = getWorkingDirectory(browser);
|
|
@@ -590,34 +562,24 @@ export function registerCommands(opts: IRegisterCommandsOptions): () => void {
|
|
|
590
562
|
}
|
|
591
563
|
});
|
|
592
564
|
|
|
593
|
-
// Re-evaluate enabled/visible state when the user changes the tree
|
|
594
|
-
// selection, in case a command's predicate depends on the selection.
|
|
595
565
|
browser.selectionChanged.connect(() => {
|
|
596
566
|
for (const id of Object.values(CommandIDs)) {
|
|
597
567
|
commands.notifyCommandChanged(id);
|
|
598
568
|
}
|
|
599
569
|
});
|
|
600
570
|
|
|
601
|
-
// This command's enabled state tracks the active widget, not the tree
|
|
602
|
-
// selection, so re-evaluate it on current-widget changes. `currentChanged`
|
|
603
|
-
// is optional on the shell interface.
|
|
604
571
|
const onCurrentChanged = (): void => {
|
|
605
572
|
commands.notifyCommandChanged(CommandIDs.revealInFileTree);
|
|
606
573
|
};
|
|
607
574
|
app.shell.currentChanged?.connect(onCurrentChanged);
|
|
608
575
|
|
|
609
|
-
// Also surface it in the palette (acts on the active editor); the file-tab
|
|
610
|
-
// context-menu entry is declared in `schema/plugin.json`.
|
|
611
576
|
const paletteItem = palette?.addItem({
|
|
612
577
|
command: CommandIDs.revealInFileTree,
|
|
613
578
|
category: trans.__('File Browser')
|
|
614
579
|
});
|
|
615
580
|
|
|
616
|
-
//
|
|
617
|
-
//
|
|
618
|
-
// schema also declares an empty submenu placeholder with id
|
|
619
|
-
// `OPEN_WITH_SUBMENU_ID`; we fill it on every open from the document
|
|
620
|
-
// factories that can open the right-clicked file.
|
|
581
|
+
// Static context-menu items live in `schema/plugin.json` so users can
|
|
582
|
+
// override them; the schema declares the empty "Open With" placeholder.
|
|
621
583
|
const updateOpenWithMenu = makeOpenWithUpdater(app, browser);
|
|
622
584
|
app.contextMenu.opened.connect(updateOpenWithMenu);
|
|
623
585
|
|
|
@@ -630,9 +592,8 @@ export function registerCommands(opts: IRegisterCommandsOptions): () => void {
|
|
|
630
592
|
}
|
|
631
593
|
|
|
632
594
|
/**
|
|
633
|
-
*
|
|
634
|
-
*
|
|
635
|
-
* than commands.
|
|
595
|
+
* Toolbar item names, distinct from {@link CommandIDs}: the toolbar API
|
|
596
|
+
* uses opaque names rather than commands.
|
|
636
597
|
*/
|
|
637
598
|
export namespace ToolbarNames {
|
|
638
599
|
export const newLauncher = 'new-launcher';
|
|
@@ -643,10 +604,8 @@ export namespace ToolbarNames {
|
|
|
643
604
|
}
|
|
644
605
|
|
|
645
606
|
/**
|
|
646
|
-
* Populate the
|
|
647
|
-
*
|
|
648
|
-
* button, a refresh button, a collapse-all button, and the file filter
|
|
649
|
-
* toggle.
|
|
607
|
+
* Populate the toolbar with the buttons that mirror the default JupyterLab
|
|
608
|
+
* file browser.
|
|
650
609
|
*/
|
|
651
610
|
export function populateToolbar(opts: {
|
|
652
611
|
app: JupyterFrontEnd;
|