quoin-editor 2.0.4 → 2.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 (215) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/MIGRATION.md +1 -1
  3. package/README.md +14 -13
  4. package/dist/ai.cjs +124 -94
  5. package/dist/ai.d.cts +7 -0
  6. package/dist/ai.d.ts +7 -0
  7. package/dist/ai.js +50 -20
  8. package/dist/ai.js.map +1 -1
  9. package/dist/catalogue.cjs +28 -26
  10. package/dist/catalogue.js +19 -17
  11. package/dist/catalogue.js.map +1 -1
  12. package/dist/{chunk-JGEDJYIV.cjs → chunk-2FUWXPPC.cjs} +92 -98
  13. package/dist/{chunk-NHNW5DK3.js → chunk-3F76QQ65.js} +6 -6
  14. package/dist/{chunk-NHNW5DK3.js.map → chunk-3F76QQ65.js.map} +1 -1
  15. package/dist/{chunk-DBOZFNWU.js → chunk-3QYFAAQR.js} +3 -3
  16. package/dist/{chunk-DBOZFNWU.js.map → chunk-3QYFAAQR.js.map} +1 -1
  17. package/dist/{chunk-I7X7B3WD.cjs → chunk-4JDRDPLC.cjs} +17 -8
  18. package/dist/{chunk-EBSDPHPS.cjs → chunk-4UFWFV43.cjs} +1060 -719
  19. package/dist/{chunk-LM3DHROX.cjs → chunk-5AUIA4B3.cjs} +2 -2
  20. package/dist/{chunk-3INFNIGN.cjs → chunk-5H3BB5VJ.cjs} +131 -78
  21. package/dist/{chunk-DJU25PFC.cjs → chunk-5L2NSIHZ.cjs} +11 -11
  22. package/dist/{chunk-W376L2GM.js → chunk-6Y7JAWYY.js} +8 -8
  23. package/dist/chunk-6Y7JAWYY.js.map +1 -0
  24. package/dist/{chunk-UDBLZILE.js → chunk-ATKDXQEY.js} +12 -7
  25. package/dist/{chunk-UDBLZILE.js.map → chunk-ATKDXQEY.js.map} +1 -1
  26. package/dist/{chunk-A2IQHMIH.js → chunk-BE2SYPK5.js} +49 -54
  27. package/dist/chunk-BE2SYPK5.js.map +1 -0
  28. package/dist/{chunk-PURYVDC3.cjs → chunk-CFICD2JP.cjs} +21 -16
  29. package/dist/{chunk-3HW3WRYC.cjs → chunk-CSIUXYRU.cjs} +2 -2
  30. package/dist/{chunk-N7BSFDDM.cjs → chunk-DBKL524I.cjs} +23 -23
  31. package/dist/{chunk-XE3IYW5B.js → chunk-DEFYFIWW.js} +90 -37
  32. package/dist/chunk-DEFYFIWW.js.map +1 -0
  33. package/dist/{chunk-7E43TURF.cjs → chunk-ECI3PSMS.cjs} +7 -7
  34. package/dist/{chunk-4G645EYO.js → chunk-F73QEF7E.js} +5 -5
  35. package/dist/{chunk-4G645EYO.js.map → chunk-F73QEF7E.js.map} +1 -1
  36. package/dist/{chunk-KHRVCTQQ.cjs → chunk-FUT7XLMP.cjs} +61 -74
  37. package/dist/{chunk-7J63427U.cjs → chunk-GQSBOBOM.cjs} +375 -320
  38. package/dist/{chunk-LU3T3JB4.js → chunk-HPNSQWRD.js} +15 -28
  39. package/dist/chunk-HPNSQWRD.js.map +1 -0
  40. package/dist/{chunk-7Y4B7NHO.js → chunk-I34BFOLL.js} +18 -11
  41. package/dist/chunk-I34BFOLL.js.map +1 -0
  42. package/dist/{chunk-AJT54OMZ.js → chunk-IFRXEFQH.js} +9 -15
  43. package/dist/chunk-IFRXEFQH.js.map +1 -0
  44. package/dist/{chunk-YYW33WUL.cjs → chunk-K3XWVRL4.cjs} +8 -8
  45. package/dist/{chunk-LSI4RMTY.js → chunk-L5L6YNLT.js} +3 -3
  46. package/dist/{chunk-LSI4RMTY.js.map → chunk-L5L6YNLT.js.map} +1 -1
  47. package/dist/{chunk-2BPXVQBP.js → chunk-MO4UMXMT.js} +238 -86
  48. package/dist/chunk-MO4UMXMT.js.map +1 -0
  49. package/dist/{chunk-2QKFRKOP.cjs → chunk-N25EH2GZ.cjs} +351 -205
  50. package/dist/{chunk-CSPCDVCT.js → chunk-NCV2ML25.js} +3 -3
  51. package/dist/{chunk-CSPCDVCT.js.map → chunk-NCV2ML25.js.map} +1 -1
  52. package/dist/{chunk-NUQ64S5B.cjs → chunk-OJSKSQTL.cjs} +26 -26
  53. package/dist/chunk-PIWMU4BV.js +9 -0
  54. package/dist/chunk-PIWMU4BV.js.map +1 -0
  55. package/dist/chunk-QFGWSFOI.cjs +10 -0
  56. package/dist/{chunk-GPTJYWGS.js → chunk-RNBLVGWY.js} +3 -3
  57. package/dist/{chunk-GPTJYWGS.js.map → chunk-RNBLVGWY.js.map} +1 -1
  58. package/dist/{chunk-5RBMZGKV.js → chunk-TL2MJOWM.js} +325 -57
  59. package/dist/chunk-TL2MJOWM.js.map +1 -0
  60. package/dist/{chunk-YEDPBYO5.cjs → chunk-UDQ52EEC.cjs} +4 -4
  61. package/dist/{chunk-EIWPJWY3.js → chunk-UE2NQPNG.js} +5 -5
  62. package/dist/{chunk-EIWPJWY3.js.map → chunk-UE2NQPNG.js.map} +1 -1
  63. package/dist/{chunk-BE2YHZXA.cjs → chunk-ULV3SCYP.cjs} +26 -15
  64. package/dist/{chunk-WDBFGX3U.cjs → chunk-VTTMJGWP.cjs} +72 -77
  65. package/dist/{chunk-556PFYES.js → chunk-WK4UGDZN.js} +290 -235
  66. package/dist/chunk-WK4UGDZN.js.map +1 -0
  67. package/dist/{chunk-JZF6UQH5.cjs → chunk-WMKA37NJ.cjs} +12 -12
  68. package/dist/{chunk-F2ZK6Z52.js → chunk-Y26F2X4E.js} +3 -3
  69. package/dist/{chunk-F2ZK6Z52.js.map → chunk-Y26F2X4E.js.map} +1 -1
  70. package/dist/{chunk-FK7EBZPX.cjs → chunk-Z5EEDCRI.cjs} +549 -276
  71. package/dist/{chunk-G6NBQYMM.js → chunk-ZGFZRVQA.js} +817 -478
  72. package/dist/chunk-ZGFZRVQA.js.map +1 -0
  73. package/dist/{chunk-QLVX7MPS.js → chunk-ZQF45LA4.js} +19 -8
  74. package/dist/chunk-ZQF45LA4.js.map +1 -0
  75. package/dist/comments.cjs +127 -65
  76. package/dist/comments.d.cts +35 -2
  77. package/dist/comments.d.ts +35 -2
  78. package/dist/comments.js +73 -12
  79. package/dist/comments.js.map +1 -1
  80. package/dist/{diagram-extension-22x_njXB.d.ts → diagram-extension-BMlh8GCw.d.ts} +1 -1
  81. package/dist/{diagram-extension-C_FSkoj9.d.cts → diagram-extension-gmndUpti.d.cts} +1 -1
  82. package/dist/diagram.cjs +10 -9
  83. package/dist/diagram.d.cts +2 -2
  84. package/dist/diagram.d.ts +2 -2
  85. package/dist/diagram.js +7 -6
  86. package/dist/diff.cjs +25 -25
  87. package/dist/diff.js +3 -3
  88. package/dist/docx.cjs +31 -30
  89. package/dist/docx.js +5 -4
  90. package/dist/docx.js.map +1 -1
  91. package/dist/embed.cjs +10 -9
  92. package/dist/embed.js +8 -7
  93. package/dist/{emoji-extension-Dk5IQLZf.d.cts → emoji-extension-DD9CQTQj.d.cts} +1 -1
  94. package/dist/{emoji-extension-C832oGeT.d.ts → emoji-extension-U_PWZ2fX.d.ts} +1 -1
  95. package/dist/emoji.cjs +10 -9
  96. package/dist/emoji.d.cts +2 -2
  97. package/dist/emoji.d.ts +2 -2
  98. package/dist/emoji.js +7 -6
  99. package/dist/engine.cjs +58 -58
  100. package/dist/engine.d.cts +3 -3
  101. package/dist/engine.d.ts +3 -3
  102. package/dist/engine.js +3 -3
  103. package/dist/{find-extension-DmK9_N81.d.ts → find-extension-BGlqooZi.d.ts} +1 -1
  104. package/dist/{find-extension-BfruAPLi.d.cts → find-extension-BPnAJ8bY.d.cts} +1 -1
  105. package/dist/find.cjs +11 -10
  106. package/dist/find.d.cts +1 -1
  107. package/dist/find.d.ts +1 -1
  108. package/dist/find.js +7 -6
  109. package/dist/headless.cjs +70 -69
  110. package/dist/headless.d.cts +33 -10
  111. package/dist/headless.d.ts +33 -10
  112. package/dist/headless.js +5 -4
  113. package/dist/highlight.cjs +7 -6
  114. package/dist/highlight.js +6 -5
  115. package/dist/highlight.js.map +1 -1
  116. package/dist/{index-3fYvwqUZ.d.cts → index-DN7vRKFw.d.cts} +1 -1
  117. package/dist/{index-CgxnzCO5.d.ts → index-DyIYI3PM.d.ts} +1 -1
  118. package/dist/index.cjs +82 -81
  119. package/dist/index.d.cts +19 -12
  120. package/dist/index.d.ts +19 -12
  121. package/dist/index.js +6 -5
  122. package/dist/{labels-CiCxj2jP.d.cts → labels-BJORhN93.d.ts} +10 -5
  123. package/dist/{labels-BhRJYo46.d.ts → labels-CVYJ2-1X.d.cts} +10 -5
  124. package/dist/locale-ar.cjs +10 -0
  125. package/dist/locale-ar.d.cts +1 -1
  126. package/dist/locale-ar.d.ts +1 -1
  127. package/dist/locale-ar.js +10 -0
  128. package/dist/locale-ar.js.map +1 -1
  129. package/dist/locale-de.cjs +4 -0
  130. package/dist/locale-de.d.cts +1 -1
  131. package/dist/locale-de.d.ts +1 -1
  132. package/dist/locale-de.js +4 -0
  133. package/dist/locale-de.js.map +1 -1
  134. package/dist/locale-es.cjs +4 -0
  135. package/dist/locale-es.d.cts +1 -1
  136. package/dist/locale-es.d.ts +1 -1
  137. package/dist/locale-es.js +4 -0
  138. package/dist/locale-es.js.map +1 -1
  139. package/dist/locale-fr.cjs +4 -0
  140. package/dist/locale-fr.d.cts +1 -1
  141. package/dist/locale-fr.d.ts +1 -1
  142. package/dist/locale-fr.js +4 -0
  143. package/dist/locale-fr.js.map +1 -1
  144. package/dist/locale-ja.cjs +4 -0
  145. package/dist/locale-ja.d.cts +1 -1
  146. package/dist/locale-ja.d.ts +1 -1
  147. package/dist/locale-ja.js +4 -0
  148. package/dist/locale-ja.js.map +1 -1
  149. package/dist/locale-pt.cjs +4 -0
  150. package/dist/locale-pt.d.cts +1 -1
  151. package/dist/locale-pt.d.ts +1 -1
  152. package/dist/locale-pt.js +4 -0
  153. package/dist/locale-pt.js.map +1 -1
  154. package/dist/locale-zh.cjs +4 -0
  155. package/dist/locale-zh.d.cts +1 -1
  156. package/dist/locale-zh.d.ts +1 -1
  157. package/dist/locale-zh.js +4 -0
  158. package/dist/locale-zh.js.map +1 -1
  159. package/dist/math.cjs +11 -10
  160. package/dist/math.js +9 -8
  161. package/dist/mention.cjs +11 -10
  162. package/dist/mention.js +9 -8
  163. package/dist/{node-reveal-DY6bimv3.d.cts → node-reveal-Be7Xa0BL.d.cts} +1 -1
  164. package/dist/{node-reveal-BnFcnHhz.d.ts → node-reveal-CftIEqF_.d.ts} +1 -1
  165. package/dist/palette-DuIFHYHc.d.cts +10 -0
  166. package/dist/palette-DuIFHYHc.d.ts +10 -0
  167. package/dist/presence.cjs +39 -38
  168. package/dist/presence.js +8 -7
  169. package/dist/presence.js.map +1 -1
  170. package/dist/source.cjs +10 -9
  171. package/dist/source.d.cts +1 -1
  172. package/dist/source.d.ts +1 -1
  173. package/dist/source.js +6 -5
  174. package/dist/source.js.map +1 -1
  175. package/dist/{stats-extension-Dmw0Ujxe.d.ts → stats-extension-Bbpr593p.d.ts} +1 -1
  176. package/dist/{stats-extension-D5HySF0a.d.cts → stats-extension-D7FaeydW.d.cts} +1 -1
  177. package/dist/stats.cjs +12 -10
  178. package/dist/stats.d.cts +2 -2
  179. package/dist/stats.d.ts +2 -2
  180. package/dist/stats.js +9 -7
  181. package/dist/styles.css +1 -1
  182. package/dist/{table-extension-7LkLNK6Q.d.cts → table-extension-DNijjmxV.d.cts} +1 -1
  183. package/dist/{table-extension-DEpV0DnP.d.ts → table-extension-Dp6FYGPh.d.ts} +1 -1
  184. package/dist/table.cjs +26 -25
  185. package/dist/table.d.cts +4 -3
  186. package/dist/table.d.ts +4 -3
  187. package/dist/table.js +7 -6
  188. package/dist/{toc-extension-Dvh37bWQ.d.cts → toc-extension-BGEVAmSY.d.cts} +1 -1
  189. package/dist/{toc-extension-SVckrFmb.d.ts → toc-extension-DZIe40eV.d.ts} +1 -1
  190. package/dist/toc.cjs +10 -9
  191. package/dist/toc.d.cts +2 -2
  192. package/dist/toc.d.ts +2 -2
  193. package/dist/toc.js +7 -6
  194. package/dist/{types-DMuuDBVh.d.ts → types-Byu2a9qk.d.ts} +6 -1
  195. package/dist/{types-Bzhq5AXj.d.cts → types-DdDlCyyZ.d.cts} +6 -1
  196. package/dist/view.cjs +4 -4
  197. package/dist/view.js +2 -2
  198. package/dist/yjs.cjs +121 -121
  199. package/dist/yjs.d.cts +2 -2
  200. package/dist/yjs.d.ts +2 -2
  201. package/dist/yjs.js +5 -5
  202. package/package.json +4 -3
  203. package/dist/chunk-2BPXVQBP.js.map +0 -1
  204. package/dist/chunk-556PFYES.js.map +0 -1
  205. package/dist/chunk-5RBMZGKV.js.map +0 -1
  206. package/dist/chunk-7Y4B7NHO.js.map +0 -1
  207. package/dist/chunk-A2IQHMIH.js.map +0 -1
  208. package/dist/chunk-AJT54OMZ.js.map +0 -1
  209. package/dist/chunk-G6NBQYMM.js.map +0 -1
  210. package/dist/chunk-LU3T3JB4.js.map +0 -1
  211. package/dist/chunk-QLVX7MPS.js.map +0 -1
  212. package/dist/chunk-W376L2GM.js.map +0 -1
  213. package/dist/chunk-XE3IYW5B.js.map +0 -1
  214. package/dist/palette-BrX-hEd-.d.cts +0 -4
  215. package/dist/palette-BrX-hEd-.d.ts +0 -4
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkFK7EBZPX_cjs = require('./chunk-FK7EBZPX.cjs');
4
- var chunkI7X7B3WD_cjs = require('./chunk-I7X7B3WD.cjs');
3
+ var chunkQFGWSFOI_cjs = require('./chunk-QFGWSFOI.cjs');
4
+ var chunkZ5EEDCRI_cjs = require('./chunk-Z5EEDCRI.cjs');
5
+ var chunk4JDRDPLC_cjs = require('./chunk-4JDRDPLC.cjs');
5
6
  var react = require('react');
6
7
  var reactDom = require('react-dom');
7
8
  var jsxRuntime = require('react/jsx-runtime');
@@ -26,9 +27,9 @@ function useEditorState(controller, selector, isEqual = Object.is) {
26
27
  }
27
28
 
28
29
  // src/view/dom/attributes.ts
29
- var sortedEntries = (attrs) => chunkI7X7B3WD_cjs.dataAttributes(attrs, "");
30
+ var sortedEntries = (attrs) => chunk4JDRDPLC_cjs.dataAttributes(attrs, "");
30
31
  function setAttributes(element, attrs, prefix = "") {
31
- for (const [name, value] of chunkI7X7B3WD_cjs.writtenAttrs(chunkI7X7B3WD_cjs.dataAttributes(attrs, prefix))) element.setAttribute(name, value);
32
+ for (const [name, value] of chunk4JDRDPLC_cjs.writtenAttrs(chunk4JDRDPLC_cjs.dataAttributes(attrs, prefix))) element.setAttribute(name, value);
32
33
  }
33
34
 
34
35
  // src/view/dom/segments.ts
@@ -43,7 +44,7 @@ function decorationRanges(decorations, length) {
43
44
  return ranges;
44
45
  }
45
46
  function toSegments(inline, decorations) {
46
- const length = chunkI7X7B3WD_cjs.inlineLength(inline);
47
+ const length = chunk4JDRDPLC_cjs.inlineLength(inline);
47
48
  const ranges = decorationRanges(decorations, length);
48
49
  const widgets = decorations.filter((decoration) => decoration.kind === "widget").map((decoration) => ({ decoration, at: Math.min(Math.max(decoration.offset, 0), length) })).sort((a, b) => a.at - b.at || (a.decoration.side ?? 1) - (b.decoration.side ?? 1));
49
50
  const edges = [...ranges.flatMap((range) => [range.from, range.to]), ...widgets.map((widget) => widget.at)];
@@ -59,7 +60,7 @@ function toSegments(inline, decorations) {
59
60
  };
60
61
  let start = 0;
61
62
  for (const node of inline) {
62
- const end = start + chunkI7X7B3WD_cjs.nodeLength(node);
63
+ const end = start + chunk4JDRDPLC_cjs.nodeLength(node);
63
64
  if (node.kind === "atom") {
64
65
  placeWidgets(start);
65
66
  segments.push({ kind: "atom", node, decorations: covering(start, end), from: start });
@@ -114,7 +115,7 @@ function create(doc, tag, attributes) {
114
115
  return element;
115
116
  }
116
117
  function linkElement({ href = "", title } = {}, doc) {
117
- const safe = chunkI7X7B3WD_cjs.sanitizeHref(href);
118
+ const safe = chunk4JDRDPLC_cjs.sanitizeHref(href);
118
119
  if (safe === null) return create(doc, "span", [["data-quoin-link", ""]]);
119
120
  const anchor = create(doc, "a", [["href", safe], ["data-quoin-link", ""]]);
120
121
  if (title) anchor.title = title;
@@ -122,8 +123,8 @@ function linkElement({ href = "", title } = {}, doc) {
122
123
  }
123
124
  function markElement2(mark2, doc) {
124
125
  if (mark2.type === "link") return linkElement(mark2.attrs, doc);
125
- const { tag, attrs } = chunkI7X7B3WD_cjs.markElement(mark2);
126
- return create(doc, tag, chunkI7X7B3WD_cjs.writtenAttrs(attrs));
126
+ const { tag, attrs } = chunk4JDRDPLC_cjs.markElement(mark2);
127
+ return create(doc, tag, chunk4JDRDPLC_cjs.writtenAttrs(attrs));
127
128
  }
128
129
 
129
130
  // src/view/dom/wrappers.ts
@@ -320,8 +321,8 @@ function reconcileChildren(parent, specs) {
320
321
  // src/view/dom/text-diff.ts
321
322
  function textDiff(before, after, caretHint) {
322
323
  if (before === after) return null;
323
- const prefix = chunkFK7EBZPX_cjs.commonPrefix(before, after);
324
- const suffix = chunkFK7EBZPX_cjs.commonSuffix(before, after);
324
+ const prefix = chunkZ5EEDCRI_cjs.commonPrefix(before, after);
325
+ const suffix = chunkZ5EEDCRI_cjs.commonSuffix(before, after);
325
326
  const shared = Math.min(suffix, Math.min(before.length, after.length) - prefix);
326
327
  const removed = before.length - prefix - shared;
327
328
  const inserted = after.length - prefix - shared;
@@ -426,12 +427,12 @@ function specsFor(segment, options, doc) {
426
427
  }
427
428
  }
428
429
  function needsFiller(inline) {
429
- const content = chunkI7X7B3WD_cjs.inlineText(inline);
430
+ const content = chunk4JDRDPLC_cjs.inlineText(inline);
430
431
  return content === "" || content.endsWith("\n");
431
432
  }
432
433
  function renderInline(host, inline, decorations, options = {}) {
433
434
  const doc = host.ownerDocument;
434
- const length = chunkI7X7B3WD_cjs.inlineLength(inline);
435
+ const length = chunk4JDRDPLC_cjs.inlineLength(inline);
435
436
  const specs = toSegments(inline, decorations).flatMap((segment) => specsFor(segment, options, doc));
436
437
  if (needsFiller(inline)) specs.push(fillerSpec(doc, length));
437
438
  reconcileChildren(host, specs);
@@ -509,10 +510,10 @@ function readSelection(registry, domSelection, blockAt2 = () => void 0) {
509
510
  if (!domSelection || !anchorNode || !focusNode) return null;
510
511
  const anchor = domToPos(registry, anchorNode, domSelection.anchorOffset);
511
512
  const head = domToPos(registry, focusNode, domSelection.focusOffset);
512
- if (anchor && head) return chunkFK7EBZPX_cjs.textSelection(anchor, head);
513
+ if (anchor && head) return chunkZ5EEDCRI_cjs.textSelection(anchor, head);
513
514
  if (anchor || head || registry.locate(anchorNode) || registry.locate(focusNode)) return null;
514
515
  const block = blockAt2(anchorNode);
515
- return block !== void 0 && block === blockAt2(focusNode) ? chunkFK7EBZPX_cjs.nodeSelection(block) : null;
516
+ return block !== void 0 && block === blockAt2(focusNode) ? chunkZ5EEDCRI_cjs.nodeSelection(block) : null;
516
517
  }
517
518
  function selectBlock(domSelection, element) {
518
519
  if (!element) return false;
@@ -524,9 +525,12 @@ function selectBlock(domSelection, element) {
524
525
  return true;
525
526
  }
526
527
  var drawnUpstream = /* @__PURE__ */ new WeakMap();
528
+ function forgetDrawnSide(domSelection) {
529
+ drawnUpstream.delete(domSelection);
530
+ }
527
531
  function drawUpstream(registry, pos, domSelection, drawn) {
528
- const caret = chunkFK7EBZPX_cjs.textSelection(pos);
529
- const isAt = () => chunkFK7EBZPX_cjs.sameSelection(readSelection(registry, domSelection), caret);
532
+ const caret = chunkZ5EEDCRI_cjs.textSelection(pos);
533
+ const isAt = () => chunkZ5EEDCRI_cjs.sameSelection(readSelection(registry, domSelection), caret);
530
534
  if (drawn?.node === domSelection.focusNode && drawn.offset === domSelection.focusOffset && isAt()) {
531
535
  drawnUpstream.set(domSelection, drawn);
532
536
  return true;
@@ -546,7 +550,7 @@ function writeSelection(registry, selection, domSelection, blockElement) {
546
550
  if (anchor.block !== head.block || anchor.region !== head.region) return false;
547
551
  const drawn = drawnUpstream.get(domSelection);
548
552
  drawnUpstream.delete(domSelection);
549
- if (chunkFK7EBZPX_cjs.sameSelection(readSelection(registry, domSelection), selection)) return true;
553
+ if (chunkZ5EEDCRI_cjs.sameSelection(readSelection(registry, domSelection), selection)) return true;
550
554
  if (selection.assoc === -1 && anchor.offset === head.offset && drawUpstream(registry, head, domSelection, drawn)) {
551
555
  return true;
552
556
  }
@@ -599,20 +603,20 @@ function wrapsAt(pos, y, glyphAt2) {
599
603
  return after !== null && !onLine(after, y) && onLine(before, y) ? before : null;
600
604
  }
601
605
  function stayOnLine(pos, y, glyphAt2) {
602
- const caret = chunkFK7EBZPX_cjs.textSelection(pos);
606
+ const caret = chunkZ5EEDCRI_cjs.textSelection(pos);
603
607
  const before = wrapsAt(pos, y, glyphAt2);
604
608
  if (before === null) return caret;
605
- return /\S/.test(before.text) ? { ...caret, assoc: -1 } : chunkFK7EBZPX_cjs.textSelection({ ...pos, offset: pos.offset - 1 });
609
+ return /\S/.test(before.text) ? { ...caret, assoc: -1 } : chunkZ5EEDCRI_cjs.textSelection({ ...pos, offset: pos.offset - 1 });
606
610
  }
607
611
 
608
612
  // src/view/navigation/clicked-side.ts
609
613
  function keepClickedSide(controller, y) {
610
614
  controller.readSelectionFromDom();
611
615
  const { selection } = controller.editor.state;
612
- if (selection?.kind !== "text" || !chunkFK7EBZPX_cjs.isCollapsed(selection)) return;
616
+ if (selection?.kind !== "text" || !chunkZ5EEDCRI_cjs.isCollapsed(selection)) return;
613
617
  const upstream = wrapsAt(selection.head, y, glyphsAround(controller.registry, selection.head)) !== null;
614
618
  if (upstream !== (selection.assoc === -1)) {
615
- const caret = chunkFK7EBZPX_cjs.textSelection(selection.head);
619
+ const caret = chunkZ5EEDCRI_cjs.textSelection(selection.head);
616
620
  dispatchSelection(controller, upstream ? { ...caret, assoc: -1 } : caret);
617
621
  }
618
622
  }
@@ -662,8 +666,8 @@ var known = /* @__PURE__ */ new WeakMap();
662
666
  function hidersOf(doc) {
663
667
  let hiders = known.get(doc);
664
668
  if (hiders === void 0) {
665
- const first = doc.blocks.findIndex(chunkFK7EBZPX_cjs.isClosedToggle);
666
- hiders = doc.blocks.map((_, index) => first < 0 || index <= first ? null : chunkFK7EBZPX_cjs.hidingToggle(doc, index + 1));
669
+ const first = doc.blocks.findIndex(chunkZ5EEDCRI_cjs.isClosedToggle);
670
+ hiders = doc.blocks.map((_, index) => first < 0 || index <= first ? null : chunkZ5EEDCRI_cjs.hidingToggle(doc, index + 1));
667
671
  known.set(doc, hiders);
668
672
  }
669
673
  return hiders;
@@ -672,7 +676,7 @@ var hidingToggleAt = (doc, index) => hidersOf(doc)[index] ?? null;
672
676
  function isHiddenAt(doc, index, choices) {
673
677
  if (choices.size === 0) return hidingToggleAt(doc, index) !== null;
674
678
  const closed = (block) => block.type === "TOGGLE" && !shownOpen(block, choices);
675
- return chunkFK7EBZPX_cjs.hidingToggle(doc, index + 1, closed) !== null;
679
+ return chunkZ5EEDCRI_cjs.hidingToggle(doc, index + 1, closed) !== null;
676
680
  }
677
681
  var visibleBlockIndexes = (doc) => hidersOf(doc).flatMap((hider, index) => hider === null ? [index] : []);
678
682
  function drawnBlockCount(doc, start = 0, end = doc.blocks.length) {
@@ -694,18 +698,18 @@ function neighbourBlock(doc, from, direction, accept = anyBlock) {
694
698
  }
695
699
  function entryEdge(controller, block, direction) {
696
700
  const { doc, schema } = controller.editor.state;
697
- const edge = direction < 0 ? chunkFK7EBZPX_cjs.endOf(doc, schema, block) : chunkFK7EBZPX_cjs.startOf(doc, schema, block);
701
+ const edge = direction < 0 ? chunkZ5EEDCRI_cjs.endOf(doc, schema, block) : chunkZ5EEDCRI_cjs.startOf(doc, schema, block);
698
702
  if (edge.kind !== "text") return edge;
699
703
  const drawn = controller.registry.get(edge.head.block, edge.head.region) !== void 0;
700
- return drawn && !entersAsNode(controller, block) ? edge : chunkFK7EBZPX_cjs.nodeSelection(block);
704
+ return drawn && !entersAsNode(controller, block) ? edge : chunkZ5EEDCRI_cjs.nodeSelection(block);
701
705
  }
702
- var ownNode = (controller, block, direction) => direction < 0 && entersAsNode(controller, block) ? chunkFK7EBZPX_cjs.nodeSelection(block) : null;
706
+ var ownNode = (controller, block, direction) => direction < 0 && entersAsNode(controller, block) ? chunkZ5EEDCRI_cjs.nodeSelection(block) : null;
703
707
  var canBeEntered = (controller) => (block) => {
704
708
  const { schema } = controller.editor.state;
705
- const region = chunkFK7EBZPX_cjs.isTextFlow(schema, block) ? chunkFK7EBZPX_cjs.primaryRegion(schema, block) : null;
709
+ const region = chunkZ5EEDCRI_cjs.isTextFlow(schema, block) ? chunkZ5EEDCRI_cjs.primaryRegion(schema, block) : null;
706
710
  return region === null || controller.registry.get(block.id, region) !== void 0 || entersAsNode(controller, block.id);
707
711
  };
708
- var holdsTextHead = (controller) => (block) => chunkFK7EBZPX_cjs.isTextFlow(controller.editor.state.schema, block) && entryEdge(controller, block.id, 1).kind === "text";
712
+ var holdsTextHead = (controller) => (block) => chunkZ5EEDCRI_cjs.isTextFlow(controller.editor.state.schema, block) && entryEdge(controller, block.id, 1).kind === "text";
709
713
  function neighbourHead(controller, from, direction) {
710
714
  const target = neighbourBlock(controller.editor.state.doc, from, direction, holdsTextHead(controller));
711
715
  const edge = target && entryEdge(controller, target.id, direction);
@@ -721,13 +725,20 @@ function moveToNeighbour(controller, from, direction) {
721
725
  // src/view/selection/scroll-container.ts
722
726
  var SCROLLS = /* @__PURE__ */ new Set(["auto", "scroll"]);
723
727
  var scrollsVertically = (element) => SCROLLS.has(getComputedStyle(element).overflowY) && element.scrollHeight > element.clientHeight;
724
- function scrollContainerOf(element) {
728
+ function drawnParent(element) {
729
+ if (element.assignedSlot) return element.assignedSlot;
730
+ if (element.parentElement) return element.parentElement;
731
+ const parent = element.parentNode;
732
+ return parent && "host" in parent ? parent.host : null;
733
+ }
734
+ var scrollsItself = (body) => getComputedStyle(body.ownerDocument.documentElement).overflowY !== "visible" && scrollsVertically(body);
735
+ function scrollContainersOf(element) {
725
736
  const { body, documentElement } = element.ownerDocument;
726
- for (let node = element; node !== null; node = node.parentElement) {
727
- if (node === body || node === documentElement) return null;
728
- if (scrollsVertically(node)) return node;
737
+ const containers = [];
738
+ for (let node = element; node !== null && node !== documentElement; node = drawnParent(node)) {
739
+ if (node === body ? scrollsItself(node) : scrollsVertically(node)) containers.push(node);
729
740
  }
730
- return null;
741
+ return containers;
731
742
  }
732
743
 
733
744
  // src/view/selection/auto-scroll.ts
@@ -738,30 +749,41 @@ function edgesOf(container, win) {
738
749
  const top = container.getBoundingClientRect().top + container.clientTop;
739
750
  return { top: Math.max(top, 0), bottom: Math.min(top + container.clientHeight, win.innerHeight) };
740
751
  }
752
+ var hasRoom = (container, delta) => delta < 0 ? container.scrollTop > 0 : Math.ceil(container.scrollTop) + container.clientHeight < container.scrollHeight;
741
753
  function createAutoScroll(element, onScroll, edge = EDGE) {
742
754
  const win = element.ownerDocument.defaultView;
743
- let container;
744
- let delta = 0;
755
+ let scrollers = null;
756
+ let pointerY = 0;
745
757
  let frame = null;
746
758
  const step = (depth) => Math.ceil(Math.min(depth, edge) / edge * MAX_STEP);
759
+ function deltaIn(container) {
760
+ const { top, bottom } = edgesOf(container, win);
761
+ const [upper, lower] = [top + edge, bottom - edge];
762
+ return pointerY < upper ? -step(upper - pointerY) : pointerY > lower ? step(pointerY - lower) : 0;
763
+ }
764
+ function next() {
765
+ scrollers ??= [...scrollContainersOf(element), null];
766
+ for (const scroller of scrollers) {
767
+ const delta = deltaIn(scroller);
768
+ if (delta !== 0 && (scroller === null || hasRoom(scroller, delta))) return { scroller, delta };
769
+ }
770
+ return null;
771
+ }
747
772
  function tick() {
748
773
  frame = null;
749
- if (delta === 0) return;
750
- (container ?? win).scrollBy(0, delta);
774
+ const target = next();
775
+ if (target === null) return;
776
+ (target.scroller ?? win).scrollBy(0, target.delta);
751
777
  onScroll();
752
778
  frame = win.requestAnimationFrame(tick);
753
779
  }
754
780
  return {
755
781
  update(clientY) {
756
- if (container === void 0) container = scrollContainerOf(element);
757
- const { top, bottom } = edgesOf(container, win);
758
- const [upper, lower] = [top + edge, bottom - edge];
759
- delta = clientY < upper ? -step(upper - clientY) : clientY > lower ? step(clientY - lower) : 0;
760
- if (delta !== 0 && frame === null) frame = win.requestAnimationFrame(tick);
782
+ pointerY = clientY;
783
+ if (frame === null && next() !== null) frame = win.requestAnimationFrame(tick);
761
784
  },
762
785
  stop() {
763
- delta = 0;
764
- container = void 0;
786
+ scrollers = null;
765
787
  if (frame !== null) win.cancelAnimationFrame(frame);
766
788
  frame = null;
767
789
  }
@@ -829,7 +851,7 @@ function isCrossSelection(selection) {
829
851
  }
830
852
  function selectionDecorations(state, mode) {
831
853
  if (mode !== "decorations" || !isCrossSelection(state.selection)) return [];
832
- return chunkFK7EBZPX_cjs.markRanges(state).map(({ block, region, from, to }) => ({
854
+ return chunkZ5EEDCRI_cjs.markRanges(state).map(({ block, region, from, to }) => ({
833
855
  kind: "inline",
834
856
  block,
835
857
  region,
@@ -863,7 +885,7 @@ function createCrossBlockPointer(controller) {
863
885
  let preventMouseDown = false;
864
886
  const scroll = createAutoScroll(root, () => follow(last.x, last.y));
865
887
  function select(selection) {
866
- if (chunkFK7EBZPX_cjs.sameSelection(selection, controller.editor.state.selection)) return;
888
+ if (chunkZ5EEDCRI_cjs.sameSelection(selection, controller.editor.state.selection)) return;
867
889
  dispatchSelection(controller, selection);
868
890
  }
869
891
  function startDragging() {
@@ -879,14 +901,14 @@ function createCrossBlockPointer(controller) {
879
901
  if (current.anchor === null) return;
880
902
  startDragging();
881
903
  }
882
- select(chunkFK7EBZPX_cjs.textSelection(current.anchor, caretPosAt(controller, target, x, y)));
904
+ select(chunkZ5EEDCRI_cjs.textSelection(current.anchor, caretPosAt(controller, target, x, y)));
883
905
  }
884
906
  function followBlocks(current, x, y) {
885
907
  if (!controller.dragging && Math.hypot(x - current.x, y - current.y) < DRAG_DISTANCE) return;
886
908
  const block = blockAt(controller, x, y);
887
909
  if (block === null) return;
888
910
  startDragging();
889
- select(chunkFK7EBZPX_cjs.blockRangeSelection(current.start, block));
911
+ select(chunkZ5EEDCRI_cjs.blockRangeSelection(current.start, block));
890
912
  }
891
913
  function follow(x, y) {
892
914
  if (press?.kind === "text") followText(press, x, y);
@@ -926,23 +948,33 @@ function createCrossBlockPointer(controller) {
926
948
  }
927
949
  function pressWhole(block) {
928
950
  if (entryEdge(controller, block, 1).kind !== "node") return;
929
- const pressed = chunkI7X7B3WD_cjs.blockById(controller.editor.state.doc, block);
930
- if (pressed !== void 0 && !canBeEntered(controller)(pressed)) return select(chunkFK7EBZPX_cjs.blockRangeSelection(block));
951
+ const pressed = chunk4JDRDPLC_cjs.blockById(controller.editor.state.doc, block);
952
+ if (pressed !== void 0 && !canBeEntered(controller)(pressed)) return select(chunkZ5EEDCRI_cjs.blockRangeSelection(block));
931
953
  controller.nodeReveal.pressed(block);
932
- select(chunkFK7EBZPX_cjs.nodeSelection(block));
954
+ select(chunkZ5EEDCRI_cjs.nodeSelection(block));
955
+ }
956
+ function followTap(event, block) {
957
+ if (block === void 0 || event.shiftKey) return;
958
+ const lift = (up) => {
959
+ if (up.pointerId !== event.pointerId) return;
960
+ end();
961
+ pressWhole(block);
962
+ };
963
+ unfollow = listen(doc, { pointerup: lift, pointercancel: end });
933
964
  }
934
965
  function onPointerDown(event) {
935
966
  end();
936
967
  preventMouseDown = false;
937
- if (event.button !== 0 || event.pointerType === "touch") return;
968
+ if (event.button !== 0) return;
938
969
  const target = event.target;
939
970
  const host = controller.registry.locate(target);
940
- const block = host === null ? controller.blockAt(target) : void 0;
941
971
  const control = target.closest(CONTROLS);
972
+ const block = host === null && !(control && root.contains(control)) ? controller.blockAt(target) : void 0;
973
+ if (event.pointerType === "touch") return followTap(event, block);
942
974
  if (host !== null) {
943
975
  press = { kind: "text", host, anchor: null };
944
976
  if (event.shiftKey) extendFrom(host, event.clientX, event.clientY);
945
- } else if (block !== void 0 && !(control && root.contains(control))) {
977
+ } else if (block !== void 0) {
946
978
  press = { kind: "blocks", start: block, x: event.clientX, y: event.clientY };
947
979
  if (!event.shiftKey) pressWhole(block);
948
980
  } else {
@@ -987,7 +1019,7 @@ function installHighlightStyle(doc) {
987
1019
  // src/view/selection/paint-selection.ts
988
1020
  var NAME = "quoin-selection";
989
1021
  function coveredRanges(controller) {
990
- return chunkFK7EBZPX_cjs.markRanges(controller.editor.state).flatMap(({ block, region, from, to }) => {
1022
+ return chunkZ5EEDCRI_cjs.markRanges(controller.editor.state).flatMap(({ block, region, from, to }) => {
991
1023
  const host = controller.registry.get(block, region);
992
1024
  const map = host && domMapOf(host);
993
1025
  if (!host || !map) return [];
@@ -1060,15 +1092,23 @@ function heldBySink(selection) {
1060
1092
  }
1061
1093
  var NO_TEXT = "\xA0";
1062
1094
  function selectionText(state) {
1063
- const text = chunkFK7EBZPX_cjs.markRanges(state).map((range) => chunkI7X7B3WD_cjs.inlinePlainText(chunkFK7EBZPX_cjs.rangeContent(state, range), state.schema)).join("\n");
1095
+ const text = chunkZ5EEDCRI_cjs.markRanges(state).map((range) => chunk4JDRDPLC_cjs.inlinePlainText(chunkZ5EEDCRI_cjs.rangeContent(state, range), state.schema)).join("\n");
1064
1096
  return text === "" ? NO_TEXT : text;
1065
1097
  }
1066
1098
  var focusInPlace = (sink) => inPlace(sink, () => sink.focus({ preventScroll: true }));
1067
1099
  var focusing = null;
1068
1100
  var focusingSink = (controller) => focusing === controller;
1101
+ function placeSink(controller, sink) {
1102
+ const id = chunkZ5EEDCRI_cjs.headBlockId(controller.editor.state.selection);
1103
+ const block = id === null ? void 0 : controller.blockElement(id);
1104
+ if (block === void 0) return;
1105
+ const offset = block.getBoundingClientRect().top - sink.getBoundingClientRect().top;
1106
+ if (offset !== 0) sink.style.top = `${(parseFloat(sink.style.top) || 0) + offset}px`;
1107
+ }
1069
1108
  function focusSink(controller) {
1070
1109
  const { sink } = controller;
1071
1110
  if (sink === null) return;
1111
+ placeSink(controller, sink);
1072
1112
  const text = selectionText(controller.editor.state);
1073
1113
  if (sink.textContent !== text) sink.textContent = text;
1074
1114
  if (sink.ownerDocument.activeElement !== sink) {
@@ -1083,7 +1123,7 @@ function focusSink(controller) {
1083
1123
  sink.ownerDocument.getSelection()?.selectAllChildren(sink);
1084
1124
  }
1085
1125
  function selectedBlockName({ doc, schema, selection }, blockLabel) {
1086
- const block = selection?.kind === "node" ? chunkI7X7B3WD_cjs.blockById(doc, selection.block) : void 0;
1126
+ const block = selection?.kind === "node" ? chunk4JDRDPLC_cjs.blockById(doc, selection.block) : void 0;
1087
1127
  return block === void 0 ? null : blockLabel?.(block, schema) ?? "";
1088
1128
  }
1089
1129
  function clearSink(controller) {
@@ -1220,7 +1260,7 @@ function createElementSlot(changed) {
1220
1260
 
1221
1261
  // src/view/controller/selection-element.ts
1222
1262
  function elementFor({ doc }, selection, rendered) {
1223
- const id = chunkFK7EBZPX_cjs.headBlockId(selection);
1263
+ const id = chunkZ5EEDCRI_cjs.headBlockId(selection);
1224
1264
  const index = id === null ? void 0 : doc.index.get(id);
1225
1265
  if (id === null || index === void 0) return void 0;
1226
1266
  const hiding = hidingToggleAt(doc, index);
@@ -1233,7 +1273,7 @@ function selectionElement(state, rendered) {
1233
1273
  if (doc.blocks.length === 0) return rendered.empty?.() ?? void 0;
1234
1274
  const sink = heldBySink(selection) ? rendered.sink?.() : null;
1235
1275
  if (sink) return sink;
1236
- return elementFor(state, selection, rendered) ?? elementFor(state, chunkFK7EBZPX_cjs.startOf(doc, schema, doc.blocks[0].id), rendered);
1276
+ return elementFor(state, selection, rendered) ?? elementFor(state, chunkZ5EEDCRI_cjs.startOf(doc, schema, doc.blocks[0].id), rendered);
1237
1277
  }
1238
1278
 
1239
1279
  // src/view/controller/tab-stop.ts
@@ -1287,7 +1327,7 @@ function createDrawnElements(hosts, state) {
1287
1327
  }
1288
1328
 
1289
1329
  // src/view/controller/engagement.ts
1290
- var chosenHere = (tr) => tr !== null && tr.selectionSet && !chunkFK7EBZPX_cjs.foreignOrigins.includes(tr.origin);
1330
+ var chosenHere = (tr) => tr !== null && tr.selectionSet && !chunkZ5EEDCRI_cjs.foreignOrigins.includes(tr.origin);
1291
1331
  function createEngagement(editor) {
1292
1332
  let engaged = false;
1293
1333
  const listeners = /* @__PURE__ */ new Set();
@@ -1321,13 +1361,33 @@ function ownsFocus(controller, doc) {
1321
1361
  return !active || active === doc.body || active === controller.root || hasFocus(controller, doc);
1322
1362
  }
1323
1363
 
1364
+ // src/view/controller/focus-follow.ts
1365
+ function createFocusFollow(controller, focusElement) {
1366
+ const take = (preventScroll) => {
1367
+ const element = focusElement();
1368
+ if (!element || element.ownerDocument.activeElement === element) return;
1369
+ if (element === controller.sink) focusSink(controller);
1370
+ else element.focus({ preventScroll });
1371
+ };
1372
+ return {
1373
+ take,
1374
+ keep(preventScroll) {
1375
+ if (controller.composingKey === null) take(preventScroll);
1376
+ },
1377
+ rewrite(host) {
1378
+ const inSelection = host.contains(controller.domSelection()?.focusNode ?? null);
1379
+ if (inSelection && hasFocus(controller, host.ownerDocument)) controller.syncSelectionToDom();
1380
+ }
1381
+ };
1382
+ }
1383
+
1324
1384
  // src/view/controller/focus-target.ts
1325
1385
  function focusTarget(state, target) {
1326
1386
  const { doc, schema, selection } = state;
1327
1387
  if (doc.blocks.length === 0) return null;
1328
- if (target === "end") return chunkFK7EBZPX_cjs.endOf(doc, schema, doc.blocks[doc.blocks.length - 1].id);
1329
- if (target === "start" || target === void 0 && selection === null) return chunkFK7EBZPX_cjs.startOf(doc, schema, doc.blocks[0].id);
1330
- return target === void 0 ? selection : chunkFK7EBZPX_cjs.textSelection(target);
1388
+ if (target === "end") return chunkZ5EEDCRI_cjs.endOf(doc, schema, doc.blocks[doc.blocks.length - 1].id);
1389
+ if (target === "start" || target === void 0 && selection === null) return chunkZ5EEDCRI_cjs.startOf(doc, schema, doc.blocks[0].id);
1390
+ return target === void 0 ? selection : chunkZ5EEDCRI_cjs.textSelection(target);
1331
1391
  }
1332
1392
 
1333
1393
  // src/view/controller/host-decorations.ts
@@ -1343,7 +1403,7 @@ function decorationsByHost(decorations) {
1343
1403
  return byHost;
1344
1404
  }
1345
1405
  function sameDecoration(a, b) {
1346
- if (a.kind !== b.kind || a.block !== b.block || !chunkI7X7B3WD_cjs.sameAttrs(a.attrs, b.attrs)) return false;
1406
+ if (a.kind !== b.kind || a.block !== b.block || !chunk4JDRDPLC_cjs.sameAttrs(a.attrs, b.attrs)) return false;
1347
1407
  if (a.kind === "inline" && b.kind === "inline") {
1348
1408
  return a.region === b.region && a.from === b.from && a.to === b.to;
1349
1409
  }
@@ -1354,7 +1414,7 @@ function sameDecoration(a, b) {
1354
1414
  return true;
1355
1415
  }
1356
1416
  function sameDecorations(a, b) {
1357
- return a === b || chunkI7X7B3WD_cjs.sameItems(a, b, sameDecoration);
1417
+ return a === b || chunk4JDRDPLC_cjs.sameItems(a, b, sameDecoration);
1358
1418
  }
1359
1419
  var byMode = { highlight: /* @__PURE__ */ new WeakMap(), decorations: /* @__PURE__ */ new WeakMap() };
1360
1420
  function hostDecorations(editor, block, region, mode = "highlight") {
@@ -1370,7 +1430,7 @@ function hostDecorations(editor, block, region, mode = "highlight") {
1370
1430
 
1371
1431
  // src/view/controller/region-inline.ts
1372
1432
  function regionInline(state, block, region) {
1373
- const regions = chunkI7X7B3WD_cjs.blockById(state.doc, block)?.regions;
1433
+ const regions = chunk4JDRDPLC_cjs.blockById(state.doc, block)?.regions;
1374
1434
  return regions && Object.hasOwn(regions, region) ? regions[region] : void 0;
1375
1435
  }
1376
1436
 
@@ -1420,7 +1480,7 @@ function createOutsideChanges(editorHasFocus, movedFrom) {
1420
1480
  }
1421
1481
  const from = moved ?? (outside && !settled ? movedFrom(tr.before.selection) : null);
1422
1482
  settled ||= outside;
1423
- moved = from && chunkFK7EBZPX_cjs.mapSelection(from, (pos, assoc) => tr.mapPos(pos, assoc), tr.before.doc);
1483
+ moved = from && chunkZ5EEDCRI_cjs.carrySelection(from, (pos, assoc) => tr.mapPos(pos, assoc), tr.before.doc, tr.doc, tr.origin);
1424
1484
  },
1425
1485
  takeFocused() {
1426
1486
  const value = focused;
@@ -1513,7 +1573,7 @@ function handleCopy(controller, event, cut) {
1513
1573
  clipboardData.setData("text/plain", copied.text);
1514
1574
  clipboardData.setData("text/html", wrapSliceHTML(copied.html, copied.json));
1515
1575
  clipboardData.setData(QUOIN_SLICE_TYPE, copied.json);
1516
- if (cut) controller.run(chunkFK7EBZPX_cjs.deleteSelection);
1576
+ if (cut) controller.run(chunkZ5EEDCRI_cjs.deleteSelection);
1517
1577
  }
1518
1578
  function handlePaste(controller, event) {
1519
1579
  if (!event.clipboardData) return;
@@ -1545,7 +1605,7 @@ function handleDrop(controller, event) {
1545
1605
  return;
1546
1606
  }
1547
1607
  const pos = dropPos(controller, event.clientX, event.clientY);
1548
- if (pos) controller.dispatch(controller.editor.createTransaction().setSelection(chunkFK7EBZPX_cjs.textSelection(pos)).setOrigin("drop"));
1608
+ if (pos) controller.dispatch(controller.editor.createTransaction().setSelection(chunkZ5EEDCRI_cjs.textSelection(pos)).setOrigin("drop"));
1549
1609
  pasteTransfer(controller, dataTransfer);
1550
1610
  }
1551
1611
  function handleDragOver(event) {
@@ -1675,29 +1735,31 @@ function createSinkComposition(controller, settled = () => {
1675
1735
  var LINE_BREAK = "\n";
1676
1736
  var transposeChars = (state, dispatch) => {
1677
1737
  const { selection } = state;
1678
- if (selection?.kind !== "text" || !chunkFK7EBZPX_cjs.isCollapsed(selection)) return false;
1738
+ if (selection?.kind !== "text" || !chunkZ5EEDCRI_cjs.isCollapsed(selection)) return false;
1679
1739
  const { head } = selection;
1680
- const inline = chunkI7X7B3WD_cjs.blockById(state.doc, head.block)?.regions[head.region];
1740
+ const inline = chunk4JDRDPLC_cjs.blockById(state.doc, head.block)?.regions[head.region];
1681
1741
  if (inline === void 0) return false;
1682
- const value = chunkI7X7B3WD_cjs.inlineText(inline);
1742
+ const value = chunk4JDRDPLC_cjs.inlineText(inline);
1683
1743
  const atLineEnd = head.offset === value.length || value[head.offset] === LINE_BREAK;
1684
- const end = atLineEnd ? head.offset : chunkFK7EBZPX_cjs.nextGraphemeOffset(value, head.offset);
1685
- const middle = chunkFK7EBZPX_cjs.prevGraphemeOffset(value, end);
1686
- const start = chunkFK7EBZPX_cjs.prevGraphemeOffset(value, middle);
1744
+ const end = atLineEnd ? head.offset : chunkZ5EEDCRI_cjs.nextGraphemeOffset(value, head.offset);
1745
+ const middle = chunkZ5EEDCRI_cjs.prevGraphemeOffset(value, end);
1746
+ const start = chunkZ5EEDCRI_cjs.prevGraphemeOffset(value, middle);
1687
1747
  if (start === middle || value.slice(start, end).includes(LINE_BREAK)) return false;
1688
- const swapped = [...chunkI7X7B3WD_cjs.sliceInline(inline, middle, end), ...chunkI7X7B3WD_cjs.sliceInline(inline, start, middle)];
1689
- const tr = new chunkFK7EBZPX_cjs.Transaction(state).setOrigin("input");
1690
- tr.step(chunkFK7EBZPX_cjs.replaceInlineStep(head.block, head.region, start, end, swapped));
1691
- dispatch?.(tr.setSelection(chunkFK7EBZPX_cjs.textSelection({ ...head, offset: end })));
1748
+ const swapped = [...chunk4JDRDPLC_cjs.sliceInline(inline, middle, end), ...chunk4JDRDPLC_cjs.sliceInline(inline, start, middle)];
1749
+ const tr = new chunkZ5EEDCRI_cjs.Transaction(state).setOrigin("input");
1750
+ tr.step(chunkZ5EEDCRI_cjs.replaceInlineStep(head.block, head.region, start, end, swapped));
1751
+ dispatch?.(tr.setSelection(chunkZ5EEDCRI_cjs.textSelection({ ...head, offset: end })));
1692
1752
  return true;
1693
1753
  };
1694
1754
 
1695
1755
  // src/view/input/replace-range.ts
1696
1756
  function replaceRange(editor, range, text, withRules) {
1697
- const dispatch = (tr) => editor.dispatch(tr);
1698
- dispatch(editor.createTransaction().setSelection(chunkFK7EBZPX_cjs.textSelection(range.from, range.to)).setOrigin("input"));
1699
- if (text === "") return chunkFK7EBZPX_cjs.deleteSelection(editor.state, (tr) => dispatch(tr.setOrigin("input")));
1700
- return withRules ? editor.insertText(text) : chunkFK7EBZPX_cjs.insertText(text, { origin: "input" })(editor.state, dispatch);
1757
+ const { doc, selection } = editor.state;
1758
+ const dispatch = (tr) => editor.dispatch(tr.setOrigin("input"));
1759
+ dispatch(editor.createTransaction().setSelection(chunkZ5EEDCRI_cjs.textSelection(range.from, range.to)));
1760
+ const replaced = text === "" ? chunkZ5EEDCRI_cjs.deleteSelection(editor.state, dispatch) : withRules ? editor.insertText(text) : chunkZ5EEDCRI_cjs.insertText(text, { origin: "input" })(editor.state, dispatch);
1761
+ if (editor.state.doc === doc && selection !== null) dispatch(editor.createTransaction().setSelection(selection));
1762
+ return replaced;
1701
1763
  }
1702
1764
 
1703
1765
  // src/view/input/target-range.ts
@@ -1708,13 +1770,13 @@ function targetRangeToModel(controller, event) {
1708
1770
  const to = domToPos(controller.registry, range.endContainer, range.endOffset);
1709
1771
  return from && to && { from, to };
1710
1772
  }
1711
- var isEmpty = ({ from, to }) => chunkFK7EBZPX_cjs.sameSelection(chunkFK7EBZPX_cjs.textSelection(from), chunkFK7EBZPX_cjs.textSelection(to));
1773
+ var isEmpty = ({ from, to }) => chunkZ5EEDCRI_cjs.sameSelection(chunkZ5EEDCRI_cjs.textSelection(from), chunkZ5EEDCRI_cjs.textSelection(to));
1712
1774
  function targetBeyondSelection(controller, event) {
1713
1775
  const range = targetRangeToModel(controller, event);
1714
1776
  if (range === null || isEmpty(range)) return null;
1715
1777
  const { doc, selection } = controller.editor.state;
1716
- const selected = chunkFK7EBZPX_cjs.selectionRange(doc, selection);
1717
- const same = selected !== null && chunkFK7EBZPX_cjs.sameSelection(chunkFK7EBZPX_cjs.textSelection(selected.from, selected.to), chunkFK7EBZPX_cjs.textSelection(range.from, range.to));
1778
+ const selected = chunkZ5EEDCRI_cjs.selectionRange(doc, selection);
1779
+ const same = selected !== null && chunkZ5EEDCRI_cjs.sameSelection(chunkZ5EEDCRI_cjs.textSelection(selected.from, selected.to), chunkZ5EEDCRI_cjs.textSelection(range.from, range.to));
1718
1780
  return same ? null : range;
1719
1781
  }
1720
1782
 
@@ -1736,34 +1798,34 @@ function insertTypedText(controller, event) {
1736
1798
  else controller.edit(() => replaceRange(controller.editor, range, text, false));
1737
1799
  }
1738
1800
  function deleteContentBackward(controller, event) {
1739
- if (!controller.run(chunkFK7EBZPX_cjs.undoInputRule)) targetOr(chunkFK7EBZPX_cjs.deleteBackward)(controller, event);
1801
+ if (!controller.run(chunkZ5EEDCRI_cjs.undoInputRule)) targetOr(chunkZ5EEDCRI_cjs.deleteBackward)(controller, event);
1740
1802
  }
1741
1803
  function insertReplacementText(controller, event) {
1742
1804
  const text = event.dataTransfer?.getData("text/plain") || event.data;
1743
1805
  if (!text) return;
1744
1806
  const range = targetRangeToModel(controller, event);
1745
- if (range === null) controller.run(chunkFK7EBZPX_cjs.insertText(text, { origin: "input" }));
1807
+ if (range === null) controller.run(chunkZ5EEDCRI_cjs.insertText(text, { origin: "input" }));
1746
1808
  else controller.edit(() => replaceRange(controller.editor, range, text, false));
1747
1809
  }
1748
1810
  var actions = {
1749
1811
  insertText: insertTypedText,
1750
1812
  insertReplacementText,
1751
1813
  insertParagraph: (controller) => void controller.edit(() => controller.editor.handleKey(ENTER)),
1752
- insertLineBreak: run(chunkFK7EBZPX_cjs.insertHardBreak),
1814
+ insertLineBreak: run(chunkZ5EEDCRI_cjs.insertHardBreak),
1753
1815
  deleteContentBackward,
1754
- deleteContentForward: targetOr(chunkFK7EBZPX_cjs.deleteForward),
1755
- deleteWordBackward: targetOr(chunkFK7EBZPX_cjs.deleteWordBackward),
1756
- deleteWordForward: targetOr(chunkFK7EBZPX_cjs.deleteWordForward),
1757
- deleteSoftLineBackward: targetOr(chunkFK7EBZPX_cjs.deleteToLineStart),
1758
- deleteHardLineBackward: targetOr(chunkFK7EBZPX_cjs.deleteToLineStart),
1759
- deleteSoftLineForward: targetOr(chunkFK7EBZPX_cjs.deleteToLineEnd),
1760
- deleteHardLineForward: targetOr(chunkFK7EBZPX_cjs.deleteToLineEnd),
1761
- formatBold: run(chunkFK7EBZPX_cjs.toggleMark("bold")),
1762
- formatItalic: run(chunkFK7EBZPX_cjs.toggleMark("italic")),
1763
- formatUnderline: run(chunkFK7EBZPX_cjs.toggleMark("underline")),
1764
- formatStrikeThrough: run(chunkFK7EBZPX_cjs.toggleMark("strike")),
1765
- historyUndo: run(chunkFK7EBZPX_cjs.undo),
1766
- historyRedo: run(chunkFK7EBZPX_cjs.redo),
1816
+ deleteContentForward: targetOr(chunkZ5EEDCRI_cjs.deleteForward),
1817
+ deleteWordBackward: targetOr(chunkZ5EEDCRI_cjs.deleteWordBackward),
1818
+ deleteWordForward: targetOr(chunkZ5EEDCRI_cjs.deleteWordForward),
1819
+ deleteSoftLineBackward: targetOr(chunkZ5EEDCRI_cjs.deleteToLineStart),
1820
+ deleteHardLineBackward: targetOr(chunkZ5EEDCRI_cjs.deleteToLineStart),
1821
+ deleteSoftLineForward: targetOr(chunkZ5EEDCRI_cjs.deleteToLineEnd),
1822
+ deleteHardLineForward: targetOr(chunkZ5EEDCRI_cjs.deleteToLineEnd),
1823
+ formatBold: run(chunkZ5EEDCRI_cjs.toggleMark("bold")),
1824
+ formatItalic: run(chunkZ5EEDCRI_cjs.toggleMark("italic")),
1825
+ formatUnderline: run(chunkZ5EEDCRI_cjs.toggleMark("underline")),
1826
+ formatStrikeThrough: run(chunkZ5EEDCRI_cjs.toggleMark("strike")),
1827
+ historyUndo: run(chunkZ5EEDCRI_cjs.undo),
1828
+ historyRedo: run(chunkZ5EEDCRI_cjs.redo),
1767
1829
  insertTranspose: run(transposeChars),
1768
1830
  insertFromPaste: leaveToHandlers,
1769
1831
  insertFromDrop: leaveToHandlers,
@@ -1864,7 +1926,7 @@ function snapshotComposition(controller, block, region) {
1864
1926
  const element = controller.registry.get(block, region);
1865
1927
  const inline = regionInline(editor.state, block, region);
1866
1928
  if (element === void 0 || inline === void 0) return null;
1867
- const text = chunkI7X7B3WD_cjs.inlineText(inline);
1929
+ const text = chunk4JDRDPLC_cjs.inlineText(inline);
1868
1930
  const end = composedEnd(controller, block, region);
1869
1931
  const since = [];
1870
1932
  const release = editor.subscribe((_, tr) => void (tr && since.push(tr)));
@@ -1978,7 +2040,7 @@ function reconcileHost(controller, block, region, caretHint) {
1978
2040
  const element = controller.registry.get(block, region);
1979
2041
  const inline = regionInline(controller.editor.state, block, region);
1980
2042
  if (element === void 0 || inline === void 0) return false;
1981
- const before = chunkI7X7B3WD_cjs.inlineText(inline);
2043
+ const before = chunk4JDRDPLC_cjs.inlineText(inline);
1982
2044
  const after = readDomText(element);
1983
2045
  const edit = before === after ? null : textDiff(before, after, domCaretOffset(element));
1984
2046
  if (edit === null) return false;
@@ -2049,33 +2111,33 @@ var arrowAsWritten = (key, direction) => direction === "rtl" && Object.hasOwn(MI
2049
2111
 
2050
2112
  // src/view/navigation/cross-moves.ts
2051
2113
  function moveHead(controller, { anchor }, head) {
2052
- dispatchSelection(controller, chunkFK7EBZPX_cjs.textSelection(anchor, head));
2114
+ dispatchSelection(controller, chunkZ5EEDCRI_cjs.textSelection(anchor, head));
2053
2115
  return true;
2054
2116
  }
2055
2117
  function blockOf(controller, { block }) {
2056
2118
  const { doc } = controller.editor.state;
2057
- return doc.blocks[chunkI7X7B3WD_cjs.requireBlockIndex(doc, block)];
2119
+ return doc.blocks[chunk4JDRDPLC_cjs.requireBlockIndex(doc, block)];
2058
2120
  }
2059
2121
  function collapseCross(controller, selection, direction) {
2060
- const { from, to } = chunkFK7EBZPX_cjs.selectionRange(controller.editor.state.doc, selection);
2061
- dispatchSelection(controller, chunkFK7EBZPX_cjs.textSelection(direction < 0 ? from : to));
2122
+ const { from, to } = chunkZ5EEDCRI_cjs.selectionRange(controller.editor.state.doc, selection);
2123
+ dispatchSelection(controller, chunkZ5EEDCRI_cjs.textSelection(direction < 0 ? from : to));
2062
2124
  return true;
2063
2125
  }
2064
2126
  function crossHeadVertically(controller, selection, direction) {
2065
2127
  const { head } = selection;
2066
2128
  const edge = neighbourHead(controller, head.block, direction);
2067
2129
  if (edge !== null) {
2068
- const end2 = chunkFK7EBZPX_cjs.regionLength(blockOf(controller, edge), edge.region);
2130
+ const end2 = chunkZ5EEDCRI_cjs.regionLength(blockOf(controller, edge), edge.region);
2069
2131
  return moveHead(controller, selection, { ...edge, offset: Math.min(head.offset, end2) });
2070
2132
  }
2071
- const end = chunkFK7EBZPX_cjs.regionLength(blockOf(controller, head), head.region);
2133
+ const end = chunkZ5EEDCRI_cjs.regionLength(blockOf(controller, head), head.region);
2072
2134
  return moveHead(controller, selection, { ...head, offset: direction < 0 ? 0 : end });
2073
2135
  }
2074
2136
  function crossHeadHorizontally(controller, selection, direction) {
2075
2137
  const { head } = selection;
2076
- const text = chunkI7X7B3WD_cjs.inlineText(blockOf(controller, head).regions[head.region] ?? []);
2138
+ const text = chunk4JDRDPLC_cjs.inlineText(blockOf(controller, head).regions[head.region] ?? []);
2077
2139
  if (direction < 0 ? head.offset > 0 : head.offset < text.length) {
2078
- const offset = direction < 0 ? chunkFK7EBZPX_cjs.prevGraphemeOffset(text, head.offset) : chunkFK7EBZPX_cjs.nextGraphemeOffset(text, head.offset);
2140
+ const offset = direction < 0 ? chunkZ5EEDCRI_cjs.prevGraphemeOffset(text, head.offset) : chunkZ5EEDCRI_cjs.nextGraphemeOffset(text, head.offset);
2079
2141
  return moveHead(controller, selection, { ...head, offset });
2080
2142
  }
2081
2143
  const edge = neighbourHead(controller, head.block, direction);
@@ -2094,9 +2156,9 @@ function moveHorizontally(controller, direction, extend) {
2094
2156
  const move = extend ? crossHeadHorizontally : collapseCross;
2095
2157
  return move(controller, selection, direction);
2096
2158
  }
2097
- if (!extend && !chunkFK7EBZPX_cjs.isCollapsed(selection)) return false;
2159
+ if (!extend && !chunkZ5EEDCRI_cjs.isCollapsed(selection)) return false;
2098
2160
  const { head } = selection;
2099
- const length = chunkFK7EBZPX_cjs.regionLength(doc.blocks[chunkI7X7B3WD_cjs.requireBlockIndex(doc, head.block)], head.region);
2161
+ const length = chunkZ5EEDCRI_cjs.regionLength(doc.blocks[chunk4JDRDPLC_cjs.requireBlockIndex(doc, head.block)], head.region);
2100
2162
  if (direction < 0 ? head.offset > 0 : head.offset < length) return false;
2101
2163
  const own2 = extend ? null : ownNode(controller, head.block, direction);
2102
2164
  if (own2 !== null) {
@@ -2108,6 +2170,26 @@ function moveHorizontally(controller, direction, extend) {
2108
2170
  return edge !== null && moveHead(controller, selection, edge);
2109
2171
  }
2110
2172
 
2173
+ // src/view/navigation/line-end.ts
2174
+ var leftLines = /* @__PURE__ */ new WeakMap();
2175
+ var toLineEnd = ({ isMac }, { altKey, ctrlKey, metaKey }, key) => !altKey && (isMac ? key === "ArrowRight" && metaKey && !ctrlKey : key === "End" && !ctrlKey && !metaKey);
2176
+ function noteLineEnd(controller, event, key) {
2177
+ leftLines.delete(controller);
2178
+ const { selection } = controller.editor.state;
2179
+ if (selection?.kind !== "text" || event.defaultPrevented || !toLineEnd(controller, event, key)) return;
2180
+ const { head, assoc } = selection;
2181
+ const glyphAt2 = glyphsAround(controller.registry, head);
2182
+ const glyph = assoc !== -1 && glyphAt2(head.offset) || glyphAt2(head.offset - 1);
2183
+ if (glyph) leftLines.set(controller, glyph.rect.top + glyph.rect.height / 2);
2184
+ }
2185
+ function sideOfLineEnd(controller, selection) {
2186
+ const y = leftLines.get(controller);
2187
+ leftLines.delete(controller);
2188
+ if (y === void 0 || selection?.kind !== "text" || !chunkZ5EEDCRI_cjs.isCollapsed(selection)) return selection;
2189
+ const { head } = selection;
2190
+ return wrapsAt(head, y, glyphsAround(controller.registry, head)) ? { ...selection, assoc: -1 } : selection;
2191
+ }
2192
+
2111
2193
  // src/view/navigation/line-edges.ts
2112
2194
  var TEXT_NODE3 = 3;
2113
2195
  var ELEMENT_NODE2 = 1;
@@ -2117,7 +2199,10 @@ function textCaretRect(text, offset) {
2117
2199
  const range = text.ownerDocument.createRange();
2118
2200
  range.setStart(text, offset);
2119
2201
  const rect = range.getClientRects()[0];
2120
- return hasSize(rect) ? rect : null;
2202
+ if (hasSize(rect) || offset === 0) return hasSize(rect) ? rect : null;
2203
+ range.setStart(text, offset - (/[\uDC00-\uDFFF]/.test(text.data[offset - 1]) ? 2 : 1));
2204
+ const before = [...range.getClientRects()].pop();
2205
+ return hasSize(before) ? edgeOf(before, inlineDirection(text.parentElement) === "ltr") : null;
2121
2206
  }
2122
2207
  function besideNode(node, before) {
2123
2208
  if (node.nodeType === TEXT_NODE3) return textCaretRect(node, before ? 0 : node.length);
@@ -2189,7 +2274,7 @@ function caretAtGoal(controller, host, at, y) {
2189
2274
  var keepOnLine = ({ registry }, pos, y) => stayOnLine(pos, y, glyphsAround(registry, pos));
2190
2275
  function landAtGoal(controller, block, direction) {
2191
2276
  const { schema } = controller.editor.state;
2192
- const region = chunkFK7EBZPX_cjs.isTextFlow(schema, block) ? chunkFK7EBZPX_cjs.primaryRegion(schema, block) : null;
2277
+ const region = chunkZ5EEDCRI_cjs.isTextFlow(schema, block) ? chunkZ5EEDCRI_cjs.primaryRegion(schema, block) : null;
2193
2278
  const host = region === null ? void 0 : controller.registry.get(block.id, region);
2194
2279
  if (!host || region === null || controller.goalX === null) return null;
2195
2280
  const line = lineInView(host, direction < 0);
@@ -2240,7 +2325,7 @@ function moveText(controller, selection, direction, extend) {
2240
2325
  function extendBlocks(controller, { anchor, head }, direction) {
2241
2326
  const next = neighbourBlock(controller.editor.state.doc, head, direction);
2242
2327
  if (next === null) return false;
2243
- dispatchSelection(controller, chunkFK7EBZPX_cjs.blockRangeSelection(anchor, next.id));
2328
+ dispatchSelection(controller, chunkZ5EEDCRI_cjs.blockRangeSelection(anchor, next.id));
2244
2329
  return true;
2245
2330
  }
2246
2331
  function moveVertically(controller, direction, extend) {
@@ -2256,8 +2341,8 @@ function moveVertically(controller, direction, extend) {
2256
2341
  // src/view/input/flip-block.ts
2257
2342
  var isTask = ({ type, attrs }) => type === "MARKDOWN" && attrs.kind === "task";
2258
2343
  function flipCommand(block) {
2259
- if (isTask(block)) return chunkFK7EBZPX_cjs.toggleTask;
2260
- return block.type === "TOGGLE" ? chunkFK7EBZPX_cjs.setAttrs({ open: block.attrs.open !== true }) : null;
2344
+ if (isTask(block)) return chunkZ5EEDCRI_cjs.toggleTask;
2345
+ return block.type === "TOGGLE" ? chunkZ5EEDCRI_cjs.setAttrs({ open: block.attrs.open !== true }) : null;
2261
2346
  }
2262
2347
  var toggleState = (open) => open ? "expanded" : "collapsed";
2263
2348
  function stateName(block) {
@@ -2266,7 +2351,7 @@ function stateName(block) {
2266
2351
  }
2267
2352
  function blockHoldingCaret({ doc, selection }) {
2268
2353
  if (selection?.kind !== "text" || selection.anchor.block !== selection.head.block) return null;
2269
- return chunkI7X7B3WD_cjs.blockById(doc, selection.head.block) ?? null;
2354
+ return chunk4JDRDPLC_cjs.blockById(doc, selection.head.block) ?? null;
2270
2355
  }
2271
2356
  function flipForReader(controller, block) {
2272
2357
  if (block?.type !== "TOGGLE") return false;
@@ -2281,7 +2366,7 @@ function flipSelectedBlock(controller) {
2281
2366
  if (controller.readOnly) return flipForReader(controller, block);
2282
2367
  const command = block && flipCommand(block);
2283
2368
  if (!block || !command || !controller.run(command)) return false;
2284
- const after = chunkI7X7B3WD_cjs.blockById(editor.state.doc, block.id);
2369
+ const after = chunk4JDRDPLC_cjs.blockById(editor.state.doc, block.id);
2285
2370
  if (after) controller.announce(stateName(after));
2286
2371
  return true;
2287
2372
  }
@@ -2352,6 +2437,7 @@ function handleKeydown(controller, event) {
2352
2437
  controller.nativeVerticalMove = false;
2353
2438
  for (const intercept of controller.keyInterceptors) if (intercept(event)) return;
2354
2439
  if (handle(controller, event)) event.preventDefault();
2440
+ noteLineEnd(controller, event, written(controller, event.key));
2355
2441
  }
2356
2442
 
2357
2443
  // src/view/input/attach-input.ts
@@ -2361,7 +2447,7 @@ function attachInput(controller, root) {
2361
2447
  const { editor } = controller;
2362
2448
  let { selection } = editor.state;
2363
2449
  const stop = editor.subscribe((_, tr) => {
2364
- if (tr && selection) selection = chunkFK7EBZPX_cjs.mapSelection(selection, (pos, assoc) => tr.mapPos(pos, assoc));
2450
+ if (tr && selection) selection = chunkZ5EEDCRI_cjs.mapSelection(selection, (pos, assoc) => tr.mapPos(pos, assoc));
2365
2451
  });
2366
2452
  fallback.flush();
2367
2453
  stop();
@@ -2453,6 +2539,22 @@ function watchFocusReturn(root, handlers) {
2453
2539
  };
2454
2540
  }
2455
2541
 
2542
+ // src/view/controller/redraw-on-relayout.ts
2543
+ function redrawOnRelayout(controller, root) {
2544
+ const view = root.ownerDocument.defaultView;
2545
+ if (!view?.ResizeObserver) return () => {
2546
+ };
2547
+ const observer = new view.ResizeObserver(() => {
2548
+ const { selection } = controller.editor.state;
2549
+ const domSelection = controller.domSelection();
2550
+ if (selection?.kind !== "text" || selection.assoc !== -1 || !domSelection) return;
2551
+ forgetDrawnSide(domSelection);
2552
+ controller.syncSelectionToDom();
2553
+ });
2554
+ observer.observe(root);
2555
+ return () => observer.disconnect();
2556
+ }
2557
+
2456
2558
  // src/view/controller/selection-sync.ts
2457
2559
  var selectionPoints = (selection) => [
2458
2560
  selection?.anchorNode ?? null,
@@ -2493,6 +2595,7 @@ function bindRoot(controller, root, cross, committed) {
2493
2595
  const input = attachInput(controller, root);
2494
2596
  const unsubscribe = controller.editor.subscribe(committed);
2495
2597
  const detachCross = cross.attach(root);
2598
+ const stopRedrawing = redrawOnRelayout(controller, root);
2496
2599
  const stopFocusReturn = watchFocusReturn(root, {
2497
2600
  pressed: () => controller.nativeVerticalMove = false,
2498
2601
  returned: (target) => {
@@ -2509,6 +2612,7 @@ function bindRoot(controller, root, cross, committed) {
2509
2612
  input.detach();
2510
2613
  unsubscribe();
2511
2614
  detachCross();
2615
+ stopRedrawing();
2512
2616
  stopFocusReturn();
2513
2617
  }
2514
2618
  };
@@ -2517,9 +2621,11 @@ function bindRoot(controller, root, cross, committed) {
2517
2621
  // src/view/controller/selection-io.ts
2518
2622
  function movedSelection(controller, doc, model) {
2519
2623
  if (controller.composingKey !== null || controller.dragging || !doc || !ownsFocus(controller, doc)) return null;
2520
- const selection = readSelection(controller.registry, doc.getSelection(), (node) => controller.blockAt(node));
2521
- const sided = selection?.kind === "text" && model?.kind === "text" ? { ...selection, assoc: model.assoc } : selection;
2522
- return sided === null || chunkFK7EBZPX_cjs.sameSelection(sided, model) ? null : selection;
2624
+ const read = readSelection(controller.registry, doc.getSelection(), (node) => controller.blockAt(node));
2625
+ const selection = sideOfLineEnd(controller, read);
2626
+ const keepsSide = selection?.kind === "text" && model?.kind === "text" && selection.assoc === void 0;
2627
+ const sided = keepsSide ? { ...selection, assoc: model.assoc } : selection;
2628
+ return sided === null || chunkZ5EEDCRI_cjs.sameSelection(sided, model) ? null : selection;
2523
2629
  }
2524
2630
  function writeModelSelection(controller, doc, moved, local) {
2525
2631
  const domSelection = doc?.getSelection();
@@ -2561,6 +2667,7 @@ var ViewController = class {
2561
2667
  #hosts;
2562
2668
  #drawn = createDrawnElements(this.registry, () => this.editor.state);
2563
2669
  #cross = createCrossMode(this);
2670
+ #focus = createFocusFollow(this, () => this.#drawn.focusElement());
2564
2671
  #outside = createOutsideChanges(
2565
2672
  () => hasFocus(this, this.#ownerDocument()),
2566
2673
  (model) => movedSelection(this, this.#ownerDocument(), model)
@@ -2579,7 +2686,7 @@ var ViewController = class {
2579
2686
  this.engagement = createEngagement(options.editor);
2580
2687
  this.#flush = options.flush ?? runNow;
2581
2688
  this.onFiles = options.onFiles;
2582
- this.isMac = options.isMac ?? chunkFK7EBZPX_cjs.detectMac();
2689
+ this.isMac = options.isMac ?? chunkZ5EEDCRI_cjs.detectMac();
2583
2690
  const decorationsOf = (block, region) => this.decorationsFor(block, region);
2584
2691
  const drain = (element) => this.#binding?.input.drain(element);
2585
2692
  this.#hosts = createHostRenderer(options.editor, options.render, decorationsOf, drain);
@@ -2665,7 +2772,7 @@ var ViewController = class {
2665
2772
  if (this.editor.state.doc !== before.doc) this.goalX = null;
2666
2773
  this.refreshHosts();
2667
2774
  this.#cross.sync();
2668
- if (focused && doc !== null && ownsFocus(this, doc)) this.#keepFocus();
2775
+ if (focused && doc !== null && ownsFocus(this, doc)) this.#focus.keep();
2669
2776
  this.syncSelectionToDom(true);
2670
2777
  return handled;
2671
2778
  }
@@ -2681,7 +2788,7 @@ var ViewController = class {
2681
2788
  if (moved) this.#selectFromDom(moved);
2682
2789
  this.#cross.sync();
2683
2790
  const follow = () => {
2684
- this.#keepFocus(quiet);
2791
+ this.#focus.keep(quiet);
2685
2792
  this.syncSelectionToDom();
2686
2793
  };
2687
2794
  if (!quiet) return follow();
@@ -2699,15 +2806,10 @@ var ViewController = class {
2699
2806
  announce(message) {
2700
2807
  this.announcer.announce(message);
2701
2808
  }
2702
- // A redraw of the decorations alone, such as one that follows a selection the browser made, replaces the nodes that
2703
- // selection sits in, and nothing else writes it back. It is written only while the editor holds focus: written while
2704
- // focus is on the page, it would pull focus into the line.
2705
2809
  renderHost(block, region) {
2706
2810
  const element = this.registry.get(block, region);
2707
2811
  const host = element && { block, region, element };
2708
- if (!host || this.#isComposing(host) || !this.#hosts.render(host)) return;
2709
- const inSelection = element.contains(this.domSelection()?.focusNode ?? null);
2710
- if (inSelection && hasFocus(this, element.ownerDocument)) this.syncSelectionToDom();
2812
+ if (host && !this.#isComposing(host) && this.#hosts.render(host)) this.#focus.rewrite(element);
2711
2813
  }
2712
2814
  domSelection() {
2713
2815
  return this.#ownerDocument()?.getSelection() ?? null;
@@ -2726,14 +2828,14 @@ var ViewController = class {
2726
2828
  this.#flush(() => this.#selectFromDom(selection));
2727
2829
  this.#cross.sync();
2728
2830
  if (!wasCross && !this.#cross.active) return;
2729
- this.#keepFocus();
2831
+ this.#focus.keep();
2730
2832
  this.syncSelectionToDom();
2731
2833
  }
2732
2834
  focus(target) {
2733
2835
  const { editor } = this;
2734
2836
  const selection = focusTarget(editor.state, target);
2735
- if (selection !== null && !chunkFK7EBZPX_cjs.sameSelection(selection, editor.state.selection)) dispatchSelection(this, selection);
2736
- this.#takeFocus();
2837
+ if (selection !== null && !chunkZ5EEDCRI_cjs.sameSelection(selection, editor.state.selection)) dispatchSelection(this, selection);
2838
+ this.#focus.take();
2737
2839
  this.syncSelectionToDom();
2738
2840
  }
2739
2841
  setReadOnly(readOnly) {
@@ -2755,17 +2857,6 @@ var ViewController = class {
2755
2857
  #ownerDocument() {
2756
2858
  return (this.#binding?.root ?? this.registry.all().next().value?.element)?.ownerDocument ?? null;
2757
2859
  }
2758
- // React replaces a host whose block changes kind, which drops focus, and Firefox does not move focus into another
2759
- // host when a script selects inside it.
2760
- #keepFocus(preventScroll) {
2761
- if (this.composingKey === null) this.#takeFocus(preventScroll);
2762
- }
2763
- #takeFocus(preventScroll) {
2764
- const element = this.#drawn.focusElement();
2765
- if (!element || element.ownerDocument.activeElement === element) return;
2766
- if (element === this.sink) focusSink(this);
2767
- else element.focus({ preventScroll });
2768
- }
2769
2860
  };
2770
2861
  var QuoinEditorContext = react.createContext(null);
2771
2862
  function useViewController() {
@@ -2780,7 +2871,7 @@ function useQuoinEditor(options) {
2780
2871
  const { blocks, readOnly = false } = options;
2781
2872
  const callbacks = react.useRef(options);
2782
2873
  const [controller] = react.useState(() => {
2783
- const editor = chunkFK7EBZPX_cjs.createEditor({
2874
+ const editor = chunkZ5EEDCRI_cjs.createEditor({
2784
2875
  blocks,
2785
2876
  extensions: options.extensions,
2786
2877
  onChange: (next) => callbacks.current.onChange(next),
@@ -2806,11 +2897,35 @@ function useQuoinEditor(options) {
2806
2897
  react.useEffect(() => () => controller.destroy(), [controller]);
2807
2898
  return controller;
2808
2899
  }
2809
- var headingPlaceholder = (_state, { type, attrs }) => type === "MARKDOWN" && attrs.kind === "heading" ? `Heading ${chunkI7X7B3WD_cjs.headingLevel(attrs.level)}` : void 0;
2900
+
2901
+ // src/view/react/renderer-labels.ts
2902
+ var TOGGLE = "Toggle";
2903
+ var englishRendererLabels = {
2904
+ paragraph: "Paragraph",
2905
+ heading: (level) => `Heading ${level}`,
2906
+ bulletItem: "Bullet list item",
2907
+ numberedItem: (n) => `Numbered list item ${n}`,
2908
+ task: "Task",
2909
+ quote: "Quote",
2910
+ callout: (tone) => `Callout, ${tone}`,
2911
+ calloutTones: { info: "info", tip: "tip", success: "success", warning: "warning", danger: "danger" },
2912
+ toggle: TOGGLE,
2913
+ toggleButton: (hidden) => hidden === 0 ? TOGGLE : `${TOGGLE}, ${hidden} ${hidden === 1 ? "block" : "blocks"} hidden`
2914
+ };
2915
+ function rendererLabelsWith(overrides) {
2916
+ if (overrides === void 0) return englishRendererLabels;
2917
+ const given = Object.entries(overrides).filter(([, value]) => value !== void 0);
2918
+ const calloutTones = { ...englishRendererLabels.calloutTones, ...overrides.calloutTones };
2919
+ return { ...englishRendererLabels, ...Object.fromEntries(given), calloutTones };
2920
+ }
2921
+
2922
+ // src/view/react/block-placeholder.ts
2923
+ var headingPlaceholderOf = (heading) => (_state, { type, attrs }) => type === "MARKDOWN" && attrs.kind === "heading" ? heading(chunk4JDRDPLC_cjs.headingLevel(attrs.level)) : void 0;
2924
+ var headingPlaceholder = headingPlaceholderOf(englishRendererLabels.heading);
2810
2925
  var BlockPlaceholderContext = react.createContext(headingPlaceholder);
2811
2926
  function regionPlaceholder(state, blockId, region, placeholderOf) {
2812
- const block = chunkI7X7B3WD_cjs.blockById(state.doc, blockId);
2813
- return block !== void 0 && chunkFK7EBZPX_cjs.primaryRegion(state.schema, block) === region ? placeholderOf(state, block) : void 0;
2927
+ const block = chunk4JDRDPLC_cjs.blockById(state.doc, blockId);
2928
+ return block !== void 0 && chunkZ5EEDCRI_cjs.primaryRegion(state.schema, block) === region ? placeholderOf(state, block) : void 0;
2814
2929
  }
2815
2930
  function useReadOnly(controller) {
2816
2931
  const subscribe = react.useCallback((notify) => controller.subscribeReadOnly(notify), [controller]);
@@ -2826,7 +2941,7 @@ function EditableRegion({ block, region, label, id, placeholder, className }) {
2826
2941
  const select = react.useCallback(
2827
2942
  (state) => {
2828
2943
  const inline2 = regionInline(state, block, region);
2829
- const empty = inline2 === void 0 || chunkI7X7B3WD_cjs.inlineLength(inline2) === 0;
2944
+ const empty = inline2 === void 0 || chunk4JDRDPLC_cjs.inlineLength(inline2) === 0;
2830
2945
  return {
2831
2946
  inline: inline2,
2832
2947
  decorations: controller.decorationsFor(block, region),
@@ -2950,6 +3065,8 @@ function LiveRegion({ blocksSelected }) {
2950
3065
  const { key, message } = react.useSyncExternalStore(subscribe, read, read);
2951
3066
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "quoin-visually-hidden", role: "status", "aria-live": "polite", "aria-atomic": "true", children: message !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { children: message }, key) });
2952
3067
  }
3068
+ var RendererLabelsContext = react.createContext(englishRendererLabels);
3069
+ var useRendererLabels = () => react.useContext(RendererLabelsContext);
2953
3070
  function SelectionSink({ label = "Selected content", blockLabel }) {
2954
3071
  const controller = useViewController();
2955
3072
  const ref = react.useRef(null);
@@ -3026,7 +3143,7 @@ function covers(state, id, index) {
3026
3143
  if (selection === null) return false;
3027
3144
  if (selection.kind === "node") return selection.block === id;
3028
3145
  if (selection.kind === "blocks") return within(state, index, [selection.anchor, selection.head]);
3029
- if (!isCrossSelection(selection) || chunkFK7EBZPX_cjs.isTextFlow(schema, doc.blocks[index])) return false;
3146
+ if (!isCrossSelection(selection) || chunkZ5EEDCRI_cjs.isTextFlow(schema, doc.blocks[index])) return false;
3030
3147
  return within(state, index, [selection.anchor.block, selection.head.block]);
3031
3148
  }
3032
3149
  function blockStatus(state, id, choices = NO_CHOICES) {
@@ -3035,21 +3152,16 @@ function blockStatus(state, id, choices = NO_CHOICES) {
3035
3152
  if (isHiddenAt(state.doc, index, choices)) return "hidden";
3036
3153
  return covers(state, id, index) ? "selected" : "plain";
3037
3154
  }
3038
-
3039
- // src/view/react/callout-tones.ts
3040
- var CALLOUT_TONES = ["info", "tip", "success", "warning", "danger"];
3041
- function calloutTone(value) {
3042
- return CALLOUT_TONES.find((tone) => tone === value) ?? "info";
3043
- }
3044
3155
  var CalloutBlock = ({ block }) => {
3045
- const tone = calloutTone(block.attrs.tone);
3046
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "quoin-callout", "data-tone": tone, children: /* @__PURE__ */ jsxRuntime.jsx(EditableRegion, { block: block.id, region: "body", label: `Callout, ${tone}` }) });
3156
+ const labels = useRendererLabels();
3157
+ const tone = chunkQFGWSFOI_cjs.calloutTone(block.attrs.tone);
3158
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "quoin-callout", "data-tone": tone, children: /* @__PURE__ */ jsxRuntime.jsx(EditableRegion, { block: block.id, region: "body", label: labels.callout(labels.calloutTones[tone]) }) });
3047
3159
  };
3048
3160
 
3049
3161
  // src/view/react/block-command.ts
3050
3162
  function onBlock(id, command) {
3051
3163
  return (state, dispatch) => {
3052
- const { ok, tr } = chunkFK7EBZPX_cjs.runCommands(state, [chunkFK7EBZPX_cjs.setSelection(chunkFK7EBZPX_cjs.blockRangeSelection(id)), command]);
3164
+ const { ok, tr } = chunkZ5EEDCRI_cjs.runCommands(state, [chunkZ5EEDCRI_cjs.setSelection(chunkZ5EEDCRI_cjs.blockRangeSelection(id)), command]);
3053
3165
  if (!ok || tr === null) return false;
3054
3166
  dispatch?.(tr.setSelection(state.selection));
3055
3167
  return true;
@@ -3069,7 +3181,7 @@ function TaskCheckbox({ block, controller, label, labelledBy }) {
3069
3181
  role: "checkbox",
3070
3182
  "aria-checked": checked,
3071
3183
  "aria-readonly": readOnly ? "true" : void 0,
3072
- "aria-label": chunkI7X7B3WD_cjs.firstNamed(label, "Task"),
3184
+ "aria-label": chunk4JDRDPLC_cjs.firstNamed(label, "Task"),
3073
3185
  "aria-labelledby": labelledBy,
3074
3186
  className: "quoin-task-box",
3075
3187
  contentEditable: false,
@@ -3100,7 +3212,7 @@ function numberDoc(doc) {
3100
3212
  numbers[index] = run2.next++;
3101
3213
  return;
3102
3214
  }
3103
- const start = chunkI7X7B3WD_cjs.orderedStart(block.attrs.start);
3215
+ const start = chunk4JDRDPLC_cjs.orderedStart(block.attrs.start);
3104
3216
  numbers[index] = start;
3105
3217
  runs.push({ indent: block.indent, next: start + 1 });
3106
3218
  });
@@ -3124,41 +3236,56 @@ function useOrderedNumber(controller, blockId) {
3124
3236
  });
3125
3237
  }
3126
3238
  var REGION = "text";
3127
- function TextRegion({ block, label }) {
3128
- return /* @__PURE__ */ jsxRuntime.jsx(EditableRegion, { block: block.id, region: REGION, label });
3239
+ function PlainMarker(props) {
3240
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "quoin-marker", "aria-hidden": "true", children: props.list === "bullet" ? "\u2022" : `${props.number}.` });
3241
+ }
3242
+ var VIEW_LOOK = { Marker: PlainMarker, headingClassName: () => "quoin-heading" };
3243
+ function TextHost({ block, label, id }) {
3244
+ return /* @__PURE__ */ jsxRuntime.jsx(EditableRegion, { id, block: block.id, region: REGION, label });
3129
3245
  }
3130
- function NumberedItem({ block, controller }) {
3246
+ function Heading({ block, look }) {
3247
+ const labels = useRendererLabels();
3248
+ const level = chunk4JDRDPLC_cjs.headingLevel(block.attrs.level);
3249
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "heading", "aria-level": level, className: look.headingClassName(level), children: /* @__PURE__ */ jsxRuntime.jsx(TextHost, { block, label: labels.heading(level) }) });
3250
+ }
3251
+ function NumberedItem({ block, controller, look }) {
3252
+ const labels = useRendererLabels();
3131
3253
  const number = useOrderedNumber(controller, block.id);
3132
3254
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "quoin-list-item", "data-list": "ordered", children: [
3133
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "quoin-marker", "aria-hidden": "true", children: `${number}.` }),
3134
- /* @__PURE__ */ jsxRuntime.jsx(TextRegion, { block, label: `Numbered list item ${number}` })
3255
+ /* @__PURE__ */ jsxRuntime.jsx(look.Marker, { list: "ordered", number, depth: block.indent }),
3256
+ /* @__PURE__ */ jsxRuntime.jsx(TextHost, { block, label: labels.numberedItem(number) })
3257
+ ] });
3258
+ }
3259
+ function TaskItem({ block, controller }) {
3260
+ const { task } = useRendererLabels();
3261
+ const hostId = useRegionDomId(block.id, REGION);
3262
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "quoin-task", "data-checked": block.attrs.checked === true, children: [
3263
+ /* @__PURE__ */ jsxRuntime.jsx(TaskCheckbox, { block, controller, label: task, labelledBy: hostId }),
3264
+ /* @__PURE__ */ jsxRuntime.jsx(TextHost, { id: hostId, block, label: task })
3135
3265
  ] });
3136
3266
  }
3137
- var MarkdownBlock = (props) => {
3267
+ function MarkdownText({ look = VIEW_LOOK, ...props }) {
3138
3268
  const { block } = props;
3269
+ const labels = useRendererLabels();
3139
3270
  switch (block.attrs.kind) {
3140
- case "heading": {
3141
- const level = chunkI7X7B3WD_cjs.headingLevel(block.attrs.level);
3142
- return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "heading", "aria-level": level, className: "quoin-heading", children: /* @__PURE__ */ jsxRuntime.jsx(TextRegion, { block, label: `Heading ${level}` }) });
3143
- }
3271
+ case "heading":
3272
+ return /* @__PURE__ */ jsxRuntime.jsx(Heading, { ...props, look });
3144
3273
  case "bullet":
3145
3274
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "quoin-list-item", "data-list": "bullet", children: [
3146
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "quoin-marker", "aria-hidden": "true", children: "\u2022" }),
3147
- /* @__PURE__ */ jsxRuntime.jsx(TextRegion, { block, label: "Bullet list item" })
3275
+ /* @__PURE__ */ jsxRuntime.jsx(look.Marker, { list: "bullet", depth: block.indent }),
3276
+ /* @__PURE__ */ jsxRuntime.jsx(TextHost, { block, label: labels.bulletItem })
3148
3277
  ] });
3149
3278
  case "ordered":
3150
- return /* @__PURE__ */ jsxRuntime.jsx(NumberedItem, { ...props });
3279
+ return /* @__PURE__ */ jsxRuntime.jsx(NumberedItem, { ...props, look });
3151
3280
  case "task":
3152
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "quoin-task", "data-checked": block.attrs.checked === true, children: [
3153
- /* @__PURE__ */ jsxRuntime.jsx(TaskCheckbox, { block, controller: props.controller }),
3154
- /* @__PURE__ */ jsxRuntime.jsx(TextRegion, { block, label: "Task" })
3155
- ] });
3281
+ return /* @__PURE__ */ jsxRuntime.jsx(TaskItem, { ...props });
3156
3282
  case "quote":
3157
- return /* @__PURE__ */ jsxRuntime.jsx("blockquote", { className: "quoin-quote", children: /* @__PURE__ */ jsxRuntime.jsx(TextRegion, { block, label: "Quote" }) });
3283
+ return /* @__PURE__ */ jsxRuntime.jsx("blockquote", { className: "quoin-quote", children: /* @__PURE__ */ jsxRuntime.jsx(TextHost, { block, label: labels.quote }) });
3158
3284
  default:
3159
- return /* @__PURE__ */ jsxRuntime.jsx(TextRegion, { block, label: "Paragraph" });
3285
+ return /* @__PURE__ */ jsxRuntime.jsx(TextHost, { block, label: labels.paragraph });
3160
3286
  }
3161
- };
3287
+ }
3288
+ var MarkdownBlock = MarkdownText;
3162
3289
  function useReaderChoices(controller) {
3163
3290
  const store = readerToggles(controller);
3164
3291
  return react.useSyncExternalStore(store.subscribe, () => store.choices, () => store.choices);
@@ -3189,11 +3316,33 @@ function ToggleChevron({ block, controller, label = "Toggle", controls }) {
3189
3316
  }
3190
3317
  );
3191
3318
  }
3319
+
3320
+ // src/view/react/use-nested-blocks.ts
3321
+ function nestedBlockIds({ doc }, blockId) {
3322
+ const index = doc.index.get(blockId);
3323
+ if (index === void 0) return [];
3324
+ return doc.blocks.slice(index + 1, chunkZ5EEDCRI_cjs.descendantsEnd(doc, index)).map((block) => block.id);
3325
+ }
3326
+ function useNestedBlocks(controller, blockId) {
3327
+ return useEditorState(controller, (state) => nestedBlockIds(state, blockId), chunk4JDRDPLC_cjs.sameItems);
3328
+ }
3192
3329
  var ToggleBlock = ({ block, controller }) => {
3330
+ const labels = useRendererLabels();
3331
+ const domId = useBlockDomId();
3332
+ const nested = useNestedBlocks(controller, block.id);
3193
3333
  const open = useToggleOpen(controller, block);
3334
+ const hidden = open ? 0 : nested.length;
3194
3335
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "quoin-toggle", "data-open": open, children: [
3195
- /* @__PURE__ */ jsxRuntime.jsx(ToggleChevron, { block, controller }),
3196
- /* @__PURE__ */ jsxRuntime.jsx(EditableRegion, { block: block.id, region: "text", label: "Toggle" })
3336
+ /* @__PURE__ */ jsxRuntime.jsx(
3337
+ ToggleChevron,
3338
+ {
3339
+ block,
3340
+ controller,
3341
+ label: hidden === 0 ? labels.toggle : labels.toggleButton(hidden),
3342
+ controls: nested.length === 0 ? void 0 : nested.map(domId).join(" ")
3343
+ }
3344
+ ),
3345
+ /* @__PURE__ */ jsxRuntime.jsx(EditableRegion, { block: block.id, region: "text", label: labels.toggle })
3197
3346
  ] });
3198
3347
  };
3199
3348
  var defaultRenderers = {
@@ -3229,7 +3378,7 @@ var BlockShell = react.memo(function BlockShell2({ block, renderers }) {
3229
3378
  const choices = useReaderChoices(controller);
3230
3379
  const status = useEditorState(controller, (state) => blockStatus(state, block.id, choices));
3231
3380
  const engaged = useEngaged(controller, status === "selected");
3232
- const decorations = useEditorState(controller, () => hostDecorations(controller.editor, block.id, ""), sameDecorations);
3381
+ const decorations = useEditorState(controller, () => controller.decorationsFor(block.id, ""), sameDecorations);
3233
3382
  const hidden = status === "hidden";
3234
3383
  useIsomorphicLayoutEffect(() => {
3235
3384
  const element = ref.current;
@@ -3247,11 +3396,11 @@ var BlockShell = react.memo(function BlockShell2({ block, renderers }) {
3247
3396
  "data-quoin-block": "",
3248
3397
  "data-block-id": block.id,
3249
3398
  "data-type": block.type,
3250
- "data-kind": chunkI7X7B3WD_cjs.optionalString(kind),
3399
+ "data-kind": chunk4JDRDPLC_cjs.optionalString(kind),
3251
3400
  "data-indent": block.indent,
3252
- "data-color": chunkI7X7B3WD_cjs.paletteOrUndefined(color),
3253
- "data-bg": chunkI7X7B3WD_cjs.paletteOrUndefined(background),
3254
- "data-align": chunkI7X7B3WD_cjs.alignOrUndefined(align),
3401
+ "data-color": chunk4JDRDPLC_cjs.paletteOrUndefined(color),
3402
+ "data-bg": chunk4JDRDPLC_cjs.paletteOrUndefined(background),
3403
+ "data-align": chunk4JDRDPLC_cjs.alignOrUndefined(align),
3255
3404
  style: { "--quoin-indent": block.indent },
3256
3405
  tabIndex: -1,
3257
3406
  "data-selected": status === "selected" && engaged ? "true" : void 0,
@@ -3279,6 +3428,7 @@ function EditorView({
3279
3428
  id,
3280
3429
  "aria-label": label = "Editor",
3281
3430
  hint = HINT,
3431
+ rendererLabels,
3282
3432
  paragraphLabel,
3283
3433
  selectedContentLabel,
3284
3434
  blockLabel,
@@ -3286,7 +3436,7 @@ function EditorView({
3286
3436
  blockErrorLabel = BLOCK_ERROR,
3287
3437
  onBlockError,
3288
3438
  placeholder,
3289
- blockPlaceholder = headingPlaceholder,
3439
+ blockPlaceholder,
3290
3440
  blocksSelectedLabel = BLOCKS_SELECTED,
3291
3441
  children
3292
3442
  }) {
@@ -3295,6 +3445,8 @@ function EditorView({
3295
3445
  const blockIdScope = react.useId();
3296
3446
  const blocks = useEditorState(controller, (state) => state.doc.blocks);
3297
3447
  const blockError = react.useMemo(() => ({ label: blockErrorLabel, report: onBlockError }), [blockErrorLabel, onBlockError]);
3448
+ const labels = react.useMemo(() => rendererLabelsWith(rendererLabels), [rendererLabels]);
3449
+ const headingPlaceholder2 = react.useMemo(() => headingPlaceholderOf(labels.heading), [labels.heading]);
3298
3450
  const shells = useBlockElements(blocks, renderers);
3299
3451
  useIsomorphicLayoutEffect(() => root.current ? controller.attach(root.current) : void 0, [controller]);
3300
3452
  return /* @__PURE__ */ jsxRuntime.jsx(QuoinEditorContext.Provider, { value: controller, children: /* @__PURE__ */ jsxRuntime.jsxs(
@@ -3311,7 +3463,7 @@ function EditorView({
3311
3463
  if (focusOwners.get(event.target) === controller) controller.engagement.engage();
3312
3464
  },
3313
3465
  children: [
3314
- /* @__PURE__ */ jsxRuntime.jsx(BlockDomIdScope.Provider, { value: blockIdScope, children: /* @__PURE__ */ jsxRuntime.jsx(UnsupportedBlockLabel.Provider, { value: unsupportedBlockLabel, children: /* @__PURE__ */ jsxRuntime.jsx(BlockErrorContext.Provider, { value: blockError, children: /* @__PURE__ */ jsxRuntime.jsx(BlockPlaceholderContext.Provider, { value: blockPlaceholder, children: blocks.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(EmptyDocumentHost, { placeholder, label: paragraphLabel }) : shells }) }) }) }),
3466
+ /* @__PURE__ */ jsxRuntime.jsx(BlockDomIdScope.Provider, { value: blockIdScope, children: /* @__PURE__ */ jsxRuntime.jsx(UnsupportedBlockLabel.Provider, { value: unsupportedBlockLabel, children: /* @__PURE__ */ jsxRuntime.jsx(BlockErrorContext.Provider, { value: blockError, children: /* @__PURE__ */ jsxRuntime.jsx(BlockPlaceholderContext.Provider, { value: blockPlaceholder ?? headingPlaceholder2, children: /* @__PURE__ */ jsxRuntime.jsx(RendererLabelsContext.Provider, { value: labels, children: blocks.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(EmptyDocumentHost, { placeholder, label: paragraphLabel ?? labels.paragraph }) : shells }) }) }) }) }),
3315
3467
  children,
3316
3468
  /* @__PURE__ */ jsxRuntime.jsx(SelectionSink, { label: selectedContentLabel, blockLabel }),
3317
3469
  /* @__PURE__ */ jsxRuntime.jsx("div", { id: hintId, className: "quoin-visually-hidden", children: hint }),
@@ -3323,16 +3475,14 @@ function EditorView({
3323
3475
  }
3324
3476
 
3325
3477
  exports.BlockErrorContext = BlockErrorContext;
3326
- exports.CALLOUT_TONES = CALLOUT_TONES;
3327
3478
  exports.EditableRegion = EditableRegion;
3328
3479
  exports.EditorView = EditorView;
3480
+ exports.MarkdownText = MarkdownText;
3329
3481
  exports.NATIVE_INTERACTION = NATIVE_INTERACTION;
3330
3482
  exports.NODE_ENTRY = NODE_ENTRY;
3331
- exports.TaskCheckbox = TaskCheckbox;
3332
- exports.ToggleChevron = ToggleChevron;
3483
+ exports.ToggleBlock = ToggleBlock;
3333
3484
  exports.ViewController = ViewController;
3334
3485
  exports.arrowAsWritten = arrowAsWritten;
3335
- exports.calloutTone = calloutTone;
3336
3486
  exports.caretClientRect = caretClientRect;
3337
3487
  exports.caretFromPoint = caretFromPoint;
3338
3488
  exports.createAutoScroll = createAutoScroll;
@@ -3340,8 +3490,8 @@ exports.dispatchSelection = dispatchSelection;
3340
3490
  exports.domMapOf = domMapOf;
3341
3491
  exports.domToPos = domToPos;
3342
3492
  exports.drawnBlockCount = drawnBlockCount;
3493
+ exports.englishRendererLabels = englishRendererLabels;
3343
3494
  exports.focusOwners = focusOwners;
3344
- exports.handleCopy = handleCopy;
3345
3495
  exports.hostKey = hostKey;
3346
3496
  exports.inlineDirection = inlineDirection;
3347
3497
  exports.isComposingKey = isComposingKey;
@@ -3356,14 +3506,10 @@ exports.posToDom = posToDom;
3356
3506
  exports.regionInline = regionInline;
3357
3507
  exports.renderInline = renderInline;
3358
3508
  exports.textDiff = textDiff;
3359
- exports.useBlockDomId = useBlockDomId;
3360
3509
  exports.useEditorState = useEditorState;
3361
3510
  exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect;
3362
- exports.useOrderedNumber = useOrderedNumber;
3363
3511
  exports.useQuoinEditor = useQuoinEditor;
3364
3512
  exports.useReadOnly = useReadOnly;
3365
- exports.useRegionDomId = useRegionDomId;
3366
- exports.useToggleOpen = useToggleOpen;
3367
3513
  exports.useViewController = useViewController;
3368
3514
  exports.visibleBlockIndexes = visibleBlockIndexes;
3369
3515
  exports.wholeState = wholeState;