@bendyline/docblocks-react 2.7.1 → 2.7.3

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 (38) hide show
  1. package/README.md +1 -1
  2. package/THIRD_PARTY_NOTICES.txt +290 -48
  3. package/dist/{AiDiagrams-LFV4YU6W.js → AiDiagrams-QE3LVYFK.js} +2 -2
  4. package/dist/{AiEditorAssistant-GN2KXKZD.js → AiEditorAssistant-YLJ5OZK2.js} +203 -164
  5. package/dist/AiStudyDialog-4TQZZGU3.js +1150 -0
  6. package/dist/{ExportDialog-IMBVGRYG.js → ExportDialog-JRVZCG3J.js} +2 -2
  7. package/dist/{ExportToolbarControls-MUM6HM3K.js → ExportToolbarControls-A2YBKUUD.js} +46 -9
  8. package/dist/KeyboardShortcutsDialog-G5OBDTNR.js +145 -0
  9. package/dist/{PresentationMaker-W2JIBHRN.js → PresentationMaker-P2JP6UUX.js} +2 -2
  10. package/dist/{Settings-DuXk6baH.d.ts → Settings-ByNImjk5.d.ts} +13 -13
  11. package/dist/{SpeechToolbarControl-OSQS7NVY.js → SpeechToolbarControl-CLU7RB2G.js} +1 -1
  12. package/dist/{TextFromNarration-XYRAB6O2.js → TextFromNarration-NITJQ4IB.js} +1 -1
  13. package/dist/{WorkspaceSearchPanel-BKZJRPMY.js → WorkspaceSearchPanel-J6BKEZQJ.js} +1 -1
  14. package/dist/{chunk-X3DDTJKR.js → chunk-3CE5RH2B.js} +255 -17
  15. package/dist/{chunk-UG4G7PJ4.js → chunk-5O5YTOXG.js} +1 -1
  16. package/dist/{chunk-VO2JYYQZ.js → chunk-6JJOGV6M.js} +5 -13
  17. package/dist/{chunk-X437UAF7.js → chunk-6MSHXQNB.js} +7 -2
  18. package/dist/{chunk-BCQZTWE5.js → chunk-6PA7QBZT.js} +107 -24
  19. package/dist/chunk-ACQF63SB.js +136 -0
  20. package/dist/chunk-DICE7VBJ.js +77 -0
  21. package/dist/{chunk-EPOLZNFD.js → chunk-EOU2JWAQ.js} +186 -71
  22. package/dist/{chunk-G4MFB3IO.js → chunk-VG434562.js} +2 -70
  23. package/dist/chunk-XNT66JC2.js +168 -0
  24. package/dist/{chunk-BD54Z5XP.js → chunk-Y5OE3HJC.js} +4 -3
  25. package/dist/{chunk-NAH52736.js → chunk-YPIVCCTB.js} +969 -98
  26. package/dist/{chunk-W55E6TE2.js → chunk-ZMCQO57Q.js} +28 -23
  27. package/dist/editor.js +7 -5
  28. package/dist/export/index.d.ts +27 -8
  29. package/dist/export/index.js +4 -4
  30. package/dist/index.d.ts +36 -8
  31. package/dist/index.js +629 -446
  32. package/dist/run-export-OHRNT2TP.js +13 -0
  33. package/dist/settings/index.d.ts +1 -1
  34. package/dist/settings/index.js +1 -1
  35. package/package.json +9 -8
  36. package/src/styles/docblocks.css +968 -329
  37. package/dist/chunk-EA4BO6E4.js +0 -73
  38. package/dist/run-export-47X5FTYZ.js +0 -11
package/dist/index.js CHANGED
@@ -1,4 +1,8 @@
1
1
  import {
2
+ ProgressivePlayer
3
+ } from "./chunk-2IYBBFQX.js";
4
+ import {
5
+ BackupIcon,
2
6
  FolderIcon,
3
7
  MoreIcon,
4
8
  NewFileIcon,
@@ -10,16 +14,13 @@ import {
10
14
  SortByNameIcon,
11
15
  SplitViewIcon,
12
16
  WorkspaceIcon
13
- } from "./chunk-EA4BO6E4.js";
17
+ } from "./chunk-DICE7VBJ.js";
14
18
  import {
15
19
  useConfirmDialog
16
20
  } from "./chunk-6B7G33D5.js";
17
21
  import {
18
22
  createSpeechInputProvider
19
23
  } from "./chunk-KBDZDFPU.js";
20
- import {
21
- ProgressivePlayer
22
- } from "./chunk-2IYBBFQX.js";
23
24
  import {
24
25
  sharedDocumentFilename
25
26
  } from "./chunk-SPUPWCSI.js";
@@ -50,13 +51,13 @@ import {
50
51
  } from "./chunk-KWG6UP5O.js";
51
52
  import {
52
53
  runExport
53
- } from "./chunk-BCQZTWE5.js";
54
+ } from "./chunk-6PA7QBZT.js";
54
55
  import {
55
56
  createImageSaveOutput
56
57
  } from "./chunk-UONFWKJ7.js";
57
58
  import {
58
59
  buildExportFilename
59
- } from "./chunk-UG4G7PJ4.js";
60
+ } from "./chunk-5O5YTOXG.js";
60
61
  import {
61
62
  createLocalProofingIgnoreStore
62
63
  } from "./chunk-DUKTAKB4.js";
@@ -86,28 +87,35 @@ import {
86
87
  saveProofingPreferences,
87
88
  saveThemePreference,
88
89
  saveWriteCanvasPreferences
89
- } from "./chunk-W55E6TE2.js";
90
+ } from "./chunk-ZMCQO57Q.js";
90
91
  import {
91
92
  FindButton,
92
- findShortcutLabel,
93
93
  focusFindInput,
94
- isApplePlatform,
95
- matchShortcut,
96
94
  pickEmptyDocumentPrompt,
97
- shortcutLabel,
98
95
  useResponsivePreviewViewportPreset
99
- } from "./chunk-G4MFB3IO.js";
100
- import "./chunk-EPOLZNFD.js";
101
- import "./chunk-NAH52736.js";
96
+ } from "./chunk-VG434562.js";
97
+ import {
98
+ findShortcutLabel,
99
+ isApplePlatform,
100
+ matchShortcut,
101
+ shortcutLabel
102
+ } from "./chunk-ACQF63SB.js";
103
+ import "./chunk-EOU2JWAQ.js";
104
+ import {
105
+ buildIssueReportUrl,
106
+ displayBuildDate,
107
+ localDateStamp,
108
+ openExternalUrl
109
+ } from "./chunk-YPIVCCTB.js";
102
110
  import "./chunk-K4I3NJFL.js";
103
111
  import {
104
112
  ExportDialog
105
- } from "./chunk-BD54Z5XP.js";
113
+ } from "./chunk-Y5OE3HJC.js";
106
114
  import "./chunk-YBEYTVU2.js";
107
115
  import {
108
116
  DEFAULT_OPTIONS,
109
117
  loadLastExportOptions
110
- } from "./chunk-X437UAF7.js";
118
+ } from "./chunk-6MSHXQNB.js";
111
119
  import {
112
120
  Dialog,
113
121
  dismissTopmostDialog
@@ -1765,8 +1773,19 @@ import {
1765
1773
  } from "@bendyline/docblocks/workspace-settings";
1766
1774
  var UPDATE_FROM_MARKDOWN_KEY = "squisq-updatefrommarkdown";
1767
1775
  var HTML_OUTPUT_KEY = "squisq-html-output";
1776
+ var pdfWorkerSrc = null;
1777
+ var configuredPdfWorkerSrc = null;
1778
+ function setOutsideInPdfWorker(src) {
1779
+ pdfWorkerSrc = src ?? null;
1780
+ }
1768
1781
  async function loadOutsideInModule() {
1769
- return await import("@bendyline/squisq-formats/outside-in");
1782
+ const outsideIn = await import("@bendyline/squisq-formats/outside-in");
1783
+ if (pdfWorkerSrc && pdfWorkerSrc !== configuredPdfWorkerSrc) {
1784
+ const { configurePdfWorker } = await import("@bendyline/squisq-formats/pdf");
1785
+ configurePdfWorker(pdfWorkerSrc);
1786
+ configuredPdfWorkerSrc = pdfWorkerSrc;
1787
+ }
1788
+ return outsideIn;
1770
1789
  }
1771
1790
  async function readOutsideInMetadata(source) {
1772
1791
  const { readOutsideInMetadata: readMetadata } = await loadOutsideInModule();
@@ -2357,6 +2376,17 @@ function newFileName(name, format) {
2357
2376
  const stem = name.trim().replace(SELECTABLE_FILE_EXTENSION, "");
2358
2377
  return stem ? `${stem}${NEW_FILE_EXTENSIONS[format]}` : null;
2359
2378
  }
2379
+ var SAVED_AS = {
2380
+ docx: "Word document",
2381
+ xlsx: "Excel workbook",
2382
+ pdf: "PDF",
2383
+ "web-interactive": "web page",
2384
+ "web-static": "web page"
2385
+ };
2386
+ function newFileFormatHint(format) {
2387
+ if (format === "markdown") return null;
2388
+ return `You write in Markdown; each save updates the ${SAVED_AS[format]}.`;
2389
+ }
2360
2390
  function newFileHtmlOutput(format) {
2361
2391
  if (format === "web-static") return "static";
2362
2392
  if (format === "web-interactive") return "interactive";
@@ -2367,13 +2397,11 @@ function newFileHtmlOutput(format) {
2367
2397
  import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
2368
2398
  function NewFileFormatOptions() {
2369
2399
  return /* @__PURE__ */ jsxs3(Fragment2, { children: [
2370
- /* @__PURE__ */ jsxs3("optgroup", { label: "Document", children: [
2371
- /* @__PURE__ */ jsx4("option", { value: "markdown", children: "Markdown (.md)" }),
2400
+ /* @__PURE__ */ jsx4("option", { value: "markdown", children: "Markdown (.md)" }),
2401
+ /* @__PURE__ */ jsxs3("optgroup", { label: "Written in Markdown, saved as", children: [
2372
2402
  /* @__PURE__ */ jsx4("option", { value: "docx", children: "Word document (.docx)" }),
2373
2403
  /* @__PURE__ */ jsx4("option", { value: "xlsx", children: "Excel workbook (.xlsx)" }),
2374
- /* @__PURE__ */ jsx4("option", { value: "pdf", children: "PDF document (.pdf)" })
2375
- ] }),
2376
- /* @__PURE__ */ jsxs3("optgroup", { label: "Web page", children: [
2404
+ /* @__PURE__ */ jsx4("option", { value: "pdf", children: "PDF (.pdf)" }),
2377
2405
  /* @__PURE__ */ jsx4("option", { value: "web-interactive", children: "Web page \u2014 Interactive (.html)" }),
2378
2406
  /* @__PURE__ */ jsx4("option", { value: "web-static", children: "Web page \u2014 Static (.html)" })
2379
2407
  ] })
@@ -2384,6 +2412,7 @@ function NewFileFormatOptions() {
2384
2412
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2385
2413
  var INTERNAL_DRAG_TYPE = "application/x-docblocks-entry";
2386
2414
  var NEW_ITEM_ERROR_ID = "db-new-item-error";
2415
+ var NEW_ITEM_HINT_ID = "db-new-item-hint";
2387
2416
  function normalisePath2(path) {
2388
2417
  return parseWorkspacePath4(path);
2389
2418
  }
@@ -2419,6 +2448,7 @@ function isInternalDrag(dataTransfer) {
2419
2448
  }
2420
2449
  function FileExplorer({
2421
2450
  provider,
2451
+ loading = false,
2422
2452
  metadataRefreshKey,
2423
2453
  activeFilePath,
2424
2454
  sortMode,
@@ -3105,6 +3135,7 @@ function FileExplorer({
3105
3135
  {
3106
3136
  className: "db-new-item-format",
3107
3137
  "aria-label": "New file type",
3138
+ "aria-describedby": newFileFormatHint(newFileFormat) ? NEW_ITEM_HINT_ID : void 0,
3108
3139
  value: newFileFormat,
3109
3140
  disabled: newItemCreationPending,
3110
3141
  onChange: (event) => {
@@ -3119,6 +3150,7 @@ function FileExplorer({
3119
3150
  ]
3120
3151
  }
3121
3152
  ),
3153
+ newItemType === "file" && newFileFormatHint(newFileFormat) && /* @__PURE__ */ jsx5("p", { id: NEW_ITEM_HINT_ID, className: "db-new-item-hint", children: newFileFormatHint(newFileFormat) }),
3122
3154
  newItemError && /* @__PURE__ */ jsx5("div", { id: NEW_ITEM_ERROR_ID, className: "db-tree-error", role: "alert", children: newItemError })
3123
3155
  ] }),
3124
3156
  moveError && /* @__PURE__ */ jsx5("div", { className: "db-tree-error", role: "alert", children: moveError }),
@@ -3143,7 +3175,7 @@ function FileExplorer({
3143
3175
  ]
3144
3176
  }
3145
3177
  ),
3146
- tree.loading ? /* @__PURE__ */ jsx5("div", { className: "db-tree", role: "status", "aria-live": "polite", children: /* @__PURE__ */ jsx5("div", { className: "db-tree-loading", children: "Loading..." }) }) : filterVisibleFileEntries(tree.entries).length === 0 ? /* @__PURE__ */ jsx5("div", { className: "db-tree", children: /* @__PURE__ */ jsx5("div", { className: "db-tree-empty", children: "No files yet" }) }) : /* @__PURE__ */ jsx5(
3178
+ tree.loading || loading ? /* @__PURE__ */ jsx5("div", { className: "db-tree", role: "status", "aria-live": "polite", children: /* @__PURE__ */ jsx5("div", { className: "db-tree-loading", children: "Loading..." }) }) : filterVisibleFileEntries(tree.entries).length === 0 ? /* @__PURE__ */ jsx5("div", { className: "db-tree", children: /* @__PURE__ */ jsx5("div", { className: "db-tree-empty", children: "No files yet" }) }) : /* @__PURE__ */ jsx5(
3147
3179
  "div",
3148
3180
  {
3149
3181
  ref: treeRef,
@@ -3210,6 +3242,7 @@ function WorkspacePicker({
3210
3242
  onCloneRepository,
3211
3243
  onRemoveWorkspace,
3212
3244
  refreshKey,
3245
+ loading = false,
3213
3246
  className
3214
3247
  }) {
3215
3248
  const [workspaces, setWorkspaces] = useState5([]);
@@ -3366,7 +3399,7 @@ function WorkspacePicker({
3366
3399
  }
3367
3400
  }, [newWorkspaceName, newWorkspacePending, onSelect, refresh, workspaces]);
3368
3401
  const activeWs = workspaces.find((w) => w.id === activeWorkspaceId);
3369
- const activeWorkspaceName = activeWs?.name ?? "No workspace";
3402
+ const activeWorkspaceName = activeWs?.name ?? (loading ? "Loading\u2026" : "No workspace");
3370
3403
  return /* @__PURE__ */ jsxs5("div", { ref: pickerRef, className: `db-workspace-picker ${className ?? ""}`, children: [
3371
3404
  /* @__PURE__ */ jsxs5(
3372
3405
  "button",
@@ -3636,7 +3669,16 @@ async function prepareHostLifecycle(session, request) {
3636
3669
  }
3637
3670
 
3638
3671
  // src/DocBlocksShell/DocBlocksShell.tsx
3639
- import { useState as useState23, useCallback as useCallback18, useEffect as useEffect29, useRef as useRef19, useMemo as useMemo6, lazy as lazy2, Suspense as Suspense2 } from "react";
3672
+ import {
3673
+ useState as useState23,
3674
+ useCallback as useCallback18,
3675
+ useEffect as useEffect29,
3676
+ useLayoutEffect as useLayoutEffect4,
3677
+ useRef as useRef19,
3678
+ useMemo as useMemo6,
3679
+ lazy as lazy2,
3680
+ Suspense as Suspense2
3681
+ } from "react";
3640
3682
  import {
3641
3683
  DocumentVersionManager
3642
3684
  } from "@bendyline/squisq/versions";
@@ -3703,6 +3745,14 @@ function readinessSentence(readiness, ready) {
3703
3745
  return readiness.state === "ready" ? ready : readiness.reason ?? "";
3704
3746
  }
3705
3747
  var PREVIEW_TEXT = "This is how I sound when I read your documents aloud.";
3748
+ function unreachable(cause) {
3749
+ const detail = cause instanceof Error ? cause.message : void 0;
3750
+ return {
3751
+ code: "unknown",
3752
+ message: "DocBlocks could not check speech on this computer.",
3753
+ ...detail ? { detail } : {}
3754
+ };
3755
+ }
3706
3756
  function SpeechSettingsControls({ speech }) {
3707
3757
  const [status, setStatus] = useState6(null);
3708
3758
  const [catalog, setCatalog] = useState6(null);
@@ -3717,11 +3767,15 @@ function SpeechSettingsControls({ speech }) {
3717
3767
  const voiceId = useId2();
3718
3768
  const speedId = useId2();
3719
3769
  const refresh = useCallback7(async () => {
3720
- const [nextStatus, nextCatalog] = await Promise.all([speech.status(), speech.catalog()]);
3721
- if (!mounted.current) return;
3722
- setStatus(nextStatus);
3723
- if (nextCatalog.ok) setCatalog(nextCatalog.value);
3724
- else setFailure(nextCatalog.error);
3770
+ try {
3771
+ const [nextStatus, nextCatalog] = await Promise.all([speech.status(), speech.catalog()]);
3772
+ if (!mounted.current) return;
3773
+ setStatus(nextStatus);
3774
+ if (nextCatalog.ok) setCatalog(nextCatalog.value);
3775
+ else setFailure(nextCatalog.error);
3776
+ } catch (cause) {
3777
+ if (mounted.current) setFailure(unreachable(cause));
3778
+ }
3725
3779
  }, [speech]);
3726
3780
  const stopPreview = useCallback7(() => {
3727
3781
  preview.current?.handle.cancel();
@@ -3739,9 +3793,14 @@ function SpeechSettingsControls({ speech }) {
3739
3793
  });
3740
3794
  });
3741
3795
  void refresh();
3742
- void speech.getPreferences().then((initial) => {
3743
- if (mounted.current) setPreferences(initial);
3744
- });
3796
+ void speech.getPreferences().then(
3797
+ (initial) => {
3798
+ if (mounted.current) setPreferences(initial);
3799
+ },
3800
+ (cause) => {
3801
+ if (mounted.current) setFailure(unreachable(cause));
3802
+ }
3803
+ );
3745
3804
  return () => {
3746
3805
  mounted.current = false;
3747
3806
  installHandle.current?.cancel();
@@ -3813,7 +3872,13 @@ function SpeechSettingsControls({ speech }) {
3813
3872
  setPreviewing(false);
3814
3873
  });
3815
3874
  }, [speech, stopPreview]);
3816
- if (!status || !catalog || !preferences) return null;
3875
+ if (!status || !catalog || !preferences) {
3876
+ if (!failure) return null;
3877
+ return /* @__PURE__ */ jsxs6("fieldset", { className: "db-settings-fieldset", children: [
3878
+ /* @__PURE__ */ jsx7("legend", { className: "db-settings-legend", children: "Speech" }),
3879
+ /* @__PURE__ */ jsx7("p", { className: "db-settings-hint db-settings-ai-error", role: "alert", children: failure.message })
3880
+ ] });
3881
+ }
3817
3882
  const sttModels = catalog.models.filter((model) => model.kind === "stt");
3818
3883
  const ttsModel = catalog.models.find((model) => model.kind === "tts") ?? null;
3819
3884
  const installedStt = sttModels.filter((model) => model.installed);
@@ -3989,6 +4054,7 @@ function formatBytes(bytes) {
3989
4054
  }
3990
4055
  return `${value >= 100 || unit === "B" ? Math.round(value) : value.toFixed(1)} ${unit}`;
3991
4056
  }
4057
+ var DOCUMENTATION_URL = "https://docblocks.com/docs/";
3992
4058
  var MORE_INFORMATION_URLS = Object.freeze({
3993
4059
  electron: "https://docblocks.com/desktop/",
3994
4060
  capacitor: "https://docblocks.com/web/",
@@ -3996,9 +4062,10 @@ var MORE_INFORMATION_URLS = Object.freeze({
3996
4062
  });
3997
4063
  function AppMenu({
3998
4064
  logoUrl,
4065
+ logoDarkUrl,
3999
4066
  themePreference = "auto",
4000
4067
  onThemeChange,
4001
- accentColor = "brown",
4068
+ accentColor = "rust",
4002
4069
  onAccentColorChange,
4003
4070
  interfaceFont = "system",
4004
4071
  onInterfaceFontChange,
@@ -4010,6 +4077,7 @@ function AppMenu({
4010
4077
  onVersioningPreferenceChange,
4011
4078
  onOpenWorkspaceSettings,
4012
4079
  onDownloadAllWorkspaces,
4080
+ onShowKeyboardShortcuts,
4013
4081
  onKeepBrowserData,
4014
4082
  onInstallApp,
4015
4083
  getStorageEstimate,
@@ -4027,7 +4095,8 @@ function AppMenu({
4027
4095
  if (settingsRequest > 0) setShowSettings(true);
4028
4096
  }, [settingsRequest]);
4029
4097
  const [requestingPersistentStorage, setRequestingPersistentStorage] = useState7(false);
4030
- const moreInformationUrl = MORE_INFORMATION_URLS[getHostEnvironment()?.surface ?? "web"] ?? MORE_INFORMATION_URLS.web;
4098
+ const surface = getHostEnvironment()?.surface ?? "web";
4099
+ const moreInformationUrl = MORE_INFORMATION_URLS[surface] ?? MORE_INFORMATION_URLS.web;
4031
4100
  const containerRef = useRef8(null);
4032
4101
  const { menuRef, triggerRef, handleMenuKeyDown, handleTriggerKeyDown, closeMenu } = useMenuKeyboard(isOpen, setIsOpen);
4033
4102
  const [storageEstimate, setStorageEstimate] = useState7(null);
@@ -4082,16 +4151,28 @@ function AppMenu({
4082
4151
  "aria-expanded": isOpen,
4083
4152
  "aria-haspopup": "menu",
4084
4153
  children: [
4085
- logoUrl ? /* @__PURE__ */ jsx8(
4086
- "img",
4087
- {
4088
- src: logoUrl,
4089
- alt: "DocBlocks",
4090
- className: "db-app-menu-logo",
4091
- width: 1266,
4092
- height: 544
4093
- }
4094
- ) : /* @__PURE__ */ jsx8("span", { className: "db-app-menu-label", children: "docblocks" }),
4154
+ logoUrl ? /* @__PURE__ */ jsxs7(Fragment5, { children: [
4155
+ /* @__PURE__ */ jsx8(
4156
+ "img",
4157
+ {
4158
+ src: logoUrl,
4159
+ alt: "DocBlocks",
4160
+ className: `db-app-menu-logo ${logoDarkUrl ? "db-app-menu-logo--light" : "db-app-menu-logo--invert"}`,
4161
+ width: 557,
4162
+ height: 242
4163
+ }
4164
+ ),
4165
+ logoDarkUrl && /* @__PURE__ */ jsx8(
4166
+ "img",
4167
+ {
4168
+ src: logoDarkUrl,
4169
+ alt: "DocBlocks",
4170
+ className: "db-app-menu-logo db-app-menu-logo--dark",
4171
+ width: 557,
4172
+ height: 242
4173
+ }
4174
+ )
4175
+ ] }) : /* @__PURE__ */ jsx8("span", { className: "db-app-menu-label", children: "docblocks" }),
4095
4176
  /* @__PURE__ */ jsx8(
4096
4177
  "span",
4097
4178
  {
@@ -4130,6 +4211,17 @@ function AppMenu({
4130
4211
  children: "Install DocBlocks\u2026"
4131
4212
  }
4132
4213
  ),
4214
+ (onDownloadAllWorkspaces || onKeepBrowserData) && /* @__PURE__ */ jsx8("div", { className: "db-app-menu-divider" }),
4215
+ onDownloadAllWorkspaces && /* @__PURE__ */ jsx8(
4216
+ "button",
4217
+ {
4218
+ className: "db-app-menu-item",
4219
+ role: "menuitem",
4220
+ tabIndex: -1,
4221
+ onClick: () => handleAction(() => void onDownloadAllWorkspaces()),
4222
+ children: "Back up all workspaces"
4223
+ }
4224
+ ),
4133
4225
  onKeepBrowserData && /* @__PURE__ */ jsx8(
4134
4226
  "button",
4135
4227
  {
@@ -4140,17 +4232,34 @@ function AppMenu({
4140
4232
  children: "Protect data from browser cleanup"
4141
4233
  }
4142
4234
  ),
4143
- onDownloadAllWorkspaces && /* @__PURE__ */ jsx8(
4235
+ /* @__PURE__ */ jsx8("div", { className: "db-app-menu-divider" }),
4236
+ onShowKeyboardShortcuts && /* @__PURE__ */ jsxs7(
4144
4237
  "button",
4238
+ {
4239
+ className: "db-app-menu-item db-app-menu-item--with-shortcut",
4240
+ role: "menuitem",
4241
+ tabIndex: -1,
4242
+ "aria-keyshortcuts": "F1",
4243
+ onClick: () => handleAction(onShowKeyboardShortcuts),
4244
+ children: [
4245
+ "Keyboard shortcuts",
4246
+ /* @__PURE__ */ jsx8("span", { className: "db-app-menu-shortcut", "aria-hidden": "true", children: "F1" })
4247
+ ]
4248
+ }
4249
+ ),
4250
+ /* @__PURE__ */ jsx8(
4251
+ "a",
4145
4252
  {
4146
4253
  className: "db-app-menu-item",
4147
4254
  role: "menuitem",
4148
4255
  tabIndex: -1,
4149
- onClick: () => handleAction(() => void onDownloadAllWorkspaces()),
4150
- children: "Download all workspaces"
4256
+ href: DOCUMENTATION_URL,
4257
+ target: "_blank",
4258
+ rel: "noopener noreferrer",
4259
+ onClick: () => closeMenu(false),
4260
+ children: "Documentation"
4151
4261
  }
4152
4262
  ),
4153
- /* @__PURE__ */ jsx8("div", { className: "db-app-menu-divider" }),
4154
4263
  /* @__PURE__ */ jsx8(
4155
4264
  "button",
4156
4265
  {
@@ -4288,29 +4397,13 @@ function AppMenu({
4288
4397
  /* @__PURE__ */ jsx8("strong", { children: "DocBlocks" }),
4289
4398
  " is a local-first Markdown document editor. Your files stay under your control."
4290
4399
  ] }),
4291
- /* @__PURE__ */ jsxs7("aside", { className: "db-about-beta", children: [
4292
- /* @__PURE__ */ jsx8("strong", { children: "Beta Software." }),
4293
- " We're still working through initial hiccups and issues. Please bear with us, make sure you keep backups, and",
4294
- " ",
4295
- /* @__PURE__ */ jsx8(
4296
- "a",
4297
- {
4298
- href: "https://github.com/bendyline/docblocks/issues/new",
4299
- target: "_blank",
4300
- rel: "noopener noreferrer",
4301
- children: "open issues"
4302
- }
4303
- ),
4304
- " ",
4305
- "where you find them. Thanks!"
4306
- ] }),
4307
4400
  appVersion && /* @__PURE__ */ jsxs7("p", { className: "db-about-version", children: [
4308
4401
  /* @__PURE__ */ jsx8("span", { children: "Version" }),
4309
4402
  /* @__PURE__ */ jsx8("code", { "aria-label": `DocBlocks version ${appVersion}`, children: appVersion })
4310
4403
  ] }),
4311
4404
  appBuildDate && /* @__PURE__ */ jsxs7("p", { className: "db-about-version", children: [
4312
4405
  /* @__PURE__ */ jsx8("span", { children: "Build" }),
4313
- /* @__PURE__ */ jsx8("time", { dateTime: appBuildDate, children: appBuildDate })
4406
+ /* @__PURE__ */ jsx8("time", { dateTime: appBuildDate, children: displayBuildDate(appBuildDate) })
4314
4407
  ] }),
4315
4408
  /* @__PURE__ */ jsxs7("p", { children: [
4316
4409
  "Built with",
@@ -4322,6 +4415,12 @@ function AppMenu({
4322
4415
  /* @__PURE__ */ jsx8("a", { href: "https://bendyline.com", target: "_blank", rel: "noopener noreferrer", children: "Bendyline" }),
4323
4416
  "."
4324
4417
  ] }),
4418
+ surface === "web" && /* @__PURE__ */ jsxs7("p", { children: [
4419
+ "See our free desktop apps at",
4420
+ " ",
4421
+ /* @__PURE__ */ jsx8("a", { href: MORE_INFORMATION_URLS.electron, target: "_blank", rel: "noopener noreferrer", children: "docblocks.com/desktop" }),
4422
+ "."
4423
+ ] }),
4325
4424
  /* @__PURE__ */ jsxs7("p", { className: "db-dialog-links", children: [
4326
4425
  /* @__PURE__ */ jsx8("a", { href: moreInformationUrl, target: "_blank", rel: "noopener noreferrer", children: "More information..." }),
4327
4426
  /* @__PURE__ */ jsx8(
@@ -4453,7 +4552,7 @@ function WorkspaceSettingsButton({
4453
4552
  role: "menuitem",
4454
4553
  tabIndex: -1,
4455
4554
  onClick: () => handleAction(onDownload),
4456
- children: "Download workspace"
4555
+ children: "Back up this workspace"
4457
4556
  }
4458
4557
  ),
4459
4558
  /* @__PURE__ */ jsx9("div", { className: "db-ws-settings-divider" }),
@@ -4896,7 +4995,7 @@ function useDocumentSession(autoSaveDelayMs = 500) {
4896
4995
  import { lazy, Suspense } from "react";
4897
4996
  import { jsx as jsx12 } from "react/jsx-runtime";
4898
4997
  var ExportToolbarControlsImplementation = lazy(
4899
- () => import("./ExportToolbarControls-MUM6HM3K.js").then((module) => ({
4998
+ () => import("./ExportToolbarControls-A2YBKUUD.js").then((module) => ({
4900
4999
  default: module.ExportToolbarControls
4901
5000
  }))
4902
5001
  );
@@ -5547,14 +5646,34 @@ async function claimOutsideInTarget(provider, desiredPath) {
5547
5646
  }
5548
5647
  throw new Error(`Too many documents are already named like \u201C${desiredPath}\u201D.`);
5549
5648
  }
5649
+ function directoriesUnder(files, root) {
5650
+ const directories = /* @__PURE__ */ new Set();
5651
+ for (const file of files) {
5652
+ if (!file.startsWith(`${root}/`)) continue;
5653
+ for (let dir = file.slice(0, file.lastIndexOf("/")); dir.length >= root.length; ) {
5654
+ directories.add(dir);
5655
+ const slash = dir.lastIndexOf("/");
5656
+ if (slash < 0) break;
5657
+ dir = dir.slice(0, slash);
5658
+ }
5659
+ }
5660
+ return [...directories].sort((a, b) => b.split("/").length - a.split("/").length);
5661
+ }
5662
+ async function removeIfEmptyDirectory(provider, path) {
5663
+ const providerV2 = getFileSystemProviderV27(provider);
5664
+ if (!providerV2) return;
5665
+ await providerV2.remove(parseWorkspacePath6(path), { recursive: false, missing: "ignore" }).catch(() => void 0);
5666
+ }
5550
5667
  async function importOutsideInFile(file, provider) {
5551
5668
  const claim = await claimOutsideInTarget(provider, file.name);
5552
5669
  const created = [claim.path];
5670
+ const companionDirectory = resolveOutsideInLayout2(claim.path)?.companionDirectory ?? null;
5553
5671
  try {
5554
5672
  const sourceBytes = await file.arrayBuffer();
5555
5673
  const layout = resolveOutsideInLayout2(claim.path);
5556
5674
  if (!layout) throw new Error(`Outside-in editing does not support \u201C${claim.path}\u201D.`);
5557
- const imported = await (isOutsideInDataFormat(layout.format) ? importOutsideInDataSidecar({ data: sourceBytes, targetPath: claim.path }) : importOutsideInDocument({ data: sourceBytes, targetPath: claim.path }));
5675
+ const conversionBytes = sourceBytes.slice(0);
5676
+ const imported = await (isOutsideInDataFormat(layout.format) ? importOutsideInDataSidecar({ data: conversionBytes, targetPath: claim.path }) : importOutsideInDocument({ data: conversionBytes, targetPath: claim.path }));
5558
5677
  for (const entry of await imported.container.listFiles()) {
5559
5678
  if (/\.md$/i.test(entry.path)) continue;
5560
5679
  const data = await imported.container.readFile(entry.path);
@@ -5568,9 +5687,14 @@ async function importOutsideInFile(file, provider) {
5568
5687
  await writeProviderBytes(provider, claim.path, sourceBytes, "upsert");
5569
5688
  return claim;
5570
5689
  } catch (error) {
5571
- for (const path of created.reverse()) {
5690
+ for (const path of [...created].reverse()) {
5572
5691
  await removeProviderEntry(provider, path).catch(() => void 0);
5573
5692
  }
5693
+ if (companionDirectory) {
5694
+ for (const directory of directoriesUnder(created, companionDirectory)) {
5695
+ await removeIfEmptyDirectory(provider, directory);
5696
+ }
5697
+ }
5574
5698
  throw error;
5575
5699
  }
5576
5700
  }
@@ -5762,6 +5886,8 @@ function NewDocumentDialog({
5762
5886
  const inputRef = useRef15(null);
5763
5887
  const nameId = useId4();
5764
5888
  const formatId = useId4();
5889
+ const hintId = useId4();
5890
+ const hint = newFileFormatHint(format);
5765
5891
  const filename = newFileName(name, format);
5766
5892
  const cancel = useCallback15(() => onSettle(null), [onSettle]);
5767
5893
  const submit = useCallback15(() => {
@@ -5814,16 +5940,44 @@ function NewDocumentDialog({
5814
5940
  {
5815
5941
  id: formatId,
5816
5942
  className: "db-git-form-input",
5943
+ "aria-describedby": hint ? hintId : void 0,
5817
5944
  value: format,
5818
5945
  onChange: (e) => setFormat(e.target.value),
5819
5946
  children: /* @__PURE__ */ jsx14(NewFileFormatOptions, {})
5820
5947
  }
5821
- )
5948
+ ),
5949
+ hint && /* @__PURE__ */ jsx14("p", { id: hintId, className: "db-new-document-hint", children: hint })
5822
5950
  ] })
5823
5951
  }
5824
5952
  );
5825
5953
  }
5826
5954
 
5955
+ // src/DocBlocksShell/EditorErrorBoundary.tsx
5956
+ import { Component } from "react";
5957
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
5958
+ var EditorErrorBoundary = class extends Component {
5959
+ constructor() {
5960
+ super(...arguments);
5961
+ this.state = { error: null, resetKey: this.props.resetKey };
5962
+ }
5963
+ static getDerivedStateFromError(error) {
5964
+ return { error };
5965
+ }
5966
+ static getDerivedStateFromProps(props, state) {
5967
+ return props.resetKey === state.resetKey ? null : { error: null, resetKey: props.resetKey };
5968
+ }
5969
+ render() {
5970
+ const { error } = this.state;
5971
+ if (!error) return this.props.children;
5972
+ return /* @__PURE__ */ jsx15("div", { className: "db-shell-empty db-shell-empty--workspace", role: "alert", children: /* @__PURE__ */ jsxs13("div", { className: "db-workspace-empty-content", children: [
5973
+ /* @__PURE__ */ jsx15("h1", { children: "This document couldn\u2019t be displayed" }),
5974
+ /* @__PURE__ */ jsx15("p", { children: "The editor ran into a problem drawing it. The document itself is unaffected." }),
5975
+ /* @__PURE__ */ jsx15("div", { className: "db-workspace-empty-actions", children: /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => this.setState({ error: null }), children: "Try again" }) }),
5976
+ /* @__PURE__ */ jsx15("p", { className: "db-workspace-empty-hint", children: error.message })
5977
+ ] }) });
5978
+ }
5979
+ };
5980
+
5827
5981
  // src/preferences/new-file-format.ts
5828
5982
  var STORAGE_KEY2 = "docblocks:lastNewFileFormat";
5829
5983
  var MAX_REMEMBERED_WORKSPACES = 200;
@@ -5883,35 +6037,6 @@ function resolveShellTheme({
5883
6037
  return osTheme;
5884
6038
  }
5885
6039
 
5886
- // src/DocBlocksShell/issue-report.ts
5887
- var NEW_ISSUE_URL = "https://github.com/bendyline/docblocks/issues/new";
5888
- var VERSION_VALUE_LIMIT = 128;
5889
- var USER_AGENT_VALUE_LIMIT = 512;
5890
- function normalizeEnvironmentValue(value, fallback, limit) {
5891
- const normalized = value.replace(/[\r\n]+/g, " ").trim().slice(0, limit);
5892
- return normalized || fallback;
5893
- }
5894
- function buildIssueReportUrl(environment) {
5895
- const body = [
5896
- "## Description",
5897
- "",
5898
- "<!-- What happened, and what did you expect? -->",
5899
- "",
5900
- "## Environment",
5901
- "",
5902
- `- Date: ${environment.reportedAt.toISOString().slice(0, 10)}`,
5903
- `- DocBlocks: ${normalizeEnvironmentValue(environment.version, "unknown", VERSION_VALUE_LIMIT)}`,
5904
- `- User agent: ${normalizeEnvironmentValue(
5905
- environment.userAgent,
5906
- "unavailable",
5907
- USER_AGENT_VALUE_LIMIT
5908
- )}`
5909
- ].join("\n");
5910
- const url = new URL(NEW_ISSUE_URL);
5911
- url.searchParams.set("body", body);
5912
- return url.href;
5913
- }
5914
-
5915
6040
  // src/DocBlocksShell/last-state.ts
5916
6041
  import { tryParseWorkspacePath as tryParseWorkspacePath2 } from "@bendyline/docblocks/filesystem";
5917
6042
  var LAST_STATE_KEY = "docblocks:lastState";
@@ -6317,11 +6442,11 @@ function useInterfaceFontAttribute(preference) {
6317
6442
  useEffect24(() => {
6318
6443
  if (typeof document === "undefined") return;
6319
6444
  const root = document.documentElement;
6320
- if (preference !== "fixed") {
6445
+ if (preference !== "system") {
6321
6446
  root.removeAttribute(INTERFACE_FONT_ATTRIBUTE);
6322
6447
  return;
6323
6448
  }
6324
- root.setAttribute(INTERFACE_FONT_ATTRIBUTE, "fixed");
6449
+ root.setAttribute(INTERFACE_FONT_ATTRIBUTE, "system");
6325
6450
  return () => root.removeAttribute(INTERFACE_FONT_ATTRIBUTE);
6326
6451
  }, [preference]);
6327
6452
  }
@@ -6510,7 +6635,7 @@ function useShellShortcuts(handlers, layoutMode) {
6510
6635
 
6511
6636
  // src/DocBlocksShell/UpdateAvailableNotice.tsx
6512
6637
  import { useState as useState21 } from "react";
6513
- import { Fragment as Fragment10, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
6638
+ import { Fragment as Fragment10, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
6514
6639
  var UPDATE_PROMPT_ID = "db-update-available-prompt";
6515
6640
  function UpdateAvailableNotice({
6516
6641
  available,
@@ -6522,8 +6647,8 @@ function UpdateAvailableNotice({
6522
6647
  const [applying, setApplying] = useState21(false);
6523
6648
  if (!available || !onApplyUpdate) return null;
6524
6649
  const promptVisible = promptOpen && !blocked;
6525
- return /* @__PURE__ */ jsxs13(Fragment10, { children: [
6526
- /* @__PURE__ */ jsx15(
6650
+ return /* @__PURE__ */ jsxs14(Fragment10, { children: [
6651
+ /* @__PURE__ */ jsx16(
6527
6652
  "button",
6528
6653
  {
6529
6654
  type: "button",
@@ -6537,16 +6662,16 @@ function UpdateAvailableNotice({
6537
6662
  children: "Update available"
6538
6663
  }
6539
6664
  ),
6540
- promptVisible && /* @__PURE__ */ jsxs13(
6665
+ promptVisible && /* @__PURE__ */ jsxs14(
6541
6666
  "div",
6542
6667
  {
6543
6668
  id: UPDATE_PROMPT_ID,
6544
6669
  className: `db-update-banner${statusBarVisible ? "" : " db-update-banner--floating"}`,
6545
6670
  role: "alert",
6546
6671
  children: [
6547
- /* @__PURE__ */ jsx15("span", { children: "A new version of DocBlocks is available. Reload to update the editor and site pages." }),
6548
- /* @__PURE__ */ jsxs13("div", { className: "db-update-banner-actions", children: [
6549
- /* @__PURE__ */ jsx15(
6672
+ /* @__PURE__ */ jsx16("span", { children: "A new version of DocBlocks is available. Reload to update the editor and site pages." }),
6673
+ /* @__PURE__ */ jsxs14("div", { className: "db-update-banner-actions", children: [
6674
+ /* @__PURE__ */ jsx16(
6550
6675
  "button",
6551
6676
  {
6552
6677
  type: "button",
@@ -6558,7 +6683,7 @@ function UpdateAvailableNotice({
6558
6683
  children: applying ? "Updating\u2026" : "Reload"
6559
6684
  }
6560
6685
  ),
6561
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => setPromptOpen(false), disabled: applying, children: "Later" })
6686
+ /* @__PURE__ */ jsx16("button", { type: "button", onClick: () => setPromptOpen(false), disabled: applying, children: "Later" })
6562
6687
  ] })
6563
6688
  ]
6564
6689
  }
@@ -6566,6 +6691,104 @@ function UpdateAvailableNotice({
6566
6691
  ] });
6567
6692
  }
6568
6693
 
6694
+ // src/DocBlocksShell/WelcomeScreen.tsx
6695
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
6696
+ var WELCOME_HEADLINE = "The Markdown editor that turns one file into anything.";
6697
+ 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.";
6698
+ var WELCOME_PRIVACY_NOTE = "No account, and your documents stay on this device.";
6699
+ var DOCBLOCKS_APPS_URL = "https://docblocks.com/desktop/";
6700
+ function WelcomeScreen({
6701
+ onCreateDocument,
6702
+ onTour,
6703
+ onDismiss,
6704
+ offerApps = false
6705
+ }) {
6706
+ return /* @__PURE__ */ jsxs15("section", { className: "db-welcome-gateway", "aria-labelledby": "db-welcome-gateway-title", children: [
6707
+ /* @__PURE__ */ jsx17(
6708
+ "button",
6709
+ {
6710
+ type: "button",
6711
+ className: "db-welcome-gateway-dismiss",
6712
+ onClick: onDismiss,
6713
+ "aria-label": "Dismiss welcome",
6714
+ title: "Dismiss",
6715
+ children: "\xD7"
6716
+ }
6717
+ ),
6718
+ /* @__PURE__ */ jsxs15("div", { className: "db-welcome-gateway-body", children: [
6719
+ /* @__PURE__ */ jsxs15("div", { className: "db-welcome-gateway-copy", children: [
6720
+ /* @__PURE__ */ jsx17("p", { className: "db-welcome-gateway-eyebrow", children: "Welcome to DocBlocks" }),
6721
+ /* @__PURE__ */ jsx17("h1", { id: "db-welcome-gateway-title", children: WELCOME_HEADLINE }),
6722
+ /* @__PURE__ */ jsx17("p", { children: WELCOME_SUMMARY }),
6723
+ /* @__PURE__ */ jsx17("p", { className: "db-welcome-gateway-note", children: WELCOME_PRIVACY_NOTE }),
6724
+ /* @__PURE__ */ jsxs15("div", { className: "db-welcome-gateway-actions", children: [
6725
+ /* @__PURE__ */ jsx17("button", { type: "button", className: "db-welcome-gateway-primary", onClick: onCreateDocument, children: "Create a document" }),
6726
+ /* @__PURE__ */ jsx17("button", { type: "button", className: "db-welcome-gateway-cta", onClick: onTour, children: "Tour the welcome document" }),
6727
+ offerApps && /* @__PURE__ */ jsx17(
6728
+ "a",
6729
+ {
6730
+ className: "db-welcome-gateway-apps",
6731
+ href: DOCBLOCKS_APPS_URL,
6732
+ target: "_blank",
6733
+ rel: "noopener noreferrer",
6734
+ children: "Check out the DocBlocks apps"
6735
+ }
6736
+ )
6737
+ ] })
6738
+ ] }),
6739
+ /* @__PURE__ */ jsx17(WelcomeLoop, {})
6740
+ ] })
6741
+ ] });
6742
+ }
6743
+ function WelcomeLoop() {
6744
+ return /* @__PURE__ */ jsxs15("div", { className: "db-welcome-loop", "aria-hidden": "true", children: [
6745
+ /* @__PURE__ */ jsxs15("div", { className: "db-welcome-loop-source", children: [
6746
+ /* @__PURE__ */ jsx17("span", { className: "db-welcome-loop-file", children: "Lisbon.md" }),
6747
+ /* @__PURE__ */ jsxs15("code", { children: [
6748
+ /* @__PURE__ */ jsx17("span", { className: "db-welcome-loop-mark", children: "# " }),
6749
+ "Lisbon in three days",
6750
+ "\n",
6751
+ "Trams, tiles, and pastries.",
6752
+ "\n\n",
6753
+ /* @__PURE__ */ jsx17("span", { className: "db-welcome-loop-mark", children: "## " }),
6754
+ "Day one",
6755
+ "\n",
6756
+ /* @__PURE__ */ jsx17("span", { className: "db-welcome-loop-mark", children: "- " }),
6757
+ "Ride Tram 28",
6758
+ "\n",
6759
+ /* @__PURE__ */ jsx17("span", { className: "db-welcome-loop-mark", children: "- " }),
6760
+ "Sunset at Gra\xE7a"
6761
+ ] })
6762
+ ] }),
6763
+ /* @__PURE__ */ jsx17("div", { className: "db-welcome-loop-arrow", children: "\u2192" }),
6764
+ /* @__PURE__ */ jsxs15("div", { className: "db-welcome-loop-stage", children: [
6765
+ /* @__PURE__ */ jsxs15("div", { className: "db-welcome-loop-frame db-welcome-loop-frame--page", children: [
6766
+ /* @__PURE__ */ jsx17("strong", { children: "Lisbon in three days" }),
6767
+ /* @__PURE__ */ jsx17("span", { children: "Trams, tiles, and pastries." }),
6768
+ /* @__PURE__ */ jsx17("em", { children: "Day one" }),
6769
+ /* @__PURE__ */ jsx17("span", { children: "\u2022 Ride Tram 28" }),
6770
+ /* @__PURE__ */ jsx17("span", { children: "\u2022 Sunset at Gra\xE7a" })
6771
+ ] }),
6772
+ /* @__PURE__ */ jsxs15("div", { className: "db-welcome-loop-frame db-welcome-loop-frame--slide", children: [
6773
+ /* @__PURE__ */ jsx17("strong", { children: "Lisbon in three days" }),
6774
+ /* @__PURE__ */ jsx17("span", { children: "Trams, tiles, and pastries." })
6775
+ ] }),
6776
+ /* @__PURE__ */ jsxs15("div", { className: "db-welcome-loop-frame db-welcome-loop-frame--video", children: [
6777
+ /* @__PURE__ */ jsx17("em", { children: "Day one" }),
6778
+ /* @__PURE__ */ jsx17("span", { children: "\u2022 Ride Tram 28" }),
6779
+ /* @__PURE__ */ jsx17("span", { children: "\u2022 Sunset at Gra\xE7a" }),
6780
+ /* @__PURE__ */ jsx17("i", { className: "db-welcome-loop-play", children: "\u25B6" }),
6781
+ /* @__PURE__ */ jsx17("i", { className: "db-welcome-loop-progress" })
6782
+ ] })
6783
+ ] }),
6784
+ /* @__PURE__ */ jsxs15("ol", { className: "db-welcome-loop-labels", children: [
6785
+ /* @__PURE__ */ jsx17("li", { children: "PDF" }),
6786
+ /* @__PURE__ */ jsx17("li", { children: "Slides" }),
6787
+ /* @__PURE__ */ jsx17("li", { children: "Video" })
6788
+ ] })
6789
+ ] });
6790
+ }
6791
+
6569
6792
  // src/DocBlocksShell/useDocumentLinkProvider.ts
6570
6793
  import { useCallback as useCallback16 } from "react";
6571
6794
 
@@ -6940,7 +7163,15 @@ function createNativeFileActions(entry, workspaceId, host) {
6940
7163
 
6941
7164
  // src/DocBlocksShell/welcome-document.ts
6942
7165
  import { DEFAULT_WORKSPACE_ID } from "@bendyline/docblocks/workspace";
6943
- var WELCOME_DOCUMENT_PATH = "/aboutDocBlocks.md";
7166
+ var WELCOME_DOCUMENT_PATH = "/Welcome.md";
7167
+ var WELCOME_DOCUMENT_NAMES = /* @__PURE__ */ new Set([
7168
+ "welcome.md",
7169
+ // Seeded as `aboutDocBlocks.md` through 2.7 (`aboutDocblocks.md` before that).
7170
+ "aboutdocblocks.md"
7171
+ ]);
7172
+ function isWelcomeDocumentPath(path) {
7173
+ return WELCOME_DOCUMENT_NAMES.has(path.replace(/^\//, "").toLowerCase());
7174
+ }
6944
7175
  function isAppDefaultWorkspace(workspaceId, hostDefaultWorkspaceIds) {
6945
7176
  return hostDefaultWorkspaceIds ? hostDefaultWorkspaceIds.has(workspaceId) : workspaceId === DEFAULT_WORKSPACE_ID;
6946
7177
  }
@@ -6950,126 +7181,57 @@ var WELCOME_DOCUMENT_CONTENT = [
6950
7181
  "squisq-cover-slide: false",
6951
7182
  "---",
6952
7183
  "",
6953
- '# DocBlocks {[title subtitle="Local-first writing for pages, documents, slideshows, and video"]}',
6954
- "",
6955
- "Write in plain Markdown. Shape it visually. Keep it portable.",
6956
- "",
6957
- "## A document editor that never asks you to stop owning the document {[factCard]}",
6958
- "",
6959
- "DocBlocks pairs a friendly visual writing surface with the durable source format you already know. There is no account to create, no proprietary document to rescue later, and no requirement to send your work to a hosted editor.",
6960
- "",
6961
- "## Start with three small moves {[list]}",
6962
- "",
6963
- "1. Choose **New file** in the file pane and give your document a name, such as `my-first-document.md`. On a small screen, open the file pane first.",
6964
- "2. Add a heading and a few sentences in **Write**, then switch to **Source** to see the Markdown behind them. Both views edit the same document.",
6965
- "3. Try a Document, Page, Slideshow, or Video preview, then open **Export and share** to make a PDF, Word document, or another supported file.",
7184
+ '# Welcome to DocBlocks {[title subtitle="Write once. Share it as a document, a deck, or a video."]}',
6966
7185
  "",
6967
- '## Choose your DocBlocks app {[twoColumn header="The same Markdown, wherever you work" left="Web|Start in a browser, with no account. Install the web app when your browser offers it." right="Desktop|Download for macOS (Apple silicon), Windows, or Linux. Work directly in your folders."]}',
7186
+ "This is an ordinary document, so go ahead and change it. Click anywhere and type; DocBlocks saves as you go.",
6968
7187
  "",
6969
- "Choose the **Web app** to start writing in your browser, or **Desktop** for everyday work in local folders on macOS (Apple silicon), Windows, and Linux. Use **VS Code** for documents beside your code, and the **CLI and MCP server** for automation. The links at the end of this guide lead to downloads and setup instructions.",
7188
+ "## Write the way you already do {[list]}",
6970
7189
  "",
6971
- "## Get started on desktop {[list]}",
7190
+ "- Type to add text, and use the toolbar for headings, lists, and bold or italic text.",
7191
+ "- Choose **Insert** in the toolbar to add a table, a checklist, a chart, a diagram, or a picture.",
7192
+ "- Choose **Source** to see the Markdown text behind this page. Both views edit the same document.",
6972
7193
  "",
6973
- "- Download the installer for your computer from the **Desktop app** link at the end of this guide. macOS builds support Apple silicon.",
6974
- "- Launch DocBlocks and choose **Open a folder** to work in a folder you own. Your Markdown and media stay in that folder.",
6975
- "- Open an existing document or create a new file. Edits save automatically; check any save or conflict message before closing.",
6976
- "- Use the same Write, Source, preview, and export workflow as the web app, with native menus and file opening.",
6977
- "",
6978
- "## Use the web app on this device {[list]}",
6979
- "",
6980
- "- Open DocBlocks in your browser and start in a browser workspace. In supported browsers, you can also open a local folder.",
6981
- "- Choose **Install DocBlocks\u2026** in the app menu when offered. The installed web app keeps using the same browser storage.",
6982
- "- Once the app has finished downloading for offline use, you can keep editing without a connection.",
6983
- "- Use **Download all workspaces** in the app menu to keep a backup before clearing browser data or moving to a new device.",
6984
- "",
6985
- "## Work inside VS Code {[content]}",
6986
- "",
6987
- "Install the DocBlocks extension, then open a `.md` file in your project. If it opens as plain text, right-click it and choose **Open in DocBlocks**. VS Code supplies the file explorer, tabs, saving, and source control; DocBlocks supplies the visual editor, Markdown source, previews, and export. Follow the extension guide below to get started.",
6988
- "",
6989
- "## On a phone or tablet {[content]}",
6990
- "",
6991
- "Use the web app on your phone or tablet today. Native apps for iPhone, iPad, and Android are in preview, with store distribution pending. Preview builds offer an **On this device** workspace, picked folders, and system sharing. Keep an exported copy of important work: uninstalling a native app removes its private device workspace.",
6992
- "",
6993
- '## Automate with the CLI and MCP {[twoColumn header="For repeatable document work" left="CLI|Install @bendyline/docblocks-cli with npm, then run docblocks --help. Build, preview, and convert files from your terminal." right="MCP|Connect the local server to an agent. Convert and preview documents, then deliberately save the resulting artifacts."]}',
6994
- "",
6995
- "With a supported version of `Node.js` installed, run `npm install -g @bendyline/docblocks-cli`, then `docblocks --help`. The CLI builds, previews, and converts files from your terminal. Its local MCP server gives agents document tools with explicitly allowed file access. Follow the CLI and MCP guide below for requirements and configuration.",
6996
- "",
6997
- "## One source, four ways to publish {[diagram]}",
7194
+ "## One document, many ways to share it {[diagram]}",
6998
7195
  "",
6999
7196
  "```diagram",
7000
- "+------------+",
7001
- "| Markdown |",
7002
- "+-----+------+",
7003
- " |",
7004
- " +---+------+------------+-----------+",
7005
- " | | | |",
7006
- " v v v v",
7007
- "+-------+ +---------+ +------------+ +-------+",
7008
- "| Pages | |Documents| | Slideshows | | Video |",
7009
- "+-------+ +---------+ +------------+ +-------+",
7197
+ " +-----------------+",
7198
+ " | Your document |",
7199
+ " +--------+--------+",
7200
+ " |",
7201
+ " +-----------+------+-----+------------+",
7202
+ " | | | |",
7203
+ " v v v v",
7204
+ "+-------+ +--------+ +----------+ +---------+",
7205
+ "| PDF | | Word | | Slides | | Video |",
7206
+ "+-------+ +--------+ +----------+ +---------+",
7010
7207
  "```",
7011
7208
  "",
7012
- "## Write visually, then look under the hood whenever you like {[content]}",
7013
- "",
7014
- "Use the rich editor for headings, lists, tables, links, images, media, and everyday formatting. Switch to raw Markdown for exact control. Add themes, transform styles, and squiggly-square section annotations when a passage deserves its own visual treatment. The readable `.md` source stays at the center of the workflow.",
7015
- "",
7016
- "## Preview the finished idea before you export it {[list]}",
7017
- "",
7018
- "- **Document** \u2014 Read the work as a polished, continuous document.",
7019
- "- **Page** \u2014 See how it behaves as a web page.",
7020
- "- **Slideshow** \u2014 Step through headings as designed presentation blocks.",
7021
- "- **Video** \u2014 Rehearse timing, motion, narration, and media in a player-ready view.",
7022
- "",
7023
- "## Try the optional desktop tools {[list]}",
7024
- "",
7025
- "- **AI assistance** can help rewrite, review, and illustrate a document. In **Settings \u2192 AI assistance**, turn on **Use AI features** and choose an available model. AI is off by default; model downloads start only when you request them.",
7026
- "- **Dictation and read aloud** run on your computer. Where available, open **Settings \u2192 Speech** to download a dictation model or narration voices, then use the microphone or read-aloud controls.",
7027
- "- These tools depend on the app, device, and installed models. Writing, previewing, and exporting work without setting them up.",
7209
+ "## Present it or send it {[content]}",
7028
7210
  "",
7029
- "## The quiet conveniences are there, too {[list]}",
7211
+ "Each heading starts a new slide, so this document is already a slideshow. Choose **Slideshow** at the top to see it, or **Export** to save it as a PDF, a Word document, a PowerPoint deck, an e-book, a web page, or a video.",
7030
7212
  "",
7031
- "- **Workspaces and file navigation** keep related documents organized without hiding their source.",
7032
- "- **Automatic saving** protects the active revision while still surfacing conflicts or save errors.",
7033
- "- **Optional version history** keeps plain sibling revisions when you want a trail of changes.",
7034
- "- **Copy-by-link sharing** puts a Markdown copy in a link that opens straight into a Document, Page, Slideshow, or Video view.",
7035
- "- **Offline-ready, local-first storage** keeps browser work on this device and native work inside folders you choose.",
7213
+ "## Your documents stay yours {[factCard]}",
7036
7214
  "",
7037
- "## Export without rebuilding the document {[list]}",
7215
+ "There is no account to create. Your documents stay on this device as plain text files that other apps can open too. Choose **Back up** at the bottom of the file list to keep a copy somewhere safe.",
7038
7216
  "",
7039
- "- Create **Word documents and PDFs** for review, printing, and sharing with a fixed page layout.",
7040
- "- Create **PowerPoint decks** from the same annotated sections you preview as a slideshow.",
7041
- "- Publish **HTML pages, packaged HTML, and EPUB e-books**.",
7042
- "- Keep portable **Markdown or DBK bundles** with their media assets.",
7043
- "- Use the linked CLI registry for **spreadsheets, MP4 video, animated GIF, batch conversion, and more**.",
7217
+ "## Make your own {[list]}",
7044
7218
  "",
7045
- "## Local-first is concrete, not decorative {[quote]}",
7219
+ "1. Choose **New File** above the file list and give it a name.",
7220
+ "2. Write a heading and a few sentences.",
7221
+ "3. Choose **Slideshow** to present it, or **Export** to share it.",
7046
7222
  "",
7047
- "> Your browser workspace stays on this device. Native folders are opened only when you choose them. Your Markdown remains useful in DocBlocks, Git, a terminal, another editor, or an AI-assisted workflow.",
7223
+ "## Go further {[list]}",
7048
7224
  "",
7049
- "## Agents get document tools, not a blank check {[factCard]}",
7050
- "",
7051
- "The local MCP server converts plain text or Markdown directly and can optionally inspect, preview, or compare documents. Results remain temporary session artifacts until they are deliberately saved, and filesystem access begins with explicit roots rather than assumed authority.",
7052
- "",
7053
- "## Take your documents to another app {[content]}",
7054
- "",
7055
- "DocBlocks does not automatically sync workspaces between apps or devices. Open the same folder in Desktop or VS Code, or export Markdown and its media to move your work. A DBK bundle keeps documents and media together for another DocBlocks app. A share link contains a snapshot; later edits do not update that copy.",
7056
- "",
7057
- "## Explore DocBlocks {[list]}",
7058
- "",
7059
- "- [Desktop app](https://docblocks.com/desktop/) \u2014 downloads and first steps for macOS (Apple silicon), Windows, and Linux.",
7060
- "- [Web app](https://docblocks.com/web/) \u2014 browser storage, installation, and offline use.",
7061
- "- [Mobile preview](https://docblocks.com/docs/#mobile-preview) \u2014 iPhone, iPad, and Android status and build guide.",
7062
- "- [VS Code extension](https://docblocks.com/vscode/) \u2014 rich Markdown editing inside a workspace.",
7063
- "- [CLI and MCP server](https://docblocks.com/cli/) \u2014 conversion, rendering, and agent workflows.",
7064
- "- [Supported formats](https://docblocks.com/formats/) \u2014 current import and export directions.",
7065
- "- [Documentation](https://docblocks.com/docs/) \u2014 compare the apps and follow the getting-started guides.",
7225
+ "- [Get the desktop app](https://docblocks.com/desktop/) to work in folders on your computer.",
7226
+ "- [Add DocBlocks to VS Code](https://docblocks.com/vscode/) to edit documents beside your code.",
7227
+ "- [Read the guides](https://docblocks.com/docs/) for everything else.",
7066
7228
  // End with a newline, as the Write view saves every document. Without it,
7067
7229
  // merely opening the welcome document in Write rewrote the file.
7068
7230
  ""
7069
7231
  ].join("\n");
7070
7232
 
7071
7233
  // src/DocBlocksShell/DocBlocksShell.tsx
7072
- import { Fragment as Fragment11, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
7234
+ import { Fragment as Fragment11, jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
7073
7235
  var editorShellModulePromise = null;
7074
7236
  function loadEditorShell() {
7075
7237
  editorShellModulePromise ?? (editorShellModulePromise = (async () => {
@@ -7086,8 +7248,11 @@ var GitUI = lazy2(() => import("./GitUI-RCWUZVS6.js").then((m) => ({ default: m.
7086
7248
  var QuickOpenDialog = lazy2(
7087
7249
  () => import("./QuickOpenDialog-2KK4SEBU.js").then((m) => ({ default: m.QuickOpenDialog }))
7088
7250
  );
7251
+ var KeyboardShortcutsDialog = lazy2(
7252
+ () => import("./KeyboardShortcutsDialog-G5OBDTNR.js").then((m) => ({ default: m.KeyboardShortcutsDialog }))
7253
+ );
7089
7254
  var WorkspaceSearchPanel = lazy2(
7090
- () => import("./WorkspaceSearchPanel-BKZJRPMY.js").then((m) => ({
7255
+ () => import("./WorkspaceSearchPanel-J6BKEZQJ.js").then((m) => ({
7091
7256
  default: m.WorkspaceSearchPanel
7092
7257
  }))
7093
7258
  );
@@ -7098,43 +7263,44 @@ var GitToolbarControl = lazy2(
7098
7263
  () => import("./GitToolbarControl-B7KG4MFP.js").then((m) => ({ default: m.GitToolbarControl }))
7099
7264
  );
7100
7265
  var AiToolbarControl = lazy2(
7101
- () => import("./AiEditorAssistant-GN2KXKZD.js").then((module) => ({
7266
+ () => import("./AiEditorAssistant-YLJ5OZK2.js").then((module) => ({
7102
7267
  default: module.AiToolbarControl
7103
7268
  }))
7104
7269
  );
7105
7270
  var PresentationMaker = lazy2(
7106
- () => import("./PresentationMaker-W2JIBHRN.js").then((module) => ({
7271
+ () => import("./PresentationMaker-P2JP6UUX.js").then((module) => ({
7107
7272
  default: module.PresentationMaker
7108
7273
  }))
7109
7274
  );
7110
7275
  var AiReviewPanel = lazy2(
7111
- () => import("./AiEditorAssistant-GN2KXKZD.js").then((module) => ({
7276
+ () => import("./AiEditorAssistant-YLJ5OZK2.js").then((module) => ({
7112
7277
  default: module.AiReviewPanel
7113
7278
  }))
7114
7279
  );
7115
7280
  var AiIllustratePanel = lazy2(
7116
- () => import("./AiDiagrams-LFV4YU6W.js").then((module) => ({
7281
+ () => import("./AiDiagrams-QE3LVYFK.js").then((module) => ({
7117
7282
  default: module.AiIllustratePanel
7118
7283
  }))
7119
7284
  );
7120
7285
  var TextFromNarration = lazy2(
7121
- () => import("./TextFromNarration-XYRAB6O2.js").then((module) => ({
7286
+ () => import("./TextFromNarration-NITJQ4IB.js").then((module) => ({
7122
7287
  default: module.TextFromNarration
7123
7288
  }))
7124
7289
  );
7125
7290
  var SpeechToolbarControl = lazy2(
7126
- () => import("./SpeechToolbarControl-OSQS7NVY.js").then((module) => ({
7291
+ () => import("./SpeechToolbarControl-CLU7RB2G.js").then((module) => ({
7127
7292
  default: module.SpeechToolbarControl
7128
7293
  }))
7129
7294
  );
7130
7295
  var SpeechMenuBridge = lazy2(
7131
- () => import("./SpeechToolbarControl-OSQS7NVY.js").then((module) => ({
7296
+ () => import("./SpeechToolbarControl-CLU7RB2G.js").then((module) => ({
7132
7297
  default: module.SpeechMenuBridge
7133
7298
  }))
7134
7299
  );
7135
7300
  var DOCBLOCKS_VIDEO_EXPORT_PALETTE = Object.freeze({
7136
7301
  overlay: "rgba(0, 0, 0, 0.72)",
7137
- surface: "var(--db-bg)",
7302
+ // A dialog floats over the chrome, so it takes the raised surface.
7303
+ surface: "var(--db-bg-raised)",
7138
7304
  control: "var(--db-bg-subtle)",
7139
7305
  border: "var(--db-border-strong)",
7140
7306
  text: "var(--db-text)",
@@ -7394,7 +7560,7 @@ async function createHostProviderFromWorkspace(ws) {
7394
7560
  var DESKTOP_TOOLBAR_WRAP_WIDTH = 900;
7395
7561
  var WEB_TOOLBAR_WRAP_WIDTH = 700;
7396
7562
  function FolderGlyph() {
7397
- return /* @__PURE__ */ jsx16(
7563
+ return /* @__PURE__ */ jsx18(
7398
7564
  "svg",
7399
7565
  {
7400
7566
  viewBox: "0 0 24 24",
@@ -7403,12 +7569,12 @@ function FolderGlyph() {
7403
7569
  strokeWidth: "1.5",
7404
7570
  strokeLinejoin: "round",
7405
7571
  "aria-hidden": "true",
7406
- children: /* @__PURE__ */ jsx16("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" })
7572
+ children: /* @__PURE__ */ jsx18("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" })
7407
7573
  }
7408
7574
  );
7409
7575
  }
7410
7576
  function FileGlyph() {
7411
- return /* @__PURE__ */ jsxs14(
7577
+ return /* @__PURE__ */ jsxs16(
7412
7578
  "svg",
7413
7579
  {
7414
7580
  viewBox: "0 0 24 24",
@@ -7418,14 +7584,14 @@ function FileGlyph() {
7418
7584
  strokeLinejoin: "round",
7419
7585
  "aria-hidden": "true",
7420
7586
  children: [
7421
- /* @__PURE__ */ jsx16("path", { d: "M6 3h8l5 5v12a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z" }),
7422
- /* @__PURE__ */ jsx16("path", { d: "M14 3v5h5" })
7587
+ /* @__PURE__ */ jsx18("path", { d: "M6 3h8l5 5v12a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z" }),
7588
+ /* @__PURE__ */ jsx18("path", { d: "M14 3v5h5" })
7423
7589
  ]
7424
7590
  }
7425
7591
  );
7426
7592
  }
7427
7593
  function CollapseSidebarGlyph() {
7428
- return /* @__PURE__ */ jsxs14(
7594
+ return /* @__PURE__ */ jsxs16(
7429
7595
  "svg",
7430
7596
  {
7431
7597
  viewBox: "0 0 64 64",
@@ -7436,9 +7602,9 @@ function CollapseSidebarGlyph() {
7436
7602
  strokeLinejoin: "round",
7437
7603
  "aria-hidden": "true",
7438
7604
  children: [
7439
- /* @__PURE__ */ jsx16("rect", { x: "7", y: "10", width: "50", height: "44", rx: "6" }),
7440
- /* @__PURE__ */ jsx16("path", { d: "M24 10v44" }),
7441
- /* @__PURE__ */ jsx16("path", { d: "m17 25-7 7 7 7" })
7605
+ /* @__PURE__ */ jsx18("rect", { x: "7", y: "10", width: "50", height: "44", rx: "6" }),
7606
+ /* @__PURE__ */ jsx18("path", { d: "M24 10v44" }),
7607
+ /* @__PURE__ */ jsx18("path", { d: "m17 25-7 7 7 7" })
7442
7608
  ]
7443
7609
  }
7444
7610
  );
@@ -7446,9 +7612,11 @@ function CollapseSidebarGlyph() {
7446
7612
  function DocBlocksShell({
7447
7613
  theme: hostTheme = "auto",
7448
7614
  logoUrl,
7615
+ logoDarkUrl,
7449
7616
  issueReportVersion,
7450
7617
  appBuildDate,
7451
7618
  ffmpegWasm,
7619
+ pdfWorkerSrc: pdfWorkerSrc2,
7452
7620
  calcEngineFactory,
7453
7621
  proofing,
7454
7622
  proofingDefaultEnabled,
@@ -7668,6 +7836,7 @@ function DocBlocksShell({
7668
7836
  );
7669
7837
  const [provider, setProvider] = useState23(null);
7670
7838
  const [workspaceStartupError, setWorkspaceStartupError] = useState23(null);
7839
+ const workspaceStarting = provider === null && workspaceStartupError === null;
7671
7840
  const [activeWorkspaceId, setActiveWorkspaceId] = useState23(null);
7672
7841
  const [defaultNewFileFormat, setDefaultNewFileFormat] = useState23(DEFAULT_NEW_FILE_FORMAT);
7673
7842
  useEffect29(() => {
@@ -7918,6 +8087,8 @@ function DocBlocksShell({
7918
8087
  const findShortcut = useMemo6(findShortcutLabel, []);
7919
8088
  const searchShortcut = useMemo6(() => shortcutLabel("workspace-search", isApplePlatform()), []);
7920
8089
  const [quickOpenOpen, setQuickOpenOpen] = useState23(false);
8090
+ const [shortcutsOpen, setShortcutsOpen] = useState23(false);
8091
+ const openKeyboardShortcuts = useCallback18(() => setShortcutsOpen(true), []);
7921
8092
  const [quickOpenFocusRequest, setQuickOpenFocusRequest] = useState23(0);
7922
8093
  const [sidebarView, setSidebarView] = useState23("files");
7923
8094
  const [searchMounted, setSearchMounted] = useState23(false);
@@ -8019,8 +8190,20 @@ function DocBlocksShell({
8019
8190
  } : null,
8020
8191
  [documentSnapshot.frozen, documentSnapshot.generation, documentSnapshot.targetKey]
8021
8192
  );
8022
- const [editorPresentationEpoch, setEditorPresentationEpoch] = useState23(0);
8023
- const editorKey = `${documentSnapshot.generation}:${editorPresentationEpoch}`;
8193
+ const [editorGeneration, setEditorGeneration] = useState23(documentSnapshot.generation);
8194
+ useEffect29(() => {
8195
+ const sync = () => setEditorGeneration(documentSession.getSnapshot().generation);
8196
+ const unsubscribe = documentSession.subscribe(sync);
8197
+ sync();
8198
+ return () => {
8199
+ unsubscribe();
8200
+ };
8201
+ }, [documentSession]);
8202
+ const editorGenerationSettled = editorGeneration === documentSnapshot.generation;
8203
+ useEffect29(() => {
8204
+ setOutsideInPdfWorker(pdfWorkerSrc2);
8205
+ }, [pdfWorkerSrc2]);
8206
+ const editorKey = String(editorGeneration);
8024
8207
  const editorPlaceholder = useMemo6(() => {
8025
8208
  void editorKey;
8026
8209
  return pickEmptyDocumentPrompt();
@@ -8040,6 +8223,15 @@ function DocBlocksShell({
8040
8223
  const [initialView, setInitialView] = useState23("wysiwyg");
8041
8224
  const [initialSharedMode, setInitialSharedMode] = useState23(null);
8042
8225
  const [showWelcomeGateway, setShowWelcomeGateway] = useState23(false);
8226
+ const welcomeScreenShown = showWelcomeGateway && !singlePane;
8227
+ const welcomeCoveredRef = useRef19(null);
8228
+ useInert(welcomeCoveredRef, welcomeScreenShown);
8229
+ const closeWelcomeGateway = useCallback18(() => {
8230
+ setShowWelcomeGateway((showing) => {
8231
+ if (showing) markWelcomeGatewayDismissed();
8232
+ return false;
8233
+ });
8234
+ }, []);
8043
8235
  const [aiPanel, setAiPanel] = useState23(null);
8044
8236
  const navigationRequestRef = useRef19(0);
8045
8237
  const workspaceAuthorityBarrier = useMemo6(() => new WorkspaceAuthorityBarrier(), []);
@@ -8230,6 +8422,8 @@ function DocBlocksShell({
8230
8422
  );
8231
8423
  const mediaContainerRef = useRef19(null);
8232
8424
  const [mediaProvider, setMediaProvider] = useState23(null);
8425
+ const [mediaProviderScope, setMediaProviderScope] = useState23(null);
8426
+ const mediaProviderCurrent = mediaProviderScope !== null && mediaProviderScope.provider === provider && mediaProviderScope.file === selectedFile && mediaProviderScope.outsideIn === selectedOutsideIn;
8233
8427
  const [mediaEpoch, setMediaEpoch] = useState23(0);
8234
8428
  const versionsContainerRef = useRef19(null);
8235
8429
  const [versionsContainer, setVersionsContainer] = useState23(null);
@@ -8346,6 +8540,7 @@ function DocBlocksShell({
8346
8540
  options.navigationRequestId,
8347
8541
  options.sharedMode ?? null
8348
8542
  ) !== null;
8543
+ if (opened) closeWelcomeGateway();
8349
8544
  return opened;
8350
8545
  } finally {
8351
8546
  if (!opened && getTransientWorkspace(options.id)?.provider === options.provider) {
@@ -8353,7 +8548,7 @@ function DocBlocksShell({
8353
8548
  }
8354
8549
  }
8355
8550
  },
8356
- [openFromIds]
8551
+ [openFromIds, closeWelcomeGateway]
8357
8552
  );
8358
8553
  const openSharedDocument = useCallback18(
8359
8554
  async (payload, navigationRequestId) => {
@@ -8395,18 +8590,18 @@ function DocBlocksShell({
8395
8590
  const entries = await readProviderDirectory2(fs, "/");
8396
8591
  if (!isCurrent()) return;
8397
8592
  const visibleEntries = filterVisibleFileEntries(entries);
8398
- if (visibleEntries.length === 1 && visibleEntries[0].kind === "file" && visibleEntries[0].path.replace(/^\//, "").toLowerCase() === "aboutdocblocks.md") {
8593
+ if (visibleEntries.length === 1 && visibleEntries[0].kind === "file" && isWelcomeDocumentPath(visibleEntries[0].path)) {
8399
8594
  const aboutPath = visibleEntries[0].path;
8400
8595
  const content = await readProviderText(fs, aboutPath);
8401
8596
  if (content !== null && isCurrent()) {
8402
8597
  await documentSession.transitionTo(createDocumentTarget(fs, fs.id, aboutPath), content);
8403
8598
  if (!isCurrent()) return;
8404
8599
  adoptRegularDocument(aboutPath);
8405
- setInitialView("preview");
8600
+ setInitialView("wysiwyg");
8406
8601
  setInitialSharedMode(null);
8407
8602
  setExplorerKey((k) => k + 1);
8408
8603
  pushHash(fs.id, aboutPath);
8409
- saveLastState({ workspaceId: fs.id, filePath: aboutPath, view: "preview" });
8604
+ saveLastState({ workspaceId: fs.id, filePath: aboutPath, view: "wysiwyg" });
8410
8605
  if (!isWelcomeGatewayDismissed()) setShowWelcomeGateway(true);
8411
8606
  }
8412
8607
  return;
@@ -8430,11 +8625,11 @@ function DocBlocksShell({
8430
8625
  );
8431
8626
  if (!isCurrent()) return;
8432
8627
  adoptRegularDocument(welcomePath);
8433
- setInitialView("preview");
8628
+ setInitialView("wysiwyg");
8434
8629
  setInitialSharedMode(null);
8435
8630
  setExplorerKey((k) => k + 1);
8436
8631
  pushHash(fs.id, welcomePath);
8437
- saveLastState({ workspaceId: fs.id, filePath: welcomePath, view: "preview" });
8632
+ saveLastState({ workspaceId: fs.id, filePath: welcomePath, view: "wysiwyg" });
8438
8633
  if (!isWelcomeGatewayDismissed()) setShowWelcomeGateway(true);
8439
8634
  },
8440
8635
  [adoptRegularDocument, createDocumentTarget, documentSession, pushHash]
@@ -8445,21 +8640,16 @@ function DocBlocksShell({
8445
8640
  startupOpenSharedDocumentRef.current = openSharedDocument;
8446
8641
  const startupSeedWelcomeFileRef = useRef19(seedWelcomeFile);
8447
8642
  startupSeedWelcomeFileRef.current = seedWelcomeFile;
8448
- const closeWelcomeGateway = useCallback18(() => {
8449
- setShowWelcomeGateway((showing) => {
8450
- if (showing) markWelcomeGatewayDismissed();
8451
- return false;
8452
- });
8453
- }, []);
8454
- const handleStartWriting = useCallback18(() => {
8643
+ const [focusAfterWelcome, setFocusAfterWelcome] = useState23(false);
8644
+ const handleTourWelcome = useCallback18(() => {
8455
8645
  closeWelcomeGateway();
8456
- setInitialView("wysiwyg");
8457
- setInitialSharedMode(null);
8458
- setEditorPresentationEpoch((epoch) => epoch + 1);
8459
- if (activeWorkspaceId && selectedFile) {
8460
- saveLastState({ workspaceId: activeWorkspaceId, filePath: selectedFile, view: "wysiwyg" });
8461
- }
8462
- }, [closeWelcomeGateway, activeWorkspaceId, selectedFile]);
8646
+ setFocusAfterWelcome(true);
8647
+ }, [closeWelcomeGateway]);
8648
+ useEffect29(() => {
8649
+ if (!focusAfterWelcome || welcomeScreenShown) return;
8650
+ setFocusAfterWelcome(false);
8651
+ editorAreaRef.current?.querySelector('[contenteditable="true"]')?.focus({ preventScroll: true });
8652
+ }, [focusAfterWelcome, welcomeScreenShown]);
8463
8653
  useEffect29(() => {
8464
8654
  const requestId = ++navigationRequestRef.current;
8465
8655
  let cancelled = false;
@@ -8824,14 +9014,16 @@ function DocBlocksShell({
8824
9014
  }).catch(() => {
8825
9015
  });
8826
9016
  }, [showBrowserStorageWarning, browserStoragePersistent, documentSnapshot.status]);
8827
- useEffect29(() => {
9017
+ useLayoutEffect4(() => {
8828
9018
  if (!provider || !selectedFile) {
8829
9019
  mediaContainerRef.current = null;
8830
9020
  versionsContainerRef.current = null;
8831
9021
  setMediaProvider(null);
9022
+ setMediaProviderScope(null);
8832
9023
  setVersionsContainer(null);
8833
9024
  return;
8834
9025
  }
9026
+ setMediaProviderScope({ provider, file: selectedFile, outsideIn: selectedOutsideIn });
8835
9027
  if (selectedOutsideIn) {
8836
9028
  const container2 = createOutsideInContentContainer(provider, selectedOutsideIn);
8837
9029
  const mp2 = createMediaProviderFromContainer(container2);
@@ -9688,15 +9880,22 @@ function DocBlocksShell({
9688
9880
  ...canBrowseWorkspace ? { "quick-open": openQuickOpen, "workspace-search": openWorkspaceSearch } : {},
9689
9881
  "new-document": () => void handleNewFile(),
9690
9882
  "new-folder": () => void handleNewFolder(),
9883
+ shortcuts: openKeyboardShortcuts,
9691
9884
  "toggle-sidebar": () => {
9885
+ if (canRestoreSplitView) {
9886
+ updateSidebarPreference("pinned");
9887
+ return;
9888
+ }
9692
9889
  if (singlePane) {
9693
9890
  setMobileShowEditor((showingEditor) => !showingEditor);
9694
9891
  return;
9695
9892
  }
9696
- updateSidebarPreference(sidebarPreference === "collapsed" ? "pinned" : "collapsed");
9893
+ updateSidebarPreference("collapsed");
9894
+ setMobileShowEditor(true);
9697
9895
  },
9698
9896
  "focus-files": () => {
9699
9897
  if (singlePane) setMobileShowEditor(false);
9898
+ setSidebarView("files");
9700
9899
  window.requestAnimationFrame(() => {
9701
9900
  const tree = document.querySelector(".db-tree");
9702
9901
  const target = tree?.querySelector('.db-tree-row[tabindex="0"]') ?? tree?.querySelector(".db-tree-row");
@@ -9723,9 +9922,10 @@ function DocBlocksShell({
9723
9922
  saveActiveDocument,
9724
9923
  handleNewFile,
9725
9924
  handleNewFolder,
9925
+ openKeyboardShortcuts,
9726
9926
  singlePane,
9727
9927
  mobileShowEditor,
9728
- sidebarPreference,
9928
+ canRestoreSplitView,
9729
9929
  updateSidebarPreference
9730
9930
  ]
9731
9931
  );
@@ -10062,24 +10262,12 @@ function DocBlocksShell({
10062
10262
  }
10063
10263
  if (target.kind === "fragment") return false;
10064
10264
  if (target.kind === "external") {
10065
- const shell = maybeGetDocBlocksHost4()?.shell;
10066
- if (hostSupports2("externalNavigation") && shell?.openExternal) {
10067
- void shell.openExternal(target.url).catch((error) => {
10068
- showToast(
10069
- "error",
10070
- error instanceof Error ? error.message : "Could not open the external link."
10071
- );
10072
- });
10073
- } else if (typeof window !== "undefined") {
10074
- try {
10075
- window.open(target.url, "_blank", "noopener,noreferrer");
10076
- } catch (error) {
10077
- showToast(
10078
- "error",
10079
- error instanceof Error ? error.message : "Could not open the external link."
10080
- );
10081
- }
10082
- }
10265
+ void openExternalUrl(target.url).catch((error) => {
10266
+ showToast(
10267
+ "error",
10268
+ error instanceof Error ? error.message : "Could not open the external link."
10269
+ );
10270
+ });
10083
10271
  return true;
10084
10272
  }
10085
10273
  void (async () => {
@@ -10602,6 +10790,7 @@ function DocBlocksShell({
10602
10790
  if (!opened && requestId === navigationRequestRef.current) {
10603
10791
  throw new Error("The requested workspace file is no longer available.");
10604
10792
  }
10793
+ if (opened) closeWelcomeGateway();
10605
10794
  return opened;
10606
10795
  }
10607
10796
  );
@@ -10613,7 +10802,7 @@ function DocBlocksShell({
10613
10802
  );
10614
10803
  });
10615
10804
  });
10616
- }, [openFromIds, openTransient, workspaceAuthorityBarrier, showToast]);
10805
+ }, [openFromIds, openTransient, workspaceAuthorityBarrier, showToast, closeWelcomeGateway]);
10617
10806
  const openTransientFromHandle = useCallback18(
10618
10807
  async (handle) => {
10619
10808
  const name = handle.name;
@@ -10759,8 +10948,7 @@ function DocBlocksShell({
10759
10948
  const url = URL.createObjectURL(blob);
10760
10949
  const a = document.createElement("a");
10761
10950
  a.href = url;
10762
- const stamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
10763
- a.download = `docblocks-workspaces-${stamp}.zip`;
10951
+ a.download = `docblocks-workspaces-${localDateStamp(/* @__PURE__ */ new Date())}.zip`;
10764
10952
  a.click();
10765
10953
  URL.revokeObjectURL(url);
10766
10954
  if (skipped.length > 0) {
@@ -10780,7 +10968,7 @@ function DocBlocksShell({
10780
10968
  if (!storage || typeof storage.persist !== "function") {
10781
10969
  await acknowledge({
10782
10970
  title: "Persistent storage unavailable",
10783
- message: "This browser does not support persistent storage requests. Please back up browser docs frequently."
10971
+ message: "This browser does not support persistent storage requests. Use Back up all workspaces regularly."
10784
10972
  });
10785
10973
  return;
10786
10974
  }
@@ -10796,18 +10984,18 @@ function DocBlocksShell({
10796
10984
  setBrowserStoragePersistent(true);
10797
10985
  await acknowledge({
10798
10986
  title: "Storage will be kept for longer",
10799
- message: "This browser will try to keep DocBlocks data for longer. Please still back up browser docs frequently."
10987
+ message: "This browser will try to keep DocBlocks data for longer. Keep using Back up all workspaces regularly."
10800
10988
  });
10801
10989
  } else {
10802
10990
  await acknowledge({
10803
10991
  title: "Storage request declined",
10804
- message: "The browser did not grant permanent storage for DocBlocks. Please try again in a day or two. Meanwhile, please back up browser documents frequently."
10992
+ message: "The browser did not grant permanent storage for DocBlocks. Please try again in a day or two. Meanwhile, use Back up all workspaces regularly."
10805
10993
  });
10806
10994
  }
10807
10995
  } catch {
10808
10996
  await acknowledge({
10809
10997
  title: "Storage request failed",
10810
- message: "DocBlocks could not request persistent browser storage. Please back up browser docs frequently."
10998
+ message: "DocBlocks could not request persistent browser storage. Use Back up all workspaces regularly."
10811
10999
  });
10812
11000
  }
10813
11001
  }, [acknowledge, showToast]);
@@ -10917,7 +11105,7 @@ function DocBlocksShell({
10917
11105
  transitionAwayFromDocument
10918
11106
  ]
10919
11107
  );
10920
- return /* @__PURE__ */ jsx16(
11108
+ return /* @__PURE__ */ jsx18(
10921
11109
  "div",
10922
11110
  {
10923
11111
  ref: shellRef,
@@ -10926,10 +11114,10 @@ function DocBlocksShell({
10926
11114
  "data-accent": accentColor,
10927
11115
  "data-interface-font": interfaceFont === "fixed" ? "fixed" : void 0,
10928
11116
  "data-document-status": documentSnapshot.status,
10929
- children: /* @__PURE__ */ jsxs14(GitContext.Provider, { value: git, children: [
11117
+ children: /* @__PURE__ */ jsxs16(GitContext.Provider, { value: git, children: [
10930
11118
  promptDialog,
10931
11119
  confirmDialog,
10932
- quickOpenOpen && activeWorkspaceId && /* @__PURE__ */ jsx16(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx16(
11120
+ quickOpenOpen && activeWorkspaceId && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(
10933
11121
  QuickOpenDialog,
10934
11122
  {
10935
11123
  index: workspaceIndex.index,
@@ -10943,7 +11131,8 @@ function DocBlocksShell({
10943
11131
  onClose: () => setQuickOpenOpen(false)
10944
11132
  }
10945
11133
  ) }),
10946
- newDocumentDialogOpen && /* @__PURE__ */ jsx16(
11134
+ shortcutsOpen && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(KeyboardShortcutsDialog, { onClose: () => setShortcutsOpen(false) }) }),
11135
+ newDocumentDialogOpen && /* @__PURE__ */ jsx18(
10947
11136
  NewDocumentDialog,
10948
11137
  {
10949
11138
  initialFormat: defaultNewFileFormat,
@@ -10953,8 +11142,8 @@ function DocBlocksShell({
10953
11142
  }
10954
11143
  }
10955
11144
  ),
10956
- workspaceStartupError && /* @__PURE__ */ jsx16("div", { className: "db-save-toast db-save-toast--error", role: "alert", "aria-live": "assertive", children: workspaceStartupError }),
10957
- saveToast && /* @__PURE__ */ jsx16(
11145
+ workspaceStartupError && /* @__PURE__ */ jsx18("div", { className: "db-save-toast db-save-toast--error", role: "alert", "aria-live": "assertive", children: workspaceStartupError }),
11146
+ saveToast && /* @__PURE__ */ jsx18(
10958
11147
  "div",
10959
11148
  {
10960
11149
  className: "db-save-toast db-save-toast--" + saveToast.kind,
@@ -10963,12 +11152,12 @@ function DocBlocksShell({
10963
11152
  children: saveToast.message
10964
11153
  }
10965
11154
  ),
10966
- offlineReadyToast && !saveToast && /* @__PURE__ */ jsx16("div", { className: "db-save-toast db-save-toast--success", role: "status", "aria-live": "polite", children: "DocBlocks is ready to work offline." }),
10967
- documentSnapshot.conflict && /* @__PURE__ */ jsxs14("div", { className: "db-document-conflict", role: "alert", children: [
10968
- /* @__PURE__ */ jsx16("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." }),
10969
- /* @__PURE__ */ jsx16("div", { className: "db-document-conflict-actions", children: /* @__PURE__ */ jsx16("button", { type: "button", onClick: () => setShowConflictComparison(true), children: "Compare versions" }) })
11155
+ offlineReadyToast && !saveToast && /* @__PURE__ */ jsx18("div", { className: "db-save-toast db-save-toast--success", role: "status", "aria-live": "polite", children: "DocBlocks is ready to work offline." }),
11156
+ documentSnapshot.conflict && /* @__PURE__ */ jsxs16("div", { className: "db-document-conflict", role: "alert", children: [
11157
+ /* @__PURE__ */ jsx18("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." }),
11158
+ /* @__PURE__ */ jsx18("div", { className: "db-document-conflict-actions", children: /* @__PURE__ */ jsx18("button", { type: "button", onClick: () => setShowConflictComparison(true), children: "Compare versions" }) })
10970
11159
  ] }),
10971
- documentSnapshot.conflict && showConflictComparison && /* @__PURE__ */ jsx16(Suspense2, { fallback: /* @__PURE__ */ jsx16("div", { role: "status", children: "Loading version comparison\u2026" }), children: /* @__PURE__ */ jsx16(
11160
+ documentSnapshot.conflict && showConflictComparison && /* @__PURE__ */ jsx18(Suspense2, { fallback: /* @__PURE__ */ jsx18("div", { role: "status", children: "Loading version comparison\u2026" }), children: /* @__PURE__ */ jsx18(
10972
11161
  DocumentConflictDialog,
10973
11162
  {
10974
11163
  conflict: documentSnapshot.conflict,
@@ -10978,14 +11167,14 @@ function DocBlocksShell({
10978
11167
  onClose: () => setShowConflictComparison(false)
10979
11168
  }
10980
11169
  ) }),
10981
- storageFull && !documentSnapshot.conflict && /* @__PURE__ */ jsxs14("div", { className: "db-storage-full-banner", role: "alert", children: [
10982
- /* @__PURE__ */ jsx16("span", { children: "Browser storage is full -- changes can\u2019t be saved. Free up space or back up your work now." }),
10983
- /* @__PURE__ */ jsxs14("div", { className: "db-storage-full-banner-actions", children: [
10984
- /* @__PURE__ */ jsx16("button", { type: "button", onClick: () => void handleDownloadAllWorkspaces(), children: "Download all workspaces" }),
10985
- /* @__PURE__ */ jsx16("button", { type: "button", onClick: () => setStorageFull(false), children: "Dismiss" })
11170
+ storageFull && !documentSnapshot.conflict && /* @__PURE__ */ jsxs16("div", { className: "db-storage-full-banner", role: "alert", children: [
11171
+ /* @__PURE__ */ jsx18("span", { children: "Browser storage is full -- changes can\u2019t be saved. Free up space or back up your work now." }),
11172
+ /* @__PURE__ */ jsxs16("div", { className: "db-storage-full-banner-actions", children: [
11173
+ /* @__PURE__ */ jsx18("button", { type: "button", onClick: () => void handleDownloadAllWorkspaces(), children: "Back up all workspaces" }),
11174
+ /* @__PURE__ */ jsx18("button", { type: "button", onClick: () => setStorageFull(false), children: "Dismiss" })
10986
11175
  ] })
10987
11176
  ] }),
10988
- workspaceSettingsOpen && activeWorkspaceDescriptor && /* @__PURE__ */ jsx16(
11177
+ workspaceSettingsOpen && activeWorkspaceDescriptor && /* @__PURE__ */ jsx18(
10989
11178
  WorkspaceSettingsDialog,
10990
11179
  {
10991
11180
  workspace: activeWorkspaceDescriptor,
@@ -10998,8 +11187,8 @@ function DocBlocksShell({
10998
11187
  onClose: () => setWorkspaceSettingsOpen(false)
10999
11188
  }
11000
11189
  ),
11001
- /* @__PURE__ */ jsxs14("div", { className: "db-shell-panes", ref: panesRef, children: [
11002
- /* @__PURE__ */ jsxs14(
11190
+ /* @__PURE__ */ jsxs16("div", { className: "db-shell-panes", ref: panesRef, children: [
11191
+ /* @__PURE__ */ jsxs16(
11003
11192
  "aside",
11004
11193
  {
11005
11194
  ref: sidebarRef,
@@ -11007,11 +11196,12 @@ function DocBlocksShell({
11007
11196
  "aria-label": "Workspace and files",
11008
11197
  style: singlePane ? void 0 : { width: `${sidebarWidth}px` },
11009
11198
  children: [
11010
- /* @__PURE__ */ jsxs14("div", { className: "db-shell-sidebar-header", children: [
11011
- /* @__PURE__ */ jsx16(
11199
+ /* @__PURE__ */ jsxs16("div", { className: "db-shell-sidebar-header", children: [
11200
+ /* @__PURE__ */ jsx18(
11012
11201
  AppMenu,
11013
11202
  {
11014
11203
  logoUrl,
11204
+ logoDarkUrl,
11015
11205
  themePreference,
11016
11206
  onThemeChange: handleThemeChange,
11017
11207
  accentColor,
@@ -11029,6 +11219,7 @@ function DocBlocksShell({
11029
11219
  onVersioningPreferenceChange: handleVersioningPreferenceChange,
11030
11220
  onOpenWorkspaceSettings: activeWorkspaceDescriptor ? handleOpenWorkspaceSettings : void 0,
11031
11221
  onDownloadAllWorkspaces: handleDownloadAllWorkspaces,
11222
+ onShowKeyboardShortcuts: singlePane ? void 0 : openKeyboardShortcuts,
11032
11223
  onKeepBrowserData: showBrowserStorageWarning && !browserStoragePersistent ? handleKeepBrowserData : void 0,
11033
11224
  onInstallApp: installPromptEvent ? handleInstallApp : void 0,
11034
11225
  getStorageEstimate: showBrowserStorageWarning ? getBrowserStorageEstimate : void 0,
@@ -11040,10 +11231,11 @@ function DocBlocksShell({
11040
11231
  settingsRequest
11041
11232
  }
11042
11233
  ),
11043
- /* @__PURE__ */ jsx16(
11234
+ /* @__PURE__ */ jsx18(
11044
11235
  WorkspacePicker,
11045
11236
  {
11046
11237
  activeWorkspaceId,
11238
+ loading: workspaceStarting,
11047
11239
  refreshKey: descriptorRefreshKey,
11048
11240
  onSelect: handleWorkspaceSelect,
11049
11241
  onOpenFolder: handleOpenFolder,
@@ -11051,7 +11243,7 @@ function DocBlocksShell({
11051
11243
  onRemoveWorkspace: (workspace) => void handleRemoveWorkspace(workspace.id)
11052
11244
  }
11053
11245
  ),
11054
- /* @__PURE__ */ jsx16(
11246
+ /* @__PURE__ */ jsx18(
11055
11247
  WorkspaceSettingsButton,
11056
11248
  {
11057
11249
  onSettings: handleOpenWorkspaceSettings,
@@ -11062,28 +11254,29 @@ function DocBlocksShell({
11062
11254
  }
11063
11255
  }
11064
11256
  ),
11065
- canRestoreSplitView && /* @__PURE__ */ jsx16(
11257
+ canRestoreSplitView && /* @__PURE__ */ jsx18(
11066
11258
  "button",
11067
11259
  {
11068
11260
  className: "db-restore-split",
11069
11261
  onClick: () => updateSidebarPreference("pinned"),
11070
11262
  "aria-label": "Restore split view",
11071
11263
  title: "Restore split view",
11072
- children: /* @__PURE__ */ jsx16(SplitViewIcon, {})
11264
+ children: /* @__PURE__ */ jsx18(SplitViewIcon, {})
11073
11265
  }
11074
11266
  ),
11075
- /* @__PURE__ */ jsx16("span", { className: "db-window-drag-grip", "aria-hidden": true })
11267
+ /* @__PURE__ */ jsx18("span", { className: "db-window-drag-grip", "aria-hidden": true })
11076
11268
  ] }),
11077
- git.available && /* @__PURE__ */ jsx16(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx16(
11269
+ git.available && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(
11078
11270
  GitUI,
11079
11271
  {
11080
11272
  onOpenFile: (path) => void handleSelect(path, "file"),
11081
11273
  onWorkspaceCloned: handleWorkspaceCloned
11082
11274
  }
11083
11275
  ) }),
11084
- /* @__PURE__ */ jsx16(
11276
+ /* @__PURE__ */ jsx18(
11085
11277
  FileExplorer,
11086
11278
  {
11279
+ loading: workspaceStarting,
11087
11280
  className: sidebarView === "search" ? "db-sidebar-view--hidden" : void 0,
11088
11281
  onShowSearch: canBrowseWorkspace ? openWorkspaceSearch : void 0,
11089
11282
  searchShortcutLabel: searchShortcut,
@@ -11115,7 +11308,7 @@ function DocBlocksShell({
11115
11308
  },
11116
11309
  explorerKey
11117
11310
  ),
11118
- searchMounted && /* @__PURE__ */ jsx16(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx16(
11311
+ searchMounted && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(
11119
11312
  WorkspaceSearchPanel,
11120
11313
  {
11121
11314
  index: workspaceIndex.index,
@@ -11126,62 +11319,60 @@ function DocBlocksShell({
11126
11319
  onShowFiles: () => setSidebarView("files")
11127
11320
  }
11128
11321
  ) }),
11129
- singlePane && showWelcomeGateway && /* @__PURE__ */ jsxs14("section", { className: "db-mobile-first-run", "aria-labelledby": "db-mobile-first-run-title", children: [
11130
- /* @__PURE__ */ jsx16("p", { className: "db-mobile-first-run-eyebrow", children: "Local-first Markdown editor" }),
11131
- /* @__PURE__ */ jsx16("h1", { id: "db-mobile-first-run-title", children: "Welcome to DocBlocks" }),
11132
- /* @__PURE__ */ jsx16("p", { children: "Write visually, keep plain Markdown underneath, and export the same document in useful formats. Keep your documents in the workspace you choose." }),
11133
- /* @__PURE__ */ jsxs14("div", { className: "db-mobile-first-run-actions", children: [
11134
- /* @__PURE__ */ jsx16(
11322
+ singlePane && showWelcomeGateway && /* @__PURE__ */ jsxs16("section", { className: "db-mobile-first-run", "aria-labelledby": "db-mobile-first-run-title", children: [
11323
+ /* @__PURE__ */ jsx18("p", { className: "db-mobile-first-run-eyebrow", children: "Local-first Markdown editor" }),
11324
+ /* @__PURE__ */ jsx18("h1", { id: "db-mobile-first-run-title", children: "Welcome to DocBlocks" }),
11325
+ /* @__PURE__ */ jsxs16("p", { children: [
11326
+ WELCOME_SUMMARY,
11327
+ " ",
11328
+ WELCOME_PRIVACY_NOTE
11329
+ ] }),
11330
+ /* @__PURE__ */ jsxs16("div", { className: "db-mobile-first-run-actions", children: [
11331
+ /* @__PURE__ */ jsx18("button", { type: "button", onClick: () => void handleNewFile(), children: "Create a document" }),
11332
+ /* @__PURE__ */ jsx18(
11135
11333
  "button",
11136
11334
  {
11137
11335
  type: "button",
11336
+ className: "db-mobile-first-run-secondary",
11138
11337
  onClick: () => {
11139
11338
  closeWelcomeGateway();
11140
11339
  setMobileShowEditor(true);
11141
11340
  },
11142
11341
  children: "Tour the welcome document"
11143
11342
  }
11144
- ),
11145
- /* @__PURE__ */ jsx16(
11146
- "button",
11147
- {
11148
- type: "button",
11149
- className: "db-mobile-first-run-secondary",
11150
- onClick: () => void handleNewFile(),
11151
- children: "Create a document"
11152
- }
11153
11343
  )
11154
11344
  ] })
11155
11345
  ] }),
11156
- git.available && git.pendingGrant && /* @__PURE__ */ jsx16(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx16(GitGrantNotice, {}) }),
11157
- /* @__PURE__ */ jsxs14("div", { className: "db-shell-sidebar-footer", children: [
11158
- /* @__PURE__ */ jsx16("a", { href: "https://docblocks.com/docs/", target: "_blank", rel: "noopener noreferrer", children: "Docs" }),
11159
- /* @__PURE__ */ jsx16("span", { className: "db-shell-sidebar-footer-separator", "aria-hidden": "true", children: "\u2022" }),
11160
- /* @__PURE__ */ jsx16("a", { href: "https://docblocks.com/terms/", target: "_blank", rel: "noopener noreferrer", children: "Terms" }),
11161
- /* @__PURE__ */ jsx16("span", { className: "db-shell-sidebar-footer-separator", "aria-hidden": "true", children: "\u2022" }),
11162
- /* @__PURE__ */ jsx16("a", { href: issueReportUrl, target: "_blank", rel: "noopener noreferrer", children: "Report issue" }),
11163
- showBrowserStorageWarning && /* @__PURE__ */ jsxs14(Fragment11, { children: [
11164
- /* @__PURE__ */ jsx16("span", { className: "db-shell-sidebar-footer-separator", "aria-hidden": "true", children: "\u2022" }),
11165
- /* @__PURE__ */ jsx16(
11166
- "button",
11167
- {
11168
- type: "button",
11169
- className: "db-shell-sidebar-footer-action",
11170
- onClick: () => void handleDownloadAllWorkspaces(),
11171
- title: "Browser documents can be removed automatically. Download all workspaces now.",
11172
- children: "Back up browser docs"
11173
- }
11174
- )
11175
- ] })
11346
+ git.available && git.pendingGrant && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(GitGrantNotice, {}) }),
11347
+ /* @__PURE__ */ jsxs16("div", { className: "db-shell-sidebar-footer", children: [
11348
+ /* @__PURE__ */ jsx18("a", { href: "https://docblocks.com/docs/", target: "_blank", rel: "noopener noreferrer", children: "Docs" }),
11349
+ /* @__PURE__ */ jsx18("span", { className: "db-shell-sidebar-footer-separator", "aria-hidden": "true", children: "\u2022" }),
11350
+ /* @__PURE__ */ jsx18("a", { href: "https://docblocks.com/terms/", target: "_blank", rel: "noopener noreferrer", children: "Terms" }),
11351
+ /* @__PURE__ */ jsx18("span", { className: "db-shell-sidebar-footer-separator", "aria-hidden": "true", children: "\u2022" }),
11352
+ /* @__PURE__ */ jsx18("a", { href: issueReportUrl, target: "_blank", rel: "noopener noreferrer", children: "Report issue" }),
11353
+ showBrowserStorageWarning && /* @__PURE__ */ jsx18(Fragment11, { children: /* @__PURE__ */ jsxs16(
11354
+ "button",
11355
+ {
11356
+ type: "button",
11357
+ className: "db-shell-sidebar-footer-action",
11358
+ onClick: () => void handleDownloadAllWorkspaces(),
11359
+ "aria-label": "Back up all workspaces",
11360
+ title: "Browsers can clear site data. Download a backup of every workspace.",
11361
+ children: [
11362
+ /* @__PURE__ */ jsx18(BackupIcon, {}),
11363
+ "Back up"
11364
+ ]
11365
+ }
11366
+ ) })
11176
11367
  ] }),
11177
- /* @__PURE__ */ jsxs14("div", { className: "db-sidebar-collapse-preview", "aria-hidden": "true", children: [
11178
- /* @__PURE__ */ jsx16("span", { className: "db-sidebar-collapse-preview-icon", children: /* @__PURE__ */ jsx16(CollapseSidebarGlyph, {}) }),
11179
- /* @__PURE__ */ jsx16("span", { className: "db-sidebar-collapse-preview-label", children: "Release to hide files" })
11368
+ /* @__PURE__ */ jsxs16("div", { className: "db-sidebar-collapse-preview", "aria-hidden": "true", children: [
11369
+ /* @__PURE__ */ jsx18("span", { className: "db-sidebar-collapse-preview-icon", children: /* @__PURE__ */ jsx18(CollapseSidebarGlyph, {}) }),
11370
+ /* @__PURE__ */ jsx18("span", { className: "db-sidebar-collapse-preview-label", children: "Release to hide files" })
11180
11371
  ] })
11181
11372
  ]
11182
11373
  }
11183
11374
  ),
11184
- !singlePane && /* @__PURE__ */ jsx16(
11375
+ !singlePane && /* @__PURE__ */ jsx18(
11185
11376
  "div",
11186
11377
  {
11187
11378
  className: "db-shell-sidebar-resizer",
@@ -11191,7 +11382,7 @@ function DocBlocksShell({
11191
11382
  onPointerDown: handleResizerPointerDown
11192
11383
  }
11193
11384
  ),
11194
- singlePane && /* @__PURE__ */ jsx16(
11385
+ singlePane && /* @__PURE__ */ jsx18(
11195
11386
  "div",
11196
11387
  {
11197
11388
  className: "db-shell-scrim",
@@ -11199,7 +11390,7 @@ function DocBlocksShell({
11199
11390
  onPointerDown: () => setMobileShowEditor(true)
11200
11391
  }
11201
11392
  ),
11202
- /* @__PURE__ */ jsxs14(
11393
+ /* @__PURE__ */ jsxs16(
11203
11394
  "main",
11204
11395
  {
11205
11396
  ref: editorAreaRef,
@@ -11210,8 +11401,8 @@ function DocBlocksShell({
11210
11401
  editorDropActive ? "db-shell-editor-area--drop-active" : ""
11211
11402
  ].filter(Boolean).join(" "),
11212
11403
  children: [
11213
- selectedFile && mediaProvider ? /* @__PURE__ */ jsxs14(Fragment11, { children: [
11214
- selectedManagedOutput === "catalog-html" ? /* @__PURE__ */ jsx16(
11404
+ /* @__PURE__ */ jsxs16("div", { ref: welcomeCoveredRef, className: "db-shell-editor-content", children: [
11405
+ selectedFile && mediaProvider ? /* @__PURE__ */ jsx18(Fragment11, { children: selectedManagedOutput === "catalog-html" ? /* @__PURE__ */ jsx18(
11215
11406
  GeneratedCatalogPage,
11216
11407
  {
11217
11408
  html: editorContent,
@@ -11219,17 +11410,17 @@ function DocBlocksShell({
11219
11410
  onOpenSettings: activeWorkspaceDescriptor ? handleOpenWorkspaceSettings : void 0,
11220
11411
  onBack: singlePane ? openDrawer : void 0
11221
11412
  }
11222
- ) : /* @__PURE__ */ jsx16(
11413
+ ) : /* @__PURE__ */ jsx18(
11223
11414
  GeneratedFileFrame,
11224
11415
  {
11225
11416
  kind: selectedManagedOutput,
11226
11417
  onOpenSettings: activeWorkspaceDescriptor ? handleOpenWorkspaceSettings : void 0,
11227
11418
  onBack: singlePane ? openDrawer : void 0,
11228
- children: /* @__PURE__ */ jsx16(
11419
+ children: /* @__PURE__ */ jsx18(
11229
11420
  Suspense2,
11230
11421
  {
11231
- fallback: /* @__PURE__ */ jsx16("div", { className: "db-shell-empty", role: "status", children: "Loading your document\u2026" }),
11232
- children: /* @__PURE__ */ jsx16(
11422
+ fallback: /* @__PURE__ */ jsx18("div", { className: "db-shell-empty", role: "status", children: "Loading your document\u2026" }),
11423
+ children: editorGenerationSettled && mediaProviderCurrent && /* @__PURE__ */ jsx18(EditorErrorBoundary, { resetKey: `${selectedFile}-${editorKey}`, children: /* @__PURE__ */ jsx18(
11233
11424
  EditorShell,
11234
11425
  {
11235
11426
  initialMarkdown: editorContent,
@@ -11247,6 +11438,8 @@ function DocBlocksShell({
11247
11438
  onChange: handleEditorChange,
11248
11439
  onLinkClick: handleEditorLinkClick,
11249
11440
  colorScheme: resolvedTheme,
11441
+ defaultThemeId: workspaceDefaultThemeId,
11442
+ defaultThemeLabel: "Workspace default",
11250
11443
  writeCanvasSettings: editorWriteCanvasSettings,
11251
11444
  height: "100%",
11252
11445
  placeholder: editorPlaceholder,
@@ -11277,19 +11470,19 @@ function DocBlocksShell({
11277
11470
  versioningAutoSaveIdleMs,
11278
11471
  onSaveVersion,
11279
11472
  statusBarSlotRight,
11280
- sidePanelSlot: ai && aiPanel && selectedImage === void 0 && (selectedOutsideIn === null || selectedOutsideInEditingEnabled) ? /* @__PURE__ */ jsx16(Suspense2, { fallback: null, children: aiPanel === "review" ? /* @__PURE__ */ jsx16(AiReviewPanel, { ai, onClose: () => setAiPanel(null) }) : /* @__PURE__ */ jsx16(AiIllustratePanel, { ai, onClose: () => setAiPanel(null) }) }) : void 0,
11281
- toolbarSlotLeft: singlePane ? /* @__PURE__ */ jsx16(
11473
+ sidePanelSlot: ai && aiPanel && selectedImage === void 0 && (selectedOutsideIn === null || selectedOutsideInEditingEnabled) ? /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: aiPanel === "review" ? /* @__PURE__ */ jsx18(AiReviewPanel, { ai, onClose: () => setAiPanel(null) }) : /* @__PURE__ */ jsx18(AiIllustratePanel, { ai, onClose: () => setAiPanel(null) }) }) : void 0,
11474
+ toolbarSlotLeft: singlePane ? /* @__PURE__ */ jsx18(
11282
11475
  "button",
11283
11476
  {
11284
11477
  className: "db-mobile-back",
11285
11478
  onClick: () => setMobileShowEditor(false),
11286
11479
  "aria-label": "Show file list",
11287
- children: /* @__PURE__ */ jsx16("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx16(FolderGlyph, {}) })
11480
+ children: /* @__PURE__ */ jsx18("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx18(FolderGlyph, {}) })
11288
11481
  }
11289
11482
  ) : void 0,
11290
- summarizationDesigner: selectedImage === void 0 && selectedManagedOutput === void 0 && (selectedOutsideIn === null || selectedOutsideInEditingEnabled) ? (onClose) => /* @__PURE__ */ jsx16(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx16(PresentationMaker, { ai: ai ?? void 0, onClose }) }) : void 0,
11291
- toolbarSlotRight: /* @__PURE__ */ jsxs14(Fragment11, { children: [
11292
- canFind && /* @__PURE__ */ jsx16(
11483
+ summarizationDesigner: selectedImage === void 0 && selectedManagedOutput === void 0 && (selectedOutsideIn === null || selectedOutsideInEditingEnabled) ? (onClose) => /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(PresentationMaker, { ai: ai ?? void 0, onClose }) }) : void 0,
11484
+ toolbarSlotRight: /* @__PURE__ */ jsxs16(Fragment11, { children: [
11485
+ canFind && /* @__PURE__ */ jsx18(
11293
11486
  FindButton,
11294
11487
  {
11295
11488
  active: findMode,
@@ -11297,7 +11490,7 @@ function DocBlocksShell({
11297
11490
  shortcutLabel: findShortcut
11298
11491
  }
11299
11492
  ),
11300
- ai && /* @__PURE__ */ jsx16(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx16(
11493
+ ai && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(
11301
11494
  AiToolbarControl,
11302
11495
  {
11303
11496
  ai,
@@ -11306,8 +11499,8 @@ function DocBlocksShell({
11306
11499
  onOpenPanel: setAiPanel
11307
11500
  }
11308
11501
  ) }),
11309
- speech && /* @__PURE__ */ jsxs14(Suspense2, { fallback: null, children: [
11310
- /* @__PURE__ */ jsx16(
11502
+ speech && /* @__PURE__ */ jsxs16(Suspense2, { fallback: null, children: [
11503
+ /* @__PURE__ */ jsx18(
11311
11504
  TextFromNarration,
11312
11505
  {
11313
11506
  speech,
@@ -11317,27 +11510,27 @@ function DocBlocksShell({
11317
11510
  onOpenSettings: openSettings
11318
11511
  }
11319
11512
  ),
11320
- hostSupports2("speechOutput") ? /* @__PURE__ */ jsx16(
11513
+ hostSupports2("speechOutput") ? /* @__PURE__ */ jsx18(
11321
11514
  SpeechToolbarControl,
11322
11515
  {
11323
11516
  speech,
11324
11517
  onOpenSettings: openSettings,
11325
11518
  readOnly: selectedImage !== void 0 || selectedOutsideIn !== null && !selectedOutsideInEditingEnabled
11326
11519
  }
11327
- ) : /* @__PURE__ */ jsx16(SpeechMenuBridge, {})
11520
+ ) : /* @__PURE__ */ jsx18(SpeechMenuBridge, {})
11328
11521
  ] }),
11329
- canRestoreSplitView && /* @__PURE__ */ jsx16(
11522
+ canRestoreSplitView && /* @__PURE__ */ jsx18(
11330
11523
  "button",
11331
11524
  {
11332
11525
  className: "db-restore-split",
11333
11526
  onClick: () => updateSidebarPreference("pinned"),
11334
11527
  "aria-label": "Restore split view",
11335
11528
  title: "Restore split view",
11336
- children: /* @__PURE__ */ jsx16(SplitViewIcon, {})
11529
+ children: /* @__PURE__ */ jsx18(SplitViewIcon, {})
11337
11530
  }
11338
11531
  ),
11339
- git.repo && /* @__PURE__ */ jsx16(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx16(GitToolbarControl, { selectedFile }) }),
11340
- /* @__PURE__ */ jsx16(
11532
+ git.repo && /* @__PURE__ */ jsx18(Suspense2, { fallback: null, children: /* @__PURE__ */ jsx18(GitToolbarControl, { selectedFile }) }),
11533
+ /* @__PURE__ */ jsx18(
11341
11534
  ExportToolbarControls,
11342
11535
  {
11343
11536
  selectedFile,
@@ -11357,91 +11550,81 @@ function DocBlocksShell({
11357
11550
  ] })
11358
11551
  },
11359
11552
  `${selectedFile}-${editorKey}`
11360
- )
11553
+ ) })
11361
11554
  }
11362
11555
  )
11363
11556
  }
11364
- ),
11365
- showWelcomeGateway && !singlePane && /* @__PURE__ */ jsxs14("div", { className: "db-welcome-gateway", role: "note", "aria-label": "Welcome tip", children: [
11366
- /* @__PURE__ */ jsxs14("span", { className: "db-welcome-gateway-text", children: [
11367
- "You\u2019re watching this welcome doc in ",
11368
- /* @__PURE__ */ jsx16("strong", { children: "Slideshow" }),
11369
- " ",
11370
- "view\u2014 it\u2019s a regular markdown file, and so is everything you\u2019ll write."
11557
+ ) }) : selectedFolder ? /* @__PURE__ */ jsxs16("div", { className: "db-folder-view", children: [
11558
+ singlePane && /* @__PURE__ */ jsxs16("button", { className: "db-mobile-back", onClick: () => setMobileShowEditor(false), children: [
11559
+ /* @__PURE__ */ jsx18("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx18(FolderGlyph, {}) }),
11560
+ "Back to files"
11371
11561
  ] }),
11372
- /* @__PURE__ */ jsx16("button", { className: "db-welcome-gateway-cta", onClick: handleStartWriting, children: "Start writing" }),
11373
- /* @__PURE__ */ jsx16(
11374
- "button",
11562
+ /* @__PURE__ */ jsxs16("div", { className: "db-folder-view-header", children: [
11563
+ /* @__PURE__ */ jsx18("span", { className: "db-folder-view-icon", children: /* @__PURE__ */ jsx18(FolderGlyph, {}) }),
11564
+ /* @__PURE__ */ jsx18("span", { className: "db-folder-view-path", children: selectedFolder })
11565
+ ] }),
11566
+ visibleFolderEntries.length === 0 ? /* @__PURE__ */ jsx18("p", { className: "db-folder-view-empty", children: "This folder is empty." }) : /* @__PURE__ */ jsx18("ul", { className: "db-folder-view-list", children: visibleFolderEntries.map((entry) => /* @__PURE__ */ jsxs16(
11567
+ "li",
11375
11568
  {
11376
- className: "db-welcome-gateway-dismiss",
11377
- onClick: closeWelcomeGateway,
11378
- "aria-label": "Dismiss welcome tip",
11379
- title: "Dismiss",
11380
- children: "\xD7"
11381
- }
11382
- )
11383
- ] })
11384
- ] }) : selectedFolder ? /* @__PURE__ */ jsxs14("div", { className: "db-folder-view", children: [
11385
- singlePane && /* @__PURE__ */ jsxs14("button", { className: "db-mobile-back", onClick: () => setMobileShowEditor(false), children: [
11386
- /* @__PURE__ */ jsx16("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx16(FolderGlyph, {}) }),
11387
- "Back to files"
11388
- ] }),
11389
- /* @__PURE__ */ jsxs14("div", { className: "db-folder-view-header", children: [
11390
- /* @__PURE__ */ jsx16("span", { className: "db-folder-view-icon", children: /* @__PURE__ */ jsx16(FolderGlyph, {}) }),
11391
- /* @__PURE__ */ jsx16("span", { className: "db-folder-view-path", children: selectedFolder })
11569
+ className: "db-folder-view-item",
11570
+ onClick: () => handleSelect(entry.path, entry.kind),
11571
+ children: [
11572
+ /* @__PURE__ */ jsx18("span", { className: "db-folder-view-item-icon", children: entry.kind === "directory" ? /* @__PURE__ */ jsx18(FolderGlyph, {}) : /* @__PURE__ */ jsx18(FileGlyph, {}) }),
11573
+ entry.name
11574
+ ]
11575
+ },
11576
+ entry.path
11577
+ )) })
11578
+ ] }) : /* @__PURE__ */ jsxs16("div", { className: "db-shell-empty db-shell-empty--workspace", children: [
11579
+ singlePane && /* @__PURE__ */ jsxs16("button", { className: "db-mobile-back", onClick: () => setMobileShowEditor(false), children: [
11580
+ /* @__PURE__ */ jsx18("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx18(FolderGlyph, {}) }),
11581
+ "Back to files"
11582
+ ] }),
11583
+ /* @__PURE__ */ jsxs16("div", { className: "db-workspace-empty-content", children: [
11584
+ /* @__PURE__ */ jsx18("span", { className: "db-workspace-empty-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx18(FileGlyph, {}) }),
11585
+ /* @__PURE__ */ jsx18("h1", { children: activeWorkspaceDescriptor?.name ?? "Workspace" }),
11586
+ /* @__PURE__ */ jsx18("p", { children: "Choose a Markdown document from the sidebar, or create a new one." }),
11587
+ /* @__PURE__ */ jsxs16("div", { className: "db-workspace-empty-actions", children: [
11588
+ /* @__PURE__ */ jsx18("button", { type: "button", onClick: () => void handleNewFile(), children: "New document" }),
11589
+ /* @__PURE__ */ jsx18(
11590
+ "button",
11591
+ {
11592
+ type: "button",
11593
+ className: "db-workspace-empty-secondary",
11594
+ onClick: () => void handleNewFolder(),
11595
+ children: "New folder"
11596
+ }
11597
+ ),
11598
+ (hostSupports2("workspaceFolderPicker") || typeof globalThis.showDirectoryPicker === "function") && /* @__PURE__ */ jsx18(
11599
+ "button",
11600
+ {
11601
+ type: "button",
11602
+ className: "db-workspace-empty-secondary",
11603
+ onClick: () => void handleOpenFolder(),
11604
+ children: "Open a folder"
11605
+ }
11606
+ )
11607
+ ] }),
11608
+ /* @__PURE__ */ jsx18("p", { className: "db-workspace-empty-hint", children: "Use the sidebar backup action to keep a portable copy of this workspace." })
11609
+ ] })
11392
11610
  ] }),
11393
- visibleFolderEntries.length === 0 ? /* @__PURE__ */ jsx16("p", { className: "db-folder-view-empty", children: "This folder is empty." }) : /* @__PURE__ */ jsx16("ul", { className: "db-folder-view-list", children: visibleFolderEntries.map((entry) => /* @__PURE__ */ jsxs14(
11394
- "li",
11611
+ /* @__PURE__ */ jsx18(
11612
+ UpdateAvailableNotice,
11395
11613
  {
11396
- className: "db-folder-view-item",
11397
- onClick: () => handleSelect(entry.path, entry.kind),
11398
- children: [
11399
- /* @__PURE__ */ jsx16("span", { className: "db-folder-view-item-icon", children: entry.kind === "directory" ? /* @__PURE__ */ jsx16(FolderGlyph, {}) : /* @__PURE__ */ jsx16(FileGlyph, {}) }),
11400
- entry.name
11401
- ]
11402
- },
11403
- entry.path
11404
- )) })
11405
- ] }) : /* @__PURE__ */ jsxs14("div", { className: "db-shell-empty db-shell-empty--workspace", children: [
11406
- singlePane && /* @__PURE__ */ jsxs14("button", { className: "db-mobile-back", onClick: () => setMobileShowEditor(false), children: [
11407
- /* @__PURE__ */ jsx16("span", { className: "db-mobile-files-icon", children: /* @__PURE__ */ jsx16(FolderGlyph, {}) }),
11408
- "Back to files"
11409
- ] }),
11410
- /* @__PURE__ */ jsxs14("div", { className: "db-workspace-empty-content", children: [
11411
- /* @__PURE__ */ jsx16("span", { className: "db-workspace-empty-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx16(FileGlyph, {}) }),
11412
- /* @__PURE__ */ jsx16("h1", { children: activeWorkspaceDescriptor?.name ?? "Workspace" }),
11413
- /* @__PURE__ */ jsx16("p", { children: "Choose a Markdown document from the sidebar, or create a new one." }),
11414
- /* @__PURE__ */ jsxs14("div", { className: "db-workspace-empty-actions", children: [
11415
- /* @__PURE__ */ jsx16("button", { type: "button", onClick: () => void handleNewFile(), children: "New document" }),
11416
- /* @__PURE__ */ jsx16(
11417
- "button",
11418
- {
11419
- type: "button",
11420
- className: "db-workspace-empty-secondary",
11421
- onClick: () => void handleNewFolder(),
11422
- children: "New folder"
11423
- }
11424
- ),
11425
- (hostSupports2("workspaceFolderPicker") || typeof globalThis.showDirectoryPicker === "function") && /* @__PURE__ */ jsx16(
11426
- "button",
11427
- {
11428
- type: "button",
11429
- className: "db-workspace-empty-secondary",
11430
- onClick: () => void handleOpenFolder(),
11431
- children: "Open a folder"
11432
- }
11433
- )
11434
- ] }),
11435
- /* @__PURE__ */ jsx16("p", { className: "db-workspace-empty-hint", children: "Use the sidebar backup action to keep a portable copy of this workspace." })
11436
- ] })
11614
+ available: updateAvailable,
11615
+ onApplyUpdate,
11616
+ blocked: documentSnapshot.conflict !== null || storageFull,
11617
+ statusBarVisible: updateStatusBarVisible
11618
+ }
11619
+ )
11437
11620
  ] }),
11438
- /* @__PURE__ */ jsx16(
11439
- UpdateAvailableNotice,
11621
+ welcomeScreenShown && /* @__PURE__ */ jsx18(
11622
+ WelcomeScreen,
11440
11623
  {
11441
- available: updateAvailable,
11442
- onApplyUpdate,
11443
- blocked: documentSnapshot.conflict !== null || storageFull,
11444
- statusBarVisible: updateStatusBarVisible
11624
+ onCreateDocument: handleNewFile,
11625
+ onTour: handleTourWelcome,
11626
+ onDismiss: handleTourWelcome,
11627
+ offerApps: hostEnvironment === null
11445
11628
  }
11446
11629
  )
11447
11630
  ]