@bendyline/docblocks-react 2.7.7 → 2.7.8

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 (42) hide show
  1. package/THIRD_PARTY_NOTICES.txt +205 -35
  2. package/dist/{AiDiagrams-7KBAOXPB.js → AiDiagrams-2IKKSBAU.js} +5 -3
  3. package/dist/{AiEditorAssistant-4B2PFFOT.js → AiEditorAssistant-ANYGVG7P.js} +46 -6
  4. package/dist/AiImagePanel-OXWEFOBC.js +314 -0
  5. package/dist/{AiStudyDialog-JPVFFZBB.js → AiStudyDialog-T3FY74HY.js} +2 -2
  6. package/dist/{AudioExportDialog-EICCBSSE.js → AudioExportDialog-CBMSLQBS.js} +1 -1
  7. package/dist/DocumentConflictDialog-4R4QMKBT.js +217 -0
  8. package/dist/{ExportDialog-EYDGTJ3S.js → ExportDialog-FNFD53SY.js} +2 -2
  9. package/dist/{ExportToolbarControls-2XY2CKGH.js → ExportToolbarControls-ZOYH4I36.js} +108 -71
  10. package/dist/{GitUI-F3CNBURE.js → GitUI-3FANM7I3.js} +88 -155
  11. package/dist/{KeyboardShortcutsDialog-HVKDFP5Z.js → KeyboardShortcutsDialog-7XJTDIX2.js} +1 -1
  12. package/dist/{PresentationMaker-VYQKNL3L.js → PresentationMaker-COLTVMTS.js} +3 -3
  13. package/dist/{QuickOpenDialog-3QEX7RZG.js → QuickOpenDialog-U2FWCEPA.js} +1 -1
  14. package/dist/{Settings-CfhY489G.d.ts → Settings-ButIB78y.d.ts} +20 -4
  15. package/dist/{ShareDialog-PF7D7ORP.js → ShareDialog-WOWHI6YI.js} +1 -1
  16. package/dist/{SpeechToolbarControl-E6OSJGHL.js → SpeechToolbarControl-BZW6IVZM.js} +1 -1
  17. package/dist/{TextFromNarration-ME6FAYWO.js → TextFromNarration-6BYTUKVZ.js} +2 -2
  18. package/dist/chunk-27E2OON2.js +90 -0
  19. package/dist/{chunk-5O5YTOXG.js → chunk-5YMULR6A.js} +13 -1
  20. package/dist/{chunk-5OIHB3SR.js → chunk-A7BK6QFL.js} +362 -25
  21. package/dist/{chunk-T2PA7QEF.js → chunk-BGA5UVKL.js} +58 -17
  22. package/dist/{chunk-N7AKLJPY.js → chunk-CXLXGFG2.js} +16 -8
  23. package/dist/{chunk-7CSBRAMT.js → chunk-F7TR5EKX.js} +8 -6
  24. package/dist/chunk-HIKMOKBQ.js +37 -0
  25. package/dist/chunk-OW6JWRAA.js +66 -0
  26. package/dist/{chunk-BNKIPCXO.js → chunk-QXBV3G6T.js} +5 -3
  27. package/dist/{chunk-7HBKKXRV.js → chunk-TN7BY5N3.js} +722 -281
  28. package/dist/{chunk-VJPGZCFS.js → chunk-UYJCL6OW.js} +4 -2
  29. package/dist/{chunk-G63YXKBC.js → chunk-WDNE5TI3.js} +13 -2
  30. package/dist/{chunk-KBUHWZCF.js → chunk-YX275NPE.js} +1 -1
  31. package/dist/editor.js +3 -3
  32. package/dist/export/index.d.ts +16 -162
  33. package/dist/export/index.js +6 -4
  34. package/dist/image-save-D18dJrUr.d.ts +182 -0
  35. package/dist/index.d.ts +15 -11
  36. package/dist/index.js +1154 -964
  37. package/dist/{run-export-SPNNH32M.js → run-export-C3PLLWLS.js} +2 -2
  38. package/dist/settings/index.d.ts +1 -1
  39. package/dist/settings/index.js +3 -2
  40. package/package.json +8 -8
  41. package/src/styles/docblocks.css +302 -10
  42. package/dist/DocumentConflictDialog-DZ2BV2IH.js +0 -111
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  exporterThemeId,
3
3
  runExport
4
- } from "./chunk-7CSBRAMT.js";
4
+ } from "./chunk-F7TR5EKX.js";
5
5
  import {
6
6
  buildExportFilename
7
- } from "./chunk-5O5YTOXG.js";
7
+ } from "./chunk-5YMULR6A.js";
8
8
  import "./chunk-6MSHXQNB.js";
9
9
  export {
10
10
  buildExportFilename,
@@ -1,4 +1,4 @@
1
- export { A as AccentColor, a as AccentColorSettings, b as AccentColorSettingsProps, c as AiSettingsControls, d as AiSettingsControlsProps, D as DEFAULT_INTERFACE_FONT, e as DEFAULT_PROOFING_PREFERENCES, f as DEFAULT_WRITE_CANVAS_FONT_SCHEME, I as InterfaceFontPreference, g as InterfaceFontSettings, h as InterfaceFontSettingsProps, P as ProofingPreferences, i as ProofingSettingsControls, j as ProofingSettingsControlsProps, S as SettingsDialog, k as SettingsDialogProps, T as ThemePreference, l as ThemeSettings, m as ThemeSettingsProps, W as WRITE_CANVAS_FONT_SCHEMES, n as WriteCanvasFontScheme, o as WriteCanvasFontSchemeGroup, p as WriteCanvasFontSchemeOption, q as WriteCanvasPreferences, r as WriteCanvasSettingsControls, s as WriteCanvasSettingsControlsProps, t as loadInterfaceFont, u as loadProofingPreferences, v as resolveWriteCanvasFonts, w as saveInterfaceFont, x as saveProofingPreferences } from '../Settings-CfhY489G.js';
1
+ export { A as AccentColor, a as AccentColorSettings, b as AccentColorSettingsProps, c as AiSettingsControls, d as AiSettingsControlsProps, D as DEFAULT_INTERFACE_FONT, e as DEFAULT_PROOFING_PREFERENCES, f as DEFAULT_WRITE_CANVAS_FONT_SCHEME, I as InterfaceFontPreference, g as InterfaceFontSettings, h as InterfaceFontSettingsProps, P as ProofingPreferences, i as ProofingSettingsControls, j as ProofingSettingsControlsProps, S as SettingsDialog, k as SettingsDialogProps, l as SettingsSection, T as ThemePreference, m as ThemeSettings, n as ThemeSettingsProps, o as WRITE_CANVAS_FONT_SCHEMES, p as WriteCanvasFontScheme, q as WriteCanvasFontSchemeGroup, r as WriteCanvasFontSchemeOption, W as WriteCanvasPreferences, s as WriteCanvasSettingsControls, t as WriteCanvasSettingsControlsProps, u as loadInterfaceFont, v as loadProofingPreferences, w as resolveWriteCanvasFonts, x as saveInterfaceFont, y as saveProofingPreferences } from '../Settings-ButIB78y.js';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import { WorkspaceSettings } from '@bendyline/docblocks/workspace-settings';
4
4
  import '@bendyline/docblocks/host';
@@ -16,9 +16,10 @@ import {
16
16
  resolveWriteCanvasFonts,
17
17
  saveInterfaceFont,
18
18
  saveProofingPreferences
19
- } from "../chunk-7HBKKXRV.js";
19
+ } from "../chunk-TN7BY5N3.js";
20
+ import "../chunk-OW6JWRAA.js";
20
21
  import "../chunk-TBLZBNQF.js";
21
- import "../chunk-VJPGZCFS.js";
22
+ import "../chunk-UYJCL6OW.js";
22
23
  export {
23
24
  AccentColorSettings,
24
25
  AiSettingsControls,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bendyline/docblocks-react",
3
- "version": "2.7.7",
3
+ "version": "2.7.8",
4
4
  "description": "React components for DocBlocks — file explorer, workspace picker, and editor shell",
5
5
  "license": "MIT",
6
6
  "author": "Bendyline",
@@ -85,14 +85,14 @@
85
85
  }
86
86
  },
87
87
  "dependencies": {
88
- "@bendyline/docblocks": "2.7.7",
89
- "@bendyline/squisq": "2.13.3",
88
+ "@bendyline/docblocks": "2.7.8",
89
+ "@bendyline/squisq": "2.13.6",
90
90
  "@bendyline/squisq-calc": "2.11.2",
91
- "@bendyline/squisq-editor-react": "2.13.5",
92
- "@bendyline/squisq-formats": "2.8.4",
93
- "@bendyline/squisq-react": "2.12.12",
94
- "@bendyline/squisq-video": "2.4.9",
95
- "@bendyline/squisq-video-react": "2.5.13",
91
+ "@bendyline/squisq-editor-react": "2.13.11",
92
+ "@bendyline/squisq-formats": "2.8.7",
93
+ "@bendyline/squisq-react": "2.12.18",
94
+ "@bendyline/squisq-video": "2.4.12",
95
+ "@bendyline/squisq-video-react": "2.5.19",
96
96
  "lucide-react": "1.52.0",
97
97
  "qrcode": "1.5.4"
98
98
  },
@@ -1631,12 +1631,11 @@
1631
1631
  visibility: visible;
1632
1632
  transition-delay: 0s;
1633
1633
  /* `transform: none`, not `translateX(0)`. ANY non-none transform makes this
1634
- element the containing block for `position: fixed` descendants, and the
1635
- modal overlay (.db-dialog-overlay, `position: fixed; inset: 0`) is rendered
1636
- inside the sidebar rather than portalled to <body>. With a transform here
1637
- every dialog opened from the app menu is sized and clipped to the drawer
1638
- instead of the viewport. Removing it once the drawer is open is visually
1639
- identical, because progress is 1 and translateX(0) moves nothing. */
1634
+ element the containing block for `position: fixed` descendants, which
1635
+ sizes and clips anything fixed inside the drawer to the drawer instead of
1636
+ the viewport. (Dialogs portal to <body> and are immune.) Removing it once
1637
+ the drawer is open is visually identical, because progress is 1 and
1638
+ translateX(0) moves nothing. */
1640
1639
  transform: none;
1641
1640
  }
1642
1641
 
@@ -2355,9 +2354,12 @@ html:has(.db-shell--mobile) .squisq-toolbar-overflow-menu {
2355
2354
  margin-bottom: 0;
2356
2355
  }
2357
2356
 
2357
+ /* A link inside running text is underlined: the accent alone sits under the
2358
+ 3:1 against the surrounding text that WCAG 1.4.1 asks for. */
2358
2359
  .db-dialog-body a {
2359
2360
  color: var(--db-accent);
2360
- text-decoration: none;
2361
+ text-decoration: underline;
2362
+ text-underline-offset: 0.15em;
2361
2363
  }
2362
2364
 
2363
2365
  .db-dialog-body a:hover {
@@ -2373,6 +2375,11 @@ html:has(.db-shell--mobile) .squisq-toolbar-overflow-menu {
2373
2375
  gap: 6px 16px;
2374
2376
  }
2375
2377
 
2378
+ /* The row holds nothing but links, so color alone marks them here. */
2379
+ .db-dialog-links a {
2380
+ text-decoration: none;
2381
+ }
2382
+
2376
2383
  .db-about-version {
2377
2384
  display: flex;
2378
2385
  align-items: center;
@@ -2400,6 +2407,113 @@ html:has(.db-shell--mobile) .squisq-toolbar-overflow-menu {
2400
2407
 
2401
2408
  /* ── Settings Dialog ─────────────────────────────────────────── */
2402
2409
 
2410
+ /* Sectioned Settings: a tab rail beside the open section, or a dropdown above
2411
+ it on phones and portrait tablets. The dialog keeps one height, so changing
2412
+ sections never resizes it under the pointer, and each section scrolls on
2413
+ its own, so returning to one finds it where it was left. The panel keeps
2414
+ the 520px measure the single-column dialog had. */
2415
+ .db-dialog.db-settings-dialog--sectioned {
2416
+ width: 740px;
2417
+ height: min(660px, calc(100vh - 32px));
2418
+ height: min(660px, calc(100dvh - 32px));
2419
+ }
2420
+
2421
+ .db-dialog-body.db-settings-dialog-body--sectioned {
2422
+ flex: 1;
2423
+ display: flex;
2424
+ padding: 0;
2425
+ overflow: hidden;
2426
+ }
2427
+
2428
+ .db-settings-sections {
2429
+ flex: 1;
2430
+ display: flex;
2431
+ min-width: 0;
2432
+ min-height: 0;
2433
+ }
2434
+
2435
+ .db-settings-sections--dropdown {
2436
+ flex-direction: column;
2437
+ }
2438
+
2439
+ .db-settings-tabs {
2440
+ flex: 0 0 180px;
2441
+ display: flex;
2442
+ flex-direction: column;
2443
+ gap: 2px;
2444
+ box-sizing: border-box;
2445
+ padding: 12px 8px;
2446
+ border-right: 1px solid var(--db-border);
2447
+ overflow-y: auto;
2448
+ }
2449
+
2450
+ .db-settings-tab {
2451
+ position: relative;
2452
+ min-height: var(--db-row-min-height);
2453
+ padding: 7px 12px;
2454
+ border: none;
2455
+ border-radius: 6px;
2456
+ background: none;
2457
+ color: var(--db-text-secondary);
2458
+ font: inherit;
2459
+ font-size: 13px;
2460
+ text-align: left;
2461
+ cursor: pointer;
2462
+ }
2463
+
2464
+ .db-settings-tab:hover {
2465
+ background: var(--db-bg-hover);
2466
+ color: var(--db-text);
2467
+ }
2468
+
2469
+ /* The accent bar is the vertical counterpart of the underline the editor's
2470
+ Write/Source tabs carry. */
2471
+ .db-settings-tab--selected,
2472
+ .db-settings-tab--selected:hover {
2473
+ background: var(--db-bg-selected);
2474
+ color: var(--db-text-on-selected);
2475
+ font-weight: 600;
2476
+ }
2477
+
2478
+ .db-settings-tab--selected::before {
2479
+ content: '';
2480
+ position: absolute;
2481
+ top: 7px;
2482
+ bottom: 7px;
2483
+ left: 0;
2484
+ width: 3px;
2485
+ border-radius: 2px;
2486
+ background: var(--db-accent);
2487
+ }
2488
+
2489
+ .db-settings-tab:focus-visible,
2490
+ .db-settings-panel:focus-visible {
2491
+ outline: 2px solid var(--db-focus);
2492
+ outline-offset: -2px;
2493
+ }
2494
+
2495
+ .db-settings-section-picker {
2496
+ flex: none;
2497
+ padding: 12px 20px;
2498
+ border-bottom: 1px solid var(--db-border);
2499
+ }
2500
+
2501
+ .db-settings-section-select {
2502
+ font-weight: 600;
2503
+ }
2504
+
2505
+ .db-settings-panel {
2506
+ flex: 1;
2507
+ min-width: 0;
2508
+ min-height: 0;
2509
+ overflow-y: auto;
2510
+ padding: 16px 20px 20px;
2511
+ }
2512
+
2513
+ .db-settings-panel[hidden] {
2514
+ display: none;
2515
+ }
2516
+
2403
2517
  .db-settings-fieldset {
2404
2518
  border: none;
2405
2519
  margin: 0;
@@ -6159,6 +6273,18 @@ html:has(.db-shell) :is(.squisq-view-menu-checkbox, .squisq-view-menu-radio) {
6159
6273
  transform: translateX(-50%);
6160
6274
  }
6161
6275
 
6276
+ .db-document-conflict-text {
6277
+ display: flex;
6278
+ flex-direction: column;
6279
+ gap: 4px;
6280
+ min-width: 0;
6281
+ }
6282
+
6283
+ .db-document-conflict-details {
6284
+ color: var(--db-text-muted);
6285
+ font-size: 12px;
6286
+ }
6287
+
6162
6288
  .db-document-conflict-actions {
6163
6289
  display: flex;
6164
6290
  flex: none;
@@ -6179,15 +6305,23 @@ html:has(.db-shell) :is(.squisq-view-menu-checkbox, .squisq-view-menu-radio) {
6179
6305
  outline-offset: 2px;
6180
6306
  }
6181
6307
 
6308
+ /* Three panes need more than the standard full dialog's 1100px. */
6309
+ .db-conflict-dialog.db-dialog--full {
6310
+ width: min(1600px, 96vw);
6311
+ }
6312
+
6313
+ /* Each version as a page, with the source diff between them. Monaco drops
6314
+ to its inline diff by itself when the middle pane is too narrow for two. */
6182
6315
  .db-conflict-columns {
6183
6316
  display: grid;
6184
- grid-template-columns: repeat(2, minmax(0, 1fr));
6317
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr) minmax(0, 1fr);
6185
6318
  gap: 16px;
6186
6319
  flex: 1;
6187
6320
  min-height: 300px;
6188
6321
  }
6189
6322
 
6190
- .db-conflict-version {
6323
+ .db-conflict-version,
6324
+ .db-conflict-diff {
6191
6325
  display: flex;
6192
6326
  flex-direction: column;
6193
6327
  min-width: 0;
@@ -6196,7 +6330,48 @@ html:has(.db-shell) :is(.squisq-view-menu-checkbox, .squisq-view-menu-radio) {
6196
6330
  border-radius: 8px;
6197
6331
  }
6198
6332
 
6199
- .db-conflict-version h3 {
6333
+ /* Two source columns need more of the width than one. */
6334
+ .db-conflict-columns--wide-diff {
6335
+ grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1fr);
6336
+ }
6337
+
6338
+ .db-conflict-diff .db-git-diff-host {
6339
+ min-height: 160px;
6340
+ }
6341
+
6342
+ .db-conflict-diff-header {
6343
+ display: flex;
6344
+ flex-wrap: wrap;
6345
+ align-items: center;
6346
+ justify-content: space-between;
6347
+ gap: 4px 12px;
6348
+ }
6349
+
6350
+ .db-conflict-diff-view {
6351
+ display: flex;
6352
+ align-items: center;
6353
+ gap: 6px;
6354
+ color: var(--db-text-muted);
6355
+ font-size: 12px;
6356
+ }
6357
+
6358
+ .db-conflict-diff-view select {
6359
+ min-height: var(--db-target-min, 32px);
6360
+ padding: 0 6px;
6361
+ color: var(--db-text);
6362
+ background: var(--db-bg);
6363
+ border: 1px solid var(--db-border-strong);
6364
+ border-radius: 5px;
6365
+ font: inherit;
6366
+ }
6367
+
6368
+ .db-conflict-diff-view select:focus-visible {
6369
+ outline: 2px solid var(--db-accent);
6370
+ outline-offset: 2px;
6371
+ }
6372
+
6373
+ .db-conflict-version h3,
6374
+ .db-conflict-diff h3 {
6200
6375
  margin: 0;
6201
6376
  color: var(--db-text);
6202
6377
  font-size: 15px;
@@ -6225,6 +6400,13 @@ html:has(.db-shell) :is(.squisq-view-menu-checkbox, .squisq-view-menu-radio) {
6225
6400
  resize: none;
6226
6401
  }
6227
6402
 
6403
+ /* The page brings its own type and (inline) theme background; thin page
6404
+ margins hug the content, so the frame supplies the inset. */
6405
+ .db-conflict-preview--rendered {
6406
+ padding: 12px 16px;
6407
+ font: inherit;
6408
+ }
6409
+
6228
6410
  .db-conflict-consequence {
6229
6411
  margin: 12px 0;
6230
6412
  font-size: 12px;
@@ -6870,7 +7052,12 @@ html:has(.db-shell) :is(.squisq-view-menu-checkbox, .squisq-view-menu-radio) {
6870
7052
  background: var(--db-bg-raised);
6871
7053
  }
6872
7054
 
7055
+ /* As tall as the close button so the title centers on the same line as the
7056
+ ×, while the findings count still stacks underneath. */
6873
7057
  .db-ai-review-header h2 {
7058
+ display: flex;
7059
+ align-items: center;
7060
+ min-height: var(--db-target-min);
6874
7061
  margin: 0;
6875
7062
  color: var(--db-text);
6876
7063
  font-size: 15px;
@@ -7410,6 +7597,107 @@ html:has(.db-shell) :is(.squisq-view-menu-checkbox, .squisq-view-menu-radio) {
7410
7597
  max-height: 420px;
7411
7598
  }
7412
7599
 
7600
+ /* ── AI image generation: the Generate image panel ── */
7601
+ .db-ai-image-form {
7602
+ padding: 12px 14px 0;
7603
+ }
7604
+
7605
+ .db-ai-image-aspects {
7606
+ display: flex;
7607
+ flex-wrap: wrap;
7608
+ gap: 6px;
7609
+ margin-bottom: 12px;
7610
+ }
7611
+
7612
+ .db-ai-review-panel .db-ai-image-aspects button[aria-checked='true'] {
7613
+ border-color: var(--db-bg-selected);
7614
+ background: var(--db-bg-selected);
7615
+ color: var(--db-text-on-selected);
7616
+ }
7617
+
7618
+ .db-ai-image-actions,
7619
+ .db-ai-image-allow {
7620
+ padding-left: 0;
7621
+ padding-right: 0;
7622
+ }
7623
+
7624
+ .db-ai-image-code {
7625
+ display: block;
7626
+ margin-top: 8px;
7627
+ color: var(--db-text);
7628
+ font:
7629
+ 600 20px/1.2 ui-monospace,
7630
+ SFMono-Regular,
7631
+ Consolas,
7632
+ monospace;
7633
+ letter-spacing: 0.08em;
7634
+ }
7635
+
7636
+ .db-ai-image-results {
7637
+ margin-bottom: 14px;
7638
+ }
7639
+
7640
+ .db-ai-image-prompt {
7641
+ margin: 0 0 8px;
7642
+ color: var(--db-text);
7643
+ overflow-wrap: anywhere;
7644
+ }
7645
+
7646
+ /* A raster image ignores the dark theme, so it sits on a light frame. */
7647
+ .db-ai-image-preview {
7648
+ display: block;
7649
+ width: 100%;
7650
+ height: auto;
7651
+ margin: 4px 0 10px;
7652
+ border: 1px solid var(--db-border);
7653
+ border-radius: 6px;
7654
+ background: #fff;
7655
+ }
7656
+
7657
+ .db-ai-image-alt {
7658
+ margin-bottom: 6px;
7659
+ font-weight: 400;
7660
+ }
7661
+
7662
+ .db-ai-image-alt input {
7663
+ min-height: var(--db-target-min);
7664
+ padding: 0 8px;
7665
+ border: 1px solid var(--db-input-border);
7666
+ border-radius: 5px;
7667
+ background: var(--db-bg-subtle);
7668
+ color: var(--db-text);
7669
+ font: 400 var(--db-input-font-size) / 1.4 var(--db-ui-font);
7670
+ }
7671
+
7672
+ .db-ai-image-result-actions {
7673
+ padding: 6px 0 0;
7674
+ }
7675
+
7676
+ /*
7677
+ * Illustrate's design graphics: raster pictures, so a light frame in dark mode
7678
+ * too. A picture scales to fit the preview's height rather than scrolling in
7679
+ * it the way a tall diagram does, so a portrait poster is seen whole.
7680
+ */
7681
+ .db-ai-design-preview {
7682
+ display: flex;
7683
+ justify-content: center;
7684
+ overflow: hidden;
7685
+ background: #fff;
7686
+ }
7687
+
7688
+ .db-ai-design-preview img {
7689
+ display: block;
7690
+ max-width: 100%;
7691
+ /* The preview's max-height, less its border. */
7692
+ max-height: 338px;
7693
+ width: auto;
7694
+ height: auto;
7695
+ }
7696
+
7697
+ .db-ai-diagram-dialog .db-ai-design-preview img {
7698
+ max-height: 418px;
7699
+ }
7700
+
7413
7701
  .db-ai-diagram-source {
7414
7702
  max-height: 220px;
7415
7703
  overflow: auto;
@@ -8079,6 +8367,10 @@ button.db-git-file-row:hover {
8079
8367
  font-size: 12.5px;
8080
8368
  }
8081
8369
 
8370
+ .db-export-error-action {
8371
+ margin-top: 8px;
8372
+ }
8373
+
8082
8374
  .db-git-hint {
8083
8375
  color: var(--db-text-muted);
8084
8376
  font-size: 12px;
@@ -1,111 +0,0 @@
1
- import {
2
- Dialog
3
- } from "./chunk-VJPGZCFS.js";
4
-
5
- // src/DocBlocksShell/DocumentConflictDialog.tsx
6
- import { useEffect, useState } from "react";
7
- import { jsx, jsxs } from "react/jsx-runtime";
8
- function formattedTime(value) {
9
- if (value === null || value === void 0) return null;
10
- const date = new Date(value);
11
- return Number.isFinite(date.getTime()) ? date.toLocaleString() : null;
12
- }
13
- function DocumentConflictDialog({
14
- conflict,
15
- readSavedFile,
16
- onUseLocal,
17
- onUseSaved,
18
- onClose
19
- }) {
20
- const [savedFile, setSavedFile] = useState(null);
21
- const [busy, setBusy] = useState(false);
22
- const [error, setError] = useState(null);
23
- useEffect(() => {
24
- let disposed = false;
25
- void readSavedFile().then(
26
- (file) => {
27
- if (!disposed) setSavedFile(file);
28
- },
29
- () => {
30
- if (!disposed) setSavedFile(null);
31
- }
32
- );
33
- return () => {
34
- disposed = true;
35
- };
36
- }, [readSavedFile, conflict.targetKey, conflict.externalContent, conflict.externalVersion]);
37
- const capturedAt = formattedTime(conflict.recoveredDraftCapturedAt);
38
- const savedAt = savedFile?.content === conflict.externalContent ? formattedTime(savedFile?.lastModified) : null;
39
- const localLabel = conflict.recoveredDraft ? "Recovery draft" : "Your unsaved version";
40
- const choose = async (resolve) => {
41
- if (busy) return;
42
- setBusy(true);
43
- setError(null);
44
- try {
45
- if (await resolve()) onClose();
46
- else setError("Could not resolve this conflict. Both versions are still available.");
47
- } catch (cause) {
48
- setError(cause instanceof Error ? cause.message : "Could not resolve this conflict.");
49
- } finally {
50
- setBusy(false);
51
- }
52
- };
53
- return /* @__PURE__ */ jsxs(
54
- Dialog,
55
- {
56
- title: "Compare document versions",
57
- size: "full",
58
- className: "db-conflict-dialog",
59
- onClose: () => {
60
- if (!busy) onClose();
61
- },
62
- closeOnBackdrop: !busy,
63
- footer: /* @__PURE__ */ jsx("button", { type: "button", disabled: busy, onClick: onClose, children: "Decide later" }),
64
- children: [
65
- /* @__PURE__ */ jsxs("p", { children: [
66
- conflict.recoveredDraft ? "This draft was recovered from a previous session. The saved file may contain newer edits." : "The saved file changed while you had unsaved edits.",
67
- " ",
68
- "Compare the document text before choosing. Neither version changes until you choose."
69
- ] }),
70
- /* @__PURE__ */ jsxs("div", { className: "db-conflict-columns", "aria-busy": busy, children: [
71
- /* @__PURE__ */ jsxs("section", { className: "db-conflict-version", "aria-label": localLabel, children: [
72
- /* @__PURE__ */ jsx("h3", { children: localLabel }),
73
- /* @__PURE__ */ jsx("p", { className: "db-conflict-metadata", children: conflict.recoveredDraft ? capturedAt ? `Recovery copy captured: ${capturedAt}` : "Recovery capture time unavailable" : "Not saved in this session" }),
74
- /* @__PURE__ */ jsx(
75
- "textarea",
76
- {
77
- className: "db-conflict-preview",
78
- "aria-label": `${localLabel} preview`,
79
- value: conflict.localContent,
80
- readOnly: true,
81
- spellCheck: false
82
- }
83
- ),
84
- /* @__PURE__ */ jsx("p", { className: "db-conflict-consequence", children: "Replaces the saved file with the draft shown above." }),
85
- /* @__PURE__ */ jsx("button", { type: "button", disabled: busy, onClick: () => void choose(onUseLocal), children: conflict.recoveredDraft ? "Replace file with draft" : "Keep mine" })
86
- ] }),
87
- /* @__PURE__ */ jsxs("section", { className: "db-conflict-version", "aria-label": "Saved file", children: [
88
- /* @__PURE__ */ jsx("h3", { children: "Saved file" }),
89
- /* @__PURE__ */ jsx("p", { className: "db-conflict-metadata", children: conflict.externalContent === null ? "File was deleted outside DocBlocks" : savedAt ? `File last modified: ${savedAt}` : "File modification time unavailable" }),
90
- conflict.externalContent === null ? /* @__PURE__ */ jsx("div", { className: "db-conflict-preview", children: "The saved file no longer exists." }) : /* @__PURE__ */ jsx(
91
- "textarea",
92
- {
93
- className: "db-conflict-preview",
94
- "aria-label": "Saved file preview",
95
- value: conflict.externalContent,
96
- readOnly: true,
97
- spellCheck: false
98
- }
99
- ),
100
- /* @__PURE__ */ jsx("p", { className: "db-conflict-consequence", children: conflict.externalContent === null ? "Discards the draft and closes this document." : "Discards the draft and opens the saved file shown above." }),
101
- /* @__PURE__ */ jsx("button", { type: "button", disabled: busy, onClick: () => void choose(onUseSaved), children: conflict.externalContent === null ? "Accept deletion" : "Use saved file" })
102
- ] })
103
- ] }),
104
- error && /* @__PURE__ */ jsx("p", { role: "alert", children: error })
105
- ]
106
- }
107
- );
108
- }
109
- export {
110
- DocumentConflictDialog as default
111
- };