xtralab 0.10.0 → 0.11.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 +27 -11
- package/lib/commandBar/index.d.ts +14 -0
- package/lib/commandBar/index.js +114 -0
- package/lib/fileBrowser/fileBrowser.js +6 -1
- package/lib/highlight/index.d.ts +15 -0
- package/lib/highlight/index.js +214 -0
- package/lib/index.js +13 -1
- package/lib/launcher/agents.d.ts +18 -1
- package/lib/launcher/agents.js +47 -4
- package/lib/launcher/editorRegistry.js +5 -3
- package/lib/launcher/editors.d.ts +17 -2
- package/lib/launcher/editors.js +31 -5
- package/lib/launcher/index.js +7 -1
- package/lib/launcher/schemaDefaults.d.ts +15 -0
- package/lib/launcher/schemaDefaults.js +44 -0
- package/lib/omnibox/files.d.ts +7 -0
- package/lib/omnibox/files.js +50 -0
- package/lib/omnibox/index.d.ts +14 -0
- package/lib/omnibox/index.js +83 -0
- package/lib/omnibox/model.d.ts +45 -0
- package/lib/omnibox/model.js +142 -0
- package/lib/omnibox/tokens.d.ts +23 -0
- package/lib/omnibox/tokens.js +11 -0
- package/lib/omnibox/widget.d.ts +36 -0
- package/lib/omnibox/widget.js +161 -0
- package/lib/searchReplace/index.d.ts +25 -0
- package/lib/searchReplace/index.js +68 -0
- package/lib/showOutput/index.d.ts +17 -0
- package/lib/showOutput/index.js +154 -0
- package/lib/terminals/index.d.ts +4 -0
- package/lib/terminals/index.js +65 -16
- package/lib/terminals/model.d.ts +56 -3
- package/lib/terminals/model.js +261 -5
- package/lib/terminals/widget.d.ts +3 -1
- package/lib/terminals/widget.js +11 -3
- package/lib/walkthrough/index.d.ts +14 -0
- package/lib/walkthrough/index.js +162 -0
- package/lib/walkthrough/panel.d.ts +54 -0
- package/lib/walkthrough/panel.js +98 -0
- package/package.json +1 -1
- package/schema/launcher.json +5 -4
- package/schema/terminals.json +15 -0
- package/src/commandBar/index.ts +165 -0
- package/src/fileBrowser/fileBrowser.tsx +8 -1
- package/src/highlight/index.ts +251 -0
- package/src/index.ts +13 -1
- package/src/launcher/agents.ts +53 -3
- package/src/launcher/editorRegistry.ts +8 -4
- package/src/launcher/editors.ts +37 -4
- package/src/launcher/index.ts +7 -1
- package/src/launcher/schemaDefaults.ts +53 -0
- package/src/omnibox/files.ts +68 -0
- package/src/omnibox/index.ts +105 -0
- package/src/omnibox/model.ts +210 -0
- package/src/omnibox/tokens.ts +29 -0
- package/src/omnibox/widget.tsx +322 -0
- package/src/searchReplace/index.ts +86 -0
- package/src/showOutput/index.ts +199 -0
- package/src/terminals/index.ts +79 -16
- package/src/terminals/model.ts +304 -3
- package/src/terminals/widget.tsx +21 -4
- package/src/walkthrough/index.ts +202 -0
- package/src/walkthrough/panel.ts +152 -0
- package/style/commandBar.css +104 -0
- package/style/highlight.css +11 -0
- package/style/index.css +5 -0
- package/style/index.js +5 -0
- package/style/omnibox.css +120 -0
- package/style/showOutput.css +11 -0
- package/style/terminals.css +54 -10
- package/style/walkthrough.css +80 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
2
|
+
import type { TranslationBundle } from '@jupyterlab/translation';
|
|
3
|
+
import { fileIcon } from '@jupyterlab/ui-components';
|
|
4
|
+
import type { CommandRegistry } from '@lumino/commands';
|
|
5
|
+
import type { ReadonlyPartialJSONValue } from '@lumino/coreutils';
|
|
6
|
+
import type { Message } from '@lumino/messaging';
|
|
7
|
+
import { Panel, Widget } from '@lumino/widgets';
|
|
8
|
+
|
|
9
|
+
/** Command the jump links dispatch; keeps the panel decoupled from the plugin. */
|
|
10
|
+
const HIGHLIGHT_LINES_COMMAND = 'xtralab:highlight-lines';
|
|
11
|
+
|
|
12
|
+
/** A rich visual embedded in a step (rendered through the rendermime registry). */
|
|
13
|
+
export interface IWalkthroughMedia {
|
|
14
|
+
mimeType: string;
|
|
15
|
+
data: ReadonlyPartialJSONValue;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** One step of a walkthrough. Every field is optional, but a step needs at least one. */
|
|
19
|
+
export interface IWalkthroughStep {
|
|
20
|
+
title?: string;
|
|
21
|
+
body?: string;
|
|
22
|
+
media?: IWalkthroughMedia;
|
|
23
|
+
path?: string;
|
|
24
|
+
line?: number;
|
|
25
|
+
endLine?: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export namespace WalkthroughPanel {
|
|
29
|
+
export interface IOptions {
|
|
30
|
+
rendermime: IRenderMimeRegistry;
|
|
31
|
+
commands: CommandRegistry;
|
|
32
|
+
trans: TranslationBundle;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A read-only, scrollable column of walkthrough steps for the side area.
|
|
38
|
+
*
|
|
39
|
+
* The agent appends steps as it narrates, so the explanation lives beside the
|
|
40
|
+
* code the user is looking at and persists for them to read at their own pace,
|
|
41
|
+
* rather than scrolling away in the chat. Each step renders Markdown (with code
|
|
42
|
+
* snippets, Mermaid, math), can embed a rich visual, and can offer a button
|
|
43
|
+
* that opens the referenced file and highlights its lines.
|
|
44
|
+
*/
|
|
45
|
+
export class WalkthroughPanel extends Panel {
|
|
46
|
+
constructor(options: WalkthroughPanel.IOptions) {
|
|
47
|
+
super();
|
|
48
|
+
this._rendermime = options.rendermime;
|
|
49
|
+
this._commands = options.commands;
|
|
50
|
+
this._trans = options.trans;
|
|
51
|
+
this.addClass('jp-xtralab-Walkthrough');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Remove every step, leaving an empty panel. */
|
|
55
|
+
clear(): void {
|
|
56
|
+
while (this.widgets.length > 0) {
|
|
57
|
+
this.widgets[0].dispose();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Dispose on close (e.g. the close button when the panel has been dragged to
|
|
63
|
+
* the main area) rather than leaving a detached, reusable widget behind. The
|
|
64
|
+
* next `xtralab:walkthrough` call recreates the panel in the side area.
|
|
65
|
+
*/
|
|
66
|
+
protected onCloseRequest(msg: Message): void {
|
|
67
|
+
super.onCloseRequest(msg);
|
|
68
|
+
this.dispose();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Append a step and scroll it into view. */
|
|
72
|
+
async addStep(step: IWalkthroughStep): Promise<void> {
|
|
73
|
+
const card = new Panel();
|
|
74
|
+
card.addClass('jp-xtralab-Walkthrough-step');
|
|
75
|
+
this.addWidget(card);
|
|
76
|
+
|
|
77
|
+
if (step.title) {
|
|
78
|
+
const heading = new Widget({ node: document.createElement('h3') });
|
|
79
|
+
heading.addClass('jp-xtralab-Walkthrough-stepTitle');
|
|
80
|
+
heading.node.textContent = step.title;
|
|
81
|
+
card.addWidget(heading);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (step.body) {
|
|
85
|
+
await this._render(card, 'text/markdown', step.body);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (step.media && typeof step.media.mimeType === 'string') {
|
|
89
|
+
await this._render(card, step.media.mimeType, step.media.data);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (step.path) {
|
|
93
|
+
card.addWidget(this._jumpButton(step.path, step.line, step.endLine));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Bring the newest step into view.
|
|
97
|
+
this.node.scrollTop = this.node.scrollHeight;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private async _render(
|
|
101
|
+
parent: Panel,
|
|
102
|
+
mimeType: string,
|
|
103
|
+
data: ReadonlyPartialJSONValue
|
|
104
|
+
): Promise<void> {
|
|
105
|
+
const bundle = { [mimeType]: data };
|
|
106
|
+
const chosen = this._rendermime.preferredMimeType(bundle, 'any');
|
|
107
|
+
if (!chosen) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const renderer = this._rendermime.createRenderer(chosen);
|
|
111
|
+
renderer.addClass('jp-xtralab-Walkthrough-content');
|
|
112
|
+
parent.addWidget(renderer);
|
|
113
|
+
await renderer.renderModel(
|
|
114
|
+
this._rendermime.createModel({ data: bundle, trusted: true })
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private _jumpButton(path: string, line?: number, endLine?: number): Widget {
|
|
119
|
+
const node = document.createElement('div');
|
|
120
|
+
node.className = 'jp-xtralab-Walkthrough-jumpRow';
|
|
121
|
+
const where = line ? `${path}:${line}` : path;
|
|
122
|
+
|
|
123
|
+
const button = document.createElement('button');
|
|
124
|
+
button.type = 'button';
|
|
125
|
+
button.className = 'jp-xtralab-Walkthrough-jump';
|
|
126
|
+
button.title = this._trans.__('Open %1 in the editor', where);
|
|
127
|
+
|
|
128
|
+
const icon = fileIcon.element({
|
|
129
|
+
tag: 'span',
|
|
130
|
+
className: 'jp-xtralab-Walkthrough-jumpIcon'
|
|
131
|
+
});
|
|
132
|
+
const label = document.createElement('span');
|
|
133
|
+
label.className = 'jp-xtralab-Walkthrough-jumpLabel';
|
|
134
|
+
label.textContent = where;
|
|
135
|
+
button.appendChild(icon);
|
|
136
|
+
button.appendChild(label);
|
|
137
|
+
node.appendChild(button);
|
|
138
|
+
|
|
139
|
+
button.addEventListener('click', () => {
|
|
140
|
+
void this._commands.execute(HIGHLIGHT_LINES_COMMAND, {
|
|
141
|
+
path,
|
|
142
|
+
line,
|
|
143
|
+
endLine
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
return new Widget({ node });
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private _rendermime: IRenderMimeRegistry;
|
|
150
|
+
private _commands: CommandRegistry;
|
|
151
|
+
private _trans: TranslationBundle;
|
|
152
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/* Centered command bar in the top area (xtralab:command-bar). */
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* The bar is an overlay centered over the whole top panel rather than a flex
|
|
5
|
+
* item, so its position does not shift with the (variable) width of the menu
|
|
6
|
+
* bar on its left or the sidebar toggle button on its right. `#jp-top-panel`
|
|
7
|
+
* is a `.lm-Widget`, which Lumino renders `position: relative`, so this
|
|
8
|
+
* absolute box is centered against the full width of the top bar.
|
|
9
|
+
*
|
|
10
|
+
* `pointer-events: none` here (with `auto` restored on the pill below) keeps
|
|
11
|
+
* only the pill clickable: the transparent strips above and below it let
|
|
12
|
+
* clicks fall through to whatever sits beneath the overlay.
|
|
13
|
+
*
|
|
14
|
+
* The `z-index` must clear JupyterLab core's settings-driven "Topbar toolbar"
|
|
15
|
+
* (`#jp-top-bar`, added to the top area at rank 900), which is a `.jp-Toolbar`
|
|
16
|
+
* at `z-index: 8` that grows to fill the center and paints an opaque
|
|
17
|
+
* `--jp-toolbar-background`. Sitting one above it lets the centered pill show
|
|
18
|
+
* through; that toolbar is empty by default, so the overlay covers blank
|
|
19
|
+
* space rather than hiding any toolbar items.
|
|
20
|
+
*/
|
|
21
|
+
.jp-xtralab-CommandBar {
|
|
22
|
+
position: absolute;
|
|
23
|
+
top: 0;
|
|
24
|
+
bottom: 0;
|
|
25
|
+
left: 50%;
|
|
26
|
+
z-index: 9;
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
transform: translateX(-50%);
|
|
30
|
+
pointer-events: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.jp-xtralab-CommandBar-button {
|
|
34
|
+
display: flex;
|
|
35
|
+
flex: 0 0 auto;
|
|
36
|
+
gap: 6px;
|
|
37
|
+
align-items: center;
|
|
38
|
+
width: clamp(160px, 16vw, 220px);
|
|
39
|
+
height: 20px;
|
|
40
|
+
padding: 0 8px;
|
|
41
|
+
margin: 0;
|
|
42
|
+
overflow: hidden;
|
|
43
|
+
font-family: var(--jp-ui-font-family);
|
|
44
|
+
font-size: var(--jp-ui-font-size1);
|
|
45
|
+
color: var(--jp-ui-font-color2);
|
|
46
|
+
text-align: left;
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
|
|
49
|
+
/* The theme's input-field fill, so the pill reads as a search box and tracks
|
|
50
|
+
each theme's input styling across light and dark (a flat layout color is
|
|
51
|
+
near-black in some dark themes). */
|
|
52
|
+
background: var(--jp-input-background);
|
|
53
|
+
border: var(--jp-border-width) solid var(--jp-border-color1);
|
|
54
|
+
border-radius: 10px;
|
|
55
|
+
appearance: none;
|
|
56
|
+
pointer-events: auto;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.jp-xtralab-CommandBar-button:hover {
|
|
60
|
+
color: var(--jp-ui-font-color1);
|
|
61
|
+
border-color: var(--jp-border-color0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.jp-xtralab-CommandBar-button:focus-visible {
|
|
65
|
+
outline: var(--jp-border-width) solid var(--jp-brand-color1);
|
|
66
|
+
outline-offset: 1px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.jp-xtralab-CommandBar-icon {
|
|
70
|
+
display: flex;
|
|
71
|
+
flex: 0 0 auto;
|
|
72
|
+
align-items: center;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.jp-xtralab-CommandBar-icon svg {
|
|
76
|
+
width: 14px;
|
|
77
|
+
height: 14px;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* The built-in JupyterLab search icon (@jupyterlab/ui-components) paints with a
|
|
81
|
+
fixed `jp-icon3` theme gray; override it to currentColor so the magnifier
|
|
82
|
+
tracks the pill's text color and brightens with the label on hover. */
|
|
83
|
+
.jp-xtralab-CommandBar-button .jp-icon3[fill] {
|
|
84
|
+
fill: currentcolor;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.jp-xtralab-CommandBar-label {
|
|
88
|
+
flex: 1 1 auto;
|
|
89
|
+
overflow: hidden;
|
|
90
|
+
text-overflow: ellipsis;
|
|
91
|
+
white-space: nowrap;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Keyboard-shortcut hint, pushed to the trailing edge by the growing label. */
|
|
95
|
+
.jp-xtralab-CommandBar-shortcut {
|
|
96
|
+
flex: 0 0 auto;
|
|
97
|
+
margin-left: 6px;
|
|
98
|
+
padding: 1px 4px;
|
|
99
|
+
font-size: var(--jp-ui-font-size0);
|
|
100
|
+
line-height: 1.2;
|
|
101
|
+
color: var(--jp-ui-font-color3);
|
|
102
|
+
border: var(--jp-border-width) solid var(--jp-border-color1);
|
|
103
|
+
border-radius: 4px;
|
|
104
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Line highlight applied by `xtralab:highlight-lines`. The class lands on the
|
|
3
|
+
* CodeMirror line wrapper (`.cm-line`), so the tint spans the full editor width
|
|
4
|
+
* and a left accent bar marks the run. The translucent background keeps the
|
|
5
|
+
* code legible on both light and dark themes.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
.jp-xtralab-highlightLine {
|
|
9
|
+
background-color: rgb(250 204 21 / 18%);
|
|
10
|
+
box-shadow: inset 2px 0 0 0 var(--jp-brand-color1);
|
|
11
|
+
}
|
package/style/index.css
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
@import url('base.css');
|
|
2
|
+
@import url('commandBar.css');
|
|
2
3
|
@import url('editorBreadcrumbs.css');
|
|
3
4
|
@import url('git.css');
|
|
5
|
+
@import url('highlight.css');
|
|
4
6
|
@import url('launcher.css');
|
|
7
|
+
@import url('omnibox.css');
|
|
8
|
+
@import url('showOutput.css');
|
|
5
9
|
@import url('sidebar.css');
|
|
6
10
|
@import url('tabs.css');
|
|
7
11
|
@import url('terminals.css');
|
|
8
12
|
@import url('topBar.css');
|
|
13
|
+
@import url('walkthrough.css');
|
package/style/index.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import './base.css';
|
|
2
|
+
import './commandBar.css';
|
|
2
3
|
import './git.css';
|
|
4
|
+
import './highlight.css';
|
|
3
5
|
import './launcher.css';
|
|
6
|
+
import './omnibox.css';
|
|
7
|
+
import './showOutput.css';
|
|
4
8
|
import './sidebar.css';
|
|
5
9
|
import './tabs.css';
|
|
6
10
|
import './terminals.css';
|
|
7
11
|
import './topBar.css';
|
|
12
|
+
import './walkthrough.css';
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/* Omnibox overlay (xtralab:omnibox): a centered search box over the shell. */
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* The widget node is attached to `document.body` (outside the shell) and only
|
|
5
|
+
* carries theme variables via `jp-ThemedContainer`; the React tree renders the
|
|
6
|
+
* fixed full-screen overlay below it.
|
|
7
|
+
*/
|
|
8
|
+
.jp-xtralab-Omnibox {
|
|
9
|
+
position: absolute;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* Transparent full-viewport layer that centers the panel and catches
|
|
13
|
+
click-outside to dismiss. */
|
|
14
|
+
.jp-xtralab-Omnibox-overlay {
|
|
15
|
+
position: fixed;
|
|
16
|
+
inset: 0;
|
|
17
|
+
z-index: 10001;
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: flex-start;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.jp-xtralab-Omnibox-panel {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
width: min(640px, 92vw);
|
|
27
|
+
max-height: 60vh;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
|
|
30
|
+
/* Drop just below the top bar so it reads as a command-center dropdown. */
|
|
31
|
+
margin-top: calc(var(--jp-private-menubar-height, 28px) + 4px);
|
|
32
|
+
background: var(--jp-layout-color1);
|
|
33
|
+
border: var(--jp-border-width) solid var(--jp-border-color1);
|
|
34
|
+
border-radius: 4px;
|
|
35
|
+
box-shadow: var(--jp-elevation-z6);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.jp-xtralab-Omnibox-input {
|
|
39
|
+
padding: 11px 14px;
|
|
40
|
+
font-family: var(--jp-ui-font-family);
|
|
41
|
+
font-size: var(--jp-ui-font-size2);
|
|
42
|
+
color: var(--jp-ui-font-color0);
|
|
43
|
+
background: transparent;
|
|
44
|
+
border: none;
|
|
45
|
+
border-bottom: var(--jp-border-width) solid var(--jp-border-color2);
|
|
46
|
+
outline: none;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.jp-xtralab-Omnibox-input::placeholder {
|
|
50
|
+
color: var(--jp-ui-font-color3);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.jp-xtralab-Omnibox-results {
|
|
54
|
+
padding: 4px 0;
|
|
55
|
+
overflow-y: auto;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.jp-xtralab-Omnibox-sectionHeader {
|
|
59
|
+
padding: 6px 14px 2px;
|
|
60
|
+
font-size: var(--jp-ui-font-size0);
|
|
61
|
+
font-weight: 600;
|
|
62
|
+
color: var(--jp-ui-font-color2);
|
|
63
|
+
text-transform: uppercase;
|
|
64
|
+
letter-spacing: 0.04em;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.jp-xtralab-Omnibox-item {
|
|
68
|
+
display: flex;
|
|
69
|
+
gap: 8px;
|
|
70
|
+
align-items: center;
|
|
71
|
+
padding: 5px 14px;
|
|
72
|
+
font-size: var(--jp-ui-font-size1);
|
|
73
|
+
color: var(--jp-ui-font-color1);
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.jp-xtralab-Omnibox-item.jp-mod-active {
|
|
78
|
+
background: var(--jp-layout-color2);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.jp-xtralab-Omnibox-itemIcon {
|
|
82
|
+
display: flex;
|
|
83
|
+
flex: 0 0 auto;
|
|
84
|
+
align-items: center;
|
|
85
|
+
width: 16px;
|
|
86
|
+
height: 16px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.jp-xtralab-Omnibox-itemIcon svg {
|
|
90
|
+
width: 16px;
|
|
91
|
+
height: 16px;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.jp-xtralab-Omnibox-itemLabel {
|
|
95
|
+
flex: 1 1 auto;
|
|
96
|
+
overflow: hidden;
|
|
97
|
+
white-space: nowrap;
|
|
98
|
+
text-overflow: ellipsis;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.jp-xtralab-Omnibox-match {
|
|
102
|
+
font-weight: 600;
|
|
103
|
+
color: var(--jp-ui-font-color0);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.jp-xtralab-Omnibox-itemCaption {
|
|
107
|
+
flex: 0 1 auto;
|
|
108
|
+
max-width: 45%;
|
|
109
|
+
overflow: hidden;
|
|
110
|
+
font-size: var(--jp-ui-font-size0);
|
|
111
|
+
color: var(--jp-ui-font-color3);
|
|
112
|
+
white-space: nowrap;
|
|
113
|
+
text-overflow: ellipsis;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.jp-xtralab-Omnibox-empty {
|
|
117
|
+
padding: 14px;
|
|
118
|
+
font-size: var(--jp-ui-font-size1);
|
|
119
|
+
color: var(--jp-ui-font-color2);
|
|
120
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The panel `xtralab:show` renders into. It holds a single rendered output and
|
|
3
|
+
* scrolls when that output is taller (or wider) than the panel, which matters
|
|
4
|
+
* most in the narrow side area.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.jp-xtralab-ShowPanel {
|
|
8
|
+
overflow: auto;
|
|
9
|
+
padding: 8px;
|
|
10
|
+
background: var(--jp-layout-color1);
|
|
11
|
+
}
|
package/style/terminals.css
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Left-sidebar panel listing running terminal sessions. Each row shows
|
|
3
|
-
* the session's real (program-published) title
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* the session's real (program-published) title, a smaller line below it
|
|
4
|
+
* with the latest output from a running coding agent, and an inline
|
|
5
|
+
* shutdown button that fades in on hover; the header carries the panel
|
|
6
|
+
* title and a "new terminal" button. Colors and spacing pull from
|
|
7
|
+
* `--jp-*` custom properties so the panel tracks the active JupyterLab
|
|
8
|
+
* theme.
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
11
|
.jp-xtralab-Terminals {
|
|
@@ -105,7 +107,7 @@
|
|
|
105
107
|
.jp-xtralab-Terminals-item {
|
|
106
108
|
display: flex;
|
|
107
109
|
align-items: stretch;
|
|
108
|
-
height: 28px;
|
|
110
|
+
min-height: 28px;
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
.jp-xtralab-Terminals-item:hover {
|
|
@@ -113,17 +115,19 @@
|
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
/*
|
|
116
|
-
* The main click target: terminal icon +
|
|
117
|
-
* whole strip activates the session. The close button
|
|
118
|
-
* and intercepts its own clicks via the React handler.
|
|
118
|
+
* The main click target: terminal icon + the title/activity text block,
|
|
119
|
+
* filling the row so the whole strip activates the session. The close button
|
|
120
|
+
* sits to its right and intercepts its own clicks via the React handler.
|
|
121
|
+
* Top-aligned so the icon sits on the title line when an activity line wraps
|
|
122
|
+
* the row to a second line.
|
|
119
123
|
*/
|
|
120
124
|
.jp-xtralab-Terminals-item-activate {
|
|
121
125
|
display: flex;
|
|
122
126
|
flex: 1 1 auto;
|
|
123
|
-
align-items:
|
|
127
|
+
align-items: flex-start;
|
|
124
128
|
gap: 6px;
|
|
125
129
|
min-width: 0;
|
|
126
|
-
padding:
|
|
130
|
+
padding: 5px 4px 5px 12px;
|
|
127
131
|
background: transparent;
|
|
128
132
|
border: none;
|
|
129
133
|
color: inherit;
|
|
@@ -137,12 +141,44 @@
|
|
|
137
141
|
outline-offset: -2px;
|
|
138
142
|
}
|
|
139
143
|
|
|
144
|
+
/* Nudge the 16px icon down a touch so it lines up with the title's cap
|
|
145
|
+
* height rather than the very top of the text block. */
|
|
146
|
+
.jp-xtralab-Terminals-item-icon {
|
|
147
|
+
margin-top: 1px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* The title + activity column, between the icon and the close button. */
|
|
151
|
+
.jp-xtralab-Terminals-item-text {
|
|
152
|
+
display: flex;
|
|
153
|
+
flex: 1 1 auto;
|
|
154
|
+
flex-direction: column;
|
|
155
|
+
gap: 1px;
|
|
156
|
+
min-width: 0;
|
|
157
|
+
}
|
|
158
|
+
|
|
140
159
|
.jp-xtralab-Terminals-item-label {
|
|
141
160
|
overflow: hidden;
|
|
142
161
|
text-overflow: ellipsis;
|
|
143
162
|
white-space: nowrap;
|
|
144
163
|
}
|
|
145
164
|
|
|
165
|
+
/*
|
|
166
|
+
* The latest line of agent output, shown under the title. Smaller and dimmer
|
|
167
|
+
* than the title so it reads as secondary, and clamped to two lines with an
|
|
168
|
+
* ellipsis so a long line can't stretch the row indefinitely.
|
|
169
|
+
*/
|
|
170
|
+
.jp-xtralab-Terminals-item-detail {
|
|
171
|
+
display: -webkit-box;
|
|
172
|
+
overflow: hidden;
|
|
173
|
+
font-size: var(--jp-ui-font-size0);
|
|
174
|
+
line-height: 1.3;
|
|
175
|
+
color: var(--jp-ui-font-color3);
|
|
176
|
+
text-overflow: ellipsis;
|
|
177
|
+
overflow-wrap: anywhere;
|
|
178
|
+
-webkit-line-clamp: 2;
|
|
179
|
+
-webkit-box-orient: vertical;
|
|
180
|
+
}
|
|
181
|
+
|
|
146
182
|
/*
|
|
147
183
|
* Close button. Hidden by default so the row reads as plain text; fades
|
|
148
184
|
* in when the row is hovered or the button itself takes focus.
|
|
@@ -205,6 +241,14 @@
|
|
|
205
241
|
background-color: var(--jp-brand-color1);
|
|
206
242
|
}
|
|
207
243
|
|
|
244
|
+
/* Keep the activity line legible on the brand background: swap the dim
|
|
245
|
+
* neutral for the inverse font color, held a touch lighter than the title so
|
|
246
|
+
* it still reads as secondary. */
|
|
247
|
+
.jp-xtralab-Terminals-item.jp-mod-current .jp-xtralab-Terminals-item-detail {
|
|
248
|
+
color: var(--jp-ui-inverse-font-color1);
|
|
249
|
+
opacity: 0.85;
|
|
250
|
+
}
|
|
251
|
+
|
|
208
252
|
/*
|
|
209
253
|
* Invert the monochrome terminal glyph against the brand background, exactly
|
|
210
254
|
* as the file listing does for its selected rows. Colored agent logos carry
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The read-only walkthrough panel (`xtralab:walkthrough`) in the side area. A
|
|
3
|
+
* scrollable column of step cards, each holding rendered Markdown, an optional
|
|
4
|
+
* embedded visual, and an optional "jump to code" button.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.jp-xtralab-Walkthrough {
|
|
8
|
+
overflow-y: auto;
|
|
9
|
+
padding: 4px 0;
|
|
10
|
+
background: var(--jp-layout-color1);
|
|
11
|
+
color: var(--jp-ui-font-color1);
|
|
12
|
+
font-size: var(--jp-ui-font-size1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.jp-xtralab-Walkthrough-step {
|
|
16
|
+
padding: 10px 12px 14px;
|
|
17
|
+
border-bottom: 1px solid var(--jp-border-color2);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.jp-xtralab-Walkthrough-stepTitle {
|
|
21
|
+
margin: 0 0 6px;
|
|
22
|
+
font-size: var(--jp-ui-font-size2);
|
|
23
|
+
font-weight: 600;
|
|
24
|
+
color: var(--jp-ui-font-color0);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.jp-xtralab-Walkthrough-content {
|
|
28
|
+
overflow-x: auto;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.jp-xtralab-Walkthrough-jumpRow {
|
|
32
|
+
margin-top: 8px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* A subtle native-feeling button: UI font and neutral colors, like the rest of
|
|
36
|
+
the JupyterLab chrome, with a leading file icon and a hover background. */
|
|
37
|
+
.jp-xtralab-Walkthrough-jump {
|
|
38
|
+
display: inline-flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
gap: 4px;
|
|
41
|
+
max-width: 100%;
|
|
42
|
+
box-sizing: border-box;
|
|
43
|
+
padding: 2px 8px 2px 5px;
|
|
44
|
+
border: var(--jp-border-width) solid var(--jp-border-color2);
|
|
45
|
+
border-radius: var(--jp-border-radius);
|
|
46
|
+
background: none;
|
|
47
|
+
color: var(--jp-ui-font-color1);
|
|
48
|
+
font-family: var(--jp-ui-font-family);
|
|
49
|
+
font-size: var(--jp-ui-font-size1);
|
|
50
|
+
line-height: 1.5;
|
|
51
|
+
cursor: pointer;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.jp-xtralab-Walkthrough-jump:hover {
|
|
55
|
+
background-color: var(--jp-layout-color2);
|
|
56
|
+
border-color: var(--jp-border-color1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.jp-xtralab-Walkthrough-jump:focus-visible {
|
|
60
|
+
outline: none;
|
|
61
|
+
border-color: var(--jp-brand-color1);
|
|
62
|
+
box-shadow: inset 0 0 0 1px var(--jp-brand-color1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.jp-xtralab-Walkthrough-jumpIcon {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex: 0 0 auto;
|
|
68
|
+
align-items: center;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.jp-xtralab-Walkthrough-jumpIcon svg {
|
|
72
|
+
width: 14px;
|
|
73
|
+
height: 14px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.jp-xtralab-Walkthrough-jumpLabel {
|
|
77
|
+
overflow: hidden;
|
|
78
|
+
text-overflow: ellipsis;
|
|
79
|
+
white-space: nowrap;
|
|
80
|
+
}
|