xtralab 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +69 -0
  3. package/lib/fileBrowser/commands.d.ts +62 -0
  4. package/lib/fileBrowser/commands.js +418 -0
  5. package/lib/fileBrowser/contents.d.ts +28 -0
  6. package/lib/fileBrowser/contents.js +48 -0
  7. package/lib/fileBrowser/fileBrowser.d.ts +24 -0
  8. package/lib/fileBrowser/fileBrowser.js +535 -0
  9. package/lib/fileBrowser/icons.d.ts +37 -0
  10. package/lib/fileBrowser/icons.js +153 -0
  11. package/lib/fileBrowser/index.d.ts +7 -0
  12. package/lib/fileBrowser/index.js +38 -0
  13. package/lib/fileBrowser/widget.d.ts +97 -0
  14. package/lib/fileBrowser/widget.js +95 -0
  15. package/lib/git/api.d.ts +39 -0
  16. package/lib/git/api.js +164 -0
  17. package/lib/git/commands.d.ts +69 -0
  18. package/lib/git/commands.js +67 -0
  19. package/lib/git/diffWidget.d.ts +108 -0
  20. package/lib/git/diffWidget.js +624 -0
  21. package/lib/git/icons.d.ts +14 -0
  22. package/lib/git/icons.js +19 -0
  23. package/lib/git/index.d.ts +11 -0
  24. package/lib/git/index.js +74 -0
  25. package/lib/git/notebookDiff.d.ts +176 -0
  26. package/lib/git/notebookDiff.js +805 -0
  27. package/lib/git/panel.d.ts +29 -0
  28. package/lib/git/panel.js +42 -0
  29. package/lib/git/panelComponent.d.ts +26 -0
  30. package/lib/git/panelComponent.js +300 -0
  31. package/lib/git/tokens.d.ts +78 -0
  32. package/lib/git/tokens.js +6 -0
  33. package/lib/index.d.ts +10 -0
  34. package/lib/index.js +14 -0
  35. package/package.json +216 -0
  36. package/schema/plugin.json +67 -0
  37. package/src/fileBrowser/commands.ts +507 -0
  38. package/src/fileBrowser/contents.ts +66 -0
  39. package/src/fileBrowser/fileBrowser.tsx +635 -0
  40. package/src/fileBrowser/icons.ts +172 -0
  41. package/src/fileBrowser/index.ts +56 -0
  42. package/src/fileBrowser/widget.tsx +202 -0
  43. package/src/git/api.ts +207 -0
  44. package/src/git/commands.ts +143 -0
  45. package/src/git/diffWidget.tsx +903 -0
  46. package/src/git/icons.ts +20 -0
  47. package/src/git/index.ts +109 -0
  48. package/src/git/notebookDiff.tsx +1294 -0
  49. package/src/git/panel.tsx +56 -0
  50. package/src/git/panelComponent.tsx +558 -0
  51. package/src/git/tokens.ts +91 -0
  52. package/src/index.ts +18 -0
  53. package/style/base.css +175 -0
  54. package/style/git.css +770 -0
  55. package/style/index.css +2 -0
  56. package/style/index.js +2 -0
package/style/git.css ADDED
@@ -0,0 +1,770 @@
1
+ /*
2
+ * Styles for the git changes panel and the diff viewer. The panel mirrors
3
+ * the visual rhythm of the default JupyterLab side panels so it does not
4
+ * stand out from the rest of the UI.
5
+ */
6
+
7
+ .jp-xtralab-GitPanel {
8
+ display: flex;
9
+ flex-direction: column;
10
+ min-width: 240px;
11
+ background-color: var(--jp-layout-color1);
12
+ color: var(--jp-ui-font-color1);
13
+ font-family: var(--jp-ui-font-family);
14
+ font-size: var(--jp-ui-font-size1);
15
+ overflow: hidden;
16
+ }
17
+
18
+ .jp-xtralab-GitPanel-content {
19
+ display: flex;
20
+ flex-direction: column;
21
+ flex: 1 1 auto;
22
+ min-height: 0;
23
+ overflow-y: auto;
24
+ }
25
+
26
+ .jp-xtralab-GitPanel-header {
27
+ display: flex;
28
+ align-items: flex-start;
29
+ gap: 8px;
30
+ padding: 8px 12px;
31
+ border-bottom: 1px solid var(--jp-border-color2);
32
+ }
33
+
34
+ .jp-xtralab-GitPanel-headerInfo {
35
+ display: flex;
36
+ flex-direction: column;
37
+ gap: 2px;
38
+ flex: 1 1 auto;
39
+ min-width: 0;
40
+ }
41
+
42
+ .jp-xtralab-GitPanel-title {
43
+ font-weight: 600;
44
+ text-transform: uppercase;
45
+ font-size: var(--jp-ui-font-size0);
46
+ letter-spacing: 0.04em;
47
+ color: var(--jp-ui-font-color2);
48
+ }
49
+
50
+ .jp-xtralab-GitPanel-repo {
51
+ font-weight: 600;
52
+ white-space: nowrap;
53
+ overflow: hidden;
54
+ text-overflow: ellipsis;
55
+ }
56
+
57
+ .jp-xtralab-GitPanel-branch {
58
+ color: var(--jp-ui-font-color2);
59
+ font-size: var(--jp-ui-font-size0);
60
+ }
61
+
62
+ .jp-xtralab-GitPanel-error {
63
+ margin: 12px;
64
+ padding: 8px;
65
+ border-radius: 4px;
66
+ background-color: var(
67
+ --jp-error-color3,
68
+ var(--jp-rendermime-error-background)
69
+ );
70
+ color: var(--jp-ui-font-color1);
71
+ font-size: var(--jp-ui-font-size1);
72
+ white-space: pre-wrap;
73
+ }
74
+
75
+ .jp-xtralab-GitPanel-empty {
76
+ margin: 12px;
77
+ color: var(--jp-ui-font-color2);
78
+ font-style: italic;
79
+ text-align: center;
80
+ }
81
+
82
+ .jp-xtralab-GitPanel-section {
83
+ display: flex;
84
+ flex-direction: column;
85
+ }
86
+
87
+ /*
88
+ * Section headers and rows place their hover actions between the label
89
+ * and the trailing count/badge, so the count stays pinned to the right
90
+ * edge regardless of whether the section has any bulk actions. Reserving
91
+ * the action width via `visibility: hidden` keeps the layout from
92
+ * shifting when the cursor enters and leaves.
93
+ */
94
+ .jp-xtralab-GitPanel-sectionHeader {
95
+ display: flex;
96
+ align-items: center;
97
+ gap: 4px;
98
+ height: 28px;
99
+ padding: 0 12px;
100
+ cursor: pointer;
101
+ user-select: none;
102
+ text-transform: uppercase;
103
+ font-size: var(--jp-ui-font-size0);
104
+ font-weight: 600;
105
+ letter-spacing: 0.04em;
106
+ color: var(--jp-ui-font-color2);
107
+ }
108
+
109
+ .jp-xtralab-GitPanel-sectionHeader:hover {
110
+ background-color: var(--jp-layout-color2);
111
+ }
112
+
113
+ .jp-xtralab-GitPanel-sectionChevron {
114
+ width: 12px;
115
+ text-align: center;
116
+ font-size: 10px;
117
+ }
118
+
119
+ .jp-xtralab-GitPanel-sectionLabel {
120
+ flex: 1 1 auto;
121
+ }
122
+
123
+ .jp-xtralab-GitPanel-sectionCount {
124
+ display: inline-flex;
125
+ align-items: center;
126
+ justify-content: center;
127
+ min-width: 18px;
128
+ height: 16px;
129
+ padding: 0 4px;
130
+ background-color: var(--jp-layout-color3);
131
+ color: var(--jp-ui-font-color1);
132
+ border-radius: 8px;
133
+ font-size: var(--jp-ui-font-size0);
134
+ font-weight: 500;
135
+ line-height: 1;
136
+ }
137
+
138
+ .jp-xtralab-GitPanel-sectionActions {
139
+ display: inline-flex;
140
+ align-items: center;
141
+ gap: 4px;
142
+ visibility: hidden;
143
+ }
144
+
145
+ .jp-xtralab-GitPanel-sectionHeader:hover
146
+ .jp-xtralab-GitPanel-sectionActions {
147
+ visibility: visible;
148
+ }
149
+
150
+ .jp-xtralab-GitPanel-sectionBody {
151
+ display: flex;
152
+ flex-direction: column;
153
+ }
154
+
155
+ /*
156
+ * Three-column row layout: the label group on the left grows, the actions
157
+ * column has a fixed reserved width that fits the worst-case button count,
158
+ * and the badge column is auto-sized on the right edge. Reserving the
159
+ * action column keeps the badge horizontally pinned regardless of the
160
+ * row's hover state.
161
+ */
162
+ .jp-xtralab-GitPanel-row {
163
+ display: flex;
164
+ align-items: center;
165
+ gap: 6px;
166
+ height: 26px;
167
+ padding: 0 12px;
168
+ cursor: pointer;
169
+ user-select: none;
170
+ }
171
+
172
+ .jp-xtralab-GitPanel-row:hover {
173
+ background-color: var(--jp-layout-color2);
174
+ }
175
+
176
+ .jp-xtralab-GitPanel-rowLabel {
177
+ display: flex;
178
+ align-items: baseline;
179
+ gap: 6px;
180
+ flex: 1 1 auto;
181
+ min-width: 0;
182
+ overflow: hidden;
183
+ }
184
+
185
+ .jp-xtralab-GitPanel-rowName {
186
+ white-space: nowrap;
187
+ overflow: hidden;
188
+ text-overflow: ellipsis;
189
+ flex: 0 1 auto;
190
+ }
191
+
192
+ .jp-xtralab-GitPanel-rowPath {
193
+ color: var(--jp-ui-font-color2);
194
+ font-size: var(--jp-ui-font-size0);
195
+ white-space: nowrap;
196
+ overflow: hidden;
197
+ text-overflow: ellipsis;
198
+ flex: 0 1 auto;
199
+ }
200
+
201
+ .jp-xtralab-GitPanel-rowActions {
202
+ /*
203
+ * Reserved width matches the worst case of two 20px buttons + a 2px
204
+ * gap. Staged rows only host the unstage button, but pinning the
205
+ * column width keeps the trailing badge horizontally aligned across
206
+ * the staged and unstaged sections.
207
+ */
208
+ display: inline-flex;
209
+ align-items: center;
210
+ justify-content: flex-end;
211
+ gap: 2px;
212
+ flex: 0 0 42px;
213
+ visibility: hidden;
214
+ }
215
+
216
+ .jp-xtralab-GitPanel-row:hover .jp-xtralab-GitPanel-rowActions,
217
+ .jp-xtralab-GitPanel-rowActions[data-pending='true'] {
218
+ visibility: visible;
219
+ }
220
+
221
+ .jp-xtralab-GitPanel-rowBadge {
222
+ display: inline-flex;
223
+ align-items: center;
224
+ justify-content: center;
225
+ flex: 0 0 16px;
226
+ width: 16px;
227
+ height: 16px;
228
+ border-radius: 2px;
229
+ font-size: var(--jp-ui-font-size0);
230
+ font-weight: 600;
231
+ font-family: var(--jp-code-font-family);
232
+ }
233
+
234
+ .jp-xtralab-GitPanel-rowBadge[data-status='modified'] {
235
+ color: var(--jp-warn-color1);
236
+ }
237
+
238
+ .jp-xtralab-GitPanel-rowBadge[data-status='added'],
239
+ .jp-xtralab-GitPanel-rowBadge[data-status='untracked'] {
240
+ color: var(--jp-success-color1);
241
+ }
242
+
243
+ .jp-xtralab-GitPanel-rowBadge[data-status='deleted'] {
244
+ color: var(--jp-error-color1);
245
+ }
246
+
247
+ .jp-xtralab-GitPanel-rowBadge[data-status='renamed'] {
248
+ color: var(--jp-info-color1, var(--jp-brand-color1));
249
+ }
250
+
251
+ .jp-xtralab-GitPanel-rowBadge[data-status='unmerged'] {
252
+ color: var(--jp-error-color1);
253
+ }
254
+
255
+ .jp-xtralab-GitPanel-iconButton {
256
+ display: inline-flex;
257
+ align-items: center;
258
+ justify-content: center;
259
+ width: 20px;
260
+ height: 20px;
261
+ border: none;
262
+ background: transparent;
263
+ color: var(--jp-ui-font-color1);
264
+ cursor: pointer;
265
+ border-radius: 2px;
266
+ font-size: var(--jp-ui-font-size1);
267
+ line-height: 1;
268
+ }
269
+
270
+ .jp-xtralab-GitPanel-iconButton:hover {
271
+ background-color: var(--jp-layout-color3);
272
+ }
273
+
274
+ .jp-xtralab-GitPanel-iconButton:disabled {
275
+ opacity: 0.4;
276
+ cursor: default;
277
+ }
278
+
279
+ /*
280
+ * Diff viewer (main area). The `MainAreaWidget` holding the React content
281
+ * gets sized by JupyterLab's box layout; the inner content div fills it
282
+ * and provides vertical scroll. Horizontal scrolling within each code
283
+ * block is owned by `@pierre/diffs` via its internal `data-code` rules.
284
+ *
285
+ * The block also forwards JupyterLab's theme variables onto the
286
+ * `--diffs-*-override` properties the library exposes, so the diff
287
+ * recolors with the active theme.
288
+ */
289
+ .jp-xtralab-DiffWidget {
290
+ background-color: var(--jp-layout-color1);
291
+ color: var(--jp-ui-font-color1);
292
+ }
293
+
294
+ /*
295
+ * Flex-column container: an optional toolbar at the top (notebook view
296
+ * mode toggle) plus a body that hosts the scrollable diff and the
297
+ * column resize handle. Splitting these responsibilities keeps the
298
+ * resize handle pinned to the visible viewport while the diff content
299
+ * scrolls underneath, and keeps the toolbar always visible.
300
+ */
301
+ .jp-xtralab-DiffWidget-content {
302
+ display: flex;
303
+ flex-direction: column;
304
+ width: 100%;
305
+ height: 100%;
306
+ background-color: var(--jp-layout-color1);
307
+ color: var(--jp-ui-font-color1);
308
+
309
+ /*
310
+ * Map JupyterLab's theme variables onto the `--diffs-*-override`
311
+ * properties the library exposes. The `*-override` variants take
312
+ * precedence over the library's defaults, so these values track the
313
+ * JupyterLab theme automatically — no JS needed when the theme
314
+ * switches. Theme-dependent colors (insertion green, deletion red, …)
315
+ * still come from the active Shiki theme passed via `options.theme`.
316
+ */
317
+ --diffs-bg-override: var(--jp-layout-color1);
318
+ --diffs-bg-buffer-override: var(--jp-layout-color1);
319
+ --diffs-bg-context-override: var(--jp-layout-color1);
320
+ --diffs-bg-separator-override: var(--jp-layout-color2);
321
+ --diffs-bg-hover-override: var(--jp-layout-color2);
322
+ --diffs-bg-selection-override: var(--jp-layout-color3);
323
+ --diffs-bg-selection-number-override: var(--jp-layout-color3);
324
+ --diffs-fg-override: var(--jp-ui-font-color1);
325
+ --diffs-fg-number-override: var(--jp-ui-font-color3);
326
+ --diffs-fg-conflict-marker-override: var(--jp-warn-color1);
327
+ --diffs-modified-color-override: var(--jp-warn-color1);
328
+ }
329
+
330
+ /*
331
+ * Body wrapping the scrollable diff + the column resize handle. Owns
332
+ * its own positioning context so the resizer can be absolutely placed
333
+ * within the body's bounds (and therefore aligned with the visible
334
+ * scroll area, not the toolbar above it).
335
+ */
336
+ .jp-xtralab-DiffWidget-body {
337
+ position: relative;
338
+ flex: 1 1 auto;
339
+ min-height: 0;
340
+ }
341
+
342
+ .jp-xtralab-DiffWidget-scroll {
343
+ position: absolute;
344
+ inset: 0;
345
+ overflow: auto;
346
+ }
347
+
348
+ /*
349
+ * Notebook/JSON view-mode selector that lives in the `MainAreaWidget`
350
+ * toolbar for `.ipynb` diffs. The host toolbar provides its own
351
+ * background and border, so this is just the segmented control itself.
352
+ */
353
+ .jp-xtralab-DiffWidget-viewModeToolbarItem {
354
+ display: flex;
355
+ align-items: center;
356
+ font-size: var(--jp-ui-font-size0);
357
+ }
358
+
359
+ .jp-xtralab-DiffWidget-segmented {
360
+ display: inline-flex;
361
+ border: 1px solid var(--jp-border-color2);
362
+ border-radius: 3px;
363
+ overflow: hidden;
364
+ background-color: var(--jp-layout-color1);
365
+ }
366
+
367
+ .jp-xtralab-DiffWidget-segmentedButton {
368
+ padding: 2px 10px;
369
+ border: none;
370
+ background: transparent;
371
+ color: var(--jp-ui-font-color1);
372
+ font-size: var(--jp-ui-font-size0);
373
+ cursor: pointer;
374
+ line-height: 1.4;
375
+ }
376
+
377
+ .jp-xtralab-DiffWidget-segmentedButton:hover {
378
+ background-color: var(--jp-layout-color2);
379
+ }
380
+
381
+ .jp-xtralab-DiffWidget-segmentedButton[data-active='true'] {
382
+ background-color: var(--jp-brand-color1);
383
+ color: var(--jp-ui-inverse-font-color1);
384
+ }
385
+
386
+ .jp-xtralab-DiffWidget-segmentedButton[data-active='true']:hover {
387
+ background-color: var(--jp-brand-color1);
388
+ }
389
+
390
+ /*
391
+ * Draggable column splitter. Sits on top of the diff (z-index above the
392
+ * content) but stays a thin strip so it doesn't visually intrude. The
393
+ * `transform: translateX(-50%)` centers the strip on the column boundary
394
+ * the inline `left` percentage points to.
395
+ */
396
+ .jp-xtralab-DiffWidget-resizer {
397
+ position: absolute;
398
+ top: 0;
399
+ bottom: 0;
400
+ width: 6px;
401
+ transform: translateX(-50%);
402
+ cursor: col-resize;
403
+ z-index: 2;
404
+ background-color: transparent;
405
+ transition: background-color 0.1s ease;
406
+ user-select: none;
407
+ touch-action: none;
408
+ }
409
+
410
+ .jp-xtralab-DiffWidget-resizer:hover,
411
+ .jp-xtralab-DiffWidget-resizer[data-dragging='true'] {
412
+ background-color: var(--jp-brand-color1);
413
+ }
414
+
415
+ .jp-xtralab-DiffWidget-status {
416
+ margin: 12px;
417
+ padding: 12px;
418
+ border-radius: 4px;
419
+ background-color: var(--jp-layout-color2);
420
+ color: var(--jp-ui-font-color2);
421
+ font-size: var(--jp-ui-font-size1);
422
+ white-space: pre-wrap;
423
+ }
424
+
425
+ .jp-xtralab-DiffWidget-status[data-error='true'] {
426
+ background-color: var(
427
+ --jp-error-color3,
428
+ var(--jp-rendermime-error-background)
429
+ );
430
+ color: var(--jp-ui-font-color1);
431
+ }
432
+
433
+ /*
434
+ * Per-hunk action overlay. The diff library injects a row at the
435
+ * annotation's anchor line and renders this content inside it; we keep the
436
+ * row visually unobtrusive — a single small icon button that fades in on
437
+ * row hover — so the annotation does not compete with the diff content.
438
+ */
439
+ .jp-xtralab-DiffWidget-hunkAnnotation {
440
+ display: flex;
441
+ justify-content: flex-end;
442
+ padding: 0 8px;
443
+ opacity: 0.4;
444
+ transition: opacity 0.1s ease;
445
+ }
446
+
447
+ .jp-xtralab-DiffWidget-hunkAnnotation:hover {
448
+ opacity: 1;
449
+ }
450
+
451
+ .jp-xtralab-DiffWidget-hunkButton {
452
+ display: inline-flex;
453
+ align-items: center;
454
+ justify-content: center;
455
+ width: 18px;
456
+ height: 18px;
457
+ padding: 0;
458
+ border: none;
459
+ border-radius: 3px;
460
+ background: transparent;
461
+ color: var(--jp-ui-font-color1);
462
+ cursor: pointer;
463
+ }
464
+
465
+ .jp-xtralab-DiffWidget-hunkButton:hover {
466
+ background-color: var(--jp-layout-color3);
467
+ }
468
+
469
+ .jp-xtralab-DiffWidget-hunkButton-icon {
470
+ display: inline-flex;
471
+ width: 14px;
472
+ height: 14px;
473
+ }
474
+
475
+ /*
476
+ * Notebook diff. Renders one block per cell stacked vertically, plus an
477
+ * optional notebook-level metadata block at the bottom. Each cell carries
478
+ * its own header (kind badge + cell index + cell type) and a body with the
479
+ * source / outputs / metadata sub-diffs the @pierre/diffs library produces.
480
+ *
481
+ * The sticky header keeps the scope visible while the user scrolls through
482
+ * a long cell, and the data-kind attributes drive the colored badges and
483
+ * left borders that distinguish added / removed / modified / unchanged.
484
+ */
485
+ .jp-xtralab-NotebookDiff {
486
+ display: flex;
487
+ flex-direction: column;
488
+ padding: 8px;
489
+ gap: 8px;
490
+ }
491
+
492
+ /*
493
+ * The cell entry grid. Two equal columns mirror the old / new mental model
494
+ * the column header bar establishes; each cell entry below either spans
495
+ * both columns (modified / unchanged) or sits in a single column with an
496
+ * empty placeholder on the other side (added / removed). Auto rows let
497
+ * each cell pick its own height naturally.
498
+ */
499
+ .jp-xtralab-NotebookDiff-grid {
500
+ display: grid;
501
+ grid-template-columns: 1fr 1fr;
502
+ gap: 8px 8px;
503
+ align-items: stretch;
504
+ }
505
+
506
+ .jp-xtralab-NotebookDiff-cell[data-placement='full'] {
507
+ grid-column: 1 / -1;
508
+ }
509
+
510
+ .jp-xtralab-NotebookDiff-cell[data-placement='left'] {
511
+ grid-column: 1;
512
+ }
513
+
514
+ .jp-xtralab-NotebookDiff-cell[data-placement='right'] {
515
+ grid-column: 2;
516
+ }
517
+
518
+ /*
519
+ * Empty placeholder rendered in the column opposite an added or removed
520
+ * cell. Visible (dashed outline) so the user can see the alignment gap
521
+ * the missing cell creates between old and new. Sized roughly like a
522
+ * minimal cell card so the row height is consistent.
523
+ */
524
+ .jp-xtralab-NotebookDiff-empty {
525
+ display: flex;
526
+ align-items: center;
527
+ justify-content: center;
528
+ min-height: 60px;
529
+ padding: 12px;
530
+ border: 1px dashed var(--jp-border-color2);
531
+ border-radius: 4px;
532
+ background-color: transparent;
533
+ }
534
+
535
+ .jp-xtralab-NotebookDiff-emptyLabel {
536
+ color: var(--jp-ui-font-color3);
537
+ font-size: var(--jp-ui-font-size0);
538
+ font-style: italic;
539
+ }
540
+
541
+ .jp-xtralab-NotebookDiff-header {
542
+ display: flex;
543
+ align-items: center;
544
+ gap: 12px;
545
+ padding: 4px 8px;
546
+ border-bottom: 1px solid var(--jp-border-color2);
547
+ font-size: var(--jp-ui-font-size1);
548
+ color: var(--jp-ui-font-color1);
549
+ }
550
+
551
+ .jp-xtralab-NotebookDiff-headerCount {
552
+ color: var(--jp-ui-font-color2);
553
+ font-size: var(--jp-ui-font-size0);
554
+ }
555
+
556
+ .jp-xtralab-NotebookDiff-stat {
557
+ font-size: var(--jp-ui-font-size0);
558
+ color: var(--jp-ui-font-color2);
559
+ }
560
+
561
+ .jp-xtralab-NotebookDiff-stat[data-kind='modified'] {
562
+ color: var(--jp-warn-color1);
563
+ }
564
+
565
+ .jp-xtralab-NotebookDiff-stat[data-kind='added'] {
566
+ color: var(--jp-success-color1);
567
+ }
568
+
569
+ .jp-xtralab-NotebookDiff-stat[data-kind='removed'] {
570
+ color: var(--jp-error-color1);
571
+ }
572
+
573
+ .jp-xtralab-NotebookDiff-cell {
574
+ display: flex;
575
+ flex-direction: column;
576
+ border: 1px solid var(--jp-border-color2);
577
+ border-radius: 4px;
578
+ background-color: var(--jp-layout-color1);
579
+ overflow: hidden;
580
+ }
581
+
582
+ .jp-xtralab-NotebookDiff-cellHeader {
583
+ display: flex;
584
+ align-items: center;
585
+ gap: 8px;
586
+ padding: 6px 10px;
587
+ background-color: var(--jp-layout-color2);
588
+ cursor: pointer;
589
+ user-select: none;
590
+ font-size: var(--jp-ui-font-size1);
591
+ }
592
+
593
+ .jp-xtralab-NotebookDiff-cellHeader:hover {
594
+ background-color: var(--jp-layout-color3);
595
+ }
596
+
597
+ .jp-xtralab-NotebookDiff-cellChevron {
598
+ width: 12px;
599
+ text-align: center;
600
+ font-size: 10px;
601
+ color: var(--jp-ui-font-color2);
602
+ }
603
+
604
+ .jp-xtralab-NotebookDiff-cellBadge {
605
+ display: inline-flex;
606
+ align-items: center;
607
+ justify-content: center;
608
+ width: 18px;
609
+ height: 18px;
610
+ border-radius: 3px;
611
+ font-size: var(--jp-ui-font-size0);
612
+ font-weight: 600;
613
+ font-family: var(--jp-code-font-family);
614
+ background-color: var(--jp-layout-color1);
615
+ }
616
+
617
+ .jp-xtralab-NotebookDiff-cellBadge[data-kind='added'] {
618
+ color: var(--jp-success-color1);
619
+ }
620
+
621
+ .jp-xtralab-NotebookDiff-cellBadge[data-kind='removed'] {
622
+ color: var(--jp-error-color1);
623
+ }
624
+
625
+ .jp-xtralab-NotebookDiff-cellBadge[data-kind='modified'] {
626
+ color: var(--jp-warn-color1);
627
+ }
628
+
629
+ .jp-xtralab-NotebookDiff-cellBadge[data-kind='unchanged'] {
630
+ color: var(--jp-ui-font-color3);
631
+ }
632
+
633
+ .jp-xtralab-NotebookDiff-cellLabel {
634
+ flex: 1 1 auto;
635
+ font-weight: 500;
636
+ color: var(--jp-ui-font-color1);
637
+ }
638
+
639
+ .jp-xtralab-NotebookDiff-cellHint {
640
+ color: var(--jp-ui-font-color3);
641
+ font-size: var(--jp-ui-font-size0);
642
+ font-style: italic;
643
+ }
644
+
645
+ .jp-xtralab-NotebookDiff-cellBody {
646
+ display: flex;
647
+ flex-direction: column;
648
+ }
649
+
650
+ .jp-xtralab-NotebookDiff-cellEmpty {
651
+ padding: 8px 12px;
652
+ color: var(--jp-ui-font-color3);
653
+ font-style: italic;
654
+ font-size: var(--jp-ui-font-size0);
655
+ }
656
+
657
+ .jp-xtralab-NotebookDiff-subdiff {
658
+ display: flex;
659
+ flex-direction: column;
660
+ border-top: 1px solid var(--jp-border-color2);
661
+ }
662
+
663
+ .jp-xtralab-NotebookDiff-subdiff:first-child {
664
+ border-top: none;
665
+ }
666
+
667
+ .jp-xtralab-NotebookDiff-subdiffLabel {
668
+ padding: 4px 12px;
669
+ background-color: var(--jp-layout-color1);
670
+ color: var(--jp-ui-font-color2);
671
+ font-size: var(--jp-ui-font-size0);
672
+ text-transform: uppercase;
673
+ letter-spacing: 0.04em;
674
+ font-weight: 600;
675
+ border-bottom: 1px solid var(--jp-border-color3);
676
+ }
677
+
678
+ /*
679
+ * The verbatim source listing rendered when the user expands an unchanged
680
+ * cell. We don't pass it through @pierre/diffs because there is no diff —
681
+ * just the cell contents — but match the diff library's monospace rhythm
682
+ * so the surrounding cells still look uniform.
683
+ */
684
+ .jp-xtralab-NotebookDiff-unchangedSource {
685
+ margin: 0;
686
+ padding: 8px 12px;
687
+ font-family: var(--jp-code-font-family);
688
+ font-size: var(--jp-code-font-size);
689
+ color: var(--jp-content-font-color1, var(--jp-ui-font-color1));
690
+ white-space: pre-wrap;
691
+ word-break: break-word;
692
+ }
693
+
694
+ .jp-xtralab-NotebookDiff-unchangedRendered,
695
+ .jp-xtralab-NotebookDiff-unchangedOutputs {
696
+ padding: 8px 12px;
697
+ background-color: var(--jp-layout-color1);
698
+ }
699
+
700
+ .jp-xtralab-NotebookDiff-unchangedOutputs {
701
+ border-top: 1px solid var(--jp-border-color3);
702
+ }
703
+
704
+ /*
705
+ * Side-by-side panes used by both OutputsSection and MarkdownPreviewSection.
706
+ * The grid columns mirror the split-mode FileDiff above so the two halves
707
+ * read as the same left=old / right=new mental model the user is already
708
+ * tracking on the source diff.
709
+ */
710
+ .jp-xtralab-NotebookDiff-sideBySide {
711
+ display: flex;
712
+ flex-direction: column;
713
+ border-top: 1px solid var(--jp-border-color2);
714
+ }
715
+
716
+ .jp-xtralab-NotebookDiff-sideBySideGrid {
717
+ display: grid;
718
+ grid-template-columns: 1fr 1fr;
719
+ background-color: var(--jp-layout-color1);
720
+ }
721
+
722
+ .jp-xtralab-NotebookDiff-sideBySide[data-layout='single']
723
+ .jp-xtralab-NotebookDiff-sideBySideGrid {
724
+ grid-template-columns: 1fr;
725
+ }
726
+
727
+ /*
728
+ * Each pane takes one column. The data-side colored bar on the left edge
729
+ * matches the cell-block kind colors so the pane's role (old vs new) is
730
+ * clear even in dark theme where the diff library's column-tint is subtle.
731
+ */
732
+ .jp-xtralab-NotebookDiff-sidePane {
733
+ padding: 8px 12px;
734
+ min-width: 0;
735
+ overflow-x: auto;
736
+ background-color: var(--jp-layout-color1);
737
+ }
738
+
739
+ .jp-xtralab-NotebookDiff-sidePane[data-side='old'] {
740
+ border-right: 1px solid var(--jp-border-color3);
741
+ background-color: var(--jp-layout-color0, var(--jp-layout-color1));
742
+ }
743
+
744
+ .jp-xtralab-NotebookDiff-sidePane[data-side='new'] {
745
+ background-color: var(--jp-layout-color1);
746
+ }
747
+
748
+ /*
749
+ * Rendermime widgets bring their own padding/margin defaults; we constrain
750
+ * them to the pane width so a wide HTML output (table, image) doesn't push
751
+ * the grid out of shape.
752
+ */
753
+ .jp-xtralab-NotebookDiff-sidePane .jp-RenderedHTMLCommon,
754
+ .jp-xtralab-NotebookDiff-sidePane .jp-OutputArea {
755
+ max-width: 100%;
756
+ }
757
+
758
+ .jp-xtralab-NotebookDiff-sidePane .jp-OutputArea-output img {
759
+ max-width: 100%;
760
+ height: auto;
761
+ }
762
+
763
+ .jp-xtralab-NotebookDiff-fallbackText {
764
+ margin: 0;
765
+ font-family: var(--jp-code-font-family);
766
+ font-size: var(--jp-code-font-size);
767
+ color: var(--jp-content-font-color1, var(--jp-ui-font-color1));
768
+ white-space: pre-wrap;
769
+ word-break: break-word;
770
+ }