quoin-editor 1.0.2 → 1.1.0

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