xtralab 0.14.0 → 0.15.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/customPanel/index.d.ts +7 -0
- package/lib/customPanel/index.js +74 -0
- package/lib/fileBrowser/commands.js +13 -1
- package/lib/fileBrowser/contents.d.ts +11 -0
- package/lib/fileBrowser/contents.js +28 -0
- package/lib/fileBrowser/dragAndDrop.d.ts +66 -0
- package/lib/fileBrowser/dragAndDrop.js +115 -0
- package/lib/fileBrowser/fileBrowser.d.ts +2 -0
- package/lib/fileBrowser/fileBrowser.js +151 -197
- package/lib/fileBrowser/index.js +39 -6
- package/lib/fileBrowser/widget.d.ts +44 -5
- package/lib/fileBrowser/widget.js +153 -14
- package/lib/index.js +4 -0
- package/lib/launcher/agents.d.ts +1 -1
- package/lib/launcher/agents.js +15 -2
- package/lib/launcher/icons.js +15 -4
- package/lib/launcher/schemaDefaults.d.ts +2 -9
- package/lib/launcher/schemaDefaults.js +37 -13
- package/lib/menuBar/icons.d.ts +6 -0
- package/lib/menuBar/icons.js +13 -0
- package/lib/menuBar/index.d.ts +15 -0
- package/lib/menuBar/index.js +164 -0
- package/lib/sidebar/index.d.ts +7 -13
- package/lib/sidebar/index.js +80 -46
- package/lib/terminals/index.d.ts +5 -3
- package/lib/terminals/index.js +17 -6
- package/lib/terminals/widget.d.ts +29 -25
- package/lib/terminals/widget.js +150 -65
- package/package.json +1 -1
- package/schema/launcher.json +2 -2
- package/schema/menu-bar.json +37 -0
- package/schema/sidebar.json +47 -7
- package/src/customPanel/index.ts +104 -0
- package/src/fileBrowser/commands.ts +14 -1
- package/src/fileBrowser/contents.ts +30 -0
- package/src/fileBrowser/dragAndDrop.ts +178 -0
- package/src/fileBrowser/fileBrowser.tsx +183 -225
- package/src/fileBrowser/index.ts +41 -6
- package/src/fileBrowser/widget.tsx +195 -14
- package/src/index.ts +4 -0
- package/src/launcher/agents.ts +16 -3
- package/src/launcher/icons.ts +16 -4
- package/src/launcher/schemaDefaults.ts +43 -13
- package/src/menuBar/icons.ts +14 -0
- package/src/menuBar/index.ts +195 -0
- package/src/sidebar/index.ts +95 -52
- package/src/terminals/index.ts +24 -6
- package/src/terminals/widget.tsx +186 -87
- package/style/base.css +22 -34
- package/style/customPanel.css +9 -0
- package/style/index.js +1 -0
- package/style/terminals.css +19 -77
package/src/terminals/widget.tsx
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IMovableSectionDestination,
|
|
3
|
+
IMovableSectionSource,
|
|
4
|
+
ISectionEntry
|
|
5
|
+
} from '@jupyterlab/apputils';
|
|
1
6
|
import {
|
|
2
7
|
type TranslationBundle,
|
|
3
8
|
nullTranslator
|
|
@@ -6,11 +11,16 @@ import {
|
|
|
6
11
|
addIcon,
|
|
7
12
|
closeIcon,
|
|
8
13
|
LabIcon,
|
|
14
|
+
PanelWithToolbar,
|
|
9
15
|
ReactWidget,
|
|
16
|
+
SidePanel,
|
|
10
17
|
stopIcon,
|
|
11
18
|
terminalIcon,
|
|
19
|
+
ToolbarButton,
|
|
12
20
|
UseSignal
|
|
13
21
|
} from '@jupyterlab/ui-components';
|
|
22
|
+
import { ISignal, Signal } from '@lumino/signaling';
|
|
23
|
+
import { AccordionPanel, Widget } from '@lumino/widgets';
|
|
14
24
|
import * as React from 'react';
|
|
15
25
|
|
|
16
26
|
import { SessionRegistry } from './model';
|
|
@@ -22,37 +32,134 @@ import { SessionRegistry } from './model';
|
|
|
22
32
|
const RUNNING_TERMINALS_ID = 'xtralab-running-terminals';
|
|
23
33
|
|
|
24
34
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* launcher *starts* sessions, this panel surfaces the ones already
|
|
28
|
-
* running so the user can jump back to a backgrounded agent — including
|
|
29
|
-
* sessions whose tab has been closed but which are still alive on the
|
|
30
|
-
* server. Each row is labelled with the session's title and, for a session
|
|
31
|
-
* running a coding agent, a smaller line below it showing the agent's latest
|
|
32
|
-
* line of output (from {@link SessionRegistry.activityFor}).
|
|
33
|
-
*
|
|
34
|
-
* Backed by {@link SessionRegistry}: a `UseSignal` re-renders the list
|
|
35
|
-
* whenever the registry emits `stateChanged`, so it tracks
|
|
36
|
-
* `runningChanged` and the agent-title cache without any local state.
|
|
37
|
-
* Click behavior (activate vs. reopen, shutdown, new terminal) is
|
|
38
|
-
* delegated to plugin-supplied callbacks so the widget never imports
|
|
39
|
-
* `app`.
|
|
35
|
+
* Id of the accordion section holding the terminals list. Persisted by the
|
|
36
|
+
* movable-sections plugin, so it must stay stable across releases.
|
|
40
37
|
*/
|
|
41
|
-
|
|
38
|
+
const TERMINALS_SECTION_ID = 'xtralab-terminals-section';
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Left-sidebar panel listing every running terminal session, including the
|
|
42
|
+
* sessions whose tab is closed but which are still alive on the server. The
|
|
43
|
+
* list is a single movable "Terminals" section.
|
|
44
|
+
*/
|
|
45
|
+
export class RunningTerminals
|
|
46
|
+
extends SidePanel
|
|
47
|
+
implements IMovableSectionSource, IMovableSectionDestination
|
|
48
|
+
{
|
|
42
49
|
constructor(options: RunningTerminals.IOptions) {
|
|
43
50
|
super();
|
|
44
51
|
this._registry = options.registry;
|
|
45
|
-
|
|
46
|
-
this._iconForCommand = options.iconForCommand;
|
|
47
|
-
this._onActivate = options.onActivate;
|
|
48
|
-
this._onShutdown = options.onShutdown;
|
|
49
|
-
this._onShutdownAll = options.onShutdownAll;
|
|
50
|
-
this._onCreate = options.onCreate;
|
|
52
|
+
const trans = options.trans ?? nullTranslator.load('jupyterlab');
|
|
51
53
|
|
|
52
54
|
this.id = RUNNING_TERMINALS_ID;
|
|
53
55
|
this.title.icon = terminalIcon;
|
|
54
|
-
this.title.caption =
|
|
56
|
+
this.title.caption = trans.__('Running Terminals');
|
|
55
57
|
this.addClass('jp-xtralab-Terminals');
|
|
58
|
+
|
|
59
|
+
const section = (this._section = new PanelWithToolbar());
|
|
60
|
+
section.id = TERMINALS_SECTION_ID;
|
|
61
|
+
section.title.label = trans.__('Terminals');
|
|
62
|
+
section.addClass('jp-xtralab-Terminals-section');
|
|
63
|
+
|
|
64
|
+
const shutdownAll = new ToolbarButton({
|
|
65
|
+
icon: stopIcon,
|
|
66
|
+
onClick: options.onShutdownAll,
|
|
67
|
+
tooltip: trans.__('Shut Down All Terminals'),
|
|
68
|
+
enabled: this._registry.sessionNames().length > 0
|
|
69
|
+
});
|
|
70
|
+
this._registry.stateChanged.connect(() => {
|
|
71
|
+
shutdownAll.enabled = this._registry.sessionNames().length > 0;
|
|
72
|
+
});
|
|
73
|
+
section.toolbar.addItem('shutdown-all', shutdownAll);
|
|
74
|
+
|
|
75
|
+
const newTerminal = new ToolbarButton({
|
|
76
|
+
icon: addIcon,
|
|
77
|
+
onClick: () => {
|
|
78
|
+
// Anchor whatever the plugin shows (usually an agent menu) to the
|
|
79
|
+
// button's bottom-left, in the viewport coordinates `Menu.open` wants.
|
|
80
|
+
const rect = newTerminal.node.getBoundingClientRect();
|
|
81
|
+
options.onCreate({ x: rect.left, y: rect.bottom });
|
|
82
|
+
},
|
|
83
|
+
tooltip: trans.__('New Terminal')
|
|
84
|
+
});
|
|
85
|
+
section.toolbar.addItem('new-terminal', newTerminal);
|
|
86
|
+
|
|
87
|
+
section.addWidget(
|
|
88
|
+
new TerminalsListing({
|
|
89
|
+
registry: this._registry,
|
|
90
|
+
trans,
|
|
91
|
+
iconForCommand: options.iconForCommand,
|
|
92
|
+
onActivate: options.onActivate,
|
|
93
|
+
onShutdown: options.onShutdown
|
|
94
|
+
})
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
this.addWidget(section);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
get accordionPanel(): AccordionPanel {
|
|
101
|
+
return this.content as AccordionPanel;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
get sectionAdded(): ISignal<this, ISectionEntry> {
|
|
105
|
+
return this._sectionAdded;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
get sections(): ReadonlyArray<Widget> {
|
|
109
|
+
return this.accordionPanel.widgets.filter(w => w !== this._section);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
getSections(): ReadonlyArray<ISectionEntry> {
|
|
113
|
+
const entry = this._sectionEntry();
|
|
114
|
+
return entry ? [entry] : [];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
removeSectionById(sectionId: string): Widget | null {
|
|
118
|
+
if (
|
|
119
|
+
sectionId !== TERMINALS_SECTION_ID ||
|
|
120
|
+
this._section.parent !== this.content
|
|
121
|
+
) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
this._section.parent = null;
|
|
125
|
+
return this._section;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
reinsertSection(widget: Widget): void {
|
|
129
|
+
this.addWidget(widget);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
addSection(widget: Widget): void {
|
|
133
|
+
this.addWidget(widget);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
removeSectionWidget(widget: Widget): void {
|
|
137
|
+
if (widget.parent === this.content) {
|
|
138
|
+
widget.parent = null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The layout restorer stores a section as collapsed whenever its panel is off
|
|
144
|
+
* screen at save time, so it can come back collapsed without the user asking.
|
|
145
|
+
*/
|
|
146
|
+
expandOwnSection(): void {
|
|
147
|
+
const accordion = this.accordionPanel;
|
|
148
|
+
const index = Array.from(accordion.widgets).indexOf(this._section);
|
|
149
|
+
if (index >= 0) {
|
|
150
|
+
accordion.expand(index);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* The move plugin reconciles persisted moves only against sections announced
|
|
156
|
+
* after `registerSource`, and this panel builds its section in the constructor.
|
|
157
|
+
*/
|
|
158
|
+
announceSections(): void {
|
|
159
|
+
const entry = this._sectionEntry();
|
|
160
|
+
if (entry) {
|
|
161
|
+
this._sectionAdded.emit(entry);
|
|
162
|
+
}
|
|
56
163
|
}
|
|
57
164
|
|
|
58
165
|
dispose(): void {
|
|
@@ -65,31 +172,23 @@ export class RunningTerminals extends ReactWidget {
|
|
|
65
172
|
super.dispose();
|
|
66
173
|
}
|
|
67
174
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
/>
|
|
81
|
-
)}
|
|
82
|
-
</UseSignal>
|
|
83
|
-
);
|
|
175
|
+
private _sectionEntry(): ISectionEntry | null {
|
|
176
|
+
const accordion = this.accordionPanel;
|
|
177
|
+
const index = Array.from(accordion.widgets).indexOf(this._section);
|
|
178
|
+
const titleNode = accordion.titles[index] as HTMLElement | undefined;
|
|
179
|
+
if (index < 0 || !titleNode) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
id: TERMINALS_SECTION_ID,
|
|
184
|
+
titleNode,
|
|
185
|
+
widget: this._section
|
|
186
|
+
};
|
|
84
187
|
}
|
|
85
188
|
|
|
86
189
|
private _registry: SessionRegistry;
|
|
87
|
-
private
|
|
88
|
-
private
|
|
89
|
-
private _onActivate: (sessionName: string) => void;
|
|
90
|
-
private _onShutdown: (sessionName: string) => void;
|
|
91
|
-
private _onShutdownAll: () => void;
|
|
92
|
-
private _onCreate: (anchor: { x: number; y: number }) => void;
|
|
190
|
+
private _section: PanelWithToolbar;
|
|
191
|
+
private _sectionAdded = new Signal<this, ISectionEntry>(this);
|
|
93
192
|
}
|
|
94
193
|
|
|
95
194
|
export namespace RunningTerminals {
|
|
@@ -128,24 +227,55 @@ export namespace RunningTerminals {
|
|
|
128
227
|
}
|
|
129
228
|
}
|
|
130
229
|
|
|
230
|
+
/**
|
|
231
|
+
* The body of the Terminals section.
|
|
232
|
+
*/
|
|
233
|
+
class TerminalsListing extends ReactWidget {
|
|
234
|
+
constructor(options: {
|
|
235
|
+
registry: SessionRegistry;
|
|
236
|
+
trans: TranslationBundle;
|
|
237
|
+
iconForCommand: (command: string | null) => LabIcon;
|
|
238
|
+
onActivate: (sessionName: string) => void;
|
|
239
|
+
onShutdown: (sessionName: string) => void;
|
|
240
|
+
}) {
|
|
241
|
+
super();
|
|
242
|
+
this._options = options;
|
|
243
|
+
this.addClass('jp-xtralab-Terminals-listing');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
protected render(): React.ReactElement {
|
|
247
|
+
return (
|
|
248
|
+
<UseSignal signal={this._options.registry.stateChanged}>
|
|
249
|
+
{() => (
|
|
250
|
+
<RunningTerminalsComponent
|
|
251
|
+
registry={this._options.registry}
|
|
252
|
+
trans={this._options.trans}
|
|
253
|
+
iconForCommand={this._options.iconForCommand}
|
|
254
|
+
onActivate={this._options.onActivate}
|
|
255
|
+
onShutdown={this._options.onShutdown}
|
|
256
|
+
/>
|
|
257
|
+
)}
|
|
258
|
+
</UseSignal>
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
private _options: {
|
|
263
|
+
registry: SessionRegistry;
|
|
264
|
+
trans: TranslationBundle;
|
|
265
|
+
iconForCommand: (command: string | null) => LabIcon;
|
|
266
|
+
onActivate: (sessionName: string) => void;
|
|
267
|
+
onShutdown: (sessionName: string) => void;
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
131
271
|
function RunningTerminalsComponent(props: {
|
|
132
272
|
registry: SessionRegistry;
|
|
133
273
|
trans: TranslationBundle;
|
|
134
274
|
iconForCommand: (command: string | null) => LabIcon;
|
|
135
275
|
onActivate: (sessionName: string) => void;
|
|
136
276
|
onShutdown: (sessionName: string) => void;
|
|
137
|
-
onShutdownAll: () => void;
|
|
138
|
-
onCreate: (anchor: { x: number; y: number }) => void;
|
|
139
277
|
}): React.ReactElement {
|
|
140
|
-
const {
|
|
141
|
-
registry,
|
|
142
|
-
trans,
|
|
143
|
-
iconForCommand,
|
|
144
|
-
onActivate,
|
|
145
|
-
onShutdown,
|
|
146
|
-
onShutdownAll,
|
|
147
|
-
onCreate
|
|
148
|
-
} = props;
|
|
278
|
+
const { registry, trans, iconForCommand, onActivate, onShutdown } = props;
|
|
149
279
|
const names = registry.sessionNames();
|
|
150
280
|
// The session whose terminal is the current widget in the main area, so its
|
|
151
281
|
// row can be highlighted. `null` when the current tab is a notebook or any
|
|
@@ -154,37 +284,6 @@ function RunningTerminalsComponent(props: {
|
|
|
154
284
|
|
|
155
285
|
return (
|
|
156
286
|
<div className="jp-xtralab-Terminals-body">
|
|
157
|
-
<div className="jp-xtralab-Terminals-header">
|
|
158
|
-
<h2 className="jp-xtralab-Terminals-title">{trans.__('Terminals')}</h2>
|
|
159
|
-
<div className="jp-xtralab-Terminals-actions">
|
|
160
|
-
<button
|
|
161
|
-
type="button"
|
|
162
|
-
className="jp-xtralab-Terminals-action jp-xtralab-Terminals-shutdown-all"
|
|
163
|
-
onClick={onShutdownAll}
|
|
164
|
-
disabled={names.length === 0}
|
|
165
|
-
title={trans.__('Shut Down All Terminals')}
|
|
166
|
-
aria-label={trans.__('Shut Down All Terminals')}
|
|
167
|
-
>
|
|
168
|
-
<stopIcon.react tag="span" verticalAlign="middle" />
|
|
169
|
-
</button>
|
|
170
|
-
<button
|
|
171
|
-
type="button"
|
|
172
|
-
className="jp-xtralab-Terminals-action jp-xtralab-Terminals-new"
|
|
173
|
-
onClick={event => {
|
|
174
|
-
// Anchor whatever the plugin shows (usually an agent menu) to
|
|
175
|
-
// the button's bottom-left, in viewport coordinates — what
|
|
176
|
-
// `Menu.open(x, y)` expects.
|
|
177
|
-
const rect = event.currentTarget.getBoundingClientRect();
|
|
178
|
-
onCreate({ x: rect.left, y: rect.bottom });
|
|
179
|
-
}}
|
|
180
|
-
title={trans.__('New Terminal')}
|
|
181
|
-
aria-label={trans.__('New Terminal')}
|
|
182
|
-
aria-haspopup="menu"
|
|
183
|
-
>
|
|
184
|
-
<addIcon.react tag="span" verticalAlign="middle" />
|
|
185
|
-
</button>
|
|
186
|
-
</div>
|
|
187
|
-
</div>
|
|
188
287
|
{names.length === 0 ? (
|
|
189
288
|
<p className="jp-xtralab-Terminals-empty">
|
|
190
289
|
{trans.__('No running terminals.')}
|
package/style/base.css
CHANGED
|
@@ -4,10 +4,22 @@
|
|
|
4
4
|
https://jupyterlab.readthedocs.io/en/stable/developer/css.html
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
/*
|
|
8
|
+
* Rules live on the section class below, so they travel when the tree moves.
|
|
9
|
+
*/
|
|
10
|
+
.jp-xtralab-FileBrowserPanel {
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
min-width: 200px;
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
}
|
|
16
|
+
|
|
7
17
|
.jp-xtralab-FileBrowser {
|
|
8
18
|
display: flex;
|
|
19
|
+
flex: 1 1 auto;
|
|
9
20
|
flex-direction: column;
|
|
10
21
|
min-width: 200px;
|
|
22
|
+
min-height: 0;
|
|
11
23
|
overflow: hidden;
|
|
12
24
|
background-color: var(--jp-layout-color1);
|
|
13
25
|
|
|
@@ -129,46 +141,22 @@
|
|
|
129
141
|
min-height: 0;
|
|
130
142
|
}
|
|
131
143
|
|
|
132
|
-
.jp-xtralab-FileBrowser
|
|
144
|
+
.jp-xtralab-FileBrowser-accordion {
|
|
133
145
|
flex: 1 1 auto;
|
|
134
146
|
min-height: 0;
|
|
135
147
|
}
|
|
136
148
|
|
|
137
149
|
/*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* preview without depending on its DOM.
|
|
150
|
+
* In an accordion the toolbar shares the title row, so it must be able to
|
|
151
|
+
* shrink.
|
|
141
152
|
*/
|
|
142
|
-
.jp-xtralab-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
gap: 4px;
|
|
147
|
-
padding: 2px 6px;
|
|
148
|
-
background-color: var(--jp-layout-color1);
|
|
149
|
-
border: 1px solid var(--jp-border-color2);
|
|
150
|
-
border-radius: 6px;
|
|
151
|
-
color: var(--jp-ui-font-color1);
|
|
152
|
-
font-family: var(--jp-ui-font-family);
|
|
153
|
-
font-size: var(--jp-ui-font-size1);
|
|
154
|
-
pointer-events: none;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
.jp-xtralab-DragImage-icon {
|
|
158
|
-
display: inline-flex;
|
|
159
|
-
align-items: center;
|
|
153
|
+
.jp-AccordionPanel-title > .jp-xtralab-FileBrowser-toolbar {
|
|
154
|
+
flex: 0 1 auto;
|
|
155
|
+
min-width: 0;
|
|
156
|
+
overflow: hidden;
|
|
160
157
|
}
|
|
161
158
|
|
|
162
|
-
.jp-xtralab-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
justify-content: center;
|
|
166
|
-
min-width: 16px;
|
|
167
|
-
height: 16px;
|
|
168
|
-
padding: 0 4px;
|
|
169
|
-
background-color: var(--jp-brand-color1);
|
|
170
|
-
border-radius: 8px;
|
|
171
|
-
color: var(--jp-ui-inverse-font-color1);
|
|
172
|
-
font-size: var(--jp-ui-font-size0);
|
|
173
|
-
line-height: 1;
|
|
159
|
+
.jp-xtralab-FileBrowser file-tree-container {
|
|
160
|
+
flex: 1 1 auto;
|
|
161
|
+
min-height: 0;
|
|
174
162
|
}
|
package/style/index.js
CHANGED
package/style/terminals.css
CHANGED
|
@@ -1,93 +1,36 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Left-sidebar panel listing running terminal sessions
|
|
3
|
-
* the session's real (program-published)
|
|
4
|
-
* with the latest output from a running coding
|
|
5
|
-
* shutdown button that fades in on hover
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* theme.
|
|
2
|
+
* Left-sidebar panel listing running terminal sessions, as a single movable
|
|
3
|
+
* "Terminals" section. Each row shows the session's real (program-published)
|
|
4
|
+
* title, a smaller line below it with the latest output from a running coding
|
|
5
|
+
* agent, and an inline shutdown button that fades in on hover. Colors and
|
|
6
|
+
* spacing pull from `--jp-*` custom properties so the panel tracks the active
|
|
7
|
+
* JupyterLab theme.
|
|
9
8
|
*/
|
|
10
9
|
|
|
11
10
|
.jp-xtralab-Terminals {
|
|
12
|
-
display: flex;
|
|
13
|
-
flex-direction: column;
|
|
14
11
|
min-width: 200px;
|
|
15
12
|
overflow: hidden;
|
|
16
|
-
background-color: var(--jp-layout-color1);
|
|
17
|
-
color: var(--jp-ui-font-color1);
|
|
18
|
-
font-size: var(--jp-ui-font-size1);
|
|
19
13
|
}
|
|
20
14
|
|
|
21
|
-
.
|
|
15
|
+
/* On the section, not the panel, so the rules travel when the section moves. */
|
|
16
|
+
.jp-xtralab-Terminals-section {
|
|
22
17
|
display: flex;
|
|
23
|
-
flex: 1 1 auto;
|
|
24
18
|
flex-direction: column;
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
.jp-xtralab-Terminals-header {
|
|
29
|
-
display: flex;
|
|
30
|
-
flex: 0 0 auto;
|
|
31
|
-
align-items: center;
|
|
32
|
-
justify-content: space-between;
|
|
33
|
-
padding: 8px 12px;
|
|
34
|
-
border-bottom: var(--jp-border-width) solid var(--jp-border-color2);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.jp-xtralab-Terminals-title {
|
|
38
|
-
margin: 0;
|
|
39
|
-
font-size: var(--jp-ui-font-size0);
|
|
40
|
-
font-weight: 600;
|
|
41
|
-
letter-spacing: 1px;
|
|
42
|
-
text-transform: uppercase;
|
|
43
|
-
color: var(--jp-ui-font-color1);
|
|
19
|
+
overflow: hidden;
|
|
44
20
|
}
|
|
45
21
|
|
|
46
|
-
.jp-xtralab-Terminals-
|
|
22
|
+
.jp-xtralab-Terminals-listing {
|
|
47
23
|
display: flex;
|
|
48
|
-
flex:
|
|
49
|
-
|
|
50
|
-
|
|
24
|
+
flex: 1 1 auto;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
min-height: 0;
|
|
51
27
|
}
|
|
52
28
|
|
|
53
|
-
.jp-xtralab-Terminals-
|
|
29
|
+
.jp-xtralab-Terminals-body {
|
|
54
30
|
display: flex;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
height: 20px;
|
|
59
|
-
padding: 0;
|
|
60
|
-
background: transparent;
|
|
61
|
-
border: none;
|
|
62
|
-
border-radius: 2px;
|
|
63
|
-
color: var(--jp-ui-font-color2);
|
|
64
|
-
cursor: pointer;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.jp-xtralab-Terminals-action:hover {
|
|
68
|
-
background-color: var(--jp-layout-color2);
|
|
69
|
-
color: var(--jp-ui-font-color1);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.jp-xtralab-Terminals-action:focus-visible {
|
|
73
|
-
outline: var(--jp-border-width) solid var(--jp-brand-color1);
|
|
74
|
-
outline-offset: -1px;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/*
|
|
78
|
-
* "Shut down all" is disabled when there are no running terminals. Dim the
|
|
79
|
-
* whole control with opacity rather than `color`: the stop glyph is an SVG
|
|
80
|
-
* whose fill comes from its own `jp-icon3` class (not `currentColor`), so a
|
|
81
|
-
* `color` change alone leaves the icon looking fully active — which is why the
|
|
82
|
-
* button did not read as disabled.
|
|
83
|
-
*/
|
|
84
|
-
.jp-xtralab-Terminals-action:disabled {
|
|
85
|
-
cursor: default;
|
|
86
|
-
opacity: 0.4;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.jp-xtralab-Terminals-action:disabled:hover {
|
|
90
|
-
background: transparent;
|
|
31
|
+
flex: 1 1 auto;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
min-height: 0;
|
|
91
34
|
}
|
|
92
35
|
|
|
93
36
|
.jp-xtralab-Terminals-empty {
|
|
@@ -214,9 +157,8 @@
|
|
|
214
157
|
opacity: 1;
|
|
215
158
|
}
|
|
216
159
|
|
|
217
|
-
/* Keep the row
|
|
218
|
-
.jp-xtralab-Terminals-item svg
|
|
219
|
-
.jp-xtralab-Terminals-action svg {
|
|
160
|
+
/* Keep the row icons at the standard 16px sidebar size. */
|
|
161
|
+
.jp-xtralab-Terminals-item svg {
|
|
220
162
|
width: 16px;
|
|
221
163
|
height: 16px;
|
|
222
164
|
}
|