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
@@ -1,129 +1,33 @@
1
1
  import * as React from 'react';
2
2
  import { undoIcon } from '@jupyterlab/ui-components';
3
3
  import { FileDiff } from '@pierre/diffs/react';
4
+ import { IconDiffSplit, IconDiffUnified, IconWordWrap } from '@pierre/icons';
4
5
  import { diffAcceptRejectHunk, parseDiffFromFile } from '@pierre/diffs';
5
6
  import { ImageDiffView, imageDataType } from './imageDiff';
6
7
  import { buildNotebookDiff, NotebookDiffView } from './notebookDiff';
7
- import { resolveDiffTheme } from './diffTheme';
8
- /**
9
- * The CSS class added to the diff main-area widget. The selectors that
10
- * style the embedded `@pierre/diffs` viewer hang off this class.
11
- */
8
+ import { DEFAULT_SPLIT_RATIO, MAX_SPLIT_RATIO, MIN_SPLIT_RATIO } from './diffPreferences';
9
+ import { DIFF_SCROLLBAR_CSS, resolveDiffTheme } from './diffTheme';
12
10
  export const DIFF_WIDGET_CSS_CLASS = 'jp-xtralab-DiffWidget';
13
11
  /**
14
- * `localStorage` key for the user's last-chosen split ratio, persisted so
15
- * the preference survives reloads (the library has no built-in way to
16
- * remember it).
17
- */
18
- const SPLIT_RATIO_STORAGE_KEY = 'xtralab:diff-split-ratio';
19
- /**
20
- * Bounds on the left-pane fraction. Keeping a few percent on either side
21
- * guarantees both panes remain visible — dragging to 0/100 would hide a
22
- * column and is almost never what the user wants.
23
- */
24
- const MIN_SPLIT_RATIO = 0.1;
25
- const MAX_SPLIT_RATIO = 0.9;
26
- const DEFAULT_SPLIT_RATIO = 0.5;
27
- /**
28
- * CSS injected via the `@pierre/diffs` `unsafeCSS` option. The library
29
- * places it inside the shadow root under `@layer unsafe`, which beats
30
- * the library's own `@layer base` rule that hardcodes
31
- * `grid-template-columns: 1fr 1fr` on the split-mode container.
32
- *
33
- * The override reads from `--xtralab-split-cols`, a custom property we set
34
- * on the host element via the `style` prop. Custom properties inherit
35
- * through the shadow DOM boundary, so adjusting it on the host instantly
36
- * resizes the columns without re-rendering the diff.
12
+ * Injected via the `unsafeCSS` option into the shadow root's `@layer
13
+ * unsafe`, beating the library's base rule that hardcodes `1fr 1fr`. Reads
14
+ * `--xtralab-split-cols` set on the host — custom properties cross the
15
+ * shadow boundary, so resizing needs no re-render.
37
16
  */
38
17
  const SPLIT_RESIZE_CSS = `pre[data-diff-type="split"][data-overflow="scroll"] {
39
18
  grid-template-columns: var(--xtralab-split-cols, 1fr 1fr);
40
19
  }`;
41
- function readStoredSplitRatio() {
42
- try {
43
- const raw = window.localStorage.getItem(SPLIT_RATIO_STORAGE_KEY);
44
- if (raw === null) {
45
- return DEFAULT_SPLIT_RATIO;
46
- }
47
- const parsed = Number.parseFloat(raw);
48
- if (Number.isFinite(parsed) &&
49
- parsed >= MIN_SPLIT_RATIO &&
50
- parsed <= MAX_SPLIT_RATIO) {
51
- return parsed;
52
- }
53
- }
54
- catch (_a) {
55
- // localStorage may throw in privacy mode or sandboxed contexts. Falling
56
- // back to the default is fine — the user can resize again on this run.
57
- }
58
- return DEFAULT_SPLIT_RATIO;
59
- }
60
- function writeStoredSplitRatio(ratio) {
61
- try {
62
- window.localStorage.setItem(SPLIT_RATIO_STORAGE_KEY, ratio.toString());
63
- }
64
- catch (_a) {
65
- // See readStoredSplitRatio — best-effort persistence.
66
- }
67
- }
68
- const DIFF_STYLE_STORAGE_KEY = 'xtralab:diff-style';
69
- export function readStoredDiffStyle() {
70
- try {
71
- const raw = window.localStorage.getItem(DIFF_STYLE_STORAGE_KEY);
72
- if (raw === 'split' || raw === 'unified') {
73
- return raw;
74
- }
75
- }
76
- catch (_a) {
77
- // See readStoredSplitRatio — privacy-mode / sandboxed contexts can throw.
78
- }
79
- return 'split';
80
- }
81
- export function writeStoredDiffStyle(style) {
82
- try {
83
- window.localStorage.setItem(DIFF_STYLE_STORAGE_KEY, style);
84
- }
85
- catch (_a) {
86
- // Best-effort.
87
- }
88
- }
89
- const NOTEBOOK_DIFF_VIEW_MODE_STORAGE_KEY = 'xtralab:notebook-diff-view-mode';
90
- export function readStoredNotebookViewMode() {
91
- try {
92
- const raw = window.localStorage.getItem(NOTEBOOK_DIFF_VIEW_MODE_STORAGE_KEY);
93
- if (raw === 'json' || raw === 'notebook') {
94
- return raw;
95
- }
96
- }
97
- catch (_a) {
98
- // See readStoredSplitRatio — privacy-mode / sandboxed contexts can
99
- // throw on access. The notebook view is the better default anyway.
100
- }
101
- return 'notebook';
102
- }
103
- export function writeStoredNotebookViewMode(mode) {
104
- try {
105
- window.localStorage.setItem(NOTEBOOK_DIFF_VIEW_MODE_STORAGE_KEY, mode);
106
- }
107
- catch (_a) {
108
- // Best-effort.
109
- }
110
- }
20
+ const DIFF_SURFACE_CSS = `${SPLIT_RESIZE_CSS}\n${DIFF_SCROLLBAR_CSS}`;
111
21
  /**
112
- * Detect notebook files by extension. We only look at the suffix so the
113
- * caller doesn't need to plumb a content-type field through; mistaking
114
- * another `.ipynb`-named file for a notebook is harmless because
115
- * {@link buildNotebookDiff} validates the JSON shape and we fall back to
116
- * the file diff if parsing fails.
22
+ * Extension-only check; a false positive is harmless because
23
+ * {@link buildNotebookDiff} validates the JSON and the file diff is the fallback.
117
24
  */
118
25
  function isNotebookPath(path) {
119
26
  return path.toLowerCase().endsWith('.ipynb');
120
27
  }
121
28
  /**
122
- * Decide whether the active JupyterLab theme is a dark theme. Prefers the
123
- * `IThemeManager` token when available, and falls back to sniffing the
124
- * `data-jp-theme-light` attribute that JupyterLab sets on `<body>` so the
125
- * component still works in stripped-down hosts where the token isn't
126
- * provided (lite, certain notebook configurations, …).
29
+ * Dark-theme check via `IThemeManager`, falling back to the
30
+ * `data-jp-theme-light` body attribute for hosts without the token.
127
31
  */
128
32
  export function isDarkTheme(themeManager) {
129
33
  if (themeManager !== null && themeManager.theme !== null) {
@@ -143,16 +47,12 @@ export function isPierreTheme(themeManager) {
143
47
  * Shared renderer for text, notebook and image diffs.
144
48
  */
145
49
  export function DiffSurface(props) {
146
- const { loading, error, isBinary, oldText, newText, newName, oldName, dark, pierreTheme, rendermime, notebookViewMode, diffStyle, onNotebookAvailabilityChange, onFileDiffActiveChange, onMetadataChange, hunkDiscard, onLineAsk, trans } = props;
50
+ const { loading, error, isBinary, oldText, newText, newName, oldName, dark, pierreTheme, rendermime, notebookViewMode, diffStyle, lineWrap, splitRatio, onSplitRatioChange, imageViewMode, onImageViewModeChange, onNotebookAvailabilityChange, onFileDiffActiveChange, onMetadataChange, hunkDiscard, onLineAsk, trans } = props;
147
51
  const hasContent = !loading && error === null && !isBinary;
148
- // Raster images take a dedicated `<img>`-based view instead of a
149
- // text/notebook diff; the host passes the two sides as base64 strings in
150
- // `oldText`/`newText` (the git server base64-encodes binary content).
52
+ // For raster images the host passes both sides as base64 in oldText/newText.
151
53
  const imageType = React.useMemo(() => imageDataType(newName), [newName]);
152
- // Pre-compute the line-oriented diff metadata. Owning it here lets us
153
- // pass it to {@link FileDiff} *and* thread the same instance through
154
- // {@link diffAcceptRejectHunk} when the user discards a hunk — so hunk
155
- // indexes line up between what the user clicked and what we mutate.
54
+ // Owning the metadata here keeps hunk indexes aligned between FileDiff
55
+ // and diffAcceptRejectHunk on discard.
156
56
  const metadata = React.useMemo(() => {
157
57
  if (!hasContent || imageType !== null) {
158
58
  return null;
@@ -164,47 +64,35 @@ export function DiffSurface(props) {
164
64
  const newFile = { name: newName, contents: newText };
165
65
  return parseDiffFromFile(oldFile, newFile);
166
66
  }, [hasContent, imageType, oldText, newText, oldName, newName]);
167
- // Cell-by-cell notebook diff for `.ipynb` files. When non-null the
168
- // renderer uses a notebook-aware view instead of the line-oriented file
169
- // diff — kept distinct from {@link metadata} so a notebook whose JSON we
170
- // cannot parse can fall back to the file diff path.
171
67
  const notebookDiff = React.useMemo(() => {
172
68
  if (!hasContent || imageType !== null || !isNotebookPath(newName)) {
173
69
  return null;
174
70
  }
175
71
  return buildNotebookDiff({ oldText, newText });
176
72
  }, [hasContent, imageType, oldText, newText, newName]);
177
- // Tell the host whether a rendered notebook view is currently available
178
- // so it can show/hide its Notebook/JSON toggle.
179
73
  React.useEffect(() => {
180
74
  onNotebookAvailabilityChange === null || onNotebookAvailabilityChange === void 0 ? void 0 : onNotebookAvailabilityChange(notebookDiff !== null);
181
75
  }, [onNotebookAvailabilityChange, notebookDiff]);
182
- // Report the diff shape so hosts can react (e.g. auto-close on empty).
183
76
  React.useEffect(() => {
184
77
  onMetadataChange === null || onMetadataChange === void 0 ? void 0 : onMetadataChange({
185
78
  hunkCount: metadata !== null ? metadata.hunks.length : null
186
79
  });
187
80
  }, [onMetadataChange, metadata]);
188
- // Decide which view to render. The notebook view requires a successful
189
- // nbformat parse; if that failed, we only show the raw JSON file diff.
190
- // Computed before the early returns below so the file-diff-active effect
191
- // can depend on it without violating the rules of hooks.
81
+ // Computed before the early returns so the hooks below can depend on
82
+ // them without breaking the rules of hooks.
192
83
  const hasNotebookView = notebookDiff !== null;
193
84
  const showNotebookView = hasNotebookView && notebookViewMode === 'notebook';
194
85
  const showFileDiff = !showNotebookView && metadata !== null;
195
- // The split vs unified choice only affects the textual/code file diff, so
196
- // tell the host whether that view is active to drive its Split/Unified
197
- // toolbar toggle.
198
86
  React.useEffect(() => {
199
87
  onFileDiffActiveChange === null || onFileDiffActiveChange === void 0 ? void 0 : onFileDiffActiveChange(showFileDiff);
200
88
  }, [onFileDiffActiveChange, showFileDiff]);
201
- // Split ratio for the diff columns: fraction of width given to the
202
- // deletions (left) pane. Persisted across sessions so the user only
203
- // dials in their layout once.
204
- const [leftRatio, setLeftRatio] = React.useState(() => readStoredSplitRatio());
89
+ // Local while dragging; the host hears the ratio when a drag ends.
90
+ const [leftRatio, setLeftRatio] = React.useState(splitRatio);
91
+ React.useEffect(() => {
92
+ setLeftRatio(splitRatio);
93
+ }, [splitRatio]);
205
94
  const wrapperRef = React.useRef(null);
206
- // The drag handler reads the live ratio from a ref so the listeners we
207
- // attach on pointer-down don't capture a stale value across renders.
95
+ // Drag listeners read the live ratio from a ref to avoid stale captures.
208
96
  const leftRatioRef = React.useRef(leftRatio);
209
97
  React.useEffect(() => {
210
98
  leftRatioRef.current = leftRatio;
@@ -216,8 +104,6 @@ export function DiffSurface(props) {
216
104
  }
217
105
  return metadata.hunks.map((hunk, hunkIndex) => ({
218
106
  side: 'additions',
219
- // The first line of each hunk in the new file. We anchor the button
220
- // there so it sits at the top of the hunk's body.
221
107
  lineNumber: hunk.additionStart,
222
108
  metadata: { hunkIndex }
223
109
  }));
@@ -227,12 +113,8 @@ export function DiffSurface(props) {
227
113
  return;
228
114
  }
229
115
  const updated = diffAcceptRejectHunk(metadata, hunkIndex, 'reject');
230
- // `additionLines` after a 'reject' contains the full new file with
231
- // the hunk reverted back to the old content. The library splits
232
- // file contents with `/(?<=\n)/` (a lookbehind that keeps the
233
- // trailing `\n` on each line), so the entries already carry their
234
- // own line endings — joining with `''` rebuilds the original text
235
- // verbatim, while joining with `'\n'` would double every newline.
116
+ // additionLines holds the full new file with the hunk reverted; lines keep
117
+ // their trailing `\n` (lookbehind split), so join('') rebuilds it verbatim.
236
118
  const text = updated.additionLines.join('');
237
119
  try {
238
120
  await hunkDiscard.save(text);
@@ -256,15 +138,11 @@ export function DiffSurface(props) {
256
138
  if (onLineAsk === undefined) {
257
139
  return;
258
140
  }
259
- // Anchor to the gutter "+" button that was just clicked. It lives in
260
- // the `@pierre/diffs` shadow root (which is open), parked on the
261
- // hovered/selected line's number element.
141
+ // Anchor to the just-clicked gutter "+" button inside the library's open shadow root.
262
142
  const slot = (_c = (_b = (_a = wrapperRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('diffs-container')) === null || _b === void 0 ? void 0 : _b.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('[data-gutter-utility-slot]');
263
143
  onLineAsk(range, slot instanceof Element ? slot.getBoundingClientRect() : null);
264
144
  }, [onLineAsk]);
265
145
  const handleResizerPointerDown = React.useCallback((event) => {
266
- // Only react to primary-button drags. Right-click / middle-click on
267
- // the handle should pass through to the browser default.
268
146
  if (event.button !== 0) {
269
147
  return;
270
148
  }
@@ -293,18 +171,16 @@ export function DiffSurface(props) {
293
171
  handle.removeEventListener('pointermove', onPointerMove);
294
172
  handle.removeEventListener('pointerup', onPointerEnd);
295
173
  handle.removeEventListener('pointercancel', onPointerEnd);
296
- // Only persist on drag-end so a quick drag isn't followed by a
297
- // burst of writes for every intermediate position.
298
- writeStoredSplitRatio(leftRatioRef.current);
174
+ onSplitRatioChange(leftRatioRef.current);
299
175
  };
300
176
  handle.addEventListener('pointermove', onPointerMove);
301
177
  handle.addEventListener('pointerup', onPointerEnd);
302
178
  handle.addEventListener('pointercancel', onPointerEnd);
303
- }, []);
179
+ }, [onSplitRatioChange]);
304
180
  const handleResizerDoubleClick = React.useCallback(() => {
305
181
  setLeftRatio(DEFAULT_SPLIT_RATIO);
306
- writeStoredSplitRatio(DEFAULT_SPLIT_RATIO);
307
- }, []);
182
+ onSplitRatioChange(DEFAULT_SPLIT_RATIO);
183
+ }, [onSplitRatioChange]);
308
184
  const handleResizerKeyDown = React.useCallback((event) => {
309
185
  const step = event.shiftKey ? 0.1 : 0.01;
310
186
  let next = null;
@@ -328,8 +204,8 @@ export function DiffSurface(props) {
328
204
  event.preventDefault();
329
205
  const clamped = Math.max(MIN_SPLIT_RATIO, Math.min(MAX_SPLIT_RATIO, next));
330
206
  setLeftRatio(clamped);
331
- writeStoredSplitRatio(clamped);
332
- }, []);
207
+ onSplitRatioChange(clamped);
208
+ }, [onSplitRatioChange]);
333
209
  if (loading) {
334
210
  return (React.createElement("div", { className: "jp-xtralab-DiffWidget-status" }, trans.__('Loading diff…')));
335
211
  }
@@ -340,49 +216,32 @@ export function DiffSurface(props) {
340
216
  return (React.createElement("div", { className: "jp-xtralab-DiffWidget-status" }, trans.__('Binary file — diff not supported.')));
341
217
  }
342
218
  if (imageType !== null) {
343
- // `oldText`/`newText` carry the two revisions as base64 here. The
344
- // image view owns its own layout and mode selector, so it does not
345
- // use the split resizer or the notebook/JSON toggle.
346
219
  return (React.createElement("div", { className: "jp-xtralab-DiffWidget-content" },
347
- React.createElement(ImageDiffView, { reference: oldText, challenger: newText, fileType: imageType, trans: trans })));
220
+ React.createElement(ImageDiffView, { reference: oldText, challenger: newText, fileType: imageType, mode: imageViewMode, onModeChange: onImageViewModeChange, trans: trans })));
348
221
  }
349
222
  if (!showNotebookView && !showFileDiff) {
350
223
  return (React.createElement("div", { className: "jp-xtralab-DiffWidget-status" }, trans.__('No content to diff.')));
351
224
  }
352
- // Custom property set on the diffs-container host. The library's
353
- // shadow-root rule consumes it via `var(--xtralab-split-cols, …)` (see
354
- // SPLIT_RESIZE_CSS) and recomputes the column tracks instantly. Only
355
- // relevant in the file-diff path; the notebook view doesn't use it.
356
225
  const leftPercent = leftRatio * 100;
226
+ // The wrapped split grid sizes its gutter tracks to their content, so a
227
+ // percentage split cannot line up with the handle.
228
+ const showResizer = showFileDiff && diffStyle === 'split' && !lineWrap;
357
229
  const hostStyle = {
358
230
  '--xtralab-split-cols': `${leftPercent}% ${100 - leftPercent}%`
359
231
  };
360
232
  return (React.createElement("div", { className: "jp-xtralab-DiffWidget-content" },
361
233
  React.createElement("div", { ref: wrapperRef, className: "jp-xtralab-DiffWidget-body" },
362
234
  React.createElement("div", { className: "jp-xtralab-DiffWidget-scroll" }, showNotebookView && notebookDiff !== null ? (React.createElement(NotebookDiffView, { diff: notebookDiff, dark: dark, pierreTheme: pierreTheme, rendermime: rendermime, trans: trans })) : showFileDiff && metadata !== null ? (React.createElement(FileDiff, { fileDiff: metadata, lineAnnotations: lineAnnotations, renderAnnotation: renderAnnotation, style: hostStyle,
363
- // Disable the worker pool: JupyterLab's webpack federation
364
- // pipeline doesn't ship the library's
365
- // `@pierre/diffs/worker/worker.js` file at a URL the worker
366
- // bootstrap can resolve from, so leaving the pool enabled
367
- // crashes on instantiation. Running on the main thread is
368
- // fine for the small files git diffs typically operate on.
235
+ // JupyterLab's federation pipeline can't serve the worker bundle
236
+ // at a resolvable URL, so the pool crashes; run on the main thread.
369
237
  disableWorkerPool: true, options: {
370
238
  diffStyle,
371
- // Drop the file header — the tab title already shows the
372
- // file name and the panel header carries the change
373
- // context.
239
+ overflow: lineWrap ? 'wrap' : 'scroll',
374
240
  disableFileHeader: true,
375
241
  theme: resolveDiffTheme(dark, pierreTheme),
376
242
  themeType: dark ? 'dark' : 'light',
377
- // Inject the column-resize override into the shadow root
378
- // via the library's `@layer unsafe` channel. Keeping the
379
- // string constant lets the library short-circuit the
380
- // re-render path it uses when this option actually
381
- // changes.
382
- unsafeCSS: SPLIT_RESIZE_CSS,
383
- // Line selection + the gutter "+" button feed the
384
- // ask-agent popup; only wired up when a handler exists so
385
- // a plain diff keeps its passive gutter.
243
+ // Constant string lets the library skip its unsafeCSS re-render path.
244
+ unsafeCSS: DIFF_SURFACE_CSS,
386
245
  ...(onLineAsk !== undefined
387
246
  ? {
388
247
  enableLineSelection: true,
@@ -391,13 +250,11 @@ export function DiffSurface(props) {
391
250
  }
392
251
  : {})
393
252
  } })) : null),
394
- showFileDiff && diffStyle === 'split' ? (React.createElement("div", { className: "jp-xtralab-DiffWidget-resizer", style: { left: `${leftPercent}%` }, role: "separator", "aria-orientation": "vertical", "aria-valuenow": Math.round(leftPercent), "aria-valuemin": Math.round(MIN_SPLIT_RATIO * 100), "aria-valuemax": Math.round(MAX_SPLIT_RATIO * 100), "aria-label": trans.__('Resize the diff panes'), tabIndex: 0, title: trans.__('Drag to resize the diff panes (double-click to reset)'), onPointerDown: handleResizerPointerDown, onDoubleClick: handleResizerDoubleClick, onKeyDown: handleResizerKeyDown })) : null)));
253
+ showResizer ? (React.createElement("div", { className: "jp-xtralab-DiffWidget-resizer", style: { left: `${leftPercent}%` }, role: "separator", "aria-orientation": "vertical", "aria-valuenow": Math.round(leftPercent), "aria-valuemin": Math.round(MIN_SPLIT_RATIO * 100), "aria-valuemax": Math.round(MAX_SPLIT_RATIO * 100), "aria-label": trans.__('Resize the diff panes'), tabIndex: 0, title: trans.__('Drag to resize the diff panes (double-click to reset)'), onPointerDown: handleResizerPointerDown, onDoubleClick: handleResizerDoubleClick, onKeyDown: handleResizerKeyDown })) : null)));
395
254
  }
396
255
  /**
397
- * Segmented Notebook/JSON selector. Hosts mount this into whatever toolbar
398
- * they own (the launcher's `MainAreaWidget` toolbar, or the
399
- * `jupyterlab-git`-provided diff toolbar) and drive its value/visibility
400
- * from the same state they pass to {@link DiffSurface}.
256
+ * Segmented Notebook/JSON selector. Hosts mount it into their own toolbar
257
+ * and drive value/visibility from the state they pass to {@link DiffSurface}.
401
258
  */
402
259
  export function NotebookViewModeControl(props) {
403
260
  const { mode, available, onChange, trans } = props;
@@ -409,37 +266,39 @@ export function NotebookViewModeControl(props) {
409
266
  React.createElement("button", { type: "button", role: "tab", "aria-selected": mode === 'json', "data-active": mode === 'json', className: "jp-xtralab-DiffWidget-segmentedButton", onClick: () => onChange('json') }, trans.__('JSON'))));
410
267
  }
411
268
  /**
412
- * Split / unified glyphs, inlined from the `@pierre/diffs` icon sprite
413
- * (`diffs-icon-diff-split` / `diffs-icon-diff-unified`) so the toggle looks
414
- * like the one on the library's own docs site without depending on the
415
- * sprite sheet being injected into the document. `currentColor` lets the
416
- * segmented-button styling drive the fill (including the active state).
417
- */
418
- function DiffSplitIcon() {
419
- return (React.createElement("svg", { viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true" },
420
- React.createElement("path", { d: "M14 0H8.5v16H14a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2m-1.5 6.5v1h1a.5.5 0 0 1 0 1h-1v1a.5.5 0 0 1-1 0v-1h-1a.5.5 0 0 1 0-1h1v-1a.5.5 0 0 1 1 0" }),
421
- React.createElement("path", { d: "M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h5.5V0zm.5 7.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1 0-1", opacity: ".3" })));
422
- }
423
- function DiffUnifiedIcon() {
424
- return (React.createElement("svg", { viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true" },
425
- React.createElement("path", { fillRule: "evenodd", d: "M16 14a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V8.5h16zm-8-4a.5.5 0 0 0-.5.5v1h-1a.5.5 0 0 0 0 1h1v1a.5.5 0 0 0 1 0v-1h1a.5.5 0 0 0 0-1h-1v-1A.5.5 0 0 0 8 10", clipRule: "evenodd" }),
426
- React.createElement("path", { fillRule: "evenodd", d: "M14 0a2 2 0 0 1 2 2v5.5H0V2a2 2 0 0 1 2-2zM6.5 3.5a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1z", clipRule: "evenodd", opacity: ".4" })));
427
- }
428
- /**
429
- * Segmented Split/Unified selector. Mirrors {@link NotebookViewModeControl}:
430
- * hosts mount it into their own toolbar and drive its value/visibility from
431
- * the same state they pass to {@link DiffSurface}. Only meaningful while the
432
- * textual/code file diff is the active view, so `available` mirrors the
433
- * surface's `onFileDiffActiveChange`.
269
+ * Split/Unified selector: two segmented buttons, or with `control: 'toggle'`
270
+ * one button that shows the layout it switches to.
271
+ * `available` mirrors the surface's `onFileDiffActiveChange`.
434
272
  */
435
273
  export function DiffStyleControl(props) {
436
- const { diffStyle, available, onChange, trans } = props;
274
+ const { diffStyle, control, available, onChange, trans } = props;
437
275
  if (!available) {
438
276
  return React.createElement(React.Fragment, null);
439
277
  }
278
+ if (control === 'toggle') {
279
+ const next = diffStyle === 'split' ? 'unified' : 'split';
280
+ const label = next === 'split'
281
+ ? trans.__('Switch to split view')
282
+ : trans.__('Switch to unified view');
283
+ return (React.createElement("div", { className: "jp-xtralab-DiffWidget-segmented" },
284
+ React.createElement("button", { type: "button", className: "jp-xtralab-DiffWidget-segmentedButton jp-xtralab-DiffWidget-segmentedButton-icon", title: label, "aria-label": label, onClick: () => onChange(next) }, next === 'split' ? React.createElement(IconDiffSplit, null) : React.createElement(IconDiffUnified, null))));
285
+ }
440
286
  return (React.createElement("div", { className: "jp-xtralab-DiffWidget-segmented", role: "tablist", "aria-label": trans.__('Diff view style') },
441
287
  React.createElement("button", { type: "button", role: "tab", "aria-selected": diffStyle === 'split', "data-active": diffStyle === 'split', className: "jp-xtralab-DiffWidget-segmentedButton jp-xtralab-DiffWidget-segmentedButton-icon", title: trans.__('Split (side-by-side) view'), "aria-label": trans.__('Split view'), onClick: () => onChange('split') },
442
- React.createElement(DiffSplitIcon, null)),
288
+ React.createElement(IconDiffSplit, null)),
443
289
  React.createElement("button", { type: "button", role: "tab", "aria-selected": diffStyle === 'unified', "data-active": diffStyle === 'unified', className: "jp-xtralab-DiffWidget-segmentedButton jp-xtralab-DiffWidget-segmentedButton-icon", title: trans.__('Unified (inline) view'), "aria-label": trans.__('Unified view'), onClick: () => onChange('unified') },
444
- React.createElement(DiffUnifiedIcon, null))));
290
+ React.createElement(IconDiffUnified, null))));
291
+ }
292
+ /**
293
+ * Line-wrap toggle styled as a one-button segmented control.
294
+ * `available` mirrors the surface's `onFileDiffActiveChange`.
295
+ */
296
+ export function LineWrapControl(props) {
297
+ const { lineWrap, available, onChange, trans } = props;
298
+ if (!available) {
299
+ return React.createElement(React.Fragment, null);
300
+ }
301
+ return (React.createElement("div", { className: "jp-xtralab-DiffWidget-segmented" },
302
+ React.createElement("button", { type: "button", "aria-pressed": lineWrap, "data-active": lineWrap, className: "jp-xtralab-DiffWidget-segmentedButton jp-xtralab-DiffWidget-segmentedButton-icon", title: trans.__('Wrap long lines'), "aria-label": trans.__('Wrap lines'), onClick: () => onChange(!lineWrap) },
303
+ React.createElement(IconWordWrap, null))));
445
304
  }
@@ -1,4 +1,11 @@
1
1
  import { type DiffsThemeNames } from '@pierre/diffs';
2
+ /**
3
+ * `unsafeCSS` for a taller, always-visible horizontal scrollbar. The library
4
+ * default is 6px and only paints the thumb on hover, in a color close to the
5
+ * background, so users miss that long lines scroll. Same thumb color as the
6
+ * app scrollbars in chrome.css.
7
+ */
8
+ export declare const DIFF_SCROLLBAR_CSS = ":host {\n --diffs-scrollbar-gutter-override: 10px;\n --xtralab-diff-scrollbar-thumb: color-mix(in srgb, var(--jp-ui-font-color1) 28%, transparent);\n}\n[data-code]::-webkit-scrollbar-thumb {\n background-color: var(--xtralab-diff-scrollbar-thumb);\n border-width: 2px;\n border-radius: 999px;\n}\n[data-code]::-webkit-scrollbar-thumb:hover {\n background-color: color-mix(in srgb, var(--jp-ui-font-color1) 45%, transparent);\n}\n@supports (-moz-appearance: none) {\n [data-code] {\n scrollbar-color: var(--xtralab-diff-scrollbar-thumb) transparent;\n }\n}";
2
9
  /**
3
10
  * Choose Pierre's palette or the JupyterLab CSS-variable theme.
4
11
  */
@@ -20,6 +20,29 @@ registerCustomCSSVariableTheme(JUPYTERLAB_DIFF_THEME, {
20
20
  'token-punctuation': 'var(--jp-mirror-editor-punctuation-color)',
21
21
  'token-link': 'var(--jp-mirror-editor-link-color)'
22
22
  });
23
+ /**
24
+ * `unsafeCSS` for a taller, always-visible horizontal scrollbar. The library
25
+ * default is 6px and only paints the thumb on hover, in a color close to the
26
+ * background, so users miss that long lines scroll. Same thumb color as the
27
+ * app scrollbars in chrome.css.
28
+ */
29
+ export const DIFF_SCROLLBAR_CSS = `:host {
30
+ --diffs-scrollbar-gutter-override: 10px;
31
+ --xtralab-diff-scrollbar-thumb: color-mix(in srgb, var(--jp-ui-font-color1) 28%, transparent);
32
+ }
33
+ [data-code]::-webkit-scrollbar-thumb {
34
+ background-color: var(--xtralab-diff-scrollbar-thumb);
35
+ border-width: 2px;
36
+ border-radius: 999px;
37
+ }
38
+ [data-code]::-webkit-scrollbar-thumb:hover {
39
+ background-color: color-mix(in srgb, var(--jp-ui-font-color1) 45%, transparent);
40
+ }
41
+ @supports (-moz-appearance: none) {
42
+ [data-code] {
43
+ scrollbar-color: var(--xtralab-diff-scrollbar-thumb) transparent;
44
+ }
45
+ }`;
23
46
  /**
24
47
  * Choose Pierre's palette or the JupyterLab CSS-variable theme.
25
48
  */
@@ -8,28 +8,55 @@ import { ReactWidget } from '@jupyterlab/ui-components';
8
8
  import { ISignal } from '@lumino/signaling';
9
9
  import { Widget } from '@lumino/widgets';
10
10
  import type { IAskAgent } from '../askAgent/tokens';
11
- import { DIFF_WIDGET_CSS_CLASS, type DiffStyle, type NotebookDiffViewMode } from './diffSurface';
11
+ import { type IDiffPreferences } from './diffPreferences';
12
+ import { DIFF_WIDGET_CSS_CLASS } from './diffSurface';
12
13
  export { DIFF_WIDGET_CSS_CLASS };
13
14
  /**
14
15
  * `Git.Diff.IModel` plus optional xtralab-only metadata.
15
16
  */
16
17
  export interface IXtralabDiffModel extends Git.Diff.IModel {
18
+ /**
19
+ * Whether the file is binary, so no text contents are fetched.
20
+ */
17
21
  isBinary?: boolean;
22
+ /**
23
+ * Whether hunks may be discarded; when absent, a working-tree heuristic decides.
24
+ */
18
25
  canDiscard?: boolean;
26
+ /**
27
+ * The old-side path when the diff represents a rename.
28
+ */
19
29
  oldFilename?: string;
20
30
  }
21
31
  /**
22
32
  * Application-level services the diff model does not carry.
23
33
  */
24
34
  export interface IXtralabDiffContext {
35
+ /**
36
+ * The contents manager used to save hunk-discard results.
37
+ */
25
38
  contentsManager: Contents.IManager;
39
+ /**
40
+ * The rendermime registry for rendered notebook diffs, or `null` to
41
+ * force the textual fallback.
42
+ */
26
43
  rendermime: IRenderMimeRegistry | null;
44
+ /**
45
+ * The theme manager used to track theme changes, or `null` to watch
46
+ * the body attribute instead.
47
+ */
27
48
  themeManager: IThemeManager | null;
28
49
  /**
29
- * The ask-agent popup; when available, diff line selections get an
30
- * "ask an agent about these lines" gutter button.
50
+ * When available, diff line selections get an "ask an agent" gutter button.
31
51
  */
32
52
  askAgent: IAskAgent | null;
53
+ /**
54
+ * The display choices shared by all diff views.
55
+ */
56
+ preferences: IDiffPreferences;
57
+ /**
58
+ * The application translation bundle.
59
+ */
33
60
  trans: TranslationBundle;
34
61
  }
35
62
  /**
@@ -37,6 +64,9 @@ export interface IXtralabDiffContext {
37
64
  */
38
65
  export declare class XtralabDiffWidget extends ReactWidget implements Git.Diff.IDiffWidget {
39
66
  constructor(model: Git.Diff.IModel, context: IXtralabDiffContext);
67
+ /**
68
+ * The git diff model being rendered.
69
+ */
40
70
  get model(): Git.Diff.IModel;
41
71
  /**
42
72
  * Swap the rendered model when the launcher reuses its preview tab.
@@ -54,41 +84,64 @@ export declare class XtralabDiffWidget extends ReactWidget implements Git.Diff.I
54
84
  * Re-pull both sides of the model and re-render.
55
85
  */
56
86
  refresh(): Promise<void>;
57
- get notebookViewMode(): NotebookDiffViewMode;
58
- setNotebookViewMode(mode: NotebookDiffViewMode): void;
59
- get notebookViewModeChanged(): ISignal<this, NotebookDiffViewMode>;
87
+ /**
88
+ * Whether a rendered notebook view is currently available.
89
+ */
60
90
  get hasNotebookView(): boolean;
91
+ /**
92
+ * Set whether a rendered notebook view is available.
93
+ */
61
94
  setHasNotebookView(value: boolean): void;
95
+ /**
96
+ * A signal emitted when rendered-notebook availability changes.
97
+ */
62
98
  get hasNotebookViewChanged(): ISignal<this, boolean>;
63
- get diffStyle(): DiffStyle;
64
- setDiffStyle(style: DiffStyle): void;
65
- get diffStyleChanged(): ISignal<this, DiffStyle>;
66
99
  /**
67
- * Whether the Split/Unified toolbar selector currently applies.
100
+ * Whether the Split/Unified and line-wrap toolbar controls currently apply.
68
101
  */
69
102
  get fileDiffActive(): boolean;
103
+ /**
104
+ * Set whether the textual file diff is the active view.
105
+ */
70
106
  setFileDiffActive(value: boolean): void;
107
+ /**
108
+ * A signal emitted when {@link fileDiffActive} changes.
109
+ */
71
110
  get fileDiffActiveChanged(): ISignal<this, boolean>;
72
111
  /**
73
112
  * Emitted when a post-discard reload leaves the diff with no hunks.
74
113
  */
75
114
  get emptied(): ISignal<this, void>;
115
+ /**
116
+ * Emit the {@link emptied} signal.
117
+ */
76
118
  notifyEmptied(): void;
119
+ /**
120
+ * Resolve and clear the pending `refresh()` promise, if any.
121
+ */
77
122
  settleRefresh(): void;
123
+ /**
124
+ * Dispose of the resources held by the widget.
125
+ */
78
126
  dispose(): void;
127
+ /**
128
+ * A counter incremented on each `refresh()` to trigger a content re-fetch.
129
+ */
79
130
  get reloadNonce(): number;
131
+ /**
132
+ * The application-level services used by the rendered diff.
133
+ */
80
134
  get context(): IXtralabDiffContext;
135
+ /**
136
+ * Render the diff view for the current model.
137
+ */
81
138
  protected render(): React.ReactElement;
82
139
  private _model;
83
140
  private _context;
84
141
  private _reloadNonce;
85
142
  private _pendingRefresh;
86
- private _notebookViewMode;
87
- private _notebookViewModeChanged;
88
143
  private _hasNotebookView;
89
144
  private _hasNotebookViewChanged;
90
- private _diffStyle;
91
- private _diffStyleChanged;
92
145
  private _fileDiffActive;
93
146
  private _fileDiffActiveChanged;
94
147
  private _emptied;
@@ -97,6 +150,9 @@ export declare class XtralabDiffWidget extends ReactWidget implements Git.Diff.I
97
150
  * Structural toolbar type shared across host package boundaries.
98
151
  */
99
152
  interface IDiffToolbar {
153
+ /**
154
+ * Add an item to the toolbar under the given name.
155
+ */
100
156
  addItem(name: string, widget: Widget): boolean;
101
157
  }
102
158
  /**