quoin-editor 1.0.2 → 1.1.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 (224) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/ai.cjs +169 -249
  3. package/dist/ai.cjs.map +1 -1
  4. package/dist/ai.js +38 -121
  5. package/dist/ai.js.map +1 -1
  6. package/dist/catalogue.cjs +29 -43
  7. package/dist/catalogue.cjs.map +1 -1
  8. package/dist/catalogue.js +21 -37
  9. package/dist/catalogue.js.map +1 -1
  10. package/dist/{chunk-DUE3HCZD.js → chunk-2EQ6FKSK.js} +19 -28
  11. package/dist/chunk-2EQ6FKSK.js.map +1 -0
  12. package/dist/{chunk-RJRX34BZ.js → chunk-3BXUGX5F.js} +4 -18
  13. package/dist/chunk-3BXUGX5F.js.map +1 -0
  14. package/dist/chunk-3QRVAI53.cjs +27 -0
  15. package/dist/chunk-3QRVAI53.cjs.map +1 -0
  16. package/dist/{chunk-U3LOLYAU.js → chunk-7FAVFJAS.js} +4 -10
  17. package/dist/chunk-7FAVFJAS.js.map +1 -0
  18. package/dist/{chunk-FDRUAL3Z.cjs → chunk-7NAONESM.cjs} +90 -153
  19. package/dist/chunk-7NAONESM.cjs.map +1 -0
  20. package/dist/{chunk-6V6GGBDK.cjs → chunk-7SVKLWDT.cjs} +24 -31
  21. package/dist/chunk-7SVKLWDT.cjs.map +1 -0
  22. package/dist/{chunk-CW3AFJBR.cjs → chunk-7XQGOCUG.cjs} +1332 -1772
  23. package/dist/chunk-7XQGOCUG.cjs.map +1 -0
  24. package/dist/{chunk-EH5KXQXY.cjs → chunk-A6PGQVTR.cjs} +36 -20
  25. package/dist/chunk-A6PGQVTR.cjs.map +1 -0
  26. package/dist/{chunk-4SLJNZSM.cjs → chunk-AIS37SL2.cjs} +201 -198
  27. package/dist/chunk-AIS37SL2.cjs.map +1 -0
  28. package/dist/{chunk-IQBMAE3F.js → chunk-CKHKCPGL.js} +34 -92
  29. package/dist/chunk-CKHKCPGL.js.map +1 -0
  30. package/dist/{chunk-T43RZTUT.js → chunk-DYWU4SQ2.js} +723 -1246
  31. package/dist/chunk-DYWU4SQ2.js.map +1 -0
  32. package/dist/chunk-EFRQMYZ6.cjs +33 -0
  33. package/dist/chunk-EFRQMYZ6.cjs.map +1 -0
  34. package/dist/{chunk-O4Z2WMFF.js → chunk-HDJ653LM.js} +25 -18
  35. package/dist/chunk-HDJ653LM.js.map +1 -0
  36. package/dist/chunk-HQ43EIYO.cjs +94 -0
  37. package/dist/chunk-HQ43EIYO.cjs.map +1 -0
  38. package/dist/{chunk-6NULZPVC.js → chunk-HTLWPSMU.js} +8 -61
  39. package/dist/chunk-HTLWPSMU.js.map +1 -0
  40. package/dist/{chunk-EPARJI4V.js → chunk-IEP7BPFN.js} +122 -267
  41. package/dist/chunk-IEP7BPFN.js.map +1 -0
  42. package/dist/{chunk-P6KYXFZC.cjs → chunk-IGZRZIAF.cjs} +440 -538
  43. package/dist/chunk-IGZRZIAF.cjs.map +1 -0
  44. package/dist/chunk-JCEFSTVG.cjs +483 -0
  45. package/dist/chunk-JCEFSTVG.cjs.map +1 -0
  46. package/dist/chunk-KXRGY5LK.cjs +612 -0
  47. package/dist/chunk-KXRGY5LK.cjs.map +1 -0
  48. package/dist/{chunk-JHQUHFLX.js → chunk-KZ6ZFCGO.js} +38 -120
  49. package/dist/chunk-KZ6ZFCGO.js.map +1 -0
  50. package/dist/{chunk-ADSJ42DO.js → chunk-L2QA2UTY.js} +17 -69
  51. package/dist/chunk-L2QA2UTY.js.map +1 -0
  52. package/dist/{chunk-OBMBSU2S.js → chunk-L4D23LM2.js} +5 -184
  53. package/dist/chunk-L4D23LM2.js.map +1 -0
  54. package/dist/{chunk-4XFXB37X.js → chunk-L6OW2FL3.js} +7 -90
  55. package/dist/chunk-L6OW2FL3.js.map +1 -0
  56. package/dist/chunk-LE5XMIFJ.cjs +4 -3
  57. package/dist/chunk-LE5XMIFJ.cjs.map +1 -1
  58. package/dist/chunk-MQUCCSWG.js +2 -3
  59. package/dist/chunk-MQUCCSWG.js.map +1 -1
  60. package/dist/{chunk-C23RQVRK.js → chunk-MUIPM26J.js} +66 -216
  61. package/dist/chunk-MUIPM26J.js.map +1 -0
  62. package/dist/{chunk-AUOEM3SF.cjs → chunk-OKWER2RV.cjs} +102 -155
  63. package/dist/chunk-OKWER2RV.cjs.map +1 -0
  64. package/dist/{chunk-TLGX43P6.cjs → chunk-OM7E43ZN.cjs} +89 -86
  65. package/dist/chunk-OM7E43ZN.cjs.map +1 -0
  66. package/dist/{chunk-NEZJ7ZP5.js → chunk-QSXPKZ2F.js} +4 -8
  67. package/dist/chunk-QSXPKZ2F.js.map +1 -0
  68. package/dist/{chunk-VCLL5C7J.js → chunk-RFLFRIPV.js} +14 -57
  69. package/dist/chunk-RFLFRIPV.js.map +1 -0
  70. package/dist/chunk-RIIXJWBR.cjs +24 -0
  71. package/dist/chunk-RIIXJWBR.cjs.map +1 -0
  72. package/dist/{chunk-VRS6WCEK.js → chunk-SFMORPWB.js} +60 -167
  73. package/dist/chunk-SFMORPWB.js.map +1 -0
  74. package/dist/{chunk-YBMUEEM5.js → chunk-TYZSB7JT.js} +4 -8
  75. package/dist/chunk-TYZSB7JT.js.map +1 -0
  76. package/dist/{chunk-BQANU5BH.cjs → chunk-U5BSCAMP.cjs} +34 -44
  77. package/dist/chunk-U5BSCAMP.cjs.map +1 -0
  78. package/dist/{chunk-OSHZQR3W.js → chunk-UEVR4B5S.js} +13 -45
  79. package/dist/chunk-UEVR4B5S.js.map +1 -0
  80. package/dist/{chunk-N4FGA3H4.js → chunk-VBJY2CSK.js} +38 -105
  81. package/dist/chunk-VBJY2CSK.js.map +1 -0
  82. package/dist/{chunk-ZKVOS57Q.cjs → chunk-VFSVN5IQ.cjs} +495 -551
  83. package/dist/chunk-VFSVN5IQ.cjs.map +1 -0
  84. package/dist/{chunk-X4HDKFW5.cjs → chunk-VNRI5DAL.cjs} +56 -105
  85. package/dist/chunk-VNRI5DAL.cjs.map +1 -0
  86. package/dist/chunk-W7B4WQ3L.cjs +200 -0
  87. package/dist/chunk-W7B4WQ3L.cjs.map +1 -0
  88. package/dist/{chunk-623AOJM2.js → chunk-WAGBELKA.js} +7 -25
  89. package/dist/chunk-WAGBELKA.js.map +1 -0
  90. package/dist/{chunk-WEYDDIBQ.cjs → chunk-WH56EW3H.cjs} +36 -64
  91. package/dist/chunk-WH56EW3H.cjs.map +1 -0
  92. package/dist/{chunk-5MAYUGTE.cjs → chunk-XAS7LANM.cjs} +233 -363
  93. package/dist/chunk-XAS7LANM.cjs.map +1 -0
  94. package/dist/comments.cjs +210 -290
  95. package/dist/comments.cjs.map +1 -1
  96. package/dist/comments.js +82 -186
  97. package/dist/comments.js.map +1 -1
  98. package/dist/diff.cjs +48 -65
  99. package/dist/diff.cjs.map +1 -1
  100. package/dist/diff.d.cts +2 -2
  101. package/dist/diff.d.ts +2 -2
  102. package/dist/diff.js +8 -32
  103. package/dist/diff.js.map +1 -1
  104. package/dist/docx.cjs +50 -63
  105. package/dist/docx.cjs.map +1 -1
  106. package/dist/docx.js +7 -22
  107. package/dist/docx.js.map +1 -1
  108. package/dist/embed.cjs +19 -12
  109. package/dist/embed.cjs.map +1 -1
  110. package/dist/embed.js +10 -16
  111. package/dist/embed.js.map +1 -1
  112. package/dist/emoji-data.cjs +7 -5
  113. package/dist/emoji-data.cjs.map +1 -1
  114. package/dist/emoji-data.js +3 -5
  115. package/dist/emoji-data.js.map +1 -1
  116. package/dist/emoji.cjs +26 -17
  117. package/dist/emoji.cjs.map +1 -1
  118. package/dist/emoji.js +9 -17
  119. package/dist/emoji.js.map +1 -1
  120. package/dist/engine.cjs +229 -118
  121. package/dist/engine.cjs.map +1 -1
  122. package/dist/engine.js +4 -118
  123. package/dist/engine.js.map +1 -1
  124. package/dist/find.cjs +30 -19
  125. package/dist/find.cjs.map +1 -1
  126. package/dist/find.js +9 -19
  127. package/dist/find.js.map +1 -1
  128. package/dist/headless.cjs +291 -151
  129. package/dist/headless.cjs.map +1 -1
  130. package/dist/headless.d.cts +5 -1
  131. package/dist/headless.d.ts +5 -1
  132. package/dist/headless.js +6 -151
  133. package/dist/headless.js.map +1 -1
  134. package/dist/index.cjs +349 -183
  135. package/dist/index.cjs.map +1 -1
  136. package/dist/index.d.cts +17 -4
  137. package/dist/index.d.ts +17 -4
  138. package/dist/index.js +8 -183
  139. package/dist/index.js.map +1 -1
  140. package/dist/math.cjs +20 -13
  141. package/dist/math.cjs.map +1 -1
  142. package/dist/math.js +11 -17
  143. package/dist/math.js.map +1 -1
  144. package/dist/mention.cjs +20 -13
  145. package/dist/mention.cjs.map +1 -1
  146. package/dist/mention.js +11 -17
  147. package/dist/mention.js.map +1 -1
  148. package/dist/presence.cjs +99 -132
  149. package/dist/presence.cjs.map +1 -1
  150. package/dist/presence.js +22 -78
  151. package/dist/presence.js.map +1 -1
  152. package/dist/{registry-CWBOSAHm.d.ts → registry-CXegaw5k.d.cts} +25 -2
  153. package/dist/{registry-CWBOSAHm.d.cts → registry-CXegaw5k.d.ts} +25 -2
  154. package/dist/stats.cjs +27 -18
  155. package/dist/stats.cjs.map +1 -1
  156. package/dist/stats.js +10 -18
  157. package/dist/stats.js.map +1 -1
  158. package/dist/styles.css +1 -1
  159. package/dist/table.cjs +90 -49
  160. package/dist/table.cjs.map +1 -1
  161. package/dist/table.js +9 -49
  162. package/dist/table.js.map +1 -1
  163. package/dist/toc.cjs +26 -17
  164. package/dist/toc.cjs.map +1 -1
  165. package/dist/toc.js +9 -17
  166. package/dist/toc.js.map +1 -1
  167. package/dist/view.cjs +13 -16
  168. package/dist/view.cjs.map +1 -1
  169. package/dist/view.d.cts +2 -2
  170. package/dist/view.d.ts +2 -2
  171. package/dist/view.js +7 -16
  172. package/dist/view.js.map +1 -1
  173. package/dist/yjs.cjs +186 -228
  174. package/dist/yjs.cjs.map +1 -1
  175. package/dist/yjs.js +12 -80
  176. package/dist/yjs.js.map +1 -1
  177. package/package.json +2 -1
  178. package/dist/chunk-4SLJNZSM.cjs.map +0 -1
  179. package/dist/chunk-4XFXB37X.js.map +0 -1
  180. package/dist/chunk-5MAYUGTE.cjs.map +0 -1
  181. package/dist/chunk-623AOJM2.js.map +0 -1
  182. package/dist/chunk-6NULZPVC.js.map +0 -1
  183. package/dist/chunk-6V6GGBDK.cjs.map +0 -1
  184. package/dist/chunk-73653CJ4.cjs +0 -34
  185. package/dist/chunk-73653CJ4.cjs.map +0 -1
  186. package/dist/chunk-ADSJ42DO.js.map +0 -1
  187. package/dist/chunk-AUOEM3SF.cjs.map +0 -1
  188. package/dist/chunk-BQANU5BH.cjs.map +0 -1
  189. package/dist/chunk-C23RQVRK.js.map +0 -1
  190. package/dist/chunk-CW3AFJBR.cjs.map +0 -1
  191. package/dist/chunk-DUE3HCZD.js.map +0 -1
  192. package/dist/chunk-EH5KXQXY.cjs.map +0 -1
  193. package/dist/chunk-EPARJI4V.js.map +0 -1
  194. package/dist/chunk-FDRUAL3Z.cjs.map +0 -1
  195. package/dist/chunk-IQBMAE3F.js.map +0 -1
  196. package/dist/chunk-JHQUHFLX.js.map +0 -1
  197. package/dist/chunk-KUYZMSMF.cjs +0 -100
  198. package/dist/chunk-KUYZMSMF.cjs.map +0 -1
  199. package/dist/chunk-LLTEGXWZ.cjs +0 -562
  200. package/dist/chunk-LLTEGXWZ.cjs.map +0 -1
  201. package/dist/chunk-N4FGA3H4.js.map +0 -1
  202. package/dist/chunk-NEZJ7ZP5.js.map +0 -1
  203. package/dist/chunk-O4Z2WMFF.js.map +0 -1
  204. package/dist/chunk-OBMBSU2S.js.map +0 -1
  205. package/dist/chunk-OSHZQR3W.js.map +0 -1
  206. package/dist/chunk-P6KYXFZC.cjs.map +0 -1
  207. package/dist/chunk-R2BLBV43.cjs +0 -239
  208. package/dist/chunk-R2BLBV43.cjs.map +0 -1
  209. package/dist/chunk-RJRX34BZ.js.map +0 -1
  210. package/dist/chunk-T43RZTUT.js.map +0 -1
  211. package/dist/chunk-TLGX43P6.cjs.map +0 -1
  212. package/dist/chunk-U3LOLYAU.js.map +0 -1
  213. package/dist/chunk-UEKXVCKC.cjs +0 -716
  214. package/dist/chunk-UEKXVCKC.cjs.map +0 -1
  215. package/dist/chunk-VCLL5C7J.js.map +0 -1
  216. package/dist/chunk-VRS6WCEK.js.map +0 -1
  217. package/dist/chunk-WEYDDIBQ.cjs.map +0 -1
  218. package/dist/chunk-X4HDKFW5.cjs.map +0 -1
  219. package/dist/chunk-X4P4TQXH.cjs +0 -30
  220. package/dist/chunk-X4P4TQXH.cjs.map +0 -1
  221. package/dist/chunk-XA3UEJIW.cjs +0 -25
  222. package/dist/chunk-XA3UEJIW.cjs.map +0 -1
  223. package/dist/chunk-YBMUEEM5.js.map +0 -1
  224. package/dist/chunk-ZKVOS57Q.cjs.map +0 -1
@@ -1,144 +1,19 @@
1
- import {
2
- EditableRegion,
3
- EditorView,
4
- NATIVE_INTERACTION,
5
- NODE_ENTRY,
6
- TaskCheckbox,
7
- ToggleChevron,
8
- createAutoScroll,
9
- dispatchSelection,
10
- domMapOf,
11
- drawnBlockCount,
12
- hostKey,
13
- isComposingKey,
14
- listen,
15
- moveToNeighbour,
16
- onBlock,
17
- regionInline,
18
- textDiff,
19
- useBlockDomId,
20
- useEditorState,
21
- useIsomorphicLayoutEffect,
22
- useOrderedNumber,
23
- useQuoinEditor,
24
- useReadOnly,
25
- useRegionDomId,
26
- useToggleOpen,
27
- visibleBlockIndexes,
28
- wholeState
29
- } from "./chunk-EPARJI4V.js";
30
- import {
31
- blockByType,
32
- defineBlock,
33
- devWarn,
34
- highlightedLines,
35
- paletteBlocks,
36
- tokenColour
37
- } from "./chunk-O4Z2WMFF.js";
38
- import {
39
- HISTORY_GROUP,
40
- LINE_JOIN,
41
- LINE_SPLIT,
42
- Transaction,
43
- blockRangeSelection,
44
- caretMarks,
45
- coreExtensions,
46
- createBlock,
47
- createPluginKey,
48
- defineExtension,
49
- deleteBlocks,
50
- descendantsEnd,
51
- detectMac,
52
- duplicateBlocks,
53
- endOf,
54
- getPluginState,
55
- headBlockId,
56
- indent,
57
- insertBlockAfter,
58
- insertBlocksStep,
59
- insertText,
60
- isActive,
61
- isCollapsed,
62
- isParagraph,
63
- isTextFlow,
64
- keyName,
65
- markExtent,
66
- markRanges,
67
- moveBlocksDown,
68
- moveBlocksTo,
69
- moveBlocksUp,
70
- movedBlockIds,
71
- nodeSelection,
72
- normalizeKey,
73
- orderedRange,
74
- outdent,
75
- primaryRegion,
76
- rangeContent,
77
- redo,
78
- regionLength,
79
- removeMarkStep,
80
- replaceBlockStep,
81
- replaceInlineStep,
82
- runCommands,
83
- sameSelection,
84
- selectAll,
85
- selectedBlockIds,
86
- selectedBlockRange,
87
- setAttrs,
88
- setAttrsStep,
89
- setBlockColor,
90
- setBlockType,
91
- setLink,
92
- setMark,
93
- setSelection,
94
- setTextAlign,
95
- startOf,
96
- textSelection,
97
- toMarkdown,
98
- toggleMark,
99
- undo,
100
- unsetLink,
101
- unsetMark,
102
- validateSelection
103
- } from "./chunk-OBMBSU2S.js";
104
- import {
105
- sameValue
106
- } from "./chunk-RJRX34BZ.js";
107
- import {
108
- PALETTE,
109
- SCHEME,
110
- addMark,
111
- alignOrUndefined,
112
- blockById,
113
- blockPlainText,
114
- createBlockCodec,
115
- createDoc,
116
- hasMark,
117
- headingLevel,
118
- inlineLength,
119
- inlineText,
120
- newId,
121
- optionalNumber,
122
- paletteOrUndefined,
123
- parseInline,
124
- requireBlockIndex,
125
- sameItems,
126
- sanitizeAssetUrl,
127
- sanitizeHref,
128
- sliceInline,
129
- specFor,
130
- str,
131
- text
132
- } from "./chunk-4XFXB37X.js";
133
-
134
- // src/canvas/BlockCanvas.tsx
135
- import { forwardRef as forwardRef8, useImperativeHandle as useImperativeHandle2, useMemo as useMemo17, useState as useState19 } from "react";
136
-
137
- // src/blocks/core.ts
138
- import { Code, FileText, Image, MessageSquare, Paperclip } from "lucide-react";
139
-
140
- // src/context.tsx
141
- import * as React from "react";
1
+ import { useQuoinEditor, EditorView, useIsomorphicLayoutEffect, useReadOnly, useEditorState, listen, wholeState, NODE_ENTRY, useBlockDomId, useToggleOpen, ToggleChevron, EditableRegion, drawnBlockCount, isComposingKey, NATIVE_INTERACTION, useRegionDomId, TaskCheckbox, useOrderedNumber, createAutoScroll, domMapOf, dispatchSelection, regionInline, onBlock, hostKey, BlockErrorContext, textDiff, moveToNeighbour, visibleBlockIndexes } from './chunk-IEP7BPFN.js';
2
+ import { defineBlock, devWarn, highlightedLines, blockByType, paletteBlocks, tokenColour, seedData, parsedData } from './chunk-HDJ653LM.js';
3
+ import { createPluginKey, coreExtensions, defineExtension, duplicateBlocks, primaryRegion, regionLength, headBlockId, sameSelection, Transaction, insertBlocksStep, startOf, replaceBlockStep, descendantsEnd, LINE_JOIN, detectMac, selectedBlockIds, blockRangeSelection, runCommands, setSelection, selectedBlockRange, toMarkdown, isCollapsed, createBlock, isParagraph, nodeSelection, setAttrsStep, LINE_SPLIT, validateSelection, endOf, insertBlockAfter, insertText, isTextFlow, markRanges, setTextAlign, orderedRange, unsetLink, textSelection, toggleMark, isActive, setBlockType, getPluginState, rangeContent, unsetMark, setMark, markExtent, setLink, deleteBlocks, setAttrs, HISTORY_GROUP, setBlockColor, removeMarkStep, caretMarks, replaceInlineStep, keyName, normalizeKey, movedBlockIds, moveBlocksUp, moveBlocksDown, selectAll, redo, undo, moveBlocksTo, indent, outdent } from './chunk-L4D23LM2.js';
4
+ import { sameValue } from './chunk-3BXUGX5F.js';
5
+ import { str, blockPlainText, sanitizeHref, inlineText, parseInline, newId, createDoc, sameItems, headingLevel, sanitizeAssetUrl, blockById, sliceInline, specFor, createBlockCodec, hasMark, alignOrUndefined, optionalNumber, requireBlockIndex, SCHEME, inlineLength, paletteOrUndefined, PALETTE, addMark, text } from './chunk-L6OW2FL3.js';
6
+ import * as React7 from 'react';
7
+ import { createContext, forwardRef, useRef, useImperativeHandle, useState, useMemo, useEffect, Fragment as Fragment$1, useContext, useSyncExternalStore, useCallback, useId, createElement } from 'react';
8
+ import { FileText, MessageSquare, Code, Image, Paperclip, CopyPlus, Copy, Link, ArrowUp, ArrowDown, Trash, Keyboard, Plus, GripVertical, Minus, Check, ExternalLink, Unlink, ChevronRightIcon, CircleIcon, ChevronDown, ListCollapse, Heading1, Heading2, Heading3, Baseline, AlignLeft, AlignJustify, AlignRight, AlignCenter, CheckIcon, Pencil, XIcon, Upload, Download, Repeat2, Palette, Droplet, Sticker, FileIcon, FileImage, FileMusic, FilePlay, FileArchive, Subscript, Superscript, Bold, Italic, Underline, Strikethrough, Type, List, ListOrdered, ListTodo, TextQuote, ListIndentIncrease, ListIndentDecrease, Undo2, Redo2 } from 'lucide-react';
9
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
+ import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
11
+ import { clsx } from 'clsx';
12
+ import { Slot } from '@radix-ui/react-slot';
13
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
14
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
15
+ import { createPortal } from 'react-dom';
16
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
142
17
 
143
18
  // src/blocks/file/format-size.ts
144
19
  var UNITS = ["B", "KB", "MB", "GB", "TB"];
@@ -315,6 +190,7 @@ var englishLabels = {
315
190
  selectedContent: "Selected content",
316
191
  editBlock: (label) => `Edit ${label}`,
317
192
  unsupportedBlock: "Unsupported block",
193
+ blockError: "Block could not be drawn",
318
194
  uploading: "Uploading...",
319
195
  uploaded: (name) => `Uploaded ${name}`,
320
196
  uploadFailed: "Upload failed.",
@@ -335,6 +211,9 @@ var englishLabels = {
335
211
  altTextHint: "Required. Describe what the image shows for anyone who cannot see it.",
336
212
  save: "Save",
337
213
  imageNoAlt: "Image, no description",
214
+ decorativeImage: "Decorative image",
215
+ noAltBadge: "No alt text",
216
+ addAltText: "No alt text, add alt text",
338
217
  uploadFile: "Upload file",
339
218
  dropFile: "Or drop or paste a file here.",
340
219
  fileTools: "File tools",
@@ -352,16 +231,13 @@ var englishLabels = {
352
231
  emptyMarkdown: "Empty markdown block",
353
232
  emptyCallout: "Empty callout"
354
233
  };
355
-
356
- // src/context.tsx
357
- import { jsx } from "react/jsx-runtime";
358
- var QuoinContext = React.createContext(null);
234
+ var QuoinContext = React7.createContext(null);
359
235
  function QuoinProvider({
360
236
  value,
361
237
  children
362
238
  }) {
363
239
  const { blockTypes, upload, resolveAssetUrl, onError, highlight, controller = null, labels = englishLabels } = value;
364
- const config = React.useMemo(
240
+ const config = React7.useMemo(
365
241
  () => ({
366
242
  blockTypes,
367
243
  upload,
@@ -378,7 +254,7 @@ function QuoinProvider({
378
254
  return /* @__PURE__ */ jsx(QuoinContext.Provider, { value: config, children });
379
255
  }
380
256
  function useQuoin() {
381
- const config = React.useContext(QuoinContext);
257
+ const config = React7.useContext(QuoinContext);
382
258
  if (!config) throw new Error("useQuoin must be used inside a QuoinProvider.");
383
259
  return config;
384
260
  }
@@ -390,20 +266,16 @@ function useLabels() {
390
266
 
391
267
  // src/blocks/caption-markdown.ts
392
268
  var captionText = (markdown) => inlineText(parseInline(markdown), () => "");
393
-
394
- // src/blocks/code/HighlightOverlay.tsx
395
- import { Fragment, useMemo as useMemo2 } from "react";
396
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
397
269
  function Token({ text: text2, color, className }) {
398
- return /* @__PURE__ */ jsx2("span", { style: { color: tokenColour(color) }, className, children: text2 });
270
+ return /* @__PURE__ */ jsx("span", { style: { color: tokenColour(color) }, className, children: text2 });
399
271
  }
400
272
  function HighlightOverlay({ code, language: language2, drawnRef, ...props }) {
401
273
  const { highlight } = useQuoin();
402
- const lines = useMemo2(() => highlightedLines(highlight, code, language2), [highlight, code, language2]);
274
+ const lines = useMemo(() => highlightedLines(highlight, code, language2), [highlight, code, language2]);
403
275
  return /* @__PURE__ */ jsxs("pre", { ...props, ref: drawnRef, className: "quoin-code-text", children: [
404
- /* @__PURE__ */ jsx2("code", { children: lines === null ? code : lines.map((line, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
276
+ /* @__PURE__ */ jsx("code", { children: lines === null ? code : lines.map((line, index) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
405
277
  index > 0 && "\n",
406
- line.map((token, at) => /* @__PURE__ */ jsx2(Token, { ...token }, at))
278
+ line.map((token, at) => /* @__PURE__ */ jsx(Token, { ...token }, at))
407
279
  ] }, index)) }),
408
280
  "\n"
409
281
  ] });
@@ -426,9 +298,6 @@ function imageSource(attrs, resolveAssetUrl) {
426
298
  const url = str(attrs.url);
427
299
  return url === "" ? assetHref(resolveAssetUrl, str(attrs.storageKey)) : sanitizeHref(url);
428
300
  }
429
-
430
- // src/blocks/previews.tsx
431
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
432
301
  var HINT = "text-sm text-muted-foreground";
433
302
  var TONE = {
434
303
  info: "border-info bg-info/15",
@@ -440,35 +309,35 @@ var TONE = {
440
309
  function MarkdownPreview({ data }) {
441
310
  const labels = useLabels();
442
311
  const markdown = str(data.markdown);
443
- if (markdown.trim() === "") return /* @__PURE__ */ jsx3("p", { className: HINT, children: labels.emptyMarkdown });
444
- return /* @__PURE__ */ jsx3("div", { className: "whitespace-pre-wrap text-base leading-7", children: markdown });
312
+ if (markdown.trim() === "") return /* @__PURE__ */ jsx("p", { className: HINT, children: labels.emptyMarkdown });
313
+ return /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap text-base leading-7", children: markdown });
445
314
  }
446
315
  function CodePreview({ data }) {
447
- return /* @__PURE__ */ jsx3("div", { dir: "ltr", className: "quoin-code quoin-code-scroll pt-3", children: /* @__PURE__ */ jsx3(HighlightOverlay, { code: str(data.code), language: str(data.language) }) });
316
+ return /* @__PURE__ */ jsx("div", { dir: "ltr", className: "quoin-code quoin-code-scroll pt-3", children: /* @__PURE__ */ jsx(HighlightOverlay, { code: str(data.code), language: str(data.language) }) });
448
317
  }
449
318
  function ImagePreview({ data }) {
450
319
  const { resolveAssetUrl, labels } = useQuoin();
451
320
  const src = imageSource(data, resolveAssetUrl);
452
- if (src === null) return /* @__PURE__ */ jsx3("p", { className: HINT, children: labels.emptyImage });
321
+ if (src === null) return /* @__PURE__ */ jsx("p", { className: HINT, children: labels.emptyImage });
453
322
  const caption = captionText(str(data.caption));
454
- return /* @__PURE__ */ jsxs2("figure", { children: [
455
- /* @__PURE__ */ jsx3("img", { src, alt: str(data.alt) || labels.imageNoAlt, className: "max-w-full rounded-md" }),
456
- caption && /* @__PURE__ */ jsx3("figcaption", { className: HINT, children: caption })
323
+ return /* @__PURE__ */ jsxs("figure", { children: [
324
+ /* @__PURE__ */ jsx("img", { src, alt: str(data.alt) || labels.imageNoAlt, className: "max-w-full rounded-md" }),
325
+ caption && /* @__PURE__ */ jsx("figcaption", { className: HINT, children: caption })
457
326
  ] });
458
327
  }
459
328
  function FilePreview({ data }) {
460
329
  const labels = useLabels();
461
330
  const name = str(data.filename);
462
- if (name === "") return /* @__PURE__ */ jsx3("p", { className: HINT, children: labels.emptyFile });
463
- return /* @__PURE__ */ jsx3("p", { className: "text-sm", children: name });
331
+ if (name === "") return /* @__PURE__ */ jsx("p", { className: HINT, children: labels.emptyFile });
332
+ return /* @__PURE__ */ jsx("p", { className: "text-sm", children: name });
464
333
  }
465
334
  function CalloutPreview({ data }) {
466
335
  const labels = useLabels();
467
336
  const body = str(data.body);
468
- if (body.trim() === "") return /* @__PURE__ */ jsx3("p", { className: HINT, children: labels.emptyCallout });
337
+ if (body.trim() === "") return /* @__PURE__ */ jsx("p", { className: HINT, children: labels.emptyCallout });
469
338
  const tone = str(data.tone) || "info";
470
339
  const paint = TONE[tone] ?? "border-border bg-muted/50";
471
- return /* @__PURE__ */ jsx3("div", { "data-tone": tone, className: `rounded-md border-l-4 ${paint} p-3 text-sm`, children: body });
340
+ return /* @__PURE__ */ jsx("div", { "data-tone": tone, className: `rounded-md border-l-4 ${paint} p-3 text-sm`, children: body });
472
341
  }
473
342
 
474
343
  // src/blocks/core.ts
@@ -510,9 +379,6 @@ var coreBlocks = [
510
379
  })
511
380
  ];
512
381
 
513
- // src/blocks/void/use-void-editing.ts
514
- import { createContext as createContext2, useCallback, useContext as useContext2, useEffect, useState } from "react";
515
-
516
382
  // src/blocks/void/select-node.ts
517
383
  function selectNode(controller, blockId) {
518
384
  const { editor } = controller;
@@ -526,9 +392,9 @@ function focusNode(controller, blockId) {
526
392
  }
527
393
 
528
394
  // src/blocks/void/use-void-editing.ts
529
- var VoidEditingContext = createContext2(null);
395
+ var VoidEditingContext = createContext(null);
530
396
  function useVoidEditing(controller, blockId, canEdit = true) {
531
- const voidEditing = useContext2(VoidEditingContext);
397
+ const voidEditing = useContext(VoidEditingContext);
532
398
  const [editing, setEditing] = useState(false);
533
399
  if (editing && !canEdit) setEditing(false);
534
400
  const start = useCallback(() => {
@@ -588,9 +454,6 @@ function createVoidEditing() {
588
454
  };
589
455
  }
590
456
 
591
- // src/gutter/BlockContextMenu.tsx
592
- import { useRef as useRef17 } from "react";
593
-
594
457
  // src/blocks/text/return-focus-to-text.ts
595
458
  function focusBelongsInText(controller, focused) {
596
459
  if (!focused || focused === focused.ownerDocument.body) return true;
@@ -602,9 +465,6 @@ function returnFocusToText(controller) {
602
465
  if (focusBelongsInText(controller, controller.root?.ownerDocument.activeElement)) controller.focus();
603
466
  };
604
467
  }
605
-
606
- // src/canvas/ui-store.ts
607
- import { createContext as createContext3, useContext as useContext3, useSyncExternalStore } from "react";
608
468
  var INITIAL = {
609
469
  hoveredBlock: null,
610
470
  blockMenu: null,
@@ -614,18 +474,18 @@ var INITIAL = {
614
474
  };
615
475
  function createCanvasUiStore() {
616
476
  let state = INITIAL;
617
- const listeners = /* @__PURE__ */ new Set();
477
+ const listeners2 = /* @__PURE__ */ new Set();
618
478
  return {
619
479
  get: () => state,
620
480
  set(patch) {
621
481
  const keys = Object.keys(patch);
622
482
  if (keys.every((key) => Object.is(state[key], patch[key]))) return;
623
483
  state = { ...state, ...patch };
624
- for (const listener of [...listeners]) listener();
484
+ for (const listener of [...listeners2]) listener();
625
485
  },
626
486
  subscribe(listener) {
627
- listeners.add(listener);
628
- return () => void listeners.delete(listener);
487
+ listeners2.add(listener);
488
+ return () => void listeners2.delete(listener);
629
489
  }
630
490
  };
631
491
  }
@@ -633,21 +493,13 @@ function useCanvasUi(store, selector) {
633
493
  const read2 = () => selector(store.get());
634
494
  return useSyncExternalStore(store.subscribe, read2, read2);
635
495
  }
636
- var CanvasUiContext = createContext3(null);
496
+ var CanvasUiContext = createContext(null);
637
497
  var CanvasUiProvider = CanvasUiContext.Provider;
638
498
  function useCanvasUiStore() {
639
- const store = useContext3(CanvasUiContext);
499
+ const store = useContext(CanvasUiContext);
640
500
  if (store === null) throw new Error("useCanvasUiStore must be used inside a BlockCanvas.");
641
501
  return store;
642
502
  }
643
-
644
- // src/ui/context-menu.tsx
645
- import * as React2 from "react";
646
- import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
647
- import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
648
-
649
- // src/ui/cn.ts
650
- import { clsx } from "clsx";
651
503
  var DISPLAY = /* @__PURE__ */ new Set(["block", "inline", "flex", "inline-flex", "grid", "contents", "hidden"]);
652
504
  var FONT_SIZE = /^text-(xs|sm|base|lg|\d?xl)(\/.+)?$/;
653
505
  var TEXT_NOT_COLOR = /^text-(left|center|right|justify|start|end|wrap|nowrap|balance|pretty|ellipsis|clip|shadow-.+|opacity-.+|[[(].*)$/;
@@ -715,20 +567,17 @@ var MENU_SUB_TRIGGER = [
715
567
  var MENU_LABEL = "px-2 py-1.5 text-sm font-medium data-[inset]:pl-8";
716
568
  var MENU_SEPARATOR = "bg-border -mx-1 my-1 h-px";
717
569
  var MENU_SHORTCUT = "text-muted-foreground ml-auto text-xs tracking-widest";
718
-
719
- // src/ui/context-menu.tsx
720
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
721
570
  function ContextMenu({ modal = false, ...props }) {
722
- return /* @__PURE__ */ jsx4(ContextMenuPrimitive.Root, { modal, ...props });
571
+ return /* @__PURE__ */ jsx(ContextMenuPrimitive.Root, { modal, ...props });
723
572
  }
724
573
  function ContextMenuSub(props) {
725
- return /* @__PURE__ */ jsx4(ContextMenuPrimitive.Sub, { ...props });
574
+ return /* @__PURE__ */ jsx(ContextMenuPrimitive.Sub, { ...props });
726
575
  }
727
- var ContextMenuTrigger = /* @__PURE__ */ React2.forwardRef(function ContextMenuTrigger2(props, ref) {
728
- return /* @__PURE__ */ jsx4(ContextMenuPrimitive.Trigger, { ref, "data-slot": "context-menu-trigger", ...props });
576
+ var ContextMenuTrigger = /* @__PURE__ */ React7.forwardRef(function ContextMenuTrigger2(props, ref) {
577
+ return /* @__PURE__ */ jsx(ContextMenuPrimitive.Trigger, { ref, "data-slot": "context-menu-trigger", ...props });
729
578
  });
730
- var ContextMenuContent = /* @__PURE__ */ React2.forwardRef(function ContextMenuContent2({ className, ...props }, ref) {
731
- return /* @__PURE__ */ jsx4(ContextMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx4(
579
+ var ContextMenuContent = /* @__PURE__ */ React7.forwardRef(function ContextMenuContent2({ className, ...props }, ref) {
580
+ return /* @__PURE__ */ jsx(ContextMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
732
581
  ContextMenuPrimitive.Content,
733
582
  {
734
583
  ref,
@@ -738,11 +587,11 @@ var ContextMenuContent = /* @__PURE__ */ React2.forwardRef(function ContextMenuC
738
587
  }
739
588
  ) });
740
589
  });
741
- var ContextMenuGroup = /* @__PURE__ */ React2.forwardRef(function ContextMenuGroup2(props, ref) {
742
- return /* @__PURE__ */ jsx4(ContextMenuPrimitive.Group, { ref, "data-slot": "context-menu-group", ...props });
590
+ var ContextMenuGroup = /* @__PURE__ */ React7.forwardRef(function ContextMenuGroup2(props, ref) {
591
+ return /* @__PURE__ */ jsx(ContextMenuPrimitive.Group, { ref, "data-slot": "context-menu-group", ...props });
743
592
  });
744
- var ContextMenuItem = /* @__PURE__ */ React2.forwardRef(function ContextMenuItem2({ className, inset, ...props }, ref) {
745
- return /* @__PURE__ */ jsx4(
593
+ var ContextMenuItem = /* @__PURE__ */ React7.forwardRef(function ContextMenuItem2({ className, inset, ...props }, ref) {
594
+ return /* @__PURE__ */ jsx(
746
595
  ContextMenuPrimitive.Item,
747
596
  {
748
597
  ref,
@@ -753,11 +602,11 @@ var ContextMenuItem = /* @__PURE__ */ React2.forwardRef(function ContextMenuItem
753
602
  }
754
603
  );
755
604
  });
756
- var ContextMenuRadioGroup = /* @__PURE__ */ React2.forwardRef(function ContextMenuRadioGroup2(props, ref) {
757
- return /* @__PURE__ */ jsx4(ContextMenuPrimitive.RadioGroup, { ref, "data-slot": "context-menu-radio-group", ...props });
605
+ var ContextMenuRadioGroup = /* @__PURE__ */ React7.forwardRef(function ContextMenuRadioGroup2(props, ref) {
606
+ return /* @__PURE__ */ jsx(ContextMenuPrimitive.RadioGroup, { ref, "data-slot": "context-menu-radio-group", ...props });
758
607
  });
759
- var ContextMenuRadioItem = /* @__PURE__ */ React2.forwardRef(function ContextMenuRadioItem2({ className, children, indicator = /* @__PURE__ */ jsx4(CircleIcon, { className: "size-2 fill-current" }), ...props }, ref) {
760
- return /* @__PURE__ */ jsxs3(
608
+ var ContextMenuRadioItem = /* @__PURE__ */ React7.forwardRef(function ContextMenuRadioItem2({ className, children, indicator = /* @__PURE__ */ jsx(CircleIcon, { className: "size-2 fill-current" }), ...props }, ref) {
609
+ return /* @__PURE__ */ jsxs(
761
610
  ContextMenuPrimitive.RadioItem,
762
611
  {
763
612
  ref,
@@ -765,14 +614,14 @@ var ContextMenuRadioItem = /* @__PURE__ */ React2.forwardRef(function ContextMen
765
614
  className: cn(MENU_CHECKABLE_ITEM, className),
766
615
  ...props,
767
616
  children: [
768
- /* @__PURE__ */ jsx4("span", { className: MENU_ITEM_INDICATOR, children: /* @__PURE__ */ jsx4(ContextMenuPrimitive.ItemIndicator, { children: indicator }) }),
617
+ /* @__PURE__ */ jsx("span", { className: MENU_ITEM_INDICATOR, children: /* @__PURE__ */ jsx(ContextMenuPrimitive.ItemIndicator, { children: indicator }) }),
769
618
  children
770
619
  ]
771
620
  }
772
621
  );
773
622
  });
774
- var ContextMenuLabel = /* @__PURE__ */ React2.forwardRef(function ContextMenuLabel2({ className, inset, ...props }, ref) {
775
- return /* @__PURE__ */ jsx4(
623
+ var ContextMenuLabel = /* @__PURE__ */ React7.forwardRef(function ContextMenuLabel2({ className, inset, ...props }, ref) {
624
+ return /* @__PURE__ */ jsx(
776
625
  ContextMenuPrimitive.Label,
777
626
  {
778
627
  ref,
@@ -783,8 +632,8 @@ var ContextMenuLabel = /* @__PURE__ */ React2.forwardRef(function ContextMenuLab
783
632
  }
784
633
  );
785
634
  });
786
- var ContextMenuSeparator = /* @__PURE__ */ React2.forwardRef(function ContextMenuSeparator2({ className, ...props }, ref) {
787
- return /* @__PURE__ */ jsx4(
635
+ var ContextMenuSeparator = /* @__PURE__ */ React7.forwardRef(function ContextMenuSeparator2({ className, ...props }, ref) {
636
+ return /* @__PURE__ */ jsx(
788
637
  ContextMenuPrimitive.Separator,
789
638
  {
790
639
  ref,
@@ -794,11 +643,11 @@ var ContextMenuSeparator = /* @__PURE__ */ React2.forwardRef(function ContextMen
794
643
  }
795
644
  );
796
645
  });
797
- var ContextMenuShortcut = /* @__PURE__ */ React2.forwardRef(function ContextMenuShortcut2({ className, ...props }, ref) {
798
- return /* @__PURE__ */ jsx4("span", { ref, "data-slot": "context-menu-shortcut", className: cn(MENU_SHORTCUT, className), ...props });
646
+ var ContextMenuShortcut = /* @__PURE__ */ React7.forwardRef(function ContextMenuShortcut2({ className, ...props }, ref) {
647
+ return /* @__PURE__ */ jsx("span", { ref, "data-slot": "context-menu-shortcut", className: cn(MENU_SHORTCUT, className), ...props });
799
648
  });
800
- var ContextMenuSubTrigger = /* @__PURE__ */ React2.forwardRef(function ContextMenuSubTrigger2({ className, inset, children, ...props }, ref) {
801
- return /* @__PURE__ */ jsxs3(
649
+ var ContextMenuSubTrigger = /* @__PURE__ */ React7.forwardRef(function ContextMenuSubTrigger2({ className, inset, children, ...props }, ref) {
650
+ return /* @__PURE__ */ jsxs(
802
651
  ContextMenuPrimitive.SubTrigger,
803
652
  {
804
653
  ref,
@@ -808,13 +657,13 @@ var ContextMenuSubTrigger = /* @__PURE__ */ React2.forwardRef(function ContextMe
808
657
  ...props,
809
658
  children: [
810
659
  children,
811
- /* @__PURE__ */ jsx4(ChevronRightIcon, { className: "ml-auto size-4" })
660
+ /* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto size-4" })
812
661
  ]
813
662
  }
814
663
  );
815
664
  });
816
- var ContextMenuSubContent = /* @__PURE__ */ React2.forwardRef(function ContextMenuSubContent2({ className, ...props }, ref) {
817
- return /* @__PURE__ */ jsx4(
665
+ var ContextMenuSubContent = /* @__PURE__ */ React7.forwardRef(function ContextMenuSubContent2({ className, ...props }, ref) {
666
+ return /* @__PURE__ */ jsx(
818
667
  ContextMenuPrimitive.SubContent,
819
668
  {
820
669
  ref,
@@ -825,9 +674,6 @@ var ContextMenuSubContent = /* @__PURE__ */ React2.forwardRef(function ContextMe
825
674
  );
826
675
  });
827
676
 
828
- // src/gutter/block-menu-items.ts
829
- import { ArrowDown, ArrowUp, Copy, CopyPlus, Link, Trash } from "lucide-react";
830
-
831
677
  // src/gutter/copy-text.ts
832
678
  function copyThroughTextArea(text2, doc) {
833
679
  const previous = doc.activeElement instanceof HTMLElement ? doc.activeElement : null;
@@ -984,12 +830,6 @@ function closeBlockMenu(store) {
984
830
  store.set({ blockMenu: null, hoveredBlock: null });
985
831
  }
986
832
 
987
- // src/gutter/BlockMenuItems.tsx
988
- import { Fragment as Fragment6 } from "react";
989
-
990
- // src/gutter/CalloutMenus.tsx
991
- import { CheckIcon as CheckIcon2, Droplet, Sticker } from "lucide-react";
992
-
993
833
  // src/blocks/text/callout-tone.ts
994
834
  var CALLOUT_TONES = ["info", "tip", "success", "warning", "danger"];
995
835
  var CALLOUT_ICONS = ["\u{1F4A1}", "\u26A0\uFE0F", "\u2705", "\u2757", "\u2139\uFE0F", "\u{1F4CC}"];
@@ -1006,15 +846,9 @@ function calloutTone(value) {
1006
846
  function calloutIcon(attrs, tone) {
1007
847
  return typeof attrs.icon === "string" && attrs.icon !== "" ? attrs.icon : TONE_ICONS[tone];
1008
848
  }
1009
-
1010
- // src/gutter/MenuIcon.tsx
1011
- import { jsx as jsx5 } from "react/jsx-runtime";
1012
849
  function MenuIcon({ icon: Icon }) {
1013
- return /* @__PURE__ */ jsx5("span", { "aria-hidden": "true", className: "flex shrink-0", children: /* @__PURE__ */ jsx5(Icon, { className: "size-4" }) });
850
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "flex shrink-0", children: /* @__PURE__ */ jsx(Icon, { className: "size-4" }) });
1014
851
  }
1015
-
1016
- // src/gutter/CalloutMenus.tsx
1017
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1018
852
  var sharedTone = (blocks) => {
1019
853
  const tones = new Set(blocks.map((block) => calloutTone(block.attrs.tone)));
1020
854
  return tones.size === 1 ? [...tones][0] : "";
@@ -1023,51 +857,46 @@ function CalloutMenus({ kit, controller, blocks }) {
1023
857
  const labels = useLabels();
1024
858
  const blockIds = blocks.map((block) => block.id);
1025
859
  const apply = (patch) => runOnBlocks(controller, blockIds, setAttrs(patch));
1026
- return /* @__PURE__ */ jsxs4(Fragment2, { children: [
1027
- /* @__PURE__ */ jsxs4(kit.Sub, { children: [
1028
- /* @__PURE__ */ jsxs4(kit.SubTrigger, { children: [
1029
- /* @__PURE__ */ jsx6(MenuIcon, { icon: Droplet }),
860
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
861
+ /* @__PURE__ */ jsxs(kit.Sub, { children: [
862
+ /* @__PURE__ */ jsxs(kit.SubTrigger, { children: [
863
+ /* @__PURE__ */ jsx(MenuIcon, { icon: Droplet }),
1030
864
  labels.tone
1031
865
  ] }),
1032
- /* @__PURE__ */ jsx6(kit.SubContent, { children: /* @__PURE__ */ jsx6(kit.RadioGroup, { value: sharedTone(blocks), onValueChange: (tone) => apply({ tone }), children: CALLOUT_TONES.map((tone) => /* @__PURE__ */ jsx6(kit.RadioItem, { value: tone, indicator: /* @__PURE__ */ jsx6(CheckIcon2, { className: "size-4" }), children: labels.calloutTones[tone] }, tone)) }) })
866
+ /* @__PURE__ */ jsx(kit.SubContent, { children: /* @__PURE__ */ jsx(kit.RadioGroup, { value: sharedTone(blocks), onValueChange: (tone) => apply({ tone }), children: CALLOUT_TONES.map((tone) => /* @__PURE__ */ jsx(kit.RadioItem, { value: tone, indicator: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }), children: labels.calloutTones[tone] }, tone)) }) })
1033
867
  ] }),
1034
- /* @__PURE__ */ jsxs4(kit.Sub, { children: [
1035
- /* @__PURE__ */ jsxs4(kit.SubTrigger, { children: [
1036
- /* @__PURE__ */ jsx6(MenuIcon, { icon: Sticker }),
868
+ /* @__PURE__ */ jsxs(kit.Sub, { children: [
869
+ /* @__PURE__ */ jsxs(kit.SubTrigger, { children: [
870
+ /* @__PURE__ */ jsx(MenuIcon, { icon: Sticker }),
1037
871
  labels.icon
1038
872
  ] }),
1039
- /* @__PURE__ */ jsx6(kit.SubContent, { className: "min-w-0", children: CALLOUT_ICONS.map((icon) => /* @__PURE__ */ jsx6(kit.Item, { className: "justify-center text-base", onSelect: () => apply({ icon }), children: icon }, icon)) })
873
+ /* @__PURE__ */ jsx(kit.SubContent, { className: "min-w-0", children: CALLOUT_ICONS.map((icon) => /* @__PURE__ */ jsx(kit.Item, { className: "justify-center text-base", onSelect: () => apply({ icon }), children: icon }, icon)) })
1040
874
  ] })
1041
875
  ] });
1042
876
  }
1043
-
1044
- // src/gutter/ColorMenu.tsx
1045
- import { useId } from "react";
1046
- import { CheckIcon as CheckIcon3, Palette } from "lucide-react";
1047
- import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1048
877
  function sharedColor(blocks, key) {
1049
878
  const coloured = blocks.filter((block) => block.type === "MARKDOWN");
1050
879
  const colors = new Set(coloured.map((block) => paletteOrUndefined(block.attrs[key]) ?? "default"));
1051
880
  return colors.size === 1 ? [...colors][0] : "";
1052
881
  }
1053
882
  var swatches = {
1054
- color: (name) => /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", "data-color": name, className: "w-4 text-center font-medium", children: "A" }),
1055
- background: (name) => /* @__PURE__ */ jsx7("span", { "aria-hidden": "true", "data-bg": name, className: "size-4 rounded-sm border border-border" })
883
+ color: (name) => /* @__PURE__ */ jsx("span", { "aria-hidden": "true", "data-color": name, className: "w-4 text-center font-medium", children: "A" }),
884
+ background: (name) => /* @__PURE__ */ jsx("span", { "aria-hidden": "true", "data-bg": name, className: "size-4 rounded-sm border border-border" })
1056
885
  };
1057
886
  function ColorGroups({ kit, value, onPick }) {
1058
887
  const labels = useLabels();
1059
888
  const textTitle = useId();
1060
889
  const backgroundTitle = useId();
1061
- const group = (key, title, titleId) => /* @__PURE__ */ jsxs5(Fragment3, { children: [
1062
- /* @__PURE__ */ jsx7(kit.Label, { id: titleId, children: title }),
1063
- /* @__PURE__ */ jsx7(kit.RadioGroup, { "aria-labelledby": titleId, value: value[key], onValueChange: (name) => onPick(key, name), children: PALETTE.map((name) => /* @__PURE__ */ jsxs5(kit.RadioItem, { value: name, indicator: /* @__PURE__ */ jsx7(CheckIcon3, { className: "size-4" }), children: [
890
+ const group = (key, title, titleId) => /* @__PURE__ */ jsxs(Fragment, { children: [
891
+ /* @__PURE__ */ jsx(kit.Label, { id: titleId, children: title }),
892
+ /* @__PURE__ */ jsx(kit.RadioGroup, { "aria-labelledby": titleId, value: value[key], onValueChange: (name) => onPick(key, name), children: PALETTE.map((name) => /* @__PURE__ */ jsxs(kit.RadioItem, { value: name, indicator: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }), children: [
1064
893
  swatches[key](name),
1065
894
  labels.colors[name]
1066
895
  ] }, name)) })
1067
896
  ] });
1068
- return /* @__PURE__ */ jsxs5(Fragment3, { children: [
897
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1069
898
  group("color", labels.textColor, textTitle),
1070
- /* @__PURE__ */ jsx7(kit.Separator, {}),
899
+ /* @__PURE__ */ jsx(kit.Separator, {}),
1071
900
  group("background", labels.backgroundColor, backgroundTitle)
1072
901
  ] });
1073
902
  }
@@ -1076,12 +905,12 @@ function ColorMenu({ kit, controller, blocks }) {
1076
905
  const blockIds = blocks.map((block) => block.id);
1077
906
  const value = { color: sharedColor(blocks, "color"), background: sharedColor(blocks, "background") };
1078
907
  const pick = (key, name) => runOnBlocks(controller, blockIds, setBlockColor({ [key]: name === "default" ? null : name }));
1079
- return /* @__PURE__ */ jsxs5(kit.Sub, { children: [
1080
- /* @__PURE__ */ jsxs5(kit.SubTrigger, { children: [
1081
- /* @__PURE__ */ jsx7(MenuIcon, { icon: Palette }),
908
+ return /* @__PURE__ */ jsxs(kit.Sub, { children: [
909
+ /* @__PURE__ */ jsxs(kit.SubTrigger, { children: [
910
+ /* @__PURE__ */ jsx(MenuIcon, { icon: Palette }),
1082
911
  labels.color
1083
912
  ] }),
1084
- /* @__PURE__ */ jsx7(kit.SubContent, { children: /* @__PURE__ */ jsx7(ColorGroups, { kit, value, onPick: pick }) })
913
+ /* @__PURE__ */ jsx(kit.SubContent, { children: /* @__PURE__ */ jsx(ColorGroups, { kit, value, onPick: pick }) })
1085
914
  ] });
1086
915
  }
1087
916
 
@@ -1126,12 +955,6 @@ function shortcutHint(key, isMac, labels) {
1126
955
  return { text: formatShortcut(key, { isMac, labels }), aria };
1127
956
  }
1128
957
 
1129
- // src/gutter/TurnIntoMenu.tsx
1130
- import { Repeat2 } from "lucide-react";
1131
-
1132
- // src/blocks/code/CodeBlock.tsx
1133
- import { useRef as useRef3 } from "react";
1134
-
1135
958
  // src/blocks/code/code-languages.ts
1136
959
  var language = (name, id = name.toLowerCase(), ...aliases) => ({ id, name, aliases });
1137
960
  var CODE_LANGUAGES = [
@@ -1191,9 +1014,6 @@ function languageOptions(query, plainText) {
1191
1014
  return [{ id: "", name: plainText }, ...CODE_LANGUAGES].filter(matches);
1192
1015
  }
1193
1016
 
1194
- // src/blocks/code/CodeEditor.tsx
1195
- import { useCallback as useCallback2, useEffect as useEffect3, useRef } from "react";
1196
-
1197
1017
  // src/blocks/insert-blocks.ts
1198
1018
  var isEmptyParagraph = (schema, block) => isParagraph(block) && regionLength(block, primaryRegion(schema, block) ?? "") === 0;
1199
1019
  function fresh(schema, { id, type, attrs, regions }, indent3) {
@@ -1424,9 +1244,6 @@ function runCodeAction(action, context) {
1424
1244
  }
1425
1245
  }
1426
1246
 
1427
- // src/blocks/code/use-type-into-code.ts
1428
- import { useEffect as useEffect2 } from "react";
1429
-
1430
1247
  // src/view/input/intercept-keys.ts
1431
1248
  function interceptKeys(controller, intercept) {
1432
1249
  controller.keyInterceptors.add(intercept);
@@ -1435,7 +1252,7 @@ function interceptKeys(controller, intercept) {
1435
1252
 
1436
1253
  // src/blocks/code/use-type-into-code.ts
1437
1254
  function useTypeIntoCode(controller, blockId, field, edit2) {
1438
- useEffect2(() => {
1255
+ useEffect(() => {
1439
1256
  const typeInto = (event) => {
1440
1257
  const area = field.current;
1441
1258
  const { selection } = controller.editor.state;
@@ -1450,9 +1267,6 @@ function useTypeIntoCode(controller, blockId, field, edit2) {
1450
1267
  return interceptKeys(controller, typeInto);
1451
1268
  }, [controller, blockId, field, edit2]);
1452
1269
  }
1453
-
1454
- // src/blocks/code/CodeEditor.tsx
1455
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1456
1270
  var sessions = 0;
1457
1271
  function CodeEditor({ block, controller, field, focusControls }) {
1458
1272
  const labels = useLabels();
@@ -1461,12 +1275,12 @@ function CodeEditor({ block, controller, field, focusControls }) {
1461
1275
  const mark = useRef(null);
1462
1276
  const { editing, stop } = useVoidEditing(controller, block.id);
1463
1277
  const blockId = block.id;
1464
- const reveal = useCallback2(() => {
1278
+ const reveal = useCallback(() => {
1465
1279
  if (field.current !== null && drawn.current !== null && mark.current !== null) {
1466
1280
  revealCaret(field.current, drawn.current, mark.current);
1467
1281
  }
1468
1282
  }, [field]);
1469
- useEffect3(() => {
1283
+ useEffect(() => {
1470
1284
  const area = field.current;
1471
1285
  if (!editing || area === null) return;
1472
1286
  area.focus();
@@ -1474,7 +1288,7 @@ function CodeEditor({ block, controller, field, focusControls }) {
1474
1288
  reveal();
1475
1289
  stop();
1476
1290
  }, [editing, stop, field, reveal]);
1477
- const edit2 = useCallback2(
1291
+ const edit2 = useCallback(
1478
1292
  (next) => {
1479
1293
  const area = field.current;
1480
1294
  if (area === null) return;
@@ -1490,8 +1304,8 @@ function CodeEditor({ block, controller, field, focusControls }) {
1490
1304
  const action = codeKeyAction(event, fieldOf(area), controller.isMac);
1491
1305
  if (action !== null && runCodeAction(action, { controller, blockId, area, edit: edit2, focusControls })) event.preventDefault();
1492
1306
  };
1493
- return /* @__PURE__ */ jsx8("div", { ...{ [NATIVE_INTERACTION]: "" }, dir: "ltr", className: "quoin-code-scroll", children: /* @__PURE__ */ jsxs6("div", { className: "quoin-code-lines", children: [
1494
- /* @__PURE__ */ jsx8(
1307
+ return /* @__PURE__ */ jsx("div", { ...{ [NATIVE_INTERACTION]: "" }, dir: "ltr", className: "quoin-code-scroll", children: /* @__PURE__ */ jsxs("div", { className: "quoin-code-lines", children: [
1308
+ /* @__PURE__ */ jsx(
1495
1309
  HighlightOverlay,
1496
1310
  {
1497
1311
  "aria-hidden": "true",
@@ -1500,8 +1314,8 @@ function CodeEditor({ block, controller, field, focusControls }) {
1500
1314
  language: str(block.attrs.language)
1501
1315
  }
1502
1316
  ),
1503
- /* @__PURE__ */ jsx8("span", { ref: mark, "aria-hidden": "true", className: "quoin-code-caret" }),
1504
- /* @__PURE__ */ jsx8(
1317
+ /* @__PURE__ */ jsx("span", { ref: mark, "aria-hidden": "true", className: "quoin-code-caret" }),
1318
+ /* @__PURE__ */ jsx(
1505
1319
  "textarea",
1506
1320
  {
1507
1321
  ref: field,
@@ -1526,15 +1340,6 @@ function CodeEditor({ block, controller, field, focusControls }) {
1526
1340
  )
1527
1341
  ] }) });
1528
1342
  }
1529
-
1530
- // src/blocks/code/CopyCodeButton.tsx
1531
- import { useEffect as useEffect4, useState as useState2 } from "react";
1532
- import { Check, Copy as Copy2 } from "lucide-react";
1533
-
1534
- // src/ui/button.tsx
1535
- import * as React3 from "react";
1536
- import { Slot } from "@radix-ui/react-slot";
1537
- import { jsx as jsx9 } from "react/jsx-runtime";
1538
1343
  var BASE = [
1539
1344
  "inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,background-color,border-color,box-shadow,opacity] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 shrink-0",
1540
1345
  FOCUS_RING
@@ -1552,9 +1357,9 @@ var SIZES = {
1552
1357
  "icon-sm": `size-8 ${SQUARE_TAP_TARGET_FLOOR}`
1553
1358
  };
1554
1359
  var buttonVariants = ({ variant = "default", size = "default", className }) => cn(BASE, variant && VARIANTS[variant], size && SIZES[size], className);
1555
- var Button = React3.forwardRef(function Button2({ className, variant = "default", size = "default", asChild = false, ...props }, ref) {
1360
+ var Button = React7.forwardRef(function Button2({ className, variant = "default", size = "default", asChild = false, ...props }, ref) {
1556
1361
  const Comp = asChild ? Slot : "button";
1557
- return /* @__PURE__ */ jsx9(
1362
+ return /* @__PURE__ */ jsx(
1558
1363
  Comp,
1559
1364
  {
1560
1365
  ref,
@@ -1566,15 +1371,12 @@ var Button = React3.forwardRef(function Button2({ className, variant = "default"
1566
1371
  }
1567
1372
  );
1568
1373
  });
1569
-
1570
- // src/blocks/code/CopyCodeButton.tsx
1571
- import { jsx as jsx10 } from "react/jsx-runtime";
1572
1374
  var COPIED_FOR_MS = 1500;
1573
1375
  function CopyCodeButton({ code, controller }) {
1574
1376
  const labels = useLabels();
1575
1377
  const readOnly = useReadOnly(controller);
1576
- const [copied, setCopied] = useState2(false);
1577
- useEffect4(() => {
1378
+ const [copied, setCopied] = useState(false);
1379
+ useEffect(() => {
1578
1380
  if (!copied) return;
1579
1381
  const timer = setTimeout(() => setCopied(false), COPIED_FOR_MS);
1580
1382
  return () => clearTimeout(timer);
@@ -1584,8 +1386,8 @@ function CopyCodeButton({ code, controller }) {
1584
1386
  setCopied(true);
1585
1387
  controller.announce(labels.copied);
1586
1388
  };
1587
- const Icon = copied ? Check : Copy2;
1588
- return /* @__PURE__ */ jsx10(
1389
+ const Icon = copied ? Check : Copy;
1390
+ return /* @__PURE__ */ jsx(
1589
1391
  Button,
1590
1392
  {
1591
1393
  type: "button",
@@ -1595,21 +1397,15 @@ function CopyCodeButton({ code, controller }) {
1595
1397
  "aria-label": labels.copyCode,
1596
1398
  className: "quoin-code-control",
1597
1399
  onClick: () => void copy(),
1598
- children: /* @__PURE__ */ jsx10(Icon, { "aria-hidden": "true" })
1400
+ children: /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" })
1599
1401
  }
1600
1402
  );
1601
1403
  }
1602
1404
 
1603
- // src/blocks/code/LanguageCombobox.tsx
1604
- import { useId as useId2, useRef as useRef2, useState as useState3 } from "react";
1605
-
1606
1405
  // src/menus/floating/keep-focus.ts
1607
1406
  function keepFocus(event) {
1608
1407
  if (!("pointerType" in event) || event.pointerType !== "touch") event.preventDefault();
1609
1408
  }
1610
-
1611
- // src/menus/suggestion/SuggestionOption.tsx
1612
- import { jsx as jsx11 } from "react/jsx-runtime";
1613
1409
  var OPTION = cn(
1614
1410
  "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm",
1615
1411
  "data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground",
@@ -1617,7 +1413,7 @@ var OPTION = cn(
1617
1413
  TAP_TARGET_FLOOR
1618
1414
  );
1619
1415
  function SuggestionOption({ id, active, onHighlight, onChoose, children }) {
1620
- return /* @__PURE__ */ jsx11(
1416
+ return /* @__PURE__ */ jsx(
1621
1417
  "div",
1622
1418
  {
1623
1419
  role: "option",
@@ -1633,19 +1429,14 @@ function SuggestionOption({ id, active, onHighlight, onChoose, children }) {
1633
1429
  }
1634
1430
  );
1635
1431
  }
1636
-
1637
- // src/ui/popover.tsx
1638
- import * as React4 from "react";
1639
- import * as PopoverPrimitive from "@radix-ui/react-popover";
1640
- import { jsx as jsx12 } from "react/jsx-runtime";
1641
1432
  function Popover(props) {
1642
- return /* @__PURE__ */ jsx12(PopoverPrimitive.Root, { ...props });
1433
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { ...props });
1643
1434
  }
1644
- var PopoverAnchor = /* @__PURE__ */ React4.forwardRef(function PopoverAnchor2(props, ref) {
1645
- return /* @__PURE__ */ jsx12(PopoverPrimitive.Anchor, { ref, "data-slot": "popover-anchor", ...props });
1435
+ var PopoverAnchor = /* @__PURE__ */ React7.forwardRef(function PopoverAnchor2(props, ref) {
1436
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Anchor, { ref, "data-slot": "popover-anchor", ...props });
1646
1437
  });
1647
- var PopoverContent = /* @__PURE__ */ React4.forwardRef(function PopoverContent2({ className, align = "center", sideOffset = 4, ...props }, ref) {
1648
- return /* @__PURE__ */ jsx12(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx12(
1438
+ var PopoverContent = /* @__PURE__ */ React7.forwardRef(function PopoverContent2({ className, align = "center", sideOffset = 4, ...props }, ref) {
1439
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
1649
1440
  PopoverPrimitive.Content,
1650
1441
  {
1651
1442
  ref,
@@ -1668,20 +1459,17 @@ var preventDefault = (event) => event.preventDefault();
1668
1459
  function setBlockAttrs(controller, blockId, patch) {
1669
1460
  if (!controller.readOnly) controller.run(onBlock(blockId, setAttrs(patch)));
1670
1461
  }
1671
-
1672
- // src/blocks/code/LanguageCombobox.tsx
1673
- import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
1674
1462
  var FIELD = `quoin-code-language quoin-code-control ${FOCUS_RING}`;
1675
1463
  var CONTENT = `${MENU_CONTENT} flex max-h-64 w-48 flex-col overflow-y-hidden`;
1676
1464
  function LanguageCombobox({ blockId, controller, language: language2, field, onDone }) {
1677
1465
  const labels = useLabels();
1678
- const listboxId = useId2();
1679
- const list = useRef2(null);
1680
- const settled = useRef2(false);
1681
- const focusedByPress = useRef2(false);
1466
+ const listboxId = useId();
1467
+ const list = useRef(null);
1468
+ const settled = useRef(false);
1469
+ const focusedByPress = useRef(false);
1682
1470
  const shown = languageName(language2) ?? language2;
1683
- const [draft, setDraft] = useState3(null);
1684
- const [active, setActive] = useState3(-1);
1471
+ const [draft, setDraft] = useState(null);
1472
+ const [active, setActive] = useState(-1);
1685
1473
  const options = draft === null ? [] : languageOptions(draft === shown ? "" : draft, labels.plainText);
1686
1474
  const open = options.length > 0;
1687
1475
  const optionId = (index) => `${listboxId}-${index}`;
@@ -1721,8 +1509,8 @@ function LanguageCombobox({ blockId, controller, language: language2, field, onD
1721
1509
  finish(event.key === "Enter" ? commit : close);
1722
1510
  }
1723
1511
  };
1724
- return /* @__PURE__ */ jsxs7(Popover, { open, children: [
1725
- /* @__PURE__ */ jsx13(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsx13(
1512
+ return /* @__PURE__ */ jsxs(Popover, { open, children: [
1513
+ /* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsx(
1726
1514
  "input",
1727
1515
  {
1728
1516
  ref: field,
@@ -1760,7 +1548,7 @@ function LanguageCombobox({ blockId, controller, language: language2, field, onD
1760
1548
  onKeyDown
1761
1549
  }
1762
1550
  ) }),
1763
- /* @__PURE__ */ jsx13(
1551
+ /* @__PURE__ */ jsx(
1764
1552
  PopoverContent,
1765
1553
  {
1766
1554
  role: void 0,
@@ -1768,7 +1556,7 @@ function LanguageCombobox({ blockId, controller, language: language2, field, onD
1768
1556
  className: CONTENT,
1769
1557
  onOpenAutoFocus: preventDefault,
1770
1558
  onCloseAutoFocus: preventDefault,
1771
- children: /* @__PURE__ */ jsx13("div", { ref: list, role: "listbox", id: listboxId, "aria-label": labels.codeLanguage, className: "min-h-0 overflow-y-auto", children: options.map((option, index) => /* @__PURE__ */ jsx13(
1559
+ children: /* @__PURE__ */ jsx("div", { ref: list, role: "listbox", id: listboxId, "aria-label": labels.codeLanguage, className: "min-h-0 overflow-y-auto", children: options.map((option, index) => /* @__PURE__ */ jsx(
1772
1560
  SuggestionOption,
1773
1561
  {
1774
1562
  id: optionId(index),
@@ -1783,20 +1571,17 @@ function LanguageCombobox({ blockId, controller, language: language2, field, onD
1783
1571
  )
1784
1572
  ] });
1785
1573
  }
1786
-
1787
- // src/blocks/code/CodeBlock.tsx
1788
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
1789
1574
  var CodeBlock = ({ block, controller }) => {
1790
1575
  const labels = useLabels();
1791
1576
  const readOnly = useReadOnly(controller);
1792
- const languageField = useRef3(null);
1793
- const codeField = useRef3(null);
1577
+ const languageField = useRef(null);
1578
+ const codeField = useRef(null);
1794
1579
  const code = str(block.attrs.code);
1795
1580
  const language2 = str(block.attrs.language);
1796
1581
  const name = languageName(language2) ?? language2;
1797
- return /* @__PURE__ */ jsxs8("div", { role: "group", "aria-label": labels.blockNames.code, contentEditable: false, className: "quoin-code", children: [
1798
- /* @__PURE__ */ jsxs8("div", { className: "quoin-code-header", children: [
1799
- readOnly ? /* @__PURE__ */ jsx14("span", { className: "quoin-code-language quoin-code-control", children: name || labels.plainText }) : /* @__PURE__ */ jsx14(
1582
+ return /* @__PURE__ */ jsxs("div", { role: "group", "aria-label": labels.blockNames.code, contentEditable: false, className: "quoin-code", children: [
1583
+ /* @__PURE__ */ jsxs("div", { className: "quoin-code-header", children: [
1584
+ readOnly ? /* @__PURE__ */ jsx("span", { className: "quoin-code-language quoin-code-control", children: name || labels.plainText }) : /* @__PURE__ */ jsx(
1800
1585
  LanguageCombobox,
1801
1586
  {
1802
1587
  blockId: block.id,
@@ -1806,9 +1591,9 @@ var CodeBlock = ({ block, controller }) => {
1806
1591
  onDone: () => codeField.current?.focus()
1807
1592
  }
1808
1593
  ),
1809
- /* @__PURE__ */ jsx14(CopyCodeButton, { code, controller })
1594
+ /* @__PURE__ */ jsx(CopyCodeButton, { code, controller })
1810
1595
  ] }),
1811
- readOnly ? /* @__PURE__ */ jsx14("div", { dir: "ltr", role: "region", "aria-label": name || labels.codeText, tabIndex: 0, className: `quoin-code-scroll ${FOCUS_RING}`, children: /* @__PURE__ */ jsx14(HighlightOverlay, { code, language: language2 }) }) : /* @__PURE__ */ jsx14(
1596
+ readOnly ? /* @__PURE__ */ jsx("div", { dir: "ltr", role: "region", "aria-label": name || labels.codeText, tabIndex: 0, className: `quoin-code-scroll ${FOCUS_RING}`, children: /* @__PURE__ */ jsx(HighlightOverlay, { code, language: language2 }) }) : /* @__PURE__ */ jsx(
1812
1597
  CodeEditor,
1813
1598
  {
1814
1599
  block,
@@ -1819,32 +1604,21 @@ var CodeBlock = ({ block, controller }) => {
1819
1604
  )
1820
1605
  ] });
1821
1606
  };
1822
-
1823
- // src/blocks/file/FileBlock.tsx
1824
- import { useRef as useRef8 } from "react";
1825
-
1826
- // src/blocks/upload/UploadArea.tsx
1827
- import { useEffect as useEffect6, useRef as useRef6 } from "react";
1828
-
1829
- // src/upload/FilePickerButton.tsx
1830
- import * as React5 from "react";
1831
- import { Upload } from "lucide-react";
1832
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1833
1607
  function FilePickerButton({ label, accept, disabled, busy = false, onPick }) {
1834
- const inputRef = React5.useRef(null);
1835
- const restoreFocus = React5.useRef(false);
1836
- React5.useEffect(() => {
1608
+ const inputRef = React7.useRef(null);
1609
+ const restoreFocus = React7.useRef(false);
1610
+ React7.useEffect(() => {
1837
1611
  if (disabled || !restoreFocus.current) return;
1838
1612
  restoreFocus.current = false;
1839
1613
  const { activeElement } = document;
1840
1614
  if (activeElement === null || activeElement === document.body) inputRef.current?.focus();
1841
1615
  }, [disabled]);
1842
- return /* @__PURE__ */ jsxs9("span", { className: "relative inline-flex rounded-md has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-[var(--quoin-ring)]", children: [
1843
- /* @__PURE__ */ jsx15(Button, { asChild: true, variant: "outline", size: "sm", children: /* @__PURE__ */ jsxs9("span", { "aria-hidden": "true", className: disabled || busy ? "pointer-events-none opacity-50" : void 0, children: [
1844
- /* @__PURE__ */ jsx15(Upload, { "aria-hidden": "true" }),
1616
+ return /* @__PURE__ */ jsxs("span", { className: "relative inline-flex rounded-md has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-[var(--quoin-ring)]", children: [
1617
+ /* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", size: "sm", children: /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: disabled || busy ? "pointer-events-none opacity-50" : void 0, children: [
1618
+ /* @__PURE__ */ jsx(Upload, { "aria-hidden": "true" }),
1845
1619
  label
1846
1620
  ] }) }),
1847
- /* @__PURE__ */ jsx15(
1621
+ /* @__PURE__ */ jsx(
1848
1622
  "input",
1849
1623
  {
1850
1624
  ref: inputRef,
@@ -1913,15 +1687,12 @@ function selectHandlers(controller, blockId, root, onSelect) {
1913
1687
  }
1914
1688
  };
1915
1689
  }
1916
-
1917
- // src/blocks/upload/use-block-upload.ts
1918
- import { useCallback as useCallback3, useRef as useRef5, useState as useState4 } from "react";
1919
1690
  var IDLE = { busy: false, error: "" };
1920
1691
  function useBlockUpload(controller, blockId, area, uploader) {
1921
1692
  const { upload, resolveAssetUrl, onError, labels } = useQuoin();
1922
- const [state, setState] = useState4(IDLE);
1923
- const started = useRef5(0);
1924
- const start = useCallback3(
1693
+ const [state, setState] = useState(IDLE);
1694
+ const started = useRef(0);
1695
+ const start = useCallback(
1925
1696
  (file) => {
1926
1697
  if (!upload) return onError(new Error(labels.uploadsUnavailable));
1927
1698
  const run = ++started.current;
@@ -1941,16 +1712,13 @@ function useBlockUpload(controller, blockId, area, uploader) {
1941
1712
  );
1942
1713
  return { ...state, start };
1943
1714
  }
1944
-
1945
- // src/blocks/upload/UploadArea.tsx
1946
- import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1947
1715
  var fileIn = (transfer, takes) => Array.from(transfer?.files ?? []).find(takes);
1948
1716
  function UploadArea(props) {
1949
1717
  const { blockId, controller, uploader, takes, accept, label, hint, className, onSelect, actions, children } = props;
1950
1718
  const { upload, labels } = useQuoin();
1951
- const area = useRef6(null);
1719
+ const area = useRef(null);
1952
1720
  const { busy, error, start } = useBlockUpload(controller, blockId, area, uploader);
1953
- useEffect6(() => {
1721
+ useEffect(() => {
1954
1722
  const element = area.current;
1955
1723
  const onDrop = (event) => {
1956
1724
  const file = fileIn(event.dataTransfer, takes);
@@ -1968,7 +1736,7 @@ function UploadArea(props) {
1968
1736
  event.preventDefault();
1969
1737
  start(file);
1970
1738
  };
1971
- return /* @__PURE__ */ jsxs10(
1739
+ return /* @__PURE__ */ jsxs(
1972
1740
  "div",
1973
1741
  {
1974
1742
  ref: area,
@@ -1976,32 +1744,29 @@ function UploadArea(props) {
1976
1744
  onPaste,
1977
1745
  ...selectHandlers(controller, blockId, area, onSelect),
1978
1746
  children: [
1979
- /* @__PURE__ */ jsxs10("div", { className: "quoin-upload-actions", children: [
1980
- /* @__PURE__ */ jsx16(FilePickerButton, { label, accept, disabled: !upload, busy, onPick: start }),
1747
+ /* @__PURE__ */ jsxs("div", { className: "quoin-upload-actions", children: [
1748
+ /* @__PURE__ */ jsx(FilePickerButton, { label, accept, disabled: !upload, busy, onPick: start }),
1981
1749
  actions
1982
1750
  ] }),
1983
1751
  children,
1984
- /* @__PURE__ */ jsx16("p", { className: "quoin-block-message", children: upload ? hint : labels.uploadsUnavailable }),
1985
- /* @__PURE__ */ jsx16("p", { role: "status", className: busy ? "quoin-block-message" : "sr-only", children: busy ? labels.uploading : "" }),
1986
- error !== "" && /* @__PURE__ */ jsx16("p", { role: "alert", className: "quoin-block-message text-destructive", children: error })
1752
+ /* @__PURE__ */ jsx("p", { className: "quoin-block-message", children: upload ? hint : labels.uploadsUnavailable }),
1753
+ /* @__PURE__ */ jsx("p", { role: "status", className: busy ? "quoin-block-message" : "sr-only", children: busy ? labels.uploading : "" }),
1754
+ error !== "" && /* @__PURE__ */ jsx("p", { role: "alert", className: "quoin-block-message text-destructive", children: error })
1987
1755
  ]
1988
1756
  }
1989
1757
  );
1990
1758
  }
1991
-
1992
- // src/blocks/void/use-node-keys.ts
1993
- import { useEffect as useEffect7 } from "react";
1994
1759
  var CONTROL = "input:not([disabled]), button:not([disabled])";
1995
1760
  var typed = (event) => !event.ctrlKey && !event.metaKey && [...event.key].length === 1;
1996
1761
  function useNodeKeys(controller, blockId, editable, opens, root, { enter, type } = {}) {
1997
1762
  const { editing, stop } = useVoidEditing(controller, blockId, editable && opens);
1998
- useEffect7(() => {
1763
+ useEffect(() => {
1999
1764
  if (!editing) return;
2000
1765
  stop();
2001
1766
  if (enter) enter();
2002
1767
  else root.current?.querySelector(CONTROL)?.focus();
2003
1768
  }, [editing, stop, enter, root]);
2004
- useEffect7(() => {
1769
+ useEffect(() => {
2005
1770
  if (!editable) return;
2006
1771
  const intercept = (event) => {
2007
1772
  const { selection } = controller.editor.state;
@@ -2014,10 +1779,6 @@ function useNodeKeys(controller, blockId, editable, opens, root, { enter, type }
2014
1779
  }, [controller, blockId, editable, type]);
2015
1780
  }
2016
1781
 
2017
- // src/blocks/file/FileCard.tsx
2018
- import { useRef as useRef7 } from "react";
2019
- import { Download } from "lucide-react";
2020
-
2021
1782
  // src/menus/bubble/bubble-part.ts
2022
1783
  var BUBBLE_PART = "data-quoin-bubble";
2023
1784
  var partIds = /* @__PURE__ */ new WeakMap();
@@ -2041,15 +1802,12 @@ function focusInEditor(controller) {
2041
1802
  const active = document.activeElement;
2042
1803
  return active !== null && (controller.isEditorElement(active) || isBubblePart(active, controller));
2043
1804
  }
2044
-
2045
- // src/blocks/file/file-icon.ts
2046
- import { FileArchive, FileIcon, FileImage, FileMusic, FilePlay, FileText as FileText2 } from "lucide-react";
2047
1805
  var KINDS = [
2048
1806
  [FileImage, /^(image\/|(png|jpe?g|gif|webp|svg|heic|bmp)$)/],
2049
1807
  [FileMusic, /^(audio\/|(mp3|wav|ogg|flac|m4a|aac)$)/],
2050
1808
  [FilePlay, /^(video\/|(mp4|mov|webm|mkv|avi|mpe?g)$)/],
2051
1809
  [FileArchive, /^(zip|rar|7z|tar|gz|xz)$/],
2052
- [FileText2, /^(text\/|(txt|md|csv|pdf|rtf|docx?)$)/]
1810
+ [FileText, /^(text\/|(txt|md|csv|pdf|rtf|docx?)$)/]
2053
1811
  ];
2054
1812
  var kindOf = (value) => KINDS.find(([, pattern]) => pattern.test(value))?.[0];
2055
1813
  var fileIcon = (mime, filename) => kindOf(mime) ?? kindOf(/\.([^.]+)$/.exec(filename)?.[1].toLowerCase() ?? "") ?? FileIcon;
@@ -2057,22 +1815,19 @@ var fileIcon = (mime, filename) => kindOf(mime) ?? kindOf(/\.([^.]+)$/.exec(file
2057
1815
  // src/blocks/file/file-source.ts
2058
1816
  var fileName = (attrs) => str(attrs.filename) || str(attrs.storageKey);
2059
1817
  var hasFile = (attrs) => fileName(attrs) !== "";
2060
-
2061
- // src/blocks/file/FileCard.tsx
2062
- import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
2063
1818
  function FileCard({ block, controller, readOnly }) {
2064
1819
  const { labels, resolveAssetUrl } = useQuoin();
2065
- const card = useRef7(null);
1820
+ const card = useRef(null);
2066
1821
  const { id, attrs } = block;
2067
1822
  const name = fileName(attrs);
2068
1823
  const size = optionalNumber(attrs.size);
2069
1824
  const href = assetHref(resolveAssetUrl, str(attrs.storageKey));
2070
1825
  const Icon = fileIcon(str(attrs.mime), name);
2071
- return /* @__PURE__ */ jsxs11("div", { ref: card, className: "quoin-file-card", ...selectHandlers(controller, id, card), children: [
2072
- /* @__PURE__ */ jsx17(Icon, { "aria-hidden": "true", className: "quoin-file-icon" }),
2073
- /* @__PURE__ */ jsx17("span", { className: "quoin-file-name", children: name }),
2074
- size !== void 0 && /* @__PURE__ */ jsx17("span", { className: "quoin-file-size", children: labels.fileSize(size) }),
2075
- href !== null && /* @__PURE__ */ jsxs11(
1826
+ return /* @__PURE__ */ jsxs("div", { ref: card, className: "quoin-file-card", ...selectHandlers(controller, id, card), children: [
1827
+ /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true", className: "quoin-file-icon" }),
1828
+ /* @__PURE__ */ jsx("span", { className: "quoin-file-name", children: name }),
1829
+ size !== void 0 && /* @__PURE__ */ jsx("span", { className: "quoin-file-size", children: labels.fileSize(size) }),
1830
+ href !== null && /* @__PURE__ */ jsxs(
2076
1831
  "a",
2077
1832
  {
2078
1833
  href,
@@ -2084,7 +1839,7 @@ function FileCard({ block, controller, readOnly }) {
2084
1839
  tabIndex: readOnly ? void 0 : -1,
2085
1840
  ...readOnly ? void 0 : bubblePart(controller),
2086
1841
  children: [
2087
- /* @__PURE__ */ jsx17(Download, { "aria-hidden": "true" }),
1842
+ /* @__PURE__ */ jsx(Download, { "aria-hidden": "true" }),
2088
1843
  labels.download
2089
1844
  ]
2090
1845
  }
@@ -2137,17 +1892,14 @@ var uploadFile = (controller, blockId, file, host) => uploadInto(
2137
1892
  host,
2138
1893
  (stored) => writeAttrs(controller, blockId, fileAttrs(file, stored), true)
2139
1894
  );
2140
-
2141
- // src/blocks/file/FileBlock.tsx
2142
- import { jsx as jsx18 } from "react/jsx-runtime";
2143
1895
  var anyFile = () => true;
2144
1896
  var FileBlock = ({ block, controller }) => {
2145
1897
  const labels = useLabels();
2146
1898
  const readOnly = useReadOnly(controller);
2147
- const root = useRef8(null);
1899
+ const root = useRef(null);
2148
1900
  const filled = hasFile(block.attrs);
2149
1901
  useNodeKeys(controller, block.id, !readOnly, !filled, root);
2150
- const empty = readOnly ? /* @__PURE__ */ jsx18("p", { className: "quoin-block-message", children: labels.emptyFile }) : /* @__PURE__ */ jsx18(
1902
+ const empty = readOnly ? /* @__PURE__ */ jsx("p", { className: "quoin-block-message", children: labels.emptyFile }) : /* @__PURE__ */ jsx(
2151
1903
  UploadArea,
2152
1904
  {
2153
1905
  blockId: block.id,
@@ -2158,15 +1910,11 @@ var FileBlock = ({ block, controller }) => {
2158
1910
  hint: labels.dropFile
2159
1911
  }
2160
1912
  );
2161
- return /* @__PURE__ */ jsx18("div", { ref: root, role: "group", "aria-label": labels.blockNames.file, contentEditable: false, className: "quoin-file", children: filled ? /* @__PURE__ */ jsx18(FileCard, { block, controller, readOnly }) : empty });
1913
+ return /* @__PURE__ */ jsx("div", { ref: root, role: "group", "aria-label": labels.blockNames.file, contentEditable: false, className: "quoin-file", children: filled ? /* @__PURE__ */ jsx(FileCard, { block, controller, readOnly }) : empty });
2162
1914
  };
2163
-
2164
- // src/blocks/upload/use-replace-picker.tsx
2165
- import { useRef as useRef9 } from "react";
2166
- import { jsx as jsx19 } from "react/jsx-runtime";
2167
1915
  function useReplacePicker(controller, blockId, uploader, accept) {
2168
1916
  const { labels, upload, resolveAssetUrl, onError } = useQuoin();
2169
- const picker = useRef9(null);
1917
+ const picker = useRef(null);
2170
1918
  const replace = (event) => {
2171
1919
  const file = event.target.files?.[0];
2172
1920
  event.target.value = "";
@@ -2178,24 +1926,21 @@ function useReplacePicker(controller, blockId, uploader, accept) {
2178
1926
  };
2179
1927
  return {
2180
1928
  open: upload && (() => picker.current?.click()),
2181
- input: /* @__PURE__ */ jsx19("input", { ref: picker, type: "file", accept, hidden: true, tabIndex: -1, onChange: replace })
1929
+ input: /* @__PURE__ */ jsx("input", { ref: picker, type: "file", accept, hidden: true, tabIndex: -1, onChange: replace })
2182
1930
  };
2183
1931
  }
2184
1932
 
2185
- // src/blocks/void/block-part.ts
2186
- import { useMemo as useMemo3 } from "react";
2187
-
2188
1933
  // src/menus/floating/virtual-anchor.ts
2189
1934
  var ROOM_BELOW = 240;
2190
1935
  function virtualAnchor(measure2, context) {
2191
- let last2 = new DOMRect();
1936
+ let last2;
2192
1937
  return {
2193
1938
  // Read when Floating UI starts watching, after the commit that drew the anchor's host has registered it.
2194
1939
  get contextElement() {
2195
1940
  return context();
2196
1941
  },
2197
1942
  getBoundingClientRect() {
2198
- last2 = measure2() ?? last2;
1943
+ last2 = measure2() ?? last2 ?? new DOMRect();
2199
1944
  return last2;
2200
1945
  }
2201
1946
  };
@@ -2207,28 +1952,22 @@ function sideFor(anchor, viewportHeight) {
2207
1952
  // src/blocks/void/block-part.ts
2208
1953
  var blockPart = (controller, blockId, selector) => controller.blockElement(blockId)?.querySelector(selector) ?? void 0;
2209
1954
  function usePartAnchor(controller, blockId, selector) {
2210
- return useMemo3(() => {
1955
+ return useMemo(() => {
2211
1956
  const part = () => blockPart(controller, blockId, selector);
2212
1957
  return { current: virtualAnchor(() => part()?.getBoundingClientRect() ?? null, part) };
2213
1958
  }, [controller, blockId, selector]);
2214
1959
  }
2215
-
2216
- // src/blocks/void/node-toolbar-items.ts
2217
- import { Trash as Trash2, Upload as Upload2 } from "lucide-react";
2218
- var replaceItem = (title, run) => run ? [{ id: "replace", title, icon: Upload2, run }] : [];
1960
+ var replaceItem = (title, run) => run ? [{ id: "replace", title, icon: Upload, run }] : [];
1961
+ function deleteBlock(controller, blockId) {
1962
+ runOnBlocks(controller, [blockId], deleteBlocks);
1963
+ controller.focus();
1964
+ }
2219
1965
  var deleteItem = (blockId, title) => ({
2220
1966
  id: "delete",
2221
1967
  title,
2222
- icon: Trash2,
2223
- run: (controller) => {
2224
- runOnBlocks(controller, [blockId], deleteBlocks);
2225
- controller.focus();
2226
- }
1968
+ icon: Trash,
1969
+ run: (controller) => deleteBlock(controller, blockId)
2227
1970
  });
2228
-
2229
- // src/menus/bubble/bubble-items.tsx
2230
- import { Bold, Code as Code2, Italic, Link as Link2, Strikethrough, Subscript, Superscript, Underline } from "lucide-react";
2231
- import { jsx as jsx20 } from "react/jsx-runtime";
2232
1971
  var PRESSED = "aria-pressed:bg-accent aria-pressed:text-accent-foreground";
2233
1972
  function markItem(mark, title, icon) {
2234
1973
  return {
@@ -2242,7 +1981,7 @@ function markItem(mark, title, icon) {
2242
1981
  var linkItem = (labels, openLink) => ({
2243
1982
  id: "link",
2244
1983
  title: labels.link,
2245
- icon: Link2,
1984
+ icon: Link,
2246
1985
  run: openLink
2247
1986
  });
2248
1987
  function bubbleItems(labels, openLink) {
@@ -2252,7 +1991,7 @@ function bubbleItems(labels, openLink) {
2252
1991
  markItem("italic", labels.italic, Italic),
2253
1992
  markItem("underline", labels.underline, Underline),
2254
1993
  markItem("strike", labels.strike, Strikethrough),
2255
- markItem("code", labels.code, Code2),
1994
+ markItem("code", labels.code, Code),
2256
1995
  linkItem(labels, openLink)
2257
1996
  ],
2258
1997
  scripts: [markItem("sub", labels.subscript, Subscript), markItem("sup", labels.superscript, Superscript)]
@@ -2261,7 +2000,7 @@ function bubbleItems(labels, openLink) {
2261
2000
  function ToolbarButton({ item, state, controller, buttonRef }) {
2262
2001
  if (item.available?.(state) === false) return null;
2263
2002
  const Icon = item.icon;
2264
- return /* @__PURE__ */ jsx20(
2003
+ return /* @__PURE__ */ jsx(
2265
2004
  Button,
2266
2005
  {
2267
2006
  ref: buttonRef,
@@ -2272,13 +2011,10 @@ function ToolbarButton({ item, state, controller, buttonRef }) {
2272
2011
  "aria-pressed": item.isActive?.(state),
2273
2012
  className: PRESSED,
2274
2013
  onClick: () => item.run(controller),
2275
- children: /* @__PURE__ */ jsx20(Icon, {})
2014
+ children: /* @__PURE__ */ jsx(Icon, {})
2276
2015
  }
2277
2016
  );
2278
2017
  }
2279
-
2280
- // src/menus/bubble/use-roving-focus.ts
2281
- import { useCallback as useCallback4, useRef as useRef10 } from "react";
2282
2018
  var MOVES = {
2283
2019
  ArrowRight: (index, count) => (index + 1) % count,
2284
2020
  ArrowLeft: (index, count) => (index - 1 + count) % count,
@@ -2286,23 +2022,23 @@ var MOVES = {
2286
2022
  End: (_, count) => count - 1
2287
2023
  };
2288
2024
  function useRovingFocus() {
2289
- const row = useRef10(null);
2290
- const current = useRef10(null);
2291
- const items = useCallback4(() => [...row.current?.querySelectorAll(":scope > button") ?? []], []);
2292
- const tabStop = useCallback4(() => {
2025
+ const row = useRef(null);
2026
+ const current = useRef(null);
2027
+ const items = useCallback(() => [...row.current?.querySelectorAll(":scope > button") ?? []], []);
2028
+ const tabStop = useCallback(() => {
2293
2029
  const all = items();
2294
2030
  return all.find((item) => item === current.current) ?? all[0];
2295
2031
  }, [items]);
2296
- const syncTabStop = useCallback4(() => {
2032
+ const syncTabStop = useCallback(() => {
2297
2033
  const stop = tabStop();
2298
2034
  for (const item of items()) item.tabIndex = item === stop ? 0 : -1;
2299
2035
  }, [items, tabStop]);
2300
- const owns = useCallback4(
2036
+ const owns = useCallback(
2301
2037
  (target) => target instanceof HTMLElement && items().includes(target),
2302
2038
  [items]
2303
2039
  );
2304
- const focusCurrent = useCallback4(() => tabStop()?.focus(), [tabStop]);
2305
- const ref = useCallback4(
2040
+ const focusCurrent = useCallback(() => tabStop()?.focus(), [tabStop]);
2041
+ const ref = useCallback(
2306
2042
  (element) => {
2307
2043
  row.current = element;
2308
2044
  syncTabStop();
@@ -2338,9 +2074,6 @@ function useFocusKey(controller, focus) {
2338
2074
  return interceptKeys(controller, intercept);
2339
2075
  }, [controller, focus]);
2340
2076
  }
2341
-
2342
- // src/blocks/void/NodeToolbar.tsx
2343
- import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
2344
2077
  function NodeToolbar(props) {
2345
2078
  const { blockId, controller, label, anchor, items, next, buttonRefs, children, popover } = props;
2346
2079
  const state = useEditorState(controller, wholeState);
@@ -2355,9 +2088,9 @@ function NodeToolbar(props) {
2355
2088
  else return roving.onKeyDown(event);
2356
2089
  event.preventDefault();
2357
2090
  };
2358
- return /* @__PURE__ */ jsxs12(Popover, { open: true, modal: false, children: [
2359
- /* @__PURE__ */ jsx21(PopoverAnchor, { virtualRef: anchor }),
2360
- /* @__PURE__ */ jsxs12(
2091
+ return /* @__PURE__ */ jsxs(Popover, { open: true, modal: false, children: [
2092
+ /* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }),
2093
+ /* @__PURE__ */ jsxs(
2361
2094
  PopoverContent,
2362
2095
  {
2363
2096
  ref: roving.ref,
@@ -2373,7 +2106,7 @@ function NodeToolbar(props) {
2373
2106
  onKeyDown,
2374
2107
  ...bubblePart(controller),
2375
2108
  children: [
2376
- items.map((item) => /* @__PURE__ */ jsx21(ToolbarButton, { item, state, controller, buttonRef: buttonRefs?.[item.id] }, item.id)),
2109
+ items.map((item) => /* @__PURE__ */ jsx(ToolbarButton, { item, state, controller, buttonRef: buttonRefs?.[item.id] }, item.id)),
2377
2110
  children
2378
2111
  ]
2379
2112
  }
@@ -2381,9 +2114,6 @@ function NodeToolbar(props) {
2381
2114
  popover
2382
2115
  ] });
2383
2116
  }
2384
-
2385
- // src/menus/bubble/use-selection-settled.ts
2386
- import { useMemo as useMemo4, useSyncExternalStore as useSyncExternalStore2 } from "react";
2387
2117
  function createSettled(controller) {
2388
2118
  let pressed = false;
2389
2119
  let composing = false;
@@ -2403,7 +2133,7 @@ function createSettled(controller) {
2403
2133
  return {
2404
2134
  read: () => focusInEditor(controller) && !pressed && !composing && !viewComposing(),
2405
2135
  subscribe(notify) {
2406
- const listeners = Object.entries(handlers).map(([type, handle2]) => {
2136
+ const listeners2 = Object.entries(handlers).map(([type, handle2]) => {
2407
2137
  const listener = (event) => {
2408
2138
  handle2(event);
2409
2139
  notify();
@@ -2413,7 +2143,7 @@ function createSettled(controller) {
2413
2143
  });
2414
2144
  const stopState = controller.editor.subscribe(() => notify());
2415
2145
  return () => {
2416
- listeners.forEach((remove) => remove());
2146
+ listeners2.forEach((remove) => remove());
2417
2147
  stopState();
2418
2148
  };
2419
2149
  }
@@ -2421,8 +2151,8 @@ function createSettled(controller) {
2421
2151
  }
2422
2152
  var NOT_SETTLED = () => false;
2423
2153
  function useSelectionSettled(controller) {
2424
- const settled = useMemo4(() => createSettled(controller), [controller]);
2425
- return useSyncExternalStore2(settled.subscribe, settled.read, NOT_SETTLED);
2154
+ const settled = useMemo(() => createSettled(controller), [controller]);
2155
+ return useSyncExternalStore(settled.subscribe, settled.read, NOT_SETTLED);
2426
2156
  }
2427
2157
 
2428
2158
  // src/blocks/void/use-toolbar-block.ts
@@ -2436,20 +2166,17 @@ function useToolbarBlock(controller, selected, keptFor = null) {
2436
2166
  const settled = useSelectionSettled(controller);
2437
2167
  return blockId !== null && !readOnly && (settled || keptFor === blockId) ? blockId : null;
2438
2168
  }
2439
-
2440
- // src/blocks/file/FileToolbar.tsx
2441
- import { jsx as jsx22 } from "react/jsx-runtime";
2442
2169
  var selectedFile = selectedBlock("FILE", hasFile);
2443
2170
  function FileToolbarOverlay({ controller }) {
2444
2171
  const blockId = useToolbarBlock(controller, selectedFile);
2445
- return blockId === null ? null : /* @__PURE__ */ jsx22(FileToolbar, { blockId, controller }, blockId);
2172
+ return blockId === null ? null : /* @__PURE__ */ jsx(FileToolbar, { blockId, controller }, blockId);
2446
2173
  }
2447
2174
  function FileToolbar({ blockId, controller }) {
2448
2175
  const { labels } = useQuoin();
2449
2176
  const picker = useReplacePicker(controller, blockId, uploadFile);
2450
2177
  const anchor = usePartAnchor(controller, blockId, ".quoin-file-card");
2451
2178
  const items = [...replaceItem(labels.replaceFile, picker.open), deleteItem(blockId, labels.delete)];
2452
- return /* @__PURE__ */ jsx22(
2179
+ return /* @__PURE__ */ jsx(
2453
2180
  NodeToolbar,
2454
2181
  {
2455
2182
  blockId,
@@ -2463,15 +2190,17 @@ function FileToolbar({ blockId, controller }) {
2463
2190
  );
2464
2191
  }
2465
2192
 
2466
- // src/blocks/image/ImageBlock.tsx
2467
- import { useRef as useRef13 } from "react";
2468
-
2469
- // src/blocks/image/ImageFigure.tsx
2470
- import { useRef as useRef12, useState as useState6 } from "react";
2471
- import { Image as Image2 } from "lucide-react";
2472
-
2473
- // src/blocks/image/ResizeHandles.tsx
2474
- import { useRef as useRef11 } from "react";
2193
+ // src/blocks/image/alt-request.ts
2194
+ var listeners = /* @__PURE__ */ new WeakMap();
2195
+ function listenForAltRequests(controller, listener) {
2196
+ listeners.set(controller, listener);
2197
+ return () => {
2198
+ if (listeners.get(controller) === listener) listeners.delete(controller);
2199
+ };
2200
+ }
2201
+ function requestAlt(controller, blockId) {
2202
+ listeners.get(controller)?.(blockId);
2203
+ }
2475
2204
 
2476
2205
  // src/blocks/image/resize-width.ts
2477
2206
  var MIN_WIDTH = 10;
@@ -2491,12 +2220,9 @@ function drawnWidth(frame) {
2491
2220
  const block = frame?.parentElement?.clientWidth ?? 0;
2492
2221
  return frame && block > 0 ? snapWidth(frame.offsetWidth / block * 100) : MAX_WIDTH;
2493
2222
  }
2494
-
2495
- // src/blocks/image/use-drawn-width.ts
2496
- import { useEffect as useEffect8, useState as useState5 } from "react";
2497
2223
  function useDrawnWidth(frame, watching) {
2498
- const [drawn, setDrawn] = useState5(MAX_WIDTH);
2499
- useEffect8(() => {
2224
+ const [drawn, setDrawn] = useState(MAX_WIDTH);
2225
+ useEffect(() => {
2500
2226
  const element = frame.current;
2501
2227
  if (!watching || element === null) return;
2502
2228
  const measure2 = () => setDrawn(drawnWidth(element));
@@ -2508,12 +2234,9 @@ function useDrawnWidth(frame, watching) {
2508
2234
  }, [frame, watching]);
2509
2235
  return drawn;
2510
2236
  }
2511
-
2512
- // src/blocks/image/ResizeHandles.tsx
2513
- import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
2514
2237
  function ResizeHandles({ blockId, controller, frame, percent, centred, onPreview }) {
2515
2238
  const labels = useLabels();
2516
- const drag = useRef11(null);
2239
+ const drag = useRef(null);
2517
2240
  const drawn = useDrawnWidth(frame, percent === void 0);
2518
2241
  const value = percent ?? drawn;
2519
2242
  const write = (widthPercent) => setBlockAttrs(controller, blockId, { widthPercent });
@@ -2548,7 +2271,7 @@ function ResizeHandles({ blockId, controller, frame, percent, centred, onPreview
2548
2271
  const to = stop();
2549
2272
  if (to !== null && to !== percent) write(to);
2550
2273
  };
2551
- const handle2 = (side) => /* @__PURE__ */ jsx23(
2274
+ const handle2 = (side) => /* @__PURE__ */ jsx(
2552
2275
  "div",
2553
2276
  {
2554
2277
  role: "slider",
@@ -2569,29 +2292,30 @@ function ResizeHandles({ blockId, controller, frame, percent, centred, onPreview
2569
2292
  onPointerCancel: stop
2570
2293
  }
2571
2294
  );
2572
- return /* @__PURE__ */ jsxs13(Fragment4, { children: [
2295
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2573
2296
  handle2(-1),
2574
2297
  handle2(1)
2575
2298
  ] });
2576
2299
  }
2577
-
2578
- // src/blocks/image/ImageFigure.tsx
2579
- import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
2580
2300
  function ImageFigure({ block, controller, readOnly }) {
2581
2301
  const { labels, resolveAssetUrl } = useQuoin();
2582
- const frame = useRef12(null);
2583
- const [preview, setPreview] = useState6(null);
2584
- const [failed, setFailed] = useState6(null);
2302
+ const frame = useRef(null);
2303
+ const [preview, setPreview] = useState(null);
2304
+ const [failed, setFailed] = useState(null);
2585
2305
  const { id, attrs, regions } = block;
2586
2306
  const src = imageSource(attrs, resolveAssetUrl);
2587
2307
  const alt = str(attrs.alt);
2588
2308
  const name = alt || labels.imageNoAlt;
2589
2309
  const percent = optionalNumber(attrs.widthPercent);
2590
2310
  const width = preview ?? percent;
2311
+ const flagged = !readOnly && alt === "" && attrs.decorative !== true;
2591
2312
  const select = () => focusNode(controller, id);
2592
- return /* @__PURE__ */ jsxs14(Fragment5, { children: [
2593
- /* @__PURE__ */ jsxs14("div", { ref: frame, className: "quoin-image-frame", style: width === void 0 ? void 0 : { width: `${width}%` }, children: [
2594
- src !== null && src !== failed ? /* @__PURE__ */ jsx24(
2313
+ const badgeText = labels.noAltBadge ?? englishLabels.noAltBadge;
2314
+ const badgeName = labels.addAltText ?? englishLabels.addAltText;
2315
+ const translatedAlone = badgeText !== englishLabels.noAltBadge && badgeName === englishLabels.addAltText;
2316
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2317
+ /* @__PURE__ */ jsxs("div", { ref: frame, className: "quoin-image-frame", style: width === void 0 ? void 0 : { width: `${width}%` }, children: [
2318
+ src !== null && src !== failed ? /* @__PURE__ */ jsx(
2595
2319
  "img",
2596
2320
  {
2597
2321
  src,
@@ -2602,11 +2326,24 @@ function ImageFigure({ block, controller, readOnly }) {
2602
2326
  onError: () => setFailed(src),
2603
2327
  onClick: select
2604
2328
  }
2605
- ) : /* @__PURE__ */ jsxs14("div", { role: "img", "aria-label": name, className: "quoin-image-missing", onClick: select, children: [
2606
- /* @__PURE__ */ jsx24(Image2, { "aria-hidden": "true" }),
2329
+ ) : /* @__PURE__ */ jsxs("div", { role: "img", "aria-label": name, className: "quoin-image-missing", onClick: select, children: [
2330
+ /* @__PURE__ */ jsx(Image, { "aria-hidden": "true" }),
2607
2331
  alt
2608
2332
  ] }),
2609
- !readOnly && /* @__PURE__ */ jsx24(
2333
+ flagged && /* @__PURE__ */ jsx(
2334
+ "button",
2335
+ {
2336
+ type: "button",
2337
+ className: "quoin-image-no-alt",
2338
+ "aria-label": translatedAlone ? void 0 : badgeName,
2339
+ onClick: () => {
2340
+ select();
2341
+ requestAlt(controller, id);
2342
+ },
2343
+ children: badgeText
2344
+ }
2345
+ ),
2346
+ !readOnly && /* @__PURE__ */ jsx(
2610
2347
  ResizeHandles,
2611
2348
  {
2612
2349
  blockId: id,
@@ -2618,7 +2355,7 @@ function ImageFigure({ block, controller, readOnly }) {
2618
2355
  }
2619
2356
  )
2620
2357
  ] }),
2621
- (!readOnly || (regions.caption?.length ?? 0) > 0) && /* @__PURE__ */ jsx24(
2358
+ (!readOnly || (regions.caption?.length ?? 0) > 0) && /* @__PURE__ */ jsx(
2622
2359
  EditableRegion,
2623
2360
  {
2624
2361
  block: id,
@@ -2631,14 +2368,6 @@ function ImageFigure({ block, controller, readOnly }) {
2631
2368
  ] });
2632
2369
  }
2633
2370
 
2634
- // src/blocks/image/ImageUploadArea.tsx
2635
- import { useState as useState8 } from "react";
2636
- import { Link as Link3 } from "lucide-react";
2637
-
2638
- // src/blocks/image/EmbedLinkForm.tsx
2639
- import { useId as useId3, useState as useState7 } from "react";
2640
- import { Check as Check2 } from "lucide-react";
2641
-
2642
2371
  // src/menus/link/link-address.ts
2643
2372
  var BARE_DOMAIN = /^[^\s/#?.]\S*\.\S*$/;
2644
2373
  var WHITESPACE = /\s/;
@@ -2649,12 +2378,8 @@ function linkAddress(typed2) {
2649
2378
  const href = sanitizeHref(completed);
2650
2379
  return href || null;
2651
2380
  }
2652
-
2653
- // src/ui/input.tsx
2654
- import * as React6 from "react";
2655
- import { jsx as jsx25 } from "react/jsx-runtime";
2656
- var Input = React6.forwardRef(function Input2({ className, type, ...props }, ref) {
2657
- return /* @__PURE__ */ jsx25(
2381
+ var Input = React7.forwardRef(function Input2({ className, type, ...props }, ref) {
2382
+ return /* @__PURE__ */ jsx(
2658
2383
  "input",
2659
2384
  {
2660
2385
  ref,
@@ -2672,14 +2397,11 @@ var Input = React6.forwardRef(function Input2({ className, type, ...props }, ref
2672
2397
  }
2673
2398
  );
2674
2399
  });
2675
-
2676
- // src/blocks/image/EmbedLinkForm.tsx
2677
- import { jsx as jsx26, jsxs as jsxs15 } from "react/jsx-runtime";
2678
2400
  function EmbedLinkForm({ blockId, controller }) {
2679
2401
  const labels = useLabels();
2680
- const [address, setAddress] = useState7("");
2681
- const [invalid, setInvalid] = useState7(false);
2682
- const messageId = useId3();
2402
+ const [address, setAddress] = useState("");
2403
+ const [invalid, setInvalid] = useState(false);
2404
+ const messageId = useId();
2683
2405
  const embed = (event) => {
2684
2406
  event.preventDefault();
2685
2407
  const url = linkAddress(address);
@@ -2690,8 +2412,8 @@ function EmbedLinkForm({ blockId, controller }) {
2690
2412
  setBlockAttrs(controller, blockId, { url });
2691
2413
  focusNode(controller, blockId);
2692
2414
  };
2693
- return /* @__PURE__ */ jsxs15("form", { noValidate: true, className: "quoin-image-link", onSubmit: embed, children: [
2694
- /* @__PURE__ */ jsx26(
2415
+ return /* @__PURE__ */ jsxs("form", { noValidate: true, className: "quoin-image-link", onSubmit: embed, children: [
2416
+ /* @__PURE__ */ jsx(
2695
2417
  Input,
2696
2418
  {
2697
2419
  type: "url",
@@ -2707,8 +2429,8 @@ function EmbedLinkForm({ blockId, controller }) {
2707
2429
  }
2708
2430
  }
2709
2431
  ),
2710
- /* @__PURE__ */ jsx26(Button, { type: "submit", variant: "ghost", size: "icon-sm", "aria-label": labels.linkApply, children: /* @__PURE__ */ jsx26(Check2, {}) }),
2711
- invalid && /* @__PURE__ */ jsx26("p", { id: messageId, role: "alert", className: "quoin-block-message", children: labels.invalidLink })
2432
+ /* @__PURE__ */ jsx(Button, { type: "submit", variant: "ghost", size: "icon-sm", "aria-label": labels.linkApply, children: /* @__PURE__ */ jsx(Check, {}) }),
2433
+ invalid && /* @__PURE__ */ jsx("p", { id: messageId, role: "alert", className: "quoin-block-message", children: labels.invalidLink })
2712
2434
  ] });
2713
2435
  }
2714
2436
 
@@ -2736,13 +2458,10 @@ var uploadImage = (controller, blockId, file, host) => uploadInto(controller, bl
2736
2458
  writeAttrs(controller, blockId, { storageKey, url: void 0, width: void 0, height: void 0 }, true);
2737
2459
  await measureImage(controller, blockId, storageKey, host.resolveAssetUrl, token);
2738
2460
  });
2739
-
2740
- // src/blocks/image/ImageUploadArea.tsx
2741
- import { jsx as jsx27, jsxs as jsxs16 } from "react/jsx-runtime";
2742
2461
  function ImageUploadArea({ blockId, controller }) {
2743
2462
  const labels = useLabels();
2744
- const [linking, setLinking] = useState8(false);
2745
- return /* @__PURE__ */ jsx27(
2463
+ const [linking, setLinking] = useState(false);
2464
+ return /* @__PURE__ */ jsx(
2746
2465
  UploadArea,
2747
2466
  {
2748
2467
  blockId,
@@ -2754,17 +2473,14 @@ function ImageUploadArea({ blockId, controller }) {
2754
2473
  hint: labels.dropImage,
2755
2474
  className: "quoin-image-upload",
2756
2475
  onSelect: () => setLinking(false),
2757
- actions: /* @__PURE__ */ jsxs16(Button, { type: "button", variant: "ghost", size: "sm", "aria-expanded": linking, onClick: () => setLinking(true), children: [
2758
- /* @__PURE__ */ jsx27(Link3, {}),
2476
+ actions: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-expanded": linking, onClick: () => setLinking(true), children: [
2477
+ /* @__PURE__ */ jsx(Link, {}),
2759
2478
  labels.embedLink
2760
2479
  ] }),
2761
- children: linking && /* @__PURE__ */ jsx27(EmbedLinkForm, { blockId, controller })
2480
+ children: linking && /* @__PURE__ */ jsx(EmbedLinkForm, { blockId, controller })
2762
2481
  }
2763
2482
  );
2764
2483
  }
2765
-
2766
- // src/blocks/image/use-image-keys.ts
2767
- import { useEffect as useEffect9, useMemo as useMemo5 } from "react";
2768
2484
  function captionEnd(controller, blockId) {
2769
2485
  const caption = blockById(controller.editor.state.doc, blockId)?.regions.caption ?? [];
2770
2486
  return { block: blockId, region: "caption", offset: inlineLength(caption) };
@@ -2772,7 +2488,7 @@ function captionEnd(controller, blockId) {
2772
2488
  var plainEnter = (event) => event.key === "Enter" && !event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey;
2773
2489
  var menuOpenOn = (host) => host?.getAttribute("aria-expanded") === "true";
2774
2490
  function useImageKeys(controller, blockId, picture, editable, root) {
2775
- const caption = useMemo5(() => {
2491
+ const caption = useMemo(() => {
2776
2492
  if (!picture) return {};
2777
2493
  return {
2778
2494
  // Called from an effect, where the canvas's own flush is refused, so the caret goes to the editor, which the view
@@ -2789,7 +2505,7 @@ function useImageKeys(controller, blockId, picture, editable, root) {
2789
2505
  };
2790
2506
  }, [controller, blockId, picture]);
2791
2507
  useNodeKeys(controller, blockId, editable, true, root, caption);
2792
- useEffect9(() => {
2508
+ useEffect(() => {
2793
2509
  if (!editable) return;
2794
2510
  const intercept = (event) => {
2795
2511
  const { selection } = controller.editor.state;
@@ -2802,17 +2518,14 @@ function useImageKeys(controller, blockId, picture, editable, root) {
2802
2518
  return interceptKeys(controller, intercept);
2803
2519
  }, [controller, blockId, editable]);
2804
2520
  }
2805
-
2806
- // src/blocks/image/ImageBlock.tsx
2807
- import { jsx as jsx28 } from "react/jsx-runtime";
2808
2521
  var ImageBlock = ({ block, controller }) => {
2809
2522
  const labels = useLabels();
2810
2523
  const readOnly = useReadOnly(controller);
2811
- const root = useRef13(null);
2524
+ const root = useRef(null);
2812
2525
  const picture = hasPicture(block.attrs);
2813
2526
  useImageKeys(controller, block.id, picture, !readOnly, root);
2814
- const empty = readOnly ? /* @__PURE__ */ jsx28("p", { className: "quoin-block-message", children: labels.emptyImage }) : /* @__PURE__ */ jsx28(ImageUploadArea, { blockId: block.id, controller });
2815
- return /* @__PURE__ */ jsx28(
2527
+ const empty = readOnly ? /* @__PURE__ */ jsx("p", { className: "quoin-block-message", children: labels.emptyImage }) : /* @__PURE__ */ jsx(ImageUploadArea, { blockId: block.id, controller });
2528
+ return /* @__PURE__ */ jsx(
2816
2529
  "div",
2817
2530
  {
2818
2531
  ref: root,
@@ -2821,21 +2534,12 @@ var ImageBlock = ({ block, controller }) => {
2821
2534
  contentEditable: false,
2822
2535
  className: "quoin-image",
2823
2536
  ...picture ? { [NODE_ENTRY]: "" } : void 0,
2824
- children: picture ? /* @__PURE__ */ jsx28(ImageFigure, { block, controller, readOnly }) : empty
2537
+ children: picture ? /* @__PURE__ */ jsx(ImageFigure, { block, controller, readOnly }) : empty
2825
2538
  }
2826
2539
  );
2827
2540
  };
2828
-
2829
- // src/blocks/image/ImageToolbar.tsx
2830
- import { useRef as useRef16, useState as useState10 } from "react";
2831
-
2832
- // src/blocks/image/AltTextPopover.tsx
2833
- import { useCallback as useCallback5, useEffect as useEffect10, useId as useId4, useRef as useRef15, useState as useState9 } from "react";
2834
-
2835
- // src/blocks/image/use-outside-press.ts
2836
- import { useRef as useRef14 } from "react";
2837
2541
  function useOutsidePress(element, ownerDocument, onPress) {
2838
- const latest = useRef14(onPress);
2542
+ const latest = useRef(onPress);
2839
2543
  useIsomorphicLayoutEffect(() => {
2840
2544
  latest.current = onPress;
2841
2545
  });
@@ -2857,36 +2561,36 @@ function useOutsidePress(element, ownerDocument, onPress) {
2857
2561
  return listen(doc, { pointerdown: down, click }, true);
2858
2562
  }, [element, ownerDocument]);
2859
2563
  }
2860
-
2861
- // src/blocks/image/AltTextPopover.tsx
2862
- import { jsx as jsx29, jsxs as jsxs17 } from "react/jsx-runtime";
2863
- function storeAlt(controller, blockId, opened, alt) {
2564
+ function storeAlt(controller, blockId, opened, patch) {
2864
2565
  const { editor } = controller;
2865
- const current = blockById(editor.state.doc, blockId)?.attrs.alt;
2866
- if (controller.readOnly || controller.root === null || str(current) !== opened) return;
2867
- onBlock(blockId, setAttrs({ alt }))(editor.state, (tr) => editor.dispatch(tr));
2566
+ const attrs = blockById(editor.state.doc, blockId)?.attrs ?? {};
2567
+ const changed = str(attrs.alt) !== opened.alt || attrs.decorative === true !== opened.decorative;
2568
+ if (controller.readOnly || controller.root === null || changed) return;
2569
+ onBlock(blockId, setAttrs(patch))(editor.state, (tr) => editor.dispatch(tr));
2868
2570
  }
2869
- function AltTextPopover({ blockId, controller, anchor, opener, alt, onClose }) {
2571
+ function AltTextPopover({ blockId, controller, anchor, opener, alt, decorative, onClose }) {
2870
2572
  const labels = useLabels();
2871
- const [opened] = useState9(alt);
2872
- const [draft, setDraft] = useState9(alt);
2873
- const fieldId = useId4();
2573
+ const [opened] = useState({ alt, decorative });
2574
+ const [draft, setDraft] = useState(alt);
2575
+ const [marked, setMarked] = useState(decorative);
2576
+ const fieldId = useId();
2874
2577
  const hintId = `${fieldId}-hint`;
2875
- const closed = useRef15(false);
2578
+ const closed = useRef(false);
2876
2579
  const finish = (store) => {
2877
2580
  if (closed.current) return false;
2878
2581
  closed.current = true;
2879
- if (store && draft !== alt) storeAlt(controller, blockId, opened, draft);
2582
+ if (store && (draft !== alt || marked !== decorative))
2583
+ storeAlt(controller, blockId, opened, { alt: draft, decorative: marked || void 0 });
2880
2584
  return true;
2881
2585
  };
2882
- const latestFinish = useRef15(finish);
2586
+ const latestFinish = useRef(finish);
2883
2587
  latestFinish.current = finish;
2884
- useEffect10(() => {
2588
+ useEffect(() => {
2885
2589
  closed.current = false;
2886
2590
  return () => void latestFinish.current(true);
2887
2591
  }, []);
2888
- useEffect10(() => {
2889
- if (alt !== opened && finish(false)) onClose();
2592
+ useEffect(() => {
2593
+ if ((alt !== opened.alt || decorative !== opened.decorative) && finish(false)) onClose();
2890
2594
  });
2891
2595
  const close = (store, refocus = true) => {
2892
2596
  if (!refocus) controller.readSelectionFromDom();
@@ -2894,8 +2598,8 @@ function AltTextPopover({ blockId, controller, anchor, opener, alt, onClose }) {
2894
2598
  onClose();
2895
2599
  if (refocus) controller.focus();
2896
2600
  };
2897
- const content = useRef15(null);
2898
- const ownerDocument = useCallback5(() => controller.root?.ownerDocument ?? document, [controller]);
2601
+ const content = useRef(null);
2602
+ const ownerDocument = useCallback(() => controller.root?.ownerDocument ?? document, [controller]);
2899
2603
  useOutsidePress(content, ownerDocument, (target) => {
2900
2604
  if (!opener.current?.contains(target)) close(true, isBubblePart(target, controller));
2901
2605
  });
@@ -2905,14 +2609,14 @@ function AltTextPopover({ blockId, controller, anchor, opener, alt, onClose }) {
2905
2609
  };
2906
2610
  const onKeyDown = (event) => {
2907
2611
  if (event.key !== "Tab" || isComposingKey(controller, event.nativeEvent)) return;
2908
- const [field, save2] = event.currentTarget.elements;
2909
- const fromField = event.target === field;
2612
+ const controls = [...event.currentTarget.elements];
2613
+ const next = controls[controls.indexOf(event.target) + (event.shiftKey ? -1 : 1)];
2910
2614
  event.preventDefault();
2911
2615
  event.stopPropagation();
2912
- if (event.shiftKey === fromField) close(true);
2913
- else (fromField ? save2 : field).focus();
2616
+ if (next === void 0) close(true);
2617
+ else next.focus();
2914
2618
  };
2915
- return /* @__PURE__ */ jsxs17(
2619
+ return /* @__PURE__ */ jsxs(
2916
2620
  Popover,
2917
2621
  {
2918
2622
  open: true,
@@ -2921,8 +2625,8 @@ function AltTextPopover({ blockId, controller, anchor, opener, alt, onClose }) {
2921
2625
  if (!open) close(true, false);
2922
2626
  },
2923
2627
  children: [
2924
- /* @__PURE__ */ jsx29(PopoverAnchor, { virtualRef: anchor }),
2925
- /* @__PURE__ */ jsx29(
2628
+ /* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }),
2629
+ /* @__PURE__ */ jsx(
2926
2630
  PopoverContent,
2927
2631
  {
2928
2632
  ref: content,
@@ -2935,20 +2639,37 @@ function AltTextPopover({ blockId, controller, anchor, opener, alt, onClose }) {
2935
2639
  if (!isComposingKey(controller, event)) close(false);
2936
2640
  },
2937
2641
  ...bubblePart(controller),
2938
- children: /* @__PURE__ */ jsxs17("form", { noValidate: true, className: "quoin-image-alt", onSubmit: save, onKeyDown, children: [
2939
- /* @__PURE__ */ jsx29("label", { htmlFor: fieldId, className: "text-sm font-medium", children: labels.altText }),
2940
- /* @__PURE__ */ jsx29(
2642
+ children: /* @__PURE__ */ jsxs("form", { noValidate: true, className: "quoin-image-alt", onSubmit: save, onKeyDown, children: [
2643
+ /* @__PURE__ */ jsx("label", { htmlFor: fieldId, className: "text-sm font-medium", children: labels.altText }),
2644
+ /* @__PURE__ */ jsx(
2941
2645
  Input,
2942
2646
  {
2943
2647
  id: fieldId,
2944
- required: true,
2945
- "aria-describedby": hintId,
2648
+ required: !marked,
2649
+ "aria-describedby": marked ? void 0 : hintId,
2946
2650
  value: draft,
2947
- onChange: (event) => setDraft(event.target.value)
2651
+ onChange: (event) => {
2652
+ setDraft(event.target.value);
2653
+ setMarked(false);
2654
+ }
2948
2655
  }
2949
2656
  ),
2950
- /* @__PURE__ */ jsx29("p", { id: hintId, className: "quoin-block-message", children: labels.altTextHint }),
2951
- /* @__PURE__ */ jsx29(Button, { type: "submit", size: "sm", children: labels.save })
2657
+ /* @__PURE__ */ jsx("p", { id: hintId, className: marked ? "quoin-block-message invisible" : "quoin-block-message", children: labels.altTextHint }),
2658
+ /* @__PURE__ */ jsxs("label", { className: "quoin-image-decorative text-sm", children: [
2659
+ /* @__PURE__ */ jsx(
2660
+ "input",
2661
+ {
2662
+ type: "checkbox",
2663
+ checked: marked,
2664
+ onChange: (event) => {
2665
+ setMarked(event.target.checked);
2666
+ if (event.target.checked) setDraft("");
2667
+ }
2668
+ }
2669
+ ),
2670
+ labels.decorativeImage ?? englishLabels.decorativeImage
2671
+ ] }),
2672
+ /* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", children: labels.save })
2952
2673
  ] })
2953
2674
  }
2954
2675
  )
@@ -2956,9 +2677,6 @@ function AltTextPopover({ blockId, controller, anchor, opener, alt, onClose }) {
2956
2677
  }
2957
2678
  );
2958
2679
  }
2959
-
2960
- // src/blocks/image/image-toolbar-items.ts
2961
- import { AlignCenter, AlignLeft, AlignRight, Download as Download2, Pencil } from "lucide-react";
2962
2680
  var ALIGNS = [
2963
2681
  ["left", AlignLeft, "alignLeft"],
2964
2682
  ["center", AlignCenter, "alignCenter"],
@@ -2979,13 +2697,10 @@ function imageToolbarItems(blockId, labels, actions) {
2979
2697
  ...aligns,
2980
2698
  ...replaceItem(labels.replaceImage, replace),
2981
2699
  { id: "alt", title: labels.altText, icon: Pencil, run: editAlt },
2982
- { id: "download", title: labels.download, icon: Download2, run: download2 },
2700
+ { id: "download", title: labels.download, icon: Download, run: download2 },
2983
2701
  deleteItem(blockId, labels.delete)
2984
2702
  ];
2985
2703
  }
2986
-
2987
- // src/blocks/image/ImageToolbar.tsx
2988
- import { jsx as jsx30 } from "react/jsx-runtime";
2989
2704
  var selectedImage = selectedBlock("IMAGE", hasPicture);
2990
2705
  function download(src, doc) {
2991
2706
  if (src === null) return;
@@ -2997,11 +2712,12 @@ function download(src, doc) {
2997
2712
  link.click();
2998
2713
  }
2999
2714
  function ImageToolbarOverlay({ controller }) {
3000
- const [altFor, setAltFor] = useState10(null);
2715
+ const [altFor, setAltFor] = useState(null);
3001
2716
  const blockId = useToolbarBlock(controller, selectedImage, altFor);
2717
+ useEffect(() => listenForAltRequests(controller, setAltFor), [controller]);
3002
2718
  if (altFor !== null && altFor !== blockId) setAltFor(null);
3003
2719
  if (blockId === null) return null;
3004
- return /* @__PURE__ */ jsx30(
2720
+ return /* @__PURE__ */ jsx(
3005
2721
  ImageToolbar,
3006
2722
  {
3007
2723
  blockId,
@@ -3016,7 +2732,7 @@ function ImageToolbar({ blockId, controller, editingAlt, onEditAlt }) {
3016
2732
  const { labels, resolveAssetUrl } = useQuoin();
3017
2733
  const state = useEditorState(controller, wholeState);
3018
2734
  const picker = useReplacePicker(controller, blockId, uploadImage, "image/*");
3019
- const altButton = useRef16(null);
2735
+ const altButton = useRef(null);
3020
2736
  const anchor = usePartAnchor(controller, blockId, ".quoin-image-frame");
3021
2737
  const attrs = blockById(state.doc, blockId)?.attrs ?? {};
3022
2738
  const items = imageToolbarItems(blockId, labels, {
@@ -3027,7 +2743,7 @@ function ImageToolbar({ blockId, controller, editingAlt, onEditAlt }) {
3027
2743
  },
3028
2744
  download: () => download(imageSource(attrs, resolveAssetUrl), controller.root?.ownerDocument ?? document)
3029
2745
  });
3030
- return /* @__PURE__ */ jsx30(
2746
+ return /* @__PURE__ */ jsx(
3031
2747
  NodeToolbar,
3032
2748
  {
3033
2749
  blockId,
@@ -3037,7 +2753,7 @@ function ImageToolbar({ blockId, controller, editingAlt, onEditAlt }) {
3037
2753
  items,
3038
2754
  next: '[role="slider"][data-side="1"]',
3039
2755
  buttonRefs: { alt: altButton },
3040
- popover: editingAlt && /* @__PURE__ */ jsx30(
2756
+ popover: editingAlt && /* @__PURE__ */ jsx(
3041
2757
  AltTextPopover,
3042
2758
  {
3043
2759
  blockId,
@@ -3045,6 +2761,7 @@ function ImageToolbar({ blockId, controller, editingAlt, onEditAlt }) {
3045
2761
  anchor,
3046
2762
  opener: altButton,
3047
2763
  alt: str(attrs.alt),
2764
+ decorative: attrs.decorative === true,
3048
2765
  onClose: () => onEditAlt(null)
3049
2766
  }
3050
2767
  ),
@@ -3063,23 +2780,17 @@ var inPlaceOverlays = {
3063
2780
  IMAGE: ImageToolbarOverlay,
3064
2781
  FILE: FileToolbarOverlay
3065
2782
  };
3066
-
3067
- // src/ui/dropdown-menu.tsx
3068
- import * as React7 from "react";
3069
- import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
3070
- import { CheckIcon as CheckIcon4, ChevronRightIcon as ChevronRightIcon2, CircleIcon as CircleIcon2 } from "lucide-react";
3071
- import { jsx as jsx31, jsxs as jsxs18 } from "react/jsx-runtime";
3072
2783
  function DropdownMenu({ modal = false, ...props }) {
3073
- return /* @__PURE__ */ jsx31(DropdownMenuPrimitive.Root, { modal, ...props });
2784
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Root, { modal, ...props });
3074
2785
  }
3075
2786
  function DropdownMenuSub(props) {
3076
- return /* @__PURE__ */ jsx31(DropdownMenuPrimitive.Sub, { ...props });
2787
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Sub, { ...props });
3077
2788
  }
3078
2789
  var DropdownMenuTrigger = /* @__PURE__ */ React7.forwardRef(function DropdownMenuTrigger2(props, ref) {
3079
- return /* @__PURE__ */ jsx31(DropdownMenuPrimitive.Trigger, { ref, "data-slot": "dropdown-menu-trigger", ...props });
2790
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Trigger, { ref, "data-slot": "dropdown-menu-trigger", ...props });
3080
2791
  });
3081
2792
  var DropdownMenuContent = /* @__PURE__ */ React7.forwardRef(function DropdownMenuContent2({ className, sideOffset = 4, ...props }, ref) {
3082
- return /* @__PURE__ */ jsx31(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx31(
2793
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
3083
2794
  DropdownMenuPrimitive.Content,
3084
2795
  {
3085
2796
  ref,
@@ -3091,10 +2802,10 @@ var DropdownMenuContent = /* @__PURE__ */ React7.forwardRef(function DropdownMen
3091
2802
  ) });
3092
2803
  });
3093
2804
  var DropdownMenuGroup = /* @__PURE__ */ React7.forwardRef(function DropdownMenuGroup2(props, ref) {
3094
- return /* @__PURE__ */ jsx31(DropdownMenuPrimitive.Group, { ref, "data-slot": "dropdown-menu-group", ...props });
2805
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Group, { ref, "data-slot": "dropdown-menu-group", ...props });
3095
2806
  });
3096
2807
  var DropdownMenuItem = /* @__PURE__ */ React7.forwardRef(function DropdownMenuItem2({ className, inset, ...props }, ref) {
3097
- return /* @__PURE__ */ jsx31(
2808
+ return /* @__PURE__ */ jsx(
3098
2809
  DropdownMenuPrimitive.Item,
3099
2810
  {
3100
2811
  ref,
@@ -3106,7 +2817,7 @@ var DropdownMenuItem = /* @__PURE__ */ React7.forwardRef(function DropdownMenuIt
3106
2817
  );
3107
2818
  });
3108
2819
  var DropdownMenuCheckboxItem = /* @__PURE__ */ React7.forwardRef(function DropdownMenuCheckboxItem2({ className, children, ...props }, ref) {
3109
- return /* @__PURE__ */ jsxs18(
2820
+ return /* @__PURE__ */ jsxs(
3110
2821
  DropdownMenuPrimitive.CheckboxItem,
3111
2822
  {
3112
2823
  ref,
@@ -3114,17 +2825,17 @@ var DropdownMenuCheckboxItem = /* @__PURE__ */ React7.forwardRef(function Dropdo
3114
2825
  className: cn(MENU_CHECKABLE_ITEM, className),
3115
2826
  ...props,
3116
2827
  children: [
3117
- /* @__PURE__ */ jsx31("span", { className: MENU_ITEM_INDICATOR, children: /* @__PURE__ */ jsx31(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx31(CheckIcon4, { className: "size-4" }) }) }),
2828
+ /* @__PURE__ */ jsx("span", { className: MENU_ITEM_INDICATOR, children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }) }) }),
3118
2829
  children
3119
2830
  ]
3120
2831
  }
3121
2832
  );
3122
2833
  });
3123
2834
  var DropdownMenuRadioGroup = /* @__PURE__ */ React7.forwardRef(function DropdownMenuRadioGroup2(props, ref) {
3124
- return /* @__PURE__ */ jsx31(DropdownMenuPrimitive.RadioGroup, { ref, "data-slot": "dropdown-menu-radio-group", ...props });
2835
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.RadioGroup, { ref, "data-slot": "dropdown-menu-radio-group", ...props });
3125
2836
  });
3126
- var DropdownMenuRadioItem = /* @__PURE__ */ React7.forwardRef(function DropdownMenuRadioItem2({ className, children, indicator = /* @__PURE__ */ jsx31(CircleIcon2, { className: "size-2 fill-current" }), ...props }, ref) {
3127
- return /* @__PURE__ */ jsxs18(
2837
+ var DropdownMenuRadioItem = /* @__PURE__ */ React7.forwardRef(function DropdownMenuRadioItem2({ className, children, indicator = /* @__PURE__ */ jsx(CircleIcon, { className: "size-2 fill-current" }), ...props }, ref) {
2838
+ return /* @__PURE__ */ jsxs(
3128
2839
  DropdownMenuPrimitive.RadioItem,
3129
2840
  {
3130
2841
  ref,
@@ -3132,14 +2843,14 @@ var DropdownMenuRadioItem = /* @__PURE__ */ React7.forwardRef(function DropdownM
3132
2843
  className: cn(MENU_CHECKABLE_ITEM, className),
3133
2844
  ...props,
3134
2845
  children: [
3135
- /* @__PURE__ */ jsx31("span", { className: MENU_ITEM_INDICATOR, children: /* @__PURE__ */ jsx31(DropdownMenuPrimitive.ItemIndicator, { children: indicator }) }),
2846
+ /* @__PURE__ */ jsx("span", { className: MENU_ITEM_INDICATOR, children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: indicator }) }),
3136
2847
  children
3137
2848
  ]
3138
2849
  }
3139
2850
  );
3140
2851
  });
3141
2852
  var DropdownMenuLabel = /* @__PURE__ */ React7.forwardRef(function DropdownMenuLabel2({ className, inset, ...props }, ref) {
3142
- return /* @__PURE__ */ jsx31(
2853
+ return /* @__PURE__ */ jsx(
3143
2854
  DropdownMenuPrimitive.Label,
3144
2855
  {
3145
2856
  ref,
@@ -3151,7 +2862,7 @@ var DropdownMenuLabel = /* @__PURE__ */ React7.forwardRef(function DropdownMenuL
3151
2862
  );
3152
2863
  });
3153
2864
  var DropdownMenuSeparator = /* @__PURE__ */ React7.forwardRef(function DropdownMenuSeparator2({ className, ...props }, ref) {
3154
- return /* @__PURE__ */ jsx31(
2865
+ return /* @__PURE__ */ jsx(
3155
2866
  DropdownMenuPrimitive.Separator,
3156
2867
  {
3157
2868
  ref,
@@ -3163,11 +2874,11 @@ var DropdownMenuSeparator = /* @__PURE__ */ React7.forwardRef(function DropdownM
3163
2874
  });
3164
2875
  var DropdownMenuShortcut = /* @__PURE__ */ React7.forwardRef(
3165
2876
  function DropdownMenuShortcut2({ className, ...props }, ref) {
3166
- return /* @__PURE__ */ jsx31("span", { ref, "data-slot": "dropdown-menu-shortcut", className: cn(MENU_SHORTCUT, className), ...props });
2877
+ return /* @__PURE__ */ jsx("span", { ref, "data-slot": "dropdown-menu-shortcut", className: cn(MENU_SHORTCUT, className), ...props });
3167
2878
  }
3168
2879
  );
3169
2880
  var DropdownMenuSubTrigger = /* @__PURE__ */ React7.forwardRef(function DropdownMenuSubTrigger2({ className, inset, children, ...props }, ref) {
3170
- return /* @__PURE__ */ jsxs18(
2881
+ return /* @__PURE__ */ jsxs(
3171
2882
  DropdownMenuPrimitive.SubTrigger,
3172
2883
  {
3173
2884
  ref,
@@ -3177,13 +2888,13 @@ var DropdownMenuSubTrigger = /* @__PURE__ */ React7.forwardRef(function Dropdown
3177
2888
  ...props,
3178
2889
  children: [
3179
2890
  children,
3180
- /* @__PURE__ */ jsx31(ChevronRightIcon2, { className: "ml-auto size-4" })
2891
+ /* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto size-4" })
3181
2892
  ]
3182
2893
  }
3183
2894
  );
3184
2895
  });
3185
2896
  var DropdownMenuSubContent = /* @__PURE__ */ React7.forwardRef(function DropdownMenuSubContent2({ className, ...props }, ref) {
3186
- return /* @__PURE__ */ jsx31(
2897
+ return /* @__PURE__ */ jsx(
3187
2898
  DropdownMenuPrimitive.SubContent,
3188
2899
  {
3189
2900
  ref,
@@ -3193,13 +2904,10 @@ var DropdownMenuSubContent = /* @__PURE__ */ React7.forwardRef(function Dropdown
3193
2904
  }
3194
2905
  );
3195
2906
  });
3196
-
3197
- // src/blocks/text/CalloutIconMenu.tsx
3198
- import { jsx as jsx32, jsxs as jsxs19 } from "react/jsx-runtime";
3199
2907
  function CalloutIconMenu({ blockId, controller, icon }) {
3200
2908
  const labels = useLabels();
3201
- return /* @__PURE__ */ jsxs19(DropdownMenu, { children: [
3202
- /* @__PURE__ */ jsx32(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx32(
2909
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
2910
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
3203
2911
  Button,
3204
2912
  {
3205
2913
  type: "button",
@@ -3208,10 +2916,10 @@ function CalloutIconMenu({ blockId, controller, icon }) {
3208
2916
  tabIndex: -1,
3209
2917
  "aria-label": labels.calloutIcon,
3210
2918
  className: "text-base",
3211
- children: /* @__PURE__ */ jsx32("span", { "aria-hidden": "true", children: icon })
2919
+ children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: icon })
3212
2920
  }
3213
2921
  ) }),
3214
- /* @__PURE__ */ jsx32(DropdownMenuContent, { align: "start", className: "min-w-0", onCloseAutoFocus: returnFocusToText(controller), children: CALLOUT_ICONS.map((choice) => /* @__PURE__ */ jsx32(
2922
+ /* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", className: "min-w-0", onCloseAutoFocus: returnFocusToText(controller), children: CALLOUT_ICONS.map((choice) => /* @__PURE__ */ jsx(
3215
2923
  DropdownMenuItem,
3216
2924
  {
3217
2925
  className: "justify-center text-base",
@@ -3222,9 +2930,6 @@ function CalloutIconMenu({ blockId, controller, icon }) {
3222
2930
  )) })
3223
2931
  ] });
3224
2932
  }
3225
-
3226
- // src/blocks/text/CalloutToneMenu.tsx
3227
- import { jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
3228
2933
  var SHOWN_WITH_THE_BLOCK = [
3229
2934
  "opacity-0 group-hover/callout:opacity-100 group-focus-within/callout:opacity-100",
3230
2935
  "in-data-[selected=true]:opacity-100 pointer-coarse:opacity-100 focus-visible:opacity-100 data-[state=open]:opacity-100"
@@ -3232,8 +2937,8 @@ var SHOWN_WITH_THE_BLOCK = [
3232
2937
  function CalloutToneMenu({ blockId, controller, tone }) {
3233
2938
  const labels = useLabels();
3234
2939
  const name = labels.calloutTones[tone];
3235
- return /* @__PURE__ */ jsxs20(DropdownMenu, { children: [
3236
- /* @__PURE__ */ jsx33(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx33(
2940
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
2941
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
3237
2942
  Button,
3238
2943
  {
3239
2944
  type: "button",
@@ -3245,27 +2950,24 @@ function CalloutToneMenu({ blockId, controller, tone }) {
3245
2950
  children: name
3246
2951
  }
3247
2952
  ) }),
3248
- /* @__PURE__ */ jsx33(DropdownMenuContent, { align: "end", onCloseAutoFocus: returnFocusToText(controller), children: /* @__PURE__ */ jsx33(
2953
+ /* @__PURE__ */ jsx(DropdownMenuContent, { align: "end", onCloseAutoFocus: returnFocusToText(controller), children: /* @__PURE__ */ jsx(
3249
2954
  DropdownMenuRadioGroup,
3250
2955
  {
3251
2956
  value: tone,
3252
2957
  onValueChange: (value) => setBlockAttrs(controller, blockId, { tone: value }),
3253
- children: CALLOUT_TONES.map((option) => /* @__PURE__ */ jsx33(DropdownMenuRadioItem, { value: option, children: labels.calloutTones[option] }, option))
2958
+ children: CALLOUT_TONES.map((option) => /* @__PURE__ */ jsx(DropdownMenuRadioItem, { value: option, children: labels.calloutTones[option] }, option))
3254
2959
  }
3255
2960
  ) })
3256
2961
  ] });
3257
2962
  }
3258
-
3259
- // src/blocks/text/CalloutBlock.tsx
3260
- import { jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
3261
2963
  var CalloutBlock = ({ block, controller }) => {
3262
2964
  const labels = useLabels();
3263
2965
  const readOnly = useReadOnly(controller);
3264
2966
  const tone = calloutTone(block.attrs.tone);
3265
2967
  const icon = calloutIcon(block.attrs, tone);
3266
- return /* @__PURE__ */ jsxs21("div", { className: cn("quoin-callout group/callout flex items-start gap-2", TONE[tone]), "data-tone": tone, children: [
3267
- readOnly ? /* @__PURE__ */ jsx34("span", { "aria-hidden": "true", className: "flex size-6 items-center justify-center text-base", children: icon }) : /* @__PURE__ */ jsx34(CalloutIconMenu, { blockId: block.id, controller, icon }),
3268
- /* @__PURE__ */ jsx34(
2968
+ return /* @__PURE__ */ jsxs("div", { className: cn("quoin-callout group/callout flex items-start gap-2", TONE[tone]), "data-tone": tone, children: [
2969
+ readOnly ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "flex size-6 items-center justify-center text-base", children: icon }) : /* @__PURE__ */ jsx(CalloutIconMenu, { blockId: block.id, controller, icon }),
2970
+ /* @__PURE__ */ jsx(
3269
2971
  EditableRegion,
3270
2972
  {
3271
2973
  block: block.id,
@@ -3274,13 +2976,10 @@ var CalloutBlock = ({ block, controller }) => {
3274
2976
  className: "min-w-0 flex-1"
3275
2977
  }
3276
2978
  ),
3277
- !readOnly && /* @__PURE__ */ jsx34(CalloutToneMenu, { blockId: block.id, controller, tone })
2979
+ !readOnly && /* @__PURE__ */ jsx(CalloutToneMenu, { blockId: block.id, controller, tone })
3278
2980
  ] });
3279
2981
  };
3280
-
3281
- // src/blocks/text/DividerBlock.tsx
3282
- import { jsx as jsx35 } from "react/jsx-runtime";
3283
- var DividerBlock = ({ block, controller }) => /* @__PURE__ */ jsx35("div", { className: "py-2", contentEditable: false, onClick: () => focusNode(controller, block.id), children: /* @__PURE__ */ jsx35("hr", { className: "border-t border-border" }) });
2982
+ var DividerBlock = ({ block, controller }) => /* @__PURE__ */ jsx("div", { className: "py-2", contentEditable: false, onClick: () => focusNode(controller, block.id), children: /* @__PURE__ */ jsx("hr", { className: "border-t border-border" }) });
3284
2983
 
3285
2984
  // src/blocks/text/marker-styles.ts
3286
2985
  var BULLETS = ["\u2022", "\u25E6", "\u25AA"];
@@ -3328,38 +3027,32 @@ function bulletGlyph(depth) {
3328
3027
  function orderedLabel(n, depth) {
3329
3028
  return `${COUNTERS[cycleOf(depth)](n)}.`;
3330
3029
  }
3331
-
3332
- // src/blocks/text/ListMarker.tsx
3333
- import { jsx as jsx36 } from "react/jsx-runtime";
3334
3030
  function ListMarker(props) {
3335
3031
  const text2 = props.list === "bullet" ? bulletGlyph(props.depth) : orderedLabel(props.number, props.depth);
3336
- return /* @__PURE__ */ jsx36("span", { className: "quoin-marker", "aria-hidden": "true", children: text2 });
3032
+ return /* @__PURE__ */ jsx("span", { className: "quoin-marker", "aria-hidden": "true", children: text2 });
3337
3033
  }
3338
-
3339
- // src/blocks/text/MarkdownBlock.tsx
3340
- import { jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
3341
3034
  var REGION = "text";
3342
3035
  var HEADING_LEVELS = ["mt-6 text-3xl", "mt-5 text-2xl", "mt-4 text-xl", "mt-3 text-lg", "mt-3 text-base", "mt-3 text-sm"];
3343
3036
  var headingStyles = (level) => `quoin-heading mb-1 font-semibold leading-tight in-[[data-quoin-block]:first-child]:mt-0 ${HEADING_LEVELS[level - 1]}`;
3344
3037
  function Heading({ block }) {
3345
3038
  const labels = useLabels();
3346
3039
  const level = headingLevel(block.attrs.level);
3347
- return /* @__PURE__ */ jsx37("div", { role: "heading", "aria-level": level, className: headingStyles(level), children: /* @__PURE__ */ jsx37(EditableRegion, { block: block.id, region: REGION, label: labels.heading(level) }) });
3040
+ return /* @__PURE__ */ jsx("div", { role: "heading", "aria-level": level, className: headingStyles(level), children: /* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: REGION, label: labels.heading(level) }) });
3348
3041
  }
3349
3042
  function NumberedItem({ block, controller }) {
3350
3043
  const labels = useLabels();
3351
3044
  const number = useOrderedNumber(controller, block.id);
3352
- return /* @__PURE__ */ jsxs22("div", { className: "quoin-list-item", "data-list": "ordered", children: [
3353
- /* @__PURE__ */ jsx37(ListMarker, { list: "ordered", number, depth: block.indent }),
3354
- /* @__PURE__ */ jsx37(EditableRegion, { block: block.id, region: REGION, label: labels.numberedItem(number) })
3045
+ return /* @__PURE__ */ jsxs("div", { className: "quoin-list-item", "data-list": "ordered", children: [
3046
+ /* @__PURE__ */ jsx(ListMarker, { list: "ordered", number, depth: block.indent }),
3047
+ /* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: REGION, label: labels.numberedItem(number) })
3355
3048
  ] });
3356
3049
  }
3357
3050
  function TaskItem({ block, controller }) {
3358
3051
  const labels = useLabels();
3359
3052
  const hostId = useRegionDomId(block.id, REGION);
3360
- return /* @__PURE__ */ jsxs22("div", { className: "quoin-task", "data-checked": block.attrs.checked === true, children: [
3361
- /* @__PURE__ */ jsx37(TaskCheckbox, { block, controller, label: labels.task, labelledBy: hostId }),
3362
- /* @__PURE__ */ jsx37(EditableRegion, { id: hostId, block: block.id, region: REGION, label: labels.task })
3053
+ return /* @__PURE__ */ jsxs("div", { className: "quoin-task", "data-checked": block.attrs.checked === true, children: [
3054
+ /* @__PURE__ */ jsx(TaskCheckbox, { block, controller, label: labels.task, labelledBy: hostId }),
3055
+ /* @__PURE__ */ jsx(EditableRegion, { id: hostId, block: block.id, region: REGION, label: labels.task })
3363
3056
  ] });
3364
3057
  }
3365
3058
  var MarkdownBlock = (props) => {
@@ -3367,20 +3060,20 @@ var MarkdownBlock = (props) => {
3367
3060
  const labels = useLabels();
3368
3061
  switch (block.attrs.kind) {
3369
3062
  case "heading":
3370
- return /* @__PURE__ */ jsx37(Heading, { block });
3063
+ return /* @__PURE__ */ jsx(Heading, { block });
3371
3064
  case "bullet":
3372
- return /* @__PURE__ */ jsxs22("div", { className: "quoin-list-item", "data-list": "bullet", children: [
3373
- /* @__PURE__ */ jsx37(ListMarker, { list: "bullet", depth: block.indent }),
3374
- /* @__PURE__ */ jsx37(EditableRegion, { block: block.id, region: REGION, label: labels.bulletItem })
3065
+ return /* @__PURE__ */ jsxs("div", { className: "quoin-list-item", "data-list": "bullet", children: [
3066
+ /* @__PURE__ */ jsx(ListMarker, { list: "bullet", depth: block.indent }),
3067
+ /* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: REGION, label: labels.bulletItem })
3375
3068
  ] });
3376
3069
  case "ordered":
3377
- return /* @__PURE__ */ jsx37(NumberedItem, { ...props });
3070
+ return /* @__PURE__ */ jsx(NumberedItem, { ...props });
3378
3071
  case "task":
3379
- return /* @__PURE__ */ jsx37(TaskItem, { ...props });
3072
+ return /* @__PURE__ */ jsx(TaskItem, { ...props });
3380
3073
  case "quote":
3381
- return /* @__PURE__ */ jsx37("div", { className: "quoin-quote", children: /* @__PURE__ */ jsx37(EditableRegion, { block: block.id, region: REGION, label: labels.quote }) });
3074
+ return /* @__PURE__ */ jsx("div", { className: "quoin-quote", children: /* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: REGION, label: labels.quote }) });
3382
3075
  default:
3383
- return /* @__PURE__ */ jsx37(EditableRegion, { block: block.id, region: REGION, label: labels.paragraph });
3076
+ return /* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: REGION, label: labels.paragraph });
3384
3077
  }
3385
3078
  };
3386
3079
 
@@ -3393,16 +3086,13 @@ function nestedBlockIds({ doc }, blockId) {
3393
3086
  function useNestedBlocks(controller, blockId) {
3394
3087
  return useEditorState(controller, (state) => nestedBlockIds(state, blockId), sameItems);
3395
3088
  }
3396
-
3397
- // src/blocks/text/ToggleBlock.tsx
3398
- import { jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
3399
3089
  var ToggleBlock = ({ block, controller }) => {
3400
3090
  const labels = useLabels();
3401
3091
  const domId = useBlockDomId();
3402
3092
  const nested = useNestedBlocks(controller, block.id);
3403
3093
  const open = useToggleOpen(controller, block);
3404
- return /* @__PURE__ */ jsxs23("div", { className: "quoin-toggle", "data-open": open, children: [
3405
- /* @__PURE__ */ jsx38(
3094
+ return /* @__PURE__ */ jsxs("div", { className: "quoin-toggle", "data-open": open, children: [
3095
+ /* @__PURE__ */ jsx(
3406
3096
  ToggleChevron,
3407
3097
  {
3408
3098
  block,
@@ -3411,7 +3101,7 @@ var ToggleBlock = ({ block, controller }) => {
3411
3101
  controls: nested.length === 0 ? void 0 : nested.map(domId).join(" ")
3412
3102
  }
3413
3103
  ),
3414
- /* @__PURE__ */ jsx38(EditableRegion, { block: block.id, region: "text", label: labels.toggle })
3104
+ /* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: "text", label: labels.toggle })
3415
3105
  ] });
3416
3106
  };
3417
3107
 
@@ -3442,21 +3132,6 @@ function drawnInPlace(definitions, type) {
3442
3132
  }
3443
3133
  var drawsType = (definitions, type) => !Object.hasOwn(inPlaceRenderers, type) || blockByType(definitions, type) !== void 0;
3444
3134
  var opensEditor = (definitions, type) => drawnInPlace(definitions, type) || !drawnAsText(definitions, type, false) && blockByType(definitions, type)?.editor !== void 0;
3445
-
3446
- // src/gutter/turn-into-targets.ts
3447
- import {
3448
- Code as Code3,
3449
- Heading1,
3450
- Heading2,
3451
- Heading3,
3452
- List,
3453
- ListCollapse,
3454
- ListOrdered,
3455
- ListTodo,
3456
- MessageSquare as MessageSquare2,
3457
- TextQuote,
3458
- Type
3459
- } from "lucide-react";
3460
3135
  var HEADING_ICONS = [Heading1, Heading2, Heading3];
3461
3136
  function turnIntoTargets(labels) {
3462
3137
  const { blockNames } = labels;
@@ -3477,50 +3152,44 @@ function turnIntoTargets(labels) {
3477
3152
  line("numberedList", blockNames.numberedList, ListOrdered, { kind: "ordered" }),
3478
3153
  line("todoList", blockNames.todoList, ListTodo, { kind: "task" }),
3479
3154
  line("quote", blockNames.quote, TextQuote, { kind: "quote" }),
3480
- { id: "callout", label: blockNames.callout, icon: MessageSquare2, type: "CALLOUT", attrs: {} },
3155
+ { id: "callout", label: blockNames.callout, icon: MessageSquare, type: "CALLOUT", attrs: {} },
3481
3156
  { id: "toggle", label: blockNames.toggle, icon: ListCollapse, type: "TOGGLE", attrs: {} },
3482
- { id: "code", label: blockNames.code, icon: Code3, type: "CODE", attrs: {} }
3157
+ { id: "code", label: blockNames.code, icon: Code, type: "CODE", attrs: {} }
3483
3158
  ];
3484
3159
  }
3485
-
3486
- // src/gutter/TurnIntoMenu.tsx
3487
- import { jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
3488
3160
  function TurnIntoItems({ kit, controller, blockIds }) {
3489
3161
  const { blockTypes, labels } = useQuoin();
3490
3162
  const targets = turnIntoTargets(labels).filter((target) => drawsType(blockTypes, target.type));
3491
- return targets.map((target) => /* @__PURE__ */ jsxs24(kit.Item, { onSelect: () => runOnBlocks(controller, blockIds, setBlockType(target.type, target.attrs)), children: [
3492
- /* @__PURE__ */ jsx39(MenuIcon, { icon: target.icon }),
3163
+ return targets.map((target) => /* @__PURE__ */ jsxs(kit.Item, { onSelect: () => runOnBlocks(controller, blockIds, setBlockType(target.type, target.attrs)), children: [
3164
+ /* @__PURE__ */ jsx(MenuIcon, { icon: target.icon }),
3493
3165
  target.label
3494
3166
  ] }, target.id));
3495
3167
  }
3496
3168
  function TurnIntoMenu(props) {
3497
3169
  const { kit } = props;
3498
3170
  const labels = useLabels();
3499
- return /* @__PURE__ */ jsxs24(kit.Sub, { children: [
3500
- /* @__PURE__ */ jsxs24(kit.SubTrigger, { children: [
3501
- /* @__PURE__ */ jsx39(MenuIcon, { icon: Repeat2 }),
3171
+ return /* @__PURE__ */ jsxs(kit.Sub, { children: [
3172
+ /* @__PURE__ */ jsxs(kit.SubTrigger, { children: [
3173
+ /* @__PURE__ */ jsx(MenuIcon, { icon: Repeat2 }),
3502
3174
  labels.turnInto
3503
3175
  ] }),
3504
- /* @__PURE__ */ jsx39(kit.SubContent, { children: /* @__PURE__ */ jsx39(TurnIntoItems, { ...props }) })
3176
+ /* @__PURE__ */ jsx(kit.SubContent, { children: /* @__PURE__ */ jsx(TurnIntoItems, { ...props }) })
3505
3177
  ] });
3506
3178
  }
3507
-
3508
- // src/gutter/BlockMenuItems.tsx
3509
- import { Fragment as Fragment7, jsx as jsx40, jsxs as jsxs25 } from "react/jsx-runtime";
3510
3179
  var DESTRUCTIVE = "text-destructive focus:text-destructive";
3511
3180
  function ActionItem({ kit, controller, action, blockIds }) {
3512
3181
  const labels = useLabels();
3513
3182
  const hint = action.shortcut === void 0 ? null : shortcutHint(action.shortcut, controller.isMac, labels);
3514
- return /* @__PURE__ */ jsxs25(
3183
+ return /* @__PURE__ */ jsxs(
3515
3184
  kit.Item,
3516
3185
  {
3517
3186
  className: action.destructive ? DESTRUCTIVE : void 0,
3518
3187
  "aria-keyshortcuts": hint?.aria,
3519
3188
  onSelect: () => action.run(controller, blockIds),
3520
3189
  children: [
3521
- /* @__PURE__ */ jsx40(MenuIcon, { icon: action.icon }),
3190
+ /* @__PURE__ */ jsx(MenuIcon, { icon: action.icon }),
3522
3191
  action.label,
3523
- hint !== null && /* @__PURE__ */ jsx40(kit.Shortcut, { "aria-hidden": "true", children: hint.text })
3192
+ hint !== null && /* @__PURE__ */ jsx(kit.Shortcut, { "aria-hidden": "true", children: hint.text })
3524
3193
  ]
3525
3194
  }
3526
3195
  );
@@ -3532,15 +3201,15 @@ function BlockMenuItems({ kit, controller, blocks, styled, title, actions }) {
3532
3201
  const anyText = styled.some((block) => isTextFlow(state.schema, block));
3533
3202
  const anyMarkdown = styled.some((block) => block.type === "MARKDOWN");
3534
3203
  const allCallouts = styled.length > 0 && styled.every((block) => block.type === "CALLOUT");
3535
- return /* @__PURE__ */ jsxs25(Fragment7, { children: [
3536
- /* @__PURE__ */ jsx40(kit.Label, { className: "text-muted-foreground text-xs", children: title }),
3537
- anyText && /* @__PURE__ */ jsx40(TurnIntoMenu, { kit, controller, blockIds: styled.map((block) => block.id) }),
3538
- anyMarkdown && /* @__PURE__ */ jsx40(ColorMenu, { kit, controller, blocks: styled }),
3539
- allCallouts && /* @__PURE__ */ jsx40(CalloutMenus, { kit, controller, blocks: styled }),
3540
- (anyText || anyMarkdown || allCallouts) && /* @__PURE__ */ jsx40(kit.Separator, {}),
3541
- shown.map((action) => /* @__PURE__ */ jsxs25(Fragment6, { children: [
3542
- action.destructive && /* @__PURE__ */ jsx40(kit.Separator, {}),
3543
- /* @__PURE__ */ jsx40(ActionItem, { kit, controller, action, blockIds })
3204
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3205
+ /* @__PURE__ */ jsx(kit.Label, { className: "text-muted-foreground text-xs", children: title }),
3206
+ anyText && /* @__PURE__ */ jsx(TurnIntoMenu, { kit, controller, blockIds: styled.map((block) => block.id) }),
3207
+ anyMarkdown && /* @__PURE__ */ jsx(ColorMenu, { kit, controller, blocks: styled }),
3208
+ allCallouts && /* @__PURE__ */ jsx(CalloutMenus, { kit, controller, blocks: styled }),
3209
+ (anyText || anyMarkdown || allCallouts) && /* @__PURE__ */ jsx(kit.Separator, {}),
3210
+ shown.map((action) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
3211
+ action.destructive && /* @__PURE__ */ jsx(kit.Separator, {}),
3212
+ /* @__PURE__ */ jsx(ActionItem, { kit, controller, action, blockIds })
3544
3213
  ] }, action.id))
3545
3214
  ] });
3546
3215
  }
@@ -3570,9 +3239,6 @@ var CONTEXT_KIT = {
3570
3239
  SubContent: ContextMenuSubContent,
3571
3240
  SubTrigger: ContextMenuSubTrigger
3572
3241
  };
3573
-
3574
- // src/gutter/use-context-menu-opener.ts
3575
- import { useEffect as useEffect11 } from "react";
3576
3242
  var GUTTER_BLOCK = "data-quoin-gutter-block";
3577
3243
  var OWN_MENU = `[${NATIVE_INTERACTION}], input, textarea, select`;
3578
3244
  function contextBlock(controller, target) {
@@ -3587,7 +3253,7 @@ function contextBlock(controller, target) {
3587
3253
  return block === void 0 || isTextFlow(state.schema, block) ? null : block.id;
3588
3254
  }
3589
3255
  function useContextMenuOpener(controller, store, trigger) {
3590
- useEffect11(() => {
3256
+ useEffect(() => {
3591
3257
  const root = controller.root;
3592
3258
  if (root === null) return;
3593
3259
  const blockOf = (event) => event.target === trigger.current || controller.readOnly ? null : contextBlock(controller, event.target);
@@ -3607,9 +3273,6 @@ function useContextMenuOpener(controller, store, trigger) {
3607
3273
  }, [controller, store, trigger]);
3608
3274
  }
3609
3275
 
3610
- // src/gutter/use-menu-blocks.ts
3611
- import { useCallback as useCallback6, useContext as useContext4, useEffect as useEffect12 } from "react";
3612
-
3613
3276
  // src/gutter/block-type-label.ts
3614
3277
  var KIND_NAMES = {
3615
3278
  paragraph: "text",
@@ -3634,14 +3297,11 @@ function blockTypeLabel(labels, block, definitions, extensionNames = {}) {
3634
3297
  if (name !== void 0) return labels.blockNames[name];
3635
3298
  return nameIn(extensionNames, block.type) ?? blockByType(definitions, block.type)?.label ?? labels.unsupportedBlock;
3636
3299
  }
3637
-
3638
- // src/gutter/extension-block-names.ts
3639
- import { createContext as createContext4 } from "react";
3640
- var ExtensionBlockNames = createContext4({});
3300
+ var ExtensionBlockNames = createContext({});
3641
3301
 
3642
3302
  // src/gutter/use-menu-blocks.ts
3643
3303
  function useLiveBlocks(controller, blockIds) {
3644
- const select = useCallback6(
3304
+ const select = useCallback(
3645
3305
  (state) => blockIds.flatMap((id) => blockById(state.doc, id) ?? []),
3646
3306
  [blockIds]
3647
3307
  );
@@ -3650,23 +3310,20 @@ function useLiveBlocks(controller, blockIds) {
3650
3310
  function useMenuBlocks(controller, store, menu) {
3651
3311
  const labels = useLabels();
3652
3312
  const { blockTypes } = useQuoin();
3653
- const extensionNames = useContext4(ExtensionBlockNames);
3313
+ const extensionNames = useContext(ExtensionBlockNames);
3654
3314
  const blocks = useLiveBlocks(controller, menu.blockIds);
3655
3315
  const styled = useLiveBlocks(controller, menu.styleIds);
3656
3316
  const gone = blocks.length === 0;
3657
- useEffect12(() => {
3317
+ useEffect(() => {
3658
3318
  if (gone) closeBlockMenu(store);
3659
3319
  }, [gone, store]);
3660
3320
  return { blocks, styled, title: gone ? "" : blockTypeLabel(labels, blocks[0], blockTypes, extensionNames) };
3661
3321
  }
3662
-
3663
- // src/gutter/BlockContextMenu.tsx
3664
- import { jsx as jsx41, jsxs as jsxs26 } from "react/jsx-runtime";
3665
3322
  function BlockContextMenuContent({ controller, store, actions, menu }) {
3666
3323
  const labels = useLabels();
3667
3324
  const { blocks, styled, title } = useMenuBlocks(controller, store, menu);
3668
3325
  if (blocks.length === 0) return null;
3669
- return /* @__PURE__ */ jsx41(ContextMenuContent, { "aria-label": labels.blockMenu(title), onCloseAutoFocus: returnFocusToText(controller), children: /* @__PURE__ */ jsx41(
3326
+ return /* @__PURE__ */ jsx(ContextMenuContent, { "aria-label": labels.blockMenu(title), onCloseAutoFocus: returnFocusToText(controller), children: /* @__PURE__ */ jsx(
3670
3327
  BlockMenuItems,
3671
3328
  {
3672
3329
  kit: CONTEXT_KIT,
@@ -3679,11 +3336,11 @@ function BlockContextMenuContent({ controller, store, actions, menu }) {
3679
3336
  ) });
3680
3337
  }
3681
3338
  function BlockContextMenu({ controller, store, actions }) {
3682
- const trigger = useRef17(null);
3339
+ const trigger = useRef(null);
3683
3340
  const menu = useCanvasUi(store, (state) => state.blockMenu);
3684
3341
  const open = menu?.anchor === "pointer";
3685
3342
  useContextMenuOpener(controller, store, trigger);
3686
- return /* @__PURE__ */ jsxs26(
3343
+ return /* @__PURE__ */ jsxs(
3687
3344
  ContextMenu,
3688
3345
  {
3689
3346
  open,
@@ -3691,8 +3348,8 @@ function BlockContextMenu({ controller, store, actions }) {
3691
3348
  if (!next) closeBlockMenu(store);
3692
3349
  },
3693
3350
  children: [
3694
- /* @__PURE__ */ jsx41(ContextMenuTrigger, { ref: trigger, hidden: true }),
3695
- open && /* @__PURE__ */ jsx41(BlockContextMenuContent, { controller, store, actions, menu })
3351
+ /* @__PURE__ */ jsx(ContextMenuTrigger, { ref: trigger, hidden: true }),
3352
+ open && /* @__PURE__ */ jsx(BlockContextMenuContent, { controller, store, actions, menu })
3696
3353
  ]
3697
3354
  }
3698
3355
  );
@@ -3708,14 +3365,6 @@ function blockMenuKeymap(store) {
3708
3365
  };
3709
3366
  return defineExtension({ name: "block-menu", keymap: { "Mod-/": openForHead } });
3710
3367
  }
3711
-
3712
- // src/gutter/Gutter.tsx
3713
- import { useEffect as useEffect15, useRef as useRef20 } from "react";
3714
- import { GripVertical, Plus } from "lucide-react";
3715
-
3716
- // src/drag/DragOverlay.tsx
3717
- import { forwardRef as forwardRef6, useImperativeHandle, useRef as useRef18 } from "react";
3718
- import { Fragment as Fragment8, jsx as jsx42, jsxs as jsxs27 } from "react/jsx-runtime";
3719
3368
  var UNIQUE_OR_FOCUSABLE = ["id", "data-block-id", "contenteditable", "tabindex"];
3720
3369
  function copyOf(shell) {
3721
3370
  const copy = shell.cloneNode(true);
@@ -3726,9 +3375,9 @@ function copyOf(shell) {
3726
3375
  return copy;
3727
3376
  }
3728
3377
  var place = (element, { top, left, width }) => Object.assign(element.style, { top: `${top}px`, left: `${left}px`, width: `${width}px` });
3729
- var DragOverlay = forwardRef6(function DragOverlay2(_props, ref) {
3730
- const ghost = useRef18(null);
3731
- const line = useRef18(null);
3378
+ var DragOverlay = forwardRef(function DragOverlay2(_props, ref) {
3379
+ const ghost = useRef(null);
3380
+ const line = useRef(null);
3732
3381
  useImperativeHandle(ref, () => ({
3733
3382
  show(shells, box) {
3734
3383
  const element = ghost.current;
@@ -3755,8 +3404,8 @@ var DragOverlay = forwardRef6(function DragOverlay2(_props, ref) {
3755
3404
  if (line.current) line.current.hidden = true;
3756
3405
  }
3757
3406
  }));
3758
- return /* @__PURE__ */ jsxs27(Fragment8, { children: [
3759
- /* @__PURE__ */ jsx42(
3407
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3408
+ /* @__PURE__ */ jsx(
3760
3409
  "div",
3761
3410
  {
3762
3411
  ref: ghost,
@@ -3766,7 +3415,7 @@ var DragOverlay = forwardRef6(function DragOverlay2(_props, ref) {
3766
3415
  className: "pointer-events-none fixed z-20 opacity-50"
3767
3416
  }
3768
3417
  ),
3769
- /* @__PURE__ */ jsx42(
3418
+ /* @__PURE__ */ jsx(
3770
3419
  "div",
3771
3420
  {
3772
3421
  ref: line,
@@ -3779,9 +3428,6 @@ var DragOverlay = forwardRef6(function DragOverlay2(_props, ref) {
3779
3428
  ] });
3780
3429
  });
3781
3430
 
3782
- // src/drag/use-block-drag.ts
3783
- import { useEffect as useEffect13, useRef as useRef19 } from "react";
3784
-
3785
3431
  // src/canvas/structure-announcement.ts
3786
3432
  var DELETION_STEPS = /* @__PURE__ */ new Set(["removeBlocks", "setIndent"]);
3787
3433
  function drawnPosition(doc, blockId) {
@@ -4009,9 +3655,9 @@ function pressDragHandle(press) {
4009
3655
  // src/drag/use-block-drag.ts
4010
3656
  function useBlockDrag(controller, store, blockId, overlay) {
4011
3657
  const labels = useLabels();
4012
- const cancel = useRef19(null);
4013
- const dragged = useRef19(false);
4014
- useEffect13(() => () => cancel.current?.(), []);
3658
+ const cancel = useRef(null);
3659
+ const dragged = useRef(false);
3660
+ useEffect(() => () => cancel.current?.(), []);
4015
3661
  return {
4016
3662
  onPointerDown(event) {
4017
3663
  cancel.current?.();
@@ -4058,21 +3704,18 @@ function addBlockBelow(controller, blockId) {
4058
3704
  controller.focus();
4059
3705
  return ok;
4060
3706
  }
4061
-
4062
- // src/gutter/BlockMenu.tsx
4063
- import { jsx as jsx43, jsxs as jsxs28 } from "react/jsx-runtime";
4064
3707
  function BlockMenuContent({ controller, store, actions, menu }) {
4065
3708
  const labels = useLabels();
4066
3709
  const { blocks, styled, title } = useMenuBlocks(controller, store, menu);
4067
3710
  if (blocks.length === 0) return null;
4068
- return /* @__PURE__ */ jsx43(
3711
+ return /* @__PURE__ */ jsx(
4069
3712
  DropdownMenuContent,
4070
3713
  {
4071
3714
  align: "start",
4072
3715
  "aria-label": labels.blockMenu(title),
4073
3716
  "aria-labelledby": void 0,
4074
3717
  onCloseAutoFocus: returnFocusToText(controller),
4075
- children: /* @__PURE__ */ jsx43(
3718
+ children: /* @__PURE__ */ jsx(
4076
3719
  BlockMenuItems,
4077
3720
  {
4078
3721
  kit: DROPDOWN_KIT,
@@ -4089,7 +3732,7 @@ function BlockMenuContent({ controller, store, actions, menu }) {
4089
3732
  function BlockMenu({ controller, store, actions, onOpen, children }) {
4090
3733
  const menu = useCanvasUi(store, (state) => state.blockMenu);
4091
3734
  const open = menu?.anchor === "handle";
4092
- return /* @__PURE__ */ jsxs28(
3735
+ return /* @__PURE__ */ jsxs(
4093
3736
  DropdownMenu,
4094
3737
  {
4095
3738
  open,
@@ -4098,8 +3741,8 @@ function BlockMenu({ controller, store, actions, onOpen, children }) {
4098
3741
  else closeBlockMenu(store);
4099
3742
  },
4100
3743
  children: [
4101
- /* @__PURE__ */ jsx43(DropdownMenuTrigger, { asChild: true, children }),
4102
- open && /* @__PURE__ */ jsx43(BlockMenuContent, { controller, store, actions, menu })
3744
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children }),
3745
+ open && /* @__PURE__ */ jsx(BlockMenuContent, { controller, store, actions, menu })
4103
3746
  ]
4104
3747
  }
4105
3748
  );
@@ -4158,9 +3801,6 @@ function useGutterPosition(controller, gutter, block) {
4158
3801
  };
4159
3802
  }, [controller, gutter, block]);
4160
3803
  }
4161
-
4162
- // src/gutter/use-gutter-target.ts
4163
- import { useEffect as useEffect14, useState as useState11 } from "react";
4164
3804
  var headOf = (state) => headBlockId(state.selection);
4165
3805
  function blockAcross(controller, root, y) {
4166
3806
  const box = root.getBoundingClientRect();
@@ -4170,8 +3810,8 @@ function blockAcross(controller, root, y) {
4170
3810
  function useGutterTarget(controller, store, gutter) {
4171
3811
  const hovered = useCanvasUi(store, (state) => state.hoveredBlock);
4172
3812
  const head = useEditorState(controller, headOf);
4173
- const [focusWithin, setFocusWithin] = useState11(false);
4174
- useEffect14(() => {
3813
+ const [focusWithin, setFocusWithin] = useState(false);
3814
+ useEffect(() => {
4175
3815
  const root = controller.root;
4176
3816
  if (root === null) return;
4177
3817
  const pinned = () => store.get().blockMenu !== null || store.get().drag !== null;
@@ -4193,21 +3833,18 @@ function useGutterTarget(controller, store, gutter) {
4193
3833
  const target = hovered ?? fallback;
4194
3834
  return { target, focused: target !== null && target === fallback };
4195
3835
  }
4196
-
4197
- // src/gutter/Gutter.tsx
4198
- import { Fragment as Fragment9, jsx as jsx44, jsxs as jsxs29 } from "react/jsx-runtime";
4199
3836
  var GUTTER = "absolute top-0 left-0 z-10 flex items-center gap-0.5 pointer-coarse:not-data-current:hidden";
4200
3837
  var ADD_BELOW = "text-muted-foreground pointer-coarse:hidden";
4201
3838
  function Gutter({ controller, store, actions }) {
4202
3839
  const labels = useLabels();
4203
- const element = useRef20(null);
4204
- const overlay = useRef20(null);
4205
- const menuOpenAtPress = useRef20(false);
3840
+ const element = useRef(null);
3841
+ const overlay = useRef(null);
3842
+ const menuOpenAtPress = useRef(false);
4206
3843
  const { target, focused } = useGutterTarget(controller, store, element);
4207
3844
  const menuOpen = useCanvasUi(store, (state) => state.blockMenu !== null);
4208
3845
  const drag = useBlockDrag(controller, store, target, overlay);
4209
3846
  useGutterPosition(controller, element, target);
4210
- useEffect15(() => () => closeBlockMenu(store), [store]);
3847
+ useEffect(() => () => closeBlockMenu(store), [store]);
4211
3848
  const openMenu = () => {
4212
3849
  const { state } = controller.editor;
4213
3850
  if (target !== null && state.doc.index.has(target)) openBlockMenu(store, state, target);
@@ -4215,8 +3852,8 @@ function Gutter({ controller, store, actions }) {
4215
3852
  const addBelow = () => {
4216
3853
  if (target !== null) addBlockBelow(controller, target);
4217
3854
  };
4218
- return /* @__PURE__ */ jsxs29(Fragment9, { children: [
4219
- /* @__PURE__ */ jsxs29(
3855
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3856
+ /* @__PURE__ */ jsxs(
4220
3857
  "div",
4221
3858
  {
4222
3859
  ref: element,
@@ -4224,7 +3861,7 @@ function Gutter({ controller, store, actions }) {
4224
3861
  "data-current": focused || menuOpen ? "" : void 0,
4225
3862
  ...{ [GUTTER_BLOCK]: target ?? void 0 },
4226
3863
  children: [
4227
- /* @__PURE__ */ jsx44(
3864
+ /* @__PURE__ */ jsx(
4228
3865
  Button,
4229
3866
  {
4230
3867
  type: "button",
@@ -4235,10 +3872,10 @@ function Gutter({ controller, store, actions }) {
4235
3872
  className: ADD_BELOW,
4236
3873
  onPointerDown: keepFocus,
4237
3874
  onClick: addBelow,
4238
- children: /* @__PURE__ */ jsx44(Plus, {})
3875
+ children: /* @__PURE__ */ jsx(Plus, {})
4239
3876
  }
4240
3877
  ),
4241
- /* @__PURE__ */ jsx44(BlockMenu, { controller, store, actions, onOpen: openMenu, children: /* @__PURE__ */ jsx44(
3878
+ /* @__PURE__ */ jsx(BlockMenu, { controller, store, actions, onOpen: openMenu, children: /* @__PURE__ */ jsx(
4242
3879
  Button,
4243
3880
  {
4244
3881
  type: "button",
@@ -4257,13 +3894,13 @@ function Gutter({ controller, store, actions }) {
4257
3894
  menuOpenAtPress.current = false;
4258
3895
  if (!drag.takeClick(event) && !closing) openMenu();
4259
3896
  },
4260
- children: /* @__PURE__ */ jsx44(GripVertical, {})
3897
+ children: /* @__PURE__ */ jsx(GripVertical, {})
4261
3898
  }
4262
3899
  ) })
4263
3900
  ]
4264
3901
  }
4265
3902
  ),
4266
- /* @__PURE__ */ jsx44(DragOverlay, { ref: overlay })
3903
+ /* @__PURE__ */ jsx(DragOverlay, { ref: overlay })
4267
3904
  ] });
4268
3905
  }
4269
3906
 
@@ -4274,15 +3911,6 @@ function resolveLabels(overrides) {
4274
3911
  return given.length === 0 ? englishLabels : { ...englishLabels, ...Object.fromEntries(given) };
4275
3912
  }
4276
3913
 
4277
- // src/menus/bubble/bubble-extension.tsx
4278
- import { createContext as createContext5, useContext as useContext5 } from "react";
4279
-
4280
- // src/menus/bubble/BubbleToolbar.tsx
4281
- import { useMemo as useMemo7 } from "react";
4282
-
4283
- // src/menus/floating/use-selection-anchor.ts
4284
- import { useMemo as useMemo6, useState as useState12 } from "react";
4285
-
4286
3914
  // src/menus/floating/range-rect.ts
4287
3915
  var TEXT_NODE = 3;
4288
3916
  function lineBox(rect, host) {
@@ -4340,7 +3968,7 @@ function selectionHost(controller) {
4340
3968
  return (first && controller.registry.get(first.block, first.region)) ?? controller.root ?? void 0;
4341
3969
  }
4342
3970
  function useSelectionAnchor(controller, state) {
4343
- const anchor = useMemo6(
3971
+ const anchor = useMemo(
4344
3972
  () => ({
4345
3973
  current: state.selection === null ? null : virtualAnchor(
4346
3974
  () => selectionRect(controller),
@@ -4349,31 +3977,24 @@ function useSelectionAnchor(controller, state) {
4349
3977
  }),
4350
3978
  [controller, state]
4351
3979
  );
4352
- const [side, setSide] = useState12("top");
3980
+ const [side, setSide] = useState("top");
4353
3981
  useIsomorphicLayoutEffect(() => {
4354
3982
  const rect = selectionRect(controller);
4355
3983
  if (rect) setSide(rect.top < ROOM_ABOVE ? "bottom" : "top");
4356
3984
  }, [controller, state]);
4357
3985
  return { anchor, side };
4358
3986
  }
4359
-
4360
- // src/menus/bubble/AlignDropdown.tsx
4361
- import { AlignCenter as AlignCenter2, AlignJustify, AlignLeft as AlignLeft2, AlignRight as AlignRight2, CheckIcon as CheckIcon5 } from "lucide-react";
4362
-
4363
- // src/menus/bubble/ToolbarMenu.tsx
4364
- import { useRef as useRef21 } from "react";
4365
- import { jsx as jsx45, jsxs as jsxs30 } from "react/jsx-runtime";
4366
3987
  function ToolbarMenu({ controller, trigger, children }) {
4367
- const fromToolbar = useRef21(false);
4368
- return /* @__PURE__ */ jsxs30(
3988
+ const fromToolbar = useRef(false);
3989
+ return /* @__PURE__ */ jsxs(
4369
3990
  DropdownMenu,
4370
3991
  {
4371
3992
  onOpenChange: (open) => {
4372
3993
  if (open) fromToolbar.current = isBubblePart(document.activeElement, controller);
4373
3994
  },
4374
3995
  children: [
4375
- /* @__PURE__ */ jsx45(DropdownMenuTrigger, { asChild: true, children: trigger }),
4376
- /* @__PURE__ */ jsx45(
3996
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: trigger }),
3997
+ /* @__PURE__ */ jsx(
4377
3998
  DropdownMenuContent,
4378
3999
  {
4379
4000
  align: "start",
@@ -4388,10 +4009,7 @@ function ToolbarMenu({ controller, trigger, children }) {
4388
4009
  }
4389
4010
  );
4390
4011
  }
4391
-
4392
- // src/menus/bubble/AlignDropdown.tsx
4393
- import { jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
4394
- var ICONS = { left: AlignLeft2, center: AlignCenter2, right: AlignRight2, justify: AlignJustify };
4012
+ var ICONS = { left: AlignLeft, center: AlignCenter, right: AlignRight, justify: AlignJustify };
4395
4013
  var ALIGNS2 = Object.keys(ICONS);
4396
4014
  var LABEL_KEYS = { left: "alignLeft", center: "alignCenter", right: "alignRight", justify: "alignJustify" };
4397
4015
  function sharedAlign(state) {
@@ -4404,17 +4022,13 @@ function AlignDropdown({ controller, state }) {
4404
4022
  const labels = useLabels();
4405
4023
  const value = sharedAlign(state);
4406
4024
  if (value === null) return null;
4407
- const Icon = value === "" ? AlignLeft2 : ICONS[value];
4408
- const trigger = /* @__PURE__ */ jsx46(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.align, children: /* @__PURE__ */ jsx46(Icon, {}) });
4409
- return /* @__PURE__ */ jsx46(ToolbarMenu, { controller, trigger, children: /* @__PURE__ */ jsx46(DropdownMenuRadioGroup, { value, onValueChange: (align) => controller.run(setTextAlign(align)), children: ALIGNS2.map((align) => /* @__PURE__ */ jsxs31(DropdownMenuRadioItem, { value: align, indicator: /* @__PURE__ */ jsx46(CheckIcon5, { className: "size-4" }), children: [
4410
- /* @__PURE__ */ jsx46(MenuIcon, { icon: ICONS[align] }),
4025
+ const Icon = value === "" ? AlignLeft : ICONS[value];
4026
+ const trigger = /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.align, children: /* @__PURE__ */ jsx(Icon, {}) });
4027
+ return /* @__PURE__ */ jsx(ToolbarMenu, { controller, trigger, children: /* @__PURE__ */ jsx(DropdownMenuRadioGroup, { value, onValueChange: (align) => controller.run(setTextAlign(align)), children: ALIGNS2.map((align) => /* @__PURE__ */ jsxs(DropdownMenuRadioItem, { value: align, indicator: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }), children: [
4028
+ /* @__PURE__ */ jsx(MenuIcon, { icon: ICONS[align] }),
4411
4029
  labels[LABEL_KEYS[align]]
4412
4030
  ] }, align)) }) });
4413
4031
  }
4414
-
4415
- // src/menus/bubble/ColorPopover.tsx
4416
- import { Baseline } from "lucide-react";
4417
- import { jsx as jsx47 } from "react/jsx-runtime";
4418
4032
  var MARKS = { color: "color", background: "highlight" };
4419
4033
  function selectionColor(state, mark) {
4420
4034
  const names = /* @__PURE__ */ new Set();
@@ -4433,30 +4047,23 @@ function colorCommand(key, name) {
4433
4047
  function ColorPopover({ controller, state }) {
4434
4048
  const labels = useLabels();
4435
4049
  const value = { color: selectionColor(state, MARKS.color), background: selectionColor(state, MARKS.background) };
4436
- const trigger = /* @__PURE__ */ jsx47(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.color, children: /* @__PURE__ */ jsx47(Baseline, {}) });
4437
- return /* @__PURE__ */ jsx47(ToolbarMenu, { controller, trigger, children: /* @__PURE__ */ jsx47(ColorGroups, { kit: DROPDOWN_KIT, value, onPick: (key, name) => controller.run(colorCommand(key, name)) }) });
4050
+ const trigger = /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.color, children: /* @__PURE__ */ jsx(Baseline, {}) });
4051
+ return /* @__PURE__ */ jsx(ToolbarMenu, { controller, trigger, children: /* @__PURE__ */ jsx(ColorGroups, { kit: DROPDOWN_KIT, value, onPick: (key, name) => controller.run(colorCommand(key, name)) }) });
4438
4052
  }
4439
-
4440
- // src/menus/bubble/TurnIntoDropdown.tsx
4441
- import { ChevronDown } from "lucide-react";
4442
- import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
4443
4053
  function TurnIntoDropdown({ controller, state }) {
4444
4054
  const labels = useLabels();
4445
- const trigger = /* @__PURE__ */ jsxs32(Button, { type: "button", variant: "ghost", size: "sm", className: "gap-1 px-2 has-[>svg]:px-2", children: [
4055
+ const trigger = /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", className: "gap-1 px-2 has-[>svg]:px-2", children: [
4446
4056
  labels.turnInto,
4447
- /* @__PURE__ */ jsx48(ChevronDown, {})
4057
+ /* @__PURE__ */ jsx(ChevronDown, {})
4448
4058
  ] });
4449
- return /* @__PURE__ */ jsx48(ToolbarMenu, { controller, trigger, children: /* @__PURE__ */ jsx48(TurnIntoItems, { kit: DROPDOWN_KIT, controller, blockIds: selectedBlockIds(state.doc, state.selection) }) });
4059
+ return /* @__PURE__ */ jsx(ToolbarMenu, { controller, trigger, children: /* @__PURE__ */ jsx(TurnIntoItems, { kit: DROPDOWN_KIT, controller, blockIds: selectedBlockIds(state.doc, state.selection) }) });
4450
4060
  }
4451
-
4452
- // src/menus/bubble/BubbleToolbar.tsx
4453
- import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
4454
4061
  var DIVIDER = "mx-0.5 h-5 w-px shrink-0 bg-border";
4455
4062
  function BubbleToolbar({ controller, labels, store, extraItems }) {
4456
4063
  const state = useEditorState(controller, wholeState);
4457
4064
  const { anchor, side } = useSelectionAnchor(controller, state);
4458
4065
  const roving = useRovingFocus();
4459
- const items = useMemo7(() => bubbleItems(labels, () => store.set({ linkPopover: { open: true } })), [labels, store]);
4066
+ const items = useMemo(() => bubbleItems(labels, () => store.set({ linkPopover: { open: true } })), [labels, store]);
4460
4067
  useFocusKey(controller, roving.focusCurrent);
4461
4068
  const onKeyDown = (event) => {
4462
4069
  if (!roving.owns(event.target)) return;
@@ -4465,10 +4072,10 @@ function BubbleToolbar({ controller, labels, store, extraItems }) {
4465
4072
  controller.focus();
4466
4073
  } else roving.onKeyDown(event);
4467
4074
  };
4468
- const button = (item) => /* @__PURE__ */ jsx49(ToolbarButton, { item, state, controller }, item.id);
4469
- return /* @__PURE__ */ jsxs33(Popover, { open: true, modal: false, children: [
4470
- /* @__PURE__ */ jsx49(PopoverAnchor, { virtualRef: anchor }),
4471
- /* @__PURE__ */ jsxs33(
4075
+ const button = (item) => /* @__PURE__ */ jsx(ToolbarButton, { item, state, controller }, item.id);
4076
+ return /* @__PURE__ */ jsxs(Popover, { open: true, modal: false, children: [
4077
+ /* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }),
4078
+ /* @__PURE__ */ jsxs(
4472
4079
  PopoverContent,
4473
4080
  {
4474
4081
  ref: roving.ref,
@@ -4484,11 +4091,11 @@ function BubbleToolbar({ controller, labels, store, extraItems }) {
4484
4091
  onKeyDown,
4485
4092
  ...bubblePart(controller),
4486
4093
  children: [
4487
- /* @__PURE__ */ jsx49(TurnIntoDropdown, { controller, state }),
4488
- /* @__PURE__ */ jsx49("span", { "aria-hidden": "true", className: DIVIDER }),
4094
+ /* @__PURE__ */ jsx(TurnIntoDropdown, { controller, state }),
4095
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: DIVIDER }),
4489
4096
  items.inline.map(button),
4490
- /* @__PURE__ */ jsx49(ColorPopover, { controller, state }),
4491
- /* @__PURE__ */ jsx49(AlignDropdown, { controller, state }),
4097
+ /* @__PURE__ */ jsx(ColorPopover, { controller, state }),
4098
+ /* @__PURE__ */ jsx(AlignDropdown, { controller, state }),
4492
4099
  items.scripts.map(button),
4493
4100
  extraItems.map(button)
4494
4101
  ]
@@ -4496,13 +4103,10 @@ function BubbleToolbar({ controller, labels, store, extraItems }) {
4496
4103
  )
4497
4104
  ] });
4498
4105
  }
4499
-
4500
- // src/ui/use-media-query.ts
4501
- import { useCallback as useCallback7, useSyncExternalStore as useSyncExternalStore3 } from "react";
4502
4106
  var listOf = (query) => typeof window.matchMedia === "function" ? window.matchMedia(query) : null;
4503
4107
  var readOnServer = () => false;
4504
4108
  function useMediaQuery(query, unsupported) {
4505
- const subscribe3 = useCallback7(
4109
+ const subscribe3 = useCallback(
4506
4110
  (notify) => {
4507
4111
  const list = listOf(query);
4508
4112
  list?.addEventListener("change", notify);
@@ -4511,7 +4115,7 @@ function useMediaQuery(query, unsupported) {
4511
4115
  [query]
4512
4116
  );
4513
4117
  const read2 = () => listOf(query)?.matches ?? unsupported;
4514
- return useSyncExternalStore3(subscribe3, read2, readOnServer);
4118
+ return useSyncExternalStore(subscribe3, read2, readOnServer);
4515
4119
  }
4516
4120
 
4517
4121
  // src/menus/bubble/use-fine-pointer.ts
@@ -4526,31 +4130,21 @@ function useBubbleVisibility(controller) {
4526
4130
  const settled = useSelectionSettled(controller);
4527
4131
  return range && !readOnly && fine && settled;
4528
4132
  }
4529
-
4530
- // src/menus/bubble/bubble-extension.tsx
4531
- import { jsx as jsx50 } from "react/jsx-runtime";
4532
4133
  var NO_ITEMS = [];
4533
- var BubbleItemsContext = createContext5(NO_ITEMS);
4134
+ var BubbleItemsContext = createContext(NO_ITEMS);
4534
4135
  var BubbleItemsProvider = BubbleItemsContext.Provider;
4535
4136
  function BubbleOverlay({ controller }) {
4536
4137
  const visible = useBubbleVisibility(controller);
4537
4138
  const labels = useLabels();
4538
4139
  const store = useCanvasUiStore();
4539
- const extraItems = useContext5(BubbleItemsContext);
4140
+ const extraItems = useContext(BubbleItemsContext);
4540
4141
  if (!visible) return null;
4541
- return /* @__PURE__ */ jsx50(BubbleToolbar, { controller, labels, store, extraItems });
4142
+ return /* @__PURE__ */ jsx(BubbleToolbar, { controller, labels, store, extraItems });
4542
4143
  }
4543
4144
  function bubbleExtension() {
4544
4145
  return defineExtension({ name: "bubble", ui: { overlays: [BubbleOverlay] } });
4545
4146
  }
4546
4147
 
4547
- // src/menus/link/link-extension.tsx
4548
- import { useEffect as useEffect19 } from "react";
4549
-
4550
- // src/menus/link/LinkHoverCard.tsx
4551
- import { ExternalLink, Pencil as Pencil2, Unlink } from "lucide-react";
4552
- import { useMemo as useMemo8, useRef as useRef23 } from "react";
4553
-
4554
4148
  // src/menus/link/link-at-selection.ts
4555
4149
  function linkAround(state, from, to = from) {
4556
4150
  if (from.block !== to.block || from.region !== to.region) return null;
@@ -4609,12 +4203,9 @@ function unlinkRange({ block, region, from, to }) {
4609
4203
  return true;
4610
4204
  };
4611
4205
  }
4612
-
4613
- // src/menus/link/use-rested-value.ts
4614
- import { useEffect as useEffect16, useState as useState13 } from "react";
4615
4206
  function useRestedValue(value, delay) {
4616
- const [rested, setRested] = useState13(null);
4617
- useEffect16(() => {
4207
+ const [rested, setRested] = useState(null);
4208
+ useEffect(() => {
4618
4209
  if (value === null) return;
4619
4210
  const timer = setTimeout(() => setRested(value), delay);
4620
4211
  return () => {
@@ -4637,19 +4228,16 @@ function useCaretInLink(controller, delay) {
4637
4228
  const settled = useSelectionSettled(controller);
4638
4229
  return useRestedValue(settled ? key : null, delay) !== null;
4639
4230
  }
4640
-
4641
- // src/menus/link/use-pointer-link.ts
4642
- import { useCallback as useCallback8, useEffect as useEffect17, useRef as useRef22, useState as useState14 } from "react";
4643
4231
  function usePointerLink(controller, card, delay) {
4644
- const [element, setElement] = useState14(null);
4645
- const shown = useRef22(null);
4646
- const timer = useRef22(void 0);
4647
- const show = useCallback8((next) => {
4232
+ const [element, setElement] = useState(null);
4233
+ const shown = useRef(null);
4234
+ const timer = useRef(void 0);
4235
+ const show = useCallback((next) => {
4648
4236
  clearTimeout(timer.current);
4649
4237
  shown.current = next;
4650
4238
  setElement(next);
4651
4239
  }, []);
4652
- useEffect17(() => {
4240
+ useEffect(() => {
4653
4241
  const onOver = (event) => {
4654
4242
  if (event.pointerType === "touch" || event.buttons > 0) return;
4655
4243
  const onCard = !!card.current?.contains(event.target);
@@ -4663,22 +4251,19 @@ function usePointerLink(controller, card, delay) {
4663
4251
  clearTimeout(timer.current);
4664
4252
  };
4665
4253
  }, [controller, card, delay, show]);
4666
- return { element, dismiss: useCallback8(() => show(null), [show]) };
4254
+ return { element, dismiss: useCallback(() => show(null), [show]) };
4667
4255
  }
4668
-
4669
- // src/menus/link/LinkHoverCard.tsx
4670
- import { jsx as jsx51, jsxs as jsxs34 } from "react/jsx-runtime";
4671
4256
  var REST_MS = 300;
4672
4257
  var URL_LENGTH = 48;
4673
4258
  var CARD = "flex w-auto items-center gap-0.5 py-1 ps-3 pe-1 shadow-md";
4674
4259
  var ADDRESS = "me-1 whitespace-nowrap text-sm text-muted-foreground";
4675
4260
  function LinkCard({ controller, labels, store, cardRef, element, onUnlinked }) {
4676
4261
  const state = useEditorState(controller, wholeState);
4677
- const link = useMemo8(
4262
+ const link = useMemo(
4678
4263
  () => element === null ? linkAtSelection(state) : linkAtElement(controller, state, element),
4679
4264
  [controller, state, element]
4680
4265
  );
4681
- const anchor = useMemo8(() => {
4266
+ const anchor = useMemo(() => {
4682
4267
  if (link === null) return { current: null };
4683
4268
  const { range } = link;
4684
4269
  const host = () => controller.registry.get(range.block, range.region);
@@ -4699,9 +4284,9 @@ function LinkCard({ controller, labels, store, cardRef, element, onUnlinked }) {
4699
4284
  controller.run(unlinkRange(link.range));
4700
4285
  onUnlinked();
4701
4286
  };
4702
- return /* @__PURE__ */ jsxs34(Popover, { open: true, modal: false, children: [
4703
- /* @__PURE__ */ jsx51(PopoverAnchor, { virtualRef: anchor }),
4704
- /* @__PURE__ */ jsxs34(
4287
+ return /* @__PURE__ */ jsxs(Popover, { open: true, modal: false, children: [
4288
+ /* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }),
4289
+ /* @__PURE__ */ jsxs(
4705
4290
  PopoverContent,
4706
4291
  {
4707
4292
  ref: cardRef,
@@ -4714,27 +4299,23 @@ function LinkCard({ controller, labels, store, cardRef, element, onUnlinked }) {
4714
4299
  onPointerDown: keepFocus,
4715
4300
  onMouseDown: keepFocus,
4716
4301
  children: [
4717
- /* @__PURE__ */ jsx51("span", { className: ADDRESS, title: address === link.href ? void 0 : link.href, children: address }),
4718
- href !== null && /* @__PURE__ */ jsx51(Button, { asChild: true, variant: "ghost", size: "icon-sm", children: /* @__PURE__ */ jsx51("a", { href, target: "_blank", rel: "noopener noreferrer", "aria-label": labels.linkOpen, children: /* @__PURE__ */ jsx51(ExternalLink, {}) }) }),
4719
- /* @__PURE__ */ jsx51(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.linkEdit, onClick: edit2, children: /* @__PURE__ */ jsx51(Pencil2, {}) }),
4720
- /* @__PURE__ */ jsx51(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.linkRemove, onClick: unlink, children: /* @__PURE__ */ jsx51(Unlink, {}) })
4302
+ /* @__PURE__ */ jsx("span", { className: ADDRESS, title: address === link.href ? void 0 : link.href, children: address }),
4303
+ href !== null && /* @__PURE__ */ jsx(Button, { asChild: true, variant: "ghost", size: "icon-sm", children: /* @__PURE__ */ jsx("a", { href, target: "_blank", rel: "noopener noreferrer", "aria-label": labels.linkOpen, children: /* @__PURE__ */ jsx(ExternalLink, {}) }) }),
4304
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.linkEdit, onClick: edit2, children: /* @__PURE__ */ jsx(Pencil, {}) }),
4305
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.linkRemove, onClick: unlink, children: /* @__PURE__ */ jsx(Unlink, {}) })
4721
4306
  ]
4722
4307
  }
4723
4308
  )
4724
4309
  ] });
4725
4310
  }
4726
4311
  function LinkHoverCard(props) {
4727
- const cardRef = useRef23(null);
4312
+ const cardRef = useRef(null);
4728
4313
  const pointer = usePointerLink(props.controller, cardRef, REST_MS);
4729
4314
  const caretInLink = useCaretInLink(props.controller, REST_MS);
4730
4315
  if (pointer.element === null && !caretInLink) return null;
4731
- return /* @__PURE__ */ jsx51(LinkCard, { ...props, cardRef, element: pointer.element, onUnlinked: pointer.dismiss });
4316
+ return /* @__PURE__ */ jsx(LinkCard, { ...props, cardRef, element: pointer.element, onUnlinked: pointer.dismiss });
4732
4317
  }
4733
4318
 
4734
- // src/menus/link/LinkPopover.tsx
4735
- import { Check as Check3, ExternalLink as ExternalLink2, Unlink as Unlink2 } from "lucide-react";
4736
- import { useId as useId5, useMemo as useMemo9, useState as useState15 } from "react";
4737
-
4738
4319
  // src/menus/link/apply-link.ts
4739
4320
  function insertLinkedText(value, href, caret) {
4740
4321
  const safe = sanitizeHref(href);
@@ -4757,9 +4338,6 @@ function applyLink(href, value) {
4757
4338
  return setLink(href, link?.title)(state, dispatch);
4758
4339
  };
4759
4340
  }
4760
-
4761
- // src/menus/link/LinkPopover.tsx
4762
- import { jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
4763
4341
  var CONTENT2 = "w-80 p-2 shadow-md";
4764
4342
  var FIELD2 = "h-8";
4765
4343
  var MESSAGE = "mt-1.5 px-1 text-sm text-destructive";
@@ -4775,11 +4353,11 @@ function popoverAnchor(controller, link) {
4775
4353
  );
4776
4354
  }
4777
4355
  function LinkPopover({ controller, labels, onClose }) {
4778
- const [link] = useState15(() => linkAtSelection(controller.editor.state));
4779
- const [address, setAddress] = useState15(link?.href ?? "");
4780
- const [invalid, setInvalid] = useState15(false);
4781
- const messageId = useId5();
4782
- const anchor = useMemo9(() => ({ current: popoverAnchor(controller, link) }), [controller, link]);
4356
+ const [link] = useState(() => linkAtSelection(controller.editor.state));
4357
+ const [address, setAddress] = useState(link?.href ?? "");
4358
+ const [invalid, setInvalid] = useState(false);
4359
+ const messageId = useId();
4360
+ const anchor = useMemo(() => ({ current: popoverAnchor(controller, link) }), [controller, link]);
4783
4361
  const openHref = link && sanitizeHref(link.href);
4784
4362
  const backToText = () => {
4785
4363
  onClose();
@@ -4800,7 +4378,7 @@ function LinkPopover({ controller, labels, onClose }) {
4800
4378
  controller.run(unsetLink);
4801
4379
  backToText();
4802
4380
  };
4803
- return /* @__PURE__ */ jsxs35(
4381
+ return /* @__PURE__ */ jsxs(
4804
4382
  Popover,
4805
4383
  {
4806
4384
  open: true,
@@ -4809,8 +4387,8 @@ function LinkPopover({ controller, labels, onClose }) {
4809
4387
  if (!open) onClose();
4810
4388
  },
4811
4389
  children: [
4812
- /* @__PURE__ */ jsx52(PopoverAnchor, { virtualRef: anchor }),
4813
- /* @__PURE__ */ jsxs35(
4390
+ /* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }),
4391
+ /* @__PURE__ */ jsxs(
4814
4392
  PopoverContent,
4815
4393
  {
4816
4394
  "aria-label": labels.link,
@@ -4823,8 +4401,8 @@ function LinkPopover({ controller, labels, onClose }) {
4823
4401
  backToText();
4824
4402
  },
4825
4403
  children: [
4826
- /* @__PURE__ */ jsxs35("form", { noValidate: true, className: "flex items-center gap-0.5", onSubmit: apply, children: [
4827
- /* @__PURE__ */ jsx52(
4404
+ /* @__PURE__ */ jsxs("form", { noValidate: true, className: "flex items-center gap-0.5", onSubmit: apply, children: [
4405
+ /* @__PURE__ */ jsx(
4828
4406
  Input,
4829
4407
  {
4830
4408
  type: "url",
@@ -4836,11 +4414,11 @@ function LinkPopover({ controller, labels, onClose }) {
4836
4414
  onChange
4837
4415
  }
4838
4416
  ),
4839
- /* @__PURE__ */ jsx52(Button, { type: "submit", variant: "ghost", size: "icon-sm", "aria-label": labels.linkApply, children: /* @__PURE__ */ jsx52(Check3, {}) }),
4840
- openHref && /* @__PURE__ */ jsx52(Button, { asChild: true, variant: "ghost", size: "icon-sm", children: /* @__PURE__ */ jsx52("a", { href: openHref, target: "_blank", rel: "noopener noreferrer", "aria-label": labels.linkOpen, children: /* @__PURE__ */ jsx52(ExternalLink2, {}) }) }),
4841
- link !== null && /* @__PURE__ */ jsx52(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.linkRemove, onClick: remove, children: /* @__PURE__ */ jsx52(Unlink2, {}) })
4417
+ /* @__PURE__ */ jsx(Button, { type: "submit", variant: "ghost", size: "icon-sm", "aria-label": labels.linkApply, children: /* @__PURE__ */ jsx(Check, {}) }),
4418
+ openHref && /* @__PURE__ */ jsx(Button, { asChild: true, variant: "ghost", size: "icon-sm", children: /* @__PURE__ */ jsx("a", { href: openHref, target: "_blank", rel: "noopener noreferrer", "aria-label": labels.linkOpen, children: /* @__PURE__ */ jsx(ExternalLink, {}) }) }),
4419
+ link !== null && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.linkRemove, onClick: remove, children: /* @__PURE__ */ jsx(Unlink, {}) })
4842
4420
  ] }),
4843
- invalid && /* @__PURE__ */ jsx52("p", { id: messageId, role: "alert", className: MESSAGE, children: labels.invalidLink })
4421
+ invalid && /* @__PURE__ */ jsx("p", { id: messageId, role: "alert", className: MESSAGE, children: labels.invalidLink })
4844
4422
  ]
4845
4423
  }
4846
4424
  )
@@ -4848,11 +4426,8 @@ function LinkPopover({ controller, labels, onClose }) {
4848
4426
  }
4849
4427
  );
4850
4428
  }
4851
-
4852
- // src/menus/link/use-link-clicks.ts
4853
- import { useEffect as useEffect18 } from "react";
4854
4429
  function useLinkClicks(controller) {
4855
- useEffect18(() => {
4430
+ useEffect(() => {
4856
4431
  const onClick = (event) => {
4857
4432
  const link = linkElementAt(controller, event.target);
4858
4433
  if (link === null || controller.readOnly) return;
@@ -4863,9 +4438,6 @@ function useLinkClicks(controller) {
4863
4438
  return () => document.removeEventListener("click", onClick, true);
4864
4439
  }, [controller]);
4865
4440
  }
4866
-
4867
- // src/menus/link/link-extension.tsx
4868
- import { jsx as jsx53 } from "react/jsx-runtime";
4869
4441
  var isPopoverOpen = (state) => state.linkPopover.open;
4870
4442
  function LinkOverlay({ controller }) {
4871
4443
  const labels = useLabels();
@@ -4873,12 +4445,12 @@ function LinkOverlay({ controller }) {
4873
4445
  const popoverOpen = useCanvasUi(store, isPopoverOpen);
4874
4446
  const readOnly = useReadOnly(controller);
4875
4447
  useLinkClicks(controller);
4876
- useEffect19(() => {
4448
+ useEffect(() => {
4877
4449
  if (readOnly && store.get().linkPopover.open) store.set({ linkPopover: { open: false } });
4878
4450
  }, [readOnly, store]);
4879
4451
  if (readOnly) return null;
4880
- if (!popoverOpen) return /* @__PURE__ */ jsx53(LinkHoverCard, { controller, labels, store });
4881
- return /* @__PURE__ */ jsx53(LinkPopover, { controller, labels, onClose: () => store.set({ linkPopover: { open: false } }) });
4452
+ if (!popoverOpen) return /* @__PURE__ */ jsx(LinkHoverCard, { controller, labels, store });
4453
+ return /* @__PURE__ */ jsx(LinkPopover, { controller, labels, onClose: () => store.set({ linkPopover: { open: false } }) });
4882
4454
  }
4883
4455
  function linkExtension(store) {
4884
4456
  const openPopover = (state, dispatch) => {
@@ -4889,9 +4461,6 @@ function linkExtension(store) {
4889
4461
  return defineExtension({ name: "link", keymap: { "Mod-k": openPopover }, ui: { overlays: [LinkOverlay] } });
4890
4462
  }
4891
4463
 
4892
- // src/menus/slash/slash-extension.tsx
4893
- import { createContext as createContext6, useContext as useContext6, useMemo as useMemo13 } from "react";
4894
-
4895
4464
  // src/menus/suggestion/find-trigger.ts
4896
4465
  var DEFAULT_MAX_LENGTH = 40;
4897
4466
  var NO_TRIGGER_TYPES = /* @__PURE__ */ new Set(["CODE", "TABLE"]);
@@ -4977,9 +4546,6 @@ function dismissSuggestion(key) {
4977
4546
 
4978
4547
  // src/menus/slash/slash-key.ts
4979
4548
  var slashKey = createPluginKey("slash");
4980
-
4981
- // src/menus/slash/slash-items.ts
4982
- import { Image as Image3, Minus, Paperclip as Paperclip2 } from "lucide-react";
4983
4549
  var DETAILS = {
4984
4550
  text: { group: "basic", keywords: ["paragraph", "plain"], shortcut: "Mod-Alt-0" },
4985
4551
  heading1: { group: "basic", keywords: ["h1", "title", "#"], shortcut: "Mod-Alt-1" },
@@ -5012,8 +4578,8 @@ function builtInSlashItems(labels, definitions) {
5012
4578
  const { blockNames } = labels;
5013
4579
  const insertions = {
5014
4580
  divider: { label: blockNames.divider, icon: Minus, type: "DIVIDER", attrs: {} },
5015
- image: { label: blockNames.image, icon: Image3, type: "IMAGE", attrs: {} },
5016
- file: { label: blockNames.file, icon: Paperclip2, type: "FILE", attrs: {} }
4581
+ image: { label: blockNames.image, icon: Image, type: "IMAGE", attrs: {} },
4582
+ file: { label: blockNames.file, icon: Paperclip, type: "FILE", attrs: {} }
5017
4583
  };
5018
4584
  for (const target of turnIntoTargets(labels)) insertions[target.id] = target;
5019
4585
  return Object.keys(DETAILS).flatMap((id) => {
@@ -5022,31 +4588,28 @@ function builtInSlashItems(labels, definitions) {
5022
4588
  return [insertionItem(id, insertion, labels, definitions)];
5023
4589
  });
5024
4590
  }
5025
- function initialBlock({ schema }, { type, initialData }) {
5026
- const data = initialData?.();
4591
+ function initialBlock({ schema }, definition, onError) {
4592
+ const { type } = definition;
4593
+ const data = seedData(definition, onError());
4594
+ if (data === null) return null;
5027
4595
  if (data === void 0) return { type };
5028
4596
  return { type, ...specFor(schema, type).fromData(data, createBlockCodec(schema).context) };
5029
4597
  }
5030
- function blockTypeSlashItems(definitions) {
4598
+ var refuse = () => false;
4599
+ function blockTypeSlashItems(definitions, onError = () => void 0) {
5031
4600
  return paletteBlocks(definitions).filter((definition) => !BUILT_IN_TYPES.has(definition.type)).map((definition) => ({
5032
4601
  id: `block:${definition.type}`,
5033
4602
  title: definition.label,
5034
4603
  group: "custom",
5035
4604
  icon: definition.icon,
5036
- command: ({ state }) => insertBlockToWrite(initialBlock(state, definition), opensEditor(definitions, definition.type))
4605
+ command: ({ state }) => {
4606
+ const block = initialBlock(state, definition, onError);
4607
+ return block === null ? refuse : insertBlockToWrite(block, opensEditor(definitions, definition.type));
4608
+ }
5037
4609
  }));
5038
4610
  }
5039
-
5040
- // src/menus/slash/SlashMenu.tsx
5041
- import { useCallback as useCallback10 } from "react";
5042
-
5043
- // src/menus/suggestion/SuggestionMenu.tsx
5044
- import { useRef as useRef28 } from "react";
5045
-
5046
- // src/menus/floating/use-range-anchor.ts
5047
- import { useMemo as useMemo10, useRef as useRef24, useState as useState16 } from "react";
5048
4611
  function useRangeAnchor(controller, range) {
5049
- const anchor = useMemo10(
4612
+ const anchor = useMemo(
5050
4613
  () => ({
5051
4614
  current: range && virtualAnchor(
5052
4615
  () => rangeRect(controller, range),
@@ -5055,8 +4618,8 @@ function useRangeAnchor(controller, range) {
5055
4618
  }),
5056
4619
  [controller, range]
5057
4620
  );
5058
- const [side, setSide] = useState16("bottom");
5059
- const latest = useRef24(range);
4621
+ const [side, setSide] = useState("bottom");
4622
+ const latest = useRef(range);
5060
4623
  const start = range === null ? null : `${range.block} ${range.region} ${range.from}`;
5061
4624
  useIsomorphicLayoutEffect(() => {
5062
4625
  latest.current = range;
@@ -5067,12 +4630,6 @@ function useRangeAnchor(controller, range) {
5067
4630
  }, [controller, start]);
5068
4631
  return { anchor, side };
5069
4632
  }
5070
-
5071
- // src/menus/suggestion/use-suggestion.ts
5072
- import { useCallback as useCallback9, useEffect as useEffect20, useId as useId6, useMemo as useMemo12, useState as useState18 } from "react";
5073
-
5074
- // src/menus/suggestion/combobox-attributes.ts
5075
- import { useRef as useRef25 } from "react";
5076
4633
  var ADDED = ["aria-expanded", "aria-controls", "aria-autocomplete", "aria-activedescendant"];
5077
4634
  var SWAPPED = ["role", "aria-multiline"];
5078
4635
  function restore(host, name, value) {
@@ -5092,7 +4649,7 @@ function openCombobox(host, listboxId) {
5092
4649
  };
5093
4650
  }
5094
4651
  function useComboboxHost(controller, block, region, listboxId, activeOptionId) {
5095
- const host = useRef25(null);
4652
+ const host = useRef(null);
5096
4653
  useIsomorphicLayoutEffect(() => {
5097
4654
  host.current = block === null || region === null ? null : controller.registry.get(block, region) ?? null;
5098
4655
  return host.current === null ? void 0 : openCombobox(host.current, listboxId);
@@ -5120,9 +4677,6 @@ function groupItems(items, groupOf2) {
5120
4677
  for (const entry of sections.flatMap((section) => section.entries)) entry.index = index++;
5121
4678
  return sections;
5122
4679
  }
5123
-
5124
- // src/menus/suggestion/use-suggestion-keys.ts
5125
- import { useRef as useRef26 } from "react";
5126
4680
  var MOVES2 = {
5127
4681
  ArrowDown: (index, count) => (index + 1) % count,
5128
4682
  ArrowUp: (index, count) => (index - 1 + count) % count,
@@ -5145,7 +4699,7 @@ function handle(event, menu) {
5145
4699
  return true;
5146
4700
  }
5147
4701
  function useSuggestionKeys(controller, open, menu) {
5148
- const latest = useRef26(menu);
4702
+ const latest = useRef(menu);
5149
4703
  useIsomorphicLayoutEffect(() => {
5150
4704
  latest.current = menu;
5151
4705
  });
@@ -5160,9 +4714,6 @@ function useSuggestionKeys(controller, open, menu) {
5160
4714
  }, [controller, open]);
5161
4715
  }
5162
4716
 
5163
- // src/menus/suggestion/use-suggestion-results.ts
5164
- import { useMemo as useMemo11, useRef as useRef27, useState as useState17 } from "react";
5165
-
5166
4717
  // src/to-error.ts
5167
4718
  var toError = (cause) => cause instanceof Error ? cause : new Error(String(cause));
5168
4719
 
@@ -5171,8 +4722,8 @@ var FORGOTTEN = { source: null, query: null, items: [] };
5171
4722
  var CLOSED = { items: [], pending: false };
5172
4723
  var isPromise = (value) => typeof value?.then === "function";
5173
4724
  function useSuggestionResults(source, query, onError) {
5174
- const [answer, setAnswer] = useState17(FORGOTTEN);
5175
- const report = useRef27(onError);
4725
+ const [answer, setAnswer] = useState(FORGOTTEN);
4726
+ const report = useRef(onError);
5176
4727
  useIsomorphicLayoutEffect(() => {
5177
4728
  report.current = onError;
5178
4729
  });
@@ -5201,7 +4752,7 @@ function useSuggestionResults(source, query, onError) {
5201
4752
  current = false;
5202
4753
  };
5203
4754
  }, [source, query]);
5204
- return useMemo11(
4755
+ return useMemo(
5205
4756
  () => query === null ? CLOSED : { items: answer.items, pending: answer.source !== source || answer.query !== query },
5206
4757
  [source, query, answer]
5207
4758
  );
@@ -5221,20 +4772,20 @@ function useSuggestion({
5221
4772
  }) {
5222
4773
  const { labels, onError } = useQuoin();
5223
4774
  const readOnly = useReadOnly(controller);
5224
- const selectTrigger = useCallback9((state) => getPluginState(state, pluginKey).active, [pluginKey]);
4775
+ const selectTrigger = useCallback((state) => getPluginState(state, pluginKey).active, [pluginKey]);
5225
4776
  const active = useEditorState(controller, selectTrigger);
5226
4777
  const trigger = readOnly ? null : active;
5227
4778
  const results = useSuggestionResults(source, trigger?.query ?? null, onError);
5228
- const sections = useMemo12(() => groupItems(results.items, groupOf2), [results.items, groupOf2]);
5229
- const ordered = useMemo12(() => sections.flatMap((section) => section.entries.map(({ item }) => item)), [sections]);
5230
- const [highlighted, setHighlighted] = useState18(null);
4779
+ const sections = useMemo(() => groupItems(results.items, groupOf2), [results.items, groupOf2]);
4780
+ const ordered = useMemo(() => sections.flatMap((section) => section.entries.map(({ item }) => item)), [sections]);
4781
+ const [highlighted, setHighlighted] = useState(null);
5231
4782
  const kept = highlighted?.trigger === trigger ? ordered.findIndex((item) => itemKey2(item) === highlighted.key) : -1;
5232
4783
  const activeIndex = Math.max(0, kept);
5233
- const baseId = useId6();
4784
+ const baseId = useId();
5234
4785
  const listboxId = `${baseId}-listbox`;
5235
- const optionId = useCallback9((item) => `${baseId}-option-${idPart(itemKey2(item))}`, [baseId, itemKey2]);
4786
+ const optionId = useCallback((item) => `${baseId}-option-${idPart(itemKey2(item))}`, [baseId, itemKey2]);
5236
4787
  const activeId = activeIndex < ordered.length ? optionId(ordered[activeIndex]) : null;
5237
- const highlight = useCallback9(
4788
+ const highlight = useCallback(
5238
4789
  (index) => {
5239
4790
  if (trigger === null || index >= ordered.length) return;
5240
4791
  const key = itemKey2(ordered[index]);
@@ -5242,29 +4793,26 @@ function useSuggestion({
5242
4793
  },
5243
4794
  [trigger, ordered, itemKey2]
5244
4795
  );
5245
- const select = useCallback9(
4796
+ const select = useCallback(
5246
4797
  (index) => {
5247
4798
  const current = getPluginState(controller.editor.state, pluginKey).active;
5248
4799
  if (current !== null && index < ordered.length) onSelect(ordered[index], rangeOf2(current));
5249
4800
  },
5250
4801
  [controller, pluginKey, ordered, onSelect]
5251
4802
  );
5252
- const dismiss = useCallback9(() => void controller.run(dismissSuggestion(pluginKey)), [controller, pluginKey]);
4803
+ const dismiss = useCallback(() => void controller.run(dismissSuggestion(pluginKey)), [controller, pluginKey]);
5253
4804
  useSuggestionKeys(controller, trigger !== null, { count: ordered.length, activeIndex, highlight, select, dismiss });
5254
4805
  useComboboxHost(controller, trigger?.block ?? null, trigger?.region ?? null, listboxId, activeId);
5255
4806
  const query = trigger?.query ?? null;
5256
4807
  const count = ordered.length;
5257
4808
  const resultMessage = count === 0 ? emptyLabel : labels.resultCount(count);
5258
- useEffect20(() => {
4809
+ useEffect(() => {
5259
4810
  if (query === null || results.pending) return;
5260
4811
  const timer = setTimeout(() => controller.announce(resultMessage), SETTLE_MS);
5261
4812
  return () => clearTimeout(timer);
5262
4813
  }, [controller, query, resultMessage, results.pending]);
5263
4814
  return { trigger, sections, pending: results.pending, activeIndex, listboxId, optionId, highlight, select, dismiss };
5264
4815
  }
5265
-
5266
- // src/menus/suggestion/SuggestionMenu.tsx
5267
- import { Fragment as Fragment10, jsx as jsx54, jsxs as jsxs36 } from "react/jsx-runtime";
5268
4816
  var CONTENT3 = cn(
5269
4817
  MENU_CONTENT,
5270
4818
  "flex w-72 max-h-[min(22rem,var(--radix-popper-available-height))] flex-col overflow-y-hidden"
@@ -5272,7 +4820,7 @@ var CONTENT3 = cn(
5272
4820
  var LISTBOX = "min-h-0 overflow-y-auto";
5273
4821
  var GROUP_LABEL = "px-2 pt-2 pb-1 text-xs font-medium text-muted-foreground";
5274
4822
  function SuggestionGroup({ section, labelId, activeIndex, optionId, renderItem, highlight, select }) {
5275
- const options = section.entries.map(({ item, index }) => /* @__PURE__ */ jsx54(
4823
+ const options = section.entries.map(({ item, index }) => /* @__PURE__ */ jsx(
5276
4824
  SuggestionOption,
5277
4825
  {
5278
4826
  id: optionId(item),
@@ -5283,9 +4831,9 @@ function SuggestionGroup({ section, labelId, activeIndex, optionId, renderItem,
5283
4831
  },
5284
4832
  optionId(item)
5285
4833
  ));
5286
- if (section.label === null) return /* @__PURE__ */ jsx54(Fragment10, { children: options });
5287
- return /* @__PURE__ */ jsxs36("div", { role: "group", "aria-labelledby": labelId, children: [
5288
- /* @__PURE__ */ jsx54("div", { role: "presentation", id: labelId, className: GROUP_LABEL, children: section.label }),
4834
+ if (section.label === null) return /* @__PURE__ */ jsx(Fragment, { children: options });
4835
+ return /* @__PURE__ */ jsxs("div", { role: "group", "aria-labelledby": labelId, children: [
4836
+ /* @__PURE__ */ jsx("div", { role: "presentation", id: labelId, className: GROUP_LABEL, children: section.label }),
5289
4837
  options
5290
4838
  ] });
5291
4839
  }
@@ -5294,7 +4842,7 @@ function SuggestionMenu(props) {
5294
4842
  const suggestion = useSuggestion(props);
5295
4843
  const { trigger, sections, activeIndex, listboxId } = suggestion;
5296
4844
  const { anchor, side } = useRangeAnchor(controller, trigger);
5297
- const listbox = useRef28(null);
4845
+ const listbox = useRef(null);
5298
4846
  useIsomorphicLayoutEffect(() => {
5299
4847
  listbox.current?.querySelector('[aria-selected="true"]')?.scrollIntoView({ block: "nearest" });
5300
4848
  }, [activeIndex, sections]);
@@ -5306,7 +4854,7 @@ function SuggestionMenu(props) {
5306
4854
  if (inEditor(event.target) && focusStays) event.preventDefault();
5307
4855
  };
5308
4856
  const status = suggestion.pending ? pendingLabel : sections.length === 0 ? emptyLabel : void 0;
5309
- return /* @__PURE__ */ jsxs36(
4857
+ return /* @__PURE__ */ jsxs(
5310
4858
  Popover,
5311
4859
  {
5312
4860
  open: true,
@@ -5315,8 +4863,8 @@ function SuggestionMenu(props) {
5315
4863
  if (!open) queueMicrotask(suggestion.dismiss);
5316
4864
  },
5317
4865
  children: [
5318
- /* @__PURE__ */ jsx54(PopoverAnchor, { virtualRef: anchor }),
5319
- /* @__PURE__ */ jsxs36(
4866
+ /* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }),
4867
+ /* @__PURE__ */ jsxs(
5320
4868
  PopoverContent,
5321
4869
  {
5322
4870
  role: void 0,
@@ -5329,7 +4877,7 @@ function SuggestionMenu(props) {
5329
4877
  onPointerDownOutside: insideEditor,
5330
4878
  onFocusOutside: insideEditor,
5331
4879
  children: [
5332
- /* @__PURE__ */ jsx54("div", { ref: listbox, role: "listbox", id: listboxId, "aria-label": label, className: LISTBOX, children: sections.map((section, index) => /* @__PURE__ */ jsx54(
4880
+ /* @__PURE__ */ jsx("div", { ref: listbox, role: "listbox", id: listboxId, "aria-label": label, className: LISTBOX, children: sections.map((section, index) => /* @__PURE__ */ jsx(
5333
4881
  SuggestionGroup,
5334
4882
  {
5335
4883
  section,
@@ -5342,7 +4890,7 @@ function SuggestionMenu(props) {
5342
4890
  },
5343
4891
  section.label ?? ""
5344
4892
  )) }),
5345
- status && /* @__PURE__ */ jsx54("p", { className: "px-2 py-1.5 text-sm text-muted-foreground", children: status })
4893
+ status && /* @__PURE__ */ jsx("p", { className: "px-2 py-1.5 text-sm text-muted-foreground", children: status })
5346
4894
  ]
5347
4895
  }
5348
4896
  )
@@ -5420,23 +4968,20 @@ function fuzzyFilter(items, query) {
5420
4968
  if (wanted === "") return [...items];
5421
4969
  return items.map((item, index) => ({ item, index, score: score(item, wanted) })).filter((entry) => entry.score > 0).sort((a, b) => b.score - a.score || a.index - b.index).map((entry) => entry.item);
5422
4970
  }
5423
-
5424
- // src/menus/slash/SlashMenu.tsx
5425
- import { Fragment as Fragment11, jsx as jsx55, jsxs as jsxs37 } from "react/jsx-runtime";
5426
4971
  var itemKey = (item) => item.id;
5427
4972
  function SlashRow({ item, isMac, labels }) {
5428
4973
  const hint = item.shortcut === void 0 ? null : shortcutHint(item.shortcut, isMac, labels);
5429
- return /* @__PURE__ */ jsxs37(Fragment11, { children: [
5430
- item.icon !== void 0 && /* @__PURE__ */ jsx55(MenuIcon, { icon: item.icon }),
5431
- /* @__PURE__ */ jsxs37("span", { className: "flex min-w-0 flex-col", children: [
5432
- /* @__PURE__ */ jsx55("span", { className: "truncate", children: item.title }),
5433
- item.description !== void 0 && /* @__PURE__ */ jsx55("span", { className: "truncate text-xs text-muted-foreground", children: item.description })
4974
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
4975
+ item.icon !== void 0 && /* @__PURE__ */ jsx(MenuIcon, { icon: item.icon }),
4976
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col", children: [
4977
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: item.title }),
4978
+ item.description !== void 0 && /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: item.description })
5434
4979
  ] }),
5435
- hint !== null && /* @__PURE__ */ jsx55("kbd", { "aria-hidden": "true", className: "ml-auto font-sans text-xs tracking-widest text-muted-foreground pointer-coarse:hidden", children: hint.text })
4980
+ hint !== null && /* @__PURE__ */ jsx("kbd", { "aria-hidden": "true", className: "ml-auto font-sans text-xs tracking-widest text-muted-foreground pointer-coarse:hidden", children: hint.text })
5436
4981
  ] });
5437
4982
  }
5438
4983
  function SlashMenu({ controller, labels, items }) {
5439
- const search = useCallback10(
4984
+ const search = useCallback(
5440
4985
  (query) => {
5441
4986
  const { state } = controller.editor;
5442
4987
  return fuzzyFilter(
@@ -5446,16 +4991,16 @@ function SlashMenu({ controller, labels, items }) {
5446
4991
  },
5447
4992
  [controller, items]
5448
4993
  );
5449
- const groupOf2 = useCallback10((item) => labels.groups[item.group], [labels]);
5450
- const renderItem = useCallback10(
5451
- (item) => /* @__PURE__ */ jsx55(SlashRow, { item, isMac: controller.isMac, labels }),
4994
+ const groupOf2 = useCallback((item) => labels.groups[item.group], [labels]);
4995
+ const renderItem = useCallback(
4996
+ (item) => /* @__PURE__ */ jsx(SlashRow, { item, isMac: controller.isMac, labels }),
5452
4997
  [controller, labels]
5453
4998
  );
5454
- const choose = useCallback10(
4999
+ const choose = useCallback(
5455
5000
  (item, range) => chooseSlashItem(controller, item, range),
5456
5001
  [controller]
5457
5002
  );
5458
- return /* @__PURE__ */ jsx55(
5003
+ return /* @__PURE__ */ jsx(
5459
5004
  SuggestionMenu,
5460
5005
  {
5461
5006
  controller,
@@ -5470,21 +5015,18 @@ function SlashMenu({ controller, labels, items }) {
5470
5015
  }
5471
5016
  );
5472
5017
  }
5473
-
5474
- // src/menus/slash/slash-extension.tsx
5475
- import { jsx as jsx56 } from "react/jsx-runtime";
5476
5018
  var NO_ITEMS2 = [];
5477
- var SlashItemsContext = createContext6(NO_ITEMS2);
5019
+ var SlashItemsContext = createContext(NO_ITEMS2);
5478
5020
  var SlashItemsProvider = SlashItemsContext.Provider;
5479
5021
  function SlashOverlay({ controller }) {
5480
5022
  const labels = useLabels();
5481
5023
  const { blockTypes } = useQuoin();
5482
- const extraItems = useContext6(SlashItemsContext);
5483
- const items = useMemo13(
5024
+ const extraItems = useContext(SlashItemsContext);
5025
+ const items = useMemo(
5484
5026
  () => [...builtInSlashItems(labels, blockTypes), ...extraItems],
5485
5027
  [labels, blockTypes, extraItems]
5486
5028
  );
5487
- return /* @__PURE__ */ jsx56(SlashMenu, { controller, labels, items });
5029
+ return /* @__PURE__ */ jsx(SlashMenu, { controller, labels, items });
5488
5030
  }
5489
5031
  function slashExtension() {
5490
5032
  return defineExtension({
@@ -5493,23 +5035,6 @@ function slashExtension() {
5493
5035
  ui: { overlays: [SlashOverlay] }
5494
5036
  });
5495
5037
  }
5496
-
5497
- // src/mobile/MobileToolbar.tsx
5498
- import { useMemo as useMemo14 } from "react";
5499
- import { createPortal } from "react-dom";
5500
-
5501
- // src/mobile/mobile-items.tsx
5502
- import {
5503
- Bold as Bold2,
5504
- Code as Code4,
5505
- Italic as Italic2,
5506
- ListIndentDecrease,
5507
- ListIndentIncrease,
5508
- Plus as Plus2,
5509
- Redo2,
5510
- Strikethrough as Strikethrough2,
5511
- Undo2
5512
- } from "lucide-react";
5513
5038
  function commandItem(id, title, icon, command) {
5514
5039
  return { id, title, icon, run: (controller) => void controller.run(command) };
5515
5040
  }
@@ -5519,12 +5044,12 @@ function addBlockAtCaret(controller) {
5519
5044
  }
5520
5045
  function mobileItems(labels, openLink) {
5521
5046
  return {
5522
- addBlock: { id: "add-block", title: labels.addBelow, icon: Plus2, run: addBlockAtCaret },
5047
+ addBlock: { id: "add-block", title: labels.addBelow, icon: Plus, run: addBlockAtCaret },
5523
5048
  editing: [
5524
- markItem("bold", labels.bold, Bold2),
5525
- markItem("italic", labels.italic, Italic2),
5526
- markItem("strike", labels.strike, Strikethrough2),
5527
- markItem("code", labels.code, Code4),
5049
+ markItem("bold", labels.bold, Bold),
5050
+ markItem("italic", labels.italic, Italic),
5051
+ markItem("strike", labels.strike, Strikethrough),
5052
+ markItem("code", labels.code, Code),
5528
5053
  linkItem(labels, openLink),
5529
5054
  commandItem("indent", labels.indent, ListIndentIncrease, indent),
5530
5055
  commandItem("outdent", labels.outdent, ListIndentDecrease, outdent),
@@ -5536,9 +5061,6 @@ function mobileItems(labels, openLink) {
5536
5061
 
5537
5062
  // src/mobile/use-coarse-pointer.ts
5538
5063
  var useCoarsePointer = () => useMediaQuery("(pointer: coarse)", false);
5539
-
5540
- // src/mobile/use-editor-focus.ts
5541
- import { useCallback as useCallback11, useSyncExternalStore as useSyncExternalStore4 } from "react";
5542
5064
  var FOCUS_EVENTS = ["focusin", "focusout"];
5543
5065
  function subscribe(notify) {
5544
5066
  for (const type of FOCUS_EVENTS) document.addEventListener(type, notify);
@@ -5548,12 +5070,9 @@ function subscribe(notify) {
5548
5070
  }
5549
5071
  var NOT_FOCUSED = () => false;
5550
5072
  function useEditorFocus(controller) {
5551
- const read2 = useCallback11(() => focusInEditor(controller), [controller]);
5552
- return useSyncExternalStore4(subscribe, read2, NOT_FOCUSED);
5073
+ const read2 = useCallback(() => focusInEditor(controller), [controller]);
5074
+ return useSyncExternalStore(subscribe, read2, NOT_FOCUSED);
5553
5075
  }
5554
-
5555
- // src/mobile/use-visual-viewport.ts
5556
- import { useSyncExternalStore as useSyncExternalStore5 } from "react";
5557
5076
  var EVENTS = ["resize", "scroll"];
5558
5077
  function subscribe2(notify) {
5559
5078
  const viewport = window.visualViewport;
@@ -5576,11 +5095,8 @@ function read() {
5576
5095
  }
5577
5096
  var readOnServer2 = () => null;
5578
5097
  function useVisualViewport() {
5579
- return useSyncExternalStore5(subscribe2, read, readOnServer2);
5098
+ return useSyncExternalStore(subscribe2, read, readOnServer2);
5580
5099
  }
5581
-
5582
- // src/mobile/MobileToolbar.tsx
5583
- import { jsx as jsx57, jsxs as jsxs38 } from "react/jsx-runtime";
5584
5100
  var TOOLBAR = [
5585
5101
  "quoin bg-popover text-popover-foreground fixed inset-x-0 z-40 flex items-center gap-0.5 overflow-x-auto",
5586
5102
  "border-t p-1 shadow-md"
@@ -5595,16 +5111,16 @@ function EditingTools({ controller }) {
5595
5111
  const state = useEditorState(controller, wholeState);
5596
5112
  const viewport = useVisualViewport();
5597
5113
  const roving = useRovingFocus();
5598
- const items = useMemo14(() => mobileItems(labels, () => store.set({ linkPopover: { open: true } })), [labels, store]);
5114
+ const items = useMemo(() => mobileItems(labels, () => store.set({ linkPopover: { open: true } })), [labels, store]);
5599
5115
  const onKeyDown = (event) => {
5600
5116
  if (event.key === "Escape" && roving.owns(event.target)) {
5601
5117
  event.preventDefault();
5602
5118
  controller.focus();
5603
5119
  } else roving.onKeyDown(event);
5604
5120
  };
5605
- const button = (item) => /* @__PURE__ */ jsx57(ToolbarButton, { item, state, controller }, item.id);
5121
+ const button = (item) => /* @__PURE__ */ jsx(ToolbarButton, { item, state, controller }, item.id);
5606
5122
  return createPortal(
5607
- /* @__PURE__ */ jsxs38(
5123
+ /* @__PURE__ */ jsxs(
5608
5124
  "div",
5609
5125
  {
5610
5126
  ref: roving.ref,
@@ -5619,7 +5135,7 @@ function EditingTools({ controller }) {
5619
5135
  ...bubblePart(controller),
5620
5136
  children: [
5621
5137
  button(items.addBlock),
5622
- /* @__PURE__ */ jsx57(TurnIntoDropdown, { controller, state }),
5138
+ /* @__PURE__ */ jsx(TurnIntoDropdown, { controller, state }),
5623
5139
  items.editing.map(button)
5624
5140
  ]
5625
5141
  }
@@ -5631,28 +5147,16 @@ function MobileToolbar({ controller }) {
5631
5147
  const coarse = useCoarsePointer();
5632
5148
  const focused = useEditorFocus(controller);
5633
5149
  if (!coarse || !focused) return null;
5634
- return /* @__PURE__ */ jsx57(EditingTools, { controller });
5150
+ return /* @__PURE__ */ jsx(EditingTools, { controller });
5635
5151
  }
5636
-
5637
- // src/shortcuts/shortcuts-extension.tsx
5638
- import { Keyboard } from "lucide-react";
5639
-
5640
- // src/shortcuts/ShortcutsDialog.tsx
5641
- import { useId as useId7, useMemo as useMemo15 } from "react";
5642
-
5643
- // src/ui/dialog.tsx
5644
- import * as React8 from "react";
5645
- import * as DialogPrimitive from "@radix-ui/react-dialog";
5646
- import { XIcon } from "lucide-react";
5647
- import { jsx as jsx58, jsxs as jsxs39 } from "react/jsx-runtime";
5648
5152
  function Dialog(props) {
5649
- return /* @__PURE__ */ jsx58(DialogPrimitive.Root, { ...props });
5153
+ return /* @__PURE__ */ jsx(DialogPrimitive.Root, { ...props });
5650
5154
  }
5651
5155
  function DialogPortal(props) {
5652
- return /* @__PURE__ */ jsx58(DialogPrimitive.Portal, { ...props });
5156
+ return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { ...props });
5653
5157
  }
5654
- var DialogOverlay = /* @__PURE__ */ React8.forwardRef(function DialogOverlay2({ className, ...props }, ref) {
5655
- return /* @__PURE__ */ jsx58(
5158
+ var DialogOverlay = /* @__PURE__ */ React7.forwardRef(function DialogOverlay2({ className, ...props }, ref) {
5159
+ return /* @__PURE__ */ jsx(
5656
5160
  DialogPrimitive.Overlay,
5657
5161
  {
5658
5162
  ref,
@@ -5665,10 +5169,10 @@ var DialogOverlay = /* @__PURE__ */ React8.forwardRef(function DialogOverlay2({
5665
5169
  }
5666
5170
  );
5667
5171
  });
5668
- var DialogContent = /* @__PURE__ */ React8.forwardRef(function DialogContent2({ className, children, closeLabel = "Close", ...props }, ref) {
5669
- return /* @__PURE__ */ jsxs39(DialogPortal, { children: [
5670
- /* @__PURE__ */ jsx58(DialogOverlay, {}),
5671
- /* @__PURE__ */ jsxs39(
5172
+ var DialogContent = /* @__PURE__ */ React7.forwardRef(function DialogContent2({ className, children, closeLabel = "Close", ...props }, ref) {
5173
+ return /* @__PURE__ */ jsxs(DialogPortal, { children: [
5174
+ /* @__PURE__ */ jsx(DialogOverlay, {}),
5175
+ /* @__PURE__ */ jsxs(
5672
5176
  DialogPrimitive.Content,
5673
5177
  {
5674
5178
  ref,
@@ -5680,7 +5184,7 @@ var DialogContent = /* @__PURE__ */ React8.forwardRef(function DialogContent2({
5680
5184
  ...props,
5681
5185
  children: [
5682
5186
  children,
5683
- /* @__PURE__ */ jsxs39(
5187
+ /* @__PURE__ */ jsxs(
5684
5188
  DialogPrimitive.Close,
5685
5189
  {
5686
5190
  className: cn(
@@ -5689,8 +5193,8 @@ var DialogContent = /* @__PURE__ */ React8.forwardRef(function DialogContent2({
5689
5193
  ICON_TAP_TARGET_FLOOR
5690
5194
  ),
5691
5195
  children: [
5692
- /* @__PURE__ */ jsx58(XIcon, {}),
5693
- /* @__PURE__ */ jsx58("span", { className: "sr-only", children: closeLabel })
5196
+ /* @__PURE__ */ jsx(XIcon, {}),
5197
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: closeLabel })
5694
5198
  ]
5695
5199
  }
5696
5200
  )
@@ -5699,8 +5203,8 @@ var DialogContent = /* @__PURE__ */ React8.forwardRef(function DialogContent2({
5699
5203
  )
5700
5204
  ] });
5701
5205
  });
5702
- var DialogHeader = /* @__PURE__ */ React8.forwardRef(function DialogHeader2({ className, ...props }, ref) {
5703
- return /* @__PURE__ */ jsx58(
5206
+ var DialogHeader = /* @__PURE__ */ React7.forwardRef(function DialogHeader2({ className, ...props }, ref) {
5207
+ return /* @__PURE__ */ jsx(
5704
5208
  "div",
5705
5209
  {
5706
5210
  ref,
@@ -5710,8 +5214,8 @@ var DialogHeader = /* @__PURE__ */ React8.forwardRef(function DialogHeader2({ cl
5710
5214
  }
5711
5215
  );
5712
5216
  });
5713
- var DialogTitle = /* @__PURE__ */ React8.forwardRef(function DialogTitle2({ className, ...props }, ref) {
5714
- return /* @__PURE__ */ jsx58(
5217
+ var DialogTitle = /* @__PURE__ */ React7.forwardRef(function DialogTitle2({ className, ...props }, ref) {
5218
+ return /* @__PURE__ */ jsx(
5715
5219
  DialogPrimitive.Title,
5716
5220
  {
5717
5221
  ref,
@@ -5801,23 +5305,20 @@ function shortcutGroups(labels, isMac) {
5801
5305
  }
5802
5306
  ];
5803
5307
  }
5804
-
5805
- // src/shortcuts/ShortcutsDialog.tsx
5806
- import { jsx as jsx59, jsxs as jsxs40 } from "react/jsx-runtime";
5807
5308
  var KEYS3 = "rounded border bg-muted px-1.5 py-0.5 font-sans text-xs whitespace-nowrap";
5808
5309
  function ShortcutSection({ group }) {
5809
- const titleId = useId7();
5810
- return /* @__PURE__ */ jsxs40("section", { "aria-labelledby": titleId, children: [
5811
- /* @__PURE__ */ jsx59("h3", { id: titleId, className: "mb-2 text-sm font-semibold", children: group.title }),
5812
- /* @__PURE__ */ jsx59("dl", { className: "grid gap-1.5 text-sm", children: group.items.map(({ label, keys }) => /* @__PURE__ */ jsxs40("div", { className: "flex items-center justify-between gap-4", children: [
5813
- /* @__PURE__ */ jsx59("dt", { children: label }),
5814
- /* @__PURE__ */ jsx59("dd", { children: /* @__PURE__ */ jsx59("kbd", { className: KEYS3, children: keys }) })
5310
+ const titleId = useId();
5311
+ return /* @__PURE__ */ jsxs("section", { "aria-labelledby": titleId, children: [
5312
+ /* @__PURE__ */ jsx("h3", { id: titleId, className: "mb-2 text-sm font-semibold", children: group.title }),
5313
+ /* @__PURE__ */ jsx("dl", { className: "grid gap-1.5 text-sm", children: group.items.map(({ label, keys }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
5314
+ /* @__PURE__ */ jsx("dt", { children: label }),
5315
+ /* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx("kbd", { className: KEYS3, children: keys }) })
5815
5316
  ] }, `${label} ${keys}`)) })
5816
5317
  ] });
5817
5318
  }
5818
5319
  function ShortcutsDialog({ open, onOpenChange, labels, isMac, onCloseAutoFocus }) {
5819
- const groups = useMemo15(() => shortcutGroups(labels, isMac), [labels, isMac]);
5820
- return /* @__PURE__ */ jsx59(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs40(
5320
+ const groups = useMemo(() => shortcutGroups(labels, isMac), [labels, isMac]);
5321
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
5821
5322
  DialogContent,
5822
5323
  {
5823
5324
  closeLabel: labels.close,
@@ -5825,22 +5326,19 @@ function ShortcutsDialog({ open, onOpenChange, labels, isMac, onCloseAutoFocus }
5825
5326
  onCloseAutoFocus,
5826
5327
  className: "max-h-[85vh] overflow-y-auto sm:max-w-2xl",
5827
5328
  children: [
5828
- /* @__PURE__ */ jsx59(DialogHeader, { children: /* @__PURE__ */ jsx59(DialogTitle, { children: labels.shortcuts }) }),
5829
- /* @__PURE__ */ jsx59("div", { className: "grid gap-6 sm:grid-cols-2", children: groups.map((group) => /* @__PURE__ */ jsx59(ShortcutSection, { group }, group.name)) })
5329
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: labels.shortcuts }) }),
5330
+ /* @__PURE__ */ jsx("div", { className: "grid gap-6 sm:grid-cols-2", children: groups.map((group) => /* @__PURE__ */ jsx(ShortcutSection, { group }, group.name)) })
5830
5331
  ]
5831
5332
  }
5832
5333
  ) });
5833
5334
  }
5834
-
5835
- // src/shortcuts/shortcuts-extension.tsx
5836
- import { jsx as jsx60 } from "react/jsx-runtime";
5837
5335
  var SHORTCUT = "Mod-Shift-/";
5838
5336
  var isOpen = (state) => state.shortcutsOpen;
5839
5337
  function ShortcutsOverlay({ controller }) {
5840
5338
  const labels = useLabels();
5841
5339
  const store = useCanvasUiStore();
5842
5340
  const open = useCanvasUi(store, isOpen);
5843
- return /* @__PURE__ */ jsx60(
5341
+ return /* @__PURE__ */ jsx(
5844
5342
  ShortcutsDialog,
5845
5343
  {
5846
5344
  open,
@@ -5890,13 +5388,6 @@ function linkedBlockId(hash) {
5890
5388
  }
5891
5389
  }
5892
5390
 
5893
- // src/blocks/void/void-renderers.ts
5894
- import { createElement } from "react";
5895
-
5896
- // src/blocks/void/VoidBlock.tsx
5897
- import { useCallback as useCallback12, useEffect as useEffect22, useRef as useRef30 } from "react";
5898
- import { Pencil as Pencil3 } from "lucide-react";
5899
-
5900
5391
  // src/blocks/void/block-data.ts
5901
5392
  var internal = (controller) => controller.editor;
5902
5393
  function readBlockData(controller, block) {
@@ -5913,15 +5404,36 @@ function writeBlockData(controller, blockId, data) {
5913
5404
  const tr = editor.createTransaction().step(replaceBlockStep({ ...block, attrs, regions }));
5914
5405
  editor.dispatch(tr.setMeta(HISTORY_GROUP, `block-data:${blockId}`));
5915
5406
  }
5916
- function insertAfterBlock(controller, blockId, type, definitions) {
5407
+ function insertAfterBlock(controller, blockId, type, definitions, onError) {
5917
5408
  const editor = internal(controller);
5918
- const data = blockByType(definitions, type)?.initialData?.();
5409
+ const data = seedData(blockByType(definitions, type), onError);
5410
+ if (data === null) return false;
5919
5411
  const content = data && specFor(editor.state.schema, type).fromData(data, editor.codec.context);
5920
5412
  controller.run(insertBlockToWrite({ type, ...content }, opensEditor(definitions, type), blockId));
5413
+ return true;
5921
5414
  }
5922
5415
 
5923
- // src/blocks/void/use-editing-focus.ts
5924
- import { useEffect as useEffect21, useMemo as useMemo16, useRef as useRef29 } from "react";
5416
+ // src/blocks/void/history-keys.ts
5417
+ var NOT_TEXT_INPUTS = /* @__PURE__ */ new Set(["button", "checkbox", "color", "file", "image", "radio", "range", "reset", "submit"]);
5418
+ function isTextField(element) {
5419
+ if (element instanceof HTMLInputElement) return !NOT_TEXT_INPUTS.has(element.type);
5420
+ if (element instanceof HTMLTextAreaElement) return true;
5421
+ const editable = element.closest("[contenteditable]");
5422
+ return editable !== null && editable.getAttribute("contenteditable") !== "false";
5423
+ }
5424
+ function isHistoryKey(controller, event) {
5425
+ const mod = controller.isMac ? event.metaKey && !event.ctrlKey : event.ctrlKey && !event.metaKey;
5426
+ const key = event.key.toLowerCase();
5427
+ return mod && !event.altKey && (key === "z" || key === "y" && !event.shiftKey);
5428
+ }
5429
+ function runHistoryKey(controller, event) {
5430
+ if (!isHistoryKey(controller, event) || isTextField(event.target)) return false;
5431
+ return controller.edit(() => controller.editor.handleKey(event.nativeEvent));
5432
+ }
5433
+ function useBlockIndex(controller, blockId) {
5434
+ const select = useCallback((state) => state.doc.index.get(blockId) ?? -1, [blockId]);
5435
+ return useEditorState(controller, select);
5436
+ }
5925
5437
  var FOCUSABLE = [
5926
5438
  "input:not([disabled])",
5927
5439
  "textarea:not([disabled])",
@@ -5933,8 +5445,8 @@ var FOCUSABLE = [
5933
5445
  ].join(", ");
5934
5446
  var CANVAS = ".quoin-editor";
5935
5447
  function useEditingFocus(root, editing, stop) {
5936
- const inside = useRef29(/* @__PURE__ */ new WeakSet());
5937
- useEffect21(() => {
5448
+ const inside = useRef(/* @__PURE__ */ new WeakSet());
5449
+ useEffect(() => {
5938
5450
  const element = root.current;
5939
5451
  if (!editing || element === null) return;
5940
5452
  (element.querySelector(FOCUSABLE) ?? element).focus();
@@ -5954,16 +5466,13 @@ function useEditingFocus(root, editing, stop) {
5954
5466
  unlisten();
5955
5467
  };
5956
5468
  }, [root, editing, stop]);
5957
- return useMemo16(() => {
5469
+ return useMemo(() => {
5958
5470
  const mark = (event) => void inside.current.add(event.nativeEvent);
5959
5471
  return { onPointerDownCapture: mark, onFocusCapture: mark };
5960
5472
  }, []);
5961
5473
  }
5962
-
5963
- // src/blocks/void/VoidBlock.tsx
5964
- import { jsx as jsx61, jsxs as jsxs41 } from "react/jsx-runtime";
5965
5474
  function useMissingPreviewWarning(readOnly, { type, preview }) {
5966
- useEffect22(() => {
5475
+ useEffect(() => {
5967
5476
  if (!readOnly || preview !== void 0) return;
5968
5477
  devWarn(
5969
5478
  `the block type "${type}" has no \`preview\`, so a read-only canvas can draw only its label. Give its definition a \`preview\` to render the block itself.`
@@ -5971,40 +5480,61 @@ function useMissingPreviewWarning(readOnly, { type, preview }) {
5971
5480
  }, [readOnly, type, preview]);
5972
5481
  }
5973
5482
  function VoidPreview({ definition: { preview: Preview }, name, ...props }) {
5974
- if (Preview === void 0) return /* @__PURE__ */ jsx61("p", { className: "py-1 text-sm text-muted-foreground", children: name });
5975
- return /* @__PURE__ */ jsx61(Preview, { ...props });
5483
+ if (Preview === void 0) return /* @__PURE__ */ jsx("p", { className: "py-1 text-sm text-muted-foreground", children: name });
5484
+ return /* @__PURE__ */ jsx(Preview, { ...props });
5485
+ }
5486
+ function VoidEditor({ Editor, controller, ...props }) {
5487
+ const index = useBlockIndex(controller, props.blockId);
5488
+ return /* @__PURE__ */ jsx(Editor, { ...props, index });
5976
5489
  }
5977
5490
  function VoidBlock({ block, controller, definition }) {
5978
5491
  const { blockTypes, labels } = useQuoin();
5492
+ const { report } = useContext(BlockErrorContext);
5979
5493
  const readOnly = useReadOnly(controller);
5980
5494
  const { editor: Editor, alwaysEditing = false } = definition;
5981
5495
  const name = blockTypeLabel(labels, block, blockTypes);
5982
5496
  const blockId = block.id;
5983
5497
  const editable = Editor !== void 0 && !readOnly;
5984
5498
  const { editing, start, stop } = useVoidEditing(controller, blockId, editable);
5985
- const root = useRef30(null);
5499
+ const root = useRef(null);
5986
5500
  const focusHandlers = useEditingFocus(root, editing, stop);
5987
5501
  useMissingPreviewWarning(readOnly, definition);
5988
- const select = useCallback12(() => focusNode(controller, blockId), [controller, blockId]);
5989
- const leave = useCallback12(() => {
5502
+ const select = useCallback(() => focusNode(controller, blockId), [controller, blockId]);
5503
+ const leave = useCallback(() => {
5990
5504
  stop();
5991
5505
  select();
5992
5506
  }, [stop, select]);
5993
- const onChange = useCallback12(
5507
+ const onChange = useCallback(
5994
5508
  (data2) => writeBlockData(controller, blockId, data2),
5995
5509
  [controller, blockId]
5996
5510
  );
5997
- const onInsertBlock = useCallback12(
5511
+ const onPreviewChange = useCallback(
5512
+ (data2) => {
5513
+ writeBlockData(controller, blockId, data2);
5514
+ const shell = root.current?.closest("[data-block-id]");
5515
+ const focused = root.current?.ownerDocument.activeElement ?? null;
5516
+ if (!shell?.contains(focused)) return;
5517
+ if (root.current?.contains(focused)) selectNode(controller, blockId);
5518
+ else select();
5519
+ },
5520
+ [controller, blockId, select]
5521
+ );
5522
+ const onRemove = useCallback(() => deleteBlock(controller, blockId), [controller, blockId]);
5523
+ const onInsertBlock = useCallback(
5998
5524
  (type) => {
5999
- insertAfterBlock(controller, blockId, type, blockTypes);
5525
+ if (!insertAfterBlock(controller, blockId, type, blockTypes, report)) return;
6000
5526
  stop();
6001
5527
  if (controller.editor.state.selection?.kind !== "node") controller.focus();
6002
5528
  },
6003
- [controller, blockId, blockTypes, stop]
5529
+ [controller, blockId, blockTypes, report, stop]
6004
5530
  );
6005
5531
  const editorShown = editable && (alwaysEditing || editing);
6006
- const data = readBlockData(controller, block);
5532
+ const data = useMemo(() => parsedData(definition, readBlockData(controller, block)), [definition, controller, block]);
6007
5533
  const onKeyDown = (event) => {
5534
+ if (!editorShown && !readOnly && isInteractive(root.current, event) && runHistoryKey(controller, event)) {
5535
+ event.preventDefault();
5536
+ return;
5537
+ }
6008
5538
  if (event.key !== "Escape" || !editorShown || !root.current?.contains(event.target)) return;
6009
5539
  event.preventDefault();
6010
5540
  leave();
@@ -6015,7 +5545,7 @@ function VoidBlock({ block, controller, definition }) {
6015
5545
  const onDoubleClick = (event) => {
6016
5546
  if (editable && !editorShown && !isInteractive(root.current, event)) start();
6017
5547
  };
6018
- return /* @__PURE__ */ jsxs41(
5548
+ return /* @__PURE__ */ jsxs(
6019
5549
  "div",
6020
5550
  {
6021
5551
  ref: root,
@@ -6030,8 +5560,29 @@ function VoidBlock({ block, controller, definition }) {
6030
5560
  onClick,
6031
5561
  onDoubleClick,
6032
5562
  children: [
6033
- editorShown && Editor ? /* @__PURE__ */ jsx61(Editor, { data, onChange, onInsertBlock, onDone: leave }) : /* @__PURE__ */ jsx61(VoidPreview, { definition, name, data, blockId }),
6034
- editable && !editorShown && /* @__PURE__ */ jsx61(
5563
+ editorShown && Editor ? /* @__PURE__ */ jsx(
5564
+ VoidEditor,
5565
+ {
5566
+ Editor,
5567
+ controller,
5568
+ data,
5569
+ onChange,
5570
+ blockId,
5571
+ onRemove,
5572
+ onInsertBlock,
5573
+ onDone: leave
5574
+ }
5575
+ ) : /* @__PURE__ */ jsx(
5576
+ VoidPreview,
5577
+ {
5578
+ definition,
5579
+ name,
5580
+ data,
5581
+ blockId,
5582
+ ...readOnly ? {} : { onChange: onPreviewChange }
5583
+ }
5584
+ ),
5585
+ editable && !editorShown && /* @__PURE__ */ jsx(
6035
5586
  Button,
6036
5587
  {
6037
5588
  type: "button",
@@ -6041,7 +5592,7 @@ function VoidBlock({ block, controller, definition }) {
6041
5592
  "aria-label": labels.editBlock(name),
6042
5593
  onClick: () => start(),
6043
5594
  className: "absolute right-0 top-0 bg-background/90 opacity-0 group-hover/void:opacity-100 in-data-[selected=true]:opacity-100 pointer-coarse:opacity-100 focus-visible:opacity-100",
6044
- children: /* @__PURE__ */ jsx61(Pencil3, { "aria-hidden": "true" })
5595
+ children: /* @__PURE__ */ jsx(Pencil, { "aria-hidden": "true" })
6045
5596
  }
6046
5597
  )
6047
5598
  ]
@@ -6081,10 +5632,10 @@ function mergeRender(uis) {
6081
5632
  atomText: render.atomText ?? merged.atomText
6082
5633
  }));
6083
5634
  }
6084
- function collectUi(extensions, definitions, readOnly = false) {
5635
+ function collectUi(extensions, definitions, readOnly = false, onError) {
6085
5636
  const uis = extensions.map(extensionUi);
6086
5637
  return {
6087
- slashItems: [...uis.flatMap((ui) => ui.slashItems ?? []), ...blockTypeSlashItems(definitions)],
5638
+ slashItems: [...uis.flatMap((ui) => ui.slashItems ?? []), ...blockTypeSlashItems(definitions, onError)],
6088
5639
  bubbleItems: uis.flatMap((ui) => ui.bubbleItems ?? []),
6089
5640
  blockMenuItems: uis.flatMap((ui) => ui.blockMenuItems ?? []),
6090
5641
  renderers: Object.assign({}, canvasRenderers(definitions, readOnly), ...uis.map((ui) => ui.renderers)),
@@ -6178,9 +5729,6 @@ var selectedBlockLabel = (labels, definitions, extensionNames) => (block, schema
6178
5729
  if (block.type === "FILE" && hasFile(attrs)) return labels.fileBlockName(firstLine2(fileName(attrs)));
6179
5730
  return firstLine2(blockPlainText(block, schema)) || blockTypeLabel(labels, block, definitions, extensionNames);
6180
5731
  };
6181
-
6182
- // src/canvas/use-block-link-target.ts
6183
- import { useEffect as useEffect23 } from "react";
6184
5732
  function revealLinkedBlock(controller, hash) {
6185
5733
  const id = linkedBlockId(hash);
6186
5734
  const shell = id === null ? void 0 : controller.blockElement(id);
@@ -6192,7 +5740,7 @@ function revealLinkedBlock(controller, hash) {
6192
5740
  return true;
6193
5741
  }
6194
5742
  function useBlockLinkTarget(controller, focusOnMount) {
6195
- useEffect23(() => {
5743
+ useEffect(() => {
6196
5744
  const view = controller.root?.ownerDocument.defaultView ?? window;
6197
5745
  const linked = revealLinkedBlock(controller, view.location.hash);
6198
5746
  if (focusOnMount) controller.focus(linked ? void 0 : "start");
@@ -6203,9 +5751,6 @@ function useBlockLinkTarget(controller, focusOnMount) {
6203
5751
  return () => view.removeEventListener("hashchange", onHashChange);
6204
5752
  }, [controller, focusOnMount]);
6205
5753
  }
6206
-
6207
- // src/canvas/use-delete-reporter.ts
6208
- import { useEffect as useEffect24, useRef as useRef31 } from "react";
6209
5754
  var WRITER_ORIGINS = /* @__PURE__ */ new Set(["command", "input", "paste"]);
6210
5755
  var isBlockDeletion = (tr) => WRITER_ORIGINS.has(tr.origin) && tr.getMeta(LINE_JOIN) !== true;
6211
5756
  var isEmptyText = (schema, block) => isTextFlow(schema, block) && regionLength(block, primaryRegion(schema, block) ?? "") === 0;
@@ -6227,11 +5772,11 @@ function deletions(codec, tr) {
6227
5772
  });
6228
5773
  }
6229
5774
  function useDeleteReporter(controller, onDelete) {
6230
- const latest = useRef31(onDelete);
5775
+ const latest = useRef(onDelete);
6231
5776
  useIsomorphicLayoutEffect(() => {
6232
5777
  latest.current = onDelete;
6233
5778
  });
6234
- useEffect24(() => {
5779
+ useEffect(() => {
6235
5780
  const { codec } = controller.editor;
6236
5781
  return controller.editor.subscribe((_state, tr) => {
6237
5782
  if (tr === null || latest.current === void 0 || !isBlockDeletion(tr)) return;
@@ -6240,11 +5785,8 @@ function useDeleteReporter(controller, onDelete) {
6240
5785
  });
6241
5786
  }, [controller]);
6242
5787
  }
6243
-
6244
- // src/canvas/use-structure-announcements.ts
6245
- import { useEffect as useEffect25 } from "react";
6246
5788
  function useStructureAnnouncements(controller, labels) {
6247
- useEffect25(() => {
5789
+ useEffect(() => {
6248
5790
  const undoKeys = formatShortcut("Mod-z", { isMac: controller.isMac, labels });
6249
5791
  return controller.editor.subscribe((_state, tr) => {
6250
5792
  const message = tr === null ? null : structureAnnouncement(tr, labels, undoKeys);
@@ -6252,11 +5794,8 @@ function useStructureAnnouncements(controller, labels) {
6252
5794
  });
6253
5795
  }, [controller, labels]);
6254
5796
  }
6255
-
6256
- // src/canvas/use-typed-in-place-warning.ts
6257
- import { useEffect as useEffect26 } from "react";
6258
5797
  function useTypedInPlaceWarning(definitions, readOnly) {
6259
- useEffect26(() => {
5798
+ useEffect(() => {
6260
5799
  if (readOnly) return;
6261
5800
  for (const type of definedTypedInPlace(definitions)) {
6262
5801
  devWarn(
@@ -6265,11 +5804,8 @@ function useTypedInPlaceWarning(definitions, readOnly) {
6265
5804
  }
6266
5805
  }, [definitions, readOnly]);
6267
5806
  }
6268
-
6269
- // src/canvas/BlockCanvas.tsx
6270
- import { jsx as jsx62, jsxs as jsxs42 } from "react/jsx-runtime";
6271
5807
  var GUTTER_ROOM = "ps-12";
6272
- var BlockCanvas = forwardRef8(function BlockCanvas2({
5808
+ var BlockCanvas = forwardRef(function BlockCanvas2({
6273
5809
  blocks,
6274
5810
  onChange,
6275
5811
  onDelete,
@@ -6288,9 +5824,9 @@ var BlockCanvas = forwardRef8(function BlockCanvas2({
6288
5824
  id,
6289
5825
  "aria-label": ariaLabel
6290
5826
  }, ref) {
6291
- const [voidEditing] = useState19(createVoidEditing);
6292
- const [uiStore] = useState19(createCanvasUiStore);
6293
- const [allExtensions] = useState19(() => [
5827
+ const [voidEditing] = useState(createVoidEditing);
5828
+ const [uiStore] = useState(createCanvasUiStore);
5829
+ const [allExtensions] = useState(() => [
6294
5830
  ...coreExtensions(),
6295
5831
  voidEditing.extension,
6296
5832
  blockMenuKeymap(uiStore),
@@ -6300,10 +5836,15 @@ var BlockCanvas = forwardRef8(function BlockCanvas2({
6300
5836
  shortcutsExtension(uiStore),
6301
5837
  ...extensions ?? []
6302
5838
  ]);
6303
- const labels = useMemo17(() => resolveLabels(labelOverrides), [labelOverrides]);
6304
- const ui = useMemo17(() => collectUi(allExtensions, blockTypes, readOnly), [allExtensions, blockTypes, readOnly]);
5839
+ const labels = useMemo(() => resolveLabels(labelOverrides), [labelOverrides]);
5840
+ const latestOnError = useRef(onError);
5841
+ latestOnError.current = onError;
5842
+ const ui = useMemo(
5843
+ () => collectUi(allExtensions, blockTypes, readOnly, () => latestOnError.current),
5844
+ [allExtensions, blockTypes, readOnly]
5845
+ );
6305
5846
  useTypedInPlaceWarning(blockTypes, readOnly);
6306
- const [focusOnMount] = useState19(autoFocus);
5847
+ const [focusOnMount] = useState(autoFocus);
6307
5848
  const controller = useQuoinEditor({
6308
5849
  blocks,
6309
5850
  onChange,
@@ -6321,23 +5862,23 @@ var BlockCanvas = forwardRef8(function BlockCanvas2({
6321
5862
  useDeleteReporter(controller, onDelete);
6322
5863
  useBlockLinkTarget(controller, focusOnMount);
6323
5864
  useStructureAnnouncements(controller, labels);
6324
- const actions = useMemo17(() => {
5865
+ const actions = useMemo(() => {
6325
5866
  const onCopied = () => controller.announce(labels.copied);
6326
5867
  return menuActions(coreBlockMenuActions(labels, { blockLink, onCopied, resolveAssetUrl }), ui.blockMenuItems);
6327
5868
  }, [controller, labels, blockLink, resolveAssetUrl, ui.blockMenuItems]);
6328
- const slashItems = useMemo17(
5869
+ const slashItems = useMemo(
6329
5870
  () => [shortcutsSlashItem(labels, uiStore), ...ui.slashItems],
6330
5871
  [labels, uiStore, ui.slashItems]
6331
5872
  );
6332
- const blockLabel = useMemo17(
5873
+ const blockLabel = useMemo(
6333
5874
  () => selectedBlockLabel(labels, blockTypes, ui.blockNames),
6334
5875
  [labels, blockTypes, ui.blockNames]
6335
5876
  );
6336
- const blockPlaceholder = useMemo17(() => {
5877
+ const blockPlaceholder = useMemo(() => {
6337
5878
  const placeholderLabels = placeholder === void 0 ? labels : { ...labels, placeholderEmpty: placeholder };
6338
5879
  return (state, block) => placeholderFor(state, block, placeholderLabels);
6339
5880
  }, [labels, placeholder]);
6340
- useImperativeHandle2(
5881
+ useImperativeHandle(
6341
5882
  ref,
6342
5883
  () => ({
6343
5884
  editor: controller.editor,
@@ -6347,7 +5888,7 @@ var BlockCanvas = forwardRef8(function BlockCanvas2({
6347
5888
  }),
6348
5889
  [controller, resolveAssetUrl]
6349
5890
  );
6350
- return /* @__PURE__ */ jsx62(QuoinProvider, { value: { blockTypes, upload, resolveAssetUrl, onError, highlight, controller, labels }, children: /* @__PURE__ */ jsx62(VoidEditingContext.Provider, { value: voidEditing, children: /* @__PURE__ */ jsx62(SlashItemsProvider, { value: slashItems, children: /* @__PURE__ */ jsx62(BubbleItemsProvider, { value: ui.bubbleItems, children: /* @__PURE__ */ jsx62(CanvasUiProvider, { value: uiStore, children: /* @__PURE__ */ jsxs42(
5891
+ return /* @__PURE__ */ jsx(QuoinProvider, { value: { blockTypes, upload, resolveAssetUrl, onError, highlight, controller, labels }, children: /* @__PURE__ */ jsx(VoidEditingContext.Provider, { value: voidEditing, children: /* @__PURE__ */ jsx(SlashItemsProvider, { value: slashItems, children: /* @__PURE__ */ jsx(BubbleItemsProvider, { value: ui.bubbleItems, children: /* @__PURE__ */ jsx(CanvasUiProvider, { value: uiStore, children: /* @__PURE__ */ jsxs(
6351
5892
  EditorView,
6352
5893
  {
6353
5894
  controller,
@@ -6360,24 +5901,22 @@ var BlockCanvas = forwardRef8(function BlockCanvas2({
6360
5901
  selectedContentLabel: labels.selectedContent,
6361
5902
  blockLabel,
6362
5903
  unsupportedBlockLabel: labels.unsupportedBlock,
5904
+ blockErrorLabel: labels.blockError,
5905
+ onBlockError: onError,
6363
5906
  placeholder: placeholder ?? labels.placeholderEmpty,
6364
5907
  blockPlaceholder,
6365
5908
  blocksSelectedLabel: labels.blocksSelected,
6366
5909
  children: [
6367
- !readOnly && /* @__PURE__ */ jsxs42(ExtensionBlockNames.Provider, { value: ui.blockNames, children: [
6368
- /* @__PURE__ */ jsx62(Gutter, { controller, store: uiStore, actions }),
6369
- /* @__PURE__ */ jsx62(BlockContextMenu, { controller, store: uiStore, actions }),
6370
- /* @__PURE__ */ jsx62(MobileToolbar, { controller })
5910
+ !readOnly && /* @__PURE__ */ jsxs(ExtensionBlockNames.Provider, { value: ui.blockNames, children: [
5911
+ /* @__PURE__ */ jsx(Gutter, { controller, store: uiStore, actions }),
5912
+ /* @__PURE__ */ jsx(BlockContextMenu, { controller, store: uiStore, actions }),
5913
+ /* @__PURE__ */ jsx(MobileToolbar, { controller })
6371
5914
  ] }),
6372
- ui.overlays.map((Overlay2, index) => /* @__PURE__ */ jsx62(Overlay2, { controller }, index))
5915
+ ui.overlays.map((Overlay2, index) => /* @__PURE__ */ jsx(Overlay2, { controller }, index))
6373
5916
  ]
6374
5917
  }
6375
5918
  ) }) }) }) }) });
6376
5919
  });
6377
-
6378
- // src/upload/UploadField.tsx
6379
- import * as React9 from "react";
6380
- import { jsx as jsx63, jsxs as jsxs43 } from "react/jsx-runtime";
6381
5920
  function progressText(state, labels) {
6382
5921
  if (state.phase === "busy") return labels.uploading;
6383
5922
  if (state.phase === "uploaded") return labels.uploaded(state.name);
@@ -6386,7 +5925,7 @@ function progressText(state, labels) {
6386
5925
  function UploadField({ category, label, accept, onUploaded }) {
6387
5926
  const { upload, onError } = useQuoin();
6388
5927
  const labels = useLabels();
6389
- const [state, setState] = React9.useState({ phase: "idle" });
5928
+ const [state, setState] = React7.useState({ phase: "idle" });
6390
5929
  async function run(file) {
6391
5930
  if (!upload) return;
6392
5931
  setState({ phase: "busy" });
@@ -6406,8 +5945,8 @@ function UploadField({ category, label, accept, onUploaded }) {
6406
5945
  }
6407
5946
  }
6408
5947
  const progress = progressText(state, labels);
6409
- return /* @__PURE__ */ jsxs43("div", { className: "flex flex-col items-start gap-1.5", children: [
6410
- /* @__PURE__ */ jsx63(
5948
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-1.5", children: [
5949
+ /* @__PURE__ */ jsx(
6411
5950
  FilePickerButton,
6412
5951
  {
6413
5952
  label,
@@ -6417,15 +5956,12 @@ function UploadField({ category, label, accept, onUploaded }) {
6417
5956
  onPick: (file) => void run(file)
6418
5957
  }
6419
5958
  ),
6420
- !upload && /* @__PURE__ */ jsx63("span", { role: "note", className: "text-xs text-muted-foreground", children: labels.uploadsUnavailable }),
6421
- /* @__PURE__ */ jsx63("span", { role: "status", className: progress === "" ? "sr-only" : "text-xs text-muted-foreground", children: progress }),
6422
- state.phase === "failed" && /* @__PURE__ */ jsx63("span", { role: "alert", className: "text-xs text-destructive", children: state.message })
5959
+ !upload && /* @__PURE__ */ jsx("span", { role: "note", className: "text-xs text-muted-foreground", children: labels.uploadsUnavailable }),
5960
+ /* @__PURE__ */ jsx("span", { role: "status", className: progress === "" ? "sr-only" : "text-xs text-muted-foreground", children: progress }),
5961
+ state.phase === "failed" && /* @__PURE__ */ jsx("span", { role: "alert", className: "text-xs text-destructive", children: state.message })
6423
5962
  ] });
6424
5963
  }
6425
5964
 
6426
- // src/hooks/useAutosave.ts
6427
- import * as React10 from "react";
6428
-
6429
5965
  // src/hooks/autosave-backoff.ts
6430
5966
  function clearTimer(ref) {
6431
5967
  if (ref.current !== null) clearTimeout(ref.current);
@@ -6535,29 +6071,29 @@ function useAutosave({
6535
6071
  isRetryable = alwaysRetry,
6536
6072
  flushOnHide = true
6537
6073
  }) {
6538
- const [status, setStatus] = React10.useState("idle");
6539
- const [error, setError] = React10.useState(null);
6074
+ const [status, setStatus] = React7.useState("idle");
6075
+ const [error, setError] = React7.useState(null);
6540
6076
  const latest = { build, save, policy: { debounceMs, maxBackoffMs, maxRetries, isRetryable } };
6541
- const [runner] = React10.useState(() => createSaveRunner({ setStatus, setError }, latest));
6542
- React10.useEffect(() => {
6077
+ const [runner] = React7.useState(() => createSaveRunner({ setStatus, setError }, latest));
6078
+ React7.useEffect(() => {
6543
6079
  runner.configure(latest);
6544
6080
  });
6545
- const seenRef = React10.useRef(null);
6546
- React10.useEffect(() => {
6081
+ const seenRef = React7.useRef(null);
6082
+ React7.useEffect(() => {
6547
6083
  const seen = seenRef.current;
6548
6084
  seenRef.current = deps;
6549
6085
  if (seen === null) return;
6550
6086
  const unchanged = sameItems(seen, deps);
6551
6087
  if (!unchanged) runner.markDirty();
6552
6088
  }, deps);
6553
- React10.useEffect(() => {
6089
+ React7.useEffect(() => {
6554
6090
  return runner.schedule(debounceMs);
6555
6091
  }, deps);
6556
- React10.useEffect(() => {
6092
+ React7.useEffect(() => {
6557
6093
  runner.mount();
6558
6094
  return runner.dispose;
6559
6095
  }, [runner]);
6560
- React10.useEffect(() => {
6096
+ React7.useEffect(() => {
6561
6097
  if (!flushOnHide) return;
6562
6098
  const onVisibility = () => {
6563
6099
  if (document.visibilityState === "hidden") runner.flush();
@@ -6572,65 +6108,6 @@ function useAutosave({
6572
6108
  return { status, error, retry: runner.retry, flush: runner.flush };
6573
6109
  }
6574
6110
 
6575
- export {
6576
- englishLabels,
6577
- QuoinProvider,
6578
- useQuoin,
6579
- useLabels,
6580
- coreBlocks,
6581
- selectNode,
6582
- focusNode,
6583
- returnFocusToText,
6584
- cn,
6585
- FOCUS_RING,
6586
- FLOATING_TOOLBAR,
6587
- MENU_ITEM,
6588
- runOnBlocks,
6589
- noChange,
6590
- styleTargets,
6591
- MenuIcon,
6592
- formatShortcut,
6593
- insertBlocks,
6594
- insertBlockToWrite,
6595
- interceptKeys,
6596
- Button,
6597
- keepFocus,
6598
- Popover,
6599
- PopoverAnchor,
6600
- PopoverContent,
6601
- preventDefault,
6602
- FilePickerButton,
6603
- selectHandlers,
6604
- useNodeKeys,
6605
- bubblePart,
6606
- virtualAnchor,
6607
- usePartAnchor,
6608
- useRovingFocus,
6609
- useFocusKey,
6610
- linkAddress,
6611
- Input,
6612
- useOutsidePress,
6613
- DropdownMenu,
6614
- DropdownMenuTrigger,
6615
- DropdownMenuContent,
6616
- DropdownMenuItem,
6617
- DropdownMenuCheckboxItem,
6618
- DropdownMenuRadioGroup,
6619
- DropdownMenuRadioItem,
6620
- DropdownMenuSeparator,
6621
- inlineDirection,
6622
- resolveLabels,
6623
- rangeRect,
6624
- suggestionPlugin,
6625
- dismissSuggestion,
6626
- useRangeAnchor,
6627
- toError,
6628
- SuggestionMenu,
6629
- replaceTrigger,
6630
- blockFragment,
6631
- linkedBlockId,
6632
- BlockCanvas,
6633
- UploadField,
6634
- useAutosave
6635
- };
6636
- //# sourceMappingURL=chunk-T43RZTUT.js.map
6111
+ export { BlockCanvas, Button, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger, FLOATING_TOOLBAR, FOCUS_RING, FilePickerButton, Input, MENU_ITEM, MenuIcon, Popover, PopoverAnchor, PopoverContent, QuoinProvider, SuggestionMenu, UploadField, blockFragment, bubblePart, cn, coreBlocks, dismissSuggestion, englishLabels, focusNode, formatShortcut, inlineDirection, insertBlockToWrite, insertBlocks, interceptKeys, keepFocus, linkAddress, linkedBlockId, noChange, preventDefault, rangeRect, replaceTrigger, resolveLabels, returnFocusToText, runOnBlocks, selectHandlers, selectNode, styleTargets, suggestionPlugin, toError, useAutosave, useFocusKey, useLabels, useNodeKeys, useOutsidePress, usePartAnchor, useQuoin, useRangeAnchor, useRovingFocus, virtualAnchor };
6112
+ //# sourceMappingURL=chunk-DYWU4SQ2.js.map
6113
+ //# sourceMappingURL=chunk-DYWU4SQ2.js.map