@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
package/dist/index.js CHANGED
@@ -1,9 +1,12 @@
1
+ import {
2
+ createSpeechInputProvider
3
+ } from "./chunk-QXBV3G6T.js";
1
4
  import {
2
5
  ProgressivePlayer
3
6
  } from "./chunk-BZRYQENB.js";
4
7
  import {
5
8
  useConfirmDialog
6
- } from "./chunk-KBUHWZCF.js";
9
+ } from "./chunk-YX275NPE.js";
7
10
  import {
8
11
  BackupIcon,
9
12
  FolderIcon,
@@ -18,9 +21,6 @@ import {
18
21
  SplitViewIcon,
19
22
  WorkspaceIcon
20
23
  } from "./chunk-KHQ44ZFA.js";
21
- import {
22
- createSpeechInputProvider
23
- } from "./chunk-BNKIPCXO.js";
24
24
  import {
25
25
  sharedDocumentFilename
26
26
  } from "./chunk-SPUPWCSI.js";
@@ -51,13 +51,13 @@ import {
51
51
  } from "./chunk-KWG6UP5O.js";
52
52
  import {
53
53
  runExport
54
- } from "./chunk-7CSBRAMT.js";
54
+ } from "./chunk-F7TR5EKX.js";
55
55
  import {
56
56
  createImageSaveOutput
57
57
  } from "./chunk-UONFWKJ7.js";
58
58
  import {
59
59
  buildExportFilename
60
- } from "./chunk-5O5YTOXG.js";
60
+ } from "./chunk-5YMULR6A.js";
61
61
  import {
62
62
  createLocalProofingIgnoreStore
63
63
  } from "./chunk-DUKTAKB4.js";
@@ -71,23 +71,34 @@ import {
71
71
  DEFAULT_WRITE_CANVAS_PREFERENCES,
72
72
  InterfaceFontSettings,
73
73
  ProofingSettingsControls,
74
+ SIDEBAR_COLLAPSE_THRESHOLD,
75
+ SIDEBAR_WIDTH_DEFAULT,
76
+ SIDEBAR_WIDTH_MAX,
77
+ SIDEBAR_WIDTH_MIN,
74
78
  SettingsDialog,
75
79
  ThemeSettings,
76
80
  WRITE_CANVAS_FONT_SCHEMES,
77
81
  WorkspaceSettingsControls,
78
82
  WriteCanvasSettingsControls,
83
+ classifyFormFactor,
84
+ formFactorDataAttributes,
85
+ formatModelSize,
86
+ isInstalledDisplayMode,
79
87
  loadAccentColor,
80
88
  loadInterfaceFont,
81
89
  loadProofingPreferences,
82
90
  loadThemePreference,
83
91
  loadWriteCanvasPreferences,
92
+ resolveLayoutMode,
84
93
  resolveWriteCanvasFonts,
85
94
  saveAccentColor,
86
95
  saveInterfaceFont,
87
96
  saveProofingPreferences,
88
97
  saveThemePreference,
89
- saveWriteCanvasPreferences
90
- } from "./chunk-7HBKKXRV.js";
98
+ saveWriteCanvasPreferences,
99
+ useMediaQuery
100
+ } from "./chunk-TN7BY5N3.js";
101
+ import "./chunk-OW6JWRAA.js";
91
102
  import "./chunk-TBLZBNQF.js";
92
103
  import {
93
104
  FindButton,
@@ -101,17 +112,17 @@ import {
101
112
  matchShortcut,
102
113
  shortcutLabel
103
114
  } from "./chunk-ACQF63SB.js";
104
- import "./chunk-T2PA7QEF.js";
115
+ import "./chunk-BGA5UVKL.js";
105
116
  import {
106
117
  buildIssueReportUrl,
107
118
  displayBuildDate,
108
119
  localDateStamp,
109
120
  openExternalUrl
110
- } from "./chunk-N7AKLJPY.js";
121
+ } from "./chunk-CXLXGFG2.js";
111
122
  import "./chunk-K4I3NJFL.js";
112
123
  import {
113
124
  ExportDialog
114
- } from "./chunk-G63YXKBC.js";
125
+ } from "./chunk-WDNE5TI3.js";
115
126
  import "./chunk-H3BK5MK6.js";
116
127
  import {
117
128
  DEFAULT_OPTIONS,
@@ -120,7 +131,7 @@ import {
120
131
  import {
121
132
  Dialog,
122
133
  dismissTopmostDialog
123
- } from "./chunk-VJPGZCFS.js";
134
+ } from "./chunk-UYJCL6OW.js";
124
135
 
125
136
  // src/FileExplorer/FileExplorer.tsx
126
137
  import { useCallback as useCallback5, useEffect as useEffect5, useMemo, useRef as useRef5, useState as useState4 } from "react";
@@ -3805,9 +3816,9 @@ async function prepareHostLifecycle(session, request) {
3805
3816
 
3806
3817
  // src/DocBlocksShell/DocBlocksShell.tsx
3807
3818
  import {
3808
- useState as useState24,
3819
+ useState as useState25,
3809
3820
  useCallback as useCallback19,
3810
- useEffect as useEffect30,
3821
+ useEffect as useEffect31,
3811
3822
  useLayoutEffect as useLayoutEffect4,
3812
3823
  useRef as useRef21,
3813
3824
  useMemo as useMemo6,
@@ -3839,7 +3850,7 @@ import {
3839
3850
  import { createMediaProviderFromContainer } from "@bendyline/squisq/storage";
3840
3851
  import {
3841
3852
  getDocBlocksHost,
3842
- getHostEnvironment as getHostEnvironment2,
3853
+ getHostEnvironment as getHostEnvironment3,
3843
3854
  hasDocBlocksHost,
3844
3855
  hostSupports as hostSupports3,
3845
3856
  maybeGetDocBlocksHost as maybeGetDocBlocksHost5
@@ -3863,26 +3874,306 @@ import {
3863
3874
  } from "@bendyline/docblocks/workspace";
3864
3875
 
3865
3876
  // src/AppMenu/AppMenu.tsx
3866
- import { useState as useState8, useCallback as useCallback9, useRef as useRef9, useEffect as useEffect9 } from "react";
3877
+ import { useState as useState9, useCallback as useCallback9, useRef as useRef9, useEffect as useEffect10 } from "react";
3867
3878
  import {
3868
- getHostEnvironment
3879
+ getHostEnvironment as getHostEnvironment2
3869
3880
  } from "@bendyline/docblocks/host";
3870
3881
 
3871
- // src/Settings/SpeechSettings.tsx
3872
- import { useCallback as useCallback7, useEffect as useEffect7, useId as useId2, useRef as useRef7, useState as useState6 } from "react";
3873
-
3874
- // src/Speech/format.ts
3875
- function formatModelSize(bytes) {
3876
- const gigabytes = bytes / 1024 ** 3;
3877
- if (gigabytes >= 0.95) return `${gigabytes.toFixed(1)} GB`;
3878
- return `${Math.max(1, Math.round(bytes / 1024 ** 2))} MB`;
3879
- }
3882
+ // src/Settings/AppSettingsDialog.tsx
3883
+ import { useEffect as useEffect9, useState as useState8 } from "react";
3884
+ import {
3885
+ getHostEnvironment
3886
+ } from "@bendyline/docblocks/host";
3880
3887
 
3881
3888
  // src/Settings/SpeechSettings.tsx
3889
+ import { useId as useId2 } from "react";
3882
3890
  import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
3883
3891
  function readinessSentence(readiness, ready) {
3884
3892
  return readiness.state === "ready" ? ready : readiness.reason ?? "";
3885
3893
  }
3894
+ function DictationSettingsControls({ session }) {
3895
+ const { status, catalog, preferences, update } = session;
3896
+ const error = sectionError(session.failure, "stt");
3897
+ if (!status || !catalog || !preferences) {
3898
+ return /* @__PURE__ */ jsx7(SpeechSectionFallback, { legend: "Dictation", error });
3899
+ }
3900
+ const sttModels = catalog.models.filter((model) => model.kind === "stt");
3901
+ const installedStt = sttModels.filter((model) => model.installed);
3902
+ const appBytes = appModelBytes(sttModels);
3903
+ return /* @__PURE__ */ jsxs6("fieldset", { className: "db-settings-fieldset", children: [
3904
+ /* @__PURE__ */ jsx7("legend", { className: "db-settings-legend", children: "Dictation" }),
3905
+ /* @__PURE__ */ jsxs6("p", { className: "db-settings-hint", children: [
3906
+ "Dictation runs on this computer; your voice never leaves it. Models download only when you choose.",
3907
+ appBytes > 0 ? ` Dictation models are using ${formatModelSize(appBytes)}.` : ""
3908
+ ] }),
3909
+ /* @__PURE__ */ jsx7(SpeechErrorNotice, { error }),
3910
+ /* @__PURE__ */ jsx7("p", { className: "db-settings-hint", role: "status", "aria-live": "polite", children: readinessSentence(status.stt, "Ready. Use the microphone button in the toolbar.") }),
3911
+ installedStt.length > 1 && /* @__PURE__ */ jsxs6("label", { className: "db-settings-select", children: [
3912
+ /* @__PURE__ */ jsx7("span", { className: "db-settings-select-header", children: "Dictation model" }),
3913
+ /* @__PURE__ */ jsxs6(
3914
+ "select",
3915
+ {
3916
+ className: "db-settings-select-input",
3917
+ value: preferences.sttModel ?? "",
3918
+ onChange: (event) => void update({ sttModel: event.currentTarget.value || null }),
3919
+ children: [
3920
+ /* @__PURE__ */ jsx7("option", { value: "", children: "Recommended" }),
3921
+ installedStt.map((model) => /* @__PURE__ */ jsx7("option", { value: model.id, children: model.label }, model.id))
3922
+ ]
3923
+ }
3924
+ )
3925
+ ] }),
3926
+ /* @__PURE__ */ jsx7("ul", { className: "db-settings-speech-models", children: sttModels.map((model) => /* @__PURE__ */ jsx7(SpeechModelRow, { model, session }, model.id)) })
3927
+ ] });
3928
+ }
3929
+ function NarrationSettingsControls({ session }) {
3930
+ const speedId = useId2();
3931
+ const { status, catalog, preferences, previewing, update } = session;
3932
+ const error = sectionError(session.failure, "tts");
3933
+ if (!status || !catalog || !preferences) {
3934
+ return /* @__PURE__ */ jsx7(SpeechSectionFallback, { legend: "Narration", error });
3935
+ }
3936
+ const ttsModel = catalog.models.find((model) => model.kind === "tts") ?? null;
3937
+ const appBytes = ttsModel ? appModelBytes([ttsModel]) : 0;
3938
+ return /* @__PURE__ */ jsxs6("fieldset", { className: "db-settings-fieldset", children: [
3939
+ /* @__PURE__ */ jsx7("legend", { className: "db-settings-legend", children: "Narration" }),
3940
+ /* @__PURE__ */ jsxs6("p", { className: "db-settings-hint", children: [
3941
+ "Narration runs on this computer; your documents never leave it. Voices download only when you choose.",
3942
+ appBytes > 0 ? ` Narration voices are using ${formatModelSize(appBytes)}.` : ""
3943
+ ] }),
3944
+ /* @__PURE__ */ jsx7(SpeechErrorNotice, { error }),
3945
+ ttsModel ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
3946
+ /* @__PURE__ */ jsx7("p", { className: "db-settings-hint", role: "status", "aria-live": "polite", children: readinessSentence(status.tts, "Ready to read documents aloud.") }),
3947
+ /* @__PURE__ */ jsx7("ul", { className: "db-settings-speech-models", children: /* @__PURE__ */ jsx7(SpeechModelRow, { model: ttsModel, session }) })
3948
+ ] }) : /* @__PURE__ */ jsx7("p", { className: "db-settings-hint", children: "Narration is not available on this computer." }),
3949
+ ttsModel?.installed && /* @__PURE__ */ jsxs6(Fragment4, { children: [
3950
+ /* @__PURE__ */ jsxs6("label", { className: "db-settings-select", children: [
3951
+ /* @__PURE__ */ jsx7("span", { className: "db-settings-select-header", children: "Voice" }),
3952
+ /* @__PURE__ */ jsx7(
3953
+ "select",
3954
+ {
3955
+ className: "db-settings-select-input",
3956
+ value: preferences.voice ?? catalog.voices[0]?.id ?? "",
3957
+ onChange: (event) => void update({ voice: event.currentTarget.value }),
3958
+ children: catalog.voices.map((voice) => /* @__PURE__ */ jsxs6("option", { value: voice.id, children: [
3959
+ voice.label,
3960
+ " (",
3961
+ voice.language === "en-GB" ? "UK" : "US",
3962
+ voice.gender ? ` ${voice.gender}` : "",
3963
+ ")"
3964
+ ] }, voice.id))
3965
+ }
3966
+ )
3967
+ ] }),
3968
+ /* @__PURE__ */ jsxs6("label", { className: "db-settings-select", htmlFor: speedId, children: [
3969
+ /* @__PURE__ */ jsxs6("span", { className: "db-settings-select-header", children: [
3970
+ "Speed: ",
3971
+ preferences.speed.toFixed(2),
3972
+ "\xD7"
3973
+ ] }),
3974
+ /* @__PURE__ */ jsx7(
3975
+ "input",
3976
+ {
3977
+ id: speedId,
3978
+ type: "range",
3979
+ min: 0.5,
3980
+ max: 2,
3981
+ step: 0.05,
3982
+ value: preferences.speed,
3983
+ onChange: (event) => session.setSpeedDraft(Number(event.currentTarget.value)),
3984
+ onPointerUp: (event) => void update({ speed: Number(event.currentTarget.value) }),
3985
+ onKeyUp: (event) => void update({ speed: Number(event.currentTarget.value) })
3986
+ }
3987
+ )
3988
+ ] }),
3989
+ /* @__PURE__ */ jsx7(
3990
+ "button",
3991
+ {
3992
+ type: "button",
3993
+ className: "db-settings-action db-settings-action--secondary",
3994
+ onClick: () => previewing ? session.stopPreview() : session.startPreview(),
3995
+ children: previewing ? "Stop preview" : "Preview voice"
3996
+ }
3997
+ )
3998
+ ] })
3999
+ ] });
4000
+ }
4001
+ function SpeechModelRow({
4002
+ model,
4003
+ session
4004
+ }) {
4005
+ const { installing } = session;
4006
+ const busy = installing?.id === model.id;
4007
+ const progress = busy ? installing.progress : null;
4008
+ const percent = progress && progress.totalBytes ? Math.round(progress.receivedBytes / progress.totalBytes * 100) : null;
4009
+ return /* @__PURE__ */ jsxs6("li", { className: "db-settings-speech-model", children: [
4010
+ /* @__PURE__ */ jsxs6("div", { className: "db-settings-speech-model-text", children: [
4011
+ /* @__PURE__ */ jsxs6("span", { className: "db-settings-speech-model-name", children: [
4012
+ model.label,
4013
+ model.recommended ? " (recommended)" : ""
4014
+ ] }),
4015
+ /* @__PURE__ */ jsxs6("span", { className: "db-settings-hint", children: [
4016
+ model.description,
4017
+ " ",
4018
+ formatModelSize(model.downloadBytes),
4019
+ " \xB7",
4020
+ " ",
4021
+ /* @__PURE__ */ jsx7("a", { href: model.licenseUrl, target: "_blank", rel: "noreferrer", children: model.license }),
4022
+ model.source === "shared" ? " \xB7 Available from Gezel, no download needed" : model.sharedStorage ? " \xB7 Shared speech storage" : "",
4023
+ model.updateRequired ? " \xB7 Update required" : ""
4024
+ ] })
4025
+ ] }),
4026
+ busy ? /* @__PURE__ */ jsxs6("div", { className: "db-settings-ai-download-progress", role: "status", children: [
4027
+ /* @__PURE__ */ jsx7(
4028
+ "progress",
4029
+ {
4030
+ max: 100,
4031
+ value: percent ?? void 0,
4032
+ "aria-label": `${model.label} download progress`
4033
+ }
4034
+ ),
4035
+ /* @__PURE__ */ jsx7("span", { children: progress?.phase === "verifying" ? "Verifying\u2026" : percent === null ? "Starting\u2026" : `${percent}%` }),
4036
+ /* @__PURE__ */ jsx7(
4037
+ "button",
4038
+ {
4039
+ type: "button",
4040
+ className: "db-settings-action db-settings-action--secondary",
4041
+ onClick: session.cancelInstall,
4042
+ children: "Cancel"
4043
+ }
4044
+ )
4045
+ ] }) : model.source === "app" ? /* @__PURE__ */ jsx7(
4046
+ "button",
4047
+ {
4048
+ type: "button",
4049
+ className: "db-settings-action db-settings-action--secondary",
4050
+ disabled: installing !== null,
4051
+ onClick: () => void session.remove(model),
4052
+ children: "Remove"
4053
+ }
4054
+ ) : model.installed ? null : /* @__PURE__ */ jsxs6(Fragment4, { children: [
4055
+ /* @__PURE__ */ jsx7(
4056
+ "button",
4057
+ {
4058
+ type: "button",
4059
+ className: "db-settings-action",
4060
+ disabled: installing !== null,
4061
+ onClick: () => void session.install(model),
4062
+ children: model.updateRequired ? "Update" : "Download"
4063
+ }
4064
+ ),
4065
+ model.updateRequired && /* @__PURE__ */ jsx7(
4066
+ "button",
4067
+ {
4068
+ type: "button",
4069
+ className: "db-settings-action db-settings-action--secondary",
4070
+ disabled: installing !== null,
4071
+ onClick: () => void session.remove(model),
4072
+ children: "Remove"
4073
+ }
4074
+ )
4075
+ ] })
4076
+ ] });
4077
+ }
4078
+ function sectionError(failure, kind) {
4079
+ return failure && (failure.kind === void 0 || failure.kind === kind) ? failure.error : null;
4080
+ }
4081
+ function appModelBytes(models) {
4082
+ return models.filter((model) => model.source === "app").reduce((sum, model) => sum + model.downloadBytes, 0);
4083
+ }
4084
+ function SpeechSectionFallback({ legend, error }) {
4085
+ if (!error) return null;
4086
+ return /* @__PURE__ */ jsxs6("fieldset", { className: "db-settings-fieldset", children: [
4087
+ /* @__PURE__ */ jsx7("legend", { className: "db-settings-legend", children: legend }),
4088
+ /* @__PURE__ */ jsx7(SpeechErrorNotice, { error })
4089
+ ] });
4090
+ }
4091
+ function SpeechErrorNotice({ error }) {
4092
+ if (!error) return null;
4093
+ return /* @__PURE__ */ jsx7("p", { className: "db-settings-hint db-settings-ai-error", role: "alert", children: error.message });
4094
+ }
4095
+
4096
+ // src/Settings/TraySettings.tsx
4097
+ import { useCallback as useCallback7, useEffect as useEffect7, useRef as useRef7, useState as useState6 } from "react";
4098
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
4099
+ function trayPlace(platform) {
4100
+ switch (platform) {
4101
+ case "darwin":
4102
+ return { legend: "Menu bar", label: "Show DocBlocks in the menu bar" };
4103
+ case "win32":
4104
+ return {
4105
+ legend: "Notification area",
4106
+ label: "Show DocBlocks in the notification area"
4107
+ };
4108
+ default:
4109
+ return { legend: "System tray", label: "Show DocBlocks in the system tray" };
4110
+ }
4111
+ }
4112
+ function TraySettingsControls({ menu, platform }) {
4113
+ const [enabled, setEnabled] = useState6(null);
4114
+ const [saving, setSaving] = useState6(false);
4115
+ const [failure, setFailure] = useState6(null);
4116
+ const mounted = useRef7(true);
4117
+ useEffect7(() => {
4118
+ mounted.current = true;
4119
+ const read2 = menu.getTrayEnabled;
4120
+ if (read2) {
4121
+ read2.call(menu).then(
4122
+ (value) => {
4123
+ if (mounted.current) setEnabled(value);
4124
+ },
4125
+ () => {
4126
+ if (mounted.current) setFailure("DocBlocks could not read this setting.");
4127
+ }
4128
+ );
4129
+ }
4130
+ return () => {
4131
+ mounted.current = false;
4132
+ };
4133
+ }, [menu]);
4134
+ const change = useCallback7(
4135
+ async (next) => {
4136
+ const write2 = menu.setTrayEnabled;
4137
+ if (!write2) return;
4138
+ setSaving(true);
4139
+ setFailure(null);
4140
+ setEnabled(next);
4141
+ try {
4142
+ const saved = await write2.call(menu, next);
4143
+ if (mounted.current) setEnabled(saved);
4144
+ } catch {
4145
+ if (mounted.current) {
4146
+ setEnabled(!next);
4147
+ setFailure("DocBlocks could not change this setting. Try again.");
4148
+ }
4149
+ } finally {
4150
+ if (mounted.current) setSaving(false);
4151
+ }
4152
+ },
4153
+ [menu]
4154
+ );
4155
+ const place = trayPlace(platform);
4156
+ return /* @__PURE__ */ jsxs7("fieldset", { className: "db-settings-fieldset", children: [
4157
+ /* @__PURE__ */ jsx8("legend", { className: "db-settings-legend", children: place.legend }),
4158
+ /* @__PURE__ */ jsxs7("label", { className: "db-settings-checkbox", children: [
4159
+ /* @__PURE__ */ jsx8(
4160
+ "input",
4161
+ {
4162
+ type: "checkbox",
4163
+ checked: enabled === true,
4164
+ disabled: enabled === null || saving,
4165
+ onChange: (event) => void change(event.currentTarget.checked)
4166
+ }
4167
+ ),
4168
+ place.label
4169
+ ] }),
4170
+ /* @__PURE__ */ jsx8("p", { className: "db-settings-hint", children: "One click to a new document, a folder, or any document you have pinned." }),
4171
+ failure && /* @__PURE__ */ jsx8("p", { className: "db-settings-hint db-settings-ai-error", role: "alert", children: failure })
4172
+ ] });
4173
+ }
4174
+
4175
+ // src/Settings/useSpeechSettings.ts
4176
+ import { useCallback as useCallback8, useEffect as useEffect8, useRef as useRef8, useState as useState7 } from "react";
3886
4177
  var PREVIEW_TEXT = "This is how I sound when I read your documents aloud.";
3887
4178
  function unreachable(cause) {
3888
4179
  const detail = cause instanceof Error ? cause.message : void 0;
@@ -3892,37 +4183,36 @@ function unreachable(cause) {
3892
4183
  ...detail ? { detail } : {}
3893
4184
  };
3894
4185
  }
3895
- function SpeechSettingsControls({ speech }) {
3896
- const [status, setStatus] = useState6(null);
3897
- const [catalog, setCatalog] = useState6(null);
3898
- const [preferences, setPreferences] = useState6(null);
3899
- const [installing, setInstalling] = useState6(null);
3900
- const [failure, setFailure] = useState6(null);
3901
- const [previewing, setPreviewing] = useState6(false);
3902
- const mounted = useRef7(true);
3903
- const installHandle = useRef7(null);
3904
- const preview = useRef7(null);
3905
- const dictationModelId = useId2();
3906
- const voiceId = useId2();
3907
- const speedId = useId2();
3908
- const refresh = useCallback7(async () => {
4186
+ function useSpeechSettings(speech) {
4187
+ const [status, setStatus] = useState7(null);
4188
+ const [catalog, setCatalog] = useState7(null);
4189
+ const [preferences, setPreferences] = useState7(null);
4190
+ const [installing, setInstalling] = useState7(null);
4191
+ const [failure, setFailure] = useState7(null);
4192
+ const [previewing, setPreviewing] = useState7(false);
4193
+ const mounted = useRef8(true);
4194
+ const installHandle = useRef8(null);
4195
+ const preview = useRef8(null);
4196
+ const refresh = useCallback8(async () => {
4197
+ if (!speech) return;
3909
4198
  try {
3910
4199
  const [nextStatus, nextCatalog] = await Promise.all([speech.status(), speech.catalog()]);
3911
4200
  if (!mounted.current) return;
3912
4201
  setStatus(nextStatus);
3913
4202
  if (nextCatalog.ok) setCatalog(nextCatalog.value);
3914
- else setFailure(nextCatalog.error);
4203
+ else setFailure({ error: nextCatalog.error });
3915
4204
  } catch (cause) {
3916
- if (mounted.current) setFailure(unreachable(cause));
4205
+ if (mounted.current) setFailure({ error: unreachable(cause) });
3917
4206
  }
3918
4207
  }, [speech]);
3919
- const stopPreview = useCallback7(() => {
4208
+ const stopPreview = useCallback8(() => {
3920
4209
  preview.current?.handle.cancel();
3921
4210
  preview.current?.player.dispose();
3922
4211
  preview.current = null;
3923
4212
  setPreviewing(false);
3924
4213
  }, []);
3925
- useEffect7(() => {
4214
+ useEffect8(() => {
4215
+ if (!speech) return;
3926
4216
  mounted.current = true;
3927
4217
  const unsubscribe = speech.onStatus((next) => {
3928
4218
  if (!mounted.current) return;
@@ -3937,7 +4227,7 @@ function SpeechSettingsControls({ speech }) {
3937
4227
  if (mounted.current) setPreferences(initial);
3938
4228
  },
3939
4229
  (cause) => {
3940
- if (mounted.current) setFailure(unreachable(cause));
4230
+ if (mounted.current) setFailure({ error: unreachable(cause) });
3941
4231
  }
3942
4232
  );
3943
4233
  return () => {
@@ -3948,8 +4238,9 @@ function SpeechSettingsControls({ speech }) {
3948
4238
  unsubscribe();
3949
4239
  };
3950
4240
  }, [refresh, speech]);
3951
- const install = useCallback7(
4241
+ const install = useCallback8(
3952
4242
  async (model) => {
4243
+ if (!speech) return;
3953
4244
  setFailure(null);
3954
4245
  setInstalling({ id: model.id, progress: null });
3955
4246
  const handle = speech.installModel(model.id, (progress) => {
@@ -3959,7 +4250,9 @@ function SpeechSettingsControls({ speech }) {
3959
4250
  try {
3960
4251
  const result = await handle.done;
3961
4252
  if (!mounted.current) return;
3962
- if (!result.ok && result.error.code !== "cancelled") setFailure(result.error);
4253
+ if (!result.ok && result.error.code !== "cancelled") {
4254
+ setFailure({ error: result.error, kind: model.kind });
4255
+ }
3963
4256
  await refresh();
3964
4257
  } finally {
3965
4258
  if (installHandle.current === handle) installHandle.current = null;
@@ -3968,18 +4261,21 @@ function SpeechSettingsControls({ speech }) {
3968
4261
  },
3969
4262
  [refresh, speech]
3970
4263
  );
3971
- const remove = useCallback7(
4264
+ const cancelInstall = useCallback8(() => installHandle.current?.cancel(), []);
4265
+ const remove = useCallback8(
3972
4266
  async (model) => {
4267
+ if (!speech) return;
3973
4268
  setFailure(null);
3974
4269
  const result = await speech.removeModel(model.id);
3975
4270
  if (!mounted.current) return;
3976
- if (!result.ok) setFailure(result.error);
4271
+ if (!result.ok) setFailure({ error: result.error, kind: model.kind });
3977
4272
  await refresh();
3978
4273
  },
3979
4274
  [refresh, speech]
3980
4275
  );
3981
- const update = useCallback7(
4276
+ const update = useCallback8(
3982
4277
  async (patch) => {
4278
+ if (!speech) return;
3983
4279
  try {
3984
4280
  const next = await speech.setPreferences(patch);
3985
4281
  if (mounted.current) setPreferences(next);
@@ -3988,8 +4284,11 @@ function SpeechSettingsControls({ speech }) {
3988
4284
  },
3989
4285
  [speech]
3990
4286
  );
3991
- const startPreview = useCallback7(() => {
3992
- const synthesize = speech.synthesize;
4287
+ const setSpeedDraft = useCallback8((speed) => {
4288
+ setPreferences((current) => current ? { ...current, speed } : current);
4289
+ }, []);
4290
+ const startPreview = useCallback8(() => {
4291
+ const synthesize = speech?.synthesize;
3993
4292
  if (!synthesize) return;
3994
4293
  stopPreview();
3995
4294
  const player = ProgressivePlayer.create(() => void 0);
@@ -4007,271 +4306,241 @@ function SpeechSettingsControls({ speech }) {
4007
4306
  preview.current = { handle, player };
4008
4307
  void handle.done.then((result) => {
4009
4308
  if (!mounted.current || preview.current?.handle !== handle) return;
4010
- if (!result.ok && result.error.code !== "cancelled") setFailure(result.error);
4309
+ if (!result.ok && result.error.code !== "cancelled") {
4310
+ setFailure({ error: result.error, kind: "tts" });
4311
+ }
4011
4312
  setPreviewing(false);
4012
4313
  });
4013
4314
  }, [speech, stopPreview]);
4014
- if (!status || !catalog || !preferences) {
4015
- if (!failure) return null;
4016
- return /* @__PURE__ */ jsxs6("fieldset", { className: "db-settings-fieldset", children: [
4017
- /* @__PURE__ */ jsx7("legend", { className: "db-settings-legend", children: "Speech" }),
4018
- /* @__PURE__ */ jsx7("p", { className: "db-settings-hint db-settings-ai-error", role: "alert", children: failure.message })
4019
- ] });
4315
+ if (!speech) return null;
4316
+ return {
4317
+ speech,
4318
+ status,
4319
+ catalog,
4320
+ preferences,
4321
+ installing,
4322
+ failure,
4323
+ previewing,
4324
+ install,
4325
+ cancelInstall,
4326
+ remove,
4327
+ update,
4328
+ setSpeedDraft,
4329
+ startPreview,
4330
+ stopPreview
4331
+ };
4332
+ }
4333
+
4334
+ // src/Settings/AppSettingsDialog.tsx
4335
+ import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
4336
+ function formatBytes(bytes) {
4337
+ if (!Number.isFinite(bytes) || bytes < 0) return "\u2014";
4338
+ let value = bytes;
4339
+ let unit = "B";
4340
+ for (const next of ["KB", "MB", "GB", "TB"]) {
4341
+ if (value < 1024) break;
4342
+ value /= 1024;
4343
+ unit = next;
4020
4344
  }
4021
- const sttModels = catalog.models.filter((model) => model.kind === "stt");
4022
- const ttsModel = catalog.models.find((model) => model.kind === "tts") ?? null;
4023
- const installedStt = sttModels.filter((model) => model.installed);
4024
- const appBytes = catalog.models.filter((model) => model.source === "app").reduce((sum, model) => sum + model.downloadBytes, 0);
4025
- const modelRow = (model) => {
4026
- const busy = installing?.id === model.id;
4027
- const progress = busy ? installing.progress : null;
4028
- const percent = progress && progress.totalBytes ? Math.round(progress.receivedBytes / progress.totalBytes * 100) : null;
4029
- return /* @__PURE__ */ jsxs6("li", { className: "db-settings-speech-model", children: [
4030
- /* @__PURE__ */ jsxs6("div", { className: "db-settings-speech-model-text", children: [
4031
- /* @__PURE__ */ jsxs6("span", { className: "db-settings-speech-model-name", children: [
4032
- model.label,
4033
- model.recommended ? " (recommended)" : ""
4034
- ] }),
4035
- /* @__PURE__ */ jsxs6("span", { className: "db-settings-hint", children: [
4036
- model.description,
4037
- " ",
4038
- formatModelSize(model.downloadBytes),
4039
- " \xB7",
4040
- " ",
4041
- /* @__PURE__ */ jsx7("a", { href: model.licenseUrl, target: "_blank", rel: "noreferrer", children: model.license }),
4042
- model.source === "shared" ? " \xB7 Available from Gezel, no download needed" : model.sharedStorage ? " \xB7 Shared speech storage" : "",
4043
- model.updateRequired ? " \xB7 Update required" : ""
4044
- ] })
4045
- ] }),
4046
- busy ? /* @__PURE__ */ jsxs6("div", { className: "db-settings-ai-download-progress", role: "status", children: [
4047
- /* @__PURE__ */ jsx7(
4048
- "progress",
4345
+ return `${value >= 100 || unit === "B" ? Math.round(value) : value.toFixed(1)} ${unit}`;
4346
+ }
4347
+ function AppSettingsDialog({
4348
+ onClose,
4349
+ section,
4350
+ onSectionChange,
4351
+ themePreference,
4352
+ onThemeChange,
4353
+ accentColor,
4354
+ onAccentColorChange,
4355
+ interfaceFont,
4356
+ onInterfaceFontChange,
4357
+ writeCanvasSettings,
4358
+ onWriteCanvasSettingsChange,
4359
+ proofingPreferences,
4360
+ onProofingPreferencesChange,
4361
+ ai,
4362
+ speech,
4363
+ tray,
4364
+ getStorageEstimate,
4365
+ storagePersistent,
4366
+ onKeepBrowserData,
4367
+ requestingPersistentStorage = false,
4368
+ versioningPreference,
4369
+ onVersioningPreferenceChange,
4370
+ onOpenWorkspaceSettings
4371
+ }) {
4372
+ const speechSession = useSpeechSettings(speech);
4373
+ const [storageEstimate, setStorageEstimate] = useState8(null);
4374
+ useEffect9(() => {
4375
+ if (!getStorageEstimate) return;
4376
+ let cancelled = false;
4377
+ getStorageEstimate().then((estimate) => {
4378
+ if (!cancelled) setStorageEstimate(estimate);
4379
+ }).catch(() => {
4380
+ if (!cancelled) setStorageEstimate(null);
4381
+ });
4382
+ return () => {
4383
+ cancelled = true;
4384
+ };
4385
+ }, [getStorageEstimate]);
4386
+ const sections = [
4387
+ {
4388
+ id: "appearance",
4389
+ label: "Appearance",
4390
+ content: /* @__PURE__ */ jsxs8(Fragment5, { children: [
4391
+ /* @__PURE__ */ jsx9(
4392
+ ThemeSettings,
4049
4393
  {
4050
- max: 100,
4051
- value: percent ?? void 0,
4052
- "aria-label": `${model.label} download progress`
4394
+ value: themePreference,
4395
+ onChange: (preference) => onThemeChange?.(preference)
4053
4396
  }
4054
4397
  ),
4055
- /* @__PURE__ */ jsx7("span", { children: progress?.phase === "verifying" ? "Verifying\u2026" : percent === null ? "Starting\u2026" : `${percent}%` }),
4056
- /* @__PURE__ */ jsx7(
4057
- "button",
4398
+ /* @__PURE__ */ jsx9(
4399
+ AccentColorSettings,
4058
4400
  {
4059
- type: "button",
4060
- className: "db-settings-action db-settings-action--secondary",
4061
- onClick: () => installHandle.current?.cancel(),
4062
- children: "Cancel"
4401
+ value: accentColor,
4402
+ onChange: (color) => onAccentColorChange?.(color)
4063
4403
  }
4064
- )
4065
- ] }) : model.source === "app" ? /* @__PURE__ */ jsx7(
4066
- "button",
4067
- {
4068
- type: "button",
4069
- className: "db-settings-action db-settings-action--secondary",
4070
- disabled: installing !== null,
4071
- onClick: () => void remove(model),
4072
- children: "Remove"
4073
- }
4074
- ) : model.installed ? null : /* @__PURE__ */ jsxs6(Fragment4, { children: [
4075
- /* @__PURE__ */ jsx7(
4076
- "button",
4404
+ ),
4405
+ /* @__PURE__ */ jsx9(
4406
+ InterfaceFontSettings,
4077
4407
  {
4078
- type: "button",
4079
- className: "db-settings-action",
4080
- disabled: installing !== null,
4081
- onClick: () => void install(model),
4082
- children: model.updateRequired ? "Update" : "Download"
4408
+ value: interfaceFont,
4409
+ onChange: (font) => onInterfaceFontChange?.(font)
4083
4410
  }
4084
4411
  ),
4085
- model.updateRequired && /* @__PURE__ */ jsx7(
4086
- "button",
4412
+ /* @__PURE__ */ jsx9(
4413
+ WriteCanvasSettingsControls,
4087
4414
  {
4088
- type: "button",
4089
- className: "db-settings-action db-settings-action--secondary",
4090
- disabled: installing !== null,
4091
- onClick: () => void remove(model),
4092
- children: "Remove"
4415
+ value: writeCanvasSettings,
4416
+ onChange: (settings) => onWriteCanvasSettingsChange?.(settings)
4093
4417
  }
4094
- )
4095
- ] })
4096
- ] }, model.id);
4097
- };
4098
- return /* @__PURE__ */ jsxs6("fieldset", { className: "db-settings-fieldset", children: [
4099
- /* @__PURE__ */ jsx7("legend", { className: "db-settings-legend", children: "Speech" }),
4100
- /* @__PURE__ */ jsxs6("p", { className: "db-settings-hint", children: [
4101
- "Dictation and narration run on this computer; your voice and documents never leave it. Models download only when you choose.",
4102
- appBytes > 0 ? ` Speech models are using ${formatModelSize(appBytes)}.` : ""
4103
- ] }),
4104
- failure && /* @__PURE__ */ jsx7("p", { className: "db-settings-hint db-settings-ai-error", role: "alert", children: failure.message }),
4105
- speech.transcribe && /* @__PURE__ */ jsxs6("section", { className: "db-settings-speech-section", "aria-labelledby": dictationModelId, children: [
4106
- /* @__PURE__ */ jsx7("h4", { className: "db-settings-subheading", id: dictationModelId, children: "Dictation" }),
4107
- /* @__PURE__ */ jsx7("p", { className: "db-settings-hint", role: "status", "aria-live": "polite", children: readinessSentence(status.stt, "Ready. Use the microphone button in the toolbar.") }),
4108
- installedStt.length > 1 && /* @__PURE__ */ jsxs6("label", { className: "db-settings-select", children: [
4109
- /* @__PURE__ */ jsx7("span", { className: "db-settings-select-header", children: "Dictation model" }),
4110
- /* @__PURE__ */ jsxs6(
4111
- "select",
4418
+ ),
4419
+ /* @__PURE__ */ jsx9(
4420
+ ProofingSettingsControls,
4112
4421
  {
4113
- className: "db-settings-select-input",
4114
- value: preferences.sttModel ?? "",
4115
- onChange: (event) => void update({ sttModel: event.currentTarget.value || null }),
4116
- children: [
4117
- /* @__PURE__ */ jsx7("option", { value: "", children: "Recommended" }),
4118
- installedStt.map((model) => /* @__PURE__ */ jsx7("option", { value: model.id, children: model.label }, model.id))
4119
- ]
4422
+ value: proofingPreferences,
4423
+ onChange: (settings) => onProofingPreferencesChange?.(settings)
4120
4424
  }
4121
4425
  )
4122
- ] }),
4123
- /* @__PURE__ */ jsx7("ul", { className: "db-settings-speech-models", children: sttModels.map(modelRow) })
4124
- ] }),
4125
- speech.synthesize && ttsModel && /* @__PURE__ */ jsxs6("section", { className: "db-settings-speech-section", "aria-labelledby": voiceId, children: [
4126
- /* @__PURE__ */ jsx7("h4", { className: "db-settings-subheading", id: voiceId, children: "Narration" }),
4127
- /* @__PURE__ */ jsx7("p", { className: "db-settings-hint", role: "status", "aria-live": "polite", children: readinessSentence(status.tts, "Ready to read documents aloud.") }),
4128
- /* @__PURE__ */ jsx7("ul", { className: "db-settings-speech-models", children: modelRow(ttsModel) }),
4129
- ttsModel.installed && /* @__PURE__ */ jsxs6(Fragment4, { children: [
4130
- /* @__PURE__ */ jsxs6("label", { className: "db-settings-select", children: [
4131
- /* @__PURE__ */ jsx7("span", { className: "db-settings-select-header", children: "Voice" }),
4132
- /* @__PURE__ */ jsx7(
4133
- "select",
4426
+ ] })
4427
+ }
4428
+ ];
4429
+ if (ai) {
4430
+ sections.push({ id: "ai", label: "AI", content: /* @__PURE__ */ jsx9(AiSettingsControls, { ai }) });
4431
+ }
4432
+ if (speechSession?.speech.transcribe) {
4433
+ sections.push({
4434
+ id: "dictation",
4435
+ label: "Dictation",
4436
+ content: /* @__PURE__ */ jsx9(DictationSettingsControls, { session: speechSession })
4437
+ });
4438
+ }
4439
+ if (speechSession?.speech.synthesize) {
4440
+ sections.push({
4441
+ id: "narration",
4442
+ label: "Narration",
4443
+ content: /* @__PURE__ */ jsx9(NarrationSettingsControls, { session: speechSession })
4444
+ });
4445
+ }
4446
+ if (tray || getStorageEstimate || onVersioningPreferenceChange) {
4447
+ sections.push({
4448
+ id: "device",
4449
+ label: "Device integration",
4450
+ content: /* @__PURE__ */ jsxs8(Fragment5, { children: [
4451
+ tray && /* @__PURE__ */ jsx9(TraySettingsControls, { menu: tray, platform: getHostEnvironment()?.platform }),
4452
+ getStorageEstimate && /* @__PURE__ */ jsxs8("fieldset", { className: "db-settings-fieldset", children: [
4453
+ /* @__PURE__ */ jsx9("legend", { className: "db-settings-legend", children: "Storage" }),
4454
+ /* @__PURE__ */ jsx9("p", { className: "db-settings-hint", children: storageEstimate ? `DocBlocks documents and app data are using ${formatBytes(
4455
+ storageEstimate.usage
4456
+ )} of the ${formatBytes(
4457
+ storageEstimate.quota
4458
+ )} this browser allows for the site.` : "Storage usage is not available in this browser." }),
4459
+ storagePersistent !== void 0 && /* @__PURE__ */ jsx9("p", { className: "db-settings-hint", children: storagePersistent ? "Protected from routine browser cleanup on this device." : "Browsers may clear site data under storage pressure unless protection is granted." }),
4460
+ onKeepBrowserData && /* @__PURE__ */ jsx9(
4461
+ "button",
4134
4462
  {
4135
- className: "db-settings-select-input",
4136
- value: preferences.voice ?? catalog.voices[0]?.id ?? "",
4137
- onChange: (event) => void update({ voice: event.currentTarget.value }),
4138
- children: catalog.voices.map((voice) => /* @__PURE__ */ jsxs6("option", { value: voice.id, children: [
4139
- voice.label,
4140
- " (",
4141
- voice.language === "en-GB" ? "UK" : "US",
4142
- voice.gender ? ` ${voice.gender}` : "",
4143
- ")"
4144
- ] }, voice.id))
4463
+ type: "button",
4464
+ className: "db-settings-action",
4465
+ disabled: requestingPersistentStorage,
4466
+ onClick: onKeepBrowserData,
4467
+ children: requestingPersistentStorage ? "Requesting storage protection\u2026" : "Protect data from browser cleanup"
4145
4468
  }
4146
4469
  )
4147
4470
  ] }),
4148
- /* @__PURE__ */ jsxs6("label", { className: "db-settings-select", htmlFor: speedId, children: [
4149
- /* @__PURE__ */ jsxs6("span", { className: "db-settings-select-header", children: [
4150
- "Speed: ",
4151
- preferences.speed.toFixed(2),
4152
- "\xD7"
4471
+ onVersioningPreferenceChange && /* @__PURE__ */ jsxs8("fieldset", { className: "db-settings-fieldset", children: [
4472
+ /* @__PURE__ */ jsx9("legend", { className: "db-settings-legend", children: "Version history" }),
4473
+ /* @__PURE__ */ jsxs8("p", { className: "db-settings-hint", children: [
4474
+ "When on, DocBlocks keeps prior revisions of each document inside a sibling",
4475
+ " ",
4476
+ /* @__PURE__ */ jsx9("code", { children: "<name>_files/.versions/" }),
4477
+ " folder. Individual workspaces can override this default in their own settings."
4153
4478
  ] }),
4154
- /* @__PURE__ */ jsx7(
4155
- "input",
4479
+ /* @__PURE__ */ jsxs8("label", { className: "db-settings-radio", children: [
4480
+ /* @__PURE__ */ jsx9(
4481
+ "input",
4482
+ {
4483
+ type: "radio",
4484
+ name: "versioning",
4485
+ value: "on",
4486
+ checked: versioningPreference === "on",
4487
+ onChange: () => onVersioningPreferenceChange("on")
4488
+ }
4489
+ ),
4490
+ "On for all workspaces"
4491
+ ] }),
4492
+ /* @__PURE__ */ jsxs8("label", { className: "db-settings-radio", children: [
4493
+ /* @__PURE__ */ jsx9(
4494
+ "input",
4495
+ {
4496
+ type: "radio",
4497
+ name: "versioning",
4498
+ value: "browser-only",
4499
+ checked: versioningPreference === "browser-only",
4500
+ onChange: () => onVersioningPreferenceChange("browser-only")
4501
+ }
4502
+ ),
4503
+ "On in browser workspaces, off for local folders"
4504
+ ] }),
4505
+ /* @__PURE__ */ jsxs8("label", { className: "db-settings-radio", children: [
4506
+ /* @__PURE__ */ jsx9(
4507
+ "input",
4508
+ {
4509
+ type: "radio",
4510
+ name: "versioning",
4511
+ value: "off",
4512
+ checked: versioningPreference === "off",
4513
+ onChange: () => onVersioningPreferenceChange("off")
4514
+ }
4515
+ ),
4516
+ "Off for all workspaces"
4517
+ ] }),
4518
+ onOpenWorkspaceSettings && /* @__PURE__ */ jsx9(
4519
+ "button",
4156
4520
  {
4157
- id: speedId,
4158
- type: "range",
4159
- min: 0.5,
4160
- max: 2,
4161
- step: 0.05,
4162
- value: preferences.speed,
4163
- onChange: (event) => setPreferences({ ...preferences, speed: Number(event.currentTarget.value) }),
4164
- onPointerUp: (event) => void update({ speed: Number(event.currentTarget.value) }),
4165
- onKeyUp: (event) => void update({ speed: Number(event.currentTarget.value) })
4521
+ type: "button",
4522
+ className: "db-git-secondary-btn db-settings-link-btn",
4523
+ onClick: onOpenWorkspaceSettings,
4524
+ children: "This workspace\u2019s settings\u2026"
4166
4525
  }
4167
4526
  )
4168
- ] }),
4169
- /* @__PURE__ */ jsx7(
4170
- "button",
4171
- {
4172
- type: "button",
4173
- className: "db-settings-action db-settings-action--secondary",
4174
- onClick: () => previewing ? stopPreview() : startPreview(),
4175
- children: previewing ? "Stop preview" : "Preview voice"
4176
- }
4177
- )
4527
+ ] })
4178
4528
  ] })
4179
- ] })
4180
- ] });
4181
- }
4182
-
4183
- // src/Settings/TraySettings.tsx
4184
- import { useCallback as useCallback8, useEffect as useEffect8, useRef as useRef8, useState as useState7 } from "react";
4185
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
4186
- function trayPlace(platform) {
4187
- switch (platform) {
4188
- case "darwin":
4189
- return { legend: "Menu bar", label: "Show DocBlocks in the menu bar" };
4190
- case "win32":
4191
- return {
4192
- legend: "Notification area",
4193
- label: "Show DocBlocks in the notification area"
4194
- };
4195
- default:
4196
- return { legend: "System tray", label: "Show DocBlocks in the system tray" };
4529
+ });
4197
4530
  }
4198
- }
4199
- function TraySettingsControls({ menu, platform }) {
4200
- const [enabled, setEnabled] = useState7(null);
4201
- const [saving, setSaving] = useState7(false);
4202
- const [failure, setFailure] = useState7(null);
4203
- const mounted = useRef8(true);
4204
- useEffect8(() => {
4205
- mounted.current = true;
4206
- const read2 = menu.getTrayEnabled;
4207
- if (read2) {
4208
- read2.call(menu).then(
4209
- (value) => {
4210
- if (mounted.current) setEnabled(value);
4211
- },
4212
- () => {
4213
- if (mounted.current) setFailure("DocBlocks could not read this setting.");
4214
- }
4215
- );
4216
- }
4217
- return () => {
4218
- mounted.current = false;
4219
- };
4220
- }, [menu]);
4221
- const change = useCallback8(
4222
- async (next) => {
4223
- const write2 = menu.setTrayEnabled;
4224
- if (!write2) return;
4225
- setSaving(true);
4226
- setFailure(null);
4227
- setEnabled(next);
4228
- try {
4229
- const saved = await write2.call(menu, next);
4230
- if (mounted.current) setEnabled(saved);
4231
- } catch {
4232
- if (mounted.current) {
4233
- setEnabled(!next);
4234
- setFailure("DocBlocks could not change this setting. Try again.");
4235
- }
4236
- } finally {
4237
- if (mounted.current) setSaving(false);
4238
- }
4239
- },
4240
- [menu]
4531
+ return /* @__PURE__ */ jsx9(
4532
+ SettingsDialog,
4533
+ {
4534
+ onClose,
4535
+ sections,
4536
+ section,
4537
+ onSectionChange
4538
+ }
4241
4539
  );
4242
- const place = trayPlace(platform);
4243
- return /* @__PURE__ */ jsxs7("fieldset", { className: "db-settings-fieldset", children: [
4244
- /* @__PURE__ */ jsx8("legend", { className: "db-settings-legend", children: place.legend }),
4245
- /* @__PURE__ */ jsxs7("label", { className: "db-settings-checkbox", children: [
4246
- /* @__PURE__ */ jsx8(
4247
- "input",
4248
- {
4249
- type: "checkbox",
4250
- checked: enabled === true,
4251
- disabled: enabled === null || saving,
4252
- onChange: (event) => void change(event.currentTarget.checked)
4253
- }
4254
- ),
4255
- place.label
4256
- ] }),
4257
- /* @__PURE__ */ jsx8("p", { className: "db-settings-hint", children: "One click to a new document, a folder, or any document you have pinned." }),
4258
- failure && /* @__PURE__ */ jsx8("p", { className: "db-settings-hint db-settings-ai-error", role: "alert", children: failure })
4259
- ] });
4260
4540
  }
4261
4541
 
4262
4542
  // src/AppMenu/AppMenu.tsx
4263
- import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
4264
- function formatBytes(bytes) {
4265
- if (!Number.isFinite(bytes) || bytes < 0) return "\u2014";
4266
- let value = bytes;
4267
- let unit = "B";
4268
- for (const next of ["KB", "MB", "GB", "TB"]) {
4269
- if (value < 1024) break;
4270
- value /= 1024;
4271
- unit = next;
4272
- }
4273
- return `${value >= 100 || unit === "B" ? Math.round(value) : value.toFixed(1)} ${unit}`;
4274
- }
4543
+ import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
4275
4544
  var DOCUMENTATION_URL = "https://docblocks.com/docs/";
4276
4545
  var MORE_INFORMATION_URLS = Object.freeze({
4277
4546
  electron: "https://docblocks.com/desktop/",
@@ -4306,33 +4575,24 @@ function AppMenu({
4306
4575
  ai,
4307
4576
  speech,
4308
4577
  tray,
4309
- settingsRequest = 0
4578
+ settingsRequest = 0,
4579
+ settingsRequestSection
4310
4580
  }) {
4311
- const [isOpen, setIsOpen] = useState8(false);
4312
- const [showAbout, setShowAbout] = useState8(false);
4313
- const [showSettings, setShowSettings] = useState8(false);
4314
- useEffect9(() => {
4315
- if (settingsRequest > 0) setShowSettings(true);
4316
- }, [settingsRequest]);
4317
- const [requestingPersistentStorage, setRequestingPersistentStorage] = useState8(false);
4318
- const surface = getHostEnvironment()?.surface ?? "web";
4581
+ const [isOpen, setIsOpen] = useState9(false);
4582
+ const [showAbout, setShowAbout] = useState9(false);
4583
+ const [showSettings, setShowSettings] = useState9(false);
4584
+ const [settingsSection, setSettingsSection] = useState9("appearance");
4585
+ useEffect10(() => {
4586
+ if (settingsRequest <= 0) return;
4587
+ if (settingsRequestSection) setSettingsSection(settingsRequestSection);
4588
+ setShowSettings(true);
4589
+ }, [settingsRequest, settingsRequestSection]);
4590
+ const [requestingPersistentStorage, setRequestingPersistentStorage] = useState9(false);
4591
+ const surface = getHostEnvironment2()?.surface ?? "web";
4319
4592
  const moreInformationUrl = MORE_INFORMATION_URLS[surface] ?? MORE_INFORMATION_URLS.web;
4320
4593
  const containerRef = useRef9(null);
4321
4594
  const { menuRef, triggerRef, handleMenuKeyDown, handleTriggerKeyDown, closeMenu } = useMenuKeyboard(isOpen, setIsOpen);
4322
- const [storageEstimate, setStorageEstimate] = useState8(null);
4323
- useEffect9(() => {
4324
- if (!showSettings || !getStorageEstimate) return;
4325
- let cancelled = false;
4326
- getStorageEstimate().then((estimate) => {
4327
- if (!cancelled) setStorageEstimate(estimate);
4328
- }).catch(() => {
4329
- if (!cancelled) setStorageEstimate(null);
4330
- });
4331
- return () => {
4332
- cancelled = true;
4333
- };
4334
- }, [showSettings, getStorageEstimate]);
4335
- useEffect9(() => {
4595
+ useEffect10(() => {
4336
4596
  if (!isOpen) return;
4337
4597
  function handleOutsideClick(e) {
4338
4598
  if (containerRef.current && !containerRef.current.contains(e.target)) {
@@ -4359,9 +4619,9 @@ function AppMenu({
4359
4619
  setRequestingPersistentStorage(false);
4360
4620
  }
4361
4621
  }, [onKeepBrowserData, requestingPersistentStorage]);
4362
- return /* @__PURE__ */ jsxs8(Fragment5, { children: [
4363
- /* @__PURE__ */ jsxs8("div", { ref: containerRef, className: "db-app-menu", children: [
4364
- /* @__PURE__ */ jsxs8(
4622
+ return /* @__PURE__ */ jsxs9(Fragment6, { children: [
4623
+ /* @__PURE__ */ jsxs9("div", { ref: containerRef, className: "db-app-menu", children: [
4624
+ /* @__PURE__ */ jsxs9(
4365
4625
  "button",
4366
4626
  {
4367
4627
  ref: triggerRef,
@@ -4371,8 +4631,8 @@ function AppMenu({
4371
4631
  "aria-expanded": isOpen,
4372
4632
  "aria-haspopup": "menu",
4373
4633
  children: [
4374
- logoUrl ? /* @__PURE__ */ jsxs8(Fragment5, { children: [
4375
- /* @__PURE__ */ jsx9(
4634
+ logoUrl ? /* @__PURE__ */ jsxs9(Fragment6, { children: [
4635
+ /* @__PURE__ */ jsx10(
4376
4636
  "img",
4377
4637
  {
4378
4638
  src: logoUrl,
@@ -4382,7 +4642,7 @@ function AppMenu({
4382
4642
  height: 242
4383
4643
  }
4384
4644
  ),
4385
- logoDarkUrl && /* @__PURE__ */ jsx9(
4645
+ logoDarkUrl && /* @__PURE__ */ jsx10(
4386
4646
  "img",
4387
4647
  {
4388
4648
  src: logoDarkUrl,
@@ -4392,8 +4652,8 @@ function AppMenu({
4392
4652
  height: 242
4393
4653
  }
4394
4654
  )
4395
- ] }) : /* @__PURE__ */ jsx9("span", { className: "db-app-menu-label", children: "docblocks" }),
4396
- /* @__PURE__ */ jsx9(
4655
+ ] }) : /* @__PURE__ */ jsx10("span", { className: "db-app-menu-label", children: "docblocks" }),
4656
+ /* @__PURE__ */ jsx10(
4397
4657
  "span",
4398
4658
  {
4399
4659
  className: `db-app-menu-caret${isOpen ? " db-app-menu-caret--open" : ""}`,
@@ -4403,7 +4663,7 @@ function AppMenu({
4403
4663
  ]
4404
4664
  }
4405
4665
  ),
4406
- isOpen && /* @__PURE__ */ jsxs8(
4666
+ isOpen && /* @__PURE__ */ jsxs9(
4407
4667
  "div",
4408
4668
  {
4409
4669
  ref: menuRef,
@@ -4411,7 +4671,7 @@ function AppMenu({
4411
4671
  role: "menu",
4412
4672
  onKeyDown: handleMenuKeyDown,
4413
4673
  children: [
4414
- /* @__PURE__ */ jsx9(
4674
+ /* @__PURE__ */ jsx10(
4415
4675
  "button",
4416
4676
  {
4417
4677
  className: "db-app-menu-item",
@@ -4421,7 +4681,7 @@ function AppMenu({
4421
4681
  children: "Settings"
4422
4682
  }
4423
4683
  ),
4424
- onInstallApp && /* @__PURE__ */ jsx9(
4684
+ onInstallApp && /* @__PURE__ */ jsx10(
4425
4685
  "button",
4426
4686
  {
4427
4687
  className: "db-app-menu-item",
@@ -4431,8 +4691,8 @@ function AppMenu({
4431
4691
  children: "Install DocBlocks\u2026"
4432
4692
  }
4433
4693
  ),
4434
- (onDownloadAllWorkspaces || onRestoreBackup || onKeepBrowserData) && /* @__PURE__ */ jsx9("div", { className: "db-app-menu-divider" }),
4435
- onDownloadAllWorkspaces && /* @__PURE__ */ jsx9(
4694
+ (onDownloadAllWorkspaces || onRestoreBackup || onKeepBrowserData) && /* @__PURE__ */ jsx10("div", { className: "db-app-menu-divider" }),
4695
+ onDownloadAllWorkspaces && /* @__PURE__ */ jsx10(
4436
4696
  "button",
4437
4697
  {
4438
4698
  className: "db-app-menu-item",
@@ -4442,7 +4702,7 @@ function AppMenu({
4442
4702
  children: "Back up all workspaces"
4443
4703
  }
4444
4704
  ),
4445
- onRestoreBackup && /* @__PURE__ */ jsx9(
4705
+ onRestoreBackup && /* @__PURE__ */ jsx10(
4446
4706
  "button",
4447
4707
  {
4448
4708
  className: "db-app-menu-item",
@@ -4452,7 +4712,7 @@ function AppMenu({
4452
4712
  children: "Restore backup\u2026"
4453
4713
  }
4454
4714
  ),
4455
- onKeepBrowserData && /* @__PURE__ */ jsx9(
4715
+ onKeepBrowserData && /* @__PURE__ */ jsx10(
4456
4716
  "button",
4457
4717
  {
4458
4718
  className: "db-app-menu-item",
@@ -4462,8 +4722,8 @@ function AppMenu({
4462
4722
  children: "Protect data from browser cleanup"
4463
4723
  }
4464
4724
  ),
4465
- /* @__PURE__ */ jsx9("div", { className: "db-app-menu-divider" }),
4466
- onShowKeyboardShortcuts && /* @__PURE__ */ jsxs8(
4725
+ /* @__PURE__ */ jsx10("div", { className: "db-app-menu-divider" }),
4726
+ onShowKeyboardShortcuts && /* @__PURE__ */ jsxs9(
4467
4727
  "button",
4468
4728
  {
4469
4729
  className: "db-app-menu-item db-app-menu-item--with-shortcut",
@@ -4473,11 +4733,11 @@ function AppMenu({
4473
4733
  onClick: () => handleAction(onShowKeyboardShortcuts),
4474
4734
  children: [
4475
4735
  "Keyboard shortcuts",
4476
- /* @__PURE__ */ jsx9("span", { className: "db-app-menu-shortcut", "aria-hidden": "true", children: "F1" })
4736
+ /* @__PURE__ */ jsx10("span", { className: "db-app-menu-shortcut", "aria-hidden": "true", children: "F1" })
4477
4737
  ]
4478
4738
  }
4479
4739
  ),
4480
- /* @__PURE__ */ jsx9(
4740
+ /* @__PURE__ */ jsx10(
4481
4741
  "a",
4482
4742
  {
4483
4743
  className: "db-app-menu-item",
@@ -4490,7 +4750,7 @@ function AppMenu({
4490
4750
  children: "Documentation"
4491
4751
  }
4492
4752
  ),
4493
- /* @__PURE__ */ jsx9(
4753
+ /* @__PURE__ */ jsx10(
4494
4754
  "button",
4495
4755
  {
4496
4756
  className: "db-app-menu-item",
@@ -4504,157 +4764,69 @@ function AppMenu({
4504
4764
  }
4505
4765
  )
4506
4766
  ] }),
4507
- showSettings && /* @__PURE__ */ jsxs8(SettingsDialog, { onClose: () => setShowSettings(false), children: [
4508
- /* @__PURE__ */ jsx9(
4509
- ThemeSettings,
4510
- {
4511
- value: themePreference,
4512
- onChange: (preference) => onThemeChange?.(preference)
4513
- }
4514
- ),
4515
- /* @__PURE__ */ jsx9(
4516
- AccentColorSettings,
4517
- {
4518
- value: accentColor,
4519
- onChange: (color) => onAccentColorChange?.(color)
4520
- }
4521
- ),
4522
- /* @__PURE__ */ jsx9(
4523
- InterfaceFontSettings,
4524
- {
4525
- value: interfaceFont,
4526
- onChange: (font) => onInterfaceFontChange?.(font)
4527
- }
4528
- ),
4529
- /* @__PURE__ */ jsx9(
4530
- WriteCanvasSettingsControls,
4531
- {
4532
- value: writeCanvasSettings,
4533
- onChange: (settings) => onWriteCanvasSettingsChange?.(settings)
4534
- }
4535
- ),
4536
- /* @__PURE__ */ jsx9(
4537
- ProofingSettingsControls,
4538
- {
4539
- value: proofingPreferences,
4540
- onChange: (settings) => onProofingPreferencesChange?.(settings)
4541
- }
4542
- ),
4543
- ai && /* @__PURE__ */ jsx9(AiSettingsControls, { ai }),
4544
- speech && /* @__PURE__ */ jsx9(SpeechSettingsControls, { speech }),
4545
- tray && /* @__PURE__ */ jsx9(TraySettingsControls, { menu: tray, platform: getHostEnvironment()?.platform }),
4546
- getStorageEstimate && /* @__PURE__ */ jsxs8("fieldset", { className: "db-settings-fieldset", children: [
4547
- /* @__PURE__ */ jsx9("legend", { className: "db-settings-legend", children: "Storage" }),
4548
- /* @__PURE__ */ jsx9("p", { className: "db-settings-hint", children: storageEstimate ? `DocBlocks documents and app data are using ${formatBytes(
4549
- storageEstimate.usage
4550
- )} of the ${formatBytes(
4551
- storageEstimate.quota
4552
- )} this browser allows for the site.` : "Storage usage is not available in this browser." }),
4553
- storagePersistent !== void 0 && /* @__PURE__ */ jsx9("p", { className: "db-settings-hint", children: storagePersistent ? "Protected from routine browser cleanup on this device." : "Browsers may clear site data under storage pressure unless protection is granted." }),
4554
- onKeepBrowserData && /* @__PURE__ */ jsx9(
4555
- "button",
4556
- {
4557
- type: "button",
4558
- className: "db-settings-action",
4559
- disabled: requestingPersistentStorage,
4560
- onClick: () => void handleKeepBrowserDataFromSettings(),
4561
- children: requestingPersistentStorage ? "Requesting storage protection\u2026" : "Protect data from browser cleanup"
4562
- }
4563
- )
4564
- ] }),
4565
- onVersioningPreferenceChange && /* @__PURE__ */ jsxs8("fieldset", { className: "db-settings-fieldset", children: [
4566
- /* @__PURE__ */ jsx9("legend", { className: "db-settings-legend", children: "Version history" }),
4567
- /* @__PURE__ */ jsxs8("p", { className: "db-settings-hint", children: [
4568
- "When on, DocBlocks keeps prior revisions of each document inside a sibling",
4569
- " ",
4570
- /* @__PURE__ */ jsx9("code", { children: "<name>_files/.versions/" }),
4571
- " folder. Individual workspaces can override this default in their own settings."
4572
- ] }),
4573
- /* @__PURE__ */ jsxs8("label", { className: "db-settings-radio", children: [
4574
- /* @__PURE__ */ jsx9(
4575
- "input",
4576
- {
4577
- type: "radio",
4578
- name: "versioning",
4579
- value: "on",
4580
- checked: versioningPreference === "on",
4581
- onChange: () => onVersioningPreferenceChange("on")
4582
- }
4583
- ),
4584
- "On for all workspaces"
4585
- ] }),
4586
- /* @__PURE__ */ jsxs8("label", { className: "db-settings-radio", children: [
4587
- /* @__PURE__ */ jsx9(
4588
- "input",
4589
- {
4590
- type: "radio",
4591
- name: "versioning",
4592
- value: "browser-only",
4593
- checked: versioningPreference === "browser-only",
4594
- onChange: () => onVersioningPreferenceChange("browser-only")
4595
- }
4596
- ),
4597
- "On in browser workspaces, off for local folders"
4598
- ] }),
4599
- /* @__PURE__ */ jsxs8("label", { className: "db-settings-radio", children: [
4600
- /* @__PURE__ */ jsx9(
4601
- "input",
4602
- {
4603
- type: "radio",
4604
- name: "versioning",
4605
- value: "off",
4606
- checked: versioningPreference === "off",
4607
- onChange: () => onVersioningPreferenceChange("off")
4608
- }
4609
- ),
4610
- "Off for all workspaces"
4611
- ] }),
4612
- onOpenWorkspaceSettings && /* @__PURE__ */ jsx9(
4613
- "button",
4614
- {
4615
- type: "button",
4616
- className: "db-git-secondary-btn db-settings-link-btn",
4617
- onClick: () => {
4618
- setShowSettings(false);
4619
- onOpenWorkspaceSettings();
4620
- },
4621
- children: "This workspace\u2019s settings\u2026"
4622
- }
4623
- )
4624
- ] })
4625
- ] }),
4626
- showAbout && /* @__PURE__ */ jsxs8(Dialog, { title: "About DocBlocks", onClose: () => setShowAbout(false), children: [
4627
- /* @__PURE__ */ jsxs8("p", { children: [
4628
- /* @__PURE__ */ jsx9("strong", { children: "DocBlocks" }),
4767
+ showSettings && /* @__PURE__ */ jsx10(
4768
+ AppSettingsDialog,
4769
+ {
4770
+ onClose: () => setShowSettings(false),
4771
+ section: settingsSection,
4772
+ onSectionChange: setSettingsSection,
4773
+ themePreference,
4774
+ onThemeChange,
4775
+ accentColor,
4776
+ onAccentColorChange,
4777
+ interfaceFont,
4778
+ onInterfaceFontChange,
4779
+ writeCanvasSettings,
4780
+ onWriteCanvasSettingsChange,
4781
+ proofingPreferences,
4782
+ onProofingPreferencesChange,
4783
+ ai,
4784
+ speech,
4785
+ tray,
4786
+ getStorageEstimate,
4787
+ storagePersistent,
4788
+ onKeepBrowserData: onKeepBrowserData ? () => void handleKeepBrowserDataFromSettings() : void 0,
4789
+ requestingPersistentStorage,
4790
+ versioningPreference,
4791
+ onVersioningPreferenceChange,
4792
+ onOpenWorkspaceSettings: onOpenWorkspaceSettings ? () => {
4793
+ setShowSettings(false);
4794
+ onOpenWorkspaceSettings();
4795
+ } : void 0
4796
+ }
4797
+ ),
4798
+ showAbout && /* @__PURE__ */ jsxs9(Dialog, { title: "About DocBlocks", onClose: () => setShowAbout(false), children: [
4799
+ /* @__PURE__ */ jsxs9("p", { children: [
4800
+ /* @__PURE__ */ jsx10("strong", { children: "DocBlocks" }),
4629
4801
  " is a local-first Markdown document editor. Your files stay under your control."
4630
4802
  ] }),
4631
- appVersion && /* @__PURE__ */ jsxs8("p", { className: "db-about-version", children: [
4632
- /* @__PURE__ */ jsx9("span", { children: "Version" }),
4633
- /* @__PURE__ */ jsx9("code", { "aria-label": `DocBlocks version ${appVersion}`, children: appVersion })
4803
+ appVersion && /* @__PURE__ */ jsxs9("p", { className: "db-about-version", children: [
4804
+ /* @__PURE__ */ jsx10("span", { children: "Version" }),
4805
+ /* @__PURE__ */ jsx10("code", { "aria-label": `DocBlocks version ${appVersion}`, children: appVersion })
4634
4806
  ] }),
4635
- appBuildDate && /* @__PURE__ */ jsxs8("p", { className: "db-about-version", children: [
4636
- /* @__PURE__ */ jsx9("span", { children: "Build" }),
4637
- /* @__PURE__ */ jsx9("time", { dateTime: appBuildDate, children: displayBuildDate(appBuildDate) })
4807
+ appBuildDate && /* @__PURE__ */ jsxs9("p", { className: "db-about-version", children: [
4808
+ /* @__PURE__ */ jsx10("span", { children: "Build" }),
4809
+ /* @__PURE__ */ jsx10("time", { dateTime: appBuildDate, children: displayBuildDate(appBuildDate) })
4638
4810
  ] }),
4639
- /* @__PURE__ */ jsxs8("p", { children: [
4811
+ /* @__PURE__ */ jsxs9("p", { children: [
4640
4812
  "Built with",
4641
4813
  " ",
4642
- /* @__PURE__ */ jsx9("a", { href: "https://github.com/bendyline/squisq", target: "_blank", rel: "noopener noreferrer", children: "squisq" }),
4814
+ /* @__PURE__ */ jsx10("a", { href: "https://github.com/bendyline/squisq", target: "_blank", rel: "noopener noreferrer", children: "squisq" }),
4643
4815
  " ",
4644
4816
  "by",
4645
4817
  " ",
4646
- /* @__PURE__ */ jsx9("a", { href: "https://bendyline.com", target: "_blank", rel: "noopener noreferrer", children: "Bendyline" }),
4818
+ /* @__PURE__ */ jsx10("a", { href: "https://bendyline.com", target: "_blank", rel: "noopener noreferrer", children: "Bendyline" }),
4647
4819
  "."
4648
4820
  ] }),
4649
- surface === "web" && /* @__PURE__ */ jsxs8("p", { children: [
4821
+ surface === "web" && /* @__PURE__ */ jsxs9("p", { children: [
4650
4822
  "See our free desktop apps at",
4651
4823
  " ",
4652
- /* @__PURE__ */ jsx9("a", { href: MORE_INFORMATION_URLS.electron, target: "_blank", rel: "noopener noreferrer", children: "docblocks.com/desktop" }),
4824
+ /* @__PURE__ */ jsx10("a", { href: MORE_INFORMATION_URLS.electron, target: "_blank", rel: "noopener noreferrer", children: "docblocks.com/desktop" }),
4653
4825
  "."
4654
4826
  ] }),
4655
- /* @__PURE__ */ jsxs8("p", { className: "db-dialog-links", children: [
4656
- /* @__PURE__ */ jsx9("a", { href: moreInformationUrl, target: "_blank", rel: "noopener noreferrer", children: "More information..." }),
4657
- /* @__PURE__ */ jsx9(
4827
+ /* @__PURE__ */ jsxs9("p", { className: "db-dialog-links", children: [
4828
+ /* @__PURE__ */ jsx10("a", { href: moreInformationUrl, target: "_blank", rel: "noopener noreferrer", children: "More information..." }),
4829
+ /* @__PURE__ */ jsx10(
4658
4830
  "a",
4659
4831
  {
4660
4832
  href: "https://github.com/bendyline/docblocks",
@@ -4663,7 +4835,7 @@ function AppMenu({
4663
4835
  children: "GitHub"
4664
4836
  }
4665
4837
  ),
4666
- /* @__PURE__ */ jsx9(
4838
+ /* @__PURE__ */ jsx10(
4667
4839
  "a",
4668
4840
  {
4669
4841
  href: "https://github.com/bendyline/docblocks/releases",
@@ -4672,7 +4844,7 @@ function AppMenu({
4672
4844
  children: "Release notes"
4673
4845
  }
4674
4846
  ),
4675
- /* @__PURE__ */ jsx9(
4847
+ /* @__PURE__ */ jsx10(
4676
4848
  "a",
4677
4849
  {
4678
4850
  href: "https://github.com/bendyline/docblocks/issues",
@@ -4681,7 +4853,7 @@ function AppMenu({
4681
4853
  children: "Support"
4682
4854
  }
4683
4855
  ),
4684
- /* @__PURE__ */ jsx9(
4856
+ /* @__PURE__ */ jsx10(
4685
4857
  "a",
4686
4858
  {
4687
4859
  href: "https://github.com/bendyline/docblocks/blob/main/LICENSE",
@@ -4690,7 +4862,7 @@ function AppMenu({
4690
4862
  children: "License (MIT)"
4691
4863
  }
4692
4864
  ),
4693
- /* @__PURE__ */ jsx9(
4865
+ /* @__PURE__ */ jsx10(
4694
4866
  "a",
4695
4867
  {
4696
4868
  href: "https://github.com/bendyline/docblocks/blob/main/NOTICE.md",
@@ -4758,18 +4930,18 @@ async function restoreBrowserBackup(file) {
4758
4930
  }
4759
4931
 
4760
4932
  // src/WorkspacePicker/WorkspaceSettingsButton.tsx
4761
- import { useState as useState9, useCallback as useCallback10, useRef as useRef10, useEffect as useEffect10 } from "react";
4762
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
4933
+ import { useState as useState10, useCallback as useCallback10, useRef as useRef10, useEffect as useEffect11 } from "react";
4934
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
4763
4935
  function WorkspaceSettingsButton({
4764
4936
  onSettings,
4765
4937
  onRename,
4766
4938
  onDownload,
4767
4939
  onRemove
4768
4940
  }) {
4769
- const [isOpen, setIsOpen] = useState9(false);
4941
+ const [isOpen, setIsOpen] = useState10(false);
4770
4942
  const containerRef = useRef10(null);
4771
4943
  const { menuRef, triggerRef, handleMenuKeyDown, handleTriggerKeyDown, closeMenu } = useMenuKeyboard(isOpen, setIsOpen);
4772
- useEffect10(() => {
4944
+ useEffect11(() => {
4773
4945
  if (!isOpen) return;
4774
4946
  function handleOutsideClick(e) {
4775
4947
  if (containerRef.current && !containerRef.current.contains(e.target)) {
@@ -4786,8 +4958,8 @@ function WorkspaceSettingsButton({
4786
4958
  },
4787
4959
  [closeMenu]
4788
4960
  );
4789
- return /* @__PURE__ */ jsxs9("div", { ref: containerRef, className: "db-ws-settings", children: [
4790
- /* @__PURE__ */ jsx10(
4961
+ return /* @__PURE__ */ jsxs10("div", { ref: containerRef, className: "db-ws-settings", children: [
4962
+ /* @__PURE__ */ jsx11(
4791
4963
  "button",
4792
4964
  {
4793
4965
  ref: triggerRef,
@@ -4798,10 +4970,10 @@ function WorkspaceSettingsButton({
4798
4970
  "aria-haspopup": "menu",
4799
4971
  "aria-label": "Workspace settings",
4800
4972
  title: "Workspace settings",
4801
- children: /* @__PURE__ */ jsx10(WorkspaceIcon, {})
4973
+ children: /* @__PURE__ */ jsx11(WorkspaceIcon, {})
4802
4974
  }
4803
4975
  ),
4804
- isOpen && /* @__PURE__ */ jsxs9(
4976
+ isOpen && /* @__PURE__ */ jsxs10(
4805
4977
  "div",
4806
4978
  {
4807
4979
  ref: menuRef,
@@ -4809,7 +4981,7 @@ function WorkspaceSettingsButton({
4809
4981
  role: "menu",
4810
4982
  onKeyDown: handleMenuKeyDown,
4811
4983
  children: [
4812
- /* @__PURE__ */ jsx10(
4984
+ /* @__PURE__ */ jsx11(
4813
4985
  "button",
4814
4986
  {
4815
4987
  className: "db-ws-settings-item",
@@ -4819,7 +4991,7 @@ function WorkspaceSettingsButton({
4819
4991
  children: "Workspace settings\u2026"
4820
4992
  }
4821
4993
  ),
4822
- /* @__PURE__ */ jsx10(
4994
+ /* @__PURE__ */ jsx11(
4823
4995
  "button",
4824
4996
  {
4825
4997
  className: "db-ws-settings-item",
@@ -4829,7 +5001,7 @@ function WorkspaceSettingsButton({
4829
5001
  children: "Rename workspace"
4830
5002
  }
4831
5003
  ),
4832
- /* @__PURE__ */ jsx10(
5004
+ /* @__PURE__ */ jsx11(
4833
5005
  "button",
4834
5006
  {
4835
5007
  className: "db-ws-settings-item",
@@ -4839,8 +5011,8 @@ function WorkspaceSettingsButton({
4839
5011
  children: "Back up this workspace"
4840
5012
  }
4841
5013
  ),
4842
- /* @__PURE__ */ jsx10("div", { className: "db-ws-settings-divider" }),
4843
- /* @__PURE__ */ jsx10(
5014
+ /* @__PURE__ */ jsx11("div", { className: "db-ws-settings-divider" }),
5015
+ /* @__PURE__ */ jsx11(
4844
5016
  "button",
4845
5017
  {
4846
5018
  className: "db-ws-settings-item db-ws-settings-item--danger",
@@ -4857,7 +5029,7 @@ function WorkspaceSettingsButton({
4857
5029
  }
4858
5030
 
4859
5031
  // src/WorkspacePicker/WorkspaceSettingsDialog.tsx
4860
- import { useEffect as useEffect11, useMemo as useMemo2, useState as useState10 } from "react";
5032
+ import { useEffect as useEffect12, useMemo as useMemo2, useState as useState11 } from "react";
4861
5033
  import { getThemeSummaries } from "@bendyline/squisq/schemas";
4862
5034
  import {
4863
5035
  diffWorkspaceSettings,
@@ -4911,7 +5083,7 @@ function resolveVersioningEnabled(workspace, globalPref, workspaceSettings) {
4911
5083
  }
4912
5084
 
4913
5085
  // src/WorkspacePicker/WorkspaceSettingsDialog.tsx
4914
- import { Fragment as Fragment6, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
5086
+ import { Fragment as Fragment7, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
4915
5087
  var VERSIONING_LABELS = {
4916
5088
  on: "on",
4917
5089
  "browser-only": "on for browser workspaces, off for local folders",
@@ -4960,15 +5132,15 @@ function WorkspaceSettingsDialog({
4960
5132
  }) {
4961
5133
  const writable = isWorkspaceSettingsWritable(settings);
4962
5134
  const base = settings.settings;
4963
- const [draft, setDraft] = useState10(
5135
+ const [draft, setDraft] = useState11(
4964
5136
  () => initialDraft(workspace, settings.settings)
4965
5137
  );
4966
- const [touched, setTouched] = useState10(false);
4967
- useEffect11(() => {
5138
+ const [touched, setTouched] = useState11(false);
5139
+ useEffect12(() => {
4968
5140
  if (!touched) setDraft(initialDraft(workspace, settings.settings));
4969
5141
  }, [settings.settings, touched, workspace]);
4970
- const [saving, setSaving] = useState10(false);
4971
- const [saveError, setSaveError] = useState10(null);
5142
+ const [saving, setSaving] = useState11(false);
5143
+ const [saveError, setSaveError] = useState11(null);
4972
5144
  const themes = useMemo2(() => getThemeSummaries(), []);
4973
5145
  const patch = useMemo2(() => diffWorkspaceSettings(base, draft), [base, draft]);
4974
5146
  const validation = useMemo2(() => tryApplyWorkspaceSettingsPatch(base, patch), [base, patch]);
@@ -4993,16 +5165,16 @@ function WorkspaceSettingsDialog({
4993
5165
  }
4994
5166
  };
4995
5167
  const notice = settings.status === "loading" ? "Loading workspace settings\u2026" : writable ? null : settings.message ?? "These workspace settings cannot be changed here.";
4996
- return /* @__PURE__ */ jsxs10(
5168
+ return /* @__PURE__ */ jsxs11(
4997
5169
  Dialog,
4998
5170
  {
4999
5171
  title: "Workspace settings",
5000
5172
  size: "wide",
5001
5173
  onClose,
5002
5174
  closeOnBackdrop: !changed,
5003
- footer: writable ? /* @__PURE__ */ jsxs10(Fragment6, { children: [
5004
- /* @__PURE__ */ jsx11("button", { type: "button", className: "db-git-secondary-btn", onClick: onClose, children: "Cancel" }),
5005
- /* @__PURE__ */ jsx11(
5175
+ footer: writable ? /* @__PURE__ */ jsxs11(Fragment7, { children: [
5176
+ /* @__PURE__ */ jsx12("button", { type: "button", className: "db-git-secondary-btn", onClick: onClose, children: "Cancel" }),
5177
+ /* @__PURE__ */ jsx12(
5006
5178
  "button",
5007
5179
  {
5008
5180
  type: "button",
@@ -5012,19 +5184,19 @@ function WorkspaceSettingsDialog({
5012
5184
  children: saving ? "Saving\u2026" : "Save"
5013
5185
  }
5014
5186
  )
5015
- ] }) : /* @__PURE__ */ jsx11("button", { type: "button", className: "db-git-secondary-btn", onClick: onClose, children: "Close" }),
5187
+ ] }) : /* @__PURE__ */ jsx12("button", { type: "button", className: "db-git-secondary-btn", onClick: onClose, children: "Close" }),
5016
5188
  children: [
5017
- /* @__PURE__ */ jsxs10("p", { className: "db-settings-hint", children: [
5018
- /* @__PURE__ */ jsx11("strong", { children: workspace.name }),
5189
+ /* @__PURE__ */ jsxs11("p", { className: "db-settings-hint", children: [
5190
+ /* @__PURE__ */ jsx12("strong", { children: workspace.name }),
5019
5191
  " \xB7",
5020
5192
  " ",
5021
5193
  isLocal ? "Local folder workspace" : "Browser workspace",
5022
5194
  " \xB7 saved in",
5023
5195
  " ",
5024
- /* @__PURE__ */ jsx11("code", { children: ".docblocks/workspace.json" })
5196
+ /* @__PURE__ */ jsx12("code", { children: ".docblocks/workspace.json" })
5025
5197
  ] }),
5026
- notice && /* @__PURE__ */ jsx11("p", { className: "db-settings-status db-settings-status--warning", role: "status", children: notice }),
5027
- /* @__PURE__ */ jsx11(
5198
+ notice && /* @__PURE__ */ jsx12("p", { className: "db-settings-status db-settings-status--warning", role: "status", children: notice }),
5199
+ /* @__PURE__ */ jsx12(
5028
5200
  WorkspaceSettingsControls,
5029
5201
  {
5030
5202
  value: draft,
@@ -5041,14 +5213,14 @@ function WorkspaceSettingsDialog({
5041
5213
  regenerating: outputsStatus.state === "running"
5042
5214
  }
5043
5215
  ),
5044
- (saveError || !validation.ok && changed) && /* @__PURE__ */ jsx11("p", { className: "db-settings-status db-settings-status--warning", role: "alert", children: saveError ?? (!validation.ok ? validation.message : null) })
5216
+ (saveError || !validation.ok && changed) && /* @__PURE__ */ jsx12("p", { className: "db-settings-status db-settings-status--warning", role: "alert", children: saveError ?? (!validation.ok ? validation.message : null) })
5045
5217
  ]
5046
5218
  }
5047
5219
  );
5048
5220
  }
5049
5221
 
5050
5222
  // src/WorkspaceSettings/useWorkspaceSettings.ts
5051
- import { useCallback as useCallback11, useEffect as useEffect12, useRef as useRef11, useState as useState11 } from "react";
5223
+ import { useCallback as useCallback11, useEffect as useEffect13, useRef as useRef11, useState as useState12 } from "react";
5052
5224
  import { maybeGetDocBlocksHost } from "@bendyline/docblocks/host";
5053
5225
  import { getFileSystemProviderV2 as getFileSystemProviderV24 } from "@bendyline/docblocks/filesystem";
5054
5226
  import {
@@ -5063,13 +5235,13 @@ function sameState(left, right) {
5063
5235
  }
5064
5236
  function useWorkspaceSettings(provider, enabled) {
5065
5237
  const providerV2 = provider && enabled ? getFileSystemProviderV24(provider) : null;
5066
- const [state, setState] = useState11(
5238
+ const [state, setState] = useState12(
5067
5239
  providerV2 ? LOADING_WORKSPACE_SETTINGS : UNAVAILABLE_WORKSPACE_SETTINGS
5068
5240
  );
5069
5241
  const stateRef = useRef11(state);
5070
5242
  stateRef.current = state;
5071
5243
  const generationRef = useRef11(0);
5072
- const [refreshKey, setRefreshKey] = useState11(0);
5244
+ const [refreshKey, setRefreshKey] = useState12(0);
5073
5245
  const refresh = useCallback11(() => setRefreshKey((key) => key + 1), []);
5074
5246
  const providerRef = useRef11(providerV2);
5075
5247
  if (providerRef.current !== providerV2) {
@@ -5079,7 +5251,7 @@ function useWorkspaceSettings(provider, enabled) {
5079
5251
  stateRef.current = reset;
5080
5252
  setState(reset);
5081
5253
  }
5082
- useEffect12(() => {
5254
+ useEffect13(() => {
5083
5255
  if (!providerV2) return;
5084
5256
  const generation = generationRef.current;
5085
5257
  let cancelled = false;
@@ -5094,7 +5266,7 @@ function useWorkspaceSettings(provider, enabled) {
5094
5266
  cancelled = true;
5095
5267
  };
5096
5268
  }, [providerV2, refreshKey]);
5097
- useEffect12(() => {
5269
+ useEffect13(() => {
5098
5270
  if (!providerV2) return;
5099
5271
  window.addEventListener("focus", refresh);
5100
5272
  const stopResume = maybeGetDocBlocksHost()?.lifecycle?.onResume?.(refresh);
@@ -5130,7 +5302,7 @@ function useWorkspaceSettings(provider, enabled) {
5130
5302
  }
5131
5303
 
5132
5304
  // src/WorkspaceSettings/useWorkspaceOutputs.ts
5133
- import { useEffect as useEffect13, useState as useState12, useSyncExternalStore as useSyncExternalStore2 } from "react";
5305
+ import { useEffect as useEffect14, useState as useState13, useSyncExternalStore as useSyncExternalStore2 } from "react";
5134
5306
  import { getFileSystemProviderV2 as getFileSystemProviderV25 } from "@bendyline/docblocks/filesystem";
5135
5307
  import {
5136
5308
  createWorkspaceOutputsScheduler,
@@ -5154,8 +5326,8 @@ var noSubscription = () => () => void 0;
5154
5326
  var idleStatus = () => IDLE_WORKSPACE_OUTPUTS_STATUS;
5155
5327
  function useWorkspaceOutputs(provider, workspaceId, settings, enabled) {
5156
5328
  const providerV2 = provider && enabled ? getFileSystemProviderV25(provider) : null;
5157
- const [scheduler, setScheduler] = useState12(null);
5158
- useEffect13(() => {
5329
+ const [scheduler, setScheduler] = useState13(null);
5330
+ useEffect14(() => {
5159
5331
  if (!providerV2 || !workspaceId) {
5160
5332
  setScheduler(null);
5161
5333
  return;
@@ -5176,7 +5348,7 @@ function useWorkspaceOutputs(provider, workspaceId, settings, enabled) {
5176
5348
  next.dispose();
5177
5349
  };
5178
5350
  }, [providerV2, workspaceId]);
5179
- useEffect13(() => {
5351
+ useEffect14(() => {
5180
5352
  scheduler?.updateSettings(settings);
5181
5353
  }, [scheduler, settings]);
5182
5354
  const status = useSyncExternalStore2(
@@ -5211,22 +5383,22 @@ async function assertNotGeneratedCatalog(provider, path) {
5211
5383
  }
5212
5384
 
5213
5385
  // src/WorkspaceSettings/GeneratedFileView.tsx
5214
- import { Fragment as Fragment7, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
5386
+ import { Fragment as Fragment8, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
5215
5387
  function GeneratedFileNotice({ kind, onOpenSettings, onBack }) {
5216
- return /* @__PURE__ */ jsxs11("div", { className: "db-generated-file-notice", role: "note", children: [
5217
- onBack && /* @__PURE__ */ jsx12("button", { type: "button", className: "db-generated-file-back", onClick: onBack, children: "Back to files" }),
5218
- /* @__PURE__ */ jsxs11("span", { className: "db-generated-file-notice-text", children: [
5219
- /* @__PURE__ */ jsx12("strong", { children: "Generated by DocBlocks \xB7 read-only." }),
5388
+ return /* @__PURE__ */ jsxs12("div", { className: "db-generated-file-notice", role: "note", children: [
5389
+ onBack && /* @__PURE__ */ jsx13("button", { type: "button", className: "db-generated-file-back", onClick: onBack, children: "Back to files" }),
5390
+ /* @__PURE__ */ jsxs12("span", { className: "db-generated-file-notice-text", children: [
5391
+ /* @__PURE__ */ jsx13("strong", { children: "Generated by DocBlocks \xB7 read-only." }),
5220
5392
  " ",
5221
5393
  kind === "catalog-html" ? "This catalog page is rebuilt from the documents in this folder as you save." : "This catalog data is rebuilt from the documents in this folder as you save."
5222
5394
  ] }),
5223
- onOpenSettings && /* @__PURE__ */ jsx12("button", { type: "button", className: "db-git-secondary-btn", onClick: onOpenSettings, children: "Catalog settings\u2026" })
5395
+ onOpenSettings && /* @__PURE__ */ jsx13("button", { type: "button", className: "db-git-secondary-btn", onClick: onOpenSettings, children: "Catalog settings\u2026" })
5224
5396
  ] });
5225
5397
  }
5226
5398
  function GeneratedCatalogPage({ html, fileName, ...notice }) {
5227
- return /* @__PURE__ */ jsxs11("div", { className: "db-generated-file", children: [
5228
- /* @__PURE__ */ jsx12(GeneratedFileNotice, { kind: "catalog-html", ...notice }),
5229
- /* @__PURE__ */ jsx12(
5399
+ return /* @__PURE__ */ jsxs12("div", { className: "db-generated-file", children: [
5400
+ /* @__PURE__ */ jsx13(GeneratedFileNotice, { kind: "catalog-html", ...notice }),
5401
+ /* @__PURE__ */ jsx13(
5230
5402
  "iframe",
5231
5403
  {
5232
5404
  className: "db-generated-file-preview",
@@ -5239,10 +5411,10 @@ function GeneratedCatalogPage({ html, fileName, ...notice }) {
5239
5411
  ] });
5240
5412
  }
5241
5413
  function GeneratedFileFrame({ kind, children, ...notice }) {
5242
- if (!kind) return /* @__PURE__ */ jsx12(Fragment7, { children });
5243
- return /* @__PURE__ */ jsxs11("div", { className: "db-generated-file", children: [
5244
- /* @__PURE__ */ jsx12(GeneratedFileNotice, { kind, ...notice }),
5245
- /* @__PURE__ */ jsx12("div", { className: "db-generated-file-body", children })
5414
+ if (!kind) return /* @__PURE__ */ jsx13(Fragment8, { children });
5415
+ return /* @__PURE__ */ jsxs12("div", { className: "db-generated-file", children: [
5416
+ /* @__PURE__ */ jsx13(GeneratedFileNotice, { kind, ...notice }),
5417
+ /* @__PURE__ */ jsx13("div", { className: "db-generated-file-body", children })
5246
5418
  ] });
5247
5419
  }
5248
5420
 
@@ -5254,14 +5426,14 @@ import {
5254
5426
  } from "@bendyline/docblocks/workspace-settings";
5255
5427
 
5256
5428
  // src/hooks/useDocumentSession.ts
5257
- import { useState as useState13, useSyncExternalStore as useSyncExternalStore3 } from "react";
5429
+ import { useState as useState14, useSyncExternalStore as useSyncExternalStore3 } from "react";
5258
5430
  import {
5259
5431
  DocumentRecoveryJournal,
5260
5432
  DocumentSession,
5261
5433
  getDefaultDocumentRecoveryStorage
5262
5434
  } from "@bendyline/docblocks/document";
5263
5435
  function useDocumentSession(autoSaveDelayMs = 500) {
5264
- const [session] = useState13(
5436
+ const [session] = useState14(
5265
5437
  () => new DocumentSession({
5266
5438
  autoSaveDelayMs,
5267
5439
  recoveryJournal: new DocumentRecoveryJournal(getDefaultDocumentRecoveryStorage())
@@ -5277,14 +5449,14 @@ function useDocumentSession(autoSaveDelayMs = 500) {
5277
5449
 
5278
5450
  // src/Export/DeferredExportToolbarControls.tsx
5279
5451
  import { lazy, Suspense } from "react";
5280
- import { jsx as jsx13 } from "react/jsx-runtime";
5452
+ import { jsx as jsx14 } from "react/jsx-runtime";
5281
5453
  var ExportToolbarControlsImplementation = lazy(
5282
- () => import("./ExportToolbarControls-2XY2CKGH.js").then((module) => ({
5454
+ () => import("./ExportToolbarControls-ZOYH4I36.js").then((module) => ({
5283
5455
  default: module.ExportToolbarControls
5284
5456
  }))
5285
5457
  );
5286
5458
  function ExportToolbarControls(props) {
5287
- return /* @__PURE__ */ jsx13(Suspense, { fallback: null, children: /* @__PURE__ */ jsx13(ExportToolbarControlsImplementation, { ...props }) });
5459
+ return /* @__PURE__ */ jsx14(Suspense, { fallback: null, children: /* @__PURE__ */ jsx14(ExportToolbarControlsImplementation, { ...props }) });
5288
5460
  }
5289
5461
 
5290
5462
  // src/Export/host-export-save.ts
@@ -5324,17 +5496,17 @@ async function saveBlobToHost(exports, documentId, blob, filename, grantId) {
5324
5496
  }
5325
5497
 
5326
5498
  // src/Git/useGit.ts
5327
- import { useCallback as useCallback13, useEffect as useEffect15, useMemo as useMemo3, useRef as useRef13, useState as useState15 } from "react";
5499
+ import { useCallback as useCallback13, useEffect as useEffect16, useMemo as useMemo3, useRef as useRef13, useState as useState16 } from "react";
5328
5500
  import { maybeGetDocBlocksHost as maybeGetDocBlocksHost2 } from "@bendyline/docblocks/host";
5329
5501
 
5330
5502
  // src/Git/useGitStatus.ts
5331
- import { useCallback as useCallback12, useEffect as useEffect14, useRef as useRef12, useState as useState14 } from "react";
5503
+ import { useCallback as useCallback12, useEffect as useEffect15, useRef as useRef12, useState as useState15 } from "react";
5332
5504
  var SCHEDULE_REFRESH_MS = 1500;
5333
5505
  function statusKey(status) {
5334
5506
  return JSON.stringify(status);
5335
5507
  }
5336
5508
  function useGitStatus(gitApi, repositoryId, enabled) {
5337
- const [status, setStatus] = useState14(null);
5509
+ const [status, setStatus] = useState15(null);
5338
5510
  const lastKeyRef = useRef12(null);
5339
5511
  const timerRef = useRef12(null);
5340
5512
  const generationRef = useRef12(0);
@@ -5344,7 +5516,7 @@ function useGitStatus(gitApi, repositoryId, enabled) {
5344
5516
  lastKeyRef.current = key;
5345
5517
  setStatus(next);
5346
5518
  }, []);
5347
- useEffect14(() => {
5519
+ useEffect15(() => {
5348
5520
  generationRef.current += 1;
5349
5521
  if (timerRef.current) {
5350
5522
  clearTimeout(timerRef.current);
@@ -5383,7 +5555,7 @@ function useGitStatus(gitApi, repositoryId, enabled) {
5383
5555
  refresh();
5384
5556
  }, SCHEDULE_REFRESH_MS);
5385
5557
  }, [refresh]);
5386
- useEffect14(() => {
5558
+ useEffect15(() => {
5387
5559
  return () => {
5388
5560
  if (timerRef.current) clearTimeout(timerRef.current);
5389
5561
  };
@@ -5409,8 +5581,8 @@ function useGit(provider, requestedWorkspaceId, theme, onWorkingTreeChanged) {
5409
5581
  const host = maybeGetDocBlocksHost2();
5410
5582
  const gitApi = host?.git ?? null;
5411
5583
  const workspaceId = gitApi ? requestedWorkspaceId : null;
5412
- const [capabilities, setCapabilities] = useState15(null);
5413
- useEffect15(() => {
5584
+ const [capabilities, setCapabilities] = useState16(null);
5585
+ useEffect16(() => {
5414
5586
  if (!gitApi) return;
5415
5587
  let cancelled = false;
5416
5588
  let timer = null;
@@ -5436,9 +5608,9 @@ function useGit(provider, requestedWorkspaceId, theme, onWorkingTreeChanged) {
5436
5608
  };
5437
5609
  }, [gitApi]);
5438
5610
  const available = gitApi !== null && capabilities?.gitAvailable === true;
5439
- const [repo, setRepo] = useState15(null);
5440
- const [remoteWeb, setRemoteWeb] = useState15(null);
5441
- const [pendingGrant, setPendingGrant] = useState15(null);
5611
+ const [repo, setRepo] = useState16(null);
5612
+ const [remoteWeb, setRemoteWeb] = useState16(null);
5613
+ const [pendingGrant, setPendingGrant] = useState16(null);
5442
5614
  const loadRemote = useCallback13(
5443
5615
  (repositoryId2, isCancelled) => {
5444
5616
  if (!gitApi) return;
@@ -5453,7 +5625,7 @@ function useGit(provider, requestedWorkspaceId, theme, onWorkingTreeChanged) {
5453
5625
  },
5454
5626
  [gitApi]
5455
5627
  );
5456
- useEffect15(() => {
5628
+ useEffect16(() => {
5457
5629
  setRepo(null);
5458
5630
  setRemoteWeb(null);
5459
5631
  setPendingGrant(null);
@@ -5479,7 +5651,7 @@ function useGit(provider, requestedWorkspaceId, theme, onWorkingTreeChanged) {
5479
5651
  cancelled = true;
5480
5652
  };
5481
5653
  }, [gitApi, workspaceId, available, loadRemote]);
5482
- const [grantBusy, setGrantBusy] = useState15(false);
5654
+ const [grantBusy, setGrantBusy] = useState16(false);
5483
5655
  const enableExpandedRepo = useCallback13(
5484
5656
  async (opts) => {
5485
5657
  if (!gitApi || !workspaceId) return false;
@@ -5501,9 +5673,9 @@ function useGit(provider, requestedWorkspaceId, theme, onWorkingTreeChanged) {
5501
5673
  const isRepo = repositoryId !== null;
5502
5674
  const { status, refresh, scheduleRefresh } = useGitStatus(gitApi, repositoryId, isRepo);
5503
5675
  const badges = useMemo3(() => buildBadgeMap(status?.changes ?? []), [status]);
5504
- const [busy, setBusy] = useState15(null);
5505
- const [lastResult, setLastResult] = useState15(null);
5506
- const [dialog, setDialog] = useState15({ kind: "none" });
5676
+ const [busy, setBusy] = useState16(null);
5677
+ const [lastResult, setLastResult] = useState16(null);
5678
+ const [dialog, setDialog] = useState16({ kind: "none" });
5507
5679
  const openDialog = useCallback13((next) => {
5508
5680
  setLastResult(null);
5509
5681
  setDialog(next);
@@ -5524,11 +5696,11 @@ function useGit(provider, requestedWorkspaceId, theme, onWorkingTreeChanged) {
5524
5696
  []
5525
5697
  );
5526
5698
  const statusRef = useRef13(status);
5527
- useEffect15(() => {
5699
+ useEffect16(() => {
5528
5700
  statusRef.current = status;
5529
5701
  }, [status]);
5530
5702
  const workingTreeChangedRef = useRef13(onWorkingTreeChanged);
5531
- useEffect15(() => {
5703
+ useEffect16(() => {
5532
5704
  workingTreeChangedRef.current = onWorkingTreeChanged;
5533
5705
  }, [onWorkingTreeChanged]);
5534
5706
  const runAction = useCallback13(
@@ -5739,7 +5911,7 @@ function retainFileSystemProvider(provider) {
5739
5911
  }
5740
5912
 
5741
5913
  // src/DocBlocksShell/document-title.ts
5742
- import { useEffect as useEffect16 } from "react";
5914
+ import { useEffect as useEffect17 } from "react";
5743
5915
  var APP_TITLE = "DocBlocks";
5744
5916
  var INSTALLED_DISPLAY_QUERIES = [
5745
5917
  "(display-mode: window-controls-overlay)",
@@ -5763,7 +5935,7 @@ function titleForSelectedFile(selectedFile, homeDocumentTitle = APP_TITLE, homeD
5763
5935
  return includeAppName ? `${name} - ${APP_TITLE}` : name;
5764
5936
  }
5765
5937
  function useDocumentTitle(selectedFile, homeDocumentTitle, homeDocumentPath) {
5766
- useEffect16(() => {
5938
+ useEffect17(() => {
5767
5939
  if (typeof document === "undefined") return;
5768
5940
  const displayQueries = typeof globalThis.matchMedia === "function" ? INSTALLED_DISPLAY_QUERIES.map((query) => globalThis.matchMedia(query)) : [];
5769
5941
  const updateTitle = () => {
@@ -6087,13 +6259,13 @@ function summariseImport(result) {
6087
6259
  }
6088
6260
 
6089
6261
  // src/components/usePromptDialog.ts
6090
- import React2, { useCallback as useCallback15, useEffect as useEffect18, useRef as useRef15, useState as useState17 } from "react";
6262
+ import React2, { useCallback as useCallback15, useEffect as useEffect19, useRef as useRef15, useState as useState18 } from "react";
6091
6263
 
6092
6264
  // src/components/PromptDialog.tsx
6093
- import { useCallback as useCallback14, useEffect as useEffect17, useId as useId3, useRef as useRef14, useState as useState16 } from "react";
6094
- import { Fragment as Fragment8, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
6265
+ import { useCallback as useCallback14, useEffect as useEffect18, useId as useId3, useRef as useRef14, useState as useState17 } from "react";
6266
+ import { Fragment as Fragment9, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
6095
6267
  function PromptDialog({ request, onSettle }) {
6096
- const [value, setValue] = useState16(request.initialValue ?? "");
6268
+ const [value, setValue] = useState17(request.initialValue ?? "");
6097
6269
  const inputRef = useRef14(null);
6098
6270
  const inputId = useId3();
6099
6271
  const cancel = useCallback14(() => onSettle(null), [onSettle]);
@@ -6102,22 +6274,22 @@ function PromptDialog({ request, onSettle }) {
6102
6274
  onSettle(value);
6103
6275
  }, [onSettle, value]);
6104
6276
  const initialSelection = request.initialSelection;
6105
- useEffect17(() => {
6277
+ useEffect18(() => {
6106
6278
  const input = inputRef.current;
6107
6279
  if (!input) return;
6108
6280
  if (initialSelection) input.setSelectionRange(initialSelection[0], initialSelection[1]);
6109
6281
  else input.select();
6110
6282
  }, []);
6111
- return /* @__PURE__ */ jsx14(
6283
+ return /* @__PURE__ */ jsx15(
6112
6284
  Dialog,
6113
6285
  {
6114
6286
  title: request.title,
6115
6287
  onClose: cancel,
6116
6288
  initialFocusRef: inputRef,
6117
6289
  closeOnBackdrop: false,
6118
- footer: /* @__PURE__ */ jsxs12(Fragment8, { children: [
6119
- /* @__PURE__ */ jsx14("button", { type: "button", className: "db-git-secondary-btn", onClick: cancel, children: "Cancel" }),
6120
- /* @__PURE__ */ jsx14(
6290
+ footer: /* @__PURE__ */ jsxs13(Fragment9, { children: [
6291
+ /* @__PURE__ */ jsx15("button", { type: "button", className: "db-git-secondary-btn", onClick: cancel, children: "Cancel" }),
6292
+ /* @__PURE__ */ jsx15(
6121
6293
  "button",
6122
6294
  {
6123
6295
  type: "button",
@@ -6128,9 +6300,9 @@ function PromptDialog({ request, onSettle }) {
6128
6300
  }
6129
6301
  )
6130
6302
  ] }),
6131
- children: /* @__PURE__ */ jsxs12("div", { className: "db-git-form-row", children: [
6132
- /* @__PURE__ */ jsx14("label", { className: "db-git-form-label", htmlFor: inputId, children: request.label }),
6133
- /* @__PURE__ */ jsx14(
6303
+ children: /* @__PURE__ */ jsxs13("div", { className: "db-git-form-row", children: [
6304
+ /* @__PURE__ */ jsx15("label", { className: "db-git-form-label", htmlFor: inputId, children: request.label }),
6305
+ /* @__PURE__ */ jsx15(
6134
6306
  "input",
6135
6307
  {
6136
6308
  id: inputId,
@@ -6153,7 +6325,7 @@ function PromptDialog({ request, onSettle }) {
6153
6325
 
6154
6326
  // src/components/usePromptDialog.ts
6155
6327
  function usePromptDialog() {
6156
- const [pending, setPending] = useState17(null);
6328
+ const [pending, setPending] = useState18(null);
6157
6329
  const pendingRef = useRef15(null);
6158
6330
  const nextIdRef = useRef15(0);
6159
6331
  const settlePending = useCallback15((value) => {
@@ -6172,7 +6344,7 @@ function usePromptDialog() {
6172
6344
  }),
6173
6345
  [settlePending]
6174
6346
  );
6175
- useEffect18(() => {
6347
+ useEffect19(() => {
6176
6348
  return () => settlePending(null);
6177
6349
  }, [settlePending]);
6178
6350
  const promptDialog = pending ? React2.createElement(PromptDialog, {
@@ -6185,14 +6357,14 @@ function usePromptDialog() {
6185
6357
  }
6186
6358
 
6187
6359
  // src/components/NewDocumentDialog.tsx
6188
- import { useCallback as useCallback16, useEffect as useEffect19, useId as useId4, useRef as useRef16, useState as useState18 } from "react";
6189
- import { Fragment as Fragment9, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
6360
+ import { useCallback as useCallback16, useEffect as useEffect20, useId as useId4, useRef as useRef16, useState as useState19 } from "react";
6361
+ import { Fragment as Fragment10, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
6190
6362
  function NewDocumentDialog({
6191
6363
  onSettle,
6192
6364
  initialFormat = "markdown"
6193
6365
  }) {
6194
- const [name, setName] = useState18("Untitled");
6195
- const [format, setFormat] = useState18(initialFormat);
6366
+ const [name, setName] = useState19("Untitled");
6367
+ const [format, setFormat] = useState19(initialFormat);
6196
6368
  const inputRef = useRef16(null);
6197
6369
  const nameId = useId4();
6198
6370
  const formatId = useId4();
@@ -6203,19 +6375,19 @@ function NewDocumentDialog({
6203
6375
  const submit = useCallback16(() => {
6204
6376
  if (filename) onSettle({ filename, format });
6205
6377
  }, [filename, format, onSettle]);
6206
- useEffect19(() => {
6378
+ useEffect20(() => {
6207
6379
  inputRef.current?.select();
6208
6380
  }, []);
6209
- return /* @__PURE__ */ jsx15(
6381
+ return /* @__PURE__ */ jsx16(
6210
6382
  Dialog,
6211
6383
  {
6212
6384
  title: "New document",
6213
6385
  onClose: cancel,
6214
6386
  initialFocusRef: inputRef,
6215
6387
  closeOnBackdrop: false,
6216
- footer: /* @__PURE__ */ jsxs13(Fragment9, { children: [
6217
- /* @__PURE__ */ jsx15("button", { type: "button", className: "db-git-secondary-btn", onClick: cancel, children: "Cancel" }),
6218
- /* @__PURE__ */ jsx15(
6388
+ footer: /* @__PURE__ */ jsxs14(Fragment10, { children: [
6389
+ /* @__PURE__ */ jsx16("button", { type: "button", className: "db-git-secondary-btn", onClick: cancel, children: "Cancel" }),
6390
+ /* @__PURE__ */ jsx16(
6219
6391
  "button",
6220
6392
  {
6221
6393
  type: "button",
@@ -6226,9 +6398,9 @@ function NewDocumentDialog({
6226
6398
  }
6227
6399
  )
6228
6400
  ] }),
6229
- children: /* @__PURE__ */ jsxs13("div", { className: "db-new-document-fields", children: [
6230
- /* @__PURE__ */ jsx15("label", { className: "db-git-form-label", htmlFor: nameId, children: "Document name" }),
6231
- /* @__PURE__ */ jsx15(
6401
+ children: /* @__PURE__ */ jsxs14("div", { className: "db-new-document-fields", children: [
6402
+ /* @__PURE__ */ jsx16("label", { className: "db-git-form-label", htmlFor: nameId, children: "Document name" }),
6403
+ /* @__PURE__ */ jsx16(
6232
6404
  "input",
6233
6405
  {
6234
6406
  id: nameId,
@@ -6244,8 +6416,8 @@ function NewDocumentDialog({
6244
6416
  }
6245
6417
  }
6246
6418
  ),
6247
- /* @__PURE__ */ jsx15("label", { className: "db-git-form-label", htmlFor: formatId, children: "Type" }),
6248
- /* @__PURE__ */ jsx15(
6419
+ /* @__PURE__ */ jsx16("label", { className: "db-git-form-label", htmlFor: formatId, children: "Type" }),
6420
+ /* @__PURE__ */ jsx16(
6249
6421
  "select",
6250
6422
  {
6251
6423
  id: formatId,
@@ -6253,10 +6425,10 @@ function NewDocumentDialog({
6253
6425
  "aria-describedby": hint ? hintId : void 0,
6254
6426
  value: format,
6255
6427
  onChange: (e) => setFormat(e.target.value),
6256
- children: /* @__PURE__ */ jsx15(NewFileFormatOptions, {})
6428
+ children: /* @__PURE__ */ jsx16(NewFileFormatOptions, {})
6257
6429
  }
6258
6430
  ),
6259
- hint && /* @__PURE__ */ jsx15("p", { id: hintId, className: "db-new-document-hint", children: hint })
6431
+ hint && /* @__PURE__ */ jsx16("p", { id: hintId, className: "db-new-document-hint", children: hint })
6260
6432
  ] })
6261
6433
  }
6262
6434
  );
@@ -6264,7 +6436,7 @@ function NewDocumentDialog({
6264
6436
 
6265
6437
  // src/DocBlocksShell/EditorErrorBoundary.tsx
6266
6438
  import { Component } from "react";
6267
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
6439
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
6268
6440
  var EditorErrorBoundary = class extends Component {
6269
6441
  constructor() {
6270
6442
  super(...arguments);
@@ -6279,11 +6451,11 @@ var EditorErrorBoundary = class extends Component {
6279
6451
  render() {
6280
6452
  const { error } = this.state;
6281
6453
  if (!error) return this.props.children;
6282
- return /* @__PURE__ */ jsx16("div", { className: "db-shell-empty db-shell-empty--workspace", role: "alert", children: /* @__PURE__ */ jsxs14("div", { className: "db-workspace-empty-content", children: [
6283
- /* @__PURE__ */ jsx16("h1", { children: "This document couldn\u2019t be displayed" }),
6284
- /* @__PURE__ */ jsx16("p", { children: "The editor ran into a problem drawing it. The document itself is unaffected." }),
6285
- /* @__PURE__ */ jsx16("div", { className: "db-workspace-empty-actions", children: /* @__PURE__ */ jsx16("button", { type: "button", onClick: () => this.setState({ error: null }), children: "Try again" }) }),
6286
- /* @__PURE__ */ jsx16("p", { className: "db-workspace-empty-hint", children: error.message })
6454
+ return /* @__PURE__ */ jsx17("div", { className: "db-shell-empty db-shell-empty--workspace", role: "alert", children: /* @__PURE__ */ jsxs15("div", { className: "db-workspace-empty-content", children: [
6455
+ /* @__PURE__ */ jsx17("h1", { children: "This document couldn\u2019t be displayed" }),
6456
+ /* @__PURE__ */ jsx17("p", { children: "The editor ran into a problem drawing it. The document itself is unaffected." }),
6457
+ /* @__PURE__ */ jsx17("div", { className: "db-workspace-empty-actions", children: /* @__PURE__ */ jsx17("button", { type: "button", onClick: () => this.setState({ error: null }), children: "Try again" }) }),
6458
+ /* @__PURE__ */ jsx17("p", { className: "db-workspace-empty-hint", children: error.message })
6287
6459
  ] }) });
6288
6460
  }
6289
6461
  };
@@ -6400,81 +6572,6 @@ function loadLastState(storage = localStorage) {
6400
6572
  }
6401
6573
  }
6402
6574
 
6403
- // src/layout/form-factor.ts
6404
- var DB_BREAKPOINTS = Object.freeze({
6405
- /** Inclusive upper bound for phones and narrow slivers. */
6406
- compactMax: 720,
6407
- /** Inclusive upper bound for tablet-portrait and half-screen laptops. */
6408
- mediumMax: 1023,
6409
- /** Inclusive upper bound for tablet-landscape and laptops. */
6410
- expandedMax: 1439,
6411
- /**
6412
- * Largest short edge still considered a phone. Orientation-independent on
6413
- * purpose: a phone turned sideways is 844x390, which is `medium` by width but
6414
- * is obviously not a tablet. The widest phone short edge in circulation is
6415
- * around 430px; the narrowest tablet short edge is the iPad mini's 744px, so
6416
- * 520 sits in open space between them.
6417
- */
6418
- phoneMaxShortEdge: 520
6419
- });
6420
- var SIDEBAR_WIDTH_DEFAULT = 320;
6421
- var SIDEBAR_WIDTH_MIN = 320;
6422
- var SIDEBAR_WIDTH_MAX = 600;
6423
- var SIDEBAR_COLLAPSE_THRESHOLD = SIDEBAR_WIDTH_MIN;
6424
- var DB_LAYOUT_MINIMA = Object.freeze({
6425
- /**
6426
- * Narrower than this, an editor pane beside the sidebar is not worth the
6427
- * split. Paired with `SIDEBAR_WIDTH_MIN` to derive `splitPaneAllowed`.
6428
- */
6429
- editorMinWidth: 480
6430
- });
6431
- var SPLIT_PANE_MIN_WIDTH = SIDEBAR_WIDTH_MIN + DB_LAYOUT_MINIMA.editorMinWidth;
6432
- function classifyWidth(width) {
6433
- if (width <= DB_BREAKPOINTS.compactMax) return "compact";
6434
- if (width <= DB_BREAKPOINTS.mediumMax) return "medium";
6435
- if (width <= DB_BREAKPOINTS.expandedMax) return "expanded";
6436
- return "wide";
6437
- }
6438
- function classifyFormFactor(input) {
6439
- const widthClass = classifyWidth(input.width);
6440
- const orientation = input.height >= input.width ? "portrait" : "landscape";
6441
- let formFactor;
6442
- if (input.pointer === "fine") {
6443
- formFactor = "desktop";
6444
- } else if (Math.min(input.width, input.height) <= DB_BREAKPOINTS.phoneMaxShortEdge) {
6445
- formFactor = "phone";
6446
- } else {
6447
- formFactor = orientation === "portrait" ? "tablet-portrait" : "tablet-landscape";
6448
- }
6449
- return {
6450
- ...input,
6451
- widthClass,
6452
- orientation,
6453
- formFactor,
6454
- splitPaneAllowed: input.width >= SPLIT_PANE_MIN_WIDTH
6455
- };
6456
- }
6457
- function resolveLayoutMode(formFactor, preference) {
6458
- if (!formFactor.splitPaneAllowed) return "single-pane";
6459
- if (preference === "collapsed") return "single-pane";
6460
- if (preference === "pinned") return "split-pane";
6461
- if (formFactor.widthClass === "expanded" || formFactor.widthClass === "wide") {
6462
- return "split-pane";
6463
- }
6464
- if (formFactor.pointer === "fine") return "split-pane";
6465
- return "single-pane";
6466
- }
6467
- function formFactorDataAttributes(formFactor, layoutMode) {
6468
- return Object.freeze({
6469
- "data-db-width": formFactor.widthClass,
6470
- "data-db-form-factor": formFactor.formFactor,
6471
- "data-db-pointer": formFactor.pointer,
6472
- "data-db-hover": formFactor.hover,
6473
- "data-db-orientation": formFactor.orientation,
6474
- "data-db-layout": layoutMode
6475
- });
6476
- }
6477
-
6478
6575
  // src/DocBlocksShell/shell-preferences.ts
6479
6576
  var WELCOME_GATEWAY_KEY = "docblocks:welcomeGatewayDismissed";
6480
6577
  var SIDEBAR_WIDTH_KEY = "docblocks:sidebarWidth";
@@ -6573,34 +6670,6 @@ function saveViewPreferences(preferences) {
6573
6670
 
6574
6671
  // src/layout/useFormFactor.ts
6575
6672
  import { useEffect as useEffect21, useMemo as useMemo4, useState as useState20 } from "react";
6576
-
6577
- // src/layout/useMediaQuery.ts
6578
- import { useEffect as useEffect20, useState as useState19 } from "react";
6579
- var INSTALLED_DISPLAY_QUERIES2 = [
6580
- "(display-mode: window-controls-overlay)",
6581
- "(display-mode: standalone)"
6582
- ];
6583
- function matchesMediaQuery(query) {
6584
- if (typeof globalThis.matchMedia !== "function") return false;
6585
- return globalThis.matchMedia(query).matches;
6586
- }
6587
- function isInstalledDisplayMode() {
6588
- return INSTALLED_DISPLAY_QUERIES2.some(matchesMediaQuery);
6589
- }
6590
- function useMediaQuery(query) {
6591
- const [matches, setMatches] = useState19(() => matchesMediaQuery(query));
6592
- useEffect20(() => {
6593
- if (typeof globalThis.matchMedia !== "function") return;
6594
- const list = globalThis.matchMedia(query);
6595
- const update = () => setMatches(list.matches);
6596
- update();
6597
- list.addEventListener("change", update);
6598
- return () => list.removeEventListener("change", update);
6599
- }, [query]);
6600
- return matches;
6601
- }
6602
-
6603
- // src/layout/useFormFactor.ts
6604
6673
  var COARSE_POINTER_QUERY = "(pointer: coarse)";
6605
6674
  var ANY_HOVER_QUERY = "(any-hover: hover)";
6606
6675
  function initialSize() {
@@ -6947,9 +7016,101 @@ function useShellShortcuts(handlers, layoutMode) {
6947
7016
  }, [layoutMode]);
6948
7017
  }
6949
7018
 
7019
+ // src/DocBlocksShell/DocumentConflictBanner.tsx
7020
+ import { useEffect as useEffect29, useState as useState22 } from "react";
7021
+
7022
+ // src/DocBlocksShell/conflict-summary.ts
7023
+ var SECOND_MS = 1e3;
7024
+ var MINUTE_MS2 = 60 * SECOND_MS;
7025
+ var HOUR_MS2 = 60 * MINUTE_MS2;
7026
+ var DAY_MS2 = 24 * HOUR_MS2;
7027
+ var shortDateFormatter2 = new Intl.DateTimeFormat(void 0, { month: "short", day: "numeric" });
7028
+ function plural2(value, unit) {
7029
+ return `${value.toLocaleString()} ${unit}${value === 1 ? "" : "s"}`;
7030
+ }
7031
+ function describeAge(timestamp, now) {
7032
+ const elapsed = now - timestamp;
7033
+ if (elapsed < -MINUTE_MS2) return null;
7034
+ if (elapsed < 10 * SECOND_MS) return "just now";
7035
+ if (elapsed < MINUTE_MS2) return `${Math.floor(elapsed / (10 * SECOND_MS)) * 10} seconds ago`;
7036
+ if (elapsed < HOUR_MS2) return `${plural2(Math.floor(elapsed / MINUTE_MS2), "minute")} ago`;
7037
+ if (elapsed < DAY_MS2) return `${plural2(Math.floor(elapsed / HOUR_MS2), "hour")} ago`;
7038
+ if (elapsed < 2 * DAY_MS2) return "yesterday";
7039
+ if (elapsed < 7 * DAY_MS2) return `${plural2(Math.floor(elapsed / DAY_MS2), "day")} ago`;
7040
+ return `on ${shortDateFormatter2.format(new Date(timestamp))}`;
7041
+ }
7042
+ function describeVersion(label, content, verb, at, now) {
7043
+ const age = at === void 0 ? null : describeAge(at, now);
7044
+ const size = plural2(Array.from(content).length, "character");
7045
+ return `${label}: ${size}${age ? `, ${verb} ${age}` : ""}.`;
7046
+ }
7047
+ function localVersionTime(conflict) {
7048
+ return conflict.localEditedAt ?? conflict.recoveredDraftCapturedAt;
7049
+ }
7050
+ function describeConflictVersions(conflict, savedAt, now) {
7051
+ const local = describeVersion(
7052
+ conflict.recoveredDraft ? "Recovery draft" : "Your version",
7053
+ conflict.localContent,
7054
+ "edited",
7055
+ localVersionTime(conflict),
7056
+ now
7057
+ );
7058
+ const saved = conflict.externalContent === null ? "The saved file was deleted." : describeVersion("Saved file", conflict.externalContent, "updated", savedAt, now);
7059
+ return `${local} ${saved}`;
7060
+ }
7061
+
7062
+ // src/DocBlocksShell/DocumentConflictBanner.tsx
7063
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
7064
+ function DocumentConflictBanner({
7065
+ conflict,
7066
+ readSavedFile,
7067
+ onCompare,
7068
+ onDismiss
7069
+ }) {
7070
+ const [savedAt, setSavedAt] = useState22(void 0);
7071
+ const [now, setNow] = useState22(() => Date.now());
7072
+ useEffect29(() => {
7073
+ let disposed = false;
7074
+ setSavedAt(void 0);
7075
+ if (conflict.externalContent === null) return;
7076
+ void readSavedFile().then(
7077
+ (file) => {
7078
+ if (disposed || !file?.lastModified || file.content !== conflict.externalContent) return;
7079
+ const parsed = Date.parse(file.lastModified);
7080
+ if (Number.isFinite(parsed)) setSavedAt(parsed);
7081
+ },
7082
+ () => {
7083
+ }
7084
+ );
7085
+ return () => {
7086
+ disposed = true;
7087
+ };
7088
+ }, [readSavedFile, conflict.targetKey, conflict.externalContent, conflict.externalVersion]);
7089
+ const localAt = localVersionTime(conflict);
7090
+ useEffect29(() => {
7091
+ if (localAt === void 0 && savedAt === void 0) return;
7092
+ const newest = Math.max(localAt ?? 0, savedAt ?? 0);
7093
+ const timer = setTimeout(
7094
+ () => setNow(Date.now()),
7095
+ Date.now() - newest < MINUTE_MS2 ? 5e3 : 3e4
7096
+ );
7097
+ return () => clearTimeout(timer);
7098
+ }, [now, localAt, savedAt]);
7099
+ return /* @__PURE__ */ jsxs16("div", { className: "db-document-conflict", children: [
7100
+ /* @__PURE__ */ jsxs16("div", { className: "db-document-conflict-text", children: [
7101
+ /* @__PURE__ */ jsx18("span", { role: "alert", children: conflict.recoveredDraft ? "A recovery draft from a previous session differs from the saved file. The saved file may be newer. Choose which version to use." : "This document changed outside DocBlocks. Your unsaved version is still intact." }),
7102
+ /* @__PURE__ */ jsx18("span", { className: "db-document-conflict-details", children: describeConflictVersions(conflict, savedAt, now) })
7103
+ ] }),
7104
+ /* @__PURE__ */ jsxs16("div", { className: "db-document-conflict-actions", children: [
7105
+ /* @__PURE__ */ jsx18("button", { type: "button", onClick: onCompare, children: "Compare versions" }),
7106
+ /* @__PURE__ */ jsx18("button", { type: "button", onClick: onDismiss, children: "Dismiss" })
7107
+ ] })
7108
+ ] });
7109
+ }
7110
+
6950
7111
  // src/DocBlocksShell/UpdateAvailableNotice.tsx
6951
- import { useState as useState22 } from "react";
6952
- import { Fragment as Fragment10, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
7112
+ import { useState as useState23 } from "react";
7113
+ import { Fragment as Fragment11, jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
6953
7114
  var UPDATE_PROMPT_ID = "db-update-available-prompt";
6954
7115
  function UpdateAvailableNotice({
6955
7116
  available,
@@ -6957,12 +7118,12 @@ function UpdateAvailableNotice({
6957
7118
  blocked = false,
6958
7119
  statusBarVisible
6959
7120
  }) {
6960
- const [promptOpen, setPromptOpen] = useState22(false);
6961
- const [applying, setApplying] = useState22(false);
7121
+ const [promptOpen, setPromptOpen] = useState23(false);
7122
+ const [applying, setApplying] = useState23(false);
6962
7123
  if (!available || !onApplyUpdate) return null;
6963
7124
  const promptVisible = promptOpen && !blocked;
6964
- return /* @__PURE__ */ jsxs15(Fragment10, { children: [
6965
- /* @__PURE__ */ jsx17(
7125
+ return /* @__PURE__ */ jsxs17(Fragment11, { children: [
7126
+ /* @__PURE__ */ jsx19(
6966
7127
  "button",
6967
7128
  {
6968
7129
  type: "button",
@@ -6976,16 +7137,16 @@ function UpdateAvailableNotice({
6976
7137
  children: "Update available"
6977
7138
  }
6978
7139
  ),
6979
- promptVisible && /* @__PURE__ */ jsxs15(
7140
+ promptVisible && /* @__PURE__ */ jsxs17(
6980
7141
  "div",
6981
7142
  {
6982
7143
  id: UPDATE_PROMPT_ID,
6983
7144
  className: `db-update-banner${statusBarVisible ? "" : " db-update-banner--floating"}`,
6984
7145
  role: "alert",
6985
7146
  children: [
6986
- /* @__PURE__ */ jsx17("span", { children: "A new version of DocBlocks is available. Reload to update the editor and site pages." }),
6987
- /* @__PURE__ */ jsxs15("div", { className: "db-update-banner-actions", children: [
6988
- /* @__PURE__ */ jsx17(
7147
+ /* @__PURE__ */ jsx19("span", { children: "A new version of DocBlocks is available. Reload to update the editor and site pages." }),
7148
+ /* @__PURE__ */ jsxs17("div", { className: "db-update-banner-actions", children: [
7149
+ /* @__PURE__ */ jsx19(
6989
7150
  "button",
6990
7151
  {
6991
7152
  type: "button",
@@ -6997,7 +7158,7 @@ function UpdateAvailableNotice({
6997
7158
  children: applying ? "Updating\u2026" : "Reload"
6998
7159
  }
6999
7160
  ),
7000
- /* @__PURE__ */ jsx17("button", { type: "button", onClick: () => setPromptOpen(false), disabled: applying, children: "Later" })
7161
+ /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => setPromptOpen(false), disabled: applying, children: "Later" })
7001
7162
  ] })
7002
7163
  ]
7003
7164
  }
@@ -7006,7 +7167,7 @@ function UpdateAvailableNotice({
7006
7167
  }
7007
7168
 
7008
7169
  // src/DocBlocksShell/WelcomeScreen.tsx
7009
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
7170
+ import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
7010
7171
  var WELCOME_HEADLINE = "The Markdown editor that turns one file into anything.";
7011
7172
  var WELCOME_SUMMARY = "Write the way you normally would, then share the same file as a PDF, a Word document, a slide deck, or a video.";
7012
7173
  var WELCOME_PRIVACY_NOTE = "No account, and your documents stay on this device.";
@@ -7017,8 +7178,8 @@ function WelcomeScreen({
7017
7178
  onDismiss,
7018
7179
  offerApps = false
7019
7180
  }) {
7020
- return /* @__PURE__ */ jsxs16("section", { className: "db-welcome-gateway", "aria-labelledby": "db-welcome-gateway-title", children: [
7021
- /* @__PURE__ */ jsx18(
7181
+ return /* @__PURE__ */ jsxs18("section", { className: "db-welcome-gateway", "aria-labelledby": "db-welcome-gateway-title", children: [
7182
+ /* @__PURE__ */ jsx20(
7022
7183
  "button",
7023
7184
  {
7024
7185
  type: "button",
@@ -7029,16 +7190,16 @@ function WelcomeScreen({
7029
7190
  children: "\xD7"
7030
7191
  }
7031
7192
  ),
7032
- /* @__PURE__ */ jsxs16("div", { className: "db-welcome-gateway-body", children: [
7033
- /* @__PURE__ */ jsxs16("div", { className: "db-welcome-gateway-copy", children: [
7034
- /* @__PURE__ */ jsx18("p", { className: "db-welcome-gateway-eyebrow", children: "Welcome to DocBlocks" }),
7035
- /* @__PURE__ */ jsx18("h1", { id: "db-welcome-gateway-title", children: WELCOME_HEADLINE }),
7036
- /* @__PURE__ */ jsx18("p", { children: WELCOME_SUMMARY }),
7037
- /* @__PURE__ */ jsx18("p", { className: "db-welcome-gateway-note", children: WELCOME_PRIVACY_NOTE }),
7038
- /* @__PURE__ */ jsxs16("div", { className: "db-welcome-gateway-actions", children: [
7039
- /* @__PURE__ */ jsx18("button", { type: "button", className: "db-welcome-gateway-primary", onClick: onCreateDocument, children: "Create a document" }),
7040
- /* @__PURE__ */ jsx18("button", { type: "button", className: "db-welcome-gateway-cta", onClick: onTour, children: "Tour the welcome document" }),
7041
- offerApps && /* @__PURE__ */ jsx18(
7193
+ /* @__PURE__ */ jsxs18("div", { className: "db-welcome-gateway-body", children: [
7194
+ /* @__PURE__ */ jsxs18("div", { className: "db-welcome-gateway-copy", children: [
7195
+ /* @__PURE__ */ jsx20("p", { className: "db-welcome-gateway-eyebrow", children: "Welcome to DocBlocks" }),
7196
+ /* @__PURE__ */ jsx20("h1", { id: "db-welcome-gateway-title", children: WELCOME_HEADLINE }),
7197
+ /* @__PURE__ */ jsx20("p", { children: WELCOME_SUMMARY }),
7198
+ /* @__PURE__ */ jsx20("p", { className: "db-welcome-gateway-note", children: WELCOME_PRIVACY_NOTE }),
7199
+ /* @__PURE__ */ jsxs18("div", { className: "db-welcome-gateway-actions", children: [
7200
+ /* @__PURE__ */ jsx20("button", { type: "button", className: "db-welcome-gateway-primary", onClick: onCreateDocument, children: "Create a document" }),
7201
+ /* @__PURE__ */ jsx20("button", { type: "button", className: "db-welcome-gateway-cta", onClick: onTour, children: "Tour the welcome document" }),
7202
+ offerApps && /* @__PURE__ */ jsx20(
7042
7203
  "a",
7043
7204
  {
7044
7205
  className: "db-welcome-gateway-apps",
@@ -7050,55 +7211,55 @@ function WelcomeScreen({
7050
7211
  )
7051
7212
  ] })
7052
7213
  ] }),
7053
- /* @__PURE__ */ jsx18(WelcomeLoop, {})
7214
+ /* @__PURE__ */ jsx20(WelcomeLoop, {})
7054
7215
  ] })
7055
7216
  ] });
7056
7217
  }
7057
7218
  function WelcomeLoop() {
7058
- return /* @__PURE__ */ jsxs16("div", { className: "db-welcome-loop", "aria-hidden": "true", children: [
7059
- /* @__PURE__ */ jsxs16("div", { className: "db-welcome-loop-source", children: [
7060
- /* @__PURE__ */ jsx18("span", { className: "db-welcome-loop-file", children: "Lisbon.md" }),
7061
- /* @__PURE__ */ jsxs16("code", { children: [
7062
- /* @__PURE__ */ jsx18("span", { className: "db-welcome-loop-mark", children: "# " }),
7219
+ return /* @__PURE__ */ jsxs18("div", { className: "db-welcome-loop", "aria-hidden": "true", children: [
7220
+ /* @__PURE__ */ jsxs18("div", { className: "db-welcome-loop-source", children: [
7221
+ /* @__PURE__ */ jsx20("span", { className: "db-welcome-loop-file", children: "Lisbon.md" }),
7222
+ /* @__PURE__ */ jsxs18("code", { children: [
7223
+ /* @__PURE__ */ jsx20("span", { className: "db-welcome-loop-mark", children: "# " }),
7063
7224
  "Lisbon in three days",
7064
7225
  "\n",
7065
7226
  "Trams, tiles, and pastries.",
7066
7227
  "\n\n",
7067
- /* @__PURE__ */ jsx18("span", { className: "db-welcome-loop-mark", children: "## " }),
7228
+ /* @__PURE__ */ jsx20("span", { className: "db-welcome-loop-mark", children: "## " }),
7068
7229
  "Day one",
7069
7230
  "\n",
7070
- /* @__PURE__ */ jsx18("span", { className: "db-welcome-loop-mark", children: "- " }),
7231
+ /* @__PURE__ */ jsx20("span", { className: "db-welcome-loop-mark", children: "- " }),
7071
7232
  "Ride Tram 28",
7072
7233
  "\n",
7073
- /* @__PURE__ */ jsx18("span", { className: "db-welcome-loop-mark", children: "- " }),
7234
+ /* @__PURE__ */ jsx20("span", { className: "db-welcome-loop-mark", children: "- " }),
7074
7235
  "Sunset at Gra\xE7a"
7075
7236
  ] })
7076
7237
  ] }),
7077
- /* @__PURE__ */ jsx18("div", { className: "db-welcome-loop-arrow", children: "\u2192" }),
7078
- /* @__PURE__ */ jsxs16("div", { className: "db-welcome-loop-stage", children: [
7079
- /* @__PURE__ */ jsxs16("div", { className: "db-welcome-loop-frame db-welcome-loop-frame--page", children: [
7080
- /* @__PURE__ */ jsx18("strong", { children: "Lisbon in three days" }),
7081
- /* @__PURE__ */ jsx18("span", { children: "Trams, tiles, and pastries." }),
7082
- /* @__PURE__ */ jsx18("em", { children: "Day one" }),
7083
- /* @__PURE__ */ jsx18("span", { children: "\u2022 Ride Tram 28" }),
7084
- /* @__PURE__ */ jsx18("span", { children: "\u2022 Sunset at Gra\xE7a" })
7238
+ /* @__PURE__ */ jsx20("div", { className: "db-welcome-loop-arrow", children: "\u2192" }),
7239
+ /* @__PURE__ */ jsxs18("div", { className: "db-welcome-loop-stage", children: [
7240
+ /* @__PURE__ */ jsxs18("div", { className: "db-welcome-loop-frame db-welcome-loop-frame--page", children: [
7241
+ /* @__PURE__ */ jsx20("strong", { children: "Lisbon in three days" }),
7242
+ /* @__PURE__ */ jsx20("span", { children: "Trams, tiles, and pastries." }),
7243
+ /* @__PURE__ */ jsx20("em", { children: "Day one" }),
7244
+ /* @__PURE__ */ jsx20("span", { children: "\u2022 Ride Tram 28" }),
7245
+ /* @__PURE__ */ jsx20("span", { children: "\u2022 Sunset at Gra\xE7a" })
7085
7246
  ] }),
7086
- /* @__PURE__ */ jsxs16("div", { className: "db-welcome-loop-frame db-welcome-loop-frame--slide", children: [
7087
- /* @__PURE__ */ jsx18("strong", { children: "Lisbon in three days" }),
7088
- /* @__PURE__ */ jsx18("span", { children: "Trams, tiles, and pastries." })
7247
+ /* @__PURE__ */ jsxs18("div", { className: "db-welcome-loop-frame db-welcome-loop-frame--slide", children: [
7248
+ /* @__PURE__ */ jsx20("strong", { children: "Lisbon in three days" }),
7249
+ /* @__PURE__ */ jsx20("span", { children: "Trams, tiles, and pastries." })
7089
7250
  ] }),
7090
- /* @__PURE__ */ jsxs16("div", { className: "db-welcome-loop-frame db-welcome-loop-frame--video", children: [
7091
- /* @__PURE__ */ jsx18("em", { children: "Day one" }),
7092
- /* @__PURE__ */ jsx18("span", { children: "\u2022 Ride Tram 28" }),
7093
- /* @__PURE__ */ jsx18("span", { children: "\u2022 Sunset at Gra\xE7a" }),
7094
- /* @__PURE__ */ jsx18("i", { className: "db-welcome-loop-play", children: "\u25B6" }),
7095
- /* @__PURE__ */ jsx18("i", { className: "db-welcome-loop-progress" })
7251
+ /* @__PURE__ */ jsxs18("div", { className: "db-welcome-loop-frame db-welcome-loop-frame--video", children: [
7252
+ /* @__PURE__ */ jsx20("em", { children: "Day one" }),
7253
+ /* @__PURE__ */ jsx20("span", { children: "\u2022 Ride Tram 28" }),
7254
+ /* @__PURE__ */ jsx20("span", { children: "\u2022 Sunset at Gra\xE7a" }),
7255
+ /* @__PURE__ */ jsx20("i", { className: "db-welcome-loop-play", children: "\u25B6" }),
7256
+ /* @__PURE__ */ jsx20("i", { className: "db-welcome-loop-progress" })
7096
7257
  ] })
7097
7258
  ] }),
7098
- /* @__PURE__ */ jsxs16("ol", { className: "db-welcome-loop-labels", children: [
7099
- /* @__PURE__ */ jsx18("li", { children: "PDF" }),
7100
- /* @__PURE__ */ jsx18("li", { children: "Slides" }),
7101
- /* @__PURE__ */ jsx18("li", { children: "Video" })
7259
+ /* @__PURE__ */ jsxs18("ol", { className: "db-welcome-loop-labels", children: [
7260
+ /* @__PURE__ */ jsx20("li", { children: "PDF" }),
7261
+ /* @__PURE__ */ jsx20("li", { children: "Slides" }),
7262
+ /* @__PURE__ */ jsx20("li", { children: "Video" })
7102
7263
  ] })
7103
7264
  ] });
7104
7265
  }
@@ -7166,7 +7327,7 @@ function useDocumentLinkProvider(index, selectedFile, ensureIndex) {
7166
7327
  }
7167
7328
 
7168
7329
  // src/WorkspaceIndex/useWorkspaceIndex.ts
7169
- import { useCallback as useCallback18, useEffect as useEffect29, useMemo as useMemo5, useRef as useRef20, useState as useState23, useSyncExternalStore as useSyncExternalStore4 } from "react";
7330
+ import { useCallback as useCallback18, useEffect as useEffect30, useMemo as useMemo5, useRef as useRef20, useState as useState24, useSyncExternalStore as useSyncExternalStore4 } from "react";
7170
7331
  import { getFileSystemProviderV2 as getFileSystemProviderV29 } from "@bendyline/docblocks/filesystem";
7171
7332
  import { maybeGetDocBlocksHost as maybeGetDocBlocksHost3 } from "@bendyline/docblocks/host";
7172
7333
  var IDLE_WORKSPACE_INDEX_STATUS = Object.freeze({
@@ -7198,9 +7359,9 @@ function whenIdle(callback) {
7198
7359
  }
7199
7360
  function useWorkspaceIndex(provider, workspaceId, mode = "eager") {
7200
7361
  const providerV2 = provider && mode !== "off" ? getFileSystemProviderV29(provider) : null;
7201
- const [index, setIndex] = useState23(null);
7362
+ const [index, setIndex] = useState24(null);
7202
7363
  const startRequestedRef = useRef20(false);
7203
- useEffect29(() => {
7364
+ useEffect30(() => {
7204
7365
  setIndex(null);
7205
7366
  startRequestedRef.current = false;
7206
7367
  if (!providerV2 || !workspaceId) return;
@@ -7222,7 +7383,7 @@ function useWorkspaceIndex(provider, workspaceId, mode = "eager") {
7222
7383
  created?.dispose();
7223
7384
  };
7224
7385
  }, [providerV2, workspaceId, mode]);
7225
- useEffect29(() => {
7386
+ useEffect30(() => {
7226
7387
  if (!index) return;
7227
7388
  const refresh = () => index.refresh();
7228
7389
  const onVisibilityChange = () => {
@@ -7598,7 +7759,7 @@ var WELCOME_DOCUMENT_CONTENT = welcomeDocumentContent({
7598
7759
  });
7599
7760
 
7600
7761
  // src/DocBlocksShell/DocBlocksShell.tsx
7601
- import { Fragment as Fragment11, jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
7762
+ import { Fragment as Fragment12, jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
7602
7763
  var editorShellModulePromise = null;
7603
7764
  function loadEditorShell() {
7604
7765
  editorShellModulePromise ?? (editorShellModulePromise = (async () => {
@@ -7610,13 +7771,13 @@ function loadEditorShell() {
7610
7771
  return editorShellModulePromise;
7611
7772
  }
7612
7773
  var EditorShell = lazy2(loadEditorShell);
7613
- var DocumentConflictDialog = lazy2(() => import("./DocumentConflictDialog-DZ2BV2IH.js"));
7614
- var GitUI = lazy2(() => import("./GitUI-F3CNBURE.js").then((m) => ({ default: m.GitUI })));
7774
+ var DocumentConflictDialog = lazy2(() => import("./DocumentConflictDialog-4R4QMKBT.js"));
7775
+ var GitUI = lazy2(() => import("./GitUI-3FANM7I3.js").then((m) => ({ default: m.GitUI })));
7615
7776
  var QuickOpenDialog = lazy2(
7616
- () => import("./QuickOpenDialog-3QEX7RZG.js").then((m) => ({ default: m.QuickOpenDialog }))
7777
+ () => import("./QuickOpenDialog-U2FWCEPA.js").then((m) => ({ default: m.QuickOpenDialog }))
7617
7778
  );
7618
7779
  var KeyboardShortcutsDialog = lazy2(
7619
- () => import("./KeyboardShortcutsDialog-HVKDFP5Z.js").then((m) => ({ default: m.KeyboardShortcutsDialog }))
7780
+ () => import("./KeyboardShortcutsDialog-7XJTDIX2.js").then((m) => ({ default: m.KeyboardShortcutsDialog }))
7620
7781
  );
7621
7782
  var WorkspaceSearchPanel = lazy2(
7622
7783
  () => import("./WorkspaceSearchPanel-MEBBTK7F.js").then((m) => ({
@@ -7630,37 +7791,42 @@ var GitToolbarControl = lazy2(
7630
7791
  () => import("./GitToolbarControl-B7KG4MFP.js").then((m) => ({ default: m.GitToolbarControl }))
7631
7792
  );
7632
7793
  var AiToolbarControl = lazy2(
7633
- () => import("./AiEditorAssistant-4B2PFFOT.js").then((module) => ({
7794
+ () => import("./AiEditorAssistant-ANYGVG7P.js").then((module) => ({
7634
7795
  default: module.AiToolbarControl
7635
7796
  }))
7636
7797
  );
7637
7798
  var PresentationMaker = lazy2(
7638
- () => import("./PresentationMaker-VYQKNL3L.js").then((module) => ({
7799
+ () => import("./PresentationMaker-COLTVMTS.js").then((module) => ({
7639
7800
  default: module.PresentationMaker
7640
7801
  }))
7641
7802
  );
7642
7803
  var AiReviewPanel = lazy2(
7643
- () => import("./AiEditorAssistant-4B2PFFOT.js").then((module) => ({
7804
+ () => import("./AiEditorAssistant-ANYGVG7P.js").then((module) => ({
7644
7805
  default: module.AiReviewPanel
7645
7806
  }))
7646
7807
  );
7647
7808
  var AiIllustratePanel = lazy2(
7648
- () => import("./AiDiagrams-7KBAOXPB.js").then((module) => ({
7809
+ () => import("./AiDiagrams-2IKKSBAU.js").then((module) => ({
7649
7810
  default: module.AiIllustratePanel
7650
7811
  }))
7651
7812
  );
7813
+ var AiImagePanel = lazy2(
7814
+ () => import("./AiImagePanel-OXWEFOBC.js").then((module) => ({
7815
+ default: module.AiImagePanel
7816
+ }))
7817
+ );
7652
7818
  var TextFromNarration = lazy2(
7653
- () => import("./TextFromNarration-ME6FAYWO.js").then((module) => ({
7819
+ () => import("./TextFromNarration-6BYTUKVZ.js").then((module) => ({
7654
7820
  default: module.TextFromNarration
7655
7821
  }))
7656
7822
  );
7657
7823
  var SpeechToolbarControl = lazy2(
7658
- () => import("./SpeechToolbarControl-E6OSJGHL.js").then((module) => ({
7824
+ () => import("./SpeechToolbarControl-BZW6IVZM.js").then((module) => ({
7659
7825
  default: module.SpeechToolbarControl
7660
7826
  }))
7661
7827
  );
7662
7828
  var SpeechMenuBridge = lazy2(
7663
- () => import("./SpeechToolbarControl-E6OSJGHL.js").then((module) => ({
7829
+ () => import("./SpeechToolbarControl-BZW6IVZM.js").then((module) => ({
7664
7830
  default: module.SpeechMenuBridge
7665
7831
  }))
7666
7832
  );
@@ -7738,10 +7904,10 @@ function isMemoryWorkspaceProvider(provider) {
7738
7904
  return typeof candidate.captureContents === "function" && typeof candidate.replaceContents === "function" && typeof candidate.treeVersion === "number";
7739
7905
  }
7740
7906
  function useOsTheme() {
7741
- const [dark, setDark] = useState24(
7907
+ const [dark, setDark] = useState25(
7742
7908
  () => typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches
7743
7909
  );
7744
- useEffect30(() => {
7910
+ useEffect31(() => {
7745
7911
  const mq = window.matchMedia("(prefers-color-scheme: dark)");
7746
7912
  const handler = (e) => setDark(e.matches);
7747
7913
  mq.addEventListener("change", handler);
@@ -7927,7 +8093,7 @@ async function createHostProviderFromWorkspace(ws) {
7927
8093
  var DESKTOP_TOOLBAR_WRAP_WIDTH = 900;
7928
8094
  var WEB_TOOLBAR_WRAP_WIDTH = 700;
7929
8095
  function FolderGlyph() {
7930
- return /* @__PURE__ */ jsx19(
8096
+ return /* @__PURE__ */ jsx21(
7931
8097
  "svg",
7932
8098
  {
7933
8099
  viewBox: "0 0 24 24",
@@ -7936,12 +8102,12 @@ function FolderGlyph() {
7936
8102
  strokeWidth: "1.5",
7937
8103
  strokeLinejoin: "round",
7938
8104
  "aria-hidden": "true",
7939
- children: /* @__PURE__ */ jsx19("path", { d: "M3 7a1 1 0 0 1 1-1h5l2 2h9a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7z" })
8105
+ children: /* @__PURE__ */ jsx21("path", { d: "M3 7a1 1 0 0 1 1-1h5l2 2h9a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7z" })
7940
8106
  }
7941
8107
  );
7942
8108
  }
7943
8109
  function FileGlyph() {
7944
- return /* @__PURE__ */ jsxs17(
8110
+ return /* @__PURE__ */ jsxs19(
7945
8111
  "svg",
7946
8112
  {
7947
8113
  viewBox: "0 0 24 24",
@@ -7951,14 +8117,14 @@ function FileGlyph() {
7951
8117
  strokeLinejoin: "round",
7952
8118
  "aria-hidden": "true",
7953
8119
  children: [
7954
- /* @__PURE__ */ jsx19("path", { d: "M6 3h8l5 5v12a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z" }),
7955
- /* @__PURE__ */ jsx19("path", { d: "M14 3v5h5" })
8120
+ /* @__PURE__ */ jsx21("path", { d: "M6 3h8l5 5v12a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z" }),
8121
+ /* @__PURE__ */ jsx21("path", { d: "M14 3v5h5" })
7956
8122
  ]
7957
8123
  }
7958
8124
  );
7959
8125
  }
7960
8126
  function CollapseSidebarGlyph() {
7961
- return /* @__PURE__ */ jsxs17(
8127
+ return /* @__PURE__ */ jsxs19(
7962
8128
  "svg",
7963
8129
  {
7964
8130
  viewBox: "0 0 64 64",
@@ -7969,9 +8135,9 @@ function CollapseSidebarGlyph() {
7969
8135
  strokeLinejoin: "round",
7970
8136
  "aria-hidden": "true",
7971
8137
  children: [
7972
- /* @__PURE__ */ jsx19("rect", { x: "7", y: "10", width: "50", height: "44", rx: "6" }),
7973
- /* @__PURE__ */ jsx19("path", { d: "M24 10v44" }),
7974
- /* @__PURE__ */ jsx19("path", { d: "m17 25-7 7 7 7" })
8138
+ /* @__PURE__ */ jsx21("rect", { x: "7", y: "10", width: "50", height: "44", rx: "6" }),
8139
+ /* @__PURE__ */ jsx21("path", { d: "M24 10v44" }),
8140
+ /* @__PURE__ */ jsx21("path", { d: "m17 25-7 7 7 7" })
7975
8141
  ]
7976
8142
  }
7977
8143
  );
@@ -8008,10 +8174,10 @@ function DocBlocksShell({
8008
8174
  offlineReady = false
8009
8175
  }) {
8010
8176
  const osTheme = useOsTheme();
8011
- const [themePreference, setThemePreference] = useState24(loadThemePreference);
8012
- const [accentColor, setAccentColor] = useState24(loadAccentColor);
8013
- const [interfaceFont, setInterfaceFont] = useState24(loadInterfaceFont);
8014
- const [writeCanvasSettings, setWriteCanvasSettings] = useState24(
8177
+ const [themePreference, setThemePreference] = useState25(loadThemePreference);
8178
+ const [accentColor, setAccentColor] = useState25(loadAccentColor);
8179
+ const [interfaceFont, setInterfaceFont] = useState25(loadInterfaceFont);
8180
+ const [writeCanvasSettings, setWriteCanvasSettings] = useState25(
8015
8181
  loadWriteCanvasPreferences
8016
8182
  );
8017
8183
  const editorWriteCanvasSettings = useMemo6(
@@ -8026,17 +8192,24 @@ function DocBlocksShell({
8026
8192
  const ai = hostSupports3("aiAssist") ? maybeGetDocBlocksHost5()?.ai : void 0;
8027
8193
  const speech = hostSupports3("speechModelManagement") ? maybeGetDocBlocksHost5()?.speech : void 0;
8028
8194
  const trayMenu = hostSupports3("trayIcon") ? maybeGetDocBlocksHost5()?.menu : void 0;
8029
- const [settingsRequest, setSettingsRequest] = useState24(0);
8030
- const openSettings = useCallback19(() => setSettingsRequest((count) => count + 1), []);
8195
+ const [settingsRequest, setSettingsRequest] = useState25({ count: 0 });
8196
+ const openDictationSettings = useCallback19(
8197
+ () => setSettingsRequest(({ count }) => ({ count: count + 1, section: "dictation" })),
8198
+ []
8199
+ );
8200
+ const openNarrationSettings = useCallback19(
8201
+ () => setSettingsRequest(({ count }) => ({ count: count + 1, section: "narration" })),
8202
+ []
8203
+ );
8031
8204
  const speechInput = useMemo6(
8032
- () => speech && hostSupports3("speechInput") ? createSpeechInputProvider(speech, { onRequestSetup: openSettings }) : null,
8033
- [speech, openSettings]
8205
+ () => speech && hostSupports3("speechInput") ? createSpeechInputProvider(speech, { onRequestSetup: openDictationSettings }) : null,
8206
+ [speech, openDictationSettings]
8034
8207
  );
8035
8208
  const handleThemeChange = useCallback19((pref) => {
8036
8209
  setThemePreference(pref);
8037
8210
  saveThemePreference(pref);
8038
8211
  }, []);
8039
- useEffect30(() => {
8212
+ useEffect31(() => {
8040
8213
  if (hostSupports3("ownsWindowChrome") || typeof document === "undefined") return;
8041
8214
  const metas = document.querySelectorAll('meta[name="theme-color"]');
8042
8215
  metas.forEach((meta) => {
@@ -8051,19 +8224,19 @@ function DocBlocksShell({
8051
8224
  setWriteCanvasSettings(settings);
8052
8225
  saveWriteCanvasPreferences(settings);
8053
8226
  }, []);
8054
- const [proofingPreferences, setProofingPreferences] = useState24(loadProofingPreferences);
8227
+ const [proofingPreferences, setProofingPreferences] = useState25(loadProofingPreferences);
8055
8228
  const handleProofingPreferencesChange = useCallback19((settings) => {
8056
8229
  setProofingPreferences(settings);
8057
8230
  saveProofingPreferences(settings);
8058
8231
  }, []);
8059
- const [viewPreferences, setViewPreferences] = useState24(loadViewPreferences);
8232
+ const [viewPreferences, setViewPreferences] = useState25(loadViewPreferences);
8060
8233
  const handleViewPreferencesChange = useCallback19((prefs) => {
8061
8234
  setViewPreferences(prefs);
8062
8235
  saveViewPreferences(prefs);
8063
8236
  }, []);
8064
8237
  const shellRef = useRef21(null);
8065
8238
  const formFactor = useFormFactor(shellRef);
8066
- const [sidebarPreference, setSidebarPreference] = useState24(loadSidebarPreference);
8239
+ const [sidebarPreference, setSidebarPreference] = useState25(loadSidebarPreference);
8067
8240
  const layoutMode = resolveLayoutMode(formFactor, sidebarPreference);
8068
8241
  const singlePane = layoutMode === "single-pane";
8069
8242
  const updateSidebarPreference = useCallback19((preference) => {
@@ -8071,21 +8244,21 @@ function DocBlocksShell({
8071
8244
  saveSidebarPreference(preference);
8072
8245
  }, []);
8073
8246
  const defaultPreviewViewportPreset = useResponsivePreviewViewportPreset();
8074
- const [mobileShowEditor, setMobileShowEditor] = useState24(
8247
+ const [mobileShowEditor, setMobileShowEditor] = useState25(
8075
8248
  () => singlePane && isWelcomeGatewayDismissed()
8076
8249
  );
8077
- useEffect30(() => {
8250
+ useEffect31(() => {
8078
8251
  if (singlePane) void loadEditorShell();
8079
8252
  }, [singlePane]);
8080
8253
  useFormFactorAttributes(shellRef, formFactor, layoutMode, !mobileShowEditor);
8081
8254
  useInterfaceFontAttribute(interfaceFont);
8082
8255
  useKeyboardInset(formFactor.pointer === "coarse");
8083
8256
  const drawerOpen = singlePane && !mobileShowEditor;
8084
- const [sidebarWidth, setSidebarWidth] = useState24(loadSidebarWidth);
8257
+ const [sidebarWidth, setSidebarWidth] = useState25(loadSidebarWidth);
8085
8258
  const canRestoreSplitView = sidebarPreference === "collapsed" && formFactor.splitPaneAllowed;
8086
8259
  const editorAreaRef = useRef21(null);
8087
- const [desktopToolbarWrapped, setDesktopToolbarWrapped] = useState24(false);
8088
- useEffect30(() => {
8260
+ const [desktopToolbarWrapped, setDesktopToolbarWrapped] = useState25(false);
8261
+ useEffect31(() => {
8089
8262
  const editorArea = editorAreaRef.current;
8090
8263
  if (!editorArea || singlePane) {
8091
8264
  setDesktopToolbarWrapped(false);
@@ -8105,7 +8278,7 @@ function DocBlocksShell({
8105
8278
  return () => observer.disconnect();
8106
8279
  }, [singlePane]);
8107
8280
  const showBrowserStorageWarning = hostSupports3("browserOriginStorage");
8108
- const hostEnvironment = getHostEnvironment2();
8281
+ const hostEnvironment = getHostEnvironment3();
8109
8282
  const desktopApp = hostEnvironment?.surface === "electron";
8110
8283
  const appVersion = hostEnvironment ? `${hostEnvironment.appVersion} ${hostEnvironment.surfaceLabel}` : issueReportVersion ?? "web";
8111
8284
  const issueReportUrl = buildIssueReportUrl({
@@ -8113,8 +8286,8 @@ function DocBlocksShell({
8113
8286
  version: appVersion,
8114
8287
  userAgent: typeof navigator === "undefined" ? "" : navigator.userAgent
8115
8288
  });
8116
- const [browserStoragePersistent, setBrowserStoragePersistent] = useState24(false);
8117
- const [saveToast, setSaveToast] = useState24(null);
8289
+ const [browserStoragePersistent, setBrowserStoragePersistent] = useState25(false);
8290
+ const [saveToast, setSaveToast] = useState25(null);
8118
8291
  const saveToastTimerRef = useRef21(null);
8119
8292
  const showToast = useCallback19((kind, message) => {
8120
8293
  setSaveToast({ kind, message });
@@ -8122,7 +8295,7 @@ function DocBlocksShell({
8122
8295
  saveToastTimerRef.current = setTimeout(() => setSaveToast(null), 3e3);
8123
8296
  }, []);
8124
8297
  const { prompt: promptForText, promptDialog } = usePromptDialog();
8125
- const [newDocumentDialogOpen, setNewDocumentDialogOpen] = useState24(false);
8298
+ const [newDocumentDialogOpen, setNewDocumentDialogOpen] = useState25(false);
8126
8299
  const { confirm: confirmAction, acknowledge, confirmDialog } = useConfirmDialog();
8127
8300
  const confirmDeleteEntry = useCallback19(
8128
8301
  (message) => confirmAction({
@@ -8133,7 +8306,7 @@ function DocBlocksShell({
8133
8306
  }),
8134
8307
  [confirmAction]
8135
8308
  );
8136
- const [installPromptEvent, setInstallPromptEvent] = useState24(
8309
+ const [installPromptEvent, setInstallPromptEvent] = useState25(
8137
8310
  null
8138
8311
  );
8139
8312
  const panesRef = useRef21(null);
@@ -8203,12 +8376,12 @@ function DocBlocksShell({
8203
8376
  },
8204
8377
  [sidebarWidth, updateSidebarPreference]
8205
8378
  );
8206
- const [provider, setProvider] = useState24(null);
8207
- const [workspaceStartupError, setWorkspaceStartupError] = useState24(null);
8379
+ const [provider, setProvider] = useState25(null);
8380
+ const [workspaceStartupError, setWorkspaceStartupError] = useState25(null);
8208
8381
  const workspaceStarting = provider === null && workspaceStartupError === null;
8209
- const [activeWorkspaceId, setActiveWorkspaceId] = useState24(null);
8210
- const [defaultNewFileFormat, setDefaultNewFileFormat] = useState24(DEFAULT_NEW_FILE_FORMAT);
8211
- useEffect30(() => {
8382
+ const [activeWorkspaceId, setActiveWorkspaceId] = useState25(null);
8383
+ const [defaultNewFileFormat, setDefaultNewFileFormat] = useState25(DEFAULT_NEW_FILE_FORMAT);
8384
+ useEffect31(() => {
8212
8385
  setDefaultNewFileFormat(loadLastNewFileFormat(activeWorkspaceId));
8213
8386
  }, [activeWorkspaceId]);
8214
8387
  const rememberNewFileFormat = useCallback19(
@@ -8220,19 +8393,19 @@ function DocBlocksShell({
8220
8393
  },
8221
8394
  [activeWorkspaceId]
8222
8395
  );
8223
- const [activeWorkspaceDescriptor, setActiveWorkspaceDescriptor] = useState24(null);
8396
+ const [activeWorkspaceDescriptor, setActiveWorkspaceDescriptor] = useState25(null);
8224
8397
  const defaultProofingIgnoreStore = useMemo6(
8225
8398
  () => createLocalProofingIgnoreStore(() => activeWorkspaceId),
8226
8399
  [activeWorkspaceId]
8227
8400
  );
8228
8401
  const effectiveProofingIgnoreStore = proofingIgnoreStore === void 0 ? defaultProofingIgnoreStore : proofingIgnoreStore;
8229
- useEffect30(() => {
8402
+ useEffect31(() => {
8230
8403
  if (!provider || getTransientWorkspace2(provider.id)) return;
8231
8404
  const providerV2 = getFileSystemProviderV211(provider);
8232
8405
  return providerV2 ? retainFileSystemProvider(providerV2) : void 0;
8233
8406
  }, [provider]);
8234
- const [descriptorRefreshKey, setDescriptorRefreshKey] = useState24(0);
8235
- useEffect30(() => {
8407
+ const [descriptorRefreshKey, setDescriptorRefreshKey] = useState25(0);
8408
+ useEffect31(() => {
8236
8409
  let cancelled = false;
8237
8410
  if (!activeWorkspaceId) {
8238
8411
  setActiveWorkspaceDescriptor(null);
@@ -8245,12 +8418,12 @@ function DocBlocksShell({
8245
8418
  cancelled = true;
8246
8419
  };
8247
8420
  }, [activeWorkspaceId, descriptorRefreshKey]);
8248
- const [pinnedDocuments, setPinnedDocuments] = useState24(loadPinnedDocuments);
8249
- const [pinnedDocumentAvailability, setPinnedDocumentAvailability] = useState24(() => /* @__PURE__ */ new Map());
8250
- useEffect30(() => {
8421
+ const [pinnedDocuments, setPinnedDocuments] = useState25(loadPinnedDocuments);
8422
+ const [pinnedDocumentAvailability, setPinnedDocumentAvailability] = useState25(() => /* @__PURE__ */ new Map());
8423
+ useEffect31(() => {
8251
8424
  savePinnedDocuments(pinnedDocuments);
8252
8425
  }, [pinnedDocuments]);
8253
- useEffect30(() => {
8426
+ useEffect31(() => {
8254
8427
  const menu = maybeGetDocBlocksHost5()?.menu;
8255
8428
  if (!hostSupports3("pinnedDocumentMirror") || !menu) return;
8256
8429
  menu.setPinnedDocuments(
@@ -8280,7 +8453,7 @@ function DocBlocksShell({
8280
8453
  })),
8281
8454
  [pinnedDocumentAvailability, pinnedDocuments]
8282
8455
  );
8283
- useEffect30(() => {
8456
+ useEffect31(() => {
8284
8457
  if (!provider || !activeWorkspaceId) return;
8285
8458
  const activePins = pinnedDocuments.filter(
8286
8459
  (document2) => document2.workspaceId === activeWorkspaceId
@@ -8330,10 +8503,10 @@ function DocBlocksShell({
8330
8503
  void subscription?.dispose();
8331
8504
  };
8332
8505
  }, [activeWorkspaceId, pinnedDocuments, provider, setPinnedAvailability]);
8333
- const [transientMoveDestinations, setTransientMoveDestinations] = useState24(
8506
+ const [transientMoveDestinations, setTransientMoveDestinations] = useState25(
8334
8507
  []
8335
8508
  );
8336
- useEffect30(() => {
8509
+ useEffect31(() => {
8337
8510
  if (activeWorkspaceDescriptor?.type !== "transient") {
8338
8511
  setTransientMoveDestinations([]);
8339
8512
  return;
@@ -8398,8 +8571,8 @@ function DocBlocksShell({
8398
8571
  workspaceOutputsSchedulerRef.current?.notify();
8399
8572
  workspaceIndexRef.current?.refresh({ force: true });
8400
8573
  };
8401
- const [workspaceSettingsOpen, setWorkspaceSettingsOpen] = useState24(false);
8402
- const [versioningPreference, setVersioningPreference] = useState24(loadVersioningPreference);
8574
+ const [workspaceSettingsOpen, setWorkspaceSettingsOpen] = useState25(false);
8575
+ const [versioningPreference, setVersioningPreference] = useState25(loadVersioningPreference);
8403
8576
  const handleVersioningPreferenceChange = useCallback19((pref) => {
8404
8577
  setVersioningPreference(pref);
8405
8578
  saveVersioningPreference(pref);
@@ -8434,16 +8607,16 @@ function DocBlocksShell({
8434
8607
  const handleRegenerateWorkspaceOutputs = useCallback19(() => {
8435
8608
  void workspaceOutputsSchedulerRef.current?.regenerate({ force: true });
8436
8609
  }, []);
8437
- const [selectedFile, setSelectedFile] = useState24(null);
8438
- const [selectedSourceFile, setSelectedSourceFile] = useState24(null);
8439
- const [selectedOutsideIn, setSelectedOutsideIn] = useState24(null);
8440
- const [selectedOutsideInEditingEnabled, setSelectedOutsideInEditingEnabled] = useState24(false);
8441
- const [selectedImage, setSelectedImage] = useState24(void 0);
8442
- const [selectedManagedOutput, setSelectedManagedOutput] = useState24(void 0);
8443
- const [findMode, setFindMode] = useState24(false);
8610
+ const [selectedFile, setSelectedFile] = useState25(null);
8611
+ const [selectedSourceFile, setSelectedSourceFile] = useState25(null);
8612
+ const [selectedOutsideIn, setSelectedOutsideIn] = useState25(null);
8613
+ const [selectedOutsideInEditingEnabled, setSelectedOutsideInEditingEnabled] = useState25(false);
8614
+ const [selectedImage, setSelectedImage] = useState25(void 0);
8615
+ const [selectedManagedOutput, setSelectedManagedOutput] = useState25(void 0);
8616
+ const [findMode, setFindMode] = useState25(false);
8444
8617
  const findModeRef = useRef21(findMode);
8445
8618
  findModeRef.current = findMode;
8446
- useEffect30(() => {
8619
+ useEffect31(() => {
8447
8620
  setFindMode(false);
8448
8621
  }, [selectedFile]);
8449
8622
  const openFind = useCallback19(() => {
@@ -8455,14 +8628,14 @@ function DocBlocksShell({
8455
8628
  }, []);
8456
8629
  const findShortcut = useMemo6(findShortcutLabel, []);
8457
8630
  const searchShortcut = useMemo6(() => shortcutLabel("workspace-search", isApplePlatform()), []);
8458
- const [quickOpenOpen, setQuickOpenOpen] = useState24(false);
8459
- const [shortcutsOpen, setShortcutsOpen] = useState24(false);
8631
+ const [quickOpenOpen, setQuickOpenOpen] = useState25(false);
8632
+ const [shortcutsOpen, setShortcutsOpen] = useState25(false);
8460
8633
  const openKeyboardShortcuts = useCallback19(() => setShortcutsOpen(true), []);
8461
- const [quickOpenFocusRequest, setQuickOpenFocusRequest] = useState24(0);
8462
- const [sidebarView, setSidebarView] = useState24("files");
8463
- const [searchMounted, setSearchMounted] = useState24(false);
8464
- const [searchFocusRequest, setSearchFocusRequest] = useState24(0);
8465
- useEffect30(() => {
8634
+ const [quickOpenFocusRequest, setQuickOpenFocusRequest] = useState25(0);
8635
+ const [sidebarView, setSidebarView] = useState25("files");
8636
+ const [searchMounted, setSearchMounted] = useState25(false);
8637
+ const [searchFocusRequest, setSearchFocusRequest] = useState25(0);
8638
+ useEffect31(() => {
8466
8639
  if (!activeWorkspaceId || !selectedFile) return;
8467
8640
  if (getTransientWorkspace2(activeWorkspaceId) === null) {
8468
8641
  recordRecentDocument(activeWorkspaceId, selectedFile);
@@ -8504,7 +8677,7 @@ function DocBlocksShell({
8504
8677
  }
8505
8678
  return URL.createObjectURL(new Blob([selectedImage.data], { type: selectedImage.mimeType }));
8506
8679
  }, [selectedImage]);
8507
- useEffect30(
8680
+ useEffect31(
8508
8681
  () => () => {
8509
8682
  if (selectedImageUrl) URL.revokeObjectURL(selectedImageUrl);
8510
8683
  },
@@ -8550,8 +8723,8 @@ function DocBlocksShell({
8550
8723
  () => hostSupports3("exportDestinations") && exportDestinationAdapter ? createImageSaveOutput(exportDestinationAdapter) : void 0,
8551
8724
  [exportDestinationAdapter]
8552
8725
  );
8553
- const [selectedFolder, setSelectedFolder] = useState24(null);
8554
- const [folderEntries, setFolderEntries] = useState24([]);
8726
+ const [selectedFolder, setSelectedFolder] = useState25(null);
8727
+ const [folderEntries, setFolderEntries] = useState25([]);
8555
8728
  const visibleFolderEntries = useMemo6(
8556
8729
  () => filterVisibleFileEntries(folderEntries),
8557
8730
  [folderEntries]
@@ -8565,8 +8738,8 @@ function DocBlocksShell({
8565
8738
  } : null,
8566
8739
  [documentSnapshot.frozen, documentSnapshot.generation, documentSnapshot.targetKey]
8567
8740
  );
8568
- const [editorGeneration, setEditorGeneration] = useState24(documentSnapshot.generation);
8569
- useEffect30(() => {
8741
+ const [editorGeneration, setEditorGeneration] = useState25(documentSnapshot.generation);
8742
+ useEffect31(() => {
8570
8743
  const sync = () => setEditorGeneration(documentSession.getSnapshot().generation);
8571
8744
  const unsubscribe = documentSession.subscribe(sync);
8572
8745
  sync();
@@ -8575,7 +8748,7 @@ function DocBlocksShell({
8575
8748
  };
8576
8749
  }, [documentSession]);
8577
8750
  const editorGenerationSettled = editorGeneration === documentSnapshot.generation;
8578
- useEffect30(() => {
8751
+ useEffect31(() => {
8579
8752
  setOutsideInPdfWorker(pdfWorkerSrc2);
8580
8753
  }, [pdfWorkerSrc2]);
8581
8754
  const editorKey = String(editorGeneration);
@@ -8583,21 +8756,21 @@ function DocBlocksShell({
8583
8756
  void editorKey;
8584
8757
  return pickEmptyDocumentPrompt();
8585
8758
  }, [editorKey]);
8586
- const [explorerKey, setExplorerKey] = useState24(0);
8759
+ const [explorerKey, setExplorerKey] = useState25(0);
8587
8760
  const workspaceOutputsResult = workspaceOutputs.status.result;
8588
- useEffect30(() => {
8761
+ useEffect31(() => {
8589
8762
  if (!workspaceOutputsResult?.outputs.some((output) => output.created)) return;
8590
8763
  if (provider && getFileSystemProviderV211(provider)?.capabilities.watch) return;
8591
8764
  setExplorerKey((key) => key + 1);
8592
8765
  }, [provider, workspaceOutputsResult]);
8593
- const [fileExplorerSortMode, setFileExplorerSortMode] = useState24(loadFileExplorerSortMode);
8766
+ const [fileExplorerSortMode, setFileExplorerSortMode] = useState25(loadFileExplorerSortMode);
8594
8767
  const handleFileExplorerSortModeChange = useCallback19((mode) => {
8595
8768
  setFileExplorerSortMode(mode);
8596
8769
  saveFileExplorerSortMode(mode);
8597
8770
  }, []);
8598
- const [initialView, setInitialView] = useState24("wysiwyg");
8599
- const [initialSharedMode, setInitialSharedMode] = useState24(null);
8600
- const [showWelcomeGateway, setShowWelcomeGateway] = useState24(false);
8771
+ const [initialView, setInitialView] = useState25("wysiwyg");
8772
+ const [initialSharedMode, setInitialSharedMode] = useState25(null);
8773
+ const [showWelcomeGateway, setShowWelcomeGateway] = useState25(false);
8601
8774
  const welcomeScreenShown = showWelcomeGateway && !singlePane;
8602
8775
  const welcomeCoveredRef = useRef21(null);
8603
8776
  useInert(welcomeCoveredRef, welcomeScreenShown);
@@ -8607,7 +8780,7 @@ function DocBlocksShell({
8607
8780
  return false;
8608
8781
  });
8609
8782
  }, []);
8610
- const [aiPanel, setAiPanel] = useState24(null);
8783
+ const [aiPanel, setAiPanel] = useState25(null);
8611
8784
  const navigationRequestRef = useRef21(0);
8612
8785
  const workspaceAuthorityBarrier = useMemo6(() => new WorkspaceAuthorityBarrier(), []);
8613
8786
  const preparedCloseRequestRef = useRef21(null);
@@ -8796,12 +8969,12 @@ function DocBlocksShell({
8796
8969
  [afterWorkspaceCommit, gitScheduleRefresh]
8797
8970
  );
8798
8971
  const mediaContainerRef = useRef21(null);
8799
- const [mediaProvider, setMediaProvider] = useState24(null);
8800
- const [mediaProviderScope, setMediaProviderScope] = useState24(null);
8972
+ const [mediaProvider, setMediaProvider] = useState25(null);
8973
+ const [mediaProviderScope, setMediaProviderScope] = useState25(null);
8801
8974
  const mediaProviderCurrent = mediaProviderScope !== null && mediaProviderScope.provider === provider && mediaProviderScope.file === selectedFile && mediaProviderScope.outsideIn === selectedOutsideIn;
8802
- const [mediaEpoch, setMediaEpoch] = useState24(0);
8975
+ const [mediaEpoch, setMediaEpoch] = useState25(0);
8803
8976
  const versionsContainerRef = useRef21(null);
8804
- const [versionsContainer, setVersionsContainer] = useState24(null);
8977
+ const [versionsContainer, setVersionsContainer] = useState25(null);
8805
8978
  const pushHash = useCallback19((wsId, filePath) => {
8806
8979
  const hash = buildHash(wsId, filePath);
8807
8980
  if (window.location.hash !== hash) {
@@ -9025,17 +9198,17 @@ function DocBlocksShell({
9025
9198
  startupOpenSharedDocumentRef.current = openSharedDocument;
9026
9199
  const startupSeedWelcomeFileRef = useRef21(seedWelcomeFile);
9027
9200
  startupSeedWelcomeFileRef.current = seedWelcomeFile;
9028
- const [focusAfterWelcome, setFocusAfterWelcome] = useState24(false);
9201
+ const [focusAfterWelcome, setFocusAfterWelcome] = useState25(false);
9029
9202
  const handleTourWelcome = useCallback19(() => {
9030
9203
  closeWelcomeGateway();
9031
9204
  setFocusAfterWelcome(true);
9032
9205
  }, [closeWelcomeGateway]);
9033
- useEffect30(() => {
9206
+ useEffect31(() => {
9034
9207
  if (!focusAfterWelcome || welcomeScreenShown) return;
9035
9208
  setFocusAfterWelcome(false);
9036
9209
  editorAreaRef.current?.querySelector('[contenteditable="true"]')?.focus({ preventScroll: true });
9037
9210
  }, [focusAfterWelcome, welcomeScreenShown]);
9038
- useEffect30(() => {
9211
+ useEffect31(() => {
9039
9212
  const requestId = ++navigationRequestRef.current;
9040
9213
  let cancelled = false;
9041
9214
  const isCurrent = () => !cancelled && requestId === navigationRequestRef.current;
@@ -9247,7 +9420,7 @@ function DocBlocksShell({
9247
9420
  if (navigationRequestRef.current === requestId) navigationRequestRef.current += 1;
9248
9421
  };
9249
9422
  }, [pushHash, workspaceAuthorityBarrier]);
9250
- useEffect30(() => {
9423
+ useEffect31(() => {
9251
9424
  const onPopState = () => {
9252
9425
  const requestedHash = window.location.hash;
9253
9426
  const restoreCurrentHash = () => {
@@ -9289,7 +9462,7 @@ function DocBlocksShell({
9289
9462
  window.addEventListener("popstate", onPopState);
9290
9463
  return () => window.removeEventListener("popstate", onPopState);
9291
9464
  }, [activeWorkspaceId, openFromIds, openSharedDocument, selectedFile, showToast]);
9292
- useEffect30(() => {
9465
+ useEffect31(() => {
9293
9466
  if (!showBrowserStorageWarning || typeof navigator === "undefined") return;
9294
9467
  const storage = navigator.storage;
9295
9468
  if (!storage || typeof storage.persisted !== "function") return;
@@ -9302,7 +9475,7 @@ function DocBlocksShell({
9302
9475
  cancelled = true;
9303
9476
  };
9304
9477
  }, [showBrowserStorageWarning]);
9305
- useEffect30(() => {
9478
+ useEffect31(() => {
9306
9479
  if (hasDocBlocksHost() || typeof window === "undefined") return;
9307
9480
  const onBeforeInstallPrompt = (e) => {
9308
9481
  e.preventDefault();
@@ -9335,7 +9508,7 @@ function DocBlocksShell({
9335
9508
  } catch {
9336
9509
  }
9337
9510
  }, [installPromptEvent]);
9338
- useEffect30(() => {
9511
+ useEffect31(() => {
9339
9512
  const handler = (e) => {
9340
9513
  const target = e.target.closest?.("[data-view]");
9341
9514
  if (target) {
@@ -9351,12 +9524,18 @@ function DocBlocksShell({
9351
9524
  window.addEventListener("click", handler, true);
9352
9525
  return () => window.removeEventListener("click", handler, true);
9353
9526
  }, [activeWorkspaceId, selectedFile, closeWelcomeGateway]);
9527
+ const [dismissedConflictKey, setDismissedConflictKey] = useState25(null);
9528
+ const conflictTargetKey = documentSnapshot.conflict?.targetKey ?? null;
9529
+ useEffect31(() => {
9530
+ if (conflictTargetKey === null) setDismissedConflictKey(null);
9531
+ }, [conflictTargetKey]);
9354
9532
  const saveActiveDocument = useCallback19(() => {
9355
9533
  void (async () => {
9356
9534
  try {
9357
9535
  await documentSession.flush("manual");
9358
9536
  showToast("success", "Saved. You\u2019re all set.");
9359
9537
  } catch (error) {
9538
+ if (error instanceof DocumentSessionConflictError) setDismissedConflictKey(null);
9360
9539
  showToast(
9361
9540
  "error",
9362
9541
  isQuotaExceededError(error) ? "Could not save -- browser storage is full. Free up space or back up your work." : error instanceof Error ? error.message : "Could not save this document."
@@ -9364,22 +9543,22 @@ function DocBlocksShell({
9364
9543
  }
9365
9544
  })();
9366
9545
  }, [documentSession, showToast]);
9367
- useEffect30(() => {
9546
+ useEffect31(() => {
9368
9547
  return () => {
9369
9548
  if (saveToastTimerRef.current) clearTimeout(saveToastTimerRef.current);
9370
9549
  };
9371
9550
  }, []);
9372
- const [offlineReadyToast, setOfflineReadyToast] = useState24(false);
9551
+ const [offlineReadyToast, setOfflineReadyToast] = useState25(false);
9373
9552
  const offlineReadyAnnouncedRef = useRef21(false);
9374
- useEffect30(() => {
9553
+ useEffect31(() => {
9375
9554
  if (!offlineReady || offlineReadyAnnouncedRef.current) return;
9376
9555
  offlineReadyAnnouncedRef.current = true;
9377
9556
  setOfflineReadyToast(true);
9378
9557
  const timer = setTimeout(() => setOfflineReadyToast(false), 3e3);
9379
9558
  return () => clearTimeout(timer);
9380
9559
  }, [offlineReady]);
9381
- const [storageFull, setStorageFull] = useState24(false);
9382
- useEffect30(() => {
9560
+ const [storageFull, setStorageFull] = useState25(false);
9561
+ useEffect31(() => {
9383
9562
  if (documentSnapshot.error && isQuotaExceededError(documentSnapshot.error)) {
9384
9563
  setStorageFull(true);
9385
9564
  } else if (documentSnapshot.status === "saved") {
@@ -9387,7 +9566,7 @@ function DocBlocksShell({
9387
9566
  }
9388
9567
  }, [documentSnapshot.error, documentSnapshot.status]);
9389
9568
  const autoPersistRequestedRef = useRef21(false);
9390
- useEffect30(() => {
9569
+ useEffect31(() => {
9391
9570
  if (!showBrowserStorageWarning || browserStoragePersistent) return;
9392
9571
  if (autoPersistRequestedRef.current) return;
9393
9572
  if (documentSnapshot.status !== "saved") return;
@@ -9441,8 +9620,8 @@ function DocBlocksShell({
9441
9620
  mp.dispose();
9442
9621
  };
9443
9622
  }, [provider, selectedFile, selectedOutsideIn, mediaEpoch]);
9444
- const [mediaEditRenders, setMediaEditRenders] = useState24(null);
9445
- useEffect30(() => {
9623
+ const [mediaEditRenders, setMediaEditRenders] = useState25(null);
9624
+ useEffect31(() => {
9446
9625
  setMediaEditRenders(null);
9447
9626
  if (!mediaProvider) return;
9448
9627
  let manager = null;
@@ -9466,7 +9645,7 @@ function DocBlocksShell({
9466
9645
  selectedSourceFile ?? selectedFile,
9467
9646
  workspaceIndex.ensure
9468
9647
  );
9469
- useEffect30(() => {
9648
+ useEffect31(() => {
9470
9649
  const ref = versioningRef;
9471
9650
  if (!ref) return;
9472
9651
  const assign = (mgr2) => {
@@ -9490,7 +9669,7 @@ function DocBlocksShell({
9490
9669
  (output) => output.status === "written" && sameProviderPath(output.path, selectedFile)
9491
9670
  ) ? workspaceOutputsResult : null;
9492
9671
  }, [selectedFile, selectedManagedOutput, workspaceOutputsResult]);
9493
- useEffect30(() => {
9672
+ useEffect31(() => {
9494
9673
  if (!provider) return;
9495
9674
  const providerV2 = getFileSystemProviderV211(provider);
9496
9675
  const lifecycle = maybeGetDocBlocksHost5()?.lifecycle;
@@ -9581,6 +9760,7 @@ function DocBlocksShell({
9581
9760
  if (!transitioned || requestId !== navigationRequestRef.current) return false;
9582
9761
  return true;
9583
9762
  } catch (error) {
9763
+ if (error instanceof DocumentSessionConflictError) setDismissedConflictKey(null);
9584
9764
  showToast(
9585
9765
  "error",
9586
9766
  error instanceof Error ? "DocBlocks could not save this document: " + error.message : "DocBlocks could not save this document."
@@ -9590,7 +9770,7 @@ function DocBlocksShell({
9590
9770
  },
9591
9771
  [documentSession, showToast]
9592
9772
  );
9593
- const [showConflictComparison, setShowConflictComparison] = useState24(false);
9773
+ const [showConflictComparison, setShowConflictComparison] = useState25(false);
9594
9774
  const readConflictFile = useCallback19(async () => {
9595
9775
  const path = selectedSourceFile ?? selectedFile;
9596
9776
  if (!provider || !path || activeWorkspaceId && getTransientWorkspace2(activeWorkspaceId)) {
@@ -9637,7 +9817,7 @@ function DocBlocksShell({
9637
9817
  return false;
9638
9818
  }
9639
9819
  }, [documentSession]);
9640
- useEffect30(() => {
9820
+ useEffect31(() => {
9641
9821
  const needsWarning = ["dirty", "saving", "error", "conflict"].includes(documentSnapshot.status);
9642
9822
  if (!documentSnapshot.targetKey) return;
9643
9823
  const flushBestEffort = () => {
@@ -9663,7 +9843,7 @@ function DocBlocksShell({
9663
9843
  document.removeEventListener("visibilitychange", onVisibilityChange);
9664
9844
  };
9665
9845
  }, [documentSession, documentSnapshot.status, documentSnapshot.targetKey]);
9666
- useEffect30(() => {
9846
+ useEffect31(() => {
9667
9847
  const lifecycle = maybeGetDocBlocksHost5()?.lifecycle;
9668
9848
  if (!hostSupports3("guardedClose") || !lifecycle) return;
9669
9849
  const stopPrepare = lifecycle.onPrepareClose(async (request) => {
@@ -10321,7 +10501,7 @@ function DocBlocksShell({
10321
10501
  ]
10322
10502
  );
10323
10503
  useShellShortcuts(shortcutHandlers, layoutMode);
10324
- useEffect30(
10504
+ useEffect31(
10325
10505
  () => maybeGetDocBlocksHost5()?.lifecycle?.onBack?.(() => {
10326
10506
  if (dismissTopmostDialog()) return true;
10327
10507
  const escape = new KeyboardEvent("keydown", {
@@ -10344,7 +10524,7 @@ function DocBlocksShell({
10344
10524
  [singlePane, mobileShowEditor]
10345
10525
  );
10346
10526
  const actionNewHandledRef = useRef21(false);
10347
- useEffect30(() => {
10527
+ useEffect31(() => {
10348
10528
  if (!provider || actionNewHandledRef.current) return;
10349
10529
  if (typeof window === "undefined") return;
10350
10530
  const params = new URLSearchParams(window.location.search);
@@ -10381,7 +10561,7 @@ function DocBlocksShell({
10381
10561
  );
10382
10562
  });
10383
10563
  }, [nativeWorkspaceId, showToast]);
10384
- useEffect30(() => {
10564
+ useEffect31(() => {
10385
10565
  const host = maybeGetDocBlocksHost5();
10386
10566
  if (!hostSupports3("menuCommands") || !host?.onMenuCommand) return;
10387
10567
  return host.onMenuCommand((cmd) => {
@@ -10439,7 +10619,7 @@ function DocBlocksShell({
10439
10619
  break;
10440
10620
  case "help:about":
10441
10621
  void (async () => {
10442
- const version = await host.updater?.getVersion() ?? getHostEnvironment2()?.appVersion ?? "unknown";
10622
+ const version = await host.updater?.getVersion() ?? getHostEnvironment3()?.appVersion ?? "unknown";
10443
10623
  await acknowledge({ title: "About DocBlocks", message: `DocBlocks ${version}` });
10444
10624
  })();
10445
10625
  break;
@@ -11284,7 +11464,7 @@ function DocBlocksShell({
11284
11464
  },
11285
11465
  [adoptTransientWorkspace]
11286
11466
  );
11287
- useEffect30(() => {
11467
+ useEffect31(() => {
11288
11468
  const host = maybeGetDocBlocksHost5();
11289
11469
  if (!hostSupports3("openRequests") || !host) return;
11290
11470
  return host.onOpenRequest((req) => {
@@ -11351,7 +11531,7 @@ function DocBlocksShell({
11351
11531
  },
11352
11532
  [adoptTransientWorkspace]
11353
11533
  );
11354
- useEffect30(() => {
11534
+ useEffect31(() => {
11355
11535
  if (hostSupports3("openRequests") || typeof window === "undefined") return;
11356
11536
  const launchQueue = window.launchQueue;
11357
11537
  if (!launchQueue) return;
@@ -11608,7 +11788,7 @@ function DocBlocksShell({
11608
11788
  transitionAwayFromDocument
11609
11789
  ]
11610
11790
  );
11611
- return /* @__PURE__ */ jsx19(
11791
+ return /* @__PURE__ */ jsx21(
11612
11792
  "div",
11613
11793
  {
11614
11794
  ref: shellRef,
@@ -11617,10 +11797,10 @@ function DocBlocksShell({
11617
11797
  "data-accent": accentColor,
11618
11798
  "data-interface-font": interfaceFont === "fixed" ? "fixed" : void 0,
11619
11799
  "data-document-status": documentSnapshot.status,
11620
- children: /* @__PURE__ */ jsxs17(GitContext.Provider, { value: git, children: [
11800
+ children: /* @__PURE__ */ jsxs19(GitContext.Provider, { value: git, children: [
11621
11801
  promptDialog,
11622
11802
  confirmDialog,
11623
- quickOpenOpen && activeWorkspaceId && /* @__PURE__ */ jsx19(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx19(
11803
+ quickOpenOpen && activeWorkspaceId && /* @__PURE__ */ jsx21(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx21(
11624
11804
  QuickOpenDialog,
11625
11805
  {
11626
11806
  index: workspaceIndex.index,
@@ -11634,8 +11814,8 @@ function DocBlocksShell({
11634
11814
  onClose: () => setQuickOpenOpen(false)
11635
11815
  }
11636
11816
  ) }),
11637
- shortcutsOpen && /* @__PURE__ */ jsx19(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx19(KeyboardShortcutsDialog, { onClose: () => setShortcutsOpen(false) }) }),
11638
- newDocumentDialogOpen && /* @__PURE__ */ jsx19(
11817
+ shortcutsOpen && /* @__PURE__ */ jsx21(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx21(KeyboardShortcutsDialog, { onClose: () => setShortcutsOpen(false) }) }),
11818
+ newDocumentDialogOpen && /* @__PURE__ */ jsx21(
11639
11819
  NewDocumentDialog,
11640
11820
  {
11641
11821
  initialFormat: defaultNewFileFormat,
@@ -11645,8 +11825,8 @@ function DocBlocksShell({
11645
11825
  }
11646
11826
  }
11647
11827
  ),
11648
- workspaceStartupError && /* @__PURE__ */ jsx19("div", { className: "db-save-toast db-save-toast--error", role: "alert", "aria-live": "assertive", children: workspaceStartupError }),
11649
- saveToast && /* @__PURE__ */ jsx19(
11828
+ workspaceStartupError && /* @__PURE__ */ jsx21("div", { className: "db-save-toast db-save-toast--error", role: "alert", "aria-live": "assertive", children: workspaceStartupError }),
11829
+ saveToast && /* @__PURE__ */ jsx21(
11650
11830
  "div",
11651
11831
  {
11652
11832
  className: "db-save-toast db-save-toast--" + saveToast.kind,
@@ -11655,29 +11835,38 @@ function DocBlocksShell({
11655
11835
  children: saveToast.message
11656
11836
  }
11657
11837
  ),
11658
- offlineReadyToast && !saveToast && /* @__PURE__ */ jsx19("div", { className: "db-save-toast db-save-toast--success", role: "status", "aria-live": "polite", children: "DocBlocks is ready to work offline." }),
11659
- documentSnapshot.conflict && /* @__PURE__ */ jsxs17("div", { className: "db-document-conflict", role: "alert", children: [
11660
- /* @__PURE__ */ jsx19("span", { children: documentSnapshot.conflict.recoveredDraft ? "A recovery draft from a previous session differs from the saved file. The saved file may be newer. Choose which version to use." : "This document changed outside DocBlocks. Your unsaved version is still intact." }),
11661
- /* @__PURE__ */ jsx19("div", { className: "db-document-conflict-actions", children: /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => setShowConflictComparison(true), children: "Compare versions" }) })
11662
- ] }),
11663
- documentSnapshot.conflict && showConflictComparison && /* @__PURE__ */ jsx19(Suspense2, { fallback: /* @__PURE__ */ jsx19("div", { role: "status", children: "Loading version comparison\u2026" }), children: /* @__PURE__ */ jsx19(
11838
+ offlineReadyToast && !saveToast && /* @__PURE__ */ jsx21("div", { className: "db-save-toast db-save-toast--success", role: "status", "aria-live": "polite", children: "DocBlocks is ready to work offline." }),
11839
+ documentSnapshot.conflict && documentSnapshot.conflict.targetKey !== dismissedConflictKey && /* @__PURE__ */ jsx21(
11840
+ DocumentConflictBanner,
11841
+ {
11842
+ conflict: documentSnapshot.conflict,
11843
+ readSavedFile: readConflictFile,
11844
+ onCompare: () => setShowConflictComparison(true),
11845
+ onDismiss: () => setDismissedConflictKey(conflictTargetKey)
11846
+ }
11847
+ ),
11848
+ documentSnapshot.conflict && showConflictComparison && /* @__PURE__ */ jsx21(Suspense2, { fallback: /* @__PURE__ */ jsx21("div", { role: "status", children: "Loading version comparison\u2026" }), children: /* @__PURE__ */ jsx21(
11664
11849
  DocumentConflictDialog,
11665
11850
  {
11666
11851
  conflict: documentSnapshot.conflict,
11852
+ fileName: selectedSourceFile ?? selectedFile ?? "",
11853
+ theme: resolvedTheme,
11854
+ defaultThemeId: workspaceDefaultThemeId,
11855
+ mediaProvider: mediaProviderCurrent ? mediaProvider : null,
11667
11856
  readSavedFile: readConflictFile,
11668
11857
  onUseLocal: handleKeepLocalDocument,
11669
11858
  onUseSaved: handleUseExternalDocument,
11670
11859
  onClose: () => setShowConflictComparison(false)
11671
11860
  }
11672
11861
  ) }),
11673
- storageFull && !documentSnapshot.conflict && /* @__PURE__ */ jsxs17("div", { className: "db-storage-full-banner", role: "alert", children: [
11674
- /* @__PURE__ */ jsx19("span", { children: "Browser storage is full -- changes can\u2019t be saved. Free up space or back up your work now." }),
11675
- /* @__PURE__ */ jsxs17("div", { className: "db-storage-full-banner-actions", children: [
11676
- /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => void handleDownloadAllWorkspaces(), children: "Back up all workspaces" }),
11677
- /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => setStorageFull(false), children: "Dismiss" })
11862
+ storageFull && !documentSnapshot.conflict && /* @__PURE__ */ jsxs19("div", { className: "db-storage-full-banner", role: "alert", children: [
11863
+ /* @__PURE__ */ jsx21("span", { children: "Browser storage is full -- changes can\u2019t be saved. Free up space or back up your work now." }),
11864
+ /* @__PURE__ */ jsxs19("div", { className: "db-storage-full-banner-actions", children: [
11865
+ /* @__PURE__ */ jsx21("button", { type: "button", onClick: () => void handleDownloadAllWorkspaces(), children: "Back up all workspaces" }),
11866
+ /* @__PURE__ */ jsx21("button", { type: "button", onClick: () => setStorageFull(false), children: "Dismiss" })
11678
11867
  ] })
11679
11868
  ] }),
11680
- workspaceSettingsOpen && activeWorkspaceDescriptor && /* @__PURE__ */ jsx19(
11869
+ workspaceSettingsOpen && activeWorkspaceDescriptor && /* @__PURE__ */ jsx21(
11681
11870
  WorkspaceSettingsDialog,
11682
11871
  {
11683
11872
  workspace: activeWorkspaceDescriptor,
@@ -11690,8 +11879,8 @@ function DocBlocksShell({
11690
11879
  onClose: () => setWorkspaceSettingsOpen(false)
11691
11880
  }
11692
11881
  ),
11693
- /* @__PURE__ */ jsxs17("div", { className: "db-shell-panes", ref: panesRef, children: [
11694
- /* @__PURE__ */ jsxs17(
11882
+ /* @__PURE__ */ jsxs19("div", { className: "db-shell-panes", ref: panesRef, children: [
11883
+ /* @__PURE__ */ jsxs19(
11695
11884
  "aside",
11696
11885
  {
11697
11886
  ref: sidebarRef,
@@ -11699,8 +11888,8 @@ function DocBlocksShell({
11699
11888
  "aria-label": "Workspace and files",
11700
11889
  style: singlePane ? void 0 : { width: `${sidebarWidth}px` },
11701
11890
  children: [
11702
- /* @__PURE__ */ jsxs17("div", { className: "db-shell-sidebar-header", children: [
11703
- /* @__PURE__ */ jsx19(
11891
+ /* @__PURE__ */ jsxs19("div", { className: "db-shell-sidebar-header", children: [
11892
+ /* @__PURE__ */ jsx21(
11704
11893
  AppMenu,
11705
11894
  {
11706
11895
  logoUrl,
@@ -11733,10 +11922,11 @@ function DocBlocksShell({
11733
11922
  ai,
11734
11923
  speech,
11735
11924
  tray: trayMenu,
11736
- settingsRequest
11925
+ settingsRequest: settingsRequest.count,
11926
+ settingsRequestSection: settingsRequest.section
11737
11927
  }
11738
11928
  ),
11739
- /* @__PURE__ */ jsx19(
11929
+ /* @__PURE__ */ jsx21(
11740
11930
  "input",
11741
11931
  {
11742
11932
  ref: restoreInputRef,
@@ -11751,7 +11941,7 @@ function DocBlocksShell({
11751
11941
  }
11752
11942
  }
11753
11943
  ),
11754
- /* @__PURE__ */ jsx19(
11944
+ /* @__PURE__ */ jsx21(
11755
11945
  WorkspacePicker,
11756
11946
  {
11757
11947
  activeWorkspaceId,
@@ -11763,7 +11953,7 @@ function DocBlocksShell({
11763
11953
  onRemoveWorkspace: (workspace) => void handleRemoveWorkspace(workspace.id)
11764
11954
  }
11765
11955
  ),
11766
- /* @__PURE__ */ jsx19(
11956
+ /* @__PURE__ */ jsx21(
11767
11957
  WorkspaceSettingsButton,
11768
11958
  {
11769
11959
  onSettings: handleOpenWorkspaceSettings,
@@ -11774,26 +11964,26 @@ function DocBlocksShell({
11774
11964
  }
11775
11965
  }
11776
11966
  ),
11777
- canRestoreSplitView && /* @__PURE__ */ jsx19(
11967
+ canRestoreSplitView && /* @__PURE__ */ jsx21(
11778
11968
  "button",
11779
11969
  {
11780
11970
  className: "db-restore-split",
11781
11971
  onClick: () => updateSidebarPreference("pinned"),
11782
11972
  "aria-label": "Restore split view",
11783
11973
  title: "Restore split view",
11784
- children: /* @__PURE__ */ jsx19(SplitViewIcon, {})
11974
+ children: /* @__PURE__ */ jsx21(SplitViewIcon, {})
11785
11975
  }
11786
11976
  ),
11787
- /* @__PURE__ */ jsx19("span", { className: "db-window-drag-grip", "aria-hidden": true })
11977
+ /* @__PURE__ */ jsx21("span", { className: "db-window-drag-grip", "aria-hidden": true })
11788
11978
  ] }),
11789
- git.available && /* @__PURE__ */ jsx19(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx19(
11979
+ git.available && /* @__PURE__ */ jsx21(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx21(
11790
11980
  GitUI,
11791
11981
  {
11792
11982
  onOpenFile: (path) => void handleSelect(path, "file"),
11793
11983
  onWorkspaceCloned: handleWorkspaceCloned
11794
11984
  }
11795
11985
  ) }),
11796
- /* @__PURE__ */ jsx19(
11986
+ /* @__PURE__ */ jsx21(
11797
11987
  FileExplorer,
11798
11988
  {
11799
11989
  loading: workspaceStarting,
@@ -11828,7 +12018,7 @@ function DocBlocksShell({
11828
12018
  },
11829
12019
  explorerKey
11830
12020
  ),
11831
- searchMounted && /* @__PURE__ */ jsx19(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx19(
12021
+ searchMounted && /* @__PURE__ */ jsx21(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx21(
11832
12022
  WorkspaceSearchPanel,
11833
12023
  {
11834
12024
  index: workspaceIndex.index,
@@ -11839,17 +12029,17 @@ function DocBlocksShell({
11839
12029
  onShowFiles: () => setSidebarView("files")
11840
12030
  }
11841
12031
  ) }),
11842
- singlePane && showWelcomeGateway && /* @__PURE__ */ jsxs17("section", { className: "db-mobile-first-run", "aria-labelledby": "db-mobile-first-run-title", children: [
11843
- /* @__PURE__ */ jsx19("p", { className: "db-mobile-first-run-eyebrow", children: "Local-first Markdown editor" }),
11844
- /* @__PURE__ */ jsx19("h1", { id: "db-mobile-first-run-title", children: "Welcome to DocBlocks" }),
11845
- /* @__PURE__ */ jsxs17("p", { children: [
12032
+ singlePane && showWelcomeGateway && /* @__PURE__ */ jsxs19("section", { className: "db-mobile-first-run", "aria-labelledby": "db-mobile-first-run-title", children: [
12033
+ /* @__PURE__ */ jsx21("p", { className: "db-mobile-first-run-eyebrow", children: "Local-first Markdown editor" }),
12034
+ /* @__PURE__ */ jsx21("h1", { id: "db-mobile-first-run-title", children: "Welcome to DocBlocks" }),
12035
+ /* @__PURE__ */ jsxs19("p", { children: [
11846
12036
  WELCOME_SUMMARY,
11847
12037
  " ",
11848
12038
  WELCOME_PRIVACY_NOTE
11849
12039
  ] }),
11850
- /* @__PURE__ */ jsxs17("div", { className: "db-mobile-first-run-actions", children: [
11851
- /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => void handleNewFile(), children: "Create a document" }),
11852
- /* @__PURE__ */ jsx19(
12040
+ /* @__PURE__ */ jsxs19("div", { className: "db-mobile-first-run-actions", children: [
12041
+ /* @__PURE__ */ jsx21("button", { type: "button", onClick: () => void handleNewFile(), children: "Create a document" }),
12042
+ /* @__PURE__ */ jsx21(
11853
12043
  "button",
11854
12044
  {
11855
12045
  type: "button",
@@ -11863,14 +12053,14 @@ function DocBlocksShell({
11863
12053
  )
11864
12054
  ] })
11865
12055
  ] }),
11866
- git.available && git.pendingGrant && /* @__PURE__ */ jsx19(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx19(GitGrantNotice, {}) }),
11867
- /* @__PURE__ */ jsxs17("div", { className: "db-shell-sidebar-footer", children: [
11868
- /* @__PURE__ */ jsx19("a", { href: "https://docblocks.com/docs/", target: "_blank", rel: "noopener noreferrer", children: "Docs" }),
11869
- /* @__PURE__ */ jsx19("span", { className: "db-shell-sidebar-footer-separator", "aria-hidden": "true", children: "\u2022" }),
11870
- /* @__PURE__ */ jsx19("a", { href: "https://docblocks.com/terms/", target: "_blank", rel: "noopener noreferrer", children: "Terms" }),
11871
- /* @__PURE__ */ jsx19("span", { className: "db-shell-sidebar-footer-separator", "aria-hidden": "true", children: "\u2022" }),
11872
- /* @__PURE__ */ jsx19("a", { href: issueReportUrl, target: "_blank", rel: "noopener noreferrer", children: "Report issue" }),
11873
- showBrowserStorageWarning && /* @__PURE__ */ jsx19(Fragment11, { children: /* @__PURE__ */ jsxs17(
12056
+ git.available && git.pendingGrant && /* @__PURE__ */ jsx21(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx21(GitGrantNotice, {}) }),
12057
+ /* @__PURE__ */ jsxs19("div", { className: "db-shell-sidebar-footer", children: [
12058
+ /* @__PURE__ */ jsx21("a", { href: "https://docblocks.com/docs/", target: "_blank", rel: "noopener noreferrer", children: "Docs" }),
12059
+ /* @__PURE__ */ jsx21("span", { className: "db-shell-sidebar-footer-separator", "aria-hidden": "true", children: "\u2022" }),
12060
+ /* @__PURE__ */ jsx21("a", { href: "https://docblocks.com/terms/", target: "_blank", rel: "noopener noreferrer", children: "Terms" }),
12061
+ /* @__PURE__ */ jsx21("span", { className: "db-shell-sidebar-footer-separator", "aria-hidden": "true", children: "\u2022" }),
12062
+ /* @__PURE__ */ jsx21("a", { href: issueReportUrl, target: "_blank", rel: "noopener noreferrer", children: "Report issue" }),
12063
+ showBrowserStorageWarning && /* @__PURE__ */ jsx21(Fragment12, { children: /* @__PURE__ */ jsxs19(
11874
12064
  "button",
11875
12065
  {
11876
12066
  type: "button",
@@ -11879,20 +12069,20 @@ function DocBlocksShell({
11879
12069
  "aria-label": "Back up all workspaces",
11880
12070
  title: "Browsers can clear site data. Download a backup of every workspace.",
11881
12071
  children: [
11882
- /* @__PURE__ */ jsx19(BackupIcon, {}),
12072
+ /* @__PURE__ */ jsx21(BackupIcon, {}),
11883
12073
  "Back up"
11884
12074
  ]
11885
12075
  }
11886
12076
  ) })
11887
12077
  ] }),
11888
- /* @__PURE__ */ jsxs17("div", { className: "db-sidebar-collapse-preview", "aria-hidden": "true", children: [
11889
- /* @__PURE__ */ jsx19("span", { className: "db-sidebar-collapse-preview-icon", children: /* @__PURE__ */ jsx19(CollapseSidebarGlyph, {}) }),
11890
- /* @__PURE__ */ jsx19("span", { className: "db-sidebar-collapse-preview-label", children: "Release to hide files" })
12078
+ /* @__PURE__ */ jsxs19("div", { className: "db-sidebar-collapse-preview", "aria-hidden": "true", children: [
12079
+ /* @__PURE__ */ jsx21("span", { className: "db-sidebar-collapse-preview-icon", children: /* @__PURE__ */ jsx21(CollapseSidebarGlyph, {}) }),
12080
+ /* @__PURE__ */ jsx21("span", { className: "db-sidebar-collapse-preview-label", children: "Release to hide files" })
11891
12081
  ] })
11892
12082
  ]
11893
12083
  }
11894
12084
  ),
11895
- !singlePane && /* @__PURE__ */ jsx19(
12085
+ !singlePane && /* @__PURE__ */ jsx21(
11896
12086
  "div",
11897
12087
  {
11898
12088
  className: "db-shell-sidebar-resizer",
@@ -11902,7 +12092,7 @@ function DocBlocksShell({
11902
12092
  onPointerDown: handleResizerPointerDown
11903
12093
  }
11904
12094
  ),
11905
- singlePane && /* @__PURE__ */ jsx19(
12095
+ singlePane && /* @__PURE__ */ jsx21(
11906
12096
  "div",
11907
12097
  {
11908
12098
  className: "db-shell-scrim",
@@ -11910,7 +12100,7 @@ function DocBlocksShell({
11910
12100
  onPointerDown: () => setMobileShowEditor(true)
11911
12101
  }
11912
12102
  ),
11913
- /* @__PURE__ */ jsxs17(
12103
+ /* @__PURE__ */ jsxs19(
11914
12104
  "main",
11915
12105
  {
11916
12106
  ref: editorAreaRef,
@@ -11921,8 +12111,8 @@ function DocBlocksShell({
11921
12111
  editorDropActive ? "db-shell-editor-area--drop-active" : ""
11922
12112
  ].filter(Boolean).join(" "),
11923
12113
  children: [
11924
- /* @__PURE__ */ jsxs17("div", { ref: welcomeCoveredRef, className: "db-shell-editor-content", children: [
11925
- selectedFile && mediaProvider ? /* @__PURE__ */ jsx19(Fragment11, { children: selectedManagedOutput === "catalog-html" ? /* @__PURE__ */ jsx19(
12114
+ /* @__PURE__ */ jsxs19("div", { ref: welcomeCoveredRef, className: "db-shell-editor-content", children: [
12115
+ selectedFile && mediaProvider ? /* @__PURE__ */ jsx21(Fragment12, { children: selectedManagedOutput === "catalog-html" ? /* @__PURE__ */ jsx21(
11926
12116
  GeneratedCatalogPage,
11927
12117
  {
11928
12118
  html: editorContent,
@@ -11930,17 +12120,17 @@ function DocBlocksShell({
11930
12120
  onOpenSettings: activeWorkspaceDescriptor ? handleOpenWorkspaceSettings : void 0,
11931
12121
  onBack: singlePane ? openDrawer : void 0
11932
12122
  }
11933
- ) : /* @__PURE__ */ jsx19(
12123
+ ) : /* @__PURE__ */ jsx21(
11934
12124
  GeneratedFileFrame,
11935
12125
  {
11936
12126
  kind: selectedManagedOutput,
11937
12127
  onOpenSettings: activeWorkspaceDescriptor ? handleOpenWorkspaceSettings : void 0,
11938
12128
  onBack: singlePane ? openDrawer : void 0,
11939
- children: /* @__PURE__ */ jsx19(
12129
+ children: /* @__PURE__ */ jsx21(
11940
12130
  Suspense2,
11941
12131
  {
11942
- fallback: /* @__PURE__ */ jsx19("div", { className: "db-shell-empty", role: "status", children: "Loading your document\u2026" }),
11943
- children: editorGenerationSettled && mediaProviderCurrent && /* @__PURE__ */ jsx19(EditorErrorBoundary, { resetKey: `${selectedFile}-${editorKey}`, children: /* @__PURE__ */ jsx19(
12132
+ fallback: /* @__PURE__ */ jsx21("div", { className: "db-shell-empty", role: "status", children: "Loading your document\u2026" }),
12133
+ children: editorGenerationSettled && mediaProviderCurrent && /* @__PURE__ */ jsx21(EditorErrorBoundary, { resetKey: `${selectedFile}-${editorKey}`, children: /* @__PURE__ */ jsx21(
11944
12134
  EditorShell,
11945
12135
  {
11946
12136
  initialMarkdown: editorContent,
@@ -11991,19 +12181,19 @@ function DocBlocksShell({
11991
12181
  versioningAutoSaveIdleMs,
11992
12182
  onSaveVersion,
11993
12183
  statusBarSlotRight,
11994
- sidePanelSlot: ai && aiPanel && selectedImage === void 0 && (selectedOutsideIn === null || selectedOutsideInEditingEnabled) ? /* @__PURE__ */ jsx19(Suspense2, { fallback: null, children: aiPanel === "review" ? /* @__PURE__ */ jsx19(AiReviewPanel, { ai, onClose: () => setAiPanel(null) }) : /* @__PURE__ */ jsx19(AiIllustratePanel, { ai, onClose: () => setAiPanel(null) }) }) : void 0,
11995
- toolbarSlotLeft: singlePane ? /* @__PURE__ */ jsx19(
12184
+ sidePanelSlot: ai && aiPanel && selectedImage === void 0 && (selectedOutsideIn === null || selectedOutsideInEditingEnabled) ? /* @__PURE__ */ jsx21(Suspense2, { fallback: null, children: aiPanel === "review" ? /* @__PURE__ */ jsx21(AiReviewPanel, { ai, onClose: () => setAiPanel(null) }) : aiPanel === "images" ? /* @__PURE__ */ jsx21(AiImagePanel, { ai, onClose: () => setAiPanel(null) }) : /* @__PURE__ */ jsx21(AiIllustratePanel, { ai, onClose: () => setAiPanel(null) }) }) : void 0,
12185
+ toolbarSlotLeft: singlePane ? /* @__PURE__ */ jsx21(
11996
12186
  "button",
11997
12187
  {
11998
12188
  className: "db-mobile-back",
11999
12189
  onClick: () => setMobileShowEditor(false),
12000
12190
  "aria-label": "Show file list",
12001
- children: /* @__PURE__ */ jsx19("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx19(FolderGlyph, {}) })
12191
+ children: /* @__PURE__ */ jsx21("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx21(FolderGlyph, {}) })
12002
12192
  }
12003
12193
  ) : void 0,
12004
- summarizationDesigner: selectedImage === void 0 && selectedManagedOutput === void 0 && (selectedOutsideIn === null || selectedOutsideInEditingEnabled) ? (onClose) => /* @__PURE__ */ jsx19(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx19(PresentationMaker, { ai: ai ?? void 0, onClose }) }) : void 0,
12005
- toolbarSlotRight: /* @__PURE__ */ jsxs17(Fragment11, { children: [
12006
- canFind && /* @__PURE__ */ jsx19(
12194
+ summarizationDesigner: selectedImage === void 0 && selectedManagedOutput === void 0 && (selectedOutsideIn === null || selectedOutsideInEditingEnabled) ? (onClose) => /* @__PURE__ */ jsx21(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx21(PresentationMaker, { ai: ai ?? void 0, onClose }) }) : void 0,
12195
+ toolbarSlotRight: /* @__PURE__ */ jsxs19(Fragment12, { children: [
12196
+ canFind && /* @__PURE__ */ jsx21(
12007
12197
  FindButton,
12008
12198
  {
12009
12199
  active: findMode,
@@ -12011,7 +12201,7 @@ function DocBlocksShell({
12011
12201
  shortcutLabel: findShortcut
12012
12202
  }
12013
12203
  ),
12014
- ai && /* @__PURE__ */ jsx19(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx19(
12204
+ ai && /* @__PURE__ */ jsx21(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx21(
12015
12205
  AiToolbarControl,
12016
12206
  {
12017
12207
  ai,
@@ -12020,38 +12210,38 @@ function DocBlocksShell({
12020
12210
  onOpenPanel: setAiPanel
12021
12211
  }
12022
12212
  ) }),
12023
- speech && /* @__PURE__ */ jsxs17(Suspense2, { fallback: null, children: [
12024
- /* @__PURE__ */ jsx19(
12213
+ speech && /* @__PURE__ */ jsxs19(Suspense2, { fallback: null, children: [
12214
+ /* @__PURE__ */ jsx21(
12025
12215
  TextFromNarration,
12026
12216
  {
12027
12217
  speech,
12028
12218
  ai: ai ?? void 0,
12029
12219
  allowRecording,
12030
12220
  readOnly: selectedImage !== void 0 || selectedManagedOutput !== void 0 || selectedOutsideIn !== null && !selectedOutsideInEditingEnabled,
12031
- onOpenSettings: openSettings
12221
+ onOpenSettings: openDictationSettings
12032
12222
  }
12033
12223
  ),
12034
- hostSupports3("speechOutput") ? /* @__PURE__ */ jsx19(
12224
+ hostSupports3("speechOutput") ? /* @__PURE__ */ jsx21(
12035
12225
  SpeechToolbarControl,
12036
12226
  {
12037
12227
  speech,
12038
- onOpenSettings: openSettings,
12228
+ onOpenSettings: openNarrationSettings,
12039
12229
  readOnly: selectedImage !== void 0 || selectedOutsideIn !== null && !selectedOutsideInEditingEnabled
12040
12230
  }
12041
- ) : /* @__PURE__ */ jsx19(SpeechMenuBridge, {})
12231
+ ) : /* @__PURE__ */ jsx21(SpeechMenuBridge, {})
12042
12232
  ] }),
12043
- canRestoreSplitView && /* @__PURE__ */ jsx19(
12233
+ canRestoreSplitView && /* @__PURE__ */ jsx21(
12044
12234
  "button",
12045
12235
  {
12046
12236
  className: "db-restore-split",
12047
12237
  onClick: () => updateSidebarPreference("pinned"),
12048
12238
  "aria-label": "Restore split view",
12049
12239
  title: "Restore split view",
12050
- children: /* @__PURE__ */ jsx19(SplitViewIcon, {})
12240
+ children: /* @__PURE__ */ jsx21(SplitViewIcon, {})
12051
12241
  }
12052
12242
  ),
12053
- git.repo && /* @__PURE__ */ jsx19(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx19(GitToolbarControl, { selectedFile }) }),
12054
- /* @__PURE__ */ jsx19(
12243
+ git.repo && /* @__PURE__ */ jsx21(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx21(GitToolbarControl, { selectedFile }) }),
12244
+ /* @__PURE__ */ jsx21(
12055
12245
  ExportToolbarControls,
12056
12246
  {
12057
12247
  selectedFile,
@@ -12075,39 +12265,39 @@ function DocBlocksShell({
12075
12265
  }
12076
12266
  )
12077
12267
  }
12078
- ) }) : selectedFolder ? /* @__PURE__ */ jsxs17("div", { className: "db-folder-view", children: [
12079
- singlePane && /* @__PURE__ */ jsxs17("button", { className: "db-mobile-back", onClick: () => setMobileShowEditor(false), children: [
12080
- /* @__PURE__ */ jsx19("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx19(FolderGlyph, {}) }),
12268
+ ) }) : selectedFolder ? /* @__PURE__ */ jsxs19("div", { className: "db-folder-view", children: [
12269
+ singlePane && /* @__PURE__ */ jsxs19("button", { className: "db-mobile-back", onClick: () => setMobileShowEditor(false), children: [
12270
+ /* @__PURE__ */ jsx21("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx21(FolderGlyph, {}) }),
12081
12271
  "Back to files"
12082
12272
  ] }),
12083
- /* @__PURE__ */ jsxs17("div", { className: "db-folder-view-header", children: [
12084
- /* @__PURE__ */ jsx19("span", { className: "db-folder-view-icon", children: /* @__PURE__ */ jsx19(FolderGlyph, {}) }),
12085
- /* @__PURE__ */ jsx19("span", { className: "db-folder-view-path", children: selectedFolder })
12273
+ /* @__PURE__ */ jsxs19("div", { className: "db-folder-view-header", children: [
12274
+ /* @__PURE__ */ jsx21("span", { className: "db-folder-view-icon", children: /* @__PURE__ */ jsx21(FolderGlyph, {}) }),
12275
+ /* @__PURE__ */ jsx21("span", { className: "db-folder-view-path", children: selectedFolder })
12086
12276
  ] }),
12087
- visibleFolderEntries.length === 0 ? /* @__PURE__ */ jsx19("p", { className: "db-folder-view-empty", children: "This folder is empty." }) : /* @__PURE__ */ jsx19("ul", { className: "db-folder-view-list", children: visibleFolderEntries.map((entry) => /* @__PURE__ */ jsxs17(
12277
+ visibleFolderEntries.length === 0 ? /* @__PURE__ */ jsx21("p", { className: "db-folder-view-empty", children: "This folder is empty." }) : /* @__PURE__ */ jsx21("ul", { className: "db-folder-view-list", children: visibleFolderEntries.map((entry) => /* @__PURE__ */ jsxs19(
12088
12278
  "li",
12089
12279
  {
12090
12280
  className: "db-folder-view-item",
12091
12281
  onClick: () => handleSelect(entry.path, entry.kind),
12092
12282
  children: [
12093
- /* @__PURE__ */ jsx19("span", { className: "db-folder-view-item-icon", children: entry.kind === "directory" ? /* @__PURE__ */ jsx19(FolderGlyph, {}) : /* @__PURE__ */ jsx19(FileGlyph, {}) }),
12283
+ /* @__PURE__ */ jsx21("span", { className: "db-folder-view-item-icon", children: entry.kind === "directory" ? /* @__PURE__ */ jsx21(FolderGlyph, {}) : /* @__PURE__ */ jsx21(FileGlyph, {}) }),
12094
12284
  entry.name
12095
12285
  ]
12096
12286
  },
12097
12287
  entry.path
12098
12288
  )) })
12099
- ] }) : /* @__PURE__ */ jsxs17("div", { className: "db-shell-empty db-shell-empty--workspace", children: [
12100
- singlePane && /* @__PURE__ */ jsxs17("button", { className: "db-mobile-back", onClick: () => setMobileShowEditor(false), children: [
12101
- /* @__PURE__ */ jsx19("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx19(FolderGlyph, {}) }),
12289
+ ] }) : /* @__PURE__ */ jsxs19("div", { className: "db-shell-empty db-shell-empty--workspace", children: [
12290
+ singlePane && /* @__PURE__ */ jsxs19("button", { className: "db-mobile-back", onClick: () => setMobileShowEditor(false), children: [
12291
+ /* @__PURE__ */ jsx21("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx21(FolderGlyph, {}) }),
12102
12292
  "Back to files"
12103
12293
  ] }),
12104
- /* @__PURE__ */ jsxs17("div", { className: "db-workspace-empty-content", children: [
12105
- /* @__PURE__ */ jsx19("span", { className: "db-workspace-empty-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx19(FileGlyph, {}) }),
12106
- /* @__PURE__ */ jsx19("h1", { children: activeWorkspaceDescriptor?.name ?? "Workspace" }),
12107
- /* @__PURE__ */ jsx19("p", { children: "Choose a Markdown document from the sidebar, or create a new one." }),
12108
- /* @__PURE__ */ jsxs17("div", { className: "db-workspace-empty-actions", children: [
12109
- /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => void handleNewFile(), children: "New document" }),
12110
- /* @__PURE__ */ jsx19(
12294
+ /* @__PURE__ */ jsxs19("div", { className: "db-workspace-empty-content", children: [
12295
+ /* @__PURE__ */ jsx21("span", { className: "db-workspace-empty-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx21(FileGlyph, {}) }),
12296
+ /* @__PURE__ */ jsx21("h1", { children: activeWorkspaceDescriptor?.name ?? "Workspace" }),
12297
+ /* @__PURE__ */ jsx21("p", { children: "Choose a Markdown document from the sidebar, or create a new one." }),
12298
+ /* @__PURE__ */ jsxs19("div", { className: "db-workspace-empty-actions", children: [
12299
+ /* @__PURE__ */ jsx21("button", { type: "button", onClick: () => void handleNewFile(), children: "New document" }),
12300
+ /* @__PURE__ */ jsx21(
12111
12301
  "button",
12112
12302
  {
12113
12303
  type: "button",
@@ -12116,7 +12306,7 @@ function DocBlocksShell({
12116
12306
  children: "New folder"
12117
12307
  }
12118
12308
  ),
12119
- (hostSupports3("workspaceFolderPicker") || typeof globalThis.showDirectoryPicker === "function") && /* @__PURE__ */ jsx19(
12309
+ (hostSupports3("workspaceFolderPicker") || typeof globalThis.showDirectoryPicker === "function") && /* @__PURE__ */ jsx21(
12120
12310
  "button",
12121
12311
  {
12122
12312
  type: "button",
@@ -12126,10 +12316,10 @@ function DocBlocksShell({
12126
12316
  }
12127
12317
  )
12128
12318
  ] }),
12129
- showBrowserStorageWarning && /* @__PURE__ */ jsx19("p", { className: "db-workspace-empty-hint", children: "Use the sidebar backup action to keep a portable copy of this workspace." })
12319
+ showBrowserStorageWarning && /* @__PURE__ */ jsx21("p", { className: "db-workspace-empty-hint", children: "Use the sidebar backup action to keep a portable copy of this workspace." })
12130
12320
  ] })
12131
12321
  ] }),
12132
- /* @__PURE__ */ jsx19(
12322
+ /* @__PURE__ */ jsx21(
12133
12323
  UpdateAvailableNotice,
12134
12324
  {
12135
12325
  available: updateAvailable,
@@ -12139,7 +12329,7 @@ function DocBlocksShell({
12139
12329
  }
12140
12330
  )
12141
12331
  ] }),
12142
- welcomeScreenShown && /* @__PURE__ */ jsx19(
12332
+ welcomeScreenShown && /* @__PURE__ */ jsx21(
12143
12333
  WelcomeScreen,
12144
12334
  {
12145
12335
  onCreateDocument: handleNewFile,