@bendyline/docblocks-react 2.6.2 → 2.7.1

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 (57) hide show
  1. package/README.md +3 -10
  2. package/THIRD_PARTY_NOTICES.txt +4284 -3651
  3. package/dist/AiDiagrams-LFV4YU6W.js +13 -0
  4. package/dist/AiEditorAssistant-GN2KXKZD.js +786 -0
  5. package/dist/AudioExportDialog-F23QXNPB.js +253 -0
  6. package/dist/DocumentConflictDialog-5LRVIGXS.js +111 -0
  7. package/dist/ExportDialog-IMBVGRYG.js +9 -0
  8. package/dist/{ExportToolbarControls-QYLBRWM7.js → ExportToolbarControls-MUM6HM3K.js} +117 -49
  9. package/dist/{GitToolbarControl-O5AXBC6T.js → GitToolbarControl-B7KG4MFP.js} +6 -6
  10. package/dist/{GitUI-L5T3XHZG.js → GitUI-RCWUZVS6.js} +6 -6
  11. package/dist/PresentationMaker-W2JIBHRN.js +9 -0
  12. package/dist/QuickOpenDialog-2KK4SEBU.js +356 -0
  13. package/dist/Settings-DuXk6baH.d.ts +144 -0
  14. package/dist/ShareDialog-XUA2OVGI.js +292 -0
  15. package/dist/SpeechToolbarControl-OSQS7NVY.js +434 -0
  16. package/dist/TextFromNarration-XYRAB6O2.js +598 -0
  17. package/dist/WorkspaceSearchPanel-BKZJRPMY.js +334 -0
  18. package/dist/chunk-2IYBBFQX.js +201 -0
  19. package/dist/{chunk-LG6HAWCK.js → chunk-56KO2LYN.js} +35 -4
  20. package/dist/chunk-6B7G33D5.js +88 -0
  21. package/dist/chunk-ARATARVJ.js +40 -0
  22. package/dist/{chunk-ODYNOPC3.js → chunk-BCQZTWE5.js} +57 -17
  23. package/dist/{chunk-FMDLZ4ZG.js → chunk-BD54Z5XP.js} +12 -3
  24. package/dist/chunk-EA4BO6E4.js +73 -0
  25. package/dist/chunk-EPOLZNFD.js +518 -0
  26. package/dist/chunk-G4MFB3IO.js +208 -0
  27. package/dist/{chunk-MRUK56JS.js → chunk-GMA4KGGO.js} +7 -3
  28. package/dist/chunk-I44HKDQX.js +314 -0
  29. package/dist/chunk-K4I3NJFL.js +49 -0
  30. package/dist/chunk-KBDZDFPU.js +61 -0
  31. package/dist/{chunk-FNSRCCBC.js → chunk-KWG6UP5O.js} +0 -10
  32. package/dist/chunk-NAH52736.js +1884 -0
  33. package/dist/chunk-RP3DVNTI.js +62 -0
  34. package/dist/chunk-SPUPWCSI.js +111 -0
  35. package/dist/chunk-TBLZBNQF.js +25 -0
  36. package/dist/{chunk-M5Y5WO7Z.js → chunk-UG4G7PJ4.js} +1 -1
  37. package/dist/chunk-UONFWKJ7.js +22 -0
  38. package/dist/chunk-VO2JYYQZ.js +40 -0
  39. package/dist/chunk-W55E6TE2.js +1714 -0
  40. package/dist/chunk-X3DDTJKR.js +574 -0
  41. package/dist/{chunk-EBWYGTN7.js → chunk-X437UAF7.js} +6 -0
  42. package/dist/editor.d.ts +36 -1
  43. package/dist/editor.js +16 -1
  44. package/dist/export/index.d.ts +27 -11
  45. package/dist/export/index.js +11 -7
  46. package/dist/index.d.ts +100 -13
  47. package/dist/index.js +3927 -1638
  48. package/dist/proofing/index.js +11 -1
  49. package/dist/{run-export-I2XOVGG4.js → run-export-47X5FTYZ.js} +3 -3
  50. package/dist/settings/index.d.ts +32 -101
  51. package/dist/settings/index.js +14 -2
  52. package/package.json +9 -9
  53. package/src/styles/docblocks.css +2344 -657
  54. package/dist/ExportDialog-Q4VWI43H.js +0 -9
  55. package/dist/ShareDialog-4OX3UPJ4.js +0 -359
  56. package/dist/chunk-JDJVRDOP.js +0 -92
  57. package/dist/chunk-Q6XNIKDG.js +0 -669
@@ -1,669 +0,0 @@
1
- import {
2
- Dialog
3
- } from "./chunk-LG6HAWCK.js";
4
-
5
- // src/Settings/Settings.tsx
6
- import {
7
- useCallback,
8
- useEffect,
9
- useId,
10
- useLayoutEffect,
11
- useRef,
12
- useState
13
- } from "react";
14
-
15
- // src/preferences/theme.ts
16
- var ACCENT_COLORS = [
17
- "brown",
18
- "green",
19
- "blue",
20
- "purple",
21
- "maroon",
22
- "orange",
23
- "gray"
24
- ];
25
- var DB_CHROME_COLORS = {
26
- light: "#f3eede",
27
- dark: "#262219"
28
- };
29
- var THEME_STORAGE_KEY = "docblocks:themePreference";
30
- var ACCENT_STORAGE_KEY = "docblocks:accentColor";
31
- function loadThemePreference() {
32
- try {
33
- const raw = localStorage.getItem(THEME_STORAGE_KEY);
34
- if (raw === "light" || raw === "dark" || raw === "auto") return raw;
35
- } catch {
36
- }
37
- return "auto";
38
- }
39
- function saveThemePreference(value) {
40
- try {
41
- localStorage.setItem(THEME_STORAGE_KEY, value);
42
- } catch {
43
- }
44
- }
45
- function loadAccentColor() {
46
- try {
47
- const raw = localStorage.getItem(ACCENT_STORAGE_KEY);
48
- if (ACCENT_COLORS.some((color) => color === raw)) return raw;
49
- } catch {
50
- }
51
- return "brown";
52
- }
53
- function saveAccentColor(value) {
54
- try {
55
- localStorage.setItem(ACCENT_STORAGE_KEY, value);
56
- } catch {
57
- }
58
- }
59
-
60
- // src/preferences/write-canvas.ts
61
- var SANS_STACK = 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';
62
- var SERIF_STACK = 'Georgia, "Times New Roman", serif';
63
- var WRITE_CANVAS_FONT_SCHEMES = [
64
- { id: "theme", label: "Inherit from theme", group: "theme" },
65
- {
66
- id: "serif-sans",
67
- label: "Serif headings \xB7 Sans body",
68
- group: "system",
69
- headerFont: SERIF_STACK,
70
- bodyFont: SANS_STACK
71
- },
72
- {
73
- id: "sans-sans",
74
- label: "Sans headings \xB7 Sans body",
75
- group: "system",
76
- headerFont: SANS_STACK,
77
- bodyFont: SANS_STACK
78
- },
79
- {
80
- id: "serif-serif",
81
- label: "Serif headings \xB7 Serif body",
82
- group: "system",
83
- headerFont: SERIF_STACK,
84
- bodyFont: SERIF_STACK
85
- },
86
- {
87
- id: "pt-serif",
88
- label: "PT Serif",
89
- group: "curated",
90
- headerFont: '"PT Serif", Georgia, serif',
91
- bodyFont: '"PT Serif", Georgia, serif'
92
- },
93
- {
94
- id: "hanken",
95
- label: "Hanken Grotesk",
96
- group: "curated",
97
- headerFont: '"Hanken Grotesk", system-ui, sans-serif',
98
- bodyFont: '"Hanken Grotesk", system-ui, sans-serif'
99
- },
100
- {
101
- id: "playfair-pt-serif",
102
- label: "Playfair Display \xB7 PT Serif",
103
- group: "curated",
104
- headerFont: '"Playfair Display", Georgia, serif',
105
- bodyFont: '"PT Serif", Georgia, serif'
106
- },
107
- {
108
- id: "hanken-lora",
109
- label: "Hanken Grotesk \xB7 Lora",
110
- group: "curated",
111
- headerFont: '"Hanken Grotesk", system-ui, sans-serif',
112
- bodyFont: '"Lora", Georgia, serif'
113
- },
114
- {
115
- id: "dm-serif-dm-sans",
116
- label: "DM Serif Display \xB7 DM Sans",
117
- group: "curated",
118
- headerFont: '"DM Serif Display", Georgia, serif',
119
- bodyFont: '"DM Sans", system-ui, sans-serif'
120
- },
121
- {
122
- id: "inter",
123
- label: "Inter",
124
- group: "curated",
125
- headerFont: '"Inter", system-ui, sans-serif',
126
- bodyFont: '"Inter", system-ui, sans-serif'
127
- }
128
- ];
129
- var FONT_SCHEMES_BY_ID = new Map(WRITE_CANVAS_FONT_SCHEMES.map((scheme) => [scheme.id, scheme]));
130
- var DEFAULT_WRITE_CANVAS_FONT_SCHEME = "theme";
131
- function resolveWriteCanvasFonts(scheme) {
132
- const option = FONT_SCHEMES_BY_ID.get(scheme);
133
- const resolved = {};
134
- if (option?.headerFont) resolved.headerFont = option.headerFont;
135
- if (option?.bodyFont) resolved.bodyFont = option.bodyFont;
136
- return resolved;
137
- }
138
- function isWriteCanvasFontScheme(value) {
139
- return typeof value === "string" && FONT_SCHEMES_BY_ID.has(value);
140
- }
141
- var WRITE_CANVAS_TEXT_SIZE_MIN = 12;
142
- var WRITE_CANVAS_TEXT_SIZE_MAX = 32;
143
- var WRITE_CANVAS_LINE_SPACING_MIN = 1;
144
- var WRITE_CANVAS_LINE_SPACING_MAX = 2.4;
145
- var DEFAULT_WRITE_CANVAS_PREFERENCES = {
146
- textSize: 16,
147
- lineSpacing: 1.7,
148
- fontScheme: DEFAULT_WRITE_CANVAS_FONT_SCHEME
149
- };
150
- var WRITE_CANVAS_STORAGE_KEY = "docblocks:writeCanvasSettings";
151
- function loadWriteCanvasPreferences() {
152
- try {
153
- const raw = localStorage.getItem(WRITE_CANVAS_STORAGE_KEY);
154
- if (!raw) return { ...DEFAULT_WRITE_CANVAS_PREFERENCES };
155
- const stored = JSON.parse(raw);
156
- if (!isRecord(stored)) return { ...DEFAULT_WRITE_CANVAS_PREFERENCES };
157
- return {
158
- textSize: numberInRange(
159
- stored.textSize,
160
- WRITE_CANVAS_TEXT_SIZE_MIN,
161
- WRITE_CANVAS_TEXT_SIZE_MAX
162
- ) ? stored.textSize : DEFAULT_WRITE_CANVAS_PREFERENCES.textSize,
163
- lineSpacing: numberInRange(
164
- stored.lineSpacing,
165
- WRITE_CANVAS_LINE_SPACING_MIN,
166
- WRITE_CANVAS_LINE_SPACING_MAX
167
- ) ? stored.lineSpacing : DEFAULT_WRITE_CANVAS_PREFERENCES.lineSpacing,
168
- // Older stored preferences predate fontScheme; fall back to the default.
169
- fontScheme: isWriteCanvasFontScheme(stored.fontScheme) ? stored.fontScheme : DEFAULT_WRITE_CANVAS_PREFERENCES.fontScheme
170
- };
171
- } catch {
172
- return { ...DEFAULT_WRITE_CANVAS_PREFERENCES };
173
- }
174
- }
175
- function saveWriteCanvasPreferences(value) {
176
- try {
177
- localStorage.setItem(WRITE_CANVAS_STORAGE_KEY, JSON.stringify(value));
178
- } catch {
179
- }
180
- }
181
- function numberInRange(value, min, max) {
182
- return typeof value === "number" && Number.isFinite(value) && value >= min && value <= max;
183
- }
184
- function isRecord(value) {
185
- return typeof value === "object" && value !== null && !Array.isArray(value);
186
- }
187
-
188
- // src/Settings/Settings.tsx
189
- import { jsx, jsxs } from "react/jsx-runtime";
190
- var ACCENT_LABELS = {
191
- brown: "Brown",
192
- green: "Green",
193
- blue: "Blue",
194
- purple: "Purple",
195
- maroon: "Maroon",
196
- orange: "Orange",
197
- gray: "Gray"
198
- };
199
- function SettingsDialog({ title = "Settings", onClose, children }) {
200
- return /* @__PURE__ */ jsx(Dialog, { title, onClose, size: "wide", children });
201
- }
202
- function ThemeSettings({ value, onChange, name = "theme" }) {
203
- return /* @__PURE__ */ jsxs("fieldset", { className: "db-settings-fieldset", children: [
204
- /* @__PURE__ */ jsx("legend", { className: "db-settings-legend", children: "Theme" }),
205
- /* @__PURE__ */ jsxs("div", { className: "db-settings-radio-row", children: [
206
- /* @__PURE__ */ jsxs("label", { className: "db-settings-radio db-settings-radio--inline", children: [
207
- /* @__PURE__ */ jsx(
208
- "input",
209
- {
210
- type: "radio",
211
- name,
212
- value: "auto",
213
- checked: value === "auto",
214
- onChange: () => onChange("auto")
215
- }
216
- ),
217
- "System default"
218
- ] }),
219
- /* @__PURE__ */ jsxs("label", { className: "db-settings-radio db-settings-radio--inline", children: [
220
- /* @__PURE__ */ jsx(
221
- "input",
222
- {
223
- type: "radio",
224
- name,
225
- value: "light",
226
- checked: value === "light",
227
- onChange: () => onChange("light")
228
- }
229
- ),
230
- "Light"
231
- ] }),
232
- /* @__PURE__ */ jsxs("label", { className: "db-settings-radio db-settings-radio--inline", children: [
233
- /* @__PURE__ */ jsx(
234
- "input",
235
- {
236
- type: "radio",
237
- name,
238
- value: "dark",
239
- checked: value === "dark",
240
- onChange: () => onChange("dark")
241
- }
242
- ),
243
- "Dark"
244
- ] })
245
- ] })
246
- ] });
247
- }
248
- function AccentColorSettings({
249
- value,
250
- onChange,
251
- name = "accent-color"
252
- }) {
253
- return /* @__PURE__ */ jsxs("fieldset", { className: "db-settings-fieldset", children: [
254
- /* @__PURE__ */ jsx("legend", { className: "db-settings-legend", children: "Accent color" }),
255
- /* @__PURE__ */ jsx("p", { className: "db-settings-hint", children: "Used in both light and dark appearances." }),
256
- /* @__PURE__ */ jsx("div", { className: "db-settings-accent-grid", children: ACCENT_COLORS.map((color) => /* @__PURE__ */ jsxs(
257
- "label",
258
- {
259
- className: `db-settings-accent${value === color ? " db-settings-accent--selected" : ""}`,
260
- children: [
261
- /* @__PURE__ */ jsx(
262
- "input",
263
- {
264
- className: "db-settings-accent-input",
265
- type: "radio",
266
- name,
267
- value: color,
268
- checked: value === color,
269
- onChange: () => onChange(color)
270
- }
271
- ),
272
- /* @__PURE__ */ jsx(
273
- "span",
274
- {
275
- className: `db-settings-accent-swatch db-settings-accent-swatch--${color}`,
276
- "aria-hidden": "true"
277
- }
278
- ),
279
- /* @__PURE__ */ jsx("span", { children: ACCENT_LABELS[color] })
280
- ]
281
- },
282
- color
283
- )) })
284
- ] });
285
- }
286
- function ProofingSettingsControls({ value, onChange }) {
287
- return /* @__PURE__ */ jsxs("fieldset", { className: "db-settings-fieldset", children: [
288
- /* @__PURE__ */ jsx("legend", { className: "db-settings-legend", children: "Spelling and grammar" }),
289
- /* @__PURE__ */ jsx("p", { className: "db-settings-hint", children: "Checking runs on this device \u2014 nothing you write is sent anywhere." }),
290
- /* @__PURE__ */ jsxs("label", { className: "db-settings-checkbox", children: [
291
- /* @__PURE__ */ jsx(
292
- "input",
293
- {
294
- type: "checkbox",
295
- checked: value.spelling,
296
- onChange: (event) => onChange({ ...value, spelling: event.currentTarget.checked })
297
- }
298
- ),
299
- "Show inline spell checking"
300
- ] }),
301
- /* @__PURE__ */ jsxs("label", { className: "db-settings-checkbox", children: [
302
- /* @__PURE__ */ jsx(
303
- "input",
304
- {
305
- type: "checkbox",
306
- checked: value.grammar,
307
- onChange: (event) => onChange({ ...value, grammar: event.currentTarget.checked })
308
- }
309
- ),
310
- "Show inline grammar checking"
311
- ] }),
312
- /* @__PURE__ */ jsx("p", { className: "db-settings-hint", children: "(Grammar checking is currently only available for English)" })
313
- ] });
314
- }
315
- function WriteCanvasSettingsControls({ value, onChange }) {
316
- return /* @__PURE__ */ jsxs("fieldset", { className: "db-settings-fieldset", children: [
317
- /* @__PURE__ */ jsx("legend", { className: "db-settings-legend", children: "Write canvas" }),
318
- /* @__PURE__ */ jsx("p", { className: "db-settings-hint", children: "Adjust the writing view without changing the document or its exported text." }),
319
- /* @__PURE__ */ jsxs("label", { className: "db-settings-slider", children: [
320
- /* @__PURE__ */ jsxs("span", { className: "db-settings-slider-header", children: [
321
- /* @__PURE__ */ jsx("span", { children: "Text size" }),
322
- /* @__PURE__ */ jsxs("output", { className: "db-settings-slider-value", "aria-hidden": "true", children: [
323
- value.textSize,
324
- "px"
325
- ] })
326
- ] }),
327
- /* @__PURE__ */ jsx(
328
- "input",
329
- {
330
- type: "range",
331
- min: WRITE_CANVAS_TEXT_SIZE_MIN,
332
- max: WRITE_CANVAS_TEXT_SIZE_MAX,
333
- step: 1,
334
- value: value.textSize,
335
- "aria-label": "Text size",
336
- "aria-valuetext": `${value.textSize} pixels`,
337
- onChange: (event) => onChange({ ...value, textSize: Number(event.currentTarget.value) })
338
- }
339
- )
340
- ] }),
341
- /* @__PURE__ */ jsxs("label", { className: "db-settings-slider", children: [
342
- /* @__PURE__ */ jsxs("span", { className: "db-settings-slider-header", children: [
343
- /* @__PURE__ */ jsx("span", { children: "Line spacing" }),
344
- /* @__PURE__ */ jsx("output", { className: "db-settings-slider-value", "aria-hidden": "true", children: formatLineSpacing(value.lineSpacing) })
345
- ] }),
346
- /* @__PURE__ */ jsx(
347
- "input",
348
- {
349
- type: "range",
350
- min: WRITE_CANVAS_LINE_SPACING_MIN,
351
- max: WRITE_CANVAS_LINE_SPACING_MAX,
352
- step: 0.1,
353
- value: value.lineSpacing,
354
- "aria-label": "Line spacing",
355
- "aria-valuetext": `${value.lineSpacing} times`,
356
- onChange: (event) => onChange({ ...value, lineSpacing: Number(event.currentTarget.value) })
357
- }
358
- )
359
- ] }),
360
- /* @__PURE__ */ jsx(
361
- FontSchemePicker,
362
- {
363
- value: value.fontScheme,
364
- onChange: (fontScheme) => onChange({ ...value, fontScheme })
365
- }
366
- )
367
- ] });
368
- }
369
- function FontSchemePicker({ value, onChange }) {
370
- const selectedIndex = Math.max(
371
- 0,
372
- WRITE_CANVAS_FONT_SCHEMES.findIndex((scheme) => scheme.id === value)
373
- );
374
- const selectedScheme = WRITE_CANVAS_FONT_SCHEMES[selectedIndex];
375
- const [isOpen, setIsOpen] = useState(false);
376
- const [activeIndex, setActiveIndex] = useState(selectedIndex);
377
- const [menuPosition, setMenuPosition] = useState(null);
378
- const rootRef = useRef(null);
379
- const triggerRef = useRef(null);
380
- const listboxRef = useRef(null);
381
- const optionRefs = useRef([]);
382
- const labelId = useId();
383
- const listboxId = useId();
384
- const close = useCallback((returnFocus) => {
385
- setIsOpen(false);
386
- setMenuPosition(null);
387
- if (returnFocus) triggerRef.current?.focus({ preventScroll: true });
388
- }, []);
389
- const updateMenuPosition = useCallback(() => {
390
- const trigger = triggerRef.current;
391
- if (!trigger) return;
392
- const rect = trigger.getBoundingClientRect();
393
- const viewportWidth = document.documentElement.clientWidth || window.innerWidth;
394
- const viewportHeight = document.documentElement.clientHeight || window.innerHeight;
395
- const gutter = 8;
396
- const gap = 4;
397
- const width = Math.min(rect.width, viewportWidth - gutter * 2);
398
- const left = Math.min(Math.max(gutter, rect.left), viewportWidth - width - gutter);
399
- const spaceBelow = viewportHeight - rect.bottom - gap - gutter;
400
- const spaceAbove = rect.top - gap - gutter;
401
- const openAbove = spaceBelow < 260 && spaceAbove > spaceBelow;
402
- const availableHeight = openAbove ? spaceAbove : spaceBelow;
403
- const maxHeight = Math.max(80, Math.min(420, availableHeight));
404
- setMenuPosition(
405
- openAbove ? {
406
- left,
407
- bottom: viewportHeight - rect.top + gap,
408
- width,
409
- maxHeight
410
- } : {
411
- left,
412
- top: rect.bottom + gap,
413
- width,
414
- maxHeight
415
- }
416
- );
417
- }, []);
418
- const open = useCallback(
419
- (index) => {
420
- setActiveIndex(index);
421
- updateMenuPosition();
422
- setIsOpen(true);
423
- },
424
- [updateMenuPosition]
425
- );
426
- useEffect(() => {
427
- if (!isOpen) setActiveIndex(selectedIndex);
428
- }, [isOpen, selectedIndex]);
429
- useLayoutEffect(() => {
430
- if (!isOpen) return;
431
- updateMenuPosition();
432
- listboxRef.current?.focus({ preventScroll: true });
433
- optionRefs.current[activeIndex]?.scrollIntoView?.({ block: "nearest" });
434
- }, [activeIndex, isOpen, updateMenuPosition]);
435
- useEffect(() => {
436
- if (!isOpen) return;
437
- const handleOutsidePointer = (event) => {
438
- if (!rootRef.current?.contains(event.target)) close(false);
439
- };
440
- const handleViewportChange = () => updateMenuPosition();
441
- document.addEventListener("mousedown", handleOutsidePointer);
442
- window.addEventListener("resize", handleViewportChange);
443
- window.addEventListener("scroll", handleViewportChange, true);
444
- return () => {
445
- document.removeEventListener("mousedown", handleOutsidePointer);
446
- window.removeEventListener("resize", handleViewportChange);
447
- window.removeEventListener("scroll", handleViewportChange, true);
448
- };
449
- }, [close, isOpen, updateMenuPosition]);
450
- const select = useCallback(
451
- (index) => {
452
- const scheme = WRITE_CANVAS_FONT_SCHEMES[index];
453
- if (!scheme) return;
454
- onChange(scheme.id);
455
- close(true);
456
- },
457
- [close, onChange]
458
- );
459
- const handleTriggerKeyDown = (event) => {
460
- if (event.key === "ArrowDown" || event.key === "ArrowUp") {
461
- event.preventDefault();
462
- open(selectedIndex);
463
- }
464
- };
465
- const handleListboxKeyDown = (event) => {
466
- switch (event.key) {
467
- case "ArrowDown":
468
- event.preventDefault();
469
- setActiveIndex((current) => (current + 1) % WRITE_CANVAS_FONT_SCHEMES.length);
470
- break;
471
- case "ArrowUp":
472
- event.preventDefault();
473
- setActiveIndex(
474
- (current) => (current - 1 + WRITE_CANVAS_FONT_SCHEMES.length) % WRITE_CANVAS_FONT_SCHEMES.length
475
- );
476
- break;
477
- case "Home":
478
- event.preventDefault();
479
- setActiveIndex(0);
480
- break;
481
- case "End":
482
- event.preventDefault();
483
- setActiveIndex(WRITE_CANVAS_FONT_SCHEMES.length - 1);
484
- break;
485
- case "Enter":
486
- case " ":
487
- event.preventDefault();
488
- select(activeIndex);
489
- break;
490
- case "Escape":
491
- event.preventDefault();
492
- event.stopPropagation();
493
- close(true);
494
- break;
495
- case "Tab":
496
- close(false);
497
- break;
498
- }
499
- };
500
- const menuStyle = menuPosition ? {
501
- left: `${menuPosition.left}px`,
502
- top: menuPosition.top === void 0 ? void 0 : `${menuPosition.top}px`,
503
- bottom: menuPosition.bottom === void 0 ? void 0 : `${menuPosition.bottom}px`,
504
- width: `${menuPosition.width}px`,
505
- maxHeight: `${menuPosition.maxHeight}px`
506
- } : void 0;
507
- return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: "db-settings-select db-font-picker", children: [
508
- /* @__PURE__ */ jsx("span", { className: "db-settings-select-header", children: /* @__PURE__ */ jsx("span", { id: labelId, children: "Font" }) }),
509
- /* @__PURE__ */ jsxs(
510
- "button",
511
- {
512
- ref: triggerRef,
513
- type: "button",
514
- className: "db-font-picker-trigger",
515
- "aria-label": `Font, ${selectedScheme.label}`,
516
- "aria-haspopup": "listbox",
517
- "aria-expanded": isOpen,
518
- "aria-controls": isOpen ? listboxId : void 0,
519
- onClick: () => isOpen ? close(false) : open(selectedIndex),
520
- onKeyDown: handleTriggerKeyDown,
521
- children: [
522
- /* @__PURE__ */ jsx(FontSchemePreview, { scheme: selectedScheme, compact: true }),
523
- /* @__PURE__ */ jsx(
524
- "span",
525
- {
526
- className: `db-font-picker-caret${isOpen ? " db-font-picker-caret--open" : ""}`,
527
- "aria-hidden": "true"
528
- }
529
- )
530
- ]
531
- }
532
- ),
533
- isOpen && /* @__PURE__ */ jsxs(
534
- "div",
535
- {
536
- ref: listboxRef,
537
- id: listboxId,
538
- className: "db-font-picker-menu",
539
- style: menuStyle,
540
- role: "listbox",
541
- tabIndex: -1,
542
- "aria-labelledby": labelId,
543
- "aria-activedescendant": `${listboxId}-option-${activeIndex}`,
544
- onKeyDown: handleListboxKeyDown,
545
- children: [
546
- WRITE_CANVAS_FONT_SCHEMES.filter((scheme) => scheme.group === "theme").map(
547
- (scheme) => renderFontSchemeOption(scheme)
548
- ),
549
- FONT_SCHEME_GROUPS.map(({ group, label }) => /* @__PURE__ */ jsxs("div", { role: "group", "aria-label": label, children: [
550
- /* @__PURE__ */ jsx("div", { className: "db-font-picker-group", "aria-hidden": "true", children: label }),
551
- WRITE_CANVAS_FONT_SCHEMES.filter((scheme) => scheme.group === group).map(
552
- (scheme) => renderFontSchemeOption(scheme)
553
- )
554
- ] }, group))
555
- ]
556
- }
557
- )
558
- ] });
559
- function renderFontSchemeOption(scheme) {
560
- const index = WRITE_CANVAS_FONT_SCHEMES.indexOf(scheme);
561
- const selected = scheme.id === value;
562
- const active = index === activeIndex;
563
- return /* @__PURE__ */ jsxs(
564
- "div",
565
- {
566
- ref: (element) => {
567
- optionRefs.current[index] = element;
568
- },
569
- id: `${listboxId}-option-${index}`,
570
- className: `db-font-picker-option${selected ? " db-font-picker-option--selected" : ""}${active ? " db-font-picker-option--active" : ""}`,
571
- role: "option",
572
- "aria-selected": selected,
573
- onMouseDown: (event) => event.preventDefault(),
574
- onMouseMove: () => setActiveIndex(index),
575
- onClick: () => select(index),
576
- children: [
577
- /* @__PURE__ */ jsx(FontSchemePreview, { scheme }),
578
- /* @__PURE__ */ jsx("span", { className: "db-font-picker-check", "aria-hidden": "true", children: selected ? "\u2713" : "" })
579
- ]
580
- },
581
- scheme.id
582
- );
583
- }
584
- }
585
- function FontSchemePreview({
586
- scheme,
587
- compact = false
588
- }) {
589
- const labels = scheme.label.split(/\s*\u00b7\s*/u);
590
- const headingLabel = labels[0] ?? scheme.label;
591
- const bodyLabel = labels[1] ?? (scheme.id === "theme" ? "Use the active theme" : "Headings & body");
592
- return /* @__PURE__ */ jsxs("span", { className: `db-font-picker-preview${compact ? " db-font-picker-preview--compact" : ""}`, children: [
593
- /* @__PURE__ */ jsx(
594
- "span",
595
- {
596
- className: "db-font-picker-heading",
597
- style: scheme.headerFont ? { fontFamily: scheme.headerFont } : void 0,
598
- children: headingLabel
599
- }
600
- ),
601
- /* @__PURE__ */ jsx(
602
- "span",
603
- {
604
- className: "db-font-picker-body",
605
- style: scheme.bodyFont ? { fontFamily: scheme.bodyFont } : void 0,
606
- children: bodyLabel
607
- }
608
- )
609
- ] });
610
- }
611
- var FONT_SCHEME_GROUPS = [
612
- { group: "system", label: "System fonts" },
613
- { group: "curated", label: "Curated pairings" }
614
- ];
615
- function formatLineSpacing(value) {
616
- return `${value.toFixed(1).replace(/\.0$/, "")}\xD7`;
617
- }
618
-
619
- // src/preferences/proofing.ts
620
- var DEFAULT_PROOFING_PREFERENCES = {
621
- spelling: true,
622
- grammar: true
623
- };
624
- var STORAGE_KEY = "docblocks:proofingPreferences";
625
- function loadProofingPreferences() {
626
- try {
627
- const raw = localStorage.getItem(STORAGE_KEY);
628
- if (!raw) return { ...DEFAULT_PROOFING_PREFERENCES };
629
- const stored = JSON.parse(raw);
630
- if (typeof stored !== "object" || stored === null) {
631
- return { ...DEFAULT_PROOFING_PREFERENCES };
632
- }
633
- const record = stored;
634
- return {
635
- spelling: typeof record.spelling === "boolean" ? record.spelling : DEFAULT_PROOFING_PREFERENCES.spelling,
636
- grammar: typeof record.grammar === "boolean" ? record.grammar : DEFAULT_PROOFING_PREFERENCES.grammar
637
- };
638
- } catch {
639
- }
640
- return { ...DEFAULT_PROOFING_PREFERENCES };
641
- }
642
- function saveProofingPreferences(value) {
643
- try {
644
- localStorage.setItem(STORAGE_KEY, JSON.stringify(value));
645
- } catch {
646
- }
647
- }
648
-
649
- export {
650
- WRITE_CANVAS_FONT_SCHEMES,
651
- DEFAULT_WRITE_CANVAS_FONT_SCHEME,
652
- resolveWriteCanvasFonts,
653
- DEFAULT_WRITE_CANVAS_PREFERENCES,
654
- loadWriteCanvasPreferences,
655
- saveWriteCanvasPreferences,
656
- DEFAULT_PROOFING_PREFERENCES,
657
- loadProofingPreferences,
658
- saveProofingPreferences,
659
- DB_CHROME_COLORS,
660
- loadThemePreference,
661
- saveThemePreference,
662
- loadAccentColor,
663
- saveAccentColor,
664
- SettingsDialog,
665
- ThemeSettings,
666
- AccentColorSettings,
667
- ProofingSettingsControls,
668
- WriteCanvasSettingsControls
669
- };