quoin-editor 2.0.1 → 2.0.3

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 (84) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/ai.cjs +34 -34
  3. package/dist/ai.js +3 -3
  4. package/dist/catalogue.cjs +21 -21
  5. package/dist/catalogue.js +12 -12
  6. package/dist/{chunk-BYYCD54G.cjs → chunk-3B5VEXVQ.cjs} +2 -2
  7. package/dist/{chunk-5YAJZSTI.cjs → chunk-4EJJ4ZNC.cjs} +18 -18
  8. package/dist/{chunk-IKZSCTRF.cjs → chunk-55MN4QZU.cjs} +8 -5
  9. package/dist/{chunk-NFO3W644.cjs → chunk-5URH2Y2L.cjs} +22 -20
  10. package/dist/{chunk-B4VCDJSA.js → chunk-77THE3KY.js} +5 -5
  11. package/dist/{chunk-B4VCDJSA.js.map → chunk-77THE3KY.js.map} +1 -1
  12. package/dist/{chunk-V4WQG7FR.cjs → chunk-BCCFJINI.cjs} +70 -65
  13. package/dist/{chunk-NL5J77VD.js → chunk-BNTRGV4A.js} +44 -13
  14. package/dist/chunk-BNTRGV4A.js.map +1 -0
  15. package/dist/{chunk-IW4TMECB.js → chunk-C4SRLMQJ.js} +3 -3
  16. package/dist/{chunk-IW4TMECB.js.map → chunk-C4SRLMQJ.js.map} +1 -1
  17. package/dist/{chunk-CJVJNMOB.cjs → chunk-DZ5XR4O6.cjs} +177 -143
  18. package/dist/{chunk-ZN5DHNSL.js → chunk-FGVTDIHT.js} +80 -45
  19. package/dist/chunk-FGVTDIHT.js.map +1 -0
  20. package/dist/{chunk-66OPHDFA.cjs → chunk-H3TRVI44.cjs} +50 -50
  21. package/dist/{chunk-2UKI26JA.js → chunk-LCGOFL7S.js} +15 -10
  22. package/dist/{chunk-2UKI26JA.js.map → chunk-LCGOFL7S.js.map} +1 -1
  23. package/dist/{chunk-EU5IGKMP.js → chunk-MDIXI7DM.js} +3 -3
  24. package/dist/{chunk-EU5IGKMP.js.map → chunk-MDIXI7DM.js.map} +1 -1
  25. package/dist/{chunk-Z6LAARPB.cjs → chunk-MGN332NY.cjs} +45 -10
  26. package/dist/{chunk-4PIJC4FD.cjs → chunk-NAMZA4NW.cjs} +14 -14
  27. package/dist/{chunk-5X52BAZB.js → chunk-NLRSAOCK.js} +5 -5
  28. package/dist/{chunk-5X52BAZB.js.map → chunk-NLRSAOCK.js.map} +1 -1
  29. package/dist/{chunk-HOSDMHK6.cjs → chunk-OMUXPNCX.cjs} +27 -26
  30. package/dist/{chunk-YABGWOAV.js → chunk-QVWNUUMJ.js} +3 -3
  31. package/dist/{chunk-YABGWOAV.js.map → chunk-QVWNUUMJ.js.map} +1 -1
  32. package/dist/{chunk-6BVE46K7.js → chunk-RNYETN6X.js} +7 -5
  33. package/dist/{chunk-6BVE46K7.js.map → chunk-RNYETN6X.js.map} +1 -1
  34. package/dist/{chunk-77CNOLHY.cjs → chunk-SDFJZNYB.cjs} +3 -3
  35. package/dist/{chunk-LEICOZYK.cjs → chunk-SQHEZ3JY.cjs} +2 -2
  36. package/dist/{chunk-D6CIIWCU.cjs → chunk-UWCU6PJY.cjs} +30 -30
  37. package/dist/{chunk-KQPZTSW3.js → chunk-VQDQBMQY.js} +4 -4
  38. package/dist/{chunk-KQPZTSW3.js.map → chunk-VQDQBMQY.js.map} +1 -1
  39. package/dist/{chunk-M77A3EGD.js → chunk-WMM56LIB.js} +8 -5
  40. package/dist/{chunk-M77A3EGD.js.map → chunk-WMM56LIB.js.map} +1 -1
  41. package/dist/{chunk-MAS4AEF4.js → chunk-YHAVXOAA.js} +6 -5
  42. package/dist/chunk-YHAVXOAA.js.map +1 -0
  43. package/dist/{chunk-J2SVYBTC.js → chunk-YWYTLNAO.js} +4 -4
  44. package/dist/{chunk-J2SVYBTC.js.map → chunk-YWYTLNAO.js.map} +1 -1
  45. package/dist/comments.cjs +30 -30
  46. package/dist/comments.js +3 -3
  47. package/dist/diagram.cjs +6 -6
  48. package/dist/diagram.js +3 -3
  49. package/dist/embed.cjs +5 -5
  50. package/dist/embed.js +3 -3
  51. package/dist/emoji-data.cjs +4 -3
  52. package/dist/emoji-data.js +4 -3
  53. package/dist/emoji-data.js.map +1 -1
  54. package/dist/emoji.cjs +6 -6
  55. package/dist/emoji.js +3 -3
  56. package/dist/find.cjs +7 -7
  57. package/dist/find.js +3 -3
  58. package/dist/headless.cjs +11 -11
  59. package/dist/headless.js +1 -1
  60. package/dist/highlight.cjs +3 -3
  61. package/dist/highlight.js +2 -2
  62. package/dist/index.cjs +23 -23
  63. package/dist/index.d.cts +1 -1
  64. package/dist/index.d.ts +1 -1
  65. package/dist/index.js +2 -2
  66. package/dist/math.cjs +6 -6
  67. package/dist/math.js +4 -4
  68. package/dist/mention.cjs +6 -6
  69. package/dist/mention.js +4 -4
  70. package/dist/presence.cjs +12 -12
  71. package/dist/presence.js +3 -3
  72. package/dist/source.cjs +2 -2
  73. package/dist/source.js +2 -2
  74. package/dist/stats.cjs +6 -6
  75. package/dist/stats.js +3 -3
  76. package/dist/styles.css +1 -1
  77. package/dist/table.cjs +22 -22
  78. package/dist/table.js +3 -3
  79. package/dist/toc.cjs +6 -6
  80. package/dist/toc.js +3 -3
  81. package/package.json +3 -2
  82. package/dist/chunk-MAS4AEF4.js.map +0 -1
  83. package/dist/chunk-NL5J77VD.js.map +0 -1
  84. package/dist/chunk-ZN5DHNSL.js.map +0 -1
@@ -1,10 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var chunkZ6LAARPB_cjs = require('./chunk-Z6LAARPB.cjs');
3
+ var chunkMGN332NY_cjs = require('./chunk-MGN332NY.cjs');
4
4
  var chunkZWTIRGY5_cjs = require('./chunk-ZWTIRGY5.cjs');
5
5
  var chunkA6PGQVTR_cjs = require('./chunk-A6PGQVTR.cjs');
6
6
  var chunkFK7EBZPX_cjs = require('./chunk-FK7EBZPX.cjs');
7
7
  var chunkI7X7B3WD_cjs = require('./chunk-I7X7B3WD.cjs');
8
+ var reactDirection = require('@radix-ui/react-direction');
8
9
  var React7 = require('react');
9
10
  var jsxRuntime = require('react/jsx-runtime');
10
11
  var ContextMenuPrimitive = require('@radix-ui/react-context-menu');
@@ -464,7 +465,11 @@ function formatSize(bytes) {
464
465
  }
465
466
 
466
467
  // src/i18n/english-labels.ts
467
- var englishLabels = {
468
+ function frozen(labels) {
469
+ for (const label of Object.values(labels)) if (typeof label === "object") Object.freeze(label);
470
+ return Object.freeze(labels);
471
+ }
472
+ var englishLabels = frozen({
468
473
  document: "Editor",
469
474
  editorHint: "Press Escape, then Tab, to leave the editor.",
470
475
  paragraph: "Paragraph",
@@ -666,7 +671,7 @@ var englishLabels = {
666
671
  emptyFile: "No file chosen",
667
672
  emptyMarkdown: "Empty markdown block",
668
673
  emptyCallout: "Empty callout"
669
- };
674
+ });
670
675
  var QuoinContext = React7__namespace.createContext(null);
671
676
  function QuoinProvider({
672
677
  value,
@@ -820,7 +825,7 @@ function selectNode(controller, blockId) {
820
825
  const { editor } = controller;
821
826
  const { selection } = editor.state;
822
827
  if (selection?.kind === "node" && selection.block === blockId) return;
823
- chunkZ6LAARPB_cjs.dispatchSelection(controller, chunkFK7EBZPX_cjs.nodeSelection(blockId));
828
+ chunkMGN332NY_cjs.dispatchSelection(controller, chunkFK7EBZPX_cjs.nodeSelection(blockId));
824
829
  }
825
830
  function focusNode(controller, blockId) {
826
831
  selectNode(controller, blockId);
@@ -1267,7 +1272,6 @@ function closeBlockMenu(store) {
1267
1272
  }
1268
1273
 
1269
1274
  // src/blocks/text/callout-tone.ts
1270
- var CALLOUT_TONES = ["info", "tip", "success", "warning", "danger"];
1271
1275
  var CALLOUT_ICONS = ["\u{1F4A1}", "\u26A0\uFE0F", "\u2705", "\u2757", "\u2139\uFE0F", "\u{1F4CC}"];
1272
1276
  var TONE_ICONS = {
1273
1277
  info: "\u2139\uFE0F",
@@ -1276,9 +1280,6 @@ var TONE_ICONS = {
1276
1280
  warning: "\u26A0\uFE0F",
1277
1281
  danger: "\u2757"
1278
1282
  };
1279
- function calloutTone(value) {
1280
- return CALLOUT_TONES.find((tone) => tone === value) ?? "info";
1281
- }
1282
1283
  function calloutIcon(attrs, tone) {
1283
1284
  return typeof attrs.icon === "string" && attrs.icon !== "" ? attrs.icon : TONE_ICONS[tone];
1284
1285
  }
@@ -1286,7 +1287,7 @@ function MenuIcon({ icon: Icon2 }) {
1286
1287
  return /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "flex shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(Icon2, { className: "size-4" }) });
1287
1288
  }
1288
1289
  var sharedTone = (blocks) => {
1289
- const tones = new Set(blocks.map((block) => calloutTone(block.attrs.tone)));
1290
+ const tones = new Set(blocks.map((block) => chunkMGN332NY_cjs.calloutTone(block.attrs.tone)));
1290
1291
  return tones.size === 1 ? [...tones][0] : "";
1291
1292
  };
1292
1293
  function CalloutMenus({ kit, controller, blocks }) {
@@ -1299,7 +1300,7 @@ function CalloutMenus({ kit, controller, blocks }) {
1299
1300
  /* @__PURE__ */ jsxRuntime.jsx(MenuIcon, { icon: Droplet }),
1300
1301
  labels.tone
1301
1302
  ] }),
1302
- /* @__PURE__ */ jsxRuntime.jsx(kit.SubContent, { children: /* @__PURE__ */ jsxRuntime.jsx(kit.RadioGroup, { value: sharedTone(blocks), onValueChange: (tone) => apply({ tone }), children: CALLOUT_TONES.map((tone) => /* @__PURE__ */ jsxRuntime.jsx(kit.RadioItem, { value: tone, indicator: /* @__PURE__ */ jsxRuntime.jsx(Check, { className: "size-4" }), children: labels.calloutTones[tone] }, tone)) }) })
1303
+ /* @__PURE__ */ jsxRuntime.jsx(kit.SubContent, { children: /* @__PURE__ */ jsxRuntime.jsx(kit.RadioGroup, { value: sharedTone(blocks), onValueChange: (tone) => apply({ tone }), children: chunkMGN332NY_cjs.CALLOUT_TONES.map((tone) => /* @__PURE__ */ jsxRuntime.jsx(kit.RadioItem, { value: tone, indicator: /* @__PURE__ */ jsxRuntime.jsx(Check, { className: "size-4" }), children: labels.calloutTones[tone] }, tone)) }) })
1303
1304
  ] }),
1304
1305
  /* @__PURE__ */ jsxRuntime.jsxs(kit.Sub, { children: [
1305
1306
  /* @__PURE__ */ jsxRuntime.jsxs(kit.SubTrigger, { children: [
@@ -1526,7 +1527,7 @@ function codeToParagraph(blockId) {
1526
1527
  };
1527
1528
  }
1528
1529
  function leaveCode(controller, blockId, direction, addsLine = false) {
1529
- const moved = chunkZ6LAARPB_cjs.moveToNeighbour(controller, blockId, direction);
1530
+ const moved = chunkMGN332NY_cjs.moveToNeighbour(controller, blockId, direction);
1530
1531
  if (!moved && !(addsLine && controller.run(insertBlocks([{ type: "MARKDOWN" }], "text", blockId)))) return false;
1531
1532
  controller.focus();
1532
1533
  return true;
@@ -1651,7 +1652,7 @@ function travel({ controller, blockId, area }, command) {
1651
1652
  const before = area.value;
1652
1653
  controller.run(command);
1653
1654
  const { selection } = controller.editor.state;
1654
- const edit2 = chunkZ6LAARPB_cjs.textDiff(before, area.value);
1655
+ const edit2 = chunkMGN332NY_cjs.textDiff(before, area.value);
1655
1656
  if (selection?.kind !== "node" || selection.block !== blockId) controller.focus();
1656
1657
  else if (edit2 !== null) area.setSelectionRange(edit2.from + edit2.insert.length, edit2.from + edit2.insert.length);
1657
1658
  return true;
@@ -1736,11 +1737,11 @@ function CodeEditor({ block, controller, field, focusControls }) {
1736
1737
  useTypeIntoCode(controller, blockId, field, edit2);
1737
1738
  const onKeyDown = (event) => {
1738
1739
  const area = event.currentTarget;
1739
- if (chunkZ6LAARPB_cjs.isComposingKey(controller, event.nativeEvent)) return;
1740
+ if (chunkMGN332NY_cjs.isComposingKey(controller, event.nativeEvent)) return;
1740
1741
  const action = codeKeyAction(event, fieldOf(area), controller.isMac);
1741
1742
  if (action !== null && runCodeAction(action, { controller, blockId, area, edit: edit2, focusControls })) event.preventDefault();
1742
1743
  };
1743
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ...{ [chunkZ6LAARPB_cjs.NATIVE_INTERACTION]: "" }, dir: "ltr", className: "quoin-code-scroll", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "quoin-code-lines", children: [
1744
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ...{ [chunkMGN332NY_cjs.NATIVE_INTERACTION]: "" }, dir: "ltr", className: "quoin-code-scroll", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "quoin-code-lines", children: [
1744
1745
  /* @__PURE__ */ jsxRuntime.jsx(
1745
1746
  HighlightOverlay,
1746
1747
  {
@@ -1810,7 +1811,7 @@ var Button = React7__namespace.forwardRef(function Button2({ className, variant
1810
1811
  var COPIED_FOR_MS = 1500;
1811
1812
  function CopyCodeButton({ code, controller }) {
1812
1813
  const labels = useLabels();
1813
- const readOnly = chunkZ6LAARPB_cjs.useReadOnly(controller);
1814
+ const readOnly = chunkMGN332NY_cjs.useReadOnly(controller);
1814
1815
  const [copied, setCopied] = React7.useState(false);
1815
1816
  React7.useEffect(() => {
1816
1817
  if (!copied) return;
@@ -1893,14 +1894,14 @@ var preventDefault = (event) => event.preventDefault();
1893
1894
 
1894
1895
  // src/blocks/text/set-block-attrs.ts
1895
1896
  function setBlockAttrs(controller, blockId, patch) {
1896
- if (!controller.readOnly) controller.run(chunkZ6LAARPB_cjs.onBlock(blockId, chunkFK7EBZPX_cjs.setAttrs(patch)));
1897
+ if (!controller.readOnly) controller.run(chunkMGN332NY_cjs.onBlock(blockId, chunkFK7EBZPX_cjs.setAttrs(patch)));
1897
1898
  }
1898
1899
  var FIELD = `quoin-code-language quoin-code-control ${FOCUS_RING}`;
1899
1900
  var CONTENT = `${MENU_CONTENT} flex max-h-64 w-48 flex-col overflow-y-hidden`;
1900
1901
  function LanguageCombobox({ blockId, controller, language: language2, field, onDone }) {
1901
1902
  const labels = useLabels();
1902
1903
  const listboxId = React7.useId();
1903
- const list = React7.useRef(null);
1904
+ const list2 = React7.useRef(null);
1904
1905
  const settled = React7.useRef(false);
1905
1906
  const focusedByPress = React7.useRef(false);
1906
1907
  const shown = languageName(language2) ?? language2;
@@ -1909,8 +1910,8 @@ function LanguageCombobox({ blockId, controller, language: language2, field, onD
1909
1910
  const options = draft === null ? [] : languageOptions(draft === shown ? "" : draft, labels.plainText);
1910
1911
  const open = options.length > 0;
1911
1912
  const optionId = (index) => `${listboxId}-${index}`;
1912
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
1913
- list.current?.querySelector('[aria-selected="true"]')?.scrollIntoView?.({ block: "nearest" });
1913
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
1914
+ list2.current?.querySelector('[aria-selected="true"]')?.scrollIntoView?.({ block: "nearest" });
1914
1915
  }, [active]);
1915
1916
  const close = () => {
1916
1917
  setDraft(null);
@@ -1935,7 +1936,7 @@ function LanguageCombobox({ blockId, controller, language: language2, field, onD
1935
1936
  onDone();
1936
1937
  };
1937
1938
  const onKeyDown = (event) => {
1938
- if (chunkZ6LAARPB_cjs.isComposingKey(controller, event.nativeEvent)) return;
1939
+ if (chunkMGN332NY_cjs.isComposingKey(controller, event.nativeEvent)) return;
1939
1940
  if (event.key === "ArrowDown" || event.key === "ArrowUp") {
1940
1941
  event.preventDefault();
1941
1942
  const step = event.key === "ArrowDown" ? 1 : -1;
@@ -1992,7 +1993,7 @@ function LanguageCombobox({ blockId, controller, language: language2, field, onD
1992
1993
  className: CONTENT,
1993
1994
  onOpenAutoFocus: preventDefault,
1994
1995
  onCloseAutoFocus: preventDefault,
1995
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: list, role: "listbox", id: listboxId, "aria-label": labels.codeLanguage, className: "min-h-0 overflow-y-auto", children: options.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
1996
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: list2, role: "listbox", id: listboxId, "aria-label": labels.codeLanguage, className: "min-h-0 overflow-y-auto", children: options.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
1996
1997
  SuggestionOption,
1997
1998
  {
1998
1999
  id: optionId(index),
@@ -2009,7 +2010,7 @@ function LanguageCombobox({ blockId, controller, language: language2, field, onD
2009
2010
  }
2010
2011
  var CodeBlock = ({ block, controller }) => {
2011
2012
  const labels = useLabels();
2012
- const readOnly = chunkZ6LAARPB_cjs.useReadOnly(controller);
2013
+ const readOnly = chunkMGN332NY_cjs.useReadOnly(controller);
2013
2014
  const languageField = React7.useRef(null);
2014
2015
  const codeField = React7.useRef(null);
2015
2016
  const code = chunkI7X7B3WD_cjs.str(block.attrs.code);
@@ -2111,7 +2112,7 @@ function selectHandlers(controller, blockId, root, onSelect) {
2111
2112
  return {
2112
2113
  onKeyDown(event) {
2113
2114
  const key = event.nativeEvent;
2114
- if (chunkZ6LAARPB_cjs.isComposingKey(controller, key)) return;
2115
+ if (chunkMGN332NY_cjs.isComposingKey(controller, key)) return;
2115
2116
  if (event.key === "Escape") select();
2116
2117
  else if (!(event.metaKey || event.ctrlKey) || event.target.matches("input:not([type=file])") || !controller.edit(() => controller.editor.handleKey(key)))
2117
2118
  return;
@@ -2235,7 +2236,7 @@ function isBubblePart(element, controller) {
2235
2236
  return element?.closest(`[${BUBBLE_PART}]`)?.getAttribute(BUBBLE_PART) === partId(controller);
2236
2237
  }
2237
2238
  function focusInEditor(controller) {
2238
- const active = document.activeElement;
2239
+ const active = controller.root?.ownerDocument.activeElement ?? null;
2239
2240
  return active !== null && (controller.isEditorElement(active) || isBubblePart(active, controller));
2240
2241
  }
2241
2242
 
@@ -2248,7 +2249,7 @@ var KINDS = [
2248
2249
  [FileText, /^(text\/|(txt|md|csv|pdf|rtf|docx?)$)/]
2249
2250
  ];
2250
2251
  var kindOf = (value) => KINDS.find(([, pattern]) => pattern.test(value))?.[0];
2251
- var fileIcon = (mime, filename) => kindOf(mime) ?? kindOf(/\.([^.]+)$/.exec(filename)?.[1].toLowerCase() ?? "") ?? FileIcon;
2252
+ var fileIcon = (mime, filename) => kindOf(mime.toLowerCase()) ?? kindOf(/\.([^.]+)$/.exec(filename)?.[1].toLowerCase() ?? "") ?? FileIcon;
2252
2253
 
2253
2254
  // src/blocks/file/file-source.ts
2254
2255
  var fileName = (attrs) => chunkI7X7B3WD_cjs.str(attrs.filename) || chunkI7X7B3WD_cjs.str(attrs.storageKey);
@@ -2333,7 +2334,7 @@ var uploadFile = (controller, blockId, file, host) => uploadInto(
2333
2334
  var anyFile = () => true;
2334
2335
  var FileBlock = ({ block, controller }) => {
2335
2336
  const labels = useLabels();
2336
- const readOnly = chunkZ6LAARPB_cjs.useReadOnly(controller);
2337
+ const readOnly = chunkMGN332NY_cjs.useReadOnly(controller);
2337
2338
  const root = React7.useRef(null);
2338
2339
  const filled = hasFile(block.attrs);
2339
2340
  useNodeKeys(controller, block.id, !readOnly, !filled, root);
@@ -2485,7 +2486,7 @@ function useRovingFocus() {
2485
2486
  },
2486
2487
  [syncTabStop]
2487
2488
  );
2488
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(syncTabStop);
2489
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(syncTabStop);
2489
2490
  const onFocus = (event) => {
2490
2491
  if (!owns(event.target)) return;
2491
2492
  current.current = event.target;
@@ -2494,9 +2495,10 @@ function useRovingFocus() {
2494
2495
  const onKeyDown = (event) => {
2495
2496
  const all = items();
2496
2497
  const index = all.indexOf(event.target);
2497
- if (index === -1 || !Object.hasOwn(MOVES, event.key)) return;
2498
+ const key = row.current === null ? event.key : chunkMGN332NY_cjs.arrowAsWritten(event.key, chunkMGN332NY_cjs.inlineDirection(row.current));
2499
+ if (index === -1 || !Object.hasOwn(MOVES, key)) return;
2498
2500
  event.preventDefault();
2499
- all[MOVES[event.key](index, all.length)].focus();
2501
+ all[MOVES[key](index, all.length)].focus();
2500
2502
  };
2501
2503
  return { ref, owns, focusCurrent, onFocus, onKeyDown };
2502
2504
  }
@@ -2504,7 +2506,7 @@ function useRovingFocus() {
2504
2506
  // src/menus/floating/use-focus-key.ts
2505
2507
  var isFocusKey = (event) => event.key === "F10" && event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey;
2506
2508
  function useFocusKey(controller, focus) {
2507
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
2509
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
2508
2510
  const intercept = (event) => {
2509
2511
  if (!isFocusKey(event)) return false;
2510
2512
  event.preventDefault();
@@ -2516,11 +2518,11 @@ function useFocusKey(controller, focus) {
2516
2518
  }
2517
2519
  function NodeToolbar(props) {
2518
2520
  const { blockId, controller, label, anchor, items, next, buttonRefs, children, popover } = props;
2519
- const state = chunkZ6LAARPB_cjs.useEditorState(controller, chunkZ6LAARPB_cjs.wholeState);
2521
+ const state = chunkMGN332NY_cjs.useEditorState(controller, chunkMGN332NY_cjs.wholeState);
2520
2522
  const roving = useRovingFocus();
2521
2523
  useFocusKey(controller, roving.focusCurrent);
2522
2524
  const onKeyDown = (event) => {
2523
- if (!roving.owns(event.target) || chunkZ6LAARPB_cjs.isComposingKey(controller, event.nativeEvent)) return;
2525
+ if (!roving.owns(event.target) || chunkMGN332NY_cjs.isComposingKey(controller, event.nativeEvent)) return;
2524
2526
  const tab = event.key === "Tab" && !event.altKey && !event.ctrlKey && !event.metaKey;
2525
2527
  const ahead = tab && !event.shiftKey && next !== void 0 ? blockPart(controller, blockId, next) : void 0;
2526
2528
  if (ahead !== void 0) ahead.focus();
@@ -2573,13 +2575,14 @@ function createSettled(controller) {
2573
2575
  return {
2574
2576
  read: () => focusInEditor(controller) && !pressed && !composing && !viewComposing(),
2575
2577
  subscribe(notify) {
2578
+ const doc = controller.root?.ownerDocument ?? document;
2576
2579
  const listeners2 = Object.entries(handlers).map(([type, handle2]) => {
2577
2580
  const listener = (event) => {
2578
2581
  handle2(event);
2579
2582
  notify();
2580
2583
  };
2581
- document.addEventListener(type, listener, true);
2582
- return () => document.removeEventListener(type, listener, true);
2584
+ doc.addEventListener(type, listener, true);
2585
+ return () => doc.removeEventListener(type, listener, true);
2583
2586
  });
2584
2587
  const stopState = controller.editor.subscribe(() => notify());
2585
2588
  return () => {
@@ -2601,8 +2604,8 @@ var selectedBlock = (type, filled) => ({ doc, selection }) => {
2601
2604
  return block?.type === type && filled(block.attrs) ? block.id : null;
2602
2605
  };
2603
2606
  function useToolbarBlock(controller, selected, keptFor = null) {
2604
- const blockId = chunkZ6LAARPB_cjs.useEditorState(controller, selected);
2605
- const readOnly = chunkZ6LAARPB_cjs.useReadOnly(controller);
2607
+ const blockId = chunkMGN332NY_cjs.useEditorState(controller, selected);
2608
+ const readOnly = chunkMGN332NY_cjs.useReadOnly(controller);
2606
2609
  const settled = useSelectionSettled(controller);
2607
2610
  return blockId !== null && !readOnly && (settled || keptFor === blockId) ? blockId : null;
2608
2611
  }
@@ -2681,7 +2684,7 @@ function ResizeHandles({ blockId, controller, frame, percent, centred, onPreview
2681
2684
  const value = percent ?? drawn;
2682
2685
  const write = (widthPercent) => setBlockAttrs(controller, blockId, { widthPercent });
2683
2686
  const onKeyDown = (event) => {
2684
- if (chunkZ6LAARPB_cjs.isComposingKey(controller, event.nativeEvent)) return;
2687
+ if (chunkMGN332NY_cjs.isComposingKey(controller, event.nativeEvent)) return;
2685
2688
  const next = keyedWidth(event.key, value);
2686
2689
  if (event.key === "Escape") controller.focus();
2687
2690
  else if (next === null) return;
@@ -2723,7 +2726,7 @@ function ResizeHandles({ blockId, controller, frame, percent, centred, onPreview
2723
2726
  "aria-valuetext": labels.widthValue(value),
2724
2727
  "data-side": side,
2725
2728
  className: "quoin-image-handle",
2726
- ...{ [chunkZ6LAARPB_cjs.NATIVE_INTERACTION]: "" },
2729
+ ...{ [chunkMGN332NY_cjs.NATIVE_INTERACTION]: "" },
2727
2730
  ...bubblePart(controller),
2728
2731
  onKeyDown,
2729
2732
  onPointerDown: onPointerDown(side),
@@ -2796,7 +2799,7 @@ function ImageFigure({ block, controller, readOnly }) {
2796
2799
  )
2797
2800
  ] }),
2798
2801
  (!readOnly || (regions.caption?.length ?? 0) > 0) && /* @__PURE__ */ jsxRuntime.jsx(
2799
- chunkZ6LAARPB_cjs.EditableRegion,
2802
+ chunkMGN332NY_cjs.EditableRegion,
2800
2803
  {
2801
2804
  block: id,
2802
2805
  region: "caption",
@@ -2810,11 +2813,16 @@ function ImageFigure({ block, controller, readOnly }) {
2810
2813
 
2811
2814
  // src/menus/link/link-address.ts
2812
2815
  var BARE_DOMAIN = /^[^\s/#?.]\S*\.\S*$/;
2816
+ var EMAIL = /^[^\s@/]+@[^\s@/]+\.[^\s@/]+$/;
2813
2817
  var WHITESPACE = /\s/;
2818
+ function scheme(address) {
2819
+ if (EMAIL.test(address)) return `mailto:${address}`;
2820
+ return BARE_DOMAIN.test(address) ? `https://${address}` : address;
2821
+ }
2814
2822
  function linkAddress(typed2) {
2815
2823
  const address = typed2.trim();
2816
2824
  if (WHITESPACE.test(address)) return null;
2817
- const completed = !chunkI7X7B3WD_cjs.SCHEME.test(address) && BARE_DOMAIN.test(address) ? `https://${address}` : address;
2825
+ const completed = chunkI7X7B3WD_cjs.SCHEME.test(address) ? address : scheme(address);
2818
2826
  const href = chunkI7X7B3WD_cjs.sanitizeHref(completed);
2819
2827
  return href || null;
2820
2828
  }
@@ -2959,7 +2967,7 @@ function useImageKeys(controller, blockId, picture, editable, root) {
2959
2967
  }
2960
2968
  var ImageBlock = ({ block, controller }) => {
2961
2969
  const labels = useLabels();
2962
- const readOnly = chunkZ6LAARPB_cjs.useReadOnly(controller);
2970
+ const readOnly = chunkMGN332NY_cjs.useReadOnly(controller);
2963
2971
  const root = React7.useRef(null);
2964
2972
  const picture = hasPicture(block.attrs);
2965
2973
  useImageKeys(controller, block.id, picture, !readOnly, root);
@@ -2972,17 +2980,17 @@ var ImageBlock = ({ block, controller }) => {
2972
2980
  "aria-label": labels.blockNames.image,
2973
2981
  contentEditable: false,
2974
2982
  className: "quoin-image",
2975
- ...picture ? { [chunkZ6LAARPB_cjs.NODE_ENTRY]: "" } : void 0,
2983
+ ...picture ? { [chunkMGN332NY_cjs.NODE_ENTRY]: "" } : void 0,
2976
2984
  children: picture ? /* @__PURE__ */ jsxRuntime.jsx(ImageFigure, { block, controller, readOnly }) : empty
2977
2985
  }
2978
2986
  );
2979
2987
  };
2980
2988
  function useOutsidePress(element, ownerDocument, onPress) {
2981
2989
  const latest = React7.useRef(onPress);
2982
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
2990
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
2983
2991
  latest.current = onPress;
2984
2992
  });
2985
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
2993
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
2986
2994
  const doc = ownerDocument();
2987
2995
  const inside = (target) => element.current?.contains(target) === true;
2988
2996
  let touched = null;
@@ -2997,7 +3005,7 @@ function useOutsidePress(element, ownerDocument, onPress) {
2997
3005
  if (touched !== null && !inside(event.target)) latest.current(touched);
2998
3006
  touched = null;
2999
3007
  };
3000
- return chunkZ6LAARPB_cjs.listen(doc, { pointerdown: down, click }, true);
3008
+ return chunkMGN332NY_cjs.listen(doc, { pointerdown: down, click }, true);
3001
3009
  }, [element, ownerDocument]);
3002
3010
  }
3003
3011
  function storeAlt(controller, blockId, opened, patch) {
@@ -3005,7 +3013,7 @@ function storeAlt(controller, blockId, opened, patch) {
3005
3013
  const attrs = chunkI7X7B3WD_cjs.blockById(editor.state.doc, blockId)?.attrs ?? {};
3006
3014
  const changed = chunkI7X7B3WD_cjs.str(attrs.alt) !== opened.alt || attrs.decorative === true !== opened.decorative;
3007
3015
  if (controller.readOnly || controller.root === null || changed) return;
3008
- chunkZ6LAARPB_cjs.onBlock(blockId, chunkFK7EBZPX_cjs.setAttrs(patch))(editor.state, (tr) => editor.dispatch(tr));
3016
+ chunkMGN332NY_cjs.onBlock(blockId, chunkFK7EBZPX_cjs.setAttrs(patch))(editor.state, (tr) => editor.dispatch(tr));
3009
3017
  }
3010
3018
  function AltTextPopover({ blockId, controller, anchor, opener, alt, decorative, onClose }) {
3011
3019
  const labels = useLabels();
@@ -3047,7 +3055,7 @@ function AltTextPopover({ blockId, controller, anchor, opener, alt, decorative,
3047
3055
  close(true);
3048
3056
  };
3049
3057
  const onKeyDown = (event) => {
3050
- if (event.key !== "Tab" || chunkZ6LAARPB_cjs.isComposingKey(controller, event.nativeEvent)) return;
3058
+ if (event.key !== "Tab" || chunkMGN332NY_cjs.isComposingKey(controller, event.nativeEvent)) return;
3051
3059
  const controls = [...event.currentTarget.elements];
3052
3060
  const next = controls[controls.indexOf(event.target) + (event.shiftKey ? -1 : 1)];
3053
3061
  event.preventDefault();
@@ -3075,7 +3083,7 @@ function AltTextPopover({ blockId, controller, anchor, opener, alt, decorative,
3075
3083
  onCloseAutoFocus: preventDefault,
3076
3084
  onEscapeKeyDown: (event) => {
3077
3085
  event.preventDefault();
3078
- if (!chunkZ6LAARPB_cjs.isComposingKey(controller, event)) close(false);
3086
+ if (!chunkMGN332NY_cjs.isComposingKey(controller, event)) close(false);
3079
3087
  },
3080
3088
  ...bubblePart(controller),
3081
3089
  children: /* @__PURE__ */ jsxRuntime.jsxs("form", { noValidate: true, className: "quoin-image-alt", onSubmit: save, onKeyDown, children: [
@@ -3171,7 +3179,7 @@ function ImageToolbarOverlay({ controller }) {
3171
3179
  }
3172
3180
  function ImageToolbar({ blockId, controller, editingAlt, onEditAlt }) {
3173
3181
  const { labels, resolveAssetUrl } = useQuoin();
3174
- const state = chunkZ6LAARPB_cjs.useEditorState(controller, chunkZ6LAARPB_cjs.wholeState);
3182
+ const state = chunkMGN332NY_cjs.useEditorState(controller, chunkMGN332NY_cjs.wholeState);
3175
3183
  const picker = useReplacePicker(controller, blockId, uploadImage, "image/*");
3176
3184
  const altButton = React7.useRef(null);
3177
3185
  const anchor = usePartAnchor(controller, blockId, ".quoin-image-frame");
@@ -3396,20 +3404,20 @@ function CalloutToneMenu({ blockId, controller, tone }) {
3396
3404
  {
3397
3405
  value: tone,
3398
3406
  onValueChange: (value) => setBlockAttrs(controller, blockId, { tone: value }),
3399
- children: CALLOUT_TONES.map((option) => /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuRadioItem, { value: option, children: labels.calloutTones[option] }, option))
3407
+ children: chunkMGN332NY_cjs.CALLOUT_TONES.map((option) => /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuRadioItem, { value: option, children: labels.calloutTones[option] }, option))
3400
3408
  }
3401
3409
  ) })
3402
3410
  ] });
3403
3411
  }
3404
3412
  var CalloutBlock = ({ block, controller }) => {
3405
3413
  const labels = useLabels();
3406
- const readOnly = chunkZ6LAARPB_cjs.useReadOnly(controller);
3407
- const tone = calloutTone(block.attrs.tone);
3414
+ const readOnly = chunkMGN332NY_cjs.useReadOnly(controller);
3415
+ const tone = chunkMGN332NY_cjs.calloutTone(block.attrs.tone);
3408
3416
  const icon = calloutIcon(block.attrs, tone);
3409
3417
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("quoin-callout group/callout flex items-start gap-2", TONE[tone]), "data-tone": tone, children: [
3410
3418
  readOnly ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "flex size-6 items-center justify-center text-base", children: icon }) : /* @__PURE__ */ jsxRuntime.jsx(CalloutIconMenu, { blockId: block.id, controller, icon }),
3411
3419
  /* @__PURE__ */ jsxRuntime.jsx(
3412
- chunkZ6LAARPB_cjs.EditableRegion,
3420
+ chunkMGN332NY_cjs.EditableRegion,
3413
3421
  {
3414
3422
  block: block.id,
3415
3423
  region: "body",
@@ -3478,22 +3486,22 @@ var headingStyles = (level) => `quoin-heading mb-1 font-semibold leading-tight i
3478
3486
  function Heading({ block }) {
3479
3487
  const labels = useLabels();
3480
3488
  const level = chunkI7X7B3WD_cjs.headingLevel(block.attrs.level);
3481
- return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "heading", "aria-level": level, className: headingStyles(level), children: /* @__PURE__ */ jsxRuntime.jsx(chunkZ6LAARPB_cjs.EditableRegion, { block: block.id, region: REGION, label: labels.heading(level) }) });
3489
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "heading", "aria-level": level, className: headingStyles(level), children: /* @__PURE__ */ jsxRuntime.jsx(chunkMGN332NY_cjs.EditableRegion, { block: block.id, region: REGION, label: labels.heading(level) }) });
3482
3490
  }
3483
3491
  function NumberedItem({ block, controller }) {
3484
3492
  const labels = useLabels();
3485
- const number = chunkZ6LAARPB_cjs.useOrderedNumber(controller, block.id);
3493
+ const number = chunkMGN332NY_cjs.useOrderedNumber(controller, block.id);
3486
3494
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "quoin-list-item", "data-list": "ordered", children: [
3487
3495
  /* @__PURE__ */ jsxRuntime.jsx(ListMarker, { list: "ordered", number, depth: block.indent }),
3488
- /* @__PURE__ */ jsxRuntime.jsx(chunkZ6LAARPB_cjs.EditableRegion, { block: block.id, region: REGION, label: labels.numberedItem(number) })
3496
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMGN332NY_cjs.EditableRegion, { block: block.id, region: REGION, label: labels.numberedItem(number) })
3489
3497
  ] });
3490
3498
  }
3491
3499
  function TaskItem({ block, controller }) {
3492
3500
  const labels = useLabels();
3493
- const hostId = chunkZ6LAARPB_cjs.useRegionDomId(block.id, REGION);
3501
+ const hostId = chunkMGN332NY_cjs.useRegionDomId(block.id, REGION);
3494
3502
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "quoin-task", "data-checked": block.attrs.checked === true, children: [
3495
- /* @__PURE__ */ jsxRuntime.jsx(chunkZ6LAARPB_cjs.TaskCheckbox, { block, controller, label: labels.task, labelledBy: hostId }),
3496
- /* @__PURE__ */ jsxRuntime.jsx(chunkZ6LAARPB_cjs.EditableRegion, { id: hostId, block: block.id, region: REGION, label: labels.task })
3503
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMGN332NY_cjs.TaskCheckbox, { block, controller, label: labels.task, labelledBy: hostId }),
3504
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMGN332NY_cjs.EditableRegion, { id: hostId, block: block.id, region: REGION, label: labels.task })
3497
3505
  ] });
3498
3506
  }
3499
3507
  var MarkdownBlock = (props) => {
@@ -3505,16 +3513,16 @@ var MarkdownBlock = (props) => {
3505
3513
  case "bullet":
3506
3514
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "quoin-list-item", "data-list": "bullet", children: [
3507
3515
  /* @__PURE__ */ jsxRuntime.jsx(ListMarker, { list: "bullet", depth: block.indent }),
3508
- /* @__PURE__ */ jsxRuntime.jsx(chunkZ6LAARPB_cjs.EditableRegion, { block: block.id, region: REGION, label: labels.bulletItem })
3516
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMGN332NY_cjs.EditableRegion, { block: block.id, region: REGION, label: labels.bulletItem })
3509
3517
  ] });
3510
3518
  case "ordered":
3511
3519
  return /* @__PURE__ */ jsxRuntime.jsx(NumberedItem, { ...props });
3512
3520
  case "task":
3513
3521
  return /* @__PURE__ */ jsxRuntime.jsx(TaskItem, { ...props });
3514
3522
  case "quote":
3515
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "quoin-quote", children: /* @__PURE__ */ jsxRuntime.jsx(chunkZ6LAARPB_cjs.EditableRegion, { block: block.id, region: REGION, label: labels.quote }) });
3523
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "quoin-quote", children: /* @__PURE__ */ jsxRuntime.jsx(chunkMGN332NY_cjs.EditableRegion, { block: block.id, region: REGION, label: labels.quote }) });
3516
3524
  default:
3517
- return /* @__PURE__ */ jsxRuntime.jsx(chunkZ6LAARPB_cjs.EditableRegion, { block: block.id, region: REGION, label: labels.paragraph });
3525
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkMGN332NY_cjs.EditableRegion, { block: block.id, region: REGION, label: labels.paragraph });
3518
3526
  }
3519
3527
  };
3520
3528
 
@@ -3525,16 +3533,16 @@ function nestedBlockIds({ doc }, blockId) {
3525
3533
  return doc.blocks.slice(index + 1, chunkFK7EBZPX_cjs.descendantsEnd(doc, index)).map((block) => block.id);
3526
3534
  }
3527
3535
  function useNestedBlocks(controller, blockId) {
3528
- return chunkZ6LAARPB_cjs.useEditorState(controller, (state) => nestedBlockIds(state, blockId), chunkI7X7B3WD_cjs.sameItems);
3536
+ return chunkMGN332NY_cjs.useEditorState(controller, (state) => nestedBlockIds(state, blockId), chunkI7X7B3WD_cjs.sameItems);
3529
3537
  }
3530
3538
  var ToggleBlock = ({ block, controller }) => {
3531
3539
  const labels = useLabels();
3532
- const domId = chunkZ6LAARPB_cjs.useBlockDomId();
3540
+ const domId = chunkMGN332NY_cjs.useBlockDomId();
3533
3541
  const nested = useNestedBlocks(controller, block.id);
3534
- const open = chunkZ6LAARPB_cjs.useToggleOpen(controller, block);
3542
+ const open = chunkMGN332NY_cjs.useToggleOpen(controller, block);
3535
3543
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "quoin-toggle", "data-open": open, children: [
3536
3544
  /* @__PURE__ */ jsxRuntime.jsx(
3537
- chunkZ6LAARPB_cjs.ToggleChevron,
3545
+ chunkMGN332NY_cjs.ToggleChevron,
3538
3546
  {
3539
3547
  block,
3540
3548
  controller,
@@ -3542,7 +3550,7 @@ var ToggleBlock = ({ block, controller }) => {
3542
3550
  controls: nested.length === 0 ? void 0 : nested.map(domId).join(" ")
3543
3551
  }
3544
3552
  ),
3545
- /* @__PURE__ */ jsxRuntime.jsx(chunkZ6LAARPB_cjs.EditableRegion, { block: block.id, region: "text", label: labels.toggle })
3553
+ /* @__PURE__ */ jsxRuntime.jsx(chunkMGN332NY_cjs.EditableRegion, { block: block.id, region: "text", label: labels.toggle })
3546
3554
  ] });
3547
3555
  };
3548
3556
 
@@ -3639,7 +3647,7 @@ function ActionItem({ kit, controller, action, blockIds }) {
3639
3647
  );
3640
3648
  }
3641
3649
  function BlockMenuItems({ kit, controller, blocks, styled, title, actions }) {
3642
- const state = chunkZ6LAARPB_cjs.useEditorState(controller, chunkZ6LAARPB_cjs.wholeState);
3650
+ const state = chunkMGN332NY_cjs.useEditorState(controller, chunkMGN332NY_cjs.wholeState);
3643
3651
  const blockIds = blocks.map((block) => block.id);
3644
3652
  const shown = actions.filter((action) => action.available?.(state, blockIds) ?? true);
3645
3653
  const anyText = styled.some((block) => chunkFK7EBZPX_cjs.isTextFlow(state.schema, block));
@@ -3684,7 +3692,7 @@ var CONTEXT_KIT = {
3684
3692
  SubTrigger: ContextMenuSubTrigger
3685
3693
  };
3686
3694
  var GUTTER_BLOCK = "data-quoin-gutter-block";
3687
- var OWN_MENU = `[${chunkZ6LAARPB_cjs.NATIVE_INTERACTION}], input, textarea, select`;
3695
+ var OWN_MENU = `[${chunkMGN332NY_cjs.NATIVE_INTERACTION}], input, textarea, select`;
3688
3696
  function contextBlock(controller, target) {
3689
3697
  const { state } = controller.editor;
3690
3698
  const gutter = target.closest(`[${GUTTER_BLOCK}]`)?.getAttribute(GUTTER_BLOCK);
@@ -3713,7 +3721,7 @@ function useContextMenuOpener(controller, store, trigger) {
3713
3721
  openBlockMenuAt(store, controller.editor.state, block, clientX, clientY);
3714
3722
  hidden.dispatchEvent(new MouseEvent("contextmenu", { bubbles: true, cancelable: true, clientX, clientY }));
3715
3723
  };
3716
- return chunkZ6LAARPB_cjs.listen(root, { mousedown: onMouseDown, contextmenu: onContextMenu });
3724
+ return chunkMGN332NY_cjs.listen(root, { mousedown: onMouseDown, contextmenu: onContextMenu });
3717
3725
  }, [controller, store, trigger]);
3718
3726
  }
3719
3727
 
@@ -3749,7 +3757,7 @@ function useLiveBlocks(controller, blockIds) {
3749
3757
  (state) => blockIds.flatMap((id) => chunkI7X7B3WD_cjs.blockById(state.doc, id) ?? []),
3750
3758
  [blockIds]
3751
3759
  );
3752
- return chunkZ6LAARPB_cjs.useEditorState(controller, select, chunkI7X7B3WD_cjs.sameItems);
3760
+ return chunkMGN332NY_cjs.useEditorState(controller, select, chunkI7X7B3WD_cjs.sameItems);
3753
3761
  }
3754
3762
  function useMenuBlocks(controller, store, menu) {
3755
3763
  const labels = useLabels();
@@ -3876,7 +3884,7 @@ var DragOverlay = React7.forwardRef(function DragOverlay2(_props, ref) {
3876
3884
  var DELETION_STEPS = /* @__PURE__ */ new Set(["removeBlocks", "setIndent"]);
3877
3885
  function drawnPosition(doc, blockId) {
3878
3886
  const index = doc.index.get(blockId) ?? 0;
3879
- return [chunkZ6LAARPB_cjs.drawnBlockCount(doc, 0, index) + 1, chunkZ6LAARPB_cjs.drawnBlockCount(doc)];
3887
+ return [chunkMGN332NY_cjs.drawnBlockCount(doc, 0, index) + 1, chunkMGN332NY_cjs.drawnBlockCount(doc)];
3880
3888
  }
3881
3889
  function blockMovedMessage(doc, blockId, labels) {
3882
3890
  return labels.blockMoved(...drawnPosition(doc, blockId));
@@ -3892,7 +3900,7 @@ function deletedCount(tr) {
3892
3900
  return tr.steps.reduce((deleted, step, i) => {
3893
3901
  const { index, count } = step.toJSON();
3894
3902
  if (step.stepType !== "removeBlocks" || typeof index !== "number" || typeof count !== "number") return deleted;
3895
- return deleted + chunkZ6LAARPB_cjs.drawnBlockCount(tr.docs[i], index, index + count);
3903
+ return deleted + chunkMGN332NY_cjs.drawnBlockCount(tr.docs[i], index, index + count);
3896
3904
  }, 0);
3897
3905
  }
3898
3906
  function insertedBlock(tr) {
@@ -3913,9 +3921,6 @@ function structureAnnouncement(tr, labels, undoKeys) {
3913
3921
  return inserted === null ? null : labels.blockInserted(...drawnPosition(tr.doc, inserted));
3914
3922
  }
3915
3923
 
3916
- // src/ui/direction.ts
3917
- var inlineDirection = (element) => getComputedStyle(element).direction === "rtl" ? "rtl" : "ltr";
3918
-
3919
3924
  // src/drag/drag-layout.ts
3920
3925
  var INDENT_STEP_REM = 1.5;
3921
3926
  function rootOrigin(root) {
@@ -3934,7 +3939,7 @@ function inlineEdges(shell, box, rtl) {
3934
3939
  function measure(controller, root, moved, rtl) {
3935
3940
  const { doc } = controller.editor.state;
3936
3941
  const origin = rootOrigin(root);
3937
- return chunkZ6LAARPB_cjs.visibleBlockIndexes(doc).flatMap((index) => {
3942
+ return chunkMGN332NY_cjs.visibleBlockIndexes(doc).flatMap((index) => {
3938
3943
  const { id, indent: indent3 } = doc.blocks[index];
3939
3944
  const shell = controller.blockElement(id);
3940
3945
  if (shell === void 0) return [];
@@ -3947,7 +3952,7 @@ function measure(controller, root, moved, rtl) {
3947
3952
  var furthestEnd = (blocks, rtl) => blocks.reduce((end, block) => rtl ? Math.min(end, block.end) : Math.max(end, block.end), blocks[0].end);
3948
3953
  function measureDrag(controller, root, ids) {
3949
3954
  const { doc } = controller.editor.state;
3950
- const direction = inlineDirection(root);
3955
+ const direction = chunkMGN332NY_cjs.inlineDirection(root);
3951
3956
  const rtl = direction === "rtl";
3952
3957
  const moved = new Set(chunkFK7EBZPX_cjs.movedBlockIds(doc, ids));
3953
3958
  const blocks = measure(controller, root, moved, rtl);
@@ -4009,7 +4014,7 @@ function draggedBlocks(controller, blockId) {
4009
4014
  function followPress(press, root, view) {
4010
4015
  const { controller, store, overlay, handle: handle2, pointerId } = press;
4011
4016
  const doc = view.document;
4012
- const scroll = chunkZ6LAARPB_cjs.createAutoScroll(root, follow, SCROLL_EDGE);
4017
+ const scroll = chunkMGN332NY_cjs.createAutoScroll(root, follow, SCROLL_EDGE);
4013
4018
  let pointer = { x: press.x, y: press.y };
4014
4019
  let active = null;
4015
4020
  let unsubscribe = () => {
@@ -4039,7 +4044,7 @@ function followPress(press, root, view) {
4039
4044
  overlay.follow(dx, pointer.y - press.y);
4040
4045
  overlay.mark({ top: target.lineTop, ...spanBetween(target.lineStart, layout.end) });
4041
4046
  if (!sameTarget(active.target, target)) {
4042
- store.set({ drag: { blockIds: ids, targetIndex: target.index, targetIndent: target.indent } });
4047
+ store.set({ drag: { blockIds: ids, targetIndent: target.indent } });
4043
4048
  }
4044
4049
  active.target = target;
4045
4050
  }
@@ -4084,9 +4089,9 @@ function followPress(press, root, view) {
4084
4089
  event.stopPropagation();
4085
4090
  finish();
4086
4091
  }
4087
- const unlistenDocument = chunkZ6LAARPB_cjs.listen(doc, { pointermove: onPointerMove, pointerup: onPointerUp, pointercancel: finish });
4088
- const unlistenBlur = chunkZ6LAARPB_cjs.listen(view, { blur: finish });
4089
- const unlistenKeys = chunkZ6LAARPB_cjs.listen(view, { keydown: onKeyDown }, true);
4092
+ const unlistenDocument = chunkMGN332NY_cjs.listen(doc, { pointermove: onPointerMove, pointerup: onPointerUp, pointercancel: finish });
4093
+ const unlistenBlur = chunkMGN332NY_cjs.listen(view, { blur: finish });
4094
+ const unlistenKeys = chunkMGN332NY_cjs.listen(view, { keydown: onKeyDown }, true);
4090
4095
  return finish;
4091
4096
  }
4092
4097
  function pressDragHandle(press) {
@@ -4215,13 +4220,13 @@ function place2(controller, root, gutter, block) {
4215
4220
  const line = firstLine(shell);
4216
4221
  const top = line.top + (line.height - gutter.offsetHeight) / 2 - rootBox.top - root.clientTop + root.scrollTop;
4217
4222
  const shellBox = shell.getBoundingClientRect();
4218
- const beside = inlineDirection(root) === "rtl" ? shellBox.right + GAP : shellBox.left - gutter.offsetWidth - GAP;
4223
+ const beside = chunkMGN332NY_cjs.inlineDirection(root) === "rtl" ? shellBox.right + GAP : shellBox.left - gutter.offsetWidth - GAP;
4219
4224
  const left = beside - rootBox.left - root.clientLeft + root.scrollLeft;
4220
4225
  gutter.style.transform = `translate(${left}px, ${top}px)`;
4221
4226
  gutter.style.visibility = "";
4222
4227
  }
4223
4228
  function useGutterPosition(controller, gutter, block) {
4224
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
4229
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
4225
4230
  const element = gutter.current;
4226
4231
  const root = controller.root;
4227
4232
  const view = root?.ownerDocument.defaultView;
@@ -4253,7 +4258,7 @@ function blockAcross(controller, root, y) {
4253
4258
  }
4254
4259
  function useGutterTarget(controller, store, gutter) {
4255
4260
  const hovered = useCanvasUi(store, (state) => state.hoveredBlock);
4256
- const head = chunkZ6LAARPB_cjs.useEditorState(controller, headOf);
4261
+ const head = chunkMGN332NY_cjs.useEditorState(controller, headOf);
4257
4262
  const [focusWithin, setFocusWithin] = React7.useState(false);
4258
4263
  React7.useEffect(() => {
4259
4264
  const root = controller.root;
@@ -4271,7 +4276,7 @@ function useGutterTarget(controller, store, gutter) {
4271
4276
  const onFocusIn = () => setFocusWithin(true);
4272
4277
  const onFocusOut = (event) => setFocusWithin(root.contains(event.relatedTarget));
4273
4278
  setFocusWithin(root.contains(root.ownerDocument.activeElement));
4274
- return chunkZ6LAARPB_cjs.listen(root, { pointermove: onPointerMove, pointerleave: onPointerLeave, focusin: onFocusIn, focusout: onFocusOut });
4279
+ return chunkMGN332NY_cjs.listen(root, { pointermove: onPointerMove, pointerleave: onPointerLeave, focusin: onFocusIn, focusout: onFocusOut });
4275
4280
  }, [controller, store, gutter]);
4276
4281
  const fallback = focusWithin ? head : null;
4277
4282
  const target = hovered ?? fallback;
@@ -4349,7 +4354,15 @@ function Gutter({ controller, store, actions }) {
4349
4354
  }
4350
4355
 
4351
4356
  // src/i18n/resolve-labels.ts
4352
- var resolveLabels = (overrides) => chunkZWTIRGY5_cjs.mergeLabels(englishLabels, overrides);
4357
+ var isRecord = (value) => typeof value === "object" && value !== null;
4358
+ function ontoRecords(overrides) {
4359
+ const taken = Object.entries(overrides).map(([key, value]) => {
4360
+ const fallback = englishLabels[key];
4361
+ return [key, isRecord(value) && isRecord(fallback) ? { ...fallback, ...value } : value];
4362
+ });
4363
+ return Object.fromEntries(taken);
4364
+ }
4365
+ var resolveLabels = (overrides) => chunkZWTIRGY5_cjs.mergeLabels(englishLabels, overrides && ontoRecords(overrides));
4353
4366
 
4354
4367
  // src/menus/floating/range-rect.ts
4355
4368
  var TEXT_NODE = 3;
@@ -4364,7 +4377,7 @@ function pointInHost(host, { node, offset }) {
4364
4377
  return host.contains(node) ? { node, offset: Math.min(offset, nodeLength(node)) } : null;
4365
4378
  }
4366
4379
  function textRect(host, { from, to }) {
4367
- const map = chunkZ6LAARPB_cjs.domMapOf(host);
4380
+ const map = chunkMGN332NY_cjs.domMapOf(host);
4368
4381
  const range = host.ownerDocument.createRange();
4369
4382
  if (map === void 0 || typeof range.getBoundingClientRect !== "function") return null;
4370
4383
  const start = pointInHost(host, map.toDom(from, 1));
@@ -4377,7 +4390,7 @@ function textRect(host, { from, to }) {
4377
4390
  }
4378
4391
  function rangeRect(controller, range) {
4379
4392
  const host = controller.registry.get(range.block, range.region);
4380
- if (host === void 0 || !host.isConnected || controller.composingKey === chunkZ6LAARPB_cjs.hostKey(range.block, range.region)) {
4393
+ if (host === void 0 || !host.isConnected || controller.composingKey === chunkMGN332NY_cjs.hostKey(range.block, range.region)) {
4381
4394
  return null;
4382
4395
  }
4383
4396
  const rect = textRect(host, range);
@@ -4418,7 +4431,7 @@ function useSelectionAnchor(controller, state) {
4418
4431
  [controller, state]
4419
4432
  );
4420
4433
  const [side, setSide] = React7.useState("top");
4421
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
4434
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
4422
4435
  const rect = selectionRect(controller);
4423
4436
  if (rect) setSide(rect.top < ROOM_ABOVE ? "bottom" : "top");
4424
4437
  }, [controller, state]);
@@ -4500,7 +4513,7 @@ function TurnIntoDropdown({ controller, state }) {
4500
4513
  }
4501
4514
  var DIVIDER = "mx-0.5 h-5 w-px shrink-0 bg-border";
4502
4515
  function BubbleToolbar({ controller, labels, store, extraItems }) {
4503
- const state = chunkZ6LAARPB_cjs.useEditorState(controller, chunkZ6LAARPB_cjs.wholeState);
4516
+ const state = chunkMGN332NY_cjs.useEditorState(controller, chunkMGN332NY_cjs.wholeState);
4504
4517
  const { anchor, side } = useSelectionAnchor(controller, state);
4505
4518
  const roving = useRovingFocus();
4506
4519
  const items = React7.useMemo(() => bubbleItems(labels, () => store.set({ linkPopover: { open: true } })), [labels, store]);
@@ -4548,9 +4561,9 @@ var readOnServer = () => false;
4548
4561
  function useMediaQuery(query, unsupported) {
4549
4562
  const subscribe3 = React7.useCallback(
4550
4563
  (notify) => {
4551
- const list = listOf(query);
4552
- list?.addEventListener("change", notify);
4553
- return () => list?.removeEventListener("change", notify);
4564
+ const list2 = listOf(query);
4565
+ list2?.addEventListener("change", notify);
4566
+ return () => list2?.removeEventListener("change", notify);
4554
4567
  },
4555
4568
  [query]
4556
4569
  );
@@ -4564,8 +4577,8 @@ var useFinePointer = () => useMediaQuery("(pointer: fine)", true);
4564
4577
  // src/menus/bubble/use-bubble-visibility.ts
4565
4578
  var hasTextRange = (state) => state.selection?.kind === "text" && !chunkFK7EBZPX_cjs.isCollapsed(state.selection) && chunkFK7EBZPX_cjs.markRanges(state).length > 0;
4566
4579
  function useBubbleVisibility(controller) {
4567
- const range = chunkZ6LAARPB_cjs.useEditorState(controller, hasTextRange);
4568
- const readOnly = chunkZ6LAARPB_cjs.useReadOnly(controller);
4580
+ const range = chunkMGN332NY_cjs.useEditorState(controller, hasTextRange);
4581
+ const readOnly = chunkMGN332NY_cjs.useReadOnly(controller);
4569
4582
  const fine = useFinePointer();
4570
4583
  const settled = useSelectionSettled(controller);
4571
4584
  return range && !readOnly && fine && settled;
@@ -4588,7 +4601,7 @@ function bubbleExtension() {
4588
4601
  // src/menus/link/link-at-selection.ts
4589
4602
  function linkAround(state, from, to = from) {
4590
4603
  if (from.block !== to.block || from.region !== to.region) return null;
4591
- const inline = chunkZ6LAARPB_cjs.regionInline(state, from.block, from.region) ?? [];
4604
+ const inline = chunkMGN332NY_cjs.regionInline(state, from.block, from.region) ?? [];
4592
4605
  const extent = chunkFK7EBZPX_cjs.markExtent(inline, from.offset, "link");
4593
4606
  if (extent === null || to.offset > extent.to) return null;
4594
4607
  const attrs = chunkI7X7B3WD_cjs.sliceInline(inline, extent.from, extent.to)[0]?.marks.find((mark) => mark.type === "link")?.attrs;
@@ -4611,7 +4624,7 @@ function linkElementAt(controller, target) {
4611
4624
  }
4612
4625
  function linkAtElement(controller, state, element) {
4613
4626
  const host = controller.registry.locate(element);
4614
- const offset = host === null ? null : chunkZ6LAARPB_cjs.domMapOf(host.element)?.fromDom(element, 0) ?? null;
4627
+ const offset = host === null ? null : chunkMGN332NY_cjs.domMapOf(host.element)?.fromDom(element, 0) ?? null;
4615
4628
  if (host === null || offset === null) return null;
4616
4629
  return linkAround(state, { block: host.block, region: host.region, offset });
4617
4630
  }
@@ -4664,7 +4677,7 @@ function caretLinkKey(state) {
4664
4677
  return link && [link.range.block, link.range.region, link.range.from, link.href].join("\0");
4665
4678
  }
4666
4679
  function useCaretInLink(controller, delay) {
4667
- const key = chunkZ6LAARPB_cjs.useEditorState(controller, caretLinkKey);
4680
+ const key = chunkMGN332NY_cjs.useEditorState(controller, caretLinkKey);
4668
4681
  const settled = useSelectionSettled(controller);
4669
4682
  return useRestedValue(settled ? key : null, delay) !== null;
4670
4683
  }
@@ -4698,7 +4711,7 @@ var URL_LENGTH = 48;
4698
4711
  var CARD = "flex w-auto items-center gap-0.5 py-1 ps-3 pe-1 shadow-md";
4699
4712
  var ADDRESS = "me-1 whitespace-nowrap text-sm text-muted-foreground";
4700
4713
  function LinkCard({ controller, labels, store, cardRef, element, onUnlinked }) {
4701
- const state = chunkZ6LAARPB_cjs.useEditorState(controller, chunkZ6LAARPB_cjs.wholeState);
4714
+ const state = chunkMGN332NY_cjs.useEditorState(controller, chunkMGN332NY_cjs.wholeState);
4702
4715
  const link = React7.useMemo(
4703
4716
  () => element === null ? linkAtSelection(state) : linkAtElement(controller, state, element),
4704
4717
  [controller, state, element]
@@ -4716,7 +4729,7 @@ function LinkCard({ controller, labels, store, cardRef, element, onUnlinked }) {
4716
4729
  const edit2 = () => {
4717
4730
  if (element !== null) {
4718
4731
  const selection = chunkFK7EBZPX_cjs.textSelection({ block, region, offset: from }, { block, region, offset: to });
4719
- chunkZ6LAARPB_cjs.dispatchSelection(controller, selection);
4732
+ chunkMGN332NY_cjs.dispatchSelection(controller, selection);
4720
4733
  }
4721
4734
  store.set({ linkPopover: { open: true } });
4722
4735
  };
@@ -4883,7 +4896,7 @@ function LinkOverlay({ controller }) {
4883
4896
  const labels = useLabels();
4884
4897
  const store = useCanvasUiStore();
4885
4898
  const popoverOpen = useCanvasUi(store, isPopoverOpen);
4886
- const readOnly = chunkZ6LAARPB_cjs.useReadOnly(controller);
4899
+ const readOnly = chunkMGN332NY_cjs.useReadOnly(controller);
4887
4900
  useLinkClicks(controller);
4888
4901
  React7.useEffect(() => {
4889
4902
  if (readOnly && store.get().linkPopover.open) store.set({ linkPopover: { open: false } });
@@ -5063,12 +5076,13 @@ function useRangeAnchor(controller, range) {
5063
5076
  const [side, setSide] = React7.useState("bottom");
5064
5077
  const latest = React7.useRef(range);
5065
5078
  const start = range === null ? null : `${range.block} ${range.region} ${range.from}`;
5066
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
5079
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
5067
5080
  latest.current = range;
5068
5081
  });
5069
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
5082
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
5070
5083
  const rect = latest.current && rangeRect(controller, latest.current);
5071
- if (rect) setSide(sideFor(rect, window.innerHeight));
5084
+ const height = controller.root?.ownerDocument.defaultView?.innerHeight;
5085
+ if (rect && height !== void 0) setSide(sideFor(rect, height));
5072
5086
  }, [controller, start]);
5073
5087
  return { anchor, side };
5074
5088
  }
@@ -5092,11 +5106,11 @@ function openCombobox(host, listboxId) {
5092
5106
  }
5093
5107
  function useComboboxHost(controller, block, region, listboxId, activeOptionId) {
5094
5108
  const host = React7.useRef(null);
5095
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
5109
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
5096
5110
  host.current = block === null || region === null ? null : controller.registry.get(block, region) ?? null;
5097
5111
  return host.current === null ? void 0 : openCombobox(host.current, listboxId);
5098
5112
  }, [controller, block, region, listboxId]);
5099
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
5113
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
5100
5114
  if (host.current !== null) restore(host.current, "aria-activedescendant", activeOptionId);
5101
5115
  }, [block, region, activeOptionId]);
5102
5116
  }
@@ -5142,10 +5156,10 @@ function handle(event, menu) {
5142
5156
  }
5143
5157
  function useSuggestionKeys(controller, open, menu) {
5144
5158
  const latest = React7.useRef(menu);
5145
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
5159
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
5146
5160
  latest.current = menu;
5147
5161
  });
5148
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
5162
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
5149
5163
  if (!open) return;
5150
5164
  const intercept = (event) => {
5151
5165
  const handled = handle(event, latest.current);
@@ -5166,10 +5180,10 @@ var isPromise = (value) => typeof value?.then === "function";
5166
5180
  function useSuggestionResults(source, query, onError) {
5167
5181
  const [answer, setAnswer] = React7.useState(FORGOTTEN);
5168
5182
  const report = React7.useRef(onError);
5169
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
5183
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
5170
5184
  report.current = onError;
5171
5185
  });
5172
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
5186
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
5173
5187
  if (query === null) {
5174
5188
  setAnswer(FORGOTTEN);
5175
5189
  return;
@@ -5213,9 +5227,9 @@ function useSuggestion({
5213
5227
  emptyLabel
5214
5228
  }) {
5215
5229
  const { labels, onError } = useQuoin();
5216
- const readOnly = chunkZ6LAARPB_cjs.useReadOnly(controller);
5230
+ const readOnly = chunkMGN332NY_cjs.useReadOnly(controller);
5217
5231
  const selectTrigger = React7.useCallback((state) => chunkFK7EBZPX_cjs.getPluginState(state, pluginKey).active, [pluginKey]);
5218
- const active = chunkZ6LAARPB_cjs.useEditorState(controller, selectTrigger);
5232
+ const active = chunkMGN332NY_cjs.useEditorState(controller, selectTrigger);
5219
5233
  const trigger = readOnly ? null : active;
5220
5234
  const results = useSuggestionResults(source, trigger?.query ?? null, onError);
5221
5235
  const sections = React7.useMemo(() => groupItems(results.items, groupOf2), [results.items, groupOf2]);
@@ -5285,7 +5299,7 @@ function SuggestionMenu(props) {
5285
5299
  const { trigger, sections, activeIndex, listboxId } = suggestion;
5286
5300
  const { anchor, side } = useRangeAnchor(controller, trigger);
5287
5301
  const listbox = React7.useRef(null);
5288
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
5302
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
5289
5303
  listbox.current?.querySelector('[aria-selected="true"]')?.scrollIntoView?.({ block: "nearest" });
5290
5304
  }, [activeIndex, sections]);
5291
5305
  if (trigger === null) return null;
@@ -5364,7 +5378,7 @@ var TEXT_STEPS = /* @__PURE__ */ new Set(["replaceInline", "addMark", "removeMar
5364
5378
  var WHITESPACE3 = /\s/;
5365
5379
  var changesBlocks = (tr) => tr !== null && tr.steps.some((step) => !TEXT_STEPS.has(step.stepType));
5366
5380
  function withSpaceBefore(state, range) {
5367
- const inline = chunkZ6LAARPB_cjs.regionInline(state, range.block, range.region);
5381
+ const inline = chunkMGN332NY_cjs.regionInline(state, range.block, range.region);
5368
5382
  if (inline === void 0 || range.from === 0) return null;
5369
5383
  const text2 = chunkI7X7B3WD_cjs.inlineText(inline);
5370
5384
  const after = text2.charAt(range.to);
@@ -5552,7 +5566,7 @@ function placement(viewport) {
5552
5566
  function EditingTools({ controller }) {
5553
5567
  const labels = useLabels();
5554
5568
  const store = useCanvasUiStore();
5555
- const state = chunkZ6LAARPB_cjs.useEditorState(controller, chunkZ6LAARPB_cjs.wholeState);
5569
+ const state = chunkMGN332NY_cjs.useEditorState(controller, chunkMGN332NY_cjs.wholeState);
5556
5570
  const viewport = useVisualViewport();
5557
5571
  const roving = useRovingFocus();
5558
5572
  const items = React7.useMemo(() => mobileItems(labels, () => store.set({ linkPopover: { open: true } })), [labels, store]);
@@ -5815,6 +5829,14 @@ function shortcutsExtension(store) {
5815
5829
  ui: { overlays: [ShortcutsOverlay] }
5816
5830
  });
5817
5831
  }
5832
+ function useRootDirection(controller) {
5833
+ const [direction, setDirection] = React7.useState("ltr");
5834
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
5835
+ const root = controller.root;
5836
+ if (root !== null) setDirection(chunkMGN332NY_cjs.inlineDirection(root));
5837
+ }, [controller]);
5838
+ return direction;
5839
+ }
5818
5840
 
5819
5841
  // src/canvas/block-link.ts
5820
5842
  var FRAGMENT = "#block-";
@@ -5876,7 +5898,7 @@ function runHistoryKey(controller, event) {
5876
5898
  }
5877
5899
  function useBlockIndex(controller, blockId) {
5878
5900
  const select = React7.useCallback((state) => state.doc.index.get(blockId) ?? -1, [blockId]);
5879
- return chunkZ6LAARPB_cjs.useEditorState(controller, select);
5901
+ return chunkMGN332NY_cjs.useEditorState(controller, select);
5880
5902
  }
5881
5903
  var FOCUSABLE = [
5882
5904
  "input:not([disabled])",
@@ -5903,8 +5925,8 @@ function useEditingFocus(root, editing, stop) {
5903
5925
  const leaveUnlessInside = (event) => {
5904
5926
  if (!inside.current.has(event)) stop();
5905
5927
  };
5906
- const unlistenCapture = chunkZ6LAARPB_cjs.listen(doc, { pointerdown: leaveForCanvas }, true);
5907
- const unlisten = chunkZ6LAARPB_cjs.listen(doc, { pointerdown: leaveUnlessInside, focusin: leaveUnlessInside });
5928
+ const unlistenCapture = chunkMGN332NY_cjs.listen(doc, { pointerdown: leaveForCanvas }, true);
5929
+ const unlisten = chunkMGN332NY_cjs.listen(doc, { pointerdown: leaveUnlessInside, focusin: leaveUnlessInside });
5908
5930
  return () => {
5909
5931
  unlistenCapture();
5910
5932
  unlisten();
@@ -5933,8 +5955,8 @@ function VoidEditor({ Editor, controller, ...props }) {
5933
5955
  }
5934
5956
  function VoidBlock({ block, controller, definition }) {
5935
5957
  const { blockTypes, labels } = useQuoin();
5936
- const { report } = React7.useContext(chunkZ6LAARPB_cjs.BlockErrorContext);
5937
- const readOnly = chunkZ6LAARPB_cjs.useReadOnly(controller);
5958
+ const { report } = React7.useContext(chunkMGN332NY_cjs.BlockErrorContext);
5959
+ const readOnly = chunkMGN332NY_cjs.useReadOnly(controller);
5938
5960
  const { editor: Editor, alwaysEditing = false } = definition;
5939
5961
  const name = blockTypeLabel(labels, block, blockTypes);
5940
5962
  const blockId = block.id;
@@ -5998,7 +6020,7 @@ function VoidBlock({ block, controller, definition }) {
5998
6020
  role: "group",
5999
6021
  "aria-label": name,
6000
6022
  tabIndex: editorShown ? -1 : void 0,
6001
- ...{ [chunkZ6LAARPB_cjs.NATIVE_INTERACTION]: editorShown ? "" : void 0 },
6023
+ ...{ [chunkMGN332NY_cjs.NATIVE_INTERACTION]: editorShown ? "" : void 0 },
6002
6024
  onKeyDown,
6003
6025
  ...focusHandlers,
6004
6026
  onClick,
@@ -6067,6 +6089,8 @@ function extensionUi(extension) {
6067
6089
  const { ui } = extension;
6068
6090
  return typeof ui === "object" && ui !== null ? ui : {};
6069
6091
  }
6092
+ var list = (value) => Array.isArray(value) ? value : [];
6093
+ var record = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
6070
6094
  function mergeRender(uis) {
6071
6095
  const given = uis.flatMap(({ render }) => render === void 0 ? [] : [render]);
6072
6096
  if (given.length === 0) return void 0;
@@ -6079,14 +6103,14 @@ function mergeRender(uis) {
6079
6103
  function collectUi(extensions, definitions, readOnly = false, onError) {
6080
6104
  const uis = extensions.map(extensionUi);
6081
6105
  return {
6082
- slashItems: [...uis.flatMap((ui) => ui.slashItems ?? []), ...blockTypeSlashItems(definitions, onError)],
6083
- bubbleItems: uis.flatMap((ui) => ui.bubbleItems ?? []),
6084
- blockMenuItems: uis.flatMap((ui) => ui.blockMenuItems ?? []),
6085
- renderers: Object.assign({}, canvasRenderers(definitions, readOnly), ...uis.map((ui) => ui.renderers)),
6086
- blockNames: Object.assign({}, ...uis.map((ui) => ui.blockNames)),
6106
+ slashItems: [...uis.flatMap((ui) => list(ui.slashItems)), ...blockTypeSlashItems(definitions, onError)],
6107
+ bubbleItems: uis.flatMap((ui) => list(ui.bubbleItems)),
6108
+ blockMenuItems: uis.flatMap((ui) => list(ui.blockMenuItems)),
6109
+ renderers: Object.assign({}, canvasRenderers(definitions, readOnly), ...uis.map((ui) => record(ui.renderers))),
6110
+ blockNames: Object.assign({}, ...uis.map((ui) => record(ui.blockNames))),
6087
6111
  render: mergeRender(uis),
6088
6112
  overlays: [
6089
- ...uis.flatMap((ui) => ui.overlays ?? []),
6113
+ ...uis.flatMap((ui) => list(ui.overlays)),
6090
6114
  ...Object.entries(inPlaceOverlays).flatMap(([type, overlay]) => drawnInPlace(definitions, type) ? [overlay] : [])
6091
6115
  ]
6092
6116
  };
@@ -6217,7 +6241,7 @@ function deletions(codec, tr) {
6217
6241
  }
6218
6242
  function useDeleteReporter(controller, onDelete) {
6219
6243
  const latest = React7.useRef(onDelete);
6220
- chunkZ6LAARPB_cjs.useIsomorphicLayoutEffect(() => {
6244
+ chunkMGN332NY_cjs.useIsomorphicLayoutEffect(() => {
6221
6245
  latest.current = onDelete;
6222
6246
  });
6223
6247
  React7.useEffect(() => {
@@ -6294,19 +6318,22 @@ var BlockCanvas = React7.forwardRef(function BlockCanvas2({
6294
6318
  );
6295
6319
  useDefinitionWarnings(blockTypes, readOnly);
6296
6320
  const [focusOnMount] = React7.useState(autoFocus);
6297
- const controller = chunkZ6LAARPB_cjs.useQuoinEditor({
6321
+ const controller = chunkMGN332NY_cjs.useQuoinEditor({
6298
6322
  blocks,
6299
6323
  onChange,
6300
6324
  readOnly,
6301
6325
  extensions: allExtensions,
6302
6326
  render: ui.render,
6303
- onFiles: (files, at) => void insertUploads(controller, files, at, {
6304
- upload,
6305
- resolveAssetUrl: resolveAssetUrl ?? String,
6306
- onError: onError ?? console.error,
6307
- unavailable: labels.uploadsUnavailable,
6308
- failed: labels.uploadFailed
6309
- })
6327
+ onFiles(files, at) {
6328
+ const report = onError ?? console.error;
6329
+ void insertUploads(controller, files, at, {
6330
+ upload,
6331
+ resolveAssetUrl: resolveAssetUrl ?? String,
6332
+ onError: report,
6333
+ unavailable: labels.uploadsUnavailable,
6334
+ failed: labels.uploadFailed
6335
+ }).catch((reason) => report(toError(reason)));
6336
+ }
6310
6337
  });
6311
6338
  useDeleteReporter(controller, onDelete);
6312
6339
  useBlockLinkTarget(controller, focusOnMount);
@@ -6327,6 +6354,7 @@ var BlockCanvas = React7.forwardRef(function BlockCanvas2({
6327
6354
  const placeholderLabels = placeholder === void 0 ? labels : { ...labels, placeholderEmpty: placeholder };
6328
6355
  return (state, block) => placeholderFor(state, block, placeholderLabels);
6329
6356
  }, [labels, placeholder]);
6357
+ const direction = useRootDirection(controller);
6330
6358
  React7.useImperativeHandle(
6331
6359
  ref,
6332
6360
  () => ({
@@ -6337,8 +6365,8 @@ var BlockCanvas = React7.forwardRef(function BlockCanvas2({
6337
6365
  }),
6338
6366
  [controller, resolveAssetUrl]
6339
6367
  );
6340
- return /* @__PURE__ */ jsxRuntime.jsx(QuoinProvider, { value: { blockTypes, upload, resolveAssetUrl, onError, highlight, controller, labels }, children: /* @__PURE__ */ jsxRuntime.jsx(VoidEditingContext.Provider, { value: voidEditing, children: /* @__PURE__ */ jsxRuntime.jsx(SlashItemsProvider, { value: slashItems, children: /* @__PURE__ */ jsxRuntime.jsx(BubbleItemsProvider, { value: ui.bubbleItems, children: /* @__PURE__ */ jsxRuntime.jsx(CanvasUiProvider, { value: uiStore, children: /* @__PURE__ */ jsxRuntime.jsxs(
6341
- chunkZ6LAARPB_cjs.EditorView,
6368
+ return /* @__PURE__ */ jsxRuntime.jsx(reactDirection.DirectionProvider, { dir: direction, children: /* @__PURE__ */ jsxRuntime.jsx(QuoinProvider, { value: { blockTypes, upload, resolveAssetUrl, onError, highlight, controller, labels }, children: /* @__PURE__ */ jsxRuntime.jsx(VoidEditingContext.Provider, { value: voidEditing, children: /* @__PURE__ */ jsxRuntime.jsx(SlashItemsProvider, { value: slashItems, children: /* @__PURE__ */ jsxRuntime.jsx(BubbleItemsProvider, { value: ui.bubbleItems, children: /* @__PURE__ */ jsxRuntime.jsx(CanvasUiProvider, { value: uiStore, children: /* @__PURE__ */ jsxRuntime.jsxs(
6369
+ chunkMGN332NY_cjs.EditorView,
6342
6370
  {
6343
6371
  controller,
6344
6372
  renderers: ui.renderers,
@@ -6364,7 +6392,7 @@ var BlockCanvas = React7.forwardRef(function BlockCanvas2({
6364
6392
  ui.overlays.map((Overlay2, index) => /* @__PURE__ */ jsxRuntime.jsx(Overlay2, { controller }, index))
6365
6393
  ]
6366
6394
  }
6367
- ) }) }) }) }) });
6395
+ ) }) }) }) }) }) });
6368
6396
  });
6369
6397
  function progressText(state, labels) {
6370
6398
  if (state.phase === "busy") return labels.uploading;
@@ -6428,8 +6456,15 @@ async function attemptSave(run) {
6428
6456
  return { error };
6429
6457
  }
6430
6458
  }
6459
+ function retryable(error, isRetryable) {
6460
+ try {
6461
+ return isRetryable(error);
6462
+ } catch {
6463
+ return false;
6464
+ }
6465
+ }
6431
6466
  function nextRetryDelay(error, retriesSoFar, { debounceMs, maxBackoffMs, maxRetries, isRetryable }) {
6432
- if (retriesSoFar >= maxRetries || !isRetryable(error)) return null;
6467
+ if (retriesSoFar >= maxRetries || !retryable(error, isRetryable)) return null;
6433
6468
  return Math.min(debounceMs * 2 ** (retriesSoFar + 1), maxBackoffMs);
6434
6469
  }
6435
6470
 
@@ -6622,7 +6657,6 @@ exports.dismissSuggestion = dismissSuggestion;
6622
6657
  exports.englishLabels = englishLabels;
6623
6658
  exports.focusNode = focusNode;
6624
6659
  exports.formatShortcut = formatShortcut;
6625
- exports.inlineDirection = inlineDirection;
6626
6660
  exports.insertBlockToWrite = insertBlockToWrite;
6627
6661
  exports.insertBlocks = insertBlocks;
6628
6662
  exports.interceptKeys = interceptKeys;