quoin-editor 1.0.2 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/ai.cjs +169 -249
  3. package/dist/ai.cjs.map +1 -1
  4. package/dist/ai.js +38 -121
  5. package/dist/ai.js.map +1 -1
  6. package/dist/catalogue.cjs +29 -43
  7. package/dist/catalogue.cjs.map +1 -1
  8. package/dist/catalogue.js +21 -37
  9. package/dist/catalogue.js.map +1 -1
  10. package/dist/{chunk-DUE3HCZD.js → chunk-2EQ6FKSK.js} +19 -28
  11. package/dist/chunk-2EQ6FKSK.js.map +1 -0
  12. package/dist/{chunk-RJRX34BZ.js → chunk-3BXUGX5F.js} +4 -18
  13. package/dist/chunk-3BXUGX5F.js.map +1 -0
  14. package/dist/chunk-3QRVAI53.cjs +27 -0
  15. package/dist/chunk-3QRVAI53.cjs.map +1 -0
  16. package/dist/{chunk-U3LOLYAU.js → chunk-7FAVFJAS.js} +4 -10
  17. package/dist/chunk-7FAVFJAS.js.map +1 -0
  18. package/dist/{chunk-FDRUAL3Z.cjs → chunk-7NAONESM.cjs} +90 -153
  19. package/dist/chunk-7NAONESM.cjs.map +1 -0
  20. package/dist/{chunk-6V6GGBDK.cjs → chunk-7SVKLWDT.cjs} +24 -31
  21. package/dist/chunk-7SVKLWDT.cjs.map +1 -0
  22. package/dist/{chunk-CW3AFJBR.cjs → chunk-7XQGOCUG.cjs} +1332 -1772
  23. package/dist/chunk-7XQGOCUG.cjs.map +1 -0
  24. package/dist/{chunk-EH5KXQXY.cjs → chunk-A6PGQVTR.cjs} +36 -20
  25. package/dist/chunk-A6PGQVTR.cjs.map +1 -0
  26. package/dist/{chunk-4SLJNZSM.cjs → chunk-AIS37SL2.cjs} +201 -198
  27. package/dist/chunk-AIS37SL2.cjs.map +1 -0
  28. package/dist/{chunk-IQBMAE3F.js → chunk-CKHKCPGL.js} +34 -92
  29. package/dist/chunk-CKHKCPGL.js.map +1 -0
  30. package/dist/{chunk-T43RZTUT.js → chunk-DYWU4SQ2.js} +723 -1246
  31. package/dist/chunk-DYWU4SQ2.js.map +1 -0
  32. package/dist/chunk-EFRQMYZ6.cjs +33 -0
  33. package/dist/chunk-EFRQMYZ6.cjs.map +1 -0
  34. package/dist/{chunk-O4Z2WMFF.js → chunk-HDJ653LM.js} +25 -18
  35. package/dist/chunk-HDJ653LM.js.map +1 -0
  36. package/dist/chunk-HQ43EIYO.cjs +94 -0
  37. package/dist/chunk-HQ43EIYO.cjs.map +1 -0
  38. package/dist/{chunk-6NULZPVC.js → chunk-HTLWPSMU.js} +8 -61
  39. package/dist/chunk-HTLWPSMU.js.map +1 -0
  40. package/dist/{chunk-EPARJI4V.js → chunk-IEP7BPFN.js} +122 -267
  41. package/dist/chunk-IEP7BPFN.js.map +1 -0
  42. package/dist/{chunk-P6KYXFZC.cjs → chunk-IGZRZIAF.cjs} +440 -538
  43. package/dist/chunk-IGZRZIAF.cjs.map +1 -0
  44. package/dist/chunk-JCEFSTVG.cjs +483 -0
  45. package/dist/chunk-JCEFSTVG.cjs.map +1 -0
  46. package/dist/chunk-KXRGY5LK.cjs +612 -0
  47. package/dist/chunk-KXRGY5LK.cjs.map +1 -0
  48. package/dist/{chunk-JHQUHFLX.js → chunk-KZ6ZFCGO.js} +38 -120
  49. package/dist/chunk-KZ6ZFCGO.js.map +1 -0
  50. package/dist/{chunk-ADSJ42DO.js → chunk-L2QA2UTY.js} +17 -69
  51. package/dist/chunk-L2QA2UTY.js.map +1 -0
  52. package/dist/{chunk-OBMBSU2S.js → chunk-L4D23LM2.js} +5 -184
  53. package/dist/chunk-L4D23LM2.js.map +1 -0
  54. package/dist/{chunk-4XFXB37X.js → chunk-L6OW2FL3.js} +7 -90
  55. package/dist/chunk-L6OW2FL3.js.map +1 -0
  56. package/dist/chunk-LE5XMIFJ.cjs +4 -3
  57. package/dist/chunk-LE5XMIFJ.cjs.map +1 -1
  58. package/dist/chunk-MQUCCSWG.js +2 -3
  59. package/dist/chunk-MQUCCSWG.js.map +1 -1
  60. package/dist/{chunk-C23RQVRK.js → chunk-MUIPM26J.js} +66 -216
  61. package/dist/chunk-MUIPM26J.js.map +1 -0
  62. package/dist/{chunk-AUOEM3SF.cjs → chunk-OKWER2RV.cjs} +102 -155
  63. package/dist/chunk-OKWER2RV.cjs.map +1 -0
  64. package/dist/{chunk-TLGX43P6.cjs → chunk-OM7E43ZN.cjs} +89 -86
  65. package/dist/chunk-OM7E43ZN.cjs.map +1 -0
  66. package/dist/{chunk-NEZJ7ZP5.js → chunk-QSXPKZ2F.js} +4 -8
  67. package/dist/chunk-QSXPKZ2F.js.map +1 -0
  68. package/dist/{chunk-VCLL5C7J.js → chunk-RFLFRIPV.js} +14 -57
  69. package/dist/chunk-RFLFRIPV.js.map +1 -0
  70. package/dist/chunk-RIIXJWBR.cjs +24 -0
  71. package/dist/chunk-RIIXJWBR.cjs.map +1 -0
  72. package/dist/{chunk-VRS6WCEK.js → chunk-SFMORPWB.js} +60 -167
  73. package/dist/chunk-SFMORPWB.js.map +1 -0
  74. package/dist/{chunk-YBMUEEM5.js → chunk-TYZSB7JT.js} +4 -8
  75. package/dist/chunk-TYZSB7JT.js.map +1 -0
  76. package/dist/{chunk-BQANU5BH.cjs → chunk-U5BSCAMP.cjs} +34 -44
  77. package/dist/chunk-U5BSCAMP.cjs.map +1 -0
  78. package/dist/{chunk-OSHZQR3W.js → chunk-UEVR4B5S.js} +13 -45
  79. package/dist/chunk-UEVR4B5S.js.map +1 -0
  80. package/dist/{chunk-N4FGA3H4.js → chunk-VBJY2CSK.js} +38 -105
  81. package/dist/chunk-VBJY2CSK.js.map +1 -0
  82. package/dist/{chunk-ZKVOS57Q.cjs → chunk-VFSVN5IQ.cjs} +495 -551
  83. package/dist/chunk-VFSVN5IQ.cjs.map +1 -0
  84. package/dist/{chunk-X4HDKFW5.cjs → chunk-VNRI5DAL.cjs} +56 -105
  85. package/dist/chunk-VNRI5DAL.cjs.map +1 -0
  86. package/dist/chunk-W7B4WQ3L.cjs +200 -0
  87. package/dist/chunk-W7B4WQ3L.cjs.map +1 -0
  88. package/dist/{chunk-623AOJM2.js → chunk-WAGBELKA.js} +7 -25
  89. package/dist/chunk-WAGBELKA.js.map +1 -0
  90. package/dist/{chunk-WEYDDIBQ.cjs → chunk-WH56EW3H.cjs} +36 -64
  91. package/dist/chunk-WH56EW3H.cjs.map +1 -0
  92. package/dist/{chunk-5MAYUGTE.cjs → chunk-XAS7LANM.cjs} +233 -363
  93. package/dist/chunk-XAS7LANM.cjs.map +1 -0
  94. package/dist/comments.cjs +210 -290
  95. package/dist/comments.cjs.map +1 -1
  96. package/dist/comments.js +82 -186
  97. package/dist/comments.js.map +1 -1
  98. package/dist/diff.cjs +48 -65
  99. package/dist/diff.cjs.map +1 -1
  100. package/dist/diff.d.cts +2 -2
  101. package/dist/diff.d.ts +2 -2
  102. package/dist/diff.js +8 -32
  103. package/dist/diff.js.map +1 -1
  104. package/dist/docx.cjs +50 -63
  105. package/dist/docx.cjs.map +1 -1
  106. package/dist/docx.js +7 -22
  107. package/dist/docx.js.map +1 -1
  108. package/dist/embed.cjs +19 -12
  109. package/dist/embed.cjs.map +1 -1
  110. package/dist/embed.js +10 -16
  111. package/dist/embed.js.map +1 -1
  112. package/dist/emoji-data.cjs +7 -5
  113. package/dist/emoji-data.cjs.map +1 -1
  114. package/dist/emoji-data.js +3 -5
  115. package/dist/emoji-data.js.map +1 -1
  116. package/dist/emoji.cjs +26 -17
  117. package/dist/emoji.cjs.map +1 -1
  118. package/dist/emoji.js +9 -17
  119. package/dist/emoji.js.map +1 -1
  120. package/dist/engine.cjs +229 -118
  121. package/dist/engine.cjs.map +1 -1
  122. package/dist/engine.js +4 -118
  123. package/dist/engine.js.map +1 -1
  124. package/dist/find.cjs +30 -19
  125. package/dist/find.cjs.map +1 -1
  126. package/dist/find.js +9 -19
  127. package/dist/find.js.map +1 -1
  128. package/dist/headless.cjs +291 -151
  129. package/dist/headless.cjs.map +1 -1
  130. package/dist/headless.d.cts +5 -1
  131. package/dist/headless.d.ts +5 -1
  132. package/dist/headless.js +6 -151
  133. package/dist/headless.js.map +1 -1
  134. package/dist/index.cjs +349 -183
  135. package/dist/index.cjs.map +1 -1
  136. package/dist/index.d.cts +17 -4
  137. package/dist/index.d.ts +17 -4
  138. package/dist/index.js +8 -183
  139. package/dist/index.js.map +1 -1
  140. package/dist/math.cjs +20 -13
  141. package/dist/math.cjs.map +1 -1
  142. package/dist/math.js +11 -17
  143. package/dist/math.js.map +1 -1
  144. package/dist/mention.cjs +20 -13
  145. package/dist/mention.cjs.map +1 -1
  146. package/dist/mention.js +11 -17
  147. package/dist/mention.js.map +1 -1
  148. package/dist/presence.cjs +99 -132
  149. package/dist/presence.cjs.map +1 -1
  150. package/dist/presence.js +22 -78
  151. package/dist/presence.js.map +1 -1
  152. package/dist/{registry-CWBOSAHm.d.ts → registry-CXegaw5k.d.cts} +25 -2
  153. package/dist/{registry-CWBOSAHm.d.cts → registry-CXegaw5k.d.ts} +25 -2
  154. package/dist/stats.cjs +27 -18
  155. package/dist/stats.cjs.map +1 -1
  156. package/dist/stats.js +10 -18
  157. package/dist/stats.js.map +1 -1
  158. package/dist/styles.css +1 -1
  159. package/dist/table.cjs +90 -49
  160. package/dist/table.cjs.map +1 -1
  161. package/dist/table.js +9 -49
  162. package/dist/table.js.map +1 -1
  163. package/dist/toc.cjs +26 -17
  164. package/dist/toc.cjs.map +1 -1
  165. package/dist/toc.js +9 -17
  166. package/dist/toc.js.map +1 -1
  167. package/dist/view.cjs +13 -16
  168. package/dist/view.cjs.map +1 -1
  169. package/dist/view.d.cts +2 -2
  170. package/dist/view.d.ts +2 -2
  171. package/dist/view.js +7 -16
  172. package/dist/view.js.map +1 -1
  173. package/dist/yjs.cjs +186 -228
  174. package/dist/yjs.cjs.map +1 -1
  175. package/dist/yjs.js +12 -80
  176. package/dist/yjs.js.map +1 -1
  177. package/package.json +2 -1
  178. package/dist/chunk-4SLJNZSM.cjs.map +0 -1
  179. package/dist/chunk-4XFXB37X.js.map +0 -1
  180. package/dist/chunk-5MAYUGTE.cjs.map +0 -1
  181. package/dist/chunk-623AOJM2.js.map +0 -1
  182. package/dist/chunk-6NULZPVC.js.map +0 -1
  183. package/dist/chunk-6V6GGBDK.cjs.map +0 -1
  184. package/dist/chunk-73653CJ4.cjs +0 -34
  185. package/dist/chunk-73653CJ4.cjs.map +0 -1
  186. package/dist/chunk-ADSJ42DO.js.map +0 -1
  187. package/dist/chunk-AUOEM3SF.cjs.map +0 -1
  188. package/dist/chunk-BQANU5BH.cjs.map +0 -1
  189. package/dist/chunk-C23RQVRK.js.map +0 -1
  190. package/dist/chunk-CW3AFJBR.cjs.map +0 -1
  191. package/dist/chunk-DUE3HCZD.js.map +0 -1
  192. package/dist/chunk-EH5KXQXY.cjs.map +0 -1
  193. package/dist/chunk-EPARJI4V.js.map +0 -1
  194. package/dist/chunk-FDRUAL3Z.cjs.map +0 -1
  195. package/dist/chunk-IQBMAE3F.js.map +0 -1
  196. package/dist/chunk-JHQUHFLX.js.map +0 -1
  197. package/dist/chunk-KUYZMSMF.cjs +0 -100
  198. package/dist/chunk-KUYZMSMF.cjs.map +0 -1
  199. package/dist/chunk-LLTEGXWZ.cjs +0 -562
  200. package/dist/chunk-LLTEGXWZ.cjs.map +0 -1
  201. package/dist/chunk-N4FGA3H4.js.map +0 -1
  202. package/dist/chunk-NEZJ7ZP5.js.map +0 -1
  203. package/dist/chunk-O4Z2WMFF.js.map +0 -1
  204. package/dist/chunk-OBMBSU2S.js.map +0 -1
  205. package/dist/chunk-OSHZQR3W.js.map +0 -1
  206. package/dist/chunk-P6KYXFZC.cjs.map +0 -1
  207. package/dist/chunk-R2BLBV43.cjs +0 -239
  208. package/dist/chunk-R2BLBV43.cjs.map +0 -1
  209. package/dist/chunk-RJRX34BZ.js.map +0 -1
  210. package/dist/chunk-T43RZTUT.js.map +0 -1
  211. package/dist/chunk-TLGX43P6.cjs.map +0 -1
  212. package/dist/chunk-U3LOLYAU.js.map +0 -1
  213. package/dist/chunk-UEKXVCKC.cjs +0 -716
  214. package/dist/chunk-UEKXVCKC.cjs.map +0 -1
  215. package/dist/chunk-VCLL5C7J.js.map +0 -1
  216. package/dist/chunk-VRS6WCEK.js.map +0 -1
  217. package/dist/chunk-WEYDDIBQ.cjs.map +0 -1
  218. package/dist/chunk-X4HDKFW5.cjs.map +0 -1
  219. package/dist/chunk-X4P4TQXH.cjs +0 -30
  220. package/dist/chunk-X4P4TQXH.cjs.map +0 -1
  221. package/dist/chunk-XA3UEJIW.cjs +0 -25
  222. package/dist/chunk-XA3UEJIW.cjs.map +0 -1
  223. package/dist/chunk-YBMUEEM5.js.map +0 -1
  224. package/dist/chunk-ZKVOS57Q.cjs.map +0 -1
@@ -1,71 +1,9 @@
1
- import {
2
- Transaction,
3
- blockRangeSelection,
4
- commonPrefix,
5
- commonSuffix,
6
- createEditor,
7
- deleteBackward,
8
- deleteForward,
9
- deleteSelection,
10
- deleteToLineEnd,
11
- deleteToLineStart,
12
- deleteWordBackward,
13
- deleteWordForward,
14
- detectMac,
15
- endOf,
16
- headBlockId,
17
- hidingToggle,
18
- insertHardBreak,
19
- insertText,
20
- isClosedToggle,
21
- isCollapsed,
22
- isTextFlow,
23
- mapSelection,
24
- markRanges,
25
- nextGraphemeOffset,
26
- nodeSelection,
27
- prevGraphemeOffset,
28
- primaryRegion,
29
- rangeContent,
30
- redo,
31
- regionLength,
32
- replaceInlineStep,
33
- runCommands,
34
- sameSelection,
35
- selectionRange,
36
- setAttrs,
37
- setSelection,
38
- startOf,
39
- textSelection,
40
- toggleMark,
41
- toggleTask,
42
- undo,
43
- undoInputRule
44
- } from "./chunk-OBMBSU2S.js";
45
- import {
46
- alignOrUndefined,
47
- blockById,
48
- dataAttributes,
49
- firstNamed,
50
- headingLevel,
51
- inlineLength,
52
- inlinePlainText,
53
- inlineText,
54
- markElement,
55
- nodeLength,
56
- optionalString,
57
- orderedStart,
58
- paletteOrUndefined,
59
- requireBlockIndex,
60
- sameAttrs,
61
- sameItems,
62
- sanitizeHref,
63
- sliceInline,
64
- writtenAttrs
65
- } from "./chunk-4XFXB37X.js";
66
-
67
- // src/view/react/use-editor-state.ts
68
- import { useCallback, useRef, useSyncExternalStore } from "react";
1
+ import { toggleMark, hidingToggle, isTextFlow, markRanges, toggleTask, setAttrs, runCommands, setSelection, blockRangeSelection, primaryRegion, isClosedToggle, commonPrefix, commonSuffix, deleteSelection, detectMac, sameSelection, createEditor, endOf, startOf, nodeSelection, mapSelection, textSelection, rangeContent, headBlockId, redo, undo, insertHardBreak, undoInputRule, insertText, isCollapsed, nextGraphemeOffset, prevGraphemeOffset, Transaction, replaceInlineStep, selectionRange, regionLength, deleteBackward, deleteToLineEnd, deleteToLineStart, deleteWordForward, deleteWordBackward, deleteForward } from './chunk-L4D23LM2.js';
2
+ import { alignOrUndefined, paletteOrUndefined, optionalString, headingLevel, sameItems, inlineLength, firstNamed, sameAttrs, blockById, orderedStart, nodeLength, inlineText, inlinePlainText, dataAttributes, writtenAttrs, markElement, sanitizeHref, sliceInline, requireBlockIndex } from './chunk-L6OW2FL3.js';
3
+ import { createContext, memo, useRef, useContext, useCallback, useSyncExternalStore, useEffect, useLayoutEffect, Component, useState, useId, useMemo } from 'react';
4
+ import { flushSync } from 'react-dom';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
69
7
  var wholeState = (state) => state;
70
8
  function useEditorState(controller, selector, isEqual = Object.is) {
71
9
  const last = useRef(null);
@@ -181,6 +119,11 @@ function segmentSignature(segment) {
181
119
  }
182
120
  }
183
121
 
122
+ // src/view/dom/decoration-attrs.ts
123
+ function withoutEventHandlers(attrs) {
124
+ return Object.fromEntries(Object.entries(attrs).filter(([name]) => !/^on/i.test(name)));
125
+ }
126
+
184
127
  // src/view/dom/mark-elements.ts
185
128
  function create(doc, tag, attributes) {
186
129
  const element = doc.createElement(tag);
@@ -205,7 +148,7 @@ var created = /* @__PURE__ */ new WeakSet();
205
148
  function decorationElement(attrs, doc) {
206
149
  const element = doc.createElement("span");
207
150
  element.setAttribute("data-quoin-deco", "");
208
- setAttributes(element, attrs);
151
+ setAttributes(element, withoutEventHandlers(attrs));
209
152
  return element;
210
153
  }
211
154
  function wrapperDepth(marks, decorations) {
@@ -706,6 +649,11 @@ function entryEdge(controller, block, direction) {
706
649
  return drawn && !entersAsNode(controller, block) ? edge : nodeSelection(block);
707
650
  }
708
651
  var ownNode = (controller, block, direction) => direction < 0 && entersAsNode(controller, block) ? nodeSelection(block) : null;
652
+ var canBeEntered = (controller) => (block) => {
653
+ const { schema } = controller.editor.state;
654
+ const region = isTextFlow(schema, block) ? primaryRegion(schema, block) : null;
655
+ return region === null || controller.registry.get(block.id, region) !== void 0 || entersAsNode(controller, block.id);
656
+ };
709
657
  var holdsTextHead = (controller) => (block) => isTextFlow(controller.editor.state.schema, block) && entryEdge(controller, block.id, 1).kind === "text";
710
658
  function neighbourHead(controller, from, direction) {
711
659
  const target = neighbourBlock(controller.editor.state.doc, from, direction, holdsTextHead(controller));
@@ -713,7 +661,7 @@ function neighbourHead(controller, from, direction) {
713
661
  return edge?.kind === "text" ? edge.head : null;
714
662
  }
715
663
  function moveToNeighbour(controller, from, direction) {
716
- const target = neighbourBlock(controller.editor.state.doc, from, direction);
664
+ const target = neighbourBlock(controller.editor.state.doc, from, direction, canBeEntered(controller));
717
665
  if (target === null) return false;
718
666
  dispatchSelection(controller, entryEdge(controller, target.id, direction));
719
667
  return true;
@@ -901,6 +849,13 @@ function createCrossBlockPointer(controller) {
901
849
  startDragging();
902
850
  follow(x, y);
903
851
  }
852
+ function pressWhole(block) {
853
+ if (entryEdge(controller, block, 1).kind !== "node") return;
854
+ const pressed = blockById(controller.editor.state.doc, block);
855
+ if (pressed !== void 0 && !canBeEntered(controller)(pressed)) return select(blockRangeSelection(block));
856
+ controller.nodeReveal.pressed(block);
857
+ select(nodeSelection(block));
858
+ }
904
859
  function onPointerDown(event) {
905
860
  end();
906
861
  preventMouseDown = false;
@@ -914,10 +869,7 @@ function createCrossBlockPointer(controller) {
914
869
  if (event.shiftKey) extendFrom(host, event.clientX, event.clientY);
915
870
  } else if (block !== void 0 && !(control && root.contains(control))) {
916
871
  press = { kind: "blocks", start: block, x: event.clientX, y: event.clientY };
917
- if (!event.shiftKey && entryEdge(controller, block, 1).kind === "node") {
918
- controller.nodeReveal.pressed(block);
919
- select(nodeSelection(block));
920
- }
872
+ if (!event.shiftKey) pressWhole(block);
921
873
  } else {
922
874
  return;
923
875
  }
@@ -1906,7 +1858,7 @@ function reconcileHost(controller, block, region, caretHint) {
1906
1858
  if (element === void 0 || inline === void 0) return false;
1907
1859
  const before = inlineText(inline);
1908
1860
  const after = readDomText(element);
1909
- const edit = before === after ? null : textDiff(before, after, caretHint ?? domCaretOffset(element));
1861
+ const edit = before === after ? null : textDiff(before, after, domCaretOffset(element));
1910
1862
  if (edit === null) return false;
1911
1863
  const at = (offset) => ({ block, region, offset });
1912
1864
  controller.edit(() => {
@@ -2151,7 +2103,7 @@ function landing(controller, { head }, direction, extend) {
2151
2103
  }
2152
2104
  const own2 = extend ? null : ownNode(controller, head.block, direction);
2153
2105
  if (own2 !== null) return own2;
2154
- const accept = extend ? holdsTextHead(controller) : void 0;
2106
+ const accept = extend ? holdsTextHead(controller) : canBeEntered(controller);
2155
2107
  const target = neighbourBlock(controller.editor.state.doc, head.block, direction, accept);
2156
2108
  return target && (landAtGoal(controller, target, direction) ?? entryEdge(controller, target.id, direction));
2157
2109
  }
@@ -2295,12 +2247,12 @@ function attachInput(controller, root) {
2295
2247
  };
2296
2248
  const onInput = (event) => fallback.onInput(event);
2297
2249
  const onCompositionStart = (event) => {
2298
- if (inHost(event) || inEmptyHost(event)) composition.start(event);
2250
+ if (inHost(event) || inEmptyHost(event)) composition.start();
2299
2251
  else if (inSink(event)) sinkComposition.start();
2300
2252
  };
2301
2253
  const onCompositionEnd = (event) => {
2302
2254
  if (inSink(event)) sinkComposition.end();
2303
- else composition.end(event);
2255
+ else composition.end();
2304
2256
  };
2305
2257
  const detachClipboard = attachClipboard(controller, root, catchUp);
2306
2258
  const unlisten = listen(root, {
@@ -2666,28 +2618,18 @@ var ViewController = class {
2666
2618
  else element.focus({ preventScroll });
2667
2619
  }
2668
2620
  };
2669
-
2670
- // src/view/react/editor-context.ts
2671
- import { createContext, useContext } from "react";
2672
2621
  var QuoinEditorContext = createContext(null);
2673
2622
  function useViewController() {
2674
2623
  const controller = useContext(QuoinEditorContext);
2675
2624
  if (controller === null) throw new Error("useViewController must be called inside an EditorView");
2676
2625
  return controller;
2677
2626
  }
2678
-
2679
- // src/view/react/use-quoin-editor.ts
2680
- import { useEffect as useEffect2, useRef as useRef2, useState } from "react";
2681
- import { flushSync } from "react-dom";
2682
-
2683
- // src/view/react/use-isomorphic-layout-effect.ts
2684
- import { useEffect, useLayoutEffect } from "react";
2685
2627
  var useIsomorphicLayoutEffect = typeof document === "undefined" ? useEffect : useLayoutEffect;
2686
2628
 
2687
2629
  // src/view/react/use-quoin-editor.ts
2688
2630
  function useQuoinEditor(options) {
2689
2631
  const { blocks, readOnly = false } = options;
2690
- const callbacks = useRef2(options);
2632
+ const callbacks = useRef(options);
2691
2633
  const [controller] = useState(() => {
2692
2634
  const editor = createEditor({
2693
2635
  blocks,
@@ -2712,30 +2654,21 @@ function useQuoinEditor(options) {
2712
2654
  useIsomorphicLayoutEffect(() => {
2713
2655
  controller.setReadOnly(readOnly);
2714
2656
  }, [controller, readOnly]);
2715
- useEffect2(() => () => controller.destroy(), [controller]);
2657
+ useEffect(() => () => controller.destroy(), [controller]);
2716
2658
  return controller;
2717
2659
  }
2718
-
2719
- // src/view/react/SelectionSink.tsx
2720
- import { useCallback as useCallback3, useRef as useRef3 } from "react";
2721
-
2722
- // src/view/react/use-read-only.ts
2723
- import { useCallback as useCallback2, useSyncExternalStore as useSyncExternalStore2 } from "react";
2724
2660
  function useReadOnly(controller) {
2725
- const subscribe = useCallback2((notify) => controller.subscribeReadOnly(notify), [controller]);
2726
- const read = useCallback2(() => controller.readOnly, [controller]);
2727
- return useSyncExternalStore2(subscribe, read, read);
2661
+ const subscribe = useCallback((notify) => controller.subscribeReadOnly(notify), [controller]);
2662
+ const read = useCallback(() => controller.readOnly, [controller]);
2663
+ return useSyncExternalStore(subscribe, read, read);
2728
2664
  }
2729
-
2730
- // src/view/react/SelectionSink.tsx
2731
- import { jsx } from "react/jsx-runtime";
2732
2665
  function SelectionSink({ label = "Selected content", blockLabel }) {
2733
2666
  const controller = useViewController();
2734
- const ref = useRef3(null);
2667
+ const ref = useRef(null);
2735
2668
  const readOnly = useReadOnly(controller);
2736
2669
  const name = useEditorState(
2737
2670
  controller,
2738
- useCallback3((state) => selectedBlockName(state, blockLabel), [blockLabel])
2671
+ useCallback((state) => selectedBlockName(state, blockLabel), [blockLabel])
2739
2672
  );
2740
2673
  useIsomorphicLayoutEffect(() => {
2741
2674
  const sink = ref.current;
@@ -2761,28 +2694,19 @@ function SelectionSink({ label = "Selected content", blockLabel }) {
2761
2694
  }
2762
2695
  );
2763
2696
  }
2764
-
2765
- // src/view/react/EditableRegion.tsx
2766
- import { useCallback as useCallback4, useContext as useContext2, useRef as useRef4 } from "react";
2767
-
2768
- // src/view/react/block-placeholder.ts
2769
- import { createContext as createContext2 } from "react";
2770
2697
  var headingPlaceholder = (_state, { type, attrs }) => type === "MARKDOWN" && attrs.kind === "heading" ? `Heading ${headingLevel(attrs.level)}` : void 0;
2771
- var BlockPlaceholderContext = createContext2(headingPlaceholder);
2698
+ var BlockPlaceholderContext = createContext(headingPlaceholder);
2772
2699
  function regionPlaceholder(state, blockId, region, placeholderOf) {
2773
2700
  const block = blockById(state.doc, blockId);
2774
2701
  return block !== void 0 && primaryRegion(state.schema, block) === region ? placeholderOf(state, block) : void 0;
2775
2702
  }
2776
-
2777
- // src/view/react/EditableRegion.tsx
2778
- import { jsx as jsx2 } from "react/jsx-runtime";
2779
2703
  var samePainted = (a, b) => a.inline === b.inline && a.placeholder === b.placeholder && sameDecorations(a.decorations, b.decorations);
2780
2704
  function EditableRegion({ block, region, label, id, placeholder, className }) {
2781
2705
  const controller = useViewController();
2782
- const placeholderOf = useContext2(BlockPlaceholderContext);
2783
- const ref = useRef4(null);
2706
+ const placeholderOf = useContext(BlockPlaceholderContext);
2707
+ const ref = useRef(null);
2784
2708
  const readOnly = useReadOnly(controller);
2785
- const select = useCallback4(
2709
+ const select = useCallback(
2786
2710
  (state) => {
2787
2711
  const inline2 = regionInline(state, block, region);
2788
2712
  const empty = inline2 === void 0 || inlineLength(inline2) === 0;
@@ -2802,7 +2726,7 @@ function EditableRegion({ block, region, label, id, placeholder, className }) {
2802
2726
  useIsomorphicLayoutEffect(() => {
2803
2727
  controller.renderHost(block, region);
2804
2728
  }, [controller, block, region, inline, decorations]);
2805
- return /* @__PURE__ */ jsx2(
2729
+ return /* @__PURE__ */ jsx(
2806
2730
  "div",
2807
2731
  {
2808
2732
  ref,
@@ -2822,15 +2746,9 @@ function EditableRegion({ block, region, label, id, placeholder, className }) {
2822
2746
  }
2823
2747
  );
2824
2748
  }
2825
-
2826
- // src/view/react/default-renderers.tsx
2827
- import { useContext as useContext3 } from "react";
2828
-
2829
- // src/view/react/callout-block.tsx
2830
- import { jsx as jsx3 } from "react/jsx-runtime";
2831
2749
  var CalloutBlock = ({ block }) => {
2832
2750
  const tone = typeof block.attrs.tone === "string" && block.attrs.tone !== "" ? block.attrs.tone : "info";
2833
- return /* @__PURE__ */ jsx3("div", { className: "quoin-callout", "data-tone": tone, children: /* @__PURE__ */ jsx3(EditableRegion, { block: block.id, region: "body", label: `Callout, ${tone}` }) });
2751
+ return /* @__PURE__ */ jsx("div", { className: "quoin-callout", "data-tone": tone, children: /* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: "body", label: `Callout, ${tone}` }) });
2834
2752
  };
2835
2753
 
2836
2754
  // src/view/react/block-command.ts
@@ -2845,14 +2763,11 @@ function onBlock(id, command) {
2845
2763
 
2846
2764
  // src/view/react/prevent-mouse-focus.ts
2847
2765
  var keepFocus = (event) => event.preventDefault();
2848
-
2849
- // src/view/react/TaskCheckbox.tsx
2850
- import { jsx as jsx4 } from "react/jsx-runtime";
2851
2766
  function TaskCheckbox({ block, controller, label, labelledBy }) {
2852
2767
  const checked = block.attrs.checked === true;
2853
2768
  const flip2 = flipCommand(block);
2854
2769
  const readOnly = useReadOnly(controller);
2855
- return /* @__PURE__ */ jsx4(
2770
+ return /* @__PURE__ */ jsx(
2856
2771
  "button",
2857
2772
  {
2858
2773
  type: "button",
@@ -2868,7 +2783,7 @@ function TaskCheckbox({ block, controller, label, labelledBy }) {
2868
2783
  onClick: () => {
2869
2784
  if (flip2 && !controller.readOnly) controller.run(onBlock(block.id, flip2));
2870
2785
  },
2871
- children: checked ? /* @__PURE__ */ jsx4("svg", { viewBox: "0 0 16 16", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx4("path", { d: "M3.5 8.5l3 3 6-7", fill: "none", stroke: "currentColor", strokeWidth: "2" }) }) : null
2786
+ children: checked ? /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx("path", { d: "M3.5 8.5l3 3 6-7", fill: "none", stroke: "currentColor", strokeWidth: "2" }) }) : null
2872
2787
  }
2873
2788
  );
2874
2789
  }
@@ -2913,18 +2828,15 @@ function useOrderedNumber(controller, blockId) {
2913
2828
  return index === void 0 ? 1 : orderedNumber(doc, index);
2914
2829
  });
2915
2830
  }
2916
-
2917
- // src/view/react/markdown-block.tsx
2918
- import { jsx as jsx5, jsxs } from "react/jsx-runtime";
2919
2831
  var REGION = "text";
2920
2832
  function TextRegion({ block, label }) {
2921
- return /* @__PURE__ */ jsx5(EditableRegion, { block: block.id, region: REGION, label });
2833
+ return /* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: REGION, label });
2922
2834
  }
2923
2835
  function NumberedItem({ block, controller }) {
2924
2836
  const number = useOrderedNumber(controller, block.id);
2925
2837
  return /* @__PURE__ */ jsxs("div", { className: "quoin-list-item", "data-list": "ordered", children: [
2926
- /* @__PURE__ */ jsx5("span", { className: "quoin-marker", "aria-hidden": "true", children: `${number}.` }),
2927
- /* @__PURE__ */ jsx5(TextRegion, { block, label: `Numbered list item ${number}` })
2838
+ /* @__PURE__ */ jsx("span", { className: "quoin-marker", "aria-hidden": "true", children: `${number}.` }),
2839
+ /* @__PURE__ */ jsx(TextRegion, { block, label: `Numbered list item ${number}` })
2928
2840
  ] });
2929
2841
  }
2930
2842
  var MarkdownBlock = (props) => {
@@ -2932,44 +2844,38 @@ var MarkdownBlock = (props) => {
2932
2844
  switch (block.attrs.kind) {
2933
2845
  case "heading": {
2934
2846
  const level = headingLevel(block.attrs.level);
2935
- return /* @__PURE__ */ jsx5("div", { role: "heading", "aria-level": level, className: "quoin-heading", children: /* @__PURE__ */ jsx5(TextRegion, { block, label: `Heading ${level}` }) });
2847
+ return /* @__PURE__ */ jsx("div", { role: "heading", "aria-level": level, className: "quoin-heading", children: /* @__PURE__ */ jsx(TextRegion, { block, label: `Heading ${level}` }) });
2936
2848
  }
2937
2849
  case "bullet":
2938
2850
  return /* @__PURE__ */ jsxs("div", { className: "quoin-list-item", "data-list": "bullet", children: [
2939
- /* @__PURE__ */ jsx5("span", { className: "quoin-marker", "aria-hidden": "true", children: "\u2022" }),
2940
- /* @__PURE__ */ jsx5(TextRegion, { block, label: "Bullet list item" })
2851
+ /* @__PURE__ */ jsx("span", { className: "quoin-marker", "aria-hidden": "true", children: "\u2022" }),
2852
+ /* @__PURE__ */ jsx(TextRegion, { block, label: "Bullet list item" })
2941
2853
  ] });
2942
2854
  case "ordered":
2943
- return /* @__PURE__ */ jsx5(NumberedItem, { ...props });
2855
+ return /* @__PURE__ */ jsx(NumberedItem, { ...props });
2944
2856
  case "task":
2945
2857
  return /* @__PURE__ */ jsxs("div", { className: "quoin-task", "data-checked": block.attrs.checked === true, children: [
2946
- /* @__PURE__ */ jsx5(TaskCheckbox, { block, controller: props.controller }),
2947
- /* @__PURE__ */ jsx5(TextRegion, { block, label: "Task" })
2858
+ /* @__PURE__ */ jsx(TaskCheckbox, { block, controller: props.controller }),
2859
+ /* @__PURE__ */ jsx(TextRegion, { block, label: "Task" })
2948
2860
  ] });
2949
2861
  case "quote":
2950
- return /* @__PURE__ */ jsx5("div", { className: "quoin-quote", children: /* @__PURE__ */ jsx5(TextRegion, { block, label: "Quote" }) });
2862
+ return /* @__PURE__ */ jsx("div", { className: "quoin-quote", children: /* @__PURE__ */ jsx(TextRegion, { block, label: "Quote" }) });
2951
2863
  default:
2952
- return /* @__PURE__ */ jsx5(TextRegion, { block, label: "Paragraph" });
2864
+ return /* @__PURE__ */ jsx(TextRegion, { block, label: "Paragraph" });
2953
2865
  }
2954
2866
  };
2955
-
2956
- // src/view/react/use-reader-choices.ts
2957
- import { useSyncExternalStore as useSyncExternalStore3 } from "react";
2958
2867
  function useReaderChoices(controller) {
2959
2868
  const store = readerToggles(controller);
2960
- return useSyncExternalStore3(store.subscribe, () => store.choices, () => store.choices);
2869
+ return useSyncExternalStore(store.subscribe, () => store.choices, () => store.choices);
2961
2870
  }
2962
2871
  function useToggleOpen(controller, block) {
2963
2872
  return shownOpen(block, useReaderChoices(controller));
2964
2873
  }
2965
-
2966
- // src/view/react/ToggleChevron.tsx
2967
- import { jsx as jsx6 } from "react/jsx-runtime";
2968
2874
  function ToggleChevron({ block, controller, label = "Toggle", controls }) {
2969
2875
  const open = useToggleOpen(controller, block);
2970
2876
  const readOnly = useReadOnly(controller);
2971
2877
  const flip2 = flipCommand(block);
2972
- return /* @__PURE__ */ jsx6(
2878
+ return /* @__PURE__ */ jsx(
2973
2879
  "button",
2974
2880
  {
2975
2881
  type: "button",
@@ -2984,48 +2890,57 @@ function ToggleChevron({ block, controller, label = "Toggle", controls }) {
2984
2890
  if (controller.readOnly) readerToggles(controller).flip(block);
2985
2891
  else if (flip2) controller.run(onBlock(block.id, flip2));
2986
2892
  },
2987
- children: /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 16 16", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx6("path", { d: "M6 3.5l4.5 4.5L6 12.5", fill: "none", stroke: "currentColor", strokeWidth: "2" }) })
2893
+ children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx("path", { d: "M6 3.5l4.5 4.5L6 12.5", fill: "none", stroke: "currentColor", strokeWidth: "2" }) })
2988
2894
  }
2989
2895
  );
2990
2896
  }
2991
-
2992
- // src/view/react/toggle-block.tsx
2993
- import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
2994
2897
  var ToggleBlock = ({ block, controller }) => {
2995
2898
  const open = useToggleOpen(controller, block);
2996
- return /* @__PURE__ */ jsxs2("div", { className: "quoin-toggle", "data-open": open, children: [
2997
- /* @__PURE__ */ jsx7(ToggleChevron, { block, controller }),
2998
- /* @__PURE__ */ jsx7(EditableRegion, { block: block.id, region: "text", label: "Toggle" })
2899
+ return /* @__PURE__ */ jsxs("div", { className: "quoin-toggle", "data-open": open, children: [
2900
+ /* @__PURE__ */ jsx(ToggleChevron, { block, controller }),
2901
+ /* @__PURE__ */ jsx(EditableRegion, { block: block.id, region: "text", label: "Toggle" })
2999
2902
  ] });
3000
2903
  };
3001
-
3002
- // src/view/react/unsupported-block-label.ts
3003
- import { createContext as createContext3 } from "react";
3004
2904
  var UNSUPPORTED_BLOCK = "Unsupported block";
3005
- var UnsupportedBlockLabel = createContext3(UNSUPPORTED_BLOCK);
3006
-
3007
- // src/view/react/default-renderers.tsx
3008
- import { jsx as jsx8 } from "react/jsx-runtime";
2905
+ var UnsupportedBlockLabel = createContext(UNSUPPORTED_BLOCK);
3009
2906
  var defaultRenderers = {
3010
2907
  MARKDOWN: MarkdownBlock,
3011
2908
  CALLOUT: CalloutBlock,
3012
2909
  TOGGLE: ToggleBlock
3013
2910
  };
3014
2911
  var VoidBlockFallback = ({ block }) => {
3015
- const label = useContext3(UnsupportedBlockLabel);
3016
- if (block.type === "DIVIDER") return /* @__PURE__ */ jsx8("div", { className: "quoin-void", contentEditable: false, role: "separator" });
3017
- return /* @__PURE__ */ jsx8("div", { className: "quoin-void", contentEditable: false, role: "group", "aria-label": label, children: label });
2912
+ const label = useContext(UnsupportedBlockLabel);
2913
+ if (block.type === "DIVIDER") return /* @__PURE__ */ jsx("div", { className: "quoin-void", contentEditable: false, role: "separator" });
2914
+ return /* @__PURE__ */ jsx("div", { className: "quoin-void", contentEditable: false, role: "group", "aria-label": label, children: label });
3018
2915
  };
3019
-
3020
- // src/view/react/BlockShell.tsx
3021
- import { memo, useRef as useRef5 } from "react";
3022
-
3023
- // src/view/react/block-dom-id.ts
3024
- import { createContext as createContext4, useCallback as useCallback5, useContext as useContext4 } from "react";
3025
- var BlockDomIdScope = createContext4("quoin");
2916
+ var BLOCK_ERROR = "Block could not be drawn";
2917
+ var BlockErrorContext = createContext({ label: BLOCK_ERROR });
2918
+ var Boundary = class extends Component {
2919
+ state = { block: this.props.block, renderer: this.props.renderer, failed: false };
2920
+ static getDerivedStateFromError() {
2921
+ return { failed: true };
2922
+ }
2923
+ static getDerivedStateFromProps(props, state) {
2924
+ const same = props.block === state.block && props.renderer === state.renderer;
2925
+ return same ? null : { block: props.block, renderer: props.renderer, failed: false };
2926
+ }
2927
+ componentDidCatch(error) {
2928
+ this.props.report?.(error instanceof Error ? error : new Error(String(error)));
2929
+ }
2930
+ render() {
2931
+ if (!this.state.failed) return this.props.children;
2932
+ const { label } = this.props;
2933
+ return /* @__PURE__ */ jsx("div", { className: "quoin-void", contentEditable: false, role: "group", "aria-label": label, children: label });
2934
+ }
2935
+ };
2936
+ function BlockErrorBoundary({ block, renderer, children }) {
2937
+ const { label, report } = useContext(BlockErrorContext);
2938
+ return /* @__PURE__ */ jsx(Boundary, { block, renderer, label, report, children });
2939
+ }
2940
+ var BlockDomIdScope = createContext("quoin");
3026
2941
  function useBlockDomId() {
3027
- const scope = useContext4(BlockDomIdScope);
3028
- return useCallback5((block) => `${scope}-${encodeURIComponent(block)}`, [scope]);
2942
+ const scope = useContext(BlockDomIdScope);
2943
+ return useCallback((block) => `${scope}-${encodeURIComponent(block)}`, [scope]);
3029
2944
  }
3030
2945
  function useRegionDomId(block, region) {
3031
2946
  return `${useBlockDomId()(block)}/${encodeURIComponent(region)}`;
@@ -3051,16 +2966,18 @@ function blockStatus(state, id, choices = NO_CHOICES) {
3051
2966
  if (isHiddenAt(state.doc, index, choices)) return "hidden";
3052
2967
  return covers(state, id, index) ? "selected" : "plain";
3053
2968
  }
3054
-
3055
- // src/view/react/BlockShell.tsx
3056
- import { jsx as jsx9 } from "react/jsx-runtime";
2969
+ function safeAttrs(decorations) {
2970
+ const attrs = Object.assign({}, ...decorations.map((decoration) => decoration.attrs));
2971
+ for (const name of Object.keys(attrs)) if (!/^(data|aria)-/.test(name)) delete attrs[name];
2972
+ return attrs;
2973
+ }
3057
2974
  function rendererFor(renderers, type) {
3058
2975
  for (const table of [renderers, defaultRenderers]) if (Object.hasOwn(table, type)) return table[type];
3059
2976
  return VoidBlockFallback;
3060
2977
  }
3061
2978
  var BlockShell = memo(function BlockShell2({ block, renderers }) {
3062
2979
  const controller = useViewController();
3063
- const ref = useRef5(null);
2980
+ const ref = useRef(null);
3064
2981
  const domId = useBlockDomId();
3065
2982
  const choices = useReaderChoices(controller);
3066
2983
  const status = useEditorState(controller, (state) => blockStatus(state, block.id, choices));
@@ -3073,10 +2990,10 @@ var BlockShell = memo(function BlockShell2({ block, renderers }) {
3073
2990
  if (hidden) return null;
3074
2991
  const Renderer = rendererFor(renderers, block.type);
3075
2992
  const { kind, color, background, align } = block.attrs;
3076
- return /* @__PURE__ */ jsx9(
2993
+ return /* @__PURE__ */ jsx(
3077
2994
  "div",
3078
2995
  {
3079
- ...Object.assign({}, ...decorations.map((decoration) => decoration.attrs)),
2996
+ ...safeAttrs(decorations),
3080
2997
  ref,
3081
2998
  id: domId(block.id),
3082
2999
  "data-quoin-block": "",
@@ -3090,20 +3007,13 @@ var BlockShell = memo(function BlockShell2({ block, renderers }) {
3090
3007
  style: { "--quoin-indent": block.indent },
3091
3008
  tabIndex: -1,
3092
3009
  "data-selected": status === "selected" ? "true" : void 0,
3093
- children: /* @__PURE__ */ jsx9(Renderer, { block, controller })
3010
+ children: /* @__PURE__ */ jsx(BlockErrorBoundary, { block, renderer: Renderer, children: /* @__PURE__ */ jsx(Renderer, { block, controller }) })
3094
3011
  }
3095
3012
  );
3096
3013
  });
3097
-
3098
- // src/view/react/EditorView.tsx
3099
- import { useId, useRef as useRef7 } from "react";
3100
-
3101
- // src/view/react/EmptyDocumentHost.tsx
3102
- import { useRef as useRef6 } from "react";
3103
- import { jsx as jsx10 } from "react/jsx-runtime";
3104
3014
  function EmptyDocumentHost({ placeholder, label = "Paragraph" }) {
3105
3015
  const controller = useViewController();
3106
- const ref = useRef6(null);
3016
+ const ref = useRef(null);
3107
3017
  const readOnly = useReadOnly(controller);
3108
3018
  useIsomorphicLayoutEffect(() => {
3109
3019
  const host = ref.current;
@@ -3111,7 +3021,7 @@ function EmptyDocumentHost({ placeholder, label = "Paragraph" }) {
3111
3021
  renderInline(host, [], []);
3112
3022
  return controller.registerEmptyHost(host);
3113
3023
  }, [controller]);
3114
- return /* @__PURE__ */ jsx10(
3024
+ return /* @__PURE__ */ jsx(
3115
3025
  "div",
3116
3026
  {
3117
3027
  ref,
@@ -3134,9 +3044,6 @@ function EmptyDocumentHost({ placeholder, label = "Paragraph" }) {
3134
3044
  // src/view/react/focus-owners.ts
3135
3045
  var focusOwners = /* @__PURE__ */ new WeakMap();
3136
3046
 
3137
- // src/view/react/LiveRegion.tsx
3138
- import { useCallback as useCallback6, useMemo, useSyncExternalStore as useSyncExternalStore4 } from "react";
3139
-
3140
3047
  // src/view/selection/selection-announcement.ts
3141
3048
  var SILENCE = { key: "", message: "" };
3142
3049
  function selectionAnnouncement({ doc, selection }, blocksSelected) {
@@ -3150,9 +3057,6 @@ function selectionAnnouncement({ doc, selection }, blocksSelected) {
3150
3057
  const count = drawnBlockCount(doc, Math.min(first, last), Math.max(first, last) + 1);
3151
3058
  return { key: `${selection.kind}:${anchor}:${head}`, message: blocksSelected(count) };
3152
3059
  }
3153
-
3154
- // src/view/react/LiveRegion.tsx
3155
- import { jsx as jsx11 } from "react/jsx-runtime";
3156
3060
  function heardNow({ editor, announcer }, blocksSelected) {
3157
3061
  const spoken = announcer.current();
3158
3062
  if (spoken !== null) return { key: `said:${spoken.serial}`, message: spoken.message };
@@ -3160,7 +3064,7 @@ function heardNow({ editor, announcer }, blocksSelected) {
3160
3064
  }
3161
3065
  function LiveRegion({ blocksSelected }) {
3162
3066
  const controller = useViewController();
3163
- const subscribe = useCallback6(
3067
+ const subscribe = useCallback(
3164
3068
  (notify) => {
3165
3069
  const stopState = controller.editor.subscribe(() => notify());
3166
3070
  const stopSpoken = controller.announcer.subscribe(notify);
@@ -3179,8 +3083,8 @@ function LiveRegion({ blocksSelected }) {
3179
3083
  return last;
3180
3084
  };
3181
3085
  }, [controller, blocksSelected]);
3182
- const { key, message } = useSyncExternalStore4(subscribe, read, read);
3183
- return /* @__PURE__ */ jsx11("div", { className: "quoin-visually-hidden", role: "status", "aria-live": "polite", "aria-atomic": "true", children: message !== "" && /* @__PURE__ */ jsx11("span", { children: message }, key) });
3086
+ const { key, message } = useSyncExternalStore(subscribe, read, read);
3087
+ return /* @__PURE__ */ jsx("div", { className: "quoin-visually-hidden", role: "status", "aria-live": "polite", "aria-atomic": "true", children: message !== "" && /* @__PURE__ */ jsx("span", { children: message }, key) });
3184
3088
  }
3185
3089
 
3186
3090
  // src/view/react/SelectionWriter.tsx
@@ -3190,23 +3094,16 @@ function SelectionWriter() {
3190
3094
  useIsomorphicLayoutEffect(() => controller.afterRender(), [controller, state]);
3191
3095
  return null;
3192
3096
  }
3193
-
3194
- // src/view/react/use-block-elements.tsx
3195
- import { useState as useState2 } from "react";
3196
- import { jsx as jsx12 } from "react/jsx-runtime";
3197
3097
  function useBlockElements(blocks, renderers) {
3198
- const [made] = useState2(() => /* @__PURE__ */ new WeakMap());
3098
+ const [made] = useState(() => /* @__PURE__ */ new WeakMap());
3199
3099
  return blocks.map((block) => {
3200
3100
  const known2 = made.get(block);
3201
3101
  if (known2?.renderers === renderers) return known2.element;
3202
- const element = /* @__PURE__ */ jsx12(BlockShell, { block, renderers }, block.id);
3102
+ const element = /* @__PURE__ */ jsx(BlockShell, { block, renderers }, block.id);
3203
3103
  made.set(block, { renderers, element });
3204
3104
  return element;
3205
3105
  });
3206
3106
  }
3207
-
3208
- // src/view/react/EditorView.tsx
3209
- import { jsx as jsx13, jsxs as jsxs3 } from "react/jsx-runtime";
3210
3107
  var NO_RENDERERS = {};
3211
3108
  var HINT = "Press Escape, then Tab, to leave the editor.";
3212
3109
  var BLOCKS_SELECTED = (count) => `${count} ${count === 1 ? "block" : "blocks"} selected`;
@@ -3221,18 +3118,21 @@ function EditorView({
3221
3118
  selectedContentLabel,
3222
3119
  blockLabel,
3223
3120
  unsupportedBlockLabel = UNSUPPORTED_BLOCK,
3121
+ blockErrorLabel = BLOCK_ERROR,
3122
+ onBlockError,
3224
3123
  placeholder,
3225
3124
  blockPlaceholder = headingPlaceholder,
3226
3125
  blocksSelectedLabel = BLOCKS_SELECTED,
3227
3126
  children
3228
3127
  }) {
3229
- const root = useRef7(null);
3128
+ const root = useRef(null);
3230
3129
  const hintId = useId();
3231
3130
  const blockIdScope = useId();
3232
3131
  const blocks = useEditorState(controller, (state) => state.doc.blocks);
3132
+ const blockError = useMemo(() => ({ label: blockErrorLabel, report: onBlockError }), [blockErrorLabel, onBlockError]);
3233
3133
  const shells = useBlockElements(blocks, renderers);
3234
3134
  useIsomorphicLayoutEffect(() => root.current ? controller.attach(root.current) : void 0, [controller]);
3235
- return /* @__PURE__ */ jsx13(QuoinEditorContext.Provider, { value: controller, children: /* @__PURE__ */ jsxs3(
3135
+ return /* @__PURE__ */ jsx(QuoinEditorContext.Provider, { value: controller, children: /* @__PURE__ */ jsxs(
3236
3136
  "div",
3237
3137
  {
3238
3138
  ref: root,
@@ -3243,62 +3143,17 @@ function EditorView({
3243
3143
  "aria-describedby": hintId,
3244
3144
  onFocusCapture: (event) => focusOwners.set(event.target, controller),
3245
3145
  children: [
3246
- /* @__PURE__ */ jsx13(BlockDomIdScope.Provider, { value: blockIdScope, children: /* @__PURE__ */ jsx13(UnsupportedBlockLabel.Provider, { value: unsupportedBlockLabel, children: /* @__PURE__ */ jsx13(BlockPlaceholderContext.Provider, { value: blockPlaceholder, children: blocks.length === 0 ? /* @__PURE__ */ jsx13(EmptyDocumentHost, { placeholder, label: paragraphLabel }) : shells }) }) }),
3146
+ /* @__PURE__ */ jsx(BlockDomIdScope.Provider, { value: blockIdScope, children: /* @__PURE__ */ jsx(UnsupportedBlockLabel.Provider, { value: unsupportedBlockLabel, children: /* @__PURE__ */ jsx(BlockErrorContext.Provider, { value: blockError, children: /* @__PURE__ */ jsx(BlockPlaceholderContext.Provider, { value: blockPlaceholder, children: blocks.length === 0 ? /* @__PURE__ */ jsx(EmptyDocumentHost, { placeholder, label: paragraphLabel }) : shells }) }) }) }),
3247
3147
  children,
3248
- /* @__PURE__ */ jsx13(SelectionSink, { label: selectedContentLabel, blockLabel }),
3249
- /* @__PURE__ */ jsx13("div", { id: hintId, className: "quoin-visually-hidden", children: hint }),
3250
- /* @__PURE__ */ jsx13(LiveRegion, { blocksSelected: blocksSelectedLabel }),
3251
- /* @__PURE__ */ jsx13(SelectionWriter, {})
3148
+ /* @__PURE__ */ jsx(SelectionSink, { label: selectedContentLabel, blockLabel }),
3149
+ /* @__PURE__ */ jsx("div", { id: hintId, className: "quoin-visually-hidden", children: hint }),
3150
+ /* @__PURE__ */ jsx(LiveRegion, { blocksSelected: blocksSelectedLabel }),
3151
+ /* @__PURE__ */ jsx(SelectionWriter, {})
3252
3152
  ]
3253
3153
  }
3254
3154
  ) });
3255
3155
  }
3256
3156
 
3257
- export {
3258
- dispatchSelection,
3259
- wholeState,
3260
- useEditorState,
3261
- useReadOnly,
3262
- isCrossSelection,
3263
- NODE_ENTRY,
3264
- visibleBlockIndexes,
3265
- drawnBlockCount,
3266
- neighbourBlock,
3267
- moveToNeighbour,
3268
- textDiff,
3269
- domMapOf,
3270
- renderInline,
3271
- domToPos,
3272
- posToDom,
3273
- caretFromPoint,
3274
- caretClientRect,
3275
- lineEdgeRect,
3276
- isOnFirstLine,
3277
- isOnLastLine,
3278
- isComposingKey,
3279
- NATIVE_INTERACTION,
3280
- useIsomorphicLayoutEffect,
3281
- onBlock,
3282
- listen,
3283
- createAutoScroll,
3284
- hostKey,
3285
- regionInline,
3286
- handleCopy,
3287
- ViewController,
3288
- useViewController,
3289
- useQuoinEditor,
3290
- useBlockDomId,
3291
- useRegionDomId,
3292
- focusOwners,
3293
- SelectionSink,
3294
- EditableRegion,
3295
- TaskCheckbox,
3296
- useOrderedNumber,
3297
- useToggleOpen,
3298
- ToggleChevron,
3299
- defaultRenderers,
3300
- VoidBlockFallback,
3301
- BlockShell,
3302
- EditorView
3303
- };
3304
- //# sourceMappingURL=chunk-EPARJI4V.js.map
3157
+ export { BlockErrorContext, BlockShell, EditableRegion, EditorView, NATIVE_INTERACTION, NODE_ENTRY, SelectionSink, TaskCheckbox, ToggleChevron, ViewController, VoidBlockFallback, caretClientRect, caretFromPoint, createAutoScroll, defaultRenderers, dispatchSelection, domMapOf, domToPos, drawnBlockCount, focusOwners, handleCopy, hostKey, isComposingKey, isCrossSelection, isOnFirstLine, isOnLastLine, lineEdgeRect, listen, moveToNeighbour, neighbourBlock, onBlock, posToDom, regionInline, renderInline, textDiff, useBlockDomId, useEditorState, useIsomorphicLayoutEffect, useOrderedNumber, useQuoinEditor, useReadOnly, useRegionDomId, useToggleOpen, useViewController, visibleBlockIndexes, wholeState };
3158
+ //# sourceMappingURL=chunk-IEP7BPFN.js.map
3159
+ //# sourceMappingURL=chunk-IEP7BPFN.js.map