xtralab 0.15.0 → 0.15.2

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.
Files changed (237) hide show
  1. package/README.md +65 -30
  2. package/lib/about/icons.d.ts +0 -5
  3. package/lib/about/icons.js +0 -5
  4. package/lib/about/index.d.ts +4 -8
  5. package/lib/about/index.js +6 -17
  6. package/lib/agentSessions.d.ts +9 -29
  7. package/lib/agentSessions.js +2 -7
  8. package/lib/askAgent/editorSelection.d.ts +20 -26
  9. package/lib/askAgent/editorSelection.js +11 -26
  10. package/lib/askAgent/icons.d.ts +2 -3
  11. package/lib/askAgent/icons.js +2 -3
  12. package/lib/askAgent/index.d.ts +4 -26
  13. package/lib/askAgent/index.js +54 -158
  14. package/lib/askAgent/popup.d.ts +12 -16
  15. package/lib/askAgent/popup.js +18 -37
  16. package/lib/askAgent/prompt.d.ts +3 -5
  17. package/lib/askAgent/prompt.js +6 -19
  18. package/lib/askAgent/queue.d.ts +11 -21
  19. package/lib/askAgent/queue.js +9 -19
  20. package/lib/askAgent/queuePanel.d.ts +13 -18
  21. package/lib/askAgent/queuePanel.js +15 -37
  22. package/lib/askAgent/targetPicker.d.ts +2 -9
  23. package/lib/askAgent/targetPicker.js +6 -11
  24. package/lib/askAgent/tokens.d.ts +32 -46
  25. package/lib/askAgent/tokens.js +4 -6
  26. package/lib/commandBar/index.d.ts +4 -13
  27. package/lib/commandBar/index.js +21 -39
  28. package/lib/customPanel/index.js +15 -0
  29. package/lib/editorBreadcrumbs/index.d.ts +3 -6
  30. package/lib/editorBreadcrumbs/index.js +10 -6
  31. package/lib/editorBreadcrumbs/widget.d.ts +17 -4
  32. package/lib/editorBreadcrumbs/widget.js +11 -17
  33. package/lib/editorIndent/index.d.ts +4 -12
  34. package/lib/editorIndent/index.js +8 -23
  35. package/lib/fileBrowser/commands.d.ts +29 -19
  36. package/lib/fileBrowser/commands.js +83 -97
  37. package/lib/fileBrowser/contents.d.ts +3 -0
  38. package/lib/fileBrowser/dragAndDrop.d.ts +17 -4
  39. package/lib/fileBrowser/dragAndDrop.js +2 -7
  40. package/lib/fileBrowser/fileBrowser.d.ts +19 -9
  41. package/lib/fileBrowser/fileBrowser.js +70 -222
  42. package/lib/fileBrowser/gitStatus.d.ts +16 -10
  43. package/lib/fileBrowser/gitStatus.js +31 -30
  44. package/lib/fileBrowser/gitignore.d.ts +4 -17
  45. package/lib/fileBrowser/gitignore.js +4 -25
  46. package/lib/fileBrowser/icons.d.ts +7 -17
  47. package/lib/fileBrowser/icons.js +25 -80
  48. package/lib/fileBrowser/index.js +2 -4
  49. package/lib/fileBrowser/widget.d.ts +141 -48
  50. package/lib/fileBrowser/widget.js +102 -4
  51. package/lib/fileTypeIcons/index.js +0 -10
  52. package/lib/git/api.d.ts +5 -13
  53. package/lib/git/api.js +10 -36
  54. package/lib/git/askRequest.d.ts +4 -8
  55. package/lib/git/askRequest.js +6 -20
  56. package/lib/git/commands.d.ts +45 -5
  57. package/lib/git/commands.js +20 -13
  58. package/lib/git/diffModel.js +4 -0
  59. package/lib/git/diffPreferences.d.ts +90 -0
  60. package/lib/git/diffPreferences.js +107 -0
  61. package/lib/git/diffProvider.js +10 -2
  62. package/lib/git/diffSurface.d.ts +64 -63
  63. package/lib/git/diffSurface.js +72 -213
  64. package/lib/git/diffTheme.d.ts +7 -0
  65. package/lib/git/diffTheme.js +23 -0
  66. package/lib/git/diffWidget.d.ts +70 -14
  67. package/lib/git/diffWidget.js +100 -94
  68. package/lib/git/imageDiff.d.ts +14 -6
  69. package/lib/git/imageDiff.js +19 -75
  70. package/lib/git/index.d.ts +0 -3
  71. package/lib/git/index.js +44 -10
  72. package/lib/git/notebookDiff.d.ts +110 -33
  73. package/lib/git/notebookDiff.js +55 -197
  74. package/lib/git/tokens.d.ts +73 -31
  75. package/lib/git/tokens.js +2 -3
  76. package/lib/highlight/index.d.ts +4 -10
  77. package/lib/highlight/index.js +10 -41
  78. package/lib/index.d.ts +0 -9
  79. package/lib/index.js +0 -9
  80. package/lib/launcher/agents.d.ts +55 -51
  81. package/lib/launcher/agents.js +15 -57
  82. package/lib/launcher/availability.d.ts +3 -9
  83. package/lib/launcher/availability.js +3 -9
  84. package/lib/launcher/commands.d.ts +7 -32
  85. package/lib/launcher/commands.js +14 -45
  86. package/lib/launcher/dashboard.d.ts +19 -24
  87. package/lib/launcher/dashboard.js +21 -67
  88. package/lib/launcher/editorRegistry.d.ts +10 -22
  89. package/lib/launcher/editorRegistry.js +14 -18
  90. package/lib/launcher/editors.d.ts +39 -45
  91. package/lib/launcher/editors.js +8 -34
  92. package/lib/launcher/icons.d.ts +0 -12
  93. package/lib/launcher/icons.js +5 -39
  94. package/lib/launcher/index.js +12 -55
  95. package/lib/launcher/invocation.d.ts +4 -10
  96. package/lib/launcher/invocation.js +7 -22
  97. package/lib/launcher/registry.d.ts +9 -7
  98. package/lib/launcher/registry.js +9 -7
  99. package/lib/launcher/tokens.d.ts +10 -22
  100. package/lib/launcher/tokens.js +5 -8
  101. package/lib/menuBar/index.d.ts +3 -10
  102. package/lib/menuBar/index.js +11 -28
  103. package/lib/menus/index.d.ts +3 -9
  104. package/lib/menus/index.js +14 -30
  105. package/lib/omnibox/files.d.ts +2 -4
  106. package/lib/omnibox/files.js +5 -11
  107. package/lib/omnibox/index.d.ts +4 -14
  108. package/lib/omnibox/index.js +9 -27
  109. package/lib/omnibox/model.d.ts +38 -10
  110. package/lib/omnibox/model.js +15 -33
  111. package/lib/omnibox/recents.d.ts +15 -17
  112. package/lib/omnibox/recents.js +12 -17
  113. package/lib/omnibox/tokens.d.ts +5 -10
  114. package/lib/omnibox/tokens.js +2 -6
  115. package/lib/omnibox/widget.d.ts +11 -7
  116. package/lib/omnibox/widget.js +8 -16
  117. package/lib/searchReplace/index.d.ts +4 -20
  118. package/lib/searchReplace/index.js +7 -27
  119. package/lib/showOutput/index.d.ts +3 -12
  120. package/lib/showOutput/index.js +6 -22
  121. package/lib/sidebar/index.d.ts +4 -7
  122. package/lib/sidebar/index.js +5 -12
  123. package/lib/terminalNotifications/index.d.ts +4 -10
  124. package/lib/terminalNotifications/index.js +6 -20
  125. package/lib/terminals/agentTerminals.d.ts +12 -5
  126. package/lib/terminals/agentTerminals.js +25 -44
  127. package/lib/terminals/detection.d.ts +4 -8
  128. package/lib/terminals/detection.js +4 -8
  129. package/lib/terminals/index.d.ts +0 -35
  130. package/lib/terminals/index.js +12 -101
  131. package/lib/terminals/model.d.ts +64 -139
  132. package/lib/terminals/model.js +80 -220
  133. package/lib/terminals/tokens.d.ts +11 -22
  134. package/lib/terminals/tokens.js +2 -2
  135. package/lib/terminals/widget.d.ts +43 -13
  136. package/lib/terminals/widget.js +33 -18
  137. package/lib/topBar/icons.d.ts +3 -8
  138. package/lib/topBar/icons.js +3 -8
  139. package/lib/topBar/index.d.ts +4 -11
  140. package/lib/topBar/index.js +10 -38
  141. package/lib/walkthrough/index.d.ts +4 -9
  142. package/lib/walkthrough/index.js +6 -20
  143. package/lib/walkthrough/panel.d.ts +40 -9
  144. package/lib/walkthrough/panel.js +4 -10
  145. package/package.json +5 -3
  146. package/schema/git-diff-preferences.json +42 -0
  147. package/src/about/icons.ts +0 -5
  148. package/src/about/index.tsx +6 -17
  149. package/src/agentSessions.ts +9 -29
  150. package/src/askAgent/editorSelection.ts +22 -29
  151. package/src/askAgent/icons.ts +2 -3
  152. package/src/askAgent/index.ts +54 -158
  153. package/src/askAgent/popup.tsx +23 -45
  154. package/src/askAgent/prompt.ts +6 -19
  155. package/src/askAgent/queue.ts +13 -24
  156. package/src/askAgent/queuePanel.tsx +21 -46
  157. package/src/askAgent/targetPicker.tsx +5 -15
  158. package/src/askAgent/tokens.ts +32 -46
  159. package/src/commandBar/index.ts +24 -39
  160. package/src/customPanel/index.ts +15 -0
  161. package/src/editorBreadcrumbs/index.ts +10 -6
  162. package/src/editorBreadcrumbs/widget.ts +23 -17
  163. package/src/editorIndent/index.ts +17 -23
  164. package/src/fileBrowser/commands.ts +119 -96
  165. package/src/fileBrowser/contents.ts +3 -0
  166. package/src/fileBrowser/dragAndDrop.ts +17 -7
  167. package/src/fileBrowser/fileBrowser.tsx +86 -230
  168. package/src/fileBrowser/gitStatus.ts +36 -33
  169. package/src/fileBrowser/gitignore.ts +4 -25
  170. package/src/fileBrowser/icons.ts +25 -80
  171. package/src/fileBrowser/index.ts +2 -4
  172. package/src/fileBrowser/widget.tsx +171 -50
  173. package/src/fileTypeIcons/index.ts +0 -10
  174. package/src/git/api.ts +10 -36
  175. package/src/git/askRequest.ts +6 -20
  176. package/src/git/commands.ts +83 -11
  177. package/src/git/diffModel.ts +25 -0
  178. package/src/git/diffPreferences.ts +192 -0
  179. package/src/git/diffProvider.tsx +11 -2
  180. package/src/git/diffSurface.tsx +165 -286
  181. package/src/git/diffTheme.ts +24 -0
  182. package/src/git/diffWidget.tsx +194 -134
  183. package/src/git/imageDiff.tsx +56 -84
  184. package/src/git/index.ts +54 -10
  185. package/src/git/notebookDiff.tsx +214 -240
  186. package/src/git/tokens.ts +73 -31
  187. package/src/highlight/index.ts +10 -41
  188. package/src/index.ts +0 -9
  189. package/src/launcher/agents.ts +64 -95
  190. package/src/launcher/availability.ts +3 -9
  191. package/src/launcher/commands.ts +14 -51
  192. package/src/launcher/dashboard.tsx +49 -88
  193. package/src/launcher/editorRegistry.ts +21 -29
  194. package/src/launcher/editors.ts +39 -58
  195. package/src/launcher/icons.ts +5 -39
  196. package/src/launcher/index.ts +12 -55
  197. package/src/launcher/invocation.ts +7 -22
  198. package/src/launcher/registry.ts +9 -7
  199. package/src/launcher/tokens.ts +10 -22
  200. package/src/menuBar/index.ts +11 -28
  201. package/src/menus/index.ts +14 -30
  202. package/src/omnibox/files.ts +10 -14
  203. package/src/omnibox/index.ts +9 -27
  204. package/src/omnibox/model.ts +50 -38
  205. package/src/omnibox/recents.ts +17 -22
  206. package/src/omnibox/tokens.ts +5 -10
  207. package/src/omnibox/widget.tsx +14 -19
  208. package/src/searchReplace/index.ts +7 -27
  209. package/src/showOutput/index.ts +6 -22
  210. package/src/sidebar/index.ts +20 -12
  211. package/src/terminalNotifications/index.ts +42 -25
  212. package/src/terminals/agentTerminals.ts +25 -49
  213. package/src/terminals/detection.ts +4 -8
  214. package/src/terminals/index.ts +12 -101
  215. package/src/terminals/model.ts +130 -246
  216. package/src/terminals/tokens.ts +11 -22
  217. package/src/terminals/widget.tsx +48 -31
  218. package/src/topBar/icons.ts +3 -8
  219. package/src/topBar/index.ts +21 -44
  220. package/src/walkthrough/index.ts +6 -20
  221. package/src/walkthrough/panel.ts +40 -10
  222. package/style/about.css +2 -7
  223. package/style/askAgent.css +8 -40
  224. package/style/base.css +9 -45
  225. package/style/chrome.css +108 -308
  226. package/style/commandBar.css +4 -20
  227. package/style/customPanel.css +1 -4
  228. package/style/git.css +26 -186
  229. package/style/highlight.css +1 -3
  230. package/style/launcher.css +6 -70
  231. package/style/omnibox.css +2 -14
  232. package/style/showOutput.css +0 -6
  233. package/style/sidebar.css +29 -9
  234. package/style/tabs.css +5 -13
  235. package/style/terminals.css +6 -53
  236. package/style/topBar.css +2 -22
  237. package/style/walkthrough.css +0 -8
@@ -11,13 +11,38 @@ import { SessionRegistry } from './model';
11
11
  */
12
12
  export declare class RunningTerminals extends SidePanel implements IMovableSectionSource, IMovableSectionDestination {
13
13
  constructor(options: RunningTerminals.IOptions);
14
+ /**
15
+ * The accordion panel hosting the sections; read by the move plugin.
16
+ */
14
17
  get accordionPanel(): AccordionPanel;
18
+ /**
19
+ * A signal emitted when a section is announced to the move plugin.
20
+ */
15
21
  get sectionAdded(): ISignal<this, ISectionEntry>;
22
+ /**
23
+ * The hosted section widgets, excluding the panel's own Terminals section.
24
+ */
16
25
  get sections(): ReadonlyArray<Widget>;
26
+ /**
27
+ * Get the movable sections: just the Terminals section, while attached here.
28
+ */
17
29
  getSections(): ReadonlyArray<ISectionEntry>;
30
+ /**
31
+ * Detach the Terminals section for the move plugin and return it; `null`
32
+ * for an unknown id or when the section is already hosted elsewhere.
33
+ */
18
34
  removeSectionById(sectionId: string): Widget | null;
35
+ /**
36
+ * Re-attach the Terminals section after it moves back to this panel.
37
+ */
19
38
  reinsertSection(widget: Widget): void;
39
+ /**
40
+ * Host a section moved in from another sidebar panel.
41
+ */
20
42
  addSection(widget: Widget): void;
43
+ /**
44
+ * Detach a hosted section when it moves back to its own panel.
45
+ */
21
46
  removeSectionWidget(widget: Widget): void;
22
47
  /**
23
48
  * The layout restorer stores a section as collapsed whenever its panel is off
@@ -29,6 +54,9 @@ export declare class RunningTerminals extends SidePanel implements IMovableSecti
29
54
  * after `registerSource`, and this panel builds its section in the constructor.
30
55
  */
31
56
  announceSections(): void;
57
+ /**
58
+ * Dispose of the panel and the registry it owns.
59
+ */
32
60
  dispose(): void;
33
61
  private _sectionEntry;
34
62
  private _registry;
@@ -36,19 +64,25 @@ export declare class RunningTerminals extends SidePanel implements IMovableSecti
36
64
  private _sectionAdded;
37
65
  }
38
66
  export declare namespace RunningTerminals {
67
+ /**
68
+ * The instantiation options for a {@link RunningTerminals} panel.
69
+ */
39
70
  interface IOptions {
71
+ /**
72
+ * The session registry the panel renders and takes ownership of.
73
+ */
40
74
  registry: SessionRegistry;
75
+ /**
76
+ * The translation bundle for the panel's labels; untranslated if omitted.
77
+ */
41
78
  trans?: TranslationBundle;
42
79
  /**
43
- * Resolve the running-agent command for a row (from
44
- * `registry.agentCommandFor`) to the icon to show before its label —
45
- * the agent's logo, or the plain terminal icon. Supplied by the plugin
46
- * so the widget never imports the agent list.
80
+ * Resolve a row's running-agent command to its icon; supplied by the
81
+ * plugin so the widget never imports the agent list.
47
82
  */
48
83
  iconForCommand: (command: string | null) => LabIcon;
49
84
  /**
50
- * Activate the named session's open tab, or reopen it in a fresh
51
- * terminal widget if no tab is currently attached.
85
+ * Activate the named session's open tab, or reopen it in a fresh widget.
52
86
  */
53
87
  onActivate: (sessionName: string) => void;
54
88
  /**
@@ -56,16 +90,12 @@ export declare namespace RunningTerminals {
56
90
  */
57
91
  onShutdown: (sessionName: string) => void;
58
92
  /**
59
- * Shut down every running terminal at once. The plugin is expected to
60
- * confirm with the user first, since it tears down all live sessions.
93
+ * Shut down every running terminal; the plugin confirms with the user first.
61
94
  */
62
95
  onShutdownAll: () => void;
63
96
  /**
64
- * Activate the "+" button, anchored at the given viewport coordinates
65
- * (the bottom-left of the button). The plugin decides what to show
66
- * there — a menu of agents plus a plain terminal, or just a new
67
- * terminal when no agents are available — so the panel only reports
68
- * where the button is and never imports the command/menu machinery.
97
+ * Handle the "+" button, anchored at its bottom-left in viewport
98
+ * coordinates; the plugin decides what to show there.
69
99
  */
70
100
  onCreate: (anchor: {
71
101
  x: number;
@@ -2,14 +2,9 @@ import { nullTranslator } from '@jupyterlab/translation';
2
2
  import { addIcon, closeIcon, PanelWithToolbar, ReactWidget, SidePanel, stopIcon, terminalIcon, ToolbarButton, UseSignal } from '@jupyterlab/ui-components';
3
3
  import { Signal } from '@lumino/signaling';
4
4
  import * as React from 'react';
5
- /**
6
- * Id of the panel widget. Used for layout restoration and as the handle
7
- * the sidebar visibility toggle would target.
8
- */
9
5
  const RUNNING_TERMINALS_ID = 'xtralab-running-terminals';
10
6
  /**
11
- * Id of the accordion section holding the terminals list. Persisted by the
12
- * movable-sections plugin, so it must stay stable across releases.
7
+ * Persisted by the movable-sections plugin — must stay stable across releases.
13
8
  */
14
9
  const TERMINALS_SECTION_ID = 'xtralab-terminals-section';
15
10
  /**
@@ -45,8 +40,6 @@ export class RunningTerminals extends SidePanel {
45
40
  const newTerminal = new ToolbarButton({
46
41
  icon: addIcon,
47
42
  onClick: () => {
48
- // Anchor whatever the plugin shows (usually an agent menu) to the
49
- // button's bottom-left, in the viewport coordinates `Menu.open` wants.
50
43
  const rect = newTerminal.node.getBoundingClientRect();
51
44
  options.onCreate({ x: rect.left, y: rect.bottom });
52
45
  },
@@ -62,19 +55,35 @@ export class RunningTerminals extends SidePanel {
62
55
  }));
63
56
  this.addWidget(section);
64
57
  }
58
+ /**
59
+ * The accordion panel hosting the sections; read by the move plugin.
60
+ */
65
61
  get accordionPanel() {
66
62
  return this.content;
67
63
  }
64
+ /**
65
+ * A signal emitted when a section is announced to the move plugin.
66
+ */
68
67
  get sectionAdded() {
69
68
  return this._sectionAdded;
70
69
  }
70
+ /**
71
+ * The hosted section widgets, excluding the panel's own Terminals section.
72
+ */
71
73
  get sections() {
72
74
  return this.accordionPanel.widgets.filter(w => w !== this._section);
73
75
  }
76
+ /**
77
+ * Get the movable sections: just the Terminals section, while attached here.
78
+ */
74
79
  getSections() {
75
80
  const entry = this._sectionEntry();
76
81
  return entry ? [entry] : [];
77
82
  }
83
+ /**
84
+ * Detach the Terminals section for the move plugin and return it; `null`
85
+ * for an unknown id or when the section is already hosted elsewhere.
86
+ */
78
87
  removeSectionById(sectionId) {
79
88
  if (sectionId !== TERMINALS_SECTION_ID ||
80
89
  this._section.parent !== this.content) {
@@ -83,12 +92,21 @@ export class RunningTerminals extends SidePanel {
83
92
  this._section.parent = null;
84
93
  return this._section;
85
94
  }
95
+ /**
96
+ * Re-attach the Terminals section after it moves back to this panel.
97
+ */
86
98
  reinsertSection(widget) {
87
99
  this.addWidget(widget);
88
100
  }
101
+ /**
102
+ * Host a section moved in from another sidebar panel.
103
+ */
89
104
  addSection(widget) {
90
105
  this.addWidget(widget);
91
106
  }
107
+ /**
108
+ * Detach a hosted section when it moves back to its own panel.
109
+ */
92
110
  removeSectionWidget(widget) {
93
111
  if (widget.parent === this.content) {
94
112
  widget.parent = null;
@@ -115,12 +133,14 @@ export class RunningTerminals extends SidePanel {
115
133
  this._sectionAdded.emit(entry);
116
134
  }
117
135
  }
136
+ /**
137
+ * Dispose of the panel and the registry it owns.
138
+ */
118
139
  dispose() {
119
140
  if (this.isDisposed) {
120
141
  return;
121
142
  }
122
- // The panel owns the registry, so tear down its upstream
123
- // subscriptions before the React tree goes away.
143
+ // The panel owns the registry; tear down its subscriptions first.
124
144
  this._registry.dispose();
125
145
  super.dispose();
126
146
  }
@@ -147,6 +167,9 @@ class TerminalsListing extends ReactWidget {
147
167
  this._options = options;
148
168
  this.addClass('jp-xtralab-Terminals-listing');
149
169
  }
170
+ /**
171
+ * Render the listing, re-rendering on every registry state change.
172
+ */
150
173
  render() {
151
174
  return (React.createElement(UseSignal, { signal: this._options.registry.stateChanged }, () => (React.createElement(RunningTerminalsComponent, { registry: this._options.registry, trans: this._options.trans, iconForCommand: this._options.iconForCommand, onActivate: this._options.onActivate, onShutdown: this._options.onShutdown }))));
152
175
  }
@@ -154,9 +177,6 @@ class TerminalsListing extends ReactWidget {
154
177
  function RunningTerminalsComponent(props) {
155
178
  const { registry, trans, iconForCommand, onActivate, onShutdown } = props;
156
179
  const names = registry.sessionNames();
157
- // The session whose terminal is the current widget in the main area, so its
158
- // row can be highlighted. `null` when the current tab is a notebook or any
159
- // other non-terminal widget.
160
180
  const currentName = registry.currentSessionName();
161
181
  return (React.createElement("div", { className: "jp-xtralab-Terminals-body" }, names.length === 0 ? (React.createElement("p", { className: "jp-xtralab-Terminals-empty" }, trans.__('No running terminals.'))) : (React.createElement("ul", { className: "jp-xtralab-Terminals-list" }, names.map(name => {
162
182
  const label = registry.labelFor(name);
@@ -164,13 +184,8 @@ function RunningTerminalsComponent(props) {
164
184
  const tooltip = hasWidget
165
185
  ? trans.__('Activate %1', label)
166
186
  : trans.__('Reopen %1', label);
167
- // The running agent's logo (e.g. Claude), or the plain terminal
168
- // icon when nothing recognised is running in the session.
169
187
  const RowIcon = iconForCommand(registry.agentCommandFor(name)).react;
170
188
  const isCurrent = name === currentName;
171
- // The latest line of output from the session's agent, shown as a
172
- // smaller line under the title; `null` for rows with nothing to
173
- // surface (no agent running, or no open tab to read a live buffer).
174
189
  const activity = registry.activityFor(name);
175
190
  return (React.createElement("li", { key: name, className: isCurrent
176
191
  ? 'jp-xtralab-Terminals-item jp-mod-current'
@@ -1,13 +1,8 @@
1
1
  import { LabIcon } from '@jupyterlab/ui-components';
2
2
  /**
3
- * Mirror-symmetric "toggle sidebar" marks for the top-bar buttons, in the
4
- * same visual language as the macOS / VS Code / svgrepo sidebar icons
5
- * (https://www.svgrepo.com/vectors/sidebar/): a rounded window outline split
6
- * by a divider, with the controlled side shaded so left vs. right reads at a
7
- * glance. The artwork is hand-authored from basic geometry (rounded rect +
8
- * divider + a shaded panel) so there is no third-party licensing to track,
9
- * and every stroke/fill uses `currentColor` so the icons inherit the top
10
- * bar's text color across the light and dark themes.
3
+ * Mirror-symmetric "toggle sidebar" marks in the macOS / VS Code visual
4
+ * language. Hand-authored from basic geometry (no third-party licensing);
5
+ * every stroke/fill uses `currentColor` to follow the top bar's text color.
11
6
  */
12
7
  export declare const leftSidebarIcon: LabIcon;
13
8
  export declare const rightSidebarIcon: LabIcon;
@@ -1,13 +1,8 @@
1
1
  import { LabIcon } from '@jupyterlab/ui-components';
2
2
  /**
3
- * Mirror-symmetric "toggle sidebar" marks for the top-bar buttons, in the
4
- * same visual language as the macOS / VS Code / svgrepo sidebar icons
5
- * (https://www.svgrepo.com/vectors/sidebar/): a rounded window outline split
6
- * by a divider, with the controlled side shaded so left vs. right reads at a
7
- * glance. The artwork is hand-authored from basic geometry (rounded rect +
8
- * divider + a shaded panel) so there is no third-party licensing to track,
9
- * and every stroke/fill uses `currentColor` so the icons inherit the top
10
- * bar's text color across the light and dark themes.
3
+ * Mirror-symmetric "toggle sidebar" marks in the macOS / VS Code visual
4
+ * language. Hand-authored from basic geometry (no third-party licensing);
5
+ * every stroke/fill uses `currentColor` to follow the top bar's text color.
11
6
  */
12
7
  export const leftSidebarIcon = new LabIcon({
13
8
  name: 'xtralab:sidebar-left',
@@ -1,16 +1,9 @@
1
1
  import { JupyterFrontEndPlugin } from '@jupyterlab/application';
2
2
  /**
3
- * Add two icon buttons to the top bar that toggle the left and right side
4
- * areas, mirroring the macOS-style sidebar buttons: a left-sidebar button at
5
- * the leading edge and a right-sidebar button at the far edge.
6
- *
7
- * Each is a `CommandToolbarButton` wrapping an existing
8
- * `application:toggle-{left,right}-area` command, so clicking it runs the
9
- * same toggle as the View menu and the button reflects the command's state —
10
- * pressed while the matching sidebar is open, and disabled when the area is
11
- * empty. Note xtralab ships nothing in the right area by default (the
12
- * property inspector, table of contents and debugger are all disabled), so
13
- * the right button stays disabled until a widget is moved or added there.
3
+ * Add macOS-style sidebar toggle buttons to the top bar: left at the leading
4
+ * edge, right at the far edge. Each wraps the upstream toggle command and
5
+ * reflects its state — pressed while the sidebar is open, disabled while the
6
+ * area is empty (as the right area is by default).
14
7
  */
15
8
  declare const plugin: JupyterFrontEndPlugin<void>;
16
9
  export default plugin;
@@ -3,13 +3,6 @@ import { ITranslator, nullTranslator } from '@jupyterlab/translation';
3
3
  import { CommandToolbarButton } from '@jupyterlab/ui-components';
4
4
  import { leftSidebarIcon, rightSidebarIcon } from './icons';
5
5
  const PLUGIN_ID = 'xtralab:top-bar';
6
- /**
7
- * Upstream commands from `@jupyterlab/application-extension` that collapse or
8
- * expand the side areas. We bind the buttons to these rather than
9
- * reimplementing the toggle, so behavior (and the `isToggled`/`isEnabled`
10
- * state the buttons reflect) stays in lockstep with the View menu entries
11
- * and their keyboard shortcuts.
12
- */
13
6
  const TOGGLE_LEFT_AREA = 'application:toggle-left-area';
14
7
  const TOGGLE_RIGHT_AREA = 'application:toggle-right-area';
15
8
  const BUTTONS = [
@@ -31,17 +24,10 @@ const BUTTONS = [
31
24
  }
32
25
  ];
33
26
  /**
34
- * Add two icon buttons to the top bar that toggle the left and right side
35
- * areas, mirroring the macOS-style sidebar buttons: a left-sidebar button at
36
- * the leading edge and a right-sidebar button at the far edge.
37
- *
38
- * Each is a `CommandToolbarButton` wrapping an existing
39
- * `application:toggle-{left,right}-area` command, so clicking it runs the
40
- * same toggle as the View menu and the button reflects the command's state —
41
- * pressed while the matching sidebar is open, and disabled when the area is
42
- * empty. Note xtralab ships nothing in the right area by default (the
43
- * property inspector, table of contents and debugger are all disabled), so
44
- * the right button stays disabled until a widget is moved or added there.
27
+ * Add macOS-style sidebar toggle buttons to the top bar: left at the leading
28
+ * edge, right at the far edge. Each wraps the upstream toggle command and
29
+ * reflects its state — pressed while the sidebar is open, disabled while the
30
+ * area is empty (as the right area is by default).
45
31
  */
46
32
  const plugin = {
47
33
  id: PLUGIN_ID,
@@ -52,39 +38,25 @@ const plugin = {
52
38
  activate: (app, labShell, translator) => {
53
39
  const { commands } = app;
54
40
  const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('jupyterlab');
55
- // The upstream toggle-{left,right}-area commands derive `isEnabled` from
56
- // `!labShell.isEmpty(side)` but don't fire `commandChanged` when widgets
57
- // move in or out of a side area. `CommandToolbarButton` only re-renders on
58
- // `commandChanged` for its own id, so the buttons need an explicit notify
59
- // whenever the shell layout shifts — `layoutModified` covers each side
60
- // handler's `_updated` (add/remove, expand/collapse), keeping both
61
- // `isEnabled` and `isToggled` in sync.
41
+ // The upstream toggle commands don't fire `commandChanged` on layout
42
+ // shifts, and `CommandToolbarButton` only re-renders on that signal.
62
43
  labShell.layoutModified.connect(() => {
63
44
  for (const spec of BUTTONS) {
64
45
  commands.notifyCommandChanged(spec.command);
65
46
  }
66
47
  });
67
- // Defer to `app.restored` so the upstream toggle commands are already in
68
- // the registry: `CommandToolbarButton` renders nothing until its command
69
- // exists and only re-renders on `commandChanged` of type `changed` /
70
- // `many-changed` (not `added`), so mounting earlier could leave a button
71
- // blank until the next unrelated command change.
48
+ // Defer to `app.restored`: `CommandToolbarButton` renders nothing until
49
+ // its command exists and doesn't re-render on the `added` change type.
72
50
  void app.restored.then(() => {
73
51
  for (const spec of BUTTONS) {
74
52
  const button = new CommandToolbarButton({
75
53
  commands,
76
54
  id: spec.command,
77
55
  icon: spec.icon,
78
- // Empty label keeps the button icon-only: the override is forwarded
79
- // verbatim and the component skips the label span when it is falsy.
80
56
  label: '',
81
57
  caption: spec.caption(trans),
82
- // Toggle on mousedown without focusing the button. Otherwise
83
- // ToolbarButtonComponent calls `event.target.focus()` on click,
84
- // leaving the stealth button showing a focus fill/outline (the
85
- // stray "border") until you click elsewhere — unwanted chrome for a
86
- // title-bar control. Keyboard Tab focus still works, so this stays
87
- // accessible.
58
+ // ToolbarButtonComponent otherwise focuses the button on click,
59
+ // leaving a stray focus fill on this title-bar control; Tab still works.
88
60
  noFocusOnClick: true
89
61
  });
90
62
  button.id = spec.id;
@@ -1,14 +1,9 @@
1
1
  import { JupyterFrontEndPlugin } from '@jupyterlab/application';
2
2
  /**
3
- * Contribute `xtralab:walkthrough`: build a persistent, read-only walkthrough
4
- * in the right side area instead of narrating only in the agent's chat.
5
- *
6
- * Each call appends a step (Markdown prose, an optional embedded visual, and an
7
- * optional code reference). When a step names a file, the editor follows along
8
- * (opening it full-width in the main area, no split) and its lines are
9
- * highlighted; the step also keeps a button so the user can jump back to it
10
- * later. The panel accumulates the whole tour beside the code, so the user can
11
- * read at their own pace rather than chasing the chat.
3
+ * Contributes `xtralab:walkthrough`: each call appends a step (Markdown prose,
4
+ * optional visual, optional code reference) to a persistent read-only panel in
5
+ * the right side area, so the tour accumulates beside the code instead of
6
+ * scrolling away in the agent's chat.
12
7
  */
13
8
  declare const plugin: JupyterFrontEndPlugin<void>;
14
9
  export default plugin;
@@ -6,15 +6,9 @@ import { tocIcon } from '@jupyterlab/ui-components';
6
6
  import { coerceData } from '../mimeData';
7
7
  import { WalkthroughPanel } from './panel';
8
8
  const PLUGIN_ID = 'xtralab:walkthrough';
9
- /**
10
- * Append a step to the read-only walkthrough panel.
11
- */
12
9
  const WALKTHROUGH_COMMAND = 'xtralab:walkthrough';
13
10
  const HIGHLIGHT_LINES_COMMAND = 'xtralab:highlight-lines';
14
11
  const PANEL_ID = 'xtralab-walkthrough';
15
- /**
16
- * Pull a `{ mimeType, data }` media object out of a JSON command argument.
17
- */
18
12
  function readMedia(value) {
19
13
  if (value &&
20
14
  typeof value === 'object' &&
@@ -36,15 +30,10 @@ function toLine(value) {
36
30
  return Number.isFinite(n) && n >= 1 ? n : undefined;
37
31
  }
38
32
  /**
39
- * Contribute `xtralab:walkthrough`: build a persistent, read-only walkthrough
40
- * in the right side area instead of narrating only in the agent's chat.
41
- *
42
- * Each call appends a step (Markdown prose, an optional embedded visual, and an
43
- * optional code reference). When a step names a file, the editor follows along
44
- * (opening it full-width in the main area, no split) and its lines are
45
- * highlighted; the step also keeps a button so the user can jump back to it
46
- * later. The panel accumulates the whole tour beside the code, so the user can
47
- * read at their own pace rather than chasing the chat.
33
+ * Contributes `xtralab:walkthrough`: each call appends a step (Markdown prose,
34
+ * optional visual, optional code reference) to a persistent read-only panel in
35
+ * the right side area, so the tour accumulates beside the code instead of
36
+ * scrolling away in the agent's chat.
48
37
  */
49
38
  const plugin = {
50
39
  id: PLUGIN_ID,
@@ -63,9 +52,8 @@ const plugin = {
63
52
  panel.title.icon = tocIcon;
64
53
  panel.title.label = trans.__('Walkthrough');
65
54
  panel.title.caption = trans.__('Walkthrough');
66
- // Closable so it gets a close button if the user drags it out of the
67
- // side area into the main document area. Closing disposes it; the next
68
- // xtralab:walkthrough call recreates it back in the side area.
55
+ // Closable so a drag into the main area gets a close button; closing
56
+ // disposes, and the next call recreates the panel in the side area.
69
57
  panel.title.closable = true;
70
58
  labShell.add(panel, 'right', { rank: 1000, type: 'Walkthrough' });
71
59
  const created = panel;
@@ -148,10 +136,8 @@ const plugin = {
148
136
  args['reset'] !== true) {
149
137
  throw new Error('xtralab:walkthrough needs at least one of: title, body, media, path');
150
138
  }
151
- // Reveal the panel, then render the step into it.
152
139
  labShell.activateById(current.id);
153
140
  await current.addStep(step);
154
- // Let the editor follow the newest step.
155
141
  if (path && args['reveal'] !== false) {
156
142
  await commands.execute(HIGHLIGHT_LINES_COMMAND, {
157
143
  path,
@@ -8,35 +8,67 @@ import { Panel } from '@lumino/widgets';
8
8
  * A rich visual embedded in a step (rendered through the rendermime registry).
9
9
  */
10
10
  export interface IWalkthroughMedia {
11
+ /**
12
+ * The MIME type of the media payload.
13
+ */
11
14
  mimeType: string;
15
+ /**
16
+ * The payload handed to the renderer for the MIME type.
17
+ */
12
18
  data: ReadonlyPartialJSONValue;
13
19
  }
14
20
  /**
15
21
  * One step of a walkthrough. Every field is optional, but a step needs at least one.
16
22
  */
17
23
  export interface IWalkthroughStep {
24
+ /**
25
+ * A heading rendered above the step content.
26
+ */
18
27
  title?: string;
28
+ /**
29
+ * The body of the step, rendered as Markdown.
30
+ */
19
31
  body?: string;
32
+ /**
33
+ * A rich visual rendered after the body.
34
+ */
20
35
  media?: IWalkthroughMedia;
36
+ /**
37
+ * The file the step points at; when set, the step renders a jump link.
38
+ */
21
39
  path?: string;
40
+ /**
41
+ * The first line to highlight when the jump link is followed.
42
+ */
22
43
  line?: number;
44
+ /**
45
+ * The last line of the highlighted range.
46
+ */
23
47
  endLine?: number;
24
48
  }
25
49
  export declare namespace WalkthroughPanel {
50
+ /**
51
+ * The instantiation options for a walkthrough panel.
52
+ */
26
53
  interface IOptions {
54
+ /**
55
+ * The rendermime registry used to render step bodies and media.
56
+ */
27
57
  rendermime: IRenderMimeRegistry;
58
+ /**
59
+ * The command registry used to execute the jump-to-line command.
60
+ */
28
61
  commands: CommandRegistry;
62
+ /**
63
+ * The translation bundle for UI strings.
64
+ */
29
65
  trans: TranslationBundle;
30
66
  }
31
67
  }
32
68
  /**
33
69
  * A read-only, scrollable column of walkthrough steps for the side area.
34
- *
35
- * The agent appends steps as it narrates, so the explanation lives beside the
36
- * code the user is looking at and persists for them to read at their own pace,
37
- * rather than scrolling away in the chat. Each step renders Markdown (with code
38
- * snippets, Mermaid, math), can embed a rich visual, and can offer a button
39
- * that opens the referenced file and highlights its lines.
70
+ * The agent appends steps as it narrates, so the explanation persists beside
71
+ * the code instead of scrolling away in the chat.
40
72
  */
41
73
  export declare class WalkthroughPanel extends Panel {
42
74
  constructor(options: WalkthroughPanel.IOptions);
@@ -45,9 +77,8 @@ export declare class WalkthroughPanel extends Panel {
45
77
  */
46
78
  clear(): void;
47
79
  /**
48
- * Dispose on close (e.g. the close button when the panel has been dragged to
49
- * the main area) rather than leaving a detached, reusable widget behind. The
50
- * next `xtralab:walkthrough` call recreates the panel in the side area.
80
+ * Dispose on close (e.g. after a drag to the main area) instead of leaving a
81
+ * detached widget; the next `xtralab:walkthrough` call recreates the panel.
51
82
  */
52
83
  protected onCloseRequest(msg: Message): void;
53
84
  /**
@@ -6,12 +6,8 @@ import { Panel, Widget } from '@lumino/widgets';
6
6
  const HIGHLIGHT_LINES_COMMAND = 'xtralab:highlight-lines';
7
7
  /**
8
8
  * A read-only, scrollable column of walkthrough steps for the side area.
9
- *
10
- * The agent appends steps as it narrates, so the explanation lives beside the
11
- * code the user is looking at and persists for them to read at their own pace,
12
- * rather than scrolling away in the chat. Each step renders Markdown (with code
13
- * snippets, Mermaid, math), can embed a rich visual, and can offer a button
14
- * that opens the referenced file and highlights its lines.
9
+ * The agent appends steps as it narrates, so the explanation persists beside
10
+ * the code instead of scrolling away in the chat.
15
11
  */
16
12
  export class WalkthroughPanel extends Panel {
17
13
  constructor(options) {
@@ -30,9 +26,8 @@ export class WalkthroughPanel extends Panel {
30
26
  }
31
27
  }
32
28
  /**
33
- * Dispose on close (e.g. the close button when the panel has been dragged to
34
- * the main area) rather than leaving a detached, reusable widget behind. The
35
- * next `xtralab:walkthrough` call recreates the panel in the side area.
29
+ * Dispose on close (e.g. after a drag to the main area) instead of leaving a
30
+ * detached widget; the next `xtralab:walkthrough` call recreates the panel.
36
31
  */
37
32
  onCloseRequest(msg) {
38
33
  super.onCloseRequest(msg);
@@ -60,7 +55,6 @@ export class WalkthroughPanel extends Panel {
60
55
  if (step.path) {
61
56
  card.addWidget(this._jumpButton(step.path, step.line, step.endLine));
62
57
  }
63
- // Bring the newest step into view.
64
58
  this.node.scrollTop = this.node.scrollHeight;
65
59
  }
66
60
  async _render(parent, mimeType, data) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xtralab",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
4
4
  "description": "An opinionated JupyterLab meta-package that bundles a curated set of extensions, ships a path-first file browser, renders jupyterlab-git's text, notebook and image diffs with its own viewers, and applies a quieter default workspace configuration.",
5
5
  "keywords": [
6
6
  "jupyter",
@@ -90,7 +90,8 @@
90
90
  "@lumino/polling": "^2.1.5",
91
91
  "@lumino/signaling": "^2.1.5",
92
92
  "@lumino/widgets": "^2.8.0",
93
- "@pierre/diffs": "^1.2.11",
93
+ "@pierre/diffs": "^1.5.1",
94
+ "@pierre/icons": "^0.9.0",
94
95
  "@pierre/trees": "1.0.0-beta.4",
95
96
  "detect-indent": "^7.0.2",
96
97
  "ignore": "^5.3.2",
@@ -136,7 +137,8 @@
136
137
  "@jupyterlab/git": {
137
138
  "bundled": false,
138
139
  "singleton": true
139
- }
140
+ },
141
+ "@pierre/icons": false
140
142
  },
141
143
  "disabledExtensions": [
142
144
  "@jupyterlab/git:notebook-diff",
@@ -0,0 +1,42 @@
1
+ {
2
+ "title": "xtralab Git Diff",
3
+ "description": "Display options for the git diff views in the launcher and the Git panel.",
4
+ "type": "object",
5
+ "properties": {
6
+ "diffStyle": {
7
+ "type": "string",
8
+ "enum": ["split", "unified"],
9
+ "title": "Layout",
10
+ "description": "Show text diffs side by side (split) or in one column (unified).",
11
+ "default": "split"
12
+ },
13
+ "diffStyleControl": {
14
+ "type": "string",
15
+ "enum": ["buttons", "toggle"],
16
+ "title": "Layout buttons",
17
+ "description": "Show two toolbar buttons for the split and unified layouts (buttons), or one button that switches between them (toggle).",
18
+ "default": "buttons"
19
+ },
20
+ "lineWrap": {
21
+ "type": "boolean",
22
+ "title": "Wrap long lines",
23
+ "description": "When true, long lines in text diffs wrap to the width of the view. When false, they scroll horizontally.",
24
+ "default": false
25
+ },
26
+ "notebookViewMode": {
27
+ "type": "string",
28
+ "enum": ["notebook", "json"],
29
+ "title": "Notebook diff view",
30
+ "description": "Show notebook diffs cell by cell (notebook) or as the diff of the notebook JSON (json).",
31
+ "default": "notebook"
32
+ },
33
+ "imageViewMode": {
34
+ "type": "string",
35
+ "enum": ["2-up", "swipe", "onion"],
36
+ "title": "Image diff view",
37
+ "description": "Compare images side by side (2-up), with a slider (swipe), or overlaid (onion).",
38
+ "default": "2-up"
39
+ }
40
+ },
41
+ "additionalProperties": false
42
+ }