@sofereditor/react 0.6.0 → 0.9.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.
package/dist/index.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -23,6 +33,7 @@ __export(index_exports, {
23
33
  A4_PAGE: () => A4_PAGE,
24
34
  Editor: () => Editor,
25
35
  EditorProvider: () => EditorProvider,
36
+ FormulaDialog: () => FormulaDialog,
26
37
  ImageCaptionDialog: () => ImageCaptionDialog,
27
38
  LinkDialog: () => LinkDialog,
28
39
  NodeView: () => NodeView,
@@ -54,8 +65,8 @@ __export(index_exports, {
54
65
  module.exports = __toCommonJS(index_exports);
55
66
 
56
67
  // src/Editor.tsx
57
- var import_react14 = require("react");
58
- var import_core8 = require("@sofereditor/core");
68
+ var import_react15 = require("react");
69
+ var import_core10 = require("@sofereditor/core");
59
70
 
60
71
  // src/dom-bridge.ts
61
72
  function findContainingBlockElement(node, root) {
@@ -335,6 +346,11 @@ var import_core2 = require("@sofereditor/core");
335
346
 
336
347
  // src/htmlToSlice.ts
337
348
  var import_core = require("@sofereditor/core");
349
+
350
+ // src/imageConstraints.ts
351
+ var MAX_INSERT_WIDTH = 600;
352
+
353
+ // src/htmlToSlice.ts
338
354
  function htmlToSlice(html) {
339
355
  if (!html || html.trim().length === 0) return null;
340
356
  let doc;
@@ -353,8 +369,10 @@ function htmlToSlice(html) {
353
369
  }
354
370
  if (blocks.length === 0) return null;
355
371
  normalizeListLevels(blocks);
356
- const temTexto = blocks.some((b) => b.text.trim().length > 0);
357
- if (!temTexto) return null;
372
+ const temConteudo = blocks.some(
373
+ (b) => b.text.trim().length > 0 || b.delta.some((op) => (0, import_core.isImageEmbed)(op.insert))
374
+ );
375
+ if (!temConteudo) return null;
358
376
  const blockLevel = blocks.length > 1 || blocks[0].type !== "paragraph";
359
377
  return { blocks, openStart: false, openEnd: false, ...blockLevel ? { blockLevel: true } : {} };
360
378
  }
@@ -465,6 +483,7 @@ function walkBlockLevel(container, marks, blocks) {
465
483
  break;
466
484
  }
467
485
  case "img":
486
+ loose.push(node);
468
487
  break;
469
488
  case "br":
470
489
  loose.push(node);
@@ -657,7 +676,11 @@ function walkInlineNode(node, marks, ops) {
657
676
  const el = node;
658
677
  const tag = el.tagName.toLowerCase();
659
678
  if (IGNORED_TAGS.has(tag) || isNamespacedTag(tag)) return;
660
- if (tag === "img") return;
679
+ if (tag === "img") {
680
+ const op = imageEmbedFromElement(el);
681
+ if (op) ops.push(op);
682
+ return;
683
+ }
661
684
  if (tag === "br") {
662
685
  ops.push({ insert: " " });
663
686
  return;
@@ -672,6 +695,73 @@ function walkInlineNode(node, marks, ops) {
672
695
  }
673
696
  for (const child of Array.from(el.childNodes)) walkInlineNode(child, nextMarks, ops);
674
697
  }
698
+ var MIN_EMBED_BYTES = 1024;
699
+ function decodedDataUrlByteLength(dataUrl) {
700
+ const commaIndex = dataUrl.indexOf(",");
701
+ if (commaIndex === -1) return 0;
702
+ const meta = dataUrl.slice(0, commaIndex);
703
+ const payload = dataUrl.slice(commaIndex + 1);
704
+ if (/;base64$/i.test(meta)) {
705
+ const padding = payload.endsWith("==") ? 2 : payload.endsWith("=") ? 1 : 0;
706
+ return Math.max(0, Math.floor(payload.length * 3 / 4) - padding);
707
+ }
708
+ try {
709
+ return decodeURIComponent(payload).length;
710
+ } catch {
711
+ return payload.length;
712
+ }
713
+ }
714
+ function imageEmbedFromElement(el) {
715
+ const src = el.getAttribute("src");
716
+ if (!src || !src.startsWith("data:image/")) return null;
717
+ if (decodedDataUrlByteLength(src) < MIN_EMBED_BYTES) return null;
718
+ const style = parseStyle(el.getAttribute("style"));
719
+ const width = readImageDimension(el, "width", style);
720
+ const height = readImageDimension(el, "height", style);
721
+ if (width == null || height == null) return null;
722
+ let w = width;
723
+ let h = height;
724
+ if (w > MAX_INSERT_WIDTH) {
725
+ h = h * MAX_INSERT_WIDTH / w;
726
+ w = MAX_INSERT_WIDTH;
727
+ }
728
+ return { insert: { type: "image", src, width: Math.round(w), height: Math.round(h) } };
729
+ }
730
+ function readImageDimension(el, attr, style) {
731
+ const raw = el.getAttribute(attr);
732
+ if (raw && /^\d+(\.\d+)?$/.test(raw.trim())) {
733
+ const n = Number.parseFloat(raw);
734
+ if (Number.isFinite(n) && n > 0) return n;
735
+ }
736
+ const fromStyle = style[attr];
737
+ if (fromStyle) {
738
+ const n = cssLengthToPx(fromStyle);
739
+ if (n != null) return n;
740
+ }
741
+ return void 0;
742
+ }
743
+ function cssLengthToPx(raw) {
744
+ const v = raw.trim();
745
+ const m = /^(-?[\d.]+)\s*(px|pt|in|cm|mm)?$/i.exec(v);
746
+ if (!m) return void 0;
747
+ const num = Number.parseFloat(m[1]);
748
+ if (!Number.isFinite(num) || num <= 0) return void 0;
749
+ const unit = (m[2] ?? "px").toLowerCase();
750
+ switch (unit) {
751
+ case "px":
752
+ return num;
753
+ case "pt":
754
+ return num * (96 / 72);
755
+ case "in":
756
+ return num * 96;
757
+ case "cm":
758
+ return num * (96 / 2.54);
759
+ case "mm":
760
+ return num * (96 / 25.4);
761
+ default:
762
+ return void 0;
763
+ }
764
+ }
675
765
  function applyTagMarks(tag, marks) {
676
766
  switch (tag) {
677
767
  case "b":
@@ -939,6 +1029,58 @@ function planPaste(cd) {
939
1029
  return { kind: "none" };
940
1030
  }
941
1031
 
1032
+ // src/resolvePastedImages.ts
1033
+ var import_core3 = require("@sofereditor/core");
1034
+ function sliceHasDataImageEmbeds(slice) {
1035
+ return slice.blocks.some(
1036
+ (b) => b.delta.some((op) => (0, import_core3.isImageEmbed)(op.insert) && op.insert.src.startsWith("data:image/"))
1037
+ );
1038
+ }
1039
+ async function resolvePastedImageUploads(slice, upload) {
1040
+ if (!upload) return slice;
1041
+ const blocks = await Promise.all(
1042
+ slice.blocks.map(async (block) => {
1043
+ let changed = false;
1044
+ const delta = await Promise.all(
1045
+ block.delta.map(async (op) => {
1046
+ if (!(0, import_core3.isImageEmbed)(op.insert) || !op.insert.src.startsWith("data:image/")) return op;
1047
+ try {
1048
+ const file = await dataUrlToFile(op.insert.src);
1049
+ const newSrc = await upload(file);
1050
+ changed = true;
1051
+ return { ...op, insert: { ...op.insert, src: newSrc } };
1052
+ } catch (err) {
1053
+ console.error(
1054
+ "[sofereditor] falha ao subir imagem colada para o storage \u2014 mantendo a imagem embutida (data:) nesta colagem",
1055
+ err
1056
+ );
1057
+ return op;
1058
+ }
1059
+ })
1060
+ );
1061
+ return changed ? { ...block, delta } : block;
1062
+ })
1063
+ );
1064
+ return { ...slice, blocks };
1065
+ }
1066
+ async function dataUrlToFile(dataUrl) {
1067
+ const blob = await fetch(dataUrl).then((r) => r.blob());
1068
+ const mime = blob.type;
1069
+ return new File([blob], `imagem-colada-${Date.now()}.${extensionForMime(mime)}`, { type: mime });
1070
+ }
1071
+ var MIME_EXTENSIONS = {
1072
+ "image/png": "png",
1073
+ "image/jpeg": "jpg",
1074
+ "image/jpg": "jpg",
1075
+ "image/gif": "gif",
1076
+ "image/webp": "webp",
1077
+ "image/bmp": "bmp",
1078
+ "image/svg+xml": "svg"
1079
+ };
1080
+ function extensionForMime(mime) {
1081
+ return MIME_EXTENSIONS[mime.toLowerCase()] ?? "png";
1082
+ }
1083
+
942
1084
  // src/BehindImageSelectAffordance.tsx
943
1085
  var import_react = require("react");
944
1086
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -1162,7 +1304,7 @@ function LinkHoverTooltip({ href, rect }) {
1162
1304
  }
1163
1305
 
1164
1306
  // src/EditorContext.tsx
1165
- var import_react5 = require("react");
1307
+ var import_react6 = require("react");
1166
1308
 
1167
1309
  // src/LinkDialog.tsx
1168
1310
  var import_react2 = require("react");
@@ -1255,7 +1397,7 @@ function LinkDialog() {
1255
1397
 
1256
1398
  // src/PageConfigDialog.tsx
1257
1399
  var import_react3 = require("react");
1258
- var import_core3 = require("@sofereditor/core");
1400
+ var import_core4 = require("@sofereditor/core");
1259
1401
  var import_jsx_runtime4 = require("react/jsx-runtime");
1260
1402
  function PageConfigDialog() {
1261
1403
  const { pageConfigRequest, resolvePageConfigRequest, setPageSettings } = useEditorContext();
@@ -1289,14 +1431,14 @@ function PageConfigDialog() {
1289
1431
  }, [pageConfigRequest]);
1290
1432
  (0, import_react3.useEffect)(() => {
1291
1433
  if (sizePreset === "custom") return;
1292
- const p = import_core3.PAGE_PRESETS[sizePreset];
1293
- setWidthMm(roundMm((0, import_core3.pxToMm)(p.width)));
1294
- setHeightMm(roundMm((0, import_core3.pxToMm)(p.height)));
1434
+ const p = import_core4.PAGE_PRESETS[sizePreset];
1435
+ setWidthMm(roundMm((0, import_core4.pxToMm)(p.width)));
1436
+ setHeightMm(roundMm((0, import_core4.pxToMm)(p.height)));
1295
1437
  }, [sizePreset]);
1296
1438
  (0, import_react3.useEffect)(() => {
1297
1439
  if (marginPreset === "custom") return;
1298
- const px = import_core3.MARGIN_PRESETS[marginPreset];
1299
- const mm = roundMm((0, import_core3.pxToMm)(px));
1440
+ const px = import_core4.MARGIN_PRESETS[marginPreset];
1441
+ const mm = roundMm((0, import_core4.pxToMm)(px));
1300
1442
  setMarginTopMm(mm);
1301
1443
  setMarginBottomMm(mm);
1302
1444
  setMarginLeftMm(mm);
@@ -1305,8 +1447,8 @@ function PageConfigDialog() {
1305
1447
  const customWidth = sizePreset === "custom";
1306
1448
  const previewPx = (0, import_react3.useMemo)(
1307
1449
  () => ({
1308
- width: Math.round((0, import_core3.mmToPx)(widthMm)),
1309
- height: Math.round((0, import_core3.mmToPx)(heightMm))
1450
+ width: Math.round((0, import_core4.mmToPx)(widthMm)),
1451
+ height: Math.round((0, import_core4.mmToPx)(heightMm))
1310
1452
  }),
1311
1453
  [widthMm, heightMm]
1312
1454
  );
@@ -1314,12 +1456,12 @@ function PageConfigDialog() {
1314
1456
  const onApply = (e) => {
1315
1457
  e.preventDefault();
1316
1458
  const next = {
1317
- width: (0, import_core3.mmToPx)(widthMm),
1318
- height: (0, import_core3.mmToPx)(heightMm),
1319
- marginTop: (0, import_core3.mmToPx)(marginTopMm),
1320
- marginBottom: (0, import_core3.mmToPx)(marginBottomMm),
1321
- marginLeft: (0, import_core3.mmToPx)(marginLeftMm),
1322
- marginRight: (0, import_core3.mmToPx)(marginRightMm)
1459
+ width: (0, import_core4.mmToPx)(widthMm),
1460
+ height: (0, import_core4.mmToPx)(heightMm),
1461
+ marginTop: (0, import_core4.mmToPx)(marginTopMm),
1462
+ marginBottom: (0, import_core4.mmToPx)(marginBottomMm),
1463
+ marginLeft: (0, import_core4.mmToPx)(marginLeftMm),
1464
+ marginRight: (0, import_core4.mmToPx)(marginRightMm)
1323
1465
  };
1324
1466
  setPageSettings(next);
1325
1467
  resolvePageConfigRequest(true);
@@ -1578,14 +1720,14 @@ function roundMm(mm) {
1578
1720
  return Math.round(mm * 10) / 10;
1579
1721
  }
1580
1722
  function hydrateFromSettings(s, setters) {
1581
- const preset = (0, import_core3.detectPreset)(s.width, s.height);
1723
+ const preset = (0, import_core4.detectPreset)(s.width, s.height);
1582
1724
  setters.setSizePreset(preset);
1583
- setters.setWidthMm(roundMm((0, import_core3.pxToMm)(s.width)));
1584
- setters.setHeightMm(roundMm((0, import_core3.pxToMm)(s.height)));
1585
- const top = roundMm((0, import_core3.pxToMm)(s.marginTop));
1586
- const bottom = roundMm((0, import_core3.pxToMm)(s.marginBottom));
1587
- const left = roundMm((0, import_core3.pxToMm)(s.marginLeft));
1588
- const right = roundMm((0, import_core3.pxToMm)(s.marginRight));
1725
+ setters.setWidthMm(roundMm((0, import_core4.pxToMm)(s.width)));
1726
+ setters.setHeightMm(roundMm((0, import_core4.pxToMm)(s.height)));
1727
+ const top = roundMm((0, import_core4.pxToMm)(s.marginTop));
1728
+ const bottom = roundMm((0, import_core4.pxToMm)(s.marginBottom));
1729
+ const left = roundMm((0, import_core4.pxToMm)(s.marginLeft));
1730
+ const right = roundMm((0, import_core4.pxToMm)(s.marginRight));
1589
1731
  setters.setMarginTopMm(top);
1590
1732
  setters.setMarginBottomMm(bottom);
1591
1733
  setters.setMarginLeftMm(left);
@@ -1596,7 +1738,7 @@ function detectMarginPreset(s) {
1596
1738
  const TOL = 1;
1597
1739
  const allEqual = Math.abs(s.marginTop - s.marginBottom) <= TOL && Math.abs(s.marginTop - s.marginLeft) <= TOL && Math.abs(s.marginTop - s.marginRight) <= TOL;
1598
1740
  if (!allEqual) return "custom";
1599
- for (const [name, px] of Object.entries(import_core3.MARGIN_PRESETS)) {
1741
+ for (const [name, px] of Object.entries(import_core4.MARGIN_PRESETS)) {
1600
1742
  if (Math.abs(s.marginTop - px) <= TOL) return name;
1601
1743
  }
1602
1744
  return "custom";
@@ -1691,19 +1833,380 @@ function ImageCaptionDialog() {
1691
1833
  );
1692
1834
  }
1693
1835
 
1694
- // src/EditorContext.tsx
1836
+ // src/FormulaDialog.tsx
1837
+ var import_react5 = require("react");
1838
+
1839
+ // src/formulaSnippet.ts
1840
+ var PALETA = [
1841
+ {
1842
+ nome: "Estruturas",
1843
+ colunas: 4,
1844
+ itens: [
1845
+ { label: "Fra\xE7\xE3o", snippet: "\\frac{}{}" },
1846
+ { label: "Expoente", snippet: "^{}" },
1847
+ { label: "\xCDndice", snippet: "_{}" },
1848
+ { label: "Raiz", snippet: "\\sqrt{}" },
1849
+ { label: "Raiz n-\xE9sima", snippet: "\\sqrt[{}]{}" },
1850
+ { label: "Somat\xF3rio", snippet: "\\sum_{}^{}" },
1851
+ { label: "Produt\xF3rio", snippet: "\\prod_{}^{}" },
1852
+ { label: "Integral", snippet: "\\int_{}^{}" },
1853
+ { label: "Limite", snippet: "\\lim_{{} \\to {}}" },
1854
+ { label: "Derivada", snippet: "\\frac{d}{d{}}" },
1855
+ {
1856
+ label: "Matriz 2\xD72",
1857
+ snippet: "\\begin{pmatrix} {} & {} \\\\ {} & {} \\end{pmatrix}"
1858
+ },
1859
+ { label: "Sistema", snippet: "\\begin{cases} {} \\\\ \\end{cases}" },
1860
+ { label: "Par\xEAnteses", snippet: "\\left({}\\right)" },
1861
+ { label: "Binomial", snippet: "\\binom{}{}" },
1862
+ { label: "M\xF3dulo", snippet: "\\left|{}\\right|" }
1863
+ ]
1864
+ },
1865
+ {
1866
+ nome: "S\xEDmbolos",
1867
+ colunas: 6,
1868
+ itens: [
1869
+ { label: "\xB1", snippet: "\\pm", titulo: "mais ou menos" },
1870
+ { label: "\xD7", snippet: "\\times", titulo: "multiplica\xE7\xE3o" },
1871
+ { label: "\xF7", snippet: "\\div", titulo: "divis\xE3o" },
1872
+ { label: "\xB7", snippet: "\\cdot", titulo: "multiplica\xE7\xE3o (ponto)" },
1873
+ { label: "\u221E", snippet: "\\infty", titulo: "infinito" },
1874
+ { label: "\xB0", snippet: "^\\circ", titulo: "grau" },
1875
+ { label: "%", snippet: "\\%", titulo: "por cento" },
1876
+ { label: ",", snippet: "{,}", titulo: "v\xEDrgula decimal" }
1877
+ ]
1878
+ },
1879
+ {
1880
+ nome: "Rela\xE7\xF5es",
1881
+ colunas: 6,
1882
+ itens: [
1883
+ { label: "\u2260", snippet: "\\neq", titulo: "diferente de" },
1884
+ { label: "\u2248", snippet: "\\approx", titulo: "aproximadamente" },
1885
+ { label: "\u2261", snippet: "\\equiv", titulo: "id\xEAntico a" },
1886
+ { label: "\u2264", snippet: "\\leq", titulo: "menor ou igual a" },
1887
+ { label: "\u2265", snippet: "\\geq", titulo: "maior ou igual a" },
1888
+ { label: "\u221D", snippet: "\\propto", titulo: "proporcional a" },
1889
+ { label: "\u22A5", snippet: "\\perp", titulo: "perpendicular a" },
1890
+ { label: "\u2225", snippet: "\\parallel", titulo: "paralelo a" },
1891
+ { label: "\u2245", snippet: "\\cong", titulo: "congruente a" },
1892
+ { label: "\u223C", snippet: "\\sim", titulo: "semelhante a" }
1893
+ ]
1894
+ },
1895
+ {
1896
+ nome: "Gregas",
1897
+ colunas: 6,
1898
+ itens: [
1899
+ { label: "\u03B1", snippet: "\\alpha", titulo: "alfa" },
1900
+ { label: "\u03B2", snippet: "\\beta", titulo: "beta" },
1901
+ { label: "\u03B3", snippet: "\\gamma", titulo: "gama" },
1902
+ { label: "\u03B4", snippet: "\\delta", titulo: "delta" },
1903
+ { label: "\u03B5", snippet: "\\varepsilon", titulo: "\xE9psilon" },
1904
+ { label: "\u03B8", snippet: "\\theta", titulo: "teta" },
1905
+ { label: "\u03BB", snippet: "\\lambda", titulo: "lambda" },
1906
+ { label: "\u03BC", snippet: "\\mu", titulo: "mi" },
1907
+ { label: "\u03C0", snippet: "\\pi", titulo: "pi" },
1908
+ { label: "\u03C1", snippet: "\\rho", titulo: "r\xF4" },
1909
+ { label: "\u03C3", snippet: "\\sigma", titulo: "sigma" },
1910
+ { label: "\u03C6", snippet: "\\varphi", titulo: "fi" },
1911
+ { label: "\u03C9", snippet: "\\omega", titulo: "\xF4mega" },
1912
+ { label: "\u0394", snippet: "\\Delta", titulo: "delta mai\xFAsculo" },
1913
+ {
1914
+ label: "\u03A3",
1915
+ snippet: "\\Sigma",
1916
+ titulo: "sigma mai\xFAsculo \u2014 letra grega; para somat\xF3rio use Estruturas"
1917
+ },
1918
+ {
1919
+ label: "\u03A0",
1920
+ snippet: "\\Pi",
1921
+ titulo: "pi mai\xFAsculo \u2014 letra grega; para produt\xF3rio use Estruturas"
1922
+ },
1923
+ { label: "\u03A9", snippet: "\\Omega", titulo: "\xF4mega mai\xFAsculo" },
1924
+ { label: "\u03A6", snippet: "\\Phi", titulo: "fi mai\xFAsculo" }
1925
+ ]
1926
+ },
1927
+ {
1928
+ nome: "Conjuntos",
1929
+ colunas: 6,
1930
+ itens: [
1931
+ { label: "\u2208", snippet: "\\in", titulo: "pertence a" },
1932
+ { label: "\u2209", snippet: "\\notin", titulo: "n\xE3o pertence a" },
1933
+ { label: "\u2282", snippet: "\\subset", titulo: "contido em" },
1934
+ { label: "\u2286", snippet: "\\subseteq", titulo: "contido ou igual a" },
1935
+ { label: "\u222A", snippet: "\\cup", titulo: "uni\xE3o" },
1936
+ { label: "\u2229", snippet: "\\cap", titulo: "interse\xE7\xE3o" },
1937
+ { label: "\u2205", snippet: "\\varnothing", titulo: "conjunto vazio" },
1938
+ { label: "\u2115", snippet: "\\mathbb{N}", titulo: "conjunto dos naturais" },
1939
+ { label: "\u2124", snippet: "\\mathbb{Z}", titulo: "conjunto dos inteiros" },
1940
+ { label: "\u211A", snippet: "\\mathbb{Q}", titulo: "conjunto dos racionais" },
1941
+ { label: "\u211D", snippet: "\\mathbb{R}", titulo: "conjunto dos reais" },
1942
+ { label: "\u2102", snippet: "\\mathbb{C}", titulo: "conjunto dos complexos" },
1943
+ { label: "\u2200", snippet: "\\forall", titulo: "para todo" },
1944
+ { label: "\u2203", snippet: "\\exists", titulo: "existe" },
1945
+ { label: "{ }", snippet: "\\{{}\\}", titulo: "chaves de conjunto" }
1946
+ ]
1947
+ },
1948
+ {
1949
+ nome: "Fun\xE7\xF5es",
1950
+ colunas: 6,
1951
+ itens: [
1952
+ { label: "sen", snippet: "\\operatorname{sen}", titulo: "seno" },
1953
+ { label: "cos", snippet: "\\cos", titulo: "cosseno" },
1954
+ { label: "tg", snippet: "\\operatorname{tg}", titulo: "tangente" },
1955
+ { label: "cotg", snippet: "\\operatorname{cotg}", titulo: "cotangente" },
1956
+ { label: "log", snippet: "\\log_{}", titulo: "logaritmo" },
1957
+ { label: "ln", snippet: "\\ln", titulo: "logaritmo natural" },
1958
+ { label: "exp", snippet: "\\exp", titulo: "exponencial" }
1959
+ ]
1960
+ },
1961
+ {
1962
+ nome: "Setas",
1963
+ colunas: 6,
1964
+ itens: [
1965
+ { label: "\u2192", snippet: "\\to", titulo: "tende a / vai para" },
1966
+ { label: "\u2190", snippet: "\\leftarrow", titulo: "vem de / sentido inverso" },
1967
+ { label: "\u21D2", snippet: "\\Rightarrow", titulo: "implica em" },
1968
+ { label: "\u21D4", snippet: "\\Leftrightarrow", titulo: "se e somente se" },
1969
+ { label: "\u21CC", snippet: "\\rightleftharpoons", titulo: "equil\xEDbrio qu\xEDmico" },
1970
+ { label: "vetor AB", snippet: "\\overrightarrow{}", titulo: "vetor entre dois pontos (AB)" },
1971
+ { label: "vetor", snippet: "\\vec{}", titulo: "vetor (f\xEDsica)" },
1972
+ { label: "\u2220", snippet: "\\angle", titulo: "\xE2ngulo" },
1973
+ { label: "\u25B3", snippet: "\\triangle", titulo: "tri\xE2ngulo" }
1974
+ ]
1975
+ }
1976
+ ];
1977
+ function paraMathlive(snippet) {
1978
+ return snippet.replaceAll("{}", "{#?}");
1979
+ }
1980
+ function paraMarkup(snippet) {
1981
+ return snippet.replaceAll("{}", "{\u25A1}");
1982
+ }
1983
+ function conteudoDoBotao(markup, snippet, label) {
1984
+ if (!markup) return { children: label };
1985
+ return { dangerouslySetInnerHTML: { __html: markup(paraMarkup(snippet)) } };
1986
+ }
1987
+
1988
+ // src/formulaGuarda.ts
1989
+ var PLACEHOLDER = "\\placeholder{}";
1990
+ var GRUPO_VAZIO = /\{\s*\}/;
1991
+ var CELULA_VAZIA = /(?:\\begin\{[a-zA-Z]+\*?\}|&|\\\\)\s*(?:&|\\\\|\\end\{)/;
1992
+ function podeInserir(latex, preview) {
1993
+ if (motivoBloqueio(latex, preview) !== null) return false;
1994
+ return latex.trim() !== "" && preview?.ok === true;
1995
+ }
1996
+ function motivoBloqueio(latex, preview) {
1997
+ if (latex.includes(PLACEHOLDER) || GRUPO_VAZIO.test(latex) || CELULA_VAZIA.test(latex)) {
1998
+ return "Preencha os campos em branco da f\xF3rmula.";
1999
+ }
2000
+ if (preview && !preview.ok) return preview.error ?? null;
2001
+ return null;
2002
+ }
2003
+
2004
+ // src/FormulaDialog.tsx
1695
2005
  var import_jsx_runtime6 = require("react/jsx-runtime");
1696
- var EditorContext = (0, import_react5.createContext)(null);
1697
- function EditorProvider({ editor, children }) {
1698
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(EditorContext.Provider, { value: editor, children: [
2006
+ var CIRCUNFLEXO_DE_TECLA_MORTA = /* @__PURE__ */ new Set(["\u02C6", "\u0302"]);
2007
+ function FormulaDialog({
2008
+ fontsDirectory
2009
+ }) {
2010
+ const { formulaRequest, resolveFormulaRequest } = useEditorContext();
2011
+ const dialogRef = (0, import_react5.useRef)(null);
2012
+ const hostRef = (0, import_react5.useRef)(null);
2013
+ const fieldRef = (0, import_react5.useRef)(null);
2014
+ const [latex, setLatex] = (0, import_react5.useState)("");
2015
+ const [display, setDisplay] = (0, import_react5.useState)(false);
2016
+ const [abaAtiva, setAbaAtiva] = (0, import_react5.useState)(0);
2017
+ (0, import_react5.useEffect)(() => {
2018
+ const dialog = dialogRef.current;
2019
+ if (!dialog) return;
2020
+ if (formulaRequest) {
2021
+ setLatex(formulaRequest.initialLatex);
2022
+ setDisplay(formulaRequest.initialDisplay);
2023
+ setAbaAtiva(0);
2024
+ if (!dialog.open) dialog.showModal();
2025
+ } else if (dialog.open) {
2026
+ dialog.close();
2027
+ }
2028
+ }, [formulaRequest]);
2029
+ const rendererRef = (0, import_react5.useRef)(null);
2030
+ const mathfieldCtorRef = (0, import_react5.useRef)(null);
2031
+ const markupRef = (0, import_react5.useRef)(null);
2032
+ const [preview, setPreview] = (0, import_react5.useState)(null);
2033
+ const [carregando, setCarregando] = (0, import_react5.useState)(false);
2034
+ const [erroCarregando, setErroCarregando] = (0, import_react5.useState)(null);
2035
+ (0, import_react5.useEffect)(() => {
2036
+ if (!formulaRequest || rendererRef.current) return;
2037
+ setCarregando(true);
2038
+ setErroCarregando(null);
2039
+ void Promise.all([import("@sofereditor/math"), import("mathlive")]).then(([math, mathlive]) => {
2040
+ rendererRef.current = math.renderLatexToSvg;
2041
+ mathfieldCtorRef.current = mathlive.MathfieldElement;
2042
+ markupRef.current = mathlive.convertLatexToMarkup;
2043
+ mathlive.MathfieldElement.soundsDirectory = null;
2044
+ if (fontsDirectory) {
2045
+ mathlive.MathfieldElement.fontsDirectory = fontsDirectory;
2046
+ }
2047
+ setCarregando(false);
2048
+ }).catch(() => {
2049
+ setCarregando(false);
2050
+ setErroCarregando(
2051
+ "N\xE3o foi poss\xEDvel carregar o editor de f\xF3rmulas. Recarregue a p\xE1gina e tente de novo."
2052
+ );
2053
+ });
2054
+ }, [formulaRequest]);
2055
+ (0, import_react5.useEffect)(() => {
2056
+ const render = rendererRef.current;
2057
+ if (!render || !latex.trim()) {
2058
+ setPreview(null);
2059
+ return;
2060
+ }
2061
+ setPreview(render(latex, display));
2062
+ }, [latex, display, carregando]);
2063
+ const onCircunflexoMorto = (0, import_react5.useCallback)((e) => {
2064
+ const ev = e;
2065
+ if (!ev.data || !CIRCUNFLEXO_DE_TECLA_MORTA.has(ev.data)) return;
2066
+ ev.preventDefault();
2067
+ ev.stopPropagation();
2068
+ fieldRef.current?.insert("^{#?}", { focus: true });
2069
+ }, []);
2070
+ (0, import_react5.useEffect)(() => {
2071
+ const Ctor = mathfieldCtorRef.current;
2072
+ const host = hostRef.current;
2073
+ if (!Ctor || !host || !formulaRequest) return;
2074
+ const mf = new Ctor();
2075
+ mf.className = "ed-formula-field";
2076
+ const onInput = () => setLatex(mf.getValue("latex"));
2077
+ mf.addEventListener("input", onInput);
2078
+ mf.addEventListener("beforeinput", onCircunflexoMorto, true);
2079
+ host.appendChild(mf);
2080
+ mf.mathVirtualKeyboardPolicy = "manual";
2081
+ mf.inlineShortcuts = {
2082
+ ...mf.inlineShortcuts,
2083
+ sen: "\\operatorname{sen}",
2084
+ tg: "\\operatorname{tg}",
2085
+ cotg: "\\operatorname{cotg}",
2086
+ // Vírgula decimal. Em modo matemático a vírgula crua é átomo de
2087
+ // pontuação e ganha espaço DEPOIS de si: digitar "3,14" sai impresso
2088
+ // como "3, 14" (medido: 4.4ex contra 4.023ex do agrupado). A paleta
2089
+ // tem um botão `{,}`, mas ninguém clica num botão para uma tecla que
2090
+ // está no teclado — e decimal aparece em toda prova de matemática,
2091
+ // física e química.
2092
+ //
2093
+ // O `after: "digit"` é o que separa os dois usos da vírgula, e foi
2094
+ // verificado no navegador: "3,14" vira `3{,}14` e "f(x,y)" continua
2095
+ // `f\left(x,y\right)`, com a vírgula de lista intacta — que é o
2096
+ // comportamento certo, ali ela É pontuação.
2097
+ ",": { after: "digit", value: "{,}" }
2098
+ };
2099
+ mf.setValue(formulaRequest.initialLatex);
2100
+ setLatex(mf.getValue("latex"));
2101
+ fieldRef.current = mf;
2102
+ queueMicrotask(() => mf.focus());
2103
+ return () => {
2104
+ mf.removeEventListener("input", onInput);
2105
+ mf.removeEventListener("beforeinput", onCircunflexoMorto, true);
2106
+ mf.remove();
2107
+ fieldRef.current = null;
2108
+ };
2109
+ }, [formulaRequest, carregando]);
2110
+ if (!formulaRequest) return null;
2111
+ const markup = markupRef.current;
2112
+ const motivo = motivoBloqueio(latex, preview);
2113
+ const podeSubmeter = podeInserir(latex, preview);
2114
+ const onSubmit = (e) => {
2115
+ e.preventDefault();
2116
+ if (!podeSubmeter) return;
2117
+ resolveFormulaRequest({ latex, display });
2118
+ };
2119
+ const onCancel = () => resolveFormulaRequest(null);
2120
+ const onPaleta = (snippet) => {
2121
+ const mf = fieldRef.current;
2122
+ if (!mf) return;
2123
+ mf.insert(paraMathlive(snippet), { focus: true });
2124
+ setLatex(mf.getValue("latex"));
2125
+ };
2126
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2127
+ "dialog",
2128
+ {
2129
+ ref: dialogRef,
2130
+ className: "ed-formula-dialog ed-link-dialog",
2131
+ style: DIALOG_CENTER_STYLE,
2132
+ onClose: onCancel,
2133
+ onCancel: (e) => {
2134
+ e.preventDefault();
2135
+ onCancel();
2136
+ },
2137
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("form", { onSubmit, className: "ed-formula-form", children: [
2138
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ed-formula-abas", role: "tablist", children: PALETA.map((cat, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2139
+ "button",
2140
+ {
2141
+ type: "button",
2142
+ role: "tab",
2143
+ "aria-selected": i === abaAtiva,
2144
+ className: "ed-formula-aba",
2145
+ onClick: () => setAbaAtiva(i),
2146
+ children: cat.nome
2147
+ },
2148
+ cat.nome
2149
+ )) }),
2150
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2151
+ "div",
2152
+ {
2153
+ className: "ed-formula-paleta",
2154
+ role: "tabpanel",
2155
+ style: { gridTemplateColumns: `repeat(${PALETA[abaAtiva].colunas}, 1fr)` },
2156
+ children: PALETA[abaAtiva].itens.map((p) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2157
+ "button",
2158
+ {
2159
+ type: "button",
2160
+ className: "ed-formula-paleta-btn",
2161
+ title: p.titulo ?? p.label,
2162
+ "aria-label": p.titulo ?? p.label,
2163
+ onClick: () => onPaleta(p.snippet),
2164
+ ...conteudoDoBotao(markup, p.snippet, p.label)
2165
+ },
2166
+ p.label
2167
+ ))
2168
+ }
2169
+ ),
2170
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: hostRef, className: "ed-formula-host" }),
2171
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "ed-formula-display", children: [
2172
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2173
+ "input",
2174
+ {
2175
+ type: "checkbox",
2176
+ checked: display,
2177
+ onChange: (e) => setDisplay(e.target.checked)
2178
+ }
2179
+ ),
2180
+ "F\xF3rmula em bloco (centralizada, limites acima e abaixo)"
2181
+ ] }),
2182
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ed-formula-preview", "aria-live": "polite", children: carregando ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "ed-formula-vazio", children: "Carregando o editor\u2026" }) : erroCarregando ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "ed-formula-erro", role: "alert", children: erroCarregando }) : motivo ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "ed-formula-erro", role: "alert", children: motivo }) : null }),
2183
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "ed-formula-acoes", children: [
2184
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", onClick: onCancel, children: "Cancelar" }),
2185
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "submit", disabled: !podeSubmeter, children: "Inserir" })
2186
+ ] })
2187
+ ] })
2188
+ }
2189
+ );
2190
+ }
2191
+
2192
+ // src/EditorContext.tsx
2193
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2194
+ var EditorContext = (0, import_react6.createContext)(null);
2195
+ function EditorProvider({
2196
+ editor,
2197
+ children,
2198
+ mathliveFontsDirectory
2199
+ }) {
2200
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(EditorContext.Provider, { value: editor, children: [
1699
2201
  children,
1700
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(LinkDialog, {}),
1701
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PageConfigDialog, {}),
1702
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ImageCaptionDialog, {})
2202
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LinkDialog, {}),
2203
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PageConfigDialog, {}),
2204
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ImageCaptionDialog, {}),
2205
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FormulaDialog, { fontsDirectory: mathliveFontsDirectory })
1703
2206
  ] });
1704
2207
  }
1705
2208
  function useEditorContext() {
1706
- const ctx = (0, import_react5.useContext)(EditorContext);
2209
+ const ctx = (0, import_react6.useContext)(EditorContext);
1707
2210
  if (!ctx) {
1708
2211
  throw new Error("useEditorContext must be used inside an <EditorProvider>");
1709
2212
  }
@@ -1711,8 +2214,8 @@ function useEditorContext() {
1711
2214
  }
1712
2215
 
1713
2216
  // src/ImageResizeOverlay.tsx
1714
- var import_react6 = require("react");
1715
- var import_jsx_runtime7 = require("react/jsx-runtime");
2217
+ var import_react7 = require("react");
2218
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1716
2219
  function ImageResizeOverlay({
1717
2220
  rootRef,
1718
2221
  blockIndex,
@@ -1723,10 +2226,10 @@ function ImageResizeOverlay({
1723
2226
  onCommitMove,
1724
2227
  onReanchor
1725
2228
  }) {
1726
- const [rect, setRect] = (0, import_react6.useState)(null);
1727
- const [isMoving, setIsMoving] = (0, import_react6.useState)(false);
1728
- const imgRef = (0, import_react6.useRef)(null);
1729
- const locateImage = (0, import_react6.useCallback)(() => {
2229
+ const [rect, setRect] = (0, import_react7.useState)(null);
2230
+ const [isMoving, setIsMoving] = (0, import_react7.useState)(false);
2231
+ const imgRef = (0, import_react7.useRef)(null);
2232
+ const locateImage = (0, import_react7.useCallback)(() => {
1730
2233
  const root = rootRef.current;
1731
2234
  if (!root) return null;
1732
2235
  let container = null;
@@ -1744,7 +2247,7 @@ function ImageResizeOverlay({
1744
2247
  `img[data-embed="image"][data-embed-offset="${localOffset}"]`
1745
2248
  );
1746
2249
  }, [rootRef, blockIndex, offset, cellIndex]);
1747
- const measure = (0, import_react6.useCallback)(() => {
2250
+ const measure = (0, import_react7.useCallback)(() => {
1748
2251
  const img = locateImage();
1749
2252
  if (!img) {
1750
2253
  setRect((prev) => prev === null ? prev : null);
@@ -1765,7 +2268,7 @@ function ImageResizeOverlay({
1765
2268
  (prev) => prev && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
1766
2269
  );
1767
2270
  }, [locateImage, rootRef]);
1768
- (0, import_react6.useLayoutEffect)(() => {
2271
+ (0, import_react7.useLayoutEffect)(() => {
1769
2272
  measure();
1770
2273
  let cancelled = false;
1771
2274
  let frame = 0;
@@ -1795,7 +2298,7 @@ function ImageResizeOverlay({
1795
2298
  embed.offsetX,
1796
2299
  embed.offsetY
1797
2300
  ]);
1798
- (0, import_react6.useEffect)(() => {
2301
+ (0, import_react7.useEffect)(() => {
1799
2302
  const root = rootRef.current;
1800
2303
  if (!root) return;
1801
2304
  const onScroll = () => measure();
@@ -1806,7 +2309,7 @@ function ImageResizeOverlay({
1806
2309
  root.removeEventListener("scroll", onScroll);
1807
2310
  };
1808
2311
  }, [measure, rootRef]);
1809
- (0, import_react6.useEffect)(() => {
2312
+ (0, import_react7.useEffect)(() => {
1810
2313
  if (typeof ResizeObserver === "undefined") return;
1811
2314
  const img = locateImage();
1812
2315
  const root = rootRef.current;
@@ -1819,7 +2322,7 @@ function ImageResizeOverlay({
1819
2322
  if (!rect) return null;
1820
2323
  const layout = embed.layout ?? "inline";
1821
2324
  const movable = layout !== "inline" && onCommitMove !== void 0;
1822
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2325
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1823
2326
  "div",
1824
2327
  {
1825
2328
  className: "ed-image-overlay",
@@ -1830,7 +2333,7 @@ function ImageResizeOverlay({
1830
2333
  // follows the cursor, so the image stays visible while it crosses the
1831
2334
  // page boundary (the real, clipped figure is hidden during the drag).
1832
2335
  // Inline styles only — the package does not ship CSS.
1833
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2336
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1834
2337
  "img",
1835
2338
  {
1836
2339
  src: embed.src,
@@ -1848,7 +2351,7 @@ function ImageResizeOverlay({
1848
2351
  }
1849
2352
  }
1850
2353
  ),
1851
- movable && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2354
+ movable && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1852
2355
  MoveHandle,
1853
2356
  {
1854
2357
  layout,
@@ -1866,7 +2369,7 @@ function ImageResizeOverlay({
1866
2369
  onMoveEnd: () => setIsMoving(false)
1867
2370
  }
1868
2371
  ),
1869
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2372
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1870
2373
  Handle,
1871
2374
  {
1872
2375
  corner: "nw",
@@ -1877,7 +2380,7 @@ function ImageResizeOverlay({
1877
2380
  onLiveChange: measure
1878
2381
  }
1879
2382
  ),
1880
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2383
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1881
2384
  Handle,
1882
2385
  {
1883
2386
  corner: "ne",
@@ -1888,7 +2391,7 @@ function ImageResizeOverlay({
1888
2391
  onLiveChange: measure
1889
2392
  }
1890
2393
  ),
1891
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2394
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1892
2395
  Handle,
1893
2396
  {
1894
2397
  corner: "sw",
@@ -1899,7 +2402,7 @@ function ImageResizeOverlay({
1899
2402
  onLiveChange: measure
1900
2403
  }
1901
2404
  ),
1902
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2405
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1903
2406
  Handle,
1904
2407
  {
1905
2408
  corner: "se",
@@ -1929,7 +2432,7 @@ function MoveHandle({
1929
2432
  onMoveStart,
1930
2433
  onMoveEnd
1931
2434
  }) {
1932
- const dragRef = (0, import_react6.useRef)(null);
2435
+ const dragRef = (0, import_react7.useRef)(null);
1933
2436
  const onPointerDown = (e) => {
1934
2437
  if (e.button !== 0) return;
1935
2438
  if (!imgRef.current) return;
@@ -2079,7 +2582,7 @@ function MoveHandle({
2079
2582
  newOffsetY
2080
2583
  );
2081
2584
  };
2082
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2585
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2083
2586
  "div",
2084
2587
  {
2085
2588
  className: "ed-image-move",
@@ -2099,7 +2602,7 @@ function Handle({
2099
2602
  onCommit,
2100
2603
  onLiveChange
2101
2604
  }) {
2102
- const dragRef = (0, import_react6.useRef)(null);
2605
+ const dragRef = (0, import_react7.useRef)(null);
2103
2606
  const onPointerDown = (e) => {
2104
2607
  if (e.button !== 0) return;
2105
2608
  if (!imgRef.current) return;
@@ -2142,7 +2645,7 @@ function Handle({
2142
2645
  }
2143
2646
  onCommit(Math.round(d.liveW), Math.round(d.liveH));
2144
2647
  };
2145
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2648
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2146
2649
  "div",
2147
2650
  {
2148
2651
  className: `ed-image-handle ${corner}`,
@@ -2155,9 +2658,9 @@ function Handle({
2155
2658
  }
2156
2659
 
2157
2660
  // src/RemoteCursorsOverlay.tsx
2158
- var import_react7 = require("react");
2159
- var import_core4 = require("@sofereditor/core");
2160
- var import_jsx_runtime8 = require("react/jsx-runtime");
2661
+ var import_react8 = require("react");
2662
+ var import_core5 = require("@sofereditor/core");
2663
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2161
2664
  var DEFAULT_COLOR = "#3b82f6";
2162
2665
  function RemoteCursorsOverlay({
2163
2666
  rootRef,
@@ -2165,9 +2668,9 @@ function RemoteCursorsOverlay({
2165
2668
  awareness,
2166
2669
  revision
2167
2670
  }) {
2168
- const [views, setViews] = (0, import_react7.useState)([]);
2169
- const rafRef = (0, import_react7.useRef)(null);
2170
- const measure = (0, import_react7.useCallback)(() => {
2671
+ const [views, setViews] = (0, import_react8.useState)([]);
2672
+ const rafRef = (0, import_react8.useRef)(null);
2673
+ const measure = (0, import_react8.useCallback)(() => {
2171
2674
  const root = rootRef.current;
2172
2675
  if (!root) {
2173
2676
  setViews((prev) => prev.length === 0 ? prev : []);
@@ -2179,7 +2682,7 @@ function RemoteCursorsOverlay({
2179
2682
  if (clientId === awareness.clientID) return;
2180
2683
  const s = state;
2181
2684
  if (!s.cursor) return;
2182
- const sel = (0, import_core4.decodeSelection)(doc, s.cursor);
2685
+ const sel = (0, import_core5.decodeSelection)(doc, s.cursor);
2183
2686
  if (!sel) return;
2184
2687
  const color = s.user?.color || DEFAULT_COLOR;
2185
2688
  const name = s.user?.name || "An\xF4nimo";
@@ -2232,7 +2735,7 @@ function RemoteCursorsOverlay({
2232
2735
  });
2233
2736
  setViews(out);
2234
2737
  }, [rootRef, doc, awareness]);
2235
- const scheduleMeasure = (0, import_react7.useCallback)(() => {
2738
+ const scheduleMeasure = (0, import_react8.useCallback)(() => {
2236
2739
  if (rafRef.current != null) return;
2237
2740
  const raf = typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb) => setTimeout(() => cb(0), 16);
2238
2741
  rafRef.current = raf(() => {
@@ -2240,16 +2743,16 @@ function RemoteCursorsOverlay({
2240
2743
  measure();
2241
2744
  });
2242
2745
  }, [measure]);
2243
- (0, import_react7.useEffect)(() => {
2746
+ (0, import_react8.useEffect)(() => {
2244
2747
  const onChange = () => scheduleMeasure();
2245
2748
  awareness.on("change", onChange);
2246
2749
  scheduleMeasure();
2247
2750
  return () => awareness.off("change", onChange);
2248
2751
  }, [awareness, scheduleMeasure]);
2249
- (0, import_react7.useEffect)(() => {
2752
+ (0, import_react8.useEffect)(() => {
2250
2753
  scheduleMeasure();
2251
2754
  }, [revision, scheduleMeasure]);
2252
- (0, import_react7.useEffect)(() => {
2755
+ (0, import_react8.useEffect)(() => {
2253
2756
  const root = rootRef.current;
2254
2757
  if (!root) return;
2255
2758
  const onScroll = () => scheduleMeasure();
@@ -2271,8 +2774,8 @@ function RemoteCursorsOverlay({
2271
2774
  pointerEvents: "none",
2272
2775
  zIndex: 6
2273
2776
  };
2274
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "ed-remote-cursors", "aria-hidden": true, style: layer, children: views.map((v) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
2275
- v.selection.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2777
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "ed-remote-cursors", "aria-hidden": true, style: layer, children: views.map((v) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
2778
+ v.selection.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2276
2779
  "div",
2277
2780
  {
2278
2781
  style: {
@@ -2288,7 +2791,7 @@ function RemoteCursorsOverlay({
2288
2791
  },
2289
2792
  i
2290
2793
  )),
2291
- v.caret && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2794
+ v.caret && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2292
2795
  "div",
2293
2796
  {
2294
2797
  style: {
@@ -2299,7 +2802,7 @@ function RemoteCursorsOverlay({
2299
2802
  width: 2,
2300
2803
  background: v.color
2301
2804
  },
2302
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2805
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2303
2806
  "span",
2304
2807
  {
2305
2808
  style: {
@@ -2325,16 +2828,16 @@ function RemoteCursorsOverlay({
2325
2828
  }
2326
2829
 
2327
2830
  // src/NodeView.tsx
2328
- var import_react10 = require("react");
2329
- var import_core6 = require("@sofereditor/core");
2831
+ var import_react11 = require("react");
2832
+ var import_core8 = require("@sofereditor/core");
2330
2833
 
2331
2834
  // src/renderInline.tsx
2332
- var import_react8 = require("react");
2333
- var import_core5 = require("@sofereditor/core");
2334
- var import_jsx_runtime9 = require("react/jsx-runtime");
2835
+ var import_react9 = require("react");
2836
+ var import_core6 = require("@sofereditor/core");
2837
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2335
2838
  function renderInline(delta, keyPrefix) {
2336
2839
  if (delta.length === 0 || delta.length === 1 && typeof delta[0].insert === "string" && delta[0].insert === "") {
2337
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("br", { "data-empty": "true" });
2840
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("br", { "data-empty": "true" });
2338
2841
  }
2339
2842
  let offset = 0;
2340
2843
  const wrapAnchors = [];
@@ -2344,18 +2847,18 @@ function renderInline(delta, keyPrefix) {
2344
2847
  const text = op.insert;
2345
2848
  if (text.length === 0) continue;
2346
2849
  const key = `${keyPrefix}-${offset}`;
2347
- body.push(/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react8.Fragment, { children: wrap(text, op.attributes) }, key));
2850
+ body.push(/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react9.Fragment, { children: wrap(text, op.attributes) }, key));
2348
2851
  offset += text.length;
2349
- } else if ((0, import_core5.isImageEmbed)(op.insert)) {
2852
+ } else if ((0, import_core6.isImageEmbed)(op.insert)) {
2350
2853
  const key = `${keyPrefix}-${offset}`;
2351
2854
  const layout = op.insert.layout ?? "inline";
2352
2855
  const commentMarkId = op.attributes?.comment?.markId;
2353
2856
  if (layout === "wrap-left" || layout === "wrap-right") {
2354
2857
  wrapAnchors.push(
2355
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ImageEmbedView, { embed: op.insert, offset, wrapAnchor: true }, `${key}-anchor`)
2858
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ImageEmbedView, { embed: op.insert, offset, wrapAnchor: true }, `${key}-anchor`)
2356
2859
  );
2357
2860
  body.push(
2358
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2861
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2359
2862
  "span",
2360
2863
  {
2361
2864
  "data-embed-phantom": "true",
@@ -2367,10 +2870,10 @@ function renderInline(delta, keyPrefix) {
2367
2870
  )
2368
2871
  );
2369
2872
  } else {
2370
- const imgNode = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ImageEmbedView, { embed: op.insert, offset }, key);
2873
+ const imgNode = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ImageEmbedView, { embed: op.insert, offset }, key);
2371
2874
  if (commentMarkId) {
2372
2875
  body.push(
2373
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-comment-id": commentMarkId, className: "ed-comment", children: imgNode }, `${key}-cmt`)
2876
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "data-comment-id": commentMarkId, className: "ed-comment", children: imgNode }, `${key}-cmt`)
2374
2877
  );
2375
2878
  } else {
2376
2879
  body.push(imgNode);
@@ -2381,7 +2884,7 @@ function renderInline(delta, keyPrefix) {
2381
2884
  offset += 1;
2382
2885
  }
2383
2886
  }
2384
- if (wrapAnchors.length === 0 && body.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("br", { "data-empty": "true" });
2887
+ if (wrapAnchors.length === 0 && body.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("br", { "data-empty": "true" });
2385
2888
  return [...wrapAnchors, ...body];
2386
2889
  }
2387
2890
  var PHANTOM_STYLE = {
@@ -2406,7 +2909,7 @@ function imageEmbedPropsEqual(a, b) {
2406
2909
  // because Y.js stores the embed in its content map and re-exposes it.
2407
2910
  x.src === y.src;
2408
2911
  }
2409
- var ImageEmbedView = (0, import_react8.memo)(ImageEmbedViewImpl, imageEmbedPropsEqual);
2912
+ var ImageEmbedView = (0, import_react9.memo)(ImageEmbedViewImpl, imageEmbedPropsEqual);
2410
2913
  function ImageEmbedViewImpl({
2411
2914
  embed,
2412
2915
  offset,
@@ -2456,7 +2959,9 @@ function ImageEmbedViewImpl({
2456
2959
  marginRight: align === "right" ? 0 : "auto"
2457
2960
  } : {
2458
2961
  display: "inline-block",
2459
- verticalAlign: "text-bottom",
2962
+ // Fórmula inline traz o deslocamento de base que o MathJax mediu;
2963
+ // sem ele a fórmula flutua no topo da linha em vez de sentar nela.
2964
+ verticalAlign: embed.formula?.vAlign ?? "text-bottom",
2460
2965
  width: embed.width
2461
2966
  };
2462
2967
  break;
@@ -2466,7 +2971,7 @@ function ImageEmbedViewImpl({
2466
2971
  height: embed.height,
2467
2972
  display: "block"
2468
2973
  };
2469
- const img = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2974
+ const img = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2470
2975
  "img",
2471
2976
  {
2472
2977
  src: embed.src,
@@ -2486,7 +2991,7 @@ function ImageEmbedViewImpl({
2486
2991
  }
2487
2992
  );
2488
2993
  const captionAlign = embed.captionAlign ?? "center";
2489
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2994
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2490
2995
  "figure",
2491
2996
  {
2492
2997
  className: "ed-figure",
@@ -2496,7 +3001,7 @@ function ImageEmbedViewImpl({
2496
3001
  style: outerStyle,
2497
3002
  children: [
2498
3003
  img,
2499
- hasCaption && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3004
+ hasCaption && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2500
3005
  "figcaption",
2501
3006
  {
2502
3007
  className: "ed-figcaption",
@@ -2510,29 +3015,29 @@ function ImageEmbedViewImpl({
2510
3015
  );
2511
3016
  }
2512
3017
  function decorateBlanks(text) {
2513
- const segs = (0, import_core5.splitUnderscoreRuns)(text);
3018
+ const segs = (0, import_core6.splitUnderscoreRuns)(text);
2514
3019
  if (segs.length === 1 && !segs[0].blank) return text;
2515
3020
  return segs.map(
2516
- (s, i) => s.blank ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-blank": "true", style: import_core5.BLANK_STYLE, children: s.text }, i) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react8.Fragment, { children: s.text }, i)
3021
+ (s, i) => s.blank ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "data-blank": "true", style: import_core6.BLANK_STYLE, children: s.text }, i) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react9.Fragment, { children: s.text }, i)
2517
3022
  );
2518
3023
  }
2519
3024
  function wrap(text, attrs) {
2520
3025
  let node = decorateBlanks(text);
2521
3026
  if (!attrs) return node;
2522
- if (attrs.bold) node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: node });
2523
- if (attrs.italic) node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("em", { children: node });
2524
- if (attrs.underline) node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("u", { children: node });
2525
- if (attrs.strike) node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("s", { children: node });
3027
+ if (attrs.bold) node = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { children: node });
3028
+ if (attrs.italic) node = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("em", { children: node });
3029
+ if (attrs.underline) node = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("u", { children: node });
3030
+ if (attrs.strike) node = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("s", { children: node });
2526
3031
  const styleParts = {};
2527
3032
  if (attrs.color) styleParts.color = attrs.color;
2528
3033
  if (attrs.highlight) styleParts.backgroundColor = attrs.highlight;
2529
3034
  if (attrs.fontFamily) styleParts.fontFamily = attrs.fontFamily;
2530
3035
  if (attrs.fontSize) styleParts.fontSize = attrs.fontSize;
2531
3036
  if (Object.keys(styleParts).length > 0) {
2532
- node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: styleParts, children: node });
3037
+ node = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: styleParts, children: node });
2533
3038
  }
2534
3039
  if (attrs.link?.href) {
2535
- node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3040
+ node = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2536
3041
  "a",
2537
3042
  {
2538
3043
  href: attrs.link.href,
@@ -2551,7 +3056,7 @@ function wrap(text, attrs) {
2551
3056
  );
2552
3057
  }
2553
3058
  if (attrs.comment?.markId) {
2554
- node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-comment-id": attrs.comment.markId, className: "ed-comment", children: node });
3059
+ node = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "data-comment-id": attrs.comment.markId, className: "ed-comment", children: node });
2555
3060
  }
2556
3061
  return node;
2557
3062
  }
@@ -2595,16 +3100,25 @@ function sliceDelta(delta, start, end) {
2595
3100
  }
2596
3101
 
2597
3102
  // src/TableResizeOverlay.tsx
2598
- var import_react9 = require("react");
2599
- var import_jsx_runtime10 = require("react/jsx-runtime");
2600
- function TableResizeOverlay({ tableRef, blockIndex, cols }) {
3103
+ var import_react10 = require("react");
3104
+ var import_core7 = require("@sofereditor/core");
3105
+ var import_jsx_runtime11 = require("react/jsx-runtime");
3106
+ function deltaPctDoArrasto(dxPx, larguraTabelaPx) {
3107
+ if (!(larguraTabelaPx > 0)) return 0;
3108
+ return dxPx / larguraTabelaPx * 100;
3109
+ }
3110
+ function distribuirAltura(base, deltaPx) {
3111
+ if (base.length === 0) return base;
3112
+ const fatia = deltaPx / base.length;
3113
+ return base.map((h) => Math.max(import_core7.MIN_LINHA_PX, Math.round(h + fatia)));
3114
+ }
3115
+ function TableResizeOverlay({ tableRef, blockIndex, cols, rows }) {
2601
3116
  const editor = useEditorContext();
2602
- const [positions, setPositions] = (0, import_react9.useState)(null);
2603
- const [layout, setLayout] = (0, import_react9.useState)(null);
2604
- const draggingRef = (0, import_react9.useRef)(null);
2605
- const measure = (0, import_react9.useCallback)(() => {
3117
+ const [layout, setLayout] = (0, import_react10.useState)(null);
3118
+ const arrastoRef = (0, import_react10.useRef)(null);
3119
+ const measureNow = (0, import_react10.useCallback)(() => {
2606
3120
  const table = tableRef.current;
2607
- if (!table) return;
3121
+ if (!table) return null;
2608
3122
  const tableRect = table.getBoundingClientRect();
2609
3123
  const cgCols = table.querySelectorAll("colgroup > col");
2610
3124
  let rights = [];
@@ -2627,55 +3141,160 @@ function TableResizeOverlay({ tableRef, blockIndex, cols }) {
2627
3141
  });
2628
3142
  }
2629
3143
  if (rights.length !== cols) {
2630
- setLayout(null);
2631
- return;
3144
+ return null;
2632
3145
  }
2633
- setLayout({ rights, height: tableRect.height });
2634
- }, [cols, tableRef]);
2635
- (0, import_react9.useLayoutEffect)(() => {
3146
+ const trs = table.querySelectorAll("tbody > tr");
3147
+ const bottoms = [];
3148
+ let accY = 0;
3149
+ trs.forEach((tr) => {
3150
+ accY += tr.getBoundingClientRect().height;
3151
+ bottoms.push(accY);
3152
+ });
3153
+ return {
3154
+ rights,
3155
+ bottoms: trs.length === rows ? bottoms : [],
3156
+ width: tableRect.width,
3157
+ height: tableRect.height
3158
+ };
3159
+ }, [cols, rows, tableRef]);
3160
+ const measure = (0, import_react10.useCallback)(() => {
3161
+ setLayout(measureNow());
3162
+ }, [measureNow]);
3163
+ (0, import_react10.useLayoutEffect)(() => {
2636
3164
  measure();
2637
3165
  }, [measure]);
2638
- (0, import_react9.useEffect)(() => {
3166
+ (0, import_react10.useEffect)(() => {
2639
3167
  const table = tableRef.current;
2640
3168
  if (!table) return;
2641
3169
  const ro = new ResizeObserver(() => measure());
2642
3170
  ro.observe(table);
2643
3171
  return () => ro.disconnect();
2644
3172
  }, [measure, tableRef]);
2645
- const onPointerDown = (0, import_react9.useCallback)(
2646
- (col) => (e) => {
3173
+ const onPointerUp = (0, import_react10.useCallback)(
3174
+ (e) => {
3175
+ arrastoRef.current = null;
3176
+ measure();
3177
+ try {
3178
+ e.currentTarget.releasePointerCapture(e.pointerId);
3179
+ } catch {
3180
+ }
3181
+ },
3182
+ [measure]
3183
+ );
3184
+ const onPointerMove = (0, import_react10.useCallback)(
3185
+ (e) => {
3186
+ const d = arrastoRef.current;
3187
+ if (!d) return;
3188
+ switch (d.tipo) {
3189
+ case "coluna": {
3190
+ const dPct = deltaPctDoArrasto(e.clientX - d.startX, d.tableWidthPx);
3191
+ editor.setColumnBoundary(blockIndex, d.boundary, dPct, d.baseWidths);
3192
+ break;
3193
+ }
3194
+ case "larguraTotal": {
3195
+ const dPct = deltaPctDoArrasto(e.clientX - d.startX, d.utilPx);
3196
+ editor.setTableWidth(blockIndex, d.baseWidthPct + dPct);
3197
+ break;
3198
+ }
3199
+ case "linha": {
3200
+ editor.setRowHeight(blockIndex, d.row, d.baseHeightPx + (e.clientY - d.startY));
3201
+ break;
3202
+ }
3203
+ case "alturaTotal": {
3204
+ editor.setRowHeights(blockIndex, distribuirAltura(d.baseHeights, e.clientY - d.startY));
3205
+ break;
3206
+ }
3207
+ case "canto": {
3208
+ const dPct = deltaPctDoArrasto(e.clientX - d.startX, d.utilPx);
3209
+ editor.setTableWidth(blockIndex, d.baseWidthPct + dPct);
3210
+ editor.setRowHeights(blockIndex, distribuirAltura(d.baseHeights, e.clientY - d.startY));
3211
+ break;
3212
+ }
3213
+ }
3214
+ },
3215
+ [blockIndex, editor]
3216
+ );
3217
+ const containerWidthPxOf = (0, import_react10.useCallback)((table, tableWidthPx) => {
3218
+ return table.parentElement?.getBoundingClientRect().width || tableWidthPx;
3219
+ }, []);
3220
+ const onColumnPointerDown = (0, import_react10.useCallback)(
3221
+ (boundary) => (e) => {
2647
3222
  e.preventDefault();
2648
3223
  e.stopPropagation();
2649
3224
  const table = tableRef.current;
2650
3225
  if (!table) return;
2651
- const cgCols = table.querySelectorAll("colgroup > col");
2652
- const startWidth = cgCols[col]?.getBoundingClientRect().width ?? 100;
2653
- draggingRef.current = { col, startX: e.clientX, startWidth };
2654
- setPositions({ x: e.clientX, height: layout?.height ?? 0 });
3226
+ const tableWidthPx = table.getBoundingClientRect().width || 1;
3227
+ const attrs = editor.doc.getBlockAttrs(blockIndex);
3228
+ const baseWidths = (0, import_core7.normalizarLarguras)(attrs.colWidths, cols);
3229
+ arrastoRef.current = { tipo: "coluna", boundary, startX: e.clientX, baseWidths, tableWidthPx };
2655
3230
  e.currentTarget.setPointerCapture(e.pointerId);
2656
3231
  },
2657
- [layout, tableRef]
3232
+ [tableRef, editor, blockIndex, cols]
2658
3233
  );
2659
- const onPointerMove = (0, import_react9.useCallback)(
3234
+ const onTableWidthPointerDown = (0, import_react10.useCallback)(
2660
3235
  (e) => {
2661
- const d = draggingRef.current;
2662
- if (!d) return;
2663
- const dx = e.clientX - d.startX;
2664
- const next = Math.max(40, d.startWidth + dx);
2665
- editor.setColumnWidth(blockIndex, d.col, next);
3236
+ e.preventDefault();
3237
+ e.stopPropagation();
3238
+ const table = tableRef.current;
3239
+ if (!table) return;
3240
+ const tableWidthPx = table.getBoundingClientRect().width || 1;
3241
+ const utilPx = containerWidthPxOf(table, tableWidthPx);
3242
+ const attrs = editor.doc.getBlockAttrs(blockIndex);
3243
+ const baseWidthPct = typeof attrs.tableWidth === "number" ? attrs.tableWidth : 100;
3244
+ arrastoRef.current = { tipo: "larguraTotal", startX: e.clientX, baseWidthPct, utilPx };
3245
+ e.currentTarget.setPointerCapture(e.pointerId);
2666
3246
  },
2667
- [blockIndex, editor]
3247
+ [tableRef, editor, blockIndex, containerWidthPxOf]
3248
+ );
3249
+ const heightsFromBottoms = (bottoms) => bottoms.map((b, i) => b - (i === 0 ? 0 : bottoms[i - 1]));
3250
+ const onRowPointerDown = (0, import_react10.useCallback)(
3251
+ (row) => (e) => {
3252
+ e.preventDefault();
3253
+ e.stopPropagation();
3254
+ const m = measureNow();
3255
+ if (!m || m.bottoms.length === 0) return;
3256
+ const baseHeightPx = m.bottoms[row] - (row === 0 ? 0 : m.bottoms[row - 1]);
3257
+ arrastoRef.current = { tipo: "linha", row, startY: e.clientY, baseHeightPx };
3258
+ e.currentTarget.setPointerCapture(e.pointerId);
3259
+ },
3260
+ [measureNow]
3261
+ );
3262
+ const onTableHeightPointerDown = (0, import_react10.useCallback)(
3263
+ (e) => {
3264
+ e.preventDefault();
3265
+ e.stopPropagation();
3266
+ const m = measureNow();
3267
+ if (!m || m.bottoms.length === 0) return;
3268
+ arrastoRef.current = { tipo: "alturaTotal", startY: e.clientY, baseHeights: heightsFromBottoms(m.bottoms) };
3269
+ e.currentTarget.setPointerCapture(e.pointerId);
3270
+ },
3271
+ [measureNow]
3272
+ );
3273
+ const onCornerPointerDown = (0, import_react10.useCallback)(
3274
+ (e) => {
3275
+ e.preventDefault();
3276
+ e.stopPropagation();
3277
+ const table = tableRef.current;
3278
+ const m = measureNow();
3279
+ if (!table || !m) return;
3280
+ const tableWidthPx = table.getBoundingClientRect().width || 1;
3281
+ const utilPx = containerWidthPxOf(table, tableWidthPx);
3282
+ const attrs = editor.doc.getBlockAttrs(blockIndex);
3283
+ const baseWidthPct = typeof attrs.tableWidth === "number" ? attrs.tableWidth : 100;
3284
+ arrastoRef.current = {
3285
+ tipo: "canto",
3286
+ startX: e.clientX,
3287
+ startY: e.clientY,
3288
+ baseWidthPct,
3289
+ utilPx,
3290
+ baseHeights: heightsFromBottoms(m.bottoms)
3291
+ };
3292
+ e.currentTarget.setPointerCapture(e.pointerId);
3293
+ },
3294
+ [tableRef, editor, blockIndex, measureNow, containerWidthPxOf]
2668
3295
  );
2669
- const onPointerUp = (0, import_react9.useCallback)((e) => {
2670
- draggingRef.current = null;
2671
- setPositions(null);
2672
- try {
2673
- e.currentTarget.releasePointerCapture(e.pointerId);
2674
- } catch {
2675
- }
2676
- }, []);
2677
3296
  if (!layout) return null;
2678
- const handleStyle = (x) => ({
3297
+ const colHandleStyle = (x) => ({
2679
3298
  position: "absolute",
2680
3299
  top: 0,
2681
3300
  left: `${x - 3}px`,
@@ -2684,28 +3303,104 @@ function TableResizeOverlay({ tableRef, blockIndex, cols }) {
2684
3303
  cursor: "col-resize",
2685
3304
  zIndex: 5
2686
3305
  });
2687
- void positions;
2688
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: layout.rights.map((x, c) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2689
- "div",
2690
- {
2691
- contentEditable: false,
2692
- className: "ed-col-resize-handle",
2693
- style: handleStyle(x),
2694
- onPointerDown: onPointerDown(c),
2695
- onPointerMove,
2696
- onPointerUp,
2697
- "aria-label": `Redimensionar coluna ${c + 1}`,
2698
- role: "separator"
2699
- },
2700
- c
2701
- )) });
3306
+ const rowHandleStyle = (y) => ({
3307
+ position: "absolute",
3308
+ left: 0,
3309
+ top: `${y - 3}px`,
3310
+ width: `${layout.width}px`,
3311
+ height: "6px",
3312
+ cursor: "row-resize",
3313
+ zIndex: 5
3314
+ });
3315
+ const cornerHandleStyle = {
3316
+ position: "absolute",
3317
+ left: `${layout.width - 5}px`,
3318
+ top: `${layout.height - 5}px`,
3319
+ width: "10px",
3320
+ height: "10px",
3321
+ cursor: "nwse-resize",
3322
+ zIndex: 6
3323
+ };
3324
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
3325
+ layout.rights.map(
3326
+ (x, c) => c < cols - 1 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3327
+ "div",
3328
+ {
3329
+ contentEditable: false,
3330
+ className: "ed-col-resize-handle",
3331
+ style: colHandleStyle(x),
3332
+ onPointerDown: onColumnPointerDown(c),
3333
+ onPointerMove,
3334
+ onPointerUp,
3335
+ "aria-label": `Redimensionar coluna ${c + 1}`,
3336
+ role: "separator"
3337
+ },
3338
+ `col-${c}`
3339
+ ) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3340
+ "div",
3341
+ {
3342
+ contentEditable: false,
3343
+ className: "ed-col-resize-handle",
3344
+ style: colHandleStyle(x),
3345
+ onPointerDown: onTableWidthPointerDown,
3346
+ onPointerMove,
3347
+ onPointerUp,
3348
+ "aria-label": "Largura da tabela",
3349
+ role: "separator"
3350
+ },
3351
+ "col-total"
3352
+ )
3353
+ ),
3354
+ layout.bottoms.map(
3355
+ (y, r) => r < rows - 1 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3356
+ "div",
3357
+ {
3358
+ contentEditable: false,
3359
+ className: "ed-row-resize-handle",
3360
+ style: rowHandleStyle(y),
3361
+ onPointerDown: onRowPointerDown(r),
3362
+ onPointerMove,
3363
+ onPointerUp,
3364
+ "aria-label": `Redimensionar linha ${r + 1}`,
3365
+ role: "separator"
3366
+ },
3367
+ `row-${r}`
3368
+ ) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3369
+ "div",
3370
+ {
3371
+ contentEditable: false,
3372
+ className: "ed-row-resize-handle",
3373
+ style: rowHandleStyle(y),
3374
+ onPointerDown: onTableHeightPointerDown,
3375
+ onPointerMove,
3376
+ onPointerUp,
3377
+ "aria-label": "Altura da tabela",
3378
+ role: "separator"
3379
+ },
3380
+ "row-total"
3381
+ )
3382
+ ),
3383
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3384
+ "div",
3385
+ {
3386
+ contentEditable: false,
3387
+ className: "ed-table-corner-handle",
3388
+ style: cornerHandleStyle,
3389
+ onPointerDown: onCornerPointerDown,
3390
+ onPointerMove,
3391
+ onPointerUp,
3392
+ "aria-label": "Redimensionar tabela",
3393
+ role: "separator"
3394
+ }
3395
+ )
3396
+ ] });
2702
3397
  }
2703
3398
 
2704
3399
  // src/NodeView.tsx
2705
- var import_jsx_runtime11 = require("react/jsx-runtime");
3400
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2706
3401
  function NodeView({ block, index, children, fragment, tableFragment }) {
2707
3402
  if (block.type === "table") {
2708
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TableView, { block, index, tableFragment });
3403
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableView, { block, index, tableFragment });
2709
3404
  }
2710
3405
  const inline = fragment ? renderInline(sliceDelta(block.delta, fragment.start, fragment.end), index) : renderInline(block.delta, index);
2711
3406
  const common = commonBlockProps(block.attrs, index, block.type, fragment);
@@ -2713,7 +3408,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2713
3408
  case "heading": {
2714
3409
  const level = clampLevel2(block.attrs.level);
2715
3410
  const Tag = `h${level}`;
2716
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3411
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2717
3412
  Tag,
2718
3413
  {
2719
3414
  ...common,
@@ -2723,7 +3418,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2723
3418
  );
2724
3419
  }
2725
3420
  case "blockquote":
2726
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3421
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2727
3422
  "blockquote",
2728
3423
  {
2729
3424
  ...common,
@@ -2732,18 +3427,18 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2732
3427
  }
2733
3428
  );
2734
3429
  case "codeBlock":
2735
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3430
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2736
3431
  "pre",
2737
3432
  {
2738
3433
  ...common,
2739
3434
  "data-language": block.attrs.language ?? void 0,
2740
3435
  className: `ed-block ed-codeblock${alignClass(block.attrs.align)}`,
2741
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("code", { children: inline })
3436
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("code", { children: inline })
2742
3437
  }
2743
3438
  );
2744
3439
  case "listItem": {
2745
3440
  const level = clampListLevel(block.attrs.listLevel);
2746
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3441
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2747
3442
  "li",
2748
3443
  {
2749
3444
  ...common,
@@ -2759,7 +3454,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2759
3454
  }
2760
3455
  case "paragraph":
2761
3456
  default:
2762
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3457
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2763
3458
  "div",
2764
3459
  {
2765
3460
  ...common,
@@ -2772,7 +3467,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2772
3467
  function commonBlockProps(attrs, index, type, fragment) {
2773
3468
  const style = {};
2774
3469
  if (attrs.align) style.textAlign = attrs.align;
2775
- Object.assign(style, (0, import_core6.answerLineStyle)(attrs) ?? {});
3470
+ Object.assign(style, (0, import_core8.answerLineStyle)(attrs) ?? {});
2776
3471
  const base = {
2777
3472
  "data-block-index": index,
2778
3473
  "data-block-type": type,
@@ -2810,80 +3505,82 @@ function TableView({ block, index, tableFragment }) {
2810
3505
  const rows = clampPositive(block.attrs.rows);
2811
3506
  const cols = clampPositive(block.attrs.cols);
2812
3507
  const cells = block.cells ?? [];
2813
- const widths = readColWidths(block.attrs.colWidths, cols);
2814
- const tableRef = (0, import_react10.useRef)(null);
3508
+ const widths = (0, import_core8.normalizarLarguras)(block.attrs.colWidths, cols);
3509
+ const tableWidth = block.attrs.tableWidth;
3510
+ const rowHeights = block.attrs.rowHeights;
3511
+ const tableRef = (0, import_react11.useRef)(null);
2815
3512
  const rowStart = tableFragment?.rowStart ?? 0;
2816
3513
  const rowEnd = tableFragment?.rowEnd ?? rows;
2817
3514
  const isFirstFragment = !tableFragment || tableFragment.index === 0;
2818
3515
  const editor = useEditorContext();
2819
- const rect = (0, import_react10.useMemo)(() => {
3516
+ const rect = (0, import_react11.useMemo)(() => {
2820
3517
  if (editor.selection.anchor.blockIndex !== index) return null;
2821
3518
  if (editor.selection.focus.blockIndex !== index) return null;
2822
- return (0, import_core6.tableRectSelection)(editor.doc, editor.selection);
3519
+ return (0, import_core8.tableRectSelection)(editor.doc, editor.selection);
2823
3520
  }, [editor.doc, editor.selection, index]);
2824
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ed-table-wrap", children: [
2825
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3521
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ed-table-wrap", children: [
3522
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2826
3523
  "table",
2827
3524
  {
2828
3525
  ref: tableRef,
2829
3526
  "data-block-index": index,
2830
3527
  "data-block-type": "table",
2831
3528
  className: "ed-block ed-table",
3529
+ style: typeof tableWidth === "number" ? { width: `${tableWidth}%` } : void 0,
2832
3530
  children: [
2833
- widths && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("colgroup", { children: widths.map((w, c) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("col", { style: w != null ? { width: `${w}px` } : void 0 }, c)) }),
2834
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", { children: Array.from({ length: rowEnd - rowStart }, (_, i) => {
3531
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("colgroup", { children: widths.map((w, c) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("col", { style: { width: `${w}%` } }, c)) }),
3532
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("tbody", { children: Array.from({ length: rowEnd - rowStart }, (_, i) => {
2835
3533
  const r = rowStart + i;
2836
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tr", { "data-cell-row": r, children: Array.from({ length: cols }, (_2, c) => {
2837
- const flat = r * cols + c;
2838
- const cell = cells[flat];
2839
- if (cell?.attrs.covered === true) return null;
2840
- const rowspan = spanAttr(cell?.attrs.rowspan);
2841
- const colspan = spanAttr(cell?.attrs.colspan);
2842
- const delta = cell?.delta ?? [];
2843
- const inRect = rect !== null && r >= rect.top && r <= rect.bottom && c >= rect.left && c <= rect.right;
2844
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2845
- "td",
2846
- {
2847
- "data-cell-index": flat,
2848
- "data-cell-row": r,
2849
- "data-cell-col": c,
2850
- "data-cell-rowspan": rowspan,
2851
- "data-cell-colspan": colspan,
2852
- rowSpan: rowspan > 1 ? rowspan : void 0,
2853
- colSpan: colspan > 1 ? colspan : void 0,
2854
- style: cellStyle(
2855
- cell?.attrs,
2856
- // rowStart/rowEnd são os limites do FRAGMENTO: numa tabela
2857
- // quebrada entre páginas, cada página fecha a própria caixa.
2858
- (0, import_core6.cellBorderStyle)(
2859
- block.attrs.borderPreset,
2860
- { row: r, col: c, rowspan, colspan, cols, rowStart, rowEnd },
2861
- "screen",
2862
- block.attrs.borderColor
2863
- )
2864
- ),
2865
- className: inRect ? "ed-cell ed-cell--selected" : "ed-cell",
2866
- children: renderInline(delta, `t${index}-c${flat}`)
2867
- },
2868
- c
2869
- );
2870
- }) }, r);
3534
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3535
+ "tr",
3536
+ {
3537
+ "data-cell-row": r,
3538
+ style: typeof rowHeights?.[r] === "number" ? { height: `${rowHeights[r]}px` } : void 0,
3539
+ children: Array.from({ length: cols }, (_2, c) => {
3540
+ const flat = r * cols + c;
3541
+ const cell = cells[flat];
3542
+ if (cell?.attrs.covered === true) return null;
3543
+ const rowspan = spanAttr(cell?.attrs.rowspan);
3544
+ const colspan = spanAttr(cell?.attrs.colspan);
3545
+ const delta = cell?.delta ?? [];
3546
+ const inRect = rect !== null && r >= rect.top && r <= rect.bottom && c >= rect.left && c <= rect.right;
3547
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3548
+ "td",
3549
+ {
3550
+ "data-cell-index": flat,
3551
+ "data-cell-row": r,
3552
+ "data-cell-col": c,
3553
+ "data-cell-rowspan": rowspan,
3554
+ "data-cell-colspan": colspan,
3555
+ rowSpan: rowspan > 1 ? rowspan : void 0,
3556
+ colSpan: colspan > 1 ? colspan : void 0,
3557
+ style: cellStyle(
3558
+ cell?.attrs,
3559
+ // rowStart/rowEnd são os limites do FRAGMENTO: numa tabela
3560
+ // quebrada entre páginas, cada página fecha a própria caixa.
3561
+ (0, import_core8.cellBorderStyle)(
3562
+ block.attrs.borderPreset,
3563
+ { row: r, col: c, rowspan, colspan, cols, rowStart, rowEnd },
3564
+ "screen",
3565
+ block.attrs.borderColor
3566
+ )
3567
+ ),
3568
+ className: inRect ? "ed-cell ed-cell--selected" : "ed-cell",
3569
+ children: renderInline(delta, `t${index}-c${flat}`)
3570
+ },
3571
+ c
3572
+ );
3573
+ })
3574
+ },
3575
+ r
3576
+ );
2871
3577
  }) })
2872
3578
  ]
2873
3579
  }
2874
3580
  ),
2875
- isFirstFragment && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TableResizeOverlay, { tableRef, blockIndex: index, cols })
3581
+ isFirstFragment && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableResizeOverlay, { tableRef, blockIndex: index, cols, rows })
2876
3582
  ] });
2877
3583
  }
2878
- function readColWidths(raw, cols) {
2879
- if (!Array.isArray(raw)) return null;
2880
- const out = [];
2881
- for (let i = 0; i < cols; i++) {
2882
- const v = raw[i];
2883
- out.push(typeof v === "number" && Number.isFinite(v) && v > 0 ? v : null);
2884
- }
2885
- return out;
2886
- }
2887
3584
  function spanAttr(v) {
2888
3585
  if (typeof v !== "number" || !Number.isFinite(v) || v < 1) return 1;
2889
3586
  return Math.trunc(v);
@@ -2894,7 +3591,7 @@ function clampPositive(n) {
2894
3591
  }
2895
3592
 
2896
3593
  // src/usePagination.ts
2897
- var import_react11 = require("react");
3594
+ var import_react12 = require("react");
2898
3595
  var A4_PAGE = {
2899
3596
  width: 794,
2900
3597
  height: 1123,
@@ -2920,10 +3617,10 @@ function defaultPageLayout(topLevelCount) {
2920
3617
  };
2921
3618
  }
2922
3619
  function usePageLayout(rootRef, geometry, topLevelCount, deps) {
2923
- const [phase, setPhase] = (0, import_react11.useState)("measure");
2924
- const [layout, setLayout] = (0, import_react11.useState)(() => defaultPageLayout(topLevelCount));
2925
- const lastDepsRef = (0, import_react11.useRef)(null);
2926
- (0, import_react11.useLayoutEffect)(() => {
3620
+ const [phase, setPhase] = (0, import_react12.useState)("measure");
3621
+ const [layout, setLayout] = (0, import_react12.useState)(() => defaultPageLayout(topLevelCount));
3622
+ const lastDepsRef = (0, import_react12.useRef)(null);
3623
+ (0, import_react12.useLayoutEffect)(() => {
2927
3624
  const currentDeps = [...deps, topLevelCount, geometry];
2928
3625
  if (lastDepsRef.current !== null && shallowArrayEqual(lastDepsRef.current, currentDeps)) {
2929
3626
  return;
@@ -2935,7 +3632,7 @@ function usePageLayout(rootRef, geometry, topLevelCount, deps) {
2935
3632
  });
2936
3633
  setPhase("measure");
2937
3634
  });
2938
- (0, import_react11.useLayoutEffect)(() => {
3635
+ (0, import_react12.useLayoutEffect)(() => {
2939
3636
  if (phase !== "measure") return;
2940
3637
  const root = rootRef.current;
2941
3638
  if (!root) return;
@@ -3407,48 +4104,47 @@ function layoutsDeepEqual(a, b) {
3407
4104
  }
3408
4105
 
3409
4106
  // src/useEditor.ts
3410
- var import_react13 = require("react");
4107
+ var import_react14 = require("react");
3411
4108
 
3412
4109
  // src/usePageSettings.ts
3413
- var import_react12 = require("react");
4110
+ var import_react13 = require("react");
3414
4111
  function usePageSettings(doc) {
3415
- const cacheRef = (0, import_react12.useRef)(null);
3416
- const subscribe = (0, import_react12.useCallback)(
4112
+ const cacheRef = (0, import_react13.useRef)(null);
4113
+ const subscribe = (0, import_react13.useCallback)(
3417
4114
  (notify) => doc.observePageSettings(notify),
3418
4115
  [doc]
3419
4116
  );
3420
- const getSnapshot = (0, import_react12.useCallback)(() => {
4117
+ const getSnapshot = (0, import_react13.useCallback)(() => {
3421
4118
  const next = doc.getPageSettings();
3422
4119
  const prev = cacheRef.current;
3423
4120
  if (prev && shallowEqual(prev, next)) return prev;
3424
4121
  cacheRef.current = next;
3425
4122
  return next;
3426
4123
  }, [doc]);
3427
- return (0, import_react12.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
4124
+ return (0, import_react13.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
3428
4125
  }
3429
4126
  function shallowEqual(a, b) {
3430
4127
  return a.width === b.width && a.height === b.height && a.marginTop === b.marginTop && a.marginBottom === b.marginBottom && a.marginLeft === b.marginLeft && a.marginRight === b.marginRight && a.preset === b.preset && a.systemHeaderTitle === b.systemHeaderTitle && a.systemHeaderAuthor === b.systemHeaderAuthor;
3431
4128
  }
3432
4129
 
3433
4130
  // src/useEditor.ts
3434
- var import_core7 = require("@sofereditor/core");
3435
- var MAX_INSERT_WIDTH = 600;
4131
+ var import_core9 = require("@sofereditor/core");
3436
4132
  function useEditor(opts = {}) {
3437
- const doc = (0, import_react13.useMemo)(() => opts.document ?? new import_core7.EditorDocument(), [opts.document]);
3438
- const history = (0, import_react13.useMemo)(() => new import_core7.EditorHistory(doc), [doc]);
3439
- const [snapshot, setSnapshot] = (0, import_react13.useState)(() => doc.toJSON());
3440
- const [selection, setSelectionState] = (0, import_react13.useState)(
3441
- () => (0, import_core7.collapsedSelection)({ blockIndex: 0, offset: 0 })
4133
+ const doc = (0, import_react14.useMemo)(() => opts.document ?? new import_core9.EditorDocument(), [opts.document]);
4134
+ const history = (0, import_react14.useMemo)(() => new import_core9.EditorHistory(doc), [doc]);
4135
+ const [snapshot, setSnapshot] = (0, import_react14.useState)(() => doc.toJSON());
4136
+ const [selection, setSelectionState] = (0, import_react14.useState)(
4137
+ () => (0, import_core9.collapsedSelection)({ blockIndex: 0, offset: 0 })
3442
4138
  );
3443
- const selectionRef = (0, import_react13.useRef)(selection);
4139
+ const selectionRef = (0, import_react14.useRef)(selection);
3444
4140
  selectionRef.current = selection;
3445
- const pendingMarksRef = (0, import_react13.useRef)({});
3446
- const [pendingMarks, setPendingMarksState] = (0, import_react13.useState)({});
3447
- const setPendingMarks = (0, import_react13.useCallback)((next) => {
4141
+ const pendingMarksRef = (0, import_react14.useRef)({});
4142
+ const [pendingMarks, setPendingMarksState] = (0, import_react14.useState)({});
4143
+ const setPendingMarks = (0, import_react14.useCallback)((next) => {
3448
4144
  pendingMarksRef.current = next;
3449
4145
  setPendingMarksState(next);
3450
4146
  }, []);
3451
- (0, import_react13.useEffect)(() => {
4147
+ (0, import_react14.useEffect)(() => {
3452
4148
  let scheduled = false;
3453
4149
  let cancelled = false;
3454
4150
  let frame = 0;
@@ -3475,8 +4171,8 @@ function useEditor(opts = {}) {
3475
4171
  doc.ydoc.off("afterTransaction", schedule);
3476
4172
  };
3477
4173
  }, [doc]);
3478
- const getSelection = (0, import_react13.useCallback)(() => selectionRef.current, []);
3479
- const setSelection = (0, import_react13.useCallback)(
4174
+ const getSelection = (0, import_react14.useCallback)(() => selectionRef.current, []);
4175
+ const setSelection = (0, import_react14.useCallback)(
3480
4176
  (sel) => {
3481
4177
  const prev = selectionRef.current;
3482
4178
  selectionRef.current = sel;
@@ -3491,19 +4187,19 @@ function useEditor(opts = {}) {
3491
4187
  },
3492
4188
  []
3493
4189
  );
3494
- const ctxRef = (0, import_react13.useRef)({ doc, getSelection, setSelection });
4190
+ const ctxRef = (0, import_react14.useRef)({ doc, getSelection, setSelection });
3495
4191
  ctxRef.current = { doc, getSelection, setSelection };
3496
- const consumePendingMarks = (0, import_react13.useCallback)(() => {
4192
+ const consumePendingMarks = (0, import_react14.useCallback)(() => {
3497
4193
  const current = pendingMarksRef.current;
3498
4194
  if (Object.keys(current).length === 0) return void 0;
3499
4195
  pendingMarksRef.current = {};
3500
4196
  setPendingMarksState({});
3501
4197
  return current;
3502
4198
  }, []);
3503
- const isMarkActive = (0, import_react13.useCallback)(
4199
+ const isMarkActive = (0, import_react14.useCallback)(
3504
4200
  (name, value) => {
3505
4201
  const sel = selectionRef.current;
3506
- const { start, end } = (0, import_core7.orderedRange)(sel);
4202
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3507
4203
  if (start.blockIndex === end.blockIndex && start.offset === end.offset) {
3508
4204
  const pending = pendingMarksRef.current[name];
3509
4205
  if (pending !== void 0) {
@@ -3512,7 +4208,7 @@ function useEditor(opts = {}) {
3512
4208
  }
3513
4209
  const yText2 = doc.getBlockText(start.blockIndex);
3514
4210
  if (!yText2 || start.offset === 0) return false;
3515
- return (0, import_core7.isMarkUniformInRange)(yText2, start.offset - 1, start.offset, name, value);
4211
+ return (0, import_core9.isMarkUniformInRange)(yText2, start.offset - 1, start.offset, name, value);
3516
4212
  }
3517
4213
  if (start.blockIndex !== end.blockIndex) {
3518
4214
  for (let i = start.blockIndex; i <= end.blockIndex; i++) {
@@ -3521,19 +4217,19 @@ function useEditor(opts = {}) {
3521
4217
  const s = i === start.blockIndex ? start.offset : 0;
3522
4218
  const e = i === end.blockIndex ? end.offset : yText2.length;
3523
4219
  if (s >= e) continue;
3524
- if (!(0, import_core7.isMarkUniformInRange)(yText2, s, e, name, value)) return false;
4220
+ if (!(0, import_core9.isMarkUniformInRange)(yText2, s, e, name, value)) return false;
3525
4221
  }
3526
4222
  return true;
3527
4223
  }
3528
4224
  const yText = doc.getBlockText(start.blockIndex);
3529
4225
  if (!yText) return false;
3530
- return (0, import_core7.isMarkUniformInRange)(yText, start.offset, end.offset, name, value);
4226
+ return (0, import_core9.isMarkUniformInRange)(yText, start.offset, end.offset, name, value);
3531
4227
  },
3532
4228
  [doc]
3533
4229
  );
3534
- const getActiveMarks = (0, import_react13.useCallback)(() => {
4230
+ const getActiveMarks = (0, import_react14.useCallback)(() => {
3535
4231
  const sel = selectionRef.current;
3536
- const { start, end } = (0, import_core7.orderedRange)(sel);
4232
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3537
4233
  if (start.blockIndex !== end.blockIndex) {
3538
4234
  return {};
3539
4235
  }
@@ -3541,14 +4237,14 @@ function useEditor(opts = {}) {
3541
4237
  if (!yText) return {};
3542
4238
  if (start.offset === end.offset) {
3543
4239
  if (start.offset === 0) return {};
3544
- return (0, import_core7.getMarksInRange)(yText, start.offset - 1, start.offset);
4240
+ return (0, import_core9.getMarksInRange)(yText, start.offset - 1, start.offset);
3545
4241
  }
3546
- return (0, import_core7.getMarksInRange)(yText, start.offset, end.offset);
4242
+ return (0, import_core9.getMarksInRange)(yText, start.offset, end.offset);
3547
4243
  }, [doc]);
3548
- const toggleMark = (0, import_react13.useCallback)(
4244
+ const toggleMark = (0, import_react14.useCallback)(
3549
4245
  (name, value) => {
3550
4246
  const sel = selectionRef.current;
3551
- const { start, end } = (0, import_core7.orderedRange)(sel);
4247
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3552
4248
  const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;
3553
4249
  if (isCollapsed) {
3554
4250
  const next = { ...pendingMarksRef.current };
@@ -3561,39 +4257,39 @@ function useEditor(opts = {}) {
3561
4257
  setPendingMarks(next);
3562
4258
  return;
3563
4259
  }
3564
- (0, import_core7.toggleMark)(ctxRef.current, name, value);
4260
+ (0, import_core9.toggleMark)(ctxRef.current, name, value);
3565
4261
  },
3566
4262
  [isMarkActive, setPendingMarks]
3567
4263
  );
3568
- const setMark = (0, import_react13.useCallback)(
4264
+ const setMark = (0, import_react14.useCallback)(
3569
4265
  (name, value) => {
3570
4266
  const sel = selectionRef.current;
3571
- const { start, end } = (0, import_core7.orderedRange)(sel);
4267
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3572
4268
  const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;
3573
4269
  if (isCollapsed) {
3574
4270
  setPendingMarks({ ...pendingMarksRef.current, [name]: value });
3575
4271
  return;
3576
4272
  }
3577
- (0, import_core7.setMark)(ctxRef.current, name, value);
4273
+ (0, import_core9.setMark)(ctxRef.current, name, value);
3578
4274
  },
3579
4275
  [setPendingMarks]
3580
4276
  );
3581
- const removeMark = (0, import_react13.useCallback)(
4277
+ const removeMark = (0, import_react14.useCallback)(
3582
4278
  (name) => {
3583
4279
  const sel = selectionRef.current;
3584
- const { start, end } = (0, import_core7.orderedRange)(sel);
4280
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3585
4281
  const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;
3586
4282
  if (isCollapsed) {
3587
4283
  setPendingMarks({ ...pendingMarksRef.current, [name]: null });
3588
4284
  return;
3589
4285
  }
3590
- (0, import_core7.removeMark)(ctxRef.current, name);
4286
+ (0, import_core9.removeMark)(ctxRef.current, name);
3591
4287
  },
3592
4288
  [setPendingMarks]
3593
4289
  );
3594
- const getBlockType = (0, import_react13.useCallback)(() => {
4290
+ const getBlockType = (0, import_react14.useCallback)(() => {
3595
4291
  const sel = selectionRef.current;
3596
- const { start, end } = (0, import_core7.orderedRange)(sel);
4292
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3597
4293
  const first = doc.getBlockType(start.blockIndex);
3598
4294
  if (first === void 0) return "paragraph";
3599
4295
  for (let i = start.blockIndex + 1; i <= end.blockIndex; i++) {
@@ -3601,10 +4297,10 @@ function useEditor(opts = {}) {
3601
4297
  }
3602
4298
  return first;
3603
4299
  }, [doc]);
3604
- const getBlockAttr = (0, import_react13.useCallback)(
4300
+ const getBlockAttr = (0, import_react14.useCallback)(
3605
4301
  (key) => {
3606
4302
  const sel = selectionRef.current;
3607
- const { start, end } = (0, import_core7.orderedRange)(sel);
4303
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3608
4304
  const first = doc.getBlockAttrs(start.blockIndex)[key];
3609
4305
  for (let i = start.blockIndex + 1; i <= end.blockIndex; i++) {
3610
4306
  const next = doc.getBlockAttrs(i)[key];
@@ -3614,60 +4310,60 @@ function useEditor(opts = {}) {
3614
4310
  },
3615
4311
  [doc]
3616
4312
  );
3617
- const setBlockType = (0, import_react13.useCallback)((type, attrs) => {
3618
- (0, import_core7.setBlockType)(ctxRef.current, type, attrs);
4313
+ const setBlockType = (0, import_react14.useCallback)((type, attrs) => {
4314
+ (0, import_core9.setBlockType)(ctxRef.current, type, attrs);
3619
4315
  }, []);
3620
- const setBlockAttr = (0, import_react13.useCallback)(
4316
+ const setBlockAttr = (0, import_react14.useCallback)(
3621
4317
  (key, value) => {
3622
- (0, import_core7.setBlockAttr)(ctxRef.current, key, value);
4318
+ (0, import_core9.setBlockAttr)(ctxRef.current, key, value);
3623
4319
  },
3624
4320
  []
3625
4321
  );
3626
- const setAlign = (0, import_react13.useCallback)((value) => {
4322
+ const setAlign = (0, import_react14.useCallback)((value) => {
3627
4323
  const sel = selectionRef.current;
3628
4324
  const inCell = sel.focus.cellIndex != null;
3629
- if (inCell) (0, import_core7.setCellAttr)(ctxRef.current, "align", value);
3630
- else (0, import_core7.setBlockAttr)(ctxRef.current, "align", value);
4325
+ if (inCell) (0, import_core9.setCellAttr)(ctxRef.current, "align", value);
4326
+ else (0, import_core9.setBlockAttr)(ctxRef.current, "align", value);
3631
4327
  }, []);
3632
- const getAlign = (0, import_react13.useCallback)(() => {
4328
+ const getAlign = (0, import_react14.useCallback)(() => {
3633
4329
  const sel = selectionRef.current;
3634
4330
  if (sel.focus.cellIndex != null && doc.isTable(sel.focus.blockIndex)) {
3635
4331
  return doc.getCellAttrs(sel.focus.blockIndex, sel.focus.cellIndex).align;
3636
4332
  }
3637
4333
  return getBlockAttr("align");
3638
4334
  }, [doc, getBlockAttr]);
3639
- const setCellBackground = (0, import_react13.useCallback)((color) => {
3640
- (0, import_core7.setCellAttr)(ctxRef.current, "bgColor", color);
4335
+ const setCellBackground = (0, import_react14.useCallback)((color) => {
4336
+ (0, import_core9.setCellAttr)(ctxRef.current, "bgColor", color);
3641
4337
  }, []);
3642
- const getCellBackground = (0, import_react13.useCallback)(() => {
4338
+ const getCellBackground = (0, import_react14.useCallback)(() => {
3643
4339
  const sel = selectionRef.current;
3644
4340
  if (sel.focus.cellIndex == null || !doc.isTable(sel.focus.blockIndex)) return void 0;
3645
4341
  return doc.getCellAttrs(sel.focus.blockIndex, sel.focus.cellIndex).bgColor;
3646
4342
  }, [doc]);
3647
- const setTableBorderPreset = (0, import_react13.useCallback)((preset) => {
4343
+ const setTableBorderPreset = (0, import_react14.useCallback)((preset) => {
3648
4344
  const sel = selectionRef.current;
3649
4345
  if (!doc.isTable(sel.focus.blockIndex)) return;
3650
- (0, import_core7.setBlockAttrAtIndex)(ctxRef.current, sel.focus.blockIndex, "borderPreset", preset);
4346
+ (0, import_core9.setBlockAttrAtIndex)(ctxRef.current, sel.focus.blockIndex, "borderPreset", preset);
3651
4347
  }, [doc]);
3652
- const getTableBorderPreset = (0, import_react13.useCallback)(() => {
4348
+ const getTableBorderPreset = (0, import_react14.useCallback)(() => {
3653
4349
  const sel = selectionRef.current;
3654
4350
  if (!doc.isTable(sel.focus.blockIndex)) return "all";
3655
4351
  return doc.getBlockAttrs(sel.focus.blockIndex).borderPreset ?? "all";
3656
4352
  }, [doc]);
3657
- const setTableBorderColor = (0, import_react13.useCallback)((color) => {
4353
+ const setTableBorderColor = (0, import_react14.useCallback)((color) => {
3658
4354
  const sel = selectionRef.current;
3659
4355
  if (!doc.isTable(sel.focus.blockIndex)) return;
3660
- (0, import_core7.setBlockAttrAtIndex)(ctxRef.current, sel.focus.blockIndex, "borderColor", color);
4356
+ (0, import_core9.setBlockAttrAtIndex)(ctxRef.current, sel.focus.blockIndex, "borderColor", color);
3661
4357
  }, [doc]);
3662
- const getTableBorderColor = (0, import_react13.useCallback)(() => {
4358
+ const getTableBorderColor = (0, import_react14.useCallback)(() => {
3663
4359
  const sel = selectionRef.current;
3664
4360
  if (!doc.isTable(sel.focus.blockIndex)) return void 0;
3665
4361
  return doc.getBlockAttrs(sel.focus.blockIndex).borderColor;
3666
4362
  }, [doc]);
3667
- const isListActive = (0, import_react13.useCallback)(
4363
+ const isListActive = (0, import_react14.useCallback)(
3668
4364
  (kind) => {
3669
4365
  const sel = selectionRef.current;
3670
- const { start, end } = (0, import_core7.orderedRange)(sel);
4366
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3671
4367
  for (let i = start.blockIndex; i <= end.blockIndex; i++) {
3672
4368
  if (doc.getBlockType(i) !== "listItem") return false;
3673
4369
  if (doc.getBlockAttrs(i).listKind !== kind) return false;
@@ -3676,119 +4372,128 @@ function useEditor(opts = {}) {
3676
4372
  },
3677
4373
  [doc]
3678
4374
  );
3679
- const toggleList = (0, import_react13.useCallback)((kind) => {
3680
- (0, import_core7.toggleList)(ctxRef.current, kind);
4375
+ const toggleList = (0, import_react14.useCallback)((kind) => {
4376
+ (0, import_core9.toggleList)(ctxRef.current, kind);
3681
4377
  }, []);
3682
- const indentList = (0, import_react13.useCallback)(() => {
3683
- (0, import_core7.indentList)(ctxRef.current);
4378
+ const indentList = (0, import_react14.useCallback)(() => {
4379
+ (0, import_core9.indentList)(ctxRef.current);
3684
4380
  }, []);
3685
- const dedentList = (0, import_react13.useCallback)(() => {
3686
- (0, import_core7.dedentList)(ctxRef.current);
4381
+ const dedentList = (0, import_react14.useCallback)(() => {
4382
+ (0, import_core9.dedentList)(ctxRef.current);
3687
4383
  }, []);
3688
- const splitListItem = (0, import_react13.useCallback)(() => {
3689
- return (0, import_core7.splitListItem)(ctxRef.current);
4384
+ const splitListItem = (0, import_react14.useCallback)(() => {
4385
+ return (0, import_core9.splitListItem)(ctxRef.current);
3690
4386
  }, []);
3691
- const isInTable = (0, import_react13.useCallback)(() => {
4387
+ const isInTable = (0, import_react14.useCallback)(() => {
3692
4388
  return selectionRef.current.focus.cellIndex != null;
3693
4389
  }, []);
3694
- const getTableLocation = (0, import_react13.useCallback)(() => {
3695
- return (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
4390
+ const getTableLocation = (0, import_react14.useCallback)(() => {
4391
+ return (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3696
4392
  }, [doc]);
3697
- const insertTable = (0, import_react13.useCallback)((rows, cols) => {
3698
- (0, import_core7.insertTable)(ctxRef.current, rows, cols);
4393
+ const insertTable = (0, import_react14.useCallback)((rows, cols) => {
4394
+ (0, import_core9.insertTable)(ctxRef.current, rows, cols);
3699
4395
  }, []);
3700
- const insertAnswerLines = (0, import_react13.useCallback)((count, spacing) => {
3701
- (0, import_core7.insertAnswerLines)(ctxRef.current, count, spacing);
4396
+ const insertAnswerLines = (0, import_react14.useCallback)((count, spacing) => {
4397
+ (0, import_core9.insertAnswerLines)(ctxRef.current, count, spacing);
3702
4398
  }, []);
3703
- const deleteTable = (0, import_react13.useCallback)((blockIndex) => {
4399
+ const deleteTable = (0, import_react14.useCallback)((blockIndex) => {
3704
4400
  const idx = blockIndex ?? selectionRef.current.focus.blockIndex;
3705
- (0, import_core7.deleteTable)(ctxRef.current, idx);
4401
+ (0, import_core9.deleteTable)(ctxRef.current, idx);
3706
4402
  }, []);
3707
- const insertRowAbove = (0, import_react13.useCallback)(() => {
3708
- const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
4403
+ const insertRowAbove = (0, import_react14.useCallback)(() => {
4404
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3709
4405
  if (!loc) return;
3710
- (0, import_core7.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "before");
4406
+ (0, import_core9.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "before");
3711
4407
  }, [doc]);
3712
- const insertRowBelow = (0, import_react13.useCallback)(() => {
3713
- const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
4408
+ const insertRowBelow = (0, import_react14.useCallback)(() => {
4409
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3714
4410
  if (!loc) return;
3715
- (0, import_core7.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "after");
4411
+ (0, import_core9.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "after");
3716
4412
  }, [doc]);
3717
- const deleteCurrentRow = (0, import_react13.useCallback)(() => {
3718
- const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
4413
+ const deleteCurrentRow = (0, import_react14.useCallback)(() => {
4414
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3719
4415
  if (!loc) return;
3720
- (0, import_core7.deleteTableRow)(ctxRef.current, loc.blockIndex, loc.row);
4416
+ (0, import_core9.deleteTableRow)(ctxRef.current, loc.blockIndex, loc.row);
3721
4417
  }, [doc]);
3722
- const insertColumnLeft = (0, import_react13.useCallback)(() => {
3723
- const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
4418
+ const insertColumnLeft = (0, import_react14.useCallback)(() => {
4419
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3724
4420
  if (!loc) return;
3725
- (0, import_core7.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "before");
4421
+ (0, import_core9.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "before");
3726
4422
  }, [doc]);
3727
- const insertColumnRight = (0, import_react13.useCallback)(() => {
3728
- const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
4423
+ const insertColumnRight = (0, import_react14.useCallback)(() => {
4424
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3729
4425
  if (!loc) return;
3730
- (0, import_core7.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "after");
4426
+ (0, import_core9.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "after");
3731
4427
  }, [doc]);
3732
- const deleteCurrentColumn = (0, import_react13.useCallback)(() => {
3733
- const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
4428
+ const deleteCurrentColumn = (0, import_react14.useCallback)(() => {
4429
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3734
4430
  if (!loc) return;
3735
- (0, import_core7.deleteTableColumn)(ctxRef.current, loc.blockIndex, loc.col);
4431
+ (0, import_core9.deleteTableColumn)(ctxRef.current, loc.blockIndex, loc.col);
3736
4432
  }, [doc]);
3737
- const moveToNextCell = (0, import_react13.useCallback)(() => {
3738
- (0, import_core7.moveToNextCell)(ctxRef.current);
4433
+ const moveToNextCell = (0, import_react14.useCallback)(() => {
4434
+ (0, import_core9.moveToNextCell)(ctxRef.current);
3739
4435
  }, []);
3740
- const moveToPrevCell = (0, import_react13.useCallback)(() => {
3741
- (0, import_core7.moveToPrevCell)(ctxRef.current);
4436
+ const moveToPrevCell = (0, import_react14.useCallback)(() => {
4437
+ (0, import_core9.moveToPrevCell)(ctxRef.current);
3742
4438
  }, []);
3743
- const mergeRight = (0, import_react13.useCallback)(() => {
3744
- const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
4439
+ const mergeRight = (0, import_react14.useCallback)(() => {
4440
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3745
4441
  if (!loc) return false;
3746
- return (0, import_core7.mergeRight)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
4442
+ return (0, import_core9.mergeRight)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3747
4443
  }, [doc]);
3748
- const mergeDown = (0, import_react13.useCallback)(() => {
3749
- const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
4444
+ const mergeDown = (0, import_react14.useCallback)(() => {
4445
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3750
4446
  if (!loc) return false;
3751
- return (0, import_core7.mergeDown)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
4447
+ return (0, import_core9.mergeDown)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3752
4448
  }, [doc]);
3753
- const splitCell = (0, import_react13.useCallback)(() => {
3754
- const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
4449
+ const splitCell = (0, import_react14.useCallback)(() => {
4450
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3755
4451
  if (!loc) return false;
3756
- return (0, import_core7.splitCell)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
4452
+ return (0, import_core9.splitCell)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3757
4453
  }, [doc]);
3758
- const setColumnWidth = (0, import_react13.useCallback)(
3759
- (blockIndex, col, widthPx) => {
3760
- (0, import_core7.setColumnWidth)(ctxRef.current, blockIndex, col, widthPx);
4454
+ const setColumnBoundary = (0, import_react14.useCallback)(
4455
+ (blockIndex, boundary, deltaPct, base) => {
4456
+ (0, import_core9.setColumnBoundary)(ctxRef.current, blockIndex, boundary, deltaPct, base);
3761
4457
  },
3762
4458
  []
3763
4459
  );
3764
- const getTableRect = (0, import_react13.useCallback)(
3765
- () => (0, import_core7.tableRectSelection)(doc, selectionRef.current),
4460
+ const setTableWidth = (0, import_react14.useCallback)((blockIndex, pct) => {
4461
+ (0, import_core9.setTableWidth)(ctxRef.current, blockIndex, pct);
4462
+ }, []);
4463
+ const setRowHeight = (0, import_react14.useCallback)((blockIndex, row, px) => {
4464
+ (0, import_core9.setRowHeight)(ctxRef.current, blockIndex, row, px);
4465
+ }, []);
4466
+ const setRowHeights = (0, import_react14.useCallback)((blockIndex, heights) => {
4467
+ (0, import_core9.setRowHeights)(ctxRef.current, blockIndex, heights);
4468
+ }, []);
4469
+ const getTableRect = (0, import_react14.useCallback)(
4470
+ () => (0, import_core9.tableRectSelection)(doc, selectionRef.current),
3766
4471
  [doc]
3767
4472
  );
3768
- const hasTableRectSelection = (0, import_react13.useCallback)(() => {
3769
- return (0, import_core7.tableRectSelection)(doc, selectionRef.current) !== null;
4473
+ const hasTableRectSelection = (0, import_react14.useCallback)(() => {
4474
+ return (0, import_core9.tableRectSelection)(doc, selectionRef.current) !== null;
3770
4475
  }, [doc]);
3771
- const mergeSelection = (0, import_react13.useCallback)(() => {
3772
- return (0, import_core7.mergeSelection)(ctxRef.current);
4476
+ const mergeSelection = (0, import_react14.useCallback)(() => {
4477
+ return (0, import_core9.mergeSelection)(ctxRef.current);
3773
4478
  }, []);
3774
- const insertImage = (0, import_react13.useCallback)((embed) => {
3775
- (0, import_core7.insertImage)(ctxRef.current, embed);
4479
+ const insertImage = (0, import_react14.useCallback)((embed) => {
4480
+ (0, import_core9.insertImage)(ctxRef.current, embed);
3776
4481
  }, []);
3777
- const setImageAttrs = (0, import_react13.useCallback)(
4482
+ const setImageAttrs = (0, import_react14.useCallback)(
3778
4483
  (blockIndex, offset, partial, cellIndex, newOffset) => {
3779
- (0, import_core7.setImageAttrs)(ctxRef.current, blockIndex, offset, partial, cellIndex, newOffset);
4484
+ (0, import_core9.setImageAttrs)(ctxRef.current, blockIndex, offset, partial, cellIndex, newOffset);
3780
4485
  },
3781
4486
  []
3782
4487
  );
3783
- const moveEmbedAnchor = (0, import_react13.useCallback)(
4488
+ const moveEmbedAnchor = (0, import_react14.useCallback)(
3784
4489
  (from, to, newOffsetX, newOffsetY) => {
3785
- (0, import_core7.moveEmbedAnchor)(ctxRef.current, from, to, newOffsetX, newOffsetY);
4490
+ (0, import_core9.moveEmbedAnchor)(ctxRef.current, from, to, newOffsetX, newOffsetY);
3786
4491
  },
3787
4492
  []
3788
4493
  );
3789
- const uploadImageRef = (0, import_react13.useRef)(opts.uploadImage);
4494
+ const uploadImageRef = (0, import_react14.useRef)(opts.uploadImage);
3790
4495
  uploadImageRef.current = opts.uploadImage;
3791
- const insertImageFromFile = (0, import_react13.useCallback)(async (file) => {
4496
+ const insertImageFromFile = (0, import_react14.useCallback)(async (file) => {
3792
4497
  if (!file.type.startsWith("image/")) return;
3793
4498
  const dataUrl = await readAsDataURL(file);
3794
4499
  const dims = await readImageDimensions(dataUrl);
@@ -3800,9 +4505,9 @@ function useEditor(opts = {}) {
3800
4505
  }
3801
4506
  const upload = uploadImageRef.current;
3802
4507
  const src = upload ? await upload(file) : dataUrl;
3803
- (0, import_core7.insertImage)(ctxRef.current, { type: "image", src, width: w, height: h });
4508
+ (0, import_core9.insertImage)(ctxRef.current, { type: "image", src, width: w, height: h });
3804
4509
  }, []);
3805
- const getSelectedEmbed = (0, import_react13.useCallback)(() => {
4510
+ const getSelectedEmbed = (0, import_react14.useCallback)(() => {
3806
4511
  const sel = selectionRef.current;
3807
4512
  if (sel.anchor.blockIndex !== sel.focus.blockIndex) return null;
3808
4513
  if ((sel.anchor.cellIndex ?? -1) !== (sel.focus.cellIndex ?? -1)) return null;
@@ -3819,7 +4524,7 @@ function useEditor(opts = {}) {
3819
4524
  cursor += op.insert.length;
3820
4525
  continue;
3821
4526
  }
3822
- if (cursor === start && (0, import_core7.isImageEmbed)(op.insert)) {
4527
+ if (cursor === start && (0, import_core9.isImageEmbed)(op.insert)) {
3823
4528
  return {
3824
4529
  blockIndex: sel.anchor.blockIndex,
3825
4530
  cellIndex: sel.anchor.cellIndex,
@@ -3831,16 +4536,16 @@ function useEditor(opts = {}) {
3831
4536
  }
3832
4537
  return null;
3833
4538
  }, [doc]);
3834
- const [linkRequest, setLinkRequest] = (0, import_react13.useState)(null);
3835
- const linkRequestRef = (0, import_react13.useRef)(null);
3836
- const requestLink = (0, import_react13.useCallback)((initialHref = "") => {
4539
+ const [linkRequest, setLinkRequest] = (0, import_react14.useState)(null);
4540
+ const linkRequestRef = (0, import_react14.useRef)(null);
4541
+ const requestLink = (0, import_react14.useCallback)((initialHref = "") => {
3837
4542
  return new Promise((resolve) => {
3838
4543
  const req = { initialHref, resolve, selection: selectionRef.current };
3839
4544
  linkRequestRef.current = req;
3840
4545
  setLinkRequest(req);
3841
4546
  });
3842
4547
  }, []);
3843
- const resolveLinkRequest = (0, import_react13.useCallback)(
4548
+ const resolveLinkRequest = (0, import_react14.useCallback)(
3844
4549
  (href) => {
3845
4550
  const req = linkRequestRef.current;
3846
4551
  linkRequestRef.current = null;
@@ -3853,26 +4558,26 @@ function useEditor(opts = {}) {
3853
4558
  [setSelection]
3854
4559
  );
3855
4560
  const pageSettings = usePageSettings(doc);
3856
- const setPageSettings = (0, import_react13.useCallback)(
4561
+ const setPageSettings = (0, import_react14.useCallback)(
3857
4562
  (partial) => {
3858
4563
  doc.setPageSettings(partial);
3859
4564
  },
3860
4565
  [doc]
3861
4566
  );
3862
- const [pageConfigRequest, setPageConfigRequest] = (0, import_react13.useState)(null);
3863
- const requestPageConfig = (0, import_react13.useCallback)(() => {
4567
+ const [pageConfigRequest, setPageConfigRequest] = (0, import_react14.useState)(null);
4568
+ const requestPageConfig = (0, import_react14.useCallback)(() => {
3864
4569
  return new Promise((resolve) => {
3865
4570
  setPageConfigRequest({ initial: doc.getPageSettings(), resolve });
3866
4571
  });
3867
4572
  }, [doc]);
3868
- const resolvePageConfigRequest = (0, import_react13.useCallback)((applied) => {
4573
+ const resolvePageConfigRequest = (0, import_react14.useCallback)((applied) => {
3869
4574
  setPageConfigRequest((prev) => {
3870
4575
  if (prev) prev.resolve(applied);
3871
4576
  return null;
3872
4577
  });
3873
4578
  }, []);
3874
- const [imageCaptionRequest, setImageCaptionRequest] = (0, import_react13.useState)(null);
3875
- const requestImageCaption = (0, import_react13.useCallback)(
4579
+ const [imageCaptionRequest, setImageCaptionRequest] = (0, import_react14.useState)(null);
4580
+ const requestImageCaption = (0, import_react14.useCallback)(
3876
4581
  (initialCaption = "", initialAlign = "center") => {
3877
4582
  return new Promise((resolve) => {
3878
4583
  setImageCaptionRequest({ initialCaption, initialAlign, resolve });
@@ -3880,12 +4585,82 @@ function useEditor(opts = {}) {
3880
4585
  },
3881
4586
  []
3882
4587
  );
3883
- const resolveImageCaptionRequest = (0, import_react13.useCallback)((result) => {
4588
+ const resolveImageCaptionRequest = (0, import_react14.useCallback)((result) => {
3884
4589
  setImageCaptionRequest((prev) => {
3885
4590
  if (prev) prev.resolve(result);
3886
4591
  return null;
3887
4592
  });
3888
4593
  }, []);
4594
+ const [formulaRequest, setFormulaRequest] = (0, import_react14.useState)(null);
4595
+ const requestFormula = (0, import_react14.useCallback)(
4596
+ (initialLatex = "", initialDisplay = false) => {
4597
+ return new Promise((resolve) => {
4598
+ setFormulaRequest({ initialLatex, initialDisplay, resolve });
4599
+ });
4600
+ },
4601
+ []
4602
+ );
4603
+ const resolveFormulaRequest = (0, import_react14.useCallback)((result) => {
4604
+ setFormulaRequest((prev) => {
4605
+ if (prev) prev.resolve(result);
4606
+ return null;
4607
+ });
4608
+ }, []);
4609
+ const insertFormula = (0, import_react14.useCallback)(
4610
+ async (latex, display) => {
4611
+ const selectionAtCall = ctxRef.current.getSelection();
4612
+ const embedAtCall = getSelectedEmbed();
4613
+ let mathModule;
4614
+ try {
4615
+ mathModule = await import("@sofereditor/math");
4616
+ } catch {
4617
+ return;
4618
+ }
4619
+ const { renderLatexToSvg, measureExInPx, svgToDataUrl, svgToPngDataUrl } = mathModule;
4620
+ const r = renderLatexToSvg(latex, display);
4621
+ if (!r.ok) return;
4622
+ const root = document.querySelector(".ed-root");
4623
+ const exPx = root ? measureExInPx(root) : 8;
4624
+ let w = Math.round(r.widthEx * exPx);
4625
+ let h = Math.round(r.heightEx * exPx);
4626
+ let vAlignScale = 1;
4627
+ if (w > MAX_INSERT_WIDTH) {
4628
+ vAlignScale = MAX_INSERT_WIDTH / w;
4629
+ h = Math.round(h * MAX_INSERT_WIDTH / w);
4630
+ w = MAX_INSERT_WIDTH;
4631
+ }
4632
+ const src = svgToDataUrl(r.svg);
4633
+ let svgFallback;
4634
+ try {
4635
+ svgFallback = await svgToPngDataUrl(r.svg, w, h);
4636
+ } catch {
4637
+ svgFallback = void 0;
4638
+ }
4639
+ ctxRef.current.setSelection(selectionAtCall);
4640
+ const inheritedLayout = {};
4641
+ if ((0, import_core9.isFormulaEmbed)(embedAtCall?.embed)) {
4642
+ const prev = embedAtCall.embed;
4643
+ if (prev.layout !== void 0) inheritedLayout.layout = prev.layout;
4644
+ if (prev.offsetX !== void 0) inheritedLayout.offsetX = prev.offsetX;
4645
+ if (prev.offsetY !== void 0) inheritedLayout.offsetY = prev.offsetY;
4646
+ }
4647
+ (0, import_core9.insertImage)(ctxRef.current, {
4648
+ type: "image",
4649
+ src,
4650
+ width: w,
4651
+ height: h,
4652
+ ...inheritedLayout,
4653
+ ...display ? { align: "center" } : {},
4654
+ formula: {
4655
+ latex,
4656
+ display,
4657
+ ...display ? {} : { vAlign: `${r.vAlignEx * vAlignScale}ex` }
4658
+ },
4659
+ ...svgFallback ? { svgFallback } : {}
4660
+ });
4661
+ },
4662
+ [getSelectedEmbed]
4663
+ );
3889
4664
  return {
3890
4665
  doc,
3891
4666
  history,
@@ -3936,7 +4711,10 @@ function useEditor(opts = {}) {
3936
4711
  mergeRight,
3937
4712
  mergeDown,
3938
4713
  splitCell,
3939
- setColumnWidth,
4714
+ setColumnBoundary,
4715
+ setTableWidth,
4716
+ setRowHeight,
4717
+ setRowHeights,
3940
4718
  getTableRect,
3941
4719
  hasTableRectSelection,
3942
4720
  mergeSelection,
@@ -3952,7 +4730,12 @@ function useEditor(opts = {}) {
3952
4730
  resolvePageConfigRequest,
3953
4731
  imageCaptionRequest,
3954
4732
  requestImageCaption,
3955
- resolveImageCaptionRequest
4733
+ resolveImageCaptionRequest,
4734
+ formulaRequest,
4735
+ requestFormula,
4736
+ resolveFormulaRequest,
4737
+ insertFormula,
4738
+ uploadImage: opts.uploadImage
3956
4739
  };
3957
4740
  }
3958
4741
  function readAsDataURL(file) {
@@ -3984,7 +4767,7 @@ function sameValue(a, b) {
3984
4767
  }
3985
4768
 
3986
4769
  // src/Editor.tsx
3987
- var import_jsx_runtime12 = require("react/jsx-runtime");
4770
+ var import_jsx_runtime13 = require("react/jsx-runtime");
3988
4771
  var defaultFooter = ({ pageNumber, pageCount }) => `${pageNumber} / ${pageCount}`;
3989
4772
  function Editor({
3990
4773
  editor: providedEditor,
@@ -3997,14 +4780,15 @@ function Editor({
3997
4780
  const internal = useEditor();
3998
4781
  const editor = providedEditor ?? internal;
3999
4782
  const { doc, history, snapshot, getSelection, setSelection } = editor;
4000
- const rootRef = (0, import_react14.useRef)(null);
4001
- const isComposingRef = (0, import_react14.useRef)(false);
4002
- const [hoveredBehind, setHoveredBehind] = (0, import_react14.useState)(null);
4003
- const hoveredBehindRef = (0, import_react14.useRef)(null);
4004
- const [hoveredLink, setHoveredLink] = (0, import_react14.useState)(null);
4005
- const hoveredLinkElRef = (0, import_react14.useRef)(null);
4006
- const suppressSelectionSyncRef = (0, import_react14.useRef)(false);
4007
- (0, import_react14.useEffect)(() => {
4783
+ const rootRef = (0, import_react15.useRef)(null);
4784
+ const isComposingRef = (0, import_react15.useRef)(false);
4785
+ const pasteInFlightRef = (0, import_react15.useRef)(false);
4786
+ const [hoveredBehind, setHoveredBehind] = (0, import_react15.useState)(null);
4787
+ const hoveredBehindRef = (0, import_react15.useRef)(null);
4788
+ const [hoveredLink, setHoveredLink] = (0, import_react15.useState)(null);
4789
+ const hoveredLinkElRef = (0, import_react15.useRef)(null);
4790
+ const suppressSelectionSyncRef = (0, import_react15.useRef)(false);
4791
+ (0, import_react15.useEffect)(() => {
4008
4792
  if (!awareness) return;
4009
4793
  const root = rootRef.current;
4010
4794
  if (!root) return;
@@ -4014,7 +4798,7 @@ function Editor({
4014
4798
  const sel = readDomSelection(root);
4015
4799
  awareness.setLocalStateField(
4016
4800
  "cursor",
4017
- sel ? (0, import_core8.encodeSelection)(doc, sel) ?? null : null
4801
+ sel ? (0, import_core10.encodeSelection)(doc, sel) ?? null : null
4018
4802
  );
4019
4803
  };
4020
4804
  const onSelChange = () => {
@@ -4034,13 +4818,13 @@ function Editor({
4034
4818
  awareness.setLocalStateField("cursor", null);
4035
4819
  };
4036
4820
  }, [awareness, doc]);
4037
- const ctxRef = (0, import_react14.useRef)({ doc, getSelection, setSelection });
4821
+ const ctxRef = (0, import_react15.useRef)({ doc, getSelection, setSelection });
4038
4822
  ctxRef.current = { doc, getSelection, setSelection };
4039
- const historyRef = (0, import_react14.useRef)(history);
4823
+ const historyRef = (0, import_react15.useRef)(history);
4040
4824
  historyRef.current = history;
4041
- const editorRef = (0, import_react14.useRef)(editor);
4825
+ const editorRef = (0, import_react15.useRef)(editor);
4042
4826
  editorRef.current = editor;
4043
- (0, import_react14.useLayoutEffect)(() => {
4827
+ (0, import_react15.useLayoutEffect)(() => {
4044
4828
  const root = rootRef.current;
4045
4829
  if (!root) return;
4046
4830
  if (isComposingRef.current) return;
@@ -4055,7 +4839,7 @@ function Editor({
4055
4839
  suppressSelectionSyncRef.current = true;
4056
4840
  applyDomSelection(root, editor.selection);
4057
4841
  });
4058
- (0, import_react14.useEffect)(() => {
4842
+ (0, import_react15.useEffect)(() => {
4059
4843
  const root = rootRef.current;
4060
4844
  if (!root) return;
4061
4845
  const handler = () => {
@@ -4076,7 +4860,7 @@ function Editor({
4076
4860
  document.addEventListener("selectionchange", handler);
4077
4861
  return () => document.removeEventListener("selectionchange", handler);
4078
4862
  }, [setSelection]);
4079
- (0, import_react14.useEffect)(() => {
4863
+ (0, import_react15.useEffect)(() => {
4080
4864
  const root = rootRef.current;
4081
4865
  if (!root) return;
4082
4866
  let drag = null;
@@ -4147,7 +4931,7 @@ function Editor({
4147
4931
  document.removeEventListener("pointerup", onPointerUp);
4148
4932
  };
4149
4933
  }, []);
4150
- (0, import_react14.useEffect)(() => {
4934
+ (0, import_react15.useEffect)(() => {
4151
4935
  const root = rootRef.current;
4152
4936
  if (!root) return;
4153
4937
  const onDragOver = (e) => {
@@ -4185,7 +4969,7 @@ function Editor({
4185
4969
  root.removeEventListener("drop", onDrop);
4186
4970
  };
4187
4971
  }, []);
4188
- (0, import_react14.useEffect)(() => {
4972
+ (0, import_react15.useEffect)(() => {
4189
4973
  const root = rootRef.current;
4190
4974
  if (!root) return;
4191
4975
  const onPointerDown = (e) => {
@@ -4213,7 +4997,27 @@ function Editor({
4213
4997
  root.addEventListener("pointerdown", onPointerDown);
4214
4998
  return () => root.removeEventListener("pointerdown", onPointerDown);
4215
4999
  }, []);
4216
- (0, import_react14.useEffect)(() => {
5000
+ (0, import_react15.useEffect)(() => {
5001
+ const root = rootRef.current;
5002
+ if (!root) return;
5003
+ const onDoubleClick = (e) => {
5004
+ const target = e.target;
5005
+ if (!(target instanceof Element)) return;
5006
+ if (!target.closest('img[data-embed="image"]')) return;
5007
+ const ed = editorRef.current;
5008
+ const sel = ed.getSelectedEmbed();
5009
+ if (!sel || !(0, import_core10.isFormulaEmbed)(sel.embed)) return;
5010
+ e.preventDefault();
5011
+ const { latex, display } = sel.embed.formula;
5012
+ void ed.requestFormula(latex, display).then((r) => {
5013
+ if (!r) return;
5014
+ void ed.insertFormula(r.latex, r.display);
5015
+ });
5016
+ };
5017
+ root.addEventListener("dblclick", onDoubleClick);
5018
+ return () => root.removeEventListener("dblclick", onDoubleClick);
5019
+ }, []);
5020
+ (0, import_react15.useEffect)(() => {
4217
5021
  const root = rootRef.current;
4218
5022
  if (!root) return;
4219
5023
  const same = (a, b) => a === b || !!a && !!b && a.blockIndex === b.blockIndex && a.offset === b.offset && (a.cellIndex ?? -1) === (b.cellIndex ?? -1);
@@ -4266,7 +5070,7 @@ function Editor({
4266
5070
  if (raf) cancelAnimationFrame(raf);
4267
5071
  };
4268
5072
  }, []);
4269
- (0, import_react14.useEffect)(() => {
5073
+ (0, import_react15.useEffect)(() => {
4270
5074
  const root = rootRef.current;
4271
5075
  if (!root) return;
4272
5076
  const clear = () => {
@@ -4301,7 +5105,7 @@ function Editor({
4301
5105
  window.removeEventListener("scroll", clear, true);
4302
5106
  };
4303
5107
  }, []);
4304
- (0, import_react14.useEffect)(() => {
5108
+ (0, import_react15.useEffect)(() => {
4305
5109
  const root = rootRef.current;
4306
5110
  if (!root) return;
4307
5111
  const handler = (e) => {
@@ -4315,14 +5119,14 @@ function Editor({
4315
5119
  const data = e.data ?? "";
4316
5120
  if (data.length > 0) {
4317
5121
  e.preventDefault();
4318
- (0, import_core8.insertText)(ctx, data, ed.consumePendingMarks());
5122
+ (0, import_core10.insertText)(ctx, data, ed.consumePendingMarks());
4319
5123
  }
4320
5124
  return;
4321
5125
  }
4322
5126
  case "insertLineBreak": {
4323
5127
  e.preventDefault();
4324
5128
  if (ed.getBlockType() === "listItem") {
4325
- (0, import_core8.insertText)(ctx, "\n", ed.consumePendingMarks());
5129
+ (0, import_core10.insertText)(ctx, "\n", ed.consumePendingMarks());
4326
5130
  return;
4327
5131
  }
4328
5132
  const selEmbed = ed.getSelectedEmbed();
@@ -4342,7 +5146,7 @@ function Editor({
4342
5146
  });
4343
5147
  }
4344
5148
  if (ed.splitListItem()) return;
4345
- (0, import_core8.insertParagraph)(ctx);
5149
+ (0, import_core10.insertParagraph)(ctx);
4346
5150
  return;
4347
5151
  }
4348
5152
  case "insertParagraph": {
@@ -4364,14 +5168,14 @@ function Editor({
4364
5168
  });
4365
5169
  }
4366
5170
  if (ed.splitListItem()) return;
4367
- (0, import_core8.insertParagraph)(ctx);
5171
+ (0, import_core10.insertParagraph)(ctx);
4368
5172
  return;
4369
5173
  }
4370
5174
  case "insertReplacementText": {
4371
5175
  const text = e.data ?? e.dataTransfer?.getData("text/plain") ?? "";
4372
5176
  if (text.length > 0) {
4373
5177
  e.preventDefault();
4374
- (0, import_core8.insertText)(ctx, text, ed.consumePendingMarks());
5178
+ (0, import_core10.insertText)(ctx, text, ed.consumePendingMarks());
4375
5179
  }
4376
5180
  return;
4377
5181
  }
@@ -4384,7 +5188,7 @@ function Editor({
4384
5188
  case "deleteSoftLineBackward":
4385
5189
  case "deleteHardLineBackward": {
4386
5190
  e.preventDefault();
4387
- (0, import_core8.deleteBackward)(ctx);
5191
+ (0, import_core10.deleteBackward)(ctx);
4388
5192
  return;
4389
5193
  }
4390
5194
  case "deleteContentForward":
@@ -4392,7 +5196,7 @@ function Editor({
4392
5196
  case "deleteSoftLineForward":
4393
5197
  case "deleteHardLineForward": {
4394
5198
  e.preventDefault();
4395
- (0, import_core8.deleteForward)(ctx);
5199
+ (0, import_core10.deleteForward)(ctx);
4396
5200
  return;
4397
5201
  }
4398
5202
  case "historyUndo": {
@@ -4414,15 +5218,15 @@ function Editor({
4414
5218
  root.addEventListener("beforeinput", handler);
4415
5219
  return () => root.removeEventListener("beforeinput", handler);
4416
5220
  }, []);
4417
- (0, import_react14.useEffect)(() => {
5221
+ (0, import_react15.useEffect)(() => {
4418
5222
  const root = rootRef.current;
4419
5223
  if (!root) return;
4420
5224
  const writeSlice = (e) => {
4421
5225
  const ctx = ctxRef.current;
4422
- const slice = (0, import_core8.serializeSelection)(ctx.doc, ctx.getSelection());
5226
+ const slice = (0, import_core10.serializeSelection)(ctx.doc, ctx.getSelection());
4423
5227
  if (!slice || !e.clipboardData) return false;
4424
- e.clipboardData.setData(import_core8.SOFER_MIME, JSON.stringify(slice));
4425
- e.clipboardData.setData("text/plain", (0, import_core8.sliceToText)(slice));
5228
+ e.clipboardData.setData(import_core10.SOFER_MIME, JSON.stringify(slice));
5229
+ e.clipboardData.setData("text/plain", (0, import_core10.sliceToText)(slice));
4426
5230
  return true;
4427
5231
  };
4428
5232
  const onCopy = (e) => {
@@ -4430,7 +5234,7 @@ function Editor({
4430
5234
  };
4431
5235
  const onCut = (e) => {
4432
5236
  e.preventDefault();
4433
- if (writeSlice(e)) (0, import_core8.deleteSelection)(ctxRef.current);
5237
+ if (writeSlice(e)) (0, import_core10.deleteSelection)(ctxRef.current);
4434
5238
  };
4435
5239
  const onPaste = (e) => {
4436
5240
  const ctx = ctxRef.current;
@@ -4441,9 +5245,48 @@ function Editor({
4441
5245
  e.preventDefault();
4442
5246
  switch (plan.kind) {
4443
5247
  case "sofer":
4444
- case "html":
4445
- (0, import_core8.insertSlice)(ctx, plan.slice);
5248
+ (0, import_core10.insertSlice)(ctx, plan.slice);
4446
5249
  return;
5250
+ case "html": {
5251
+ if (!sliceHasDataImageEmbeds(plan.slice)) {
5252
+ (0, import_core10.insertSlice)(ctx, plan.slice);
5253
+ return;
5254
+ }
5255
+ if (pasteInFlightRef.current) {
5256
+ console.warn(
5257
+ "[sofereditor] colagem com imagem ainda subindo \u2014 descartando esta colagem concorrente para n\xE3o corromper a posi\xE7\xE3o de inser\xE7\xE3o"
5258
+ );
5259
+ return;
5260
+ }
5261
+ pasteInFlightRef.current = true;
5262
+ const capturedSelection = ctx.getSelection();
5263
+ void (async () => {
5264
+ try {
5265
+ const resolved = await resolvePastedImageUploads(plan.slice, editorRef.current.uploadImage);
5266
+ const liveSelection = ctxRef.current.getSelection();
5267
+ const userMovedAway = !selectionsEqual(liveSelection, capturedSelection);
5268
+ const { blockIndex, cellIndex } = capturedSelection.focus;
5269
+ const targetText = ctxRef.current.doc.textAt(blockIndex, cellIndex);
5270
+ let insertAt = capturedSelection;
5271
+ if (!targetText) {
5272
+ console.error(
5273
+ "[sofereditor] bloco de destino da colagem sumiu durante o upload da imagem \u2014 inserindo no fim do documento em vez de descartar a colagem"
5274
+ );
5275
+ const lastIndex = Math.max(0, ctxRef.current.doc.blockCount() - 1);
5276
+ const lastText = ctxRef.current.doc.getBlockText(lastIndex);
5277
+ insertAt = (0, import_core10.collapsedSelection)({ blockIndex: lastIndex, offset: lastText ? lastText.length : 0 });
5278
+ }
5279
+ ctxRef.current.setSelection(insertAt);
5280
+ (0, import_core10.insertSlice)(ctxRef.current, resolved);
5281
+ if (userMovedAway) {
5282
+ ctxRef.current.setSelection(liveSelection);
5283
+ }
5284
+ } finally {
5285
+ pasteInFlightRef.current = false;
5286
+ }
5287
+ })();
5288
+ return;
5289
+ }
4447
5290
  case "images":
4448
5291
  void (async () => {
4449
5292
  for (const f of plan.files) await editorRef.current.insertImageFromFile(f);
@@ -4452,8 +5295,8 @@ function Editor({
4452
5295
  case "text": {
4453
5296
  const lines = plan.text.split(/\r\n|\r|\n/);
4454
5297
  lines.forEach((line, i) => {
4455
- if (i > 0) (0, import_core8.insertParagraph)(ctx);
4456
- if (line.length > 0) (0, import_core8.insertText)(ctx, line);
5298
+ if (i > 0) (0, import_core10.insertParagraph)(ctx);
5299
+ if (line.length > 0) (0, import_core10.insertText)(ctx, line);
4457
5300
  });
4458
5301
  return;
4459
5302
  }
@@ -4468,7 +5311,7 @@ function Editor({
4468
5311
  root.removeEventListener("paste", onPaste);
4469
5312
  };
4470
5313
  }, []);
4471
- const onKeyDown = (0, import_react14.useCallback)((e) => {
5314
+ const onKeyDown = (0, import_react15.useCallback)((e) => {
4472
5315
  const ed = editorRef.current;
4473
5316
  const mod = e.metaKey || e.ctrlKey;
4474
5317
  if (e.key === "Tab") {
@@ -4496,6 +5339,17 @@ function Editor({
4496
5339
  }
4497
5340
  return;
4498
5341
  }
5342
+ if (!mod && (e.key === "Backspace" || e.key === "Delete")) {
5343
+ if (isComposingRef.current) return;
5344
+ const direction = e.key === "Backspace" ? "backward" : "forward";
5345
+ const shouldIntercept = ed.getSelectedEmbed() != null || (0, import_core10.isEmbedAdjacentToCaret)(ctxRef.current, direction);
5346
+ if (shouldIntercept) {
5347
+ e.preventDefault();
5348
+ if (direction === "backward") (0, import_core10.deleteBackward)(ctxRef.current);
5349
+ else (0, import_core10.deleteForward)(ctxRef.current);
5350
+ }
5351
+ return;
5352
+ }
4499
5353
  if (!mod) return;
4500
5354
  const key = e.key.toLowerCase();
4501
5355
  if (!e.shiftKey && !e.altKey && key === "z") {
@@ -4542,17 +5396,17 @@ function Editor({
4542
5396
  });
4543
5397
  }
4544
5398
  }, []);
4545
- const onCompositionStart = (0, import_react14.useCallback)(() => {
5399
+ const onCompositionStart = (0, import_react15.useCallback)(() => {
4546
5400
  isComposingRef.current = true;
4547
5401
  }, []);
4548
- const onCompositionEnd = (0, import_react14.useCallback)((e) => {
5402
+ const onCompositionEnd = (0, import_react15.useCallback)((e) => {
4549
5403
  isComposingRef.current = false;
4550
5404
  if (e.data && e.data.length > 0) {
4551
- (0, import_core8.insertText)(ctxRef.current, e.data);
5405
+ (0, import_core10.insertText)(ctxRef.current, e.data);
4552
5406
  }
4553
5407
  }, []);
4554
- const topLevels = (0, import_react14.useMemo)(() => groupTopLevels(snapshot.blocks), [snapshot]);
4555
- const topLevelsStructuralKey = (0, import_react14.useMemo)(
5408
+ const topLevels = (0, import_react15.useMemo)(() => groupTopLevels(snapshot.blocks), [snapshot]);
5409
+ const topLevelsStructuralKey = (0, import_react15.useMemo)(
4556
5410
  () => topLevels.map(
4557
5411
  (t) => t.kind === "list" ? `L:${t.listKind}:${t.items.length}:${t.ordinalStart}` : `B:${t.block.type}:${t.block.attrs.level ?? ""}`
4558
5412
  ).join("|"),
@@ -4574,7 +5428,7 @@ function Editor({
4574
5428
  [topLevelsStructuralKey, pageGeometry]
4575
5429
  );
4576
5430
  const effectiveLayout = paginated ? layout : defaultPageLayout(topLevels.length);
4577
- const pageStyle = (0, import_react14.useMemo)(
5431
+ const pageStyle = (0, import_react15.useMemo)(
4578
5432
  () => paginated ? {
4579
5433
  "--ed-page-width": `${geom.width}px`,
4580
5434
  "--ed-page-height": `${geom.height}px`,
@@ -4593,7 +5447,7 @@ function Editor({
4593
5447
  geom.marginRight
4594
5448
  ]
4595
5449
  );
4596
- const body = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5450
+ const body = /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4597
5451
  "div",
4598
5452
  {
4599
5453
  ref: rootRef,
@@ -4619,7 +5473,7 @@ function Editor({
4619
5473
  const pageInlineStyle = pi === 0 && geom.firstPageExtraTop ? {
4620
5474
  "--ed-page-margin-top": `${geom.marginTop + geom.firstPageExtraTop}px`
4621
5475
  } : void 0;
4622
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5476
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4623
5477
  "div",
4624
5478
  {
4625
5479
  className: "ed-page",
@@ -4627,15 +5481,15 @@ function Editor({
4627
5481
  "data-page-total": ctx.pageCount,
4628
5482
  style: pageInlineStyle,
4629
5483
  children: [
4630
- renderPageHeader && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ed-page-header", contentEditable: false, children: renderPageHeader(ctx) }),
4631
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ed-page-content", children: page.slots.map((slot) => renderSlot(slot, topLevels)) }),
4632
- renderPageFooter && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ed-page-footer", contentEditable: false, children: renderPageFooter(ctx) })
5484
+ renderPageHeader && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ed-page-header", contentEditable: false, children: renderPageHeader(ctx) }),
5485
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ed-page-content", children: page.slots.map((slot) => renderSlot(slot, topLevels)) }),
5486
+ renderPageFooter && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ed-page-footer", contentEditable: false, children: renderPageFooter(ctx) })
4633
5487
  ]
4634
5488
  },
4635
5489
  `page-${pi}`
4636
5490
  );
4637
5491
  }) : topLevels.map((t) => renderTopLevel(t)),
4638
- selectedEmbed && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5492
+ selectedEmbed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4639
5493
  ImageResizeOverlay,
4640
5494
  {
4641
5495
  rootRef,
@@ -4667,7 +5521,7 @@ function Editor({
4667
5521
  )
4668
5522
  }
4669
5523
  ),
4670
- hoveredBehind && !(selectedEmbed && selectedEmbed.blockIndex === hoveredBehind.blockIndex && selectedEmbed.offset === hoveredBehind.offset && (selectedEmbed.cellIndex ?? -1) === (hoveredBehind.cellIndex ?? -1)) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5524
+ hoveredBehind && !(selectedEmbed && selectedEmbed.blockIndex === hoveredBehind.blockIndex && selectedEmbed.offset === hoveredBehind.offset && (selectedEmbed.cellIndex ?? -1) === (hoveredBehind.cellIndex ?? -1)) && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4671
5525
  BehindImageSelectAffordance,
4672
5526
  {
4673
5527
  rootRef,
@@ -4688,8 +5542,8 @@ function Editor({
4688
5542
  })
4689
5543
  }
4690
5544
  ),
4691
- hoveredLink && hoveredLink.href && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LinkHoverTooltip, { href: hoveredLink.href, rect: hoveredLink.rect }),
4692
- awareness && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5545
+ hoveredLink && hoveredLink.href && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LinkHoverTooltip, { href: hoveredLink.href, rect: hoveredLink.rect }),
5546
+ awareness && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4693
5547
  RemoteCursorsOverlay,
4694
5548
  {
4695
5549
  rootRef,
@@ -4701,7 +5555,7 @@ function Editor({
4701
5555
  ]
4702
5556
  }
4703
5557
  );
4704
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(EditorProvider, { editor, children: body });
5558
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EditorProvider, { editor, children: body });
4705
5559
  }
4706
5560
  function groupTopLevels(snapshot) {
4707
5561
  const out = [];
@@ -4755,7 +5609,7 @@ function renderSlot(slot, topLevels) {
4755
5609
  start: slot.fragment.start,
4756
5610
  end: slot.fragment.end
4757
5611
  };
4758
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5612
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4759
5613
  NodeView,
4760
5614
  {
4761
5615
  block: top.block,
@@ -4766,7 +5620,7 @@ function renderSlot(slot, topLevels) {
4766
5620
  );
4767
5621
  }
4768
5622
  if (slot.tableFragment && top.kind === "block" && top.block.type === "table") {
4769
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5623
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4770
5624
  NodeView,
4771
5625
  {
4772
5626
  block: top.block,
@@ -4786,7 +5640,7 @@ function renderTopLevel(top) {
4786
5640
  const tree = buildListTree(top.items);
4787
5641
  return renderListTree(tree, top, top.ordinalStart, `list-${top.key}`);
4788
5642
  }
4789
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(NodeView, { block: top.block, index: top.blockIndex }, top.key);
5643
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(NodeView, { block: top.block, index: top.blockIndex }, top.key);
4790
5644
  }
4791
5645
  function renderListFragment(top, frag) {
4792
5646
  const ranges = topLevelItemRanges(top.items);
@@ -4828,9 +5682,9 @@ function buildListTree(items) {
4828
5682
  function renderListTree(tree, top, start, key) {
4829
5683
  const className = `ed-list ed-list-${top.listKind}`;
4830
5684
  const style = top.listStyle ? { listStyleType: top.listStyle } : void 0;
4831
- const items = tree.map((node) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(NodeView, { block: node.entry.block, index: node.entry.index, children: node.children.length > 0 ? renderNestedListTree(node.children, `nested-${node.entry.index}`) : null }, node.entry.index));
5685
+ const items = tree.map((node) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(NodeView, { block: node.entry.block, index: node.entry.index, children: node.children.length > 0 ? renderNestedListTree(node.children, `nested-${node.entry.index}`) : null }, node.entry.index));
4832
5686
  if (top.listKind === "ordered") {
4833
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5687
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4834
5688
  "ol",
4835
5689
  {
4836
5690
  className,
@@ -4842,12 +5696,12 @@ function renderListTree(tree, top, start, key) {
4842
5696
  key
4843
5697
  );
4844
5698
  }
4845
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ul", { className, "data-list-kind": "bullet", style, children: items }, key);
5699
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("ul", { className, "data-list-kind": "bullet", style, children: items }, key);
4846
5700
  }
4847
5701
  function renderNestedListTree(tree, key) {
4848
5702
  const kind = tree[0]?.entry.block.attrs.listKind === "ordered" ? "ordered" : "bullet";
4849
5703
  const Tag = kind === "ordered" ? "ol" : "ul";
4850
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Tag, { className: `ed-list ed-list-${kind}`, "data-list-kind": kind, children: tree.map((node) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(NodeView, { block: node.entry.block, index: node.entry.index, children: node.children.length > 0 ? renderNestedListTree(node.children, `nested-${node.entry.index}`) : null }, node.entry.index)) }, key);
5704
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Tag, { className: `ed-list ed-list-${kind}`, "data-list-kind": kind, children: tree.map((node) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(NodeView, { block: node.entry.block, index: node.entry.index, children: node.children.length > 0 ? renderNestedListTree(node.children, `nested-${node.entry.index}`) : null }, node.entry.index)) }, key);
4851
5705
  }
4852
5706
  function clampListLevel2(l) {
4853
5707
  if (typeof l !== "number" || !Number.isFinite(l)) return 0;
@@ -4875,9 +5729,76 @@ function caretRangeFromPoint(x, y) {
4875
5729
  }
4876
5730
 
4877
5731
  // src/Toolbar.tsx
4878
- var import_react15 = require("react");
4879
- var import_core9 = require("@sofereditor/core");
4880
- var import_jsx_runtime13 = require("react/jsx-runtime");
5732
+ var import_react16 = require("react");
5733
+ var import_core11 = require("@sofereditor/core");
5734
+
5735
+ // src/TableBorderPanel.tsx
5736
+ var import_jsx_runtime14 = require("react/jsx-runtime");
5737
+ var BORDER_PRESETS = [
5738
+ { key: "all", label: "Todas", glyph: "\u229E" },
5739
+ { key: "outer", label: "S\xF3 externas", glyph: "\u25A1" },
5740
+ { key: "horizontal", label: "S\xF3 horizontais", glyph: "\u25A4" },
5741
+ { key: "vertical", label: "S\xF3 verticais", glyph: "\u25A5" },
5742
+ { key: "none", label: "Nenhuma", glyph: "\u2B1A" }
5743
+ ];
5744
+ var BORDER_MENU_GLYPH = "\u229E";
5745
+ function TableBorderPanel({
5746
+ preset,
5747
+ color,
5748
+ onPreset,
5749
+ onColor,
5750
+ onResetColor
5751
+ }) {
5752
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "ed-border-panel", children: [
5753
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "ed-border-presets", children: BORDER_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
5754
+ "button",
5755
+ {
5756
+ type: "button",
5757
+ className: "ed-border-preset",
5758
+ "aria-pressed": preset === p.key,
5759
+ title: p.label,
5760
+ onClick: (e) => {
5761
+ e.preventDefault();
5762
+ onPreset(p.key);
5763
+ },
5764
+ children: [
5765
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ed-border-glyph", "aria-hidden": true, children: p.glyph }),
5766
+ p.label
5767
+ ]
5768
+ },
5769
+ p.key
5770
+ )) }),
5771
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("hr", {}),
5772
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "ed-toolbar-label ed-border-color", children: [
5773
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ed-toolbar-swatch", "aria-hidden": true, style: { background: color } }),
5774
+ "Cor da linha",
5775
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5776
+ "input",
5777
+ {
5778
+ type: "color",
5779
+ value: color,
5780
+ onChange: (e) => onColor(e.target.value),
5781
+ "aria-label": "Cor da linha da borda"
5782
+ }
5783
+ )
5784
+ ] }),
5785
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5786
+ "button",
5787
+ {
5788
+ type: "button",
5789
+ className: "ed-border-reset",
5790
+ onClick: (e) => {
5791
+ e.preventDefault();
5792
+ onResetColor();
5793
+ },
5794
+ children: "Padr\xE3o"
5795
+ }
5796
+ )
5797
+ ] });
5798
+ }
5799
+
5800
+ // src/Toolbar.tsx
5801
+ var import_jsx_runtime15 = require("react/jsx-runtime");
4881
5802
  var FONT_FAMILIES = ["Arial"];
4882
5803
  var FONT_SIZES = ["8pt", "10pt", "11pt", "12pt", "14pt", "16pt", "18pt", "24pt", "32pt", "48pt"];
4883
5804
  var BLOCK_OPTIONS = [
@@ -4981,14 +5902,14 @@ function Toolbar({ className }) {
4981
5902
  }
4982
5903
  setAlign(value);
4983
5904
  };
4984
- const onInsertImageClick = (0, import_react15.useCallback)(
5905
+ const onInsertImageClick = (0, import_react16.useCallback)(
4985
5906
  (e) => {
4986
5907
  e.preventDefault();
4987
5908
  imageInputRef.current?.click();
4988
5909
  },
4989
5910
  []
4990
5911
  );
4991
- const onImageInputChange = (0, import_react15.useCallback)(
5912
+ const onImageInputChange = (0, import_react16.useCallback)(
4992
5913
  (e) => {
4993
5914
  const file = e.target.files?.[0];
4994
5915
  if (file) void editor.insertImageFromFile(file);
@@ -4996,14 +5917,14 @@ function Toolbar({ className }) {
4996
5917
  },
4997
5918
  [editor]
4998
5919
  );
4999
- const imageInputRef = (0, import_react15.useRef)(null);
5920
+ const imageInputRef = (0, import_react16.useRef)(null);
5000
5921
  const onToggleDir = (e) => {
5001
5922
  e.preventDefault();
5002
5923
  const next = blockDir === "rtl" ? "ltr" : "rtl";
5003
5924
  setBlockAttr("dir", next);
5004
5925
  };
5005
5926
  const linkActive = isMarkActive("link");
5006
- const onLinkClick = (0, import_react15.useCallback)(
5927
+ const onLinkClick = (0, import_react16.useCallback)(
5007
5928
  (e) => {
5008
5929
  e.preventDefault();
5009
5930
  const currentHref = active.link && typeof active.link === "object" && "href" in active.link ? active.link.href : "";
@@ -5034,7 +5955,7 @@ function Toolbar({ className }) {
5034
5955
  sel.cellIndex
5035
5956
  );
5036
5957
  };
5037
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
5958
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5038
5959
  "div",
5039
5960
  {
5040
5961
  className: className ?? "ed-toolbar",
@@ -5042,7 +5963,7 @@ function Toolbar({ className }) {
5042
5963
  "aria-label": "Editor toolbar",
5043
5964
  onMouseDown: stop,
5044
5965
  children: [
5045
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
5966
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5046
5967
  "select",
5047
5968
  {
5048
5969
  className: "ed-toolbar-select",
@@ -5051,23 +5972,23 @@ function Toolbar({ className }) {
5051
5972
  onMouseDown: stop,
5052
5973
  "aria-label": "Tipo de bloco",
5053
5974
  children: [
5054
- blockValue === "" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "", children: "\u2014 (misto)" }),
5055
- BLOCK_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: o.value, children: o.label }, o.value))
5975
+ blockValue === "" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: "", children: "\u2014 (misto)" }),
5976
+ BLOCK_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: o.value, children: o.label }, o.value))
5056
5977
  ]
5057
5978
  }
5058
5979
  ) }),
5059
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5060
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MarkButton, { title: "Negrito (\u2318B)", pressed: isMarkActive("bold"), onClick: onToggle("bold"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "B" }) }),
5061
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MarkButton, { title: "It\xE1lico (\u2318I)", pressed: isMarkActive("italic"), onClick: onToggle("italic"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("em", { children: "I" }) }),
5062
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MarkButton, { title: "Sublinhado (\u2318U)", pressed: isMarkActive("underline"), onClick: onToggle("underline"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("u", { children: "U" }) }),
5063
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MarkButton, { title: "Tachado (\u2318\u21E7X)", pressed: isMarkActive("strike"), onClick: onToggle("strike"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("s", { children: "S" }) })
5980
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Group, { children: [
5981
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MarkButton, { title: "Negrito (\u2318B)", pressed: isMarkActive("bold"), onClick: onToggle("bold"), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { children: "B" }) }),
5982
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MarkButton, { title: "It\xE1lico (\u2318I)", pressed: isMarkActive("italic"), onClick: onToggle("italic"), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("em", { children: "I" }) }),
5983
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MarkButton, { title: "Sublinhado (\u2318U)", pressed: isMarkActive("underline"), onClick: onToggle("underline"), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("u", { children: "U" }) }),
5984
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MarkButton, { title: "Tachado (\u2318\u21E7X)", pressed: isMarkActive("strike"), onClick: onToggle("strike"), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("s", { children: "S" }) })
5064
5985
  ] }),
5065
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5066
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label", children: [
5067
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ed-toolbar-swatch", "aria-hidden": true, style: { background: colorValue } }),
5068
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "color", value: colorValue, onChange: onColorChange, onMouseDown: stop, "aria-label": "Cor do texto" })
5986
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Group, { children: [
5987
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "ed-toolbar-label", children: [
5988
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "ed-toolbar-swatch", "aria-hidden": true, style: { background: colorValue } }),
5989
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("input", { type: "color", value: colorValue, onChange: onColorChange, onMouseDown: stop, "aria-label": "Cor do texto" })
5069
5990
  ] }),
5070
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5991
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5071
5992
  "button",
5072
5993
  {
5073
5994
  type: "button",
@@ -5081,8 +6002,8 @@ function Toolbar({ className }) {
5081
6002
  children: "\u232B"
5082
6003
  }
5083
6004
  ),
5084
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label", title: "Marca-texto", children: [
5085
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6005
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "ed-toolbar-label", title: "Marca-texto", children: [
6006
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5086
6007
  "span",
5087
6008
  {
5088
6009
  className: "ed-toolbar-swatch ed-toolbar-swatch--highlight",
@@ -5090,7 +6011,7 @@ function Toolbar({ className }) {
5090
6011
  style: { background: highlightValue }
5091
6012
  }
5092
6013
  ),
5093
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6014
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5094
6015
  "input",
5095
6016
  {
5096
6017
  type: "color",
@@ -5101,7 +6022,7 @@ function Toolbar({ className }) {
5101
6022
  }
5102
6023
  )
5103
6024
  ] }),
5104
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6025
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5105
6026
  "button",
5106
6027
  {
5107
6028
  type: "button",
@@ -5116,8 +6037,8 @@ function Toolbar({ className }) {
5116
6037
  }
5117
6038
  )
5118
6039
  ] }),
5119
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5120
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6040
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Group, { children: [
6041
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5121
6042
  "select",
5122
6043
  {
5123
6044
  className: "ed-toolbar-select",
@@ -5126,12 +6047,12 @@ function Toolbar({ className }) {
5126
6047
  onMouseDown: stop,
5127
6048
  "aria-label": "Fam\xEDlia da fonte",
5128
6049
  children: [
5129
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "", children: "Fonte\u2026" }),
5130
- FONT_FAMILIES.map((f) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: f, children: f }, f))
6050
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: "", children: "Fonte\u2026" }),
6051
+ FONT_FAMILIES.map((f) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: f, children: f }, f))
5131
6052
  ]
5132
6053
  }
5133
6054
  ),
5134
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6055
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5135
6056
  "select",
5136
6057
  {
5137
6058
  className: "ed-toolbar-select",
@@ -5140,13 +6061,13 @@ function Toolbar({ className }) {
5140
6061
  onMouseDown: stop,
5141
6062
  "aria-label": "Tamanho da fonte",
5142
6063
  children: [
5143
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "", children: "Tamanho\u2026" }),
5144
- FONT_SIZES.map((s) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: s, children: s }, s))
6064
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: "", children: "Tamanho\u2026" }),
6065
+ FONT_SIZES.map((s) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: s, children: s }, s))
5145
6066
  ]
5146
6067
  }
5147
6068
  )
5148
6069
  ] }),
5149
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { children: ALIGN_OPTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6070
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Group, { children: ALIGN_OPTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5150
6071
  "button",
5151
6072
  {
5152
6073
  type: "button",
@@ -5159,7 +6080,7 @@ function Toolbar({ className }) {
5159
6080
  },
5160
6081
  a.value
5161
6082
  )) }),
5162
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6083
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5163
6084
  "button",
5164
6085
  {
5165
6086
  type: "button",
@@ -5171,8 +6092,8 @@ function Toolbar({ className }) {
5171
6092
  children: blockDir === "rtl" ? "RTL" : "LTR"
5172
6093
  }
5173
6094
  ) }),
5174
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5175
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6095
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Group, { children: [
6096
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5176
6097
  "button",
5177
6098
  {
5178
6099
  type: "button",
@@ -5187,7 +6108,7 @@ function Toolbar({ className }) {
5187
6108
  children: "\u2022"
5188
6109
  }
5189
6110
  ),
5190
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6111
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5191
6112
  "button",
5192
6113
  {
5193
6114
  type: "button",
@@ -5202,7 +6123,7 @@ function Toolbar({ className }) {
5202
6123
  children: "1."
5203
6124
  }
5204
6125
  ),
5205
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6126
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5206
6127
  "button",
5207
6128
  {
5208
6129
  type: "button",
@@ -5216,7 +6137,7 @@ function Toolbar({ className }) {
5216
6137
  children: "\u21E4"
5217
6138
  }
5218
6139
  ),
5219
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6140
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5220
6141
  "button",
5221
6142
  {
5222
6143
  type: "button",
@@ -5231,7 +6152,7 @@ function Toolbar({ className }) {
5231
6152
  }
5232
6153
  )
5233
6154
  ] }),
5234
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6155
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5235
6156
  "button",
5236
6157
  {
5237
6158
  type: "button",
@@ -5243,12 +6164,12 @@ function Toolbar({ className }) {
5243
6164
  children: "\u{1F517}"
5244
6165
  }
5245
6166
  ) }),
5246
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5247
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TableMenu, {}),
5248
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AnswerLinesMenu, {})
6167
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Group, { children: [
6168
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TableMenu, {}),
6169
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AnswerLinesMenu, {})
5249
6170
  ] }),
5250
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5251
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6171
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Group, { children: [
6172
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5252
6173
  "button",
5253
6174
  {
5254
6175
  type: "button",
@@ -5259,7 +6180,7 @@ function Toolbar({ className }) {
5259
6180
  children: "\u{1F5BC}"
5260
6181
  }
5261
6182
  ),
5262
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6183
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5263
6184
  "input",
5264
6185
  {
5265
6186
  ref: imageInputRef,
@@ -5268,10 +6189,26 @@ function Toolbar({ className }) {
5268
6189
  hidden: true,
5269
6190
  onChange: onImageInputChange
5270
6191
  }
6192
+ ),
6193
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
6194
+ "button",
6195
+ {
6196
+ type: "button",
6197
+ className: "ed-toolbar-btn",
6198
+ title: "Inserir f\xF3rmula",
6199
+ onMouseDown: stop,
6200
+ onClick: (e) => {
6201
+ e.preventDefault();
6202
+ void editor.requestFormula().then((r) => r ? editor.insertFormula(r.latex, r.display) : void 0).catch((err) => {
6203
+ console.error("Falha ao inserir f\xF3rmula:", err);
6204
+ });
6205
+ },
6206
+ children: "\u221Ax"
6207
+ }
5271
6208
  )
5272
6209
  ] }),
5273
- selectedEmbed && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5274
- IMAGE_LAYOUT_OPTIONS.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6210
+ selectedEmbed && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Group, { children: [
6211
+ IMAGE_LAYOUT_OPTIONS.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5275
6212
  "button",
5276
6213
  {
5277
6214
  type: "button",
@@ -5284,7 +6221,25 @@ function Toolbar({ className }) {
5284
6221
  },
5285
6222
  opt.value
5286
6223
  )),
5287
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6224
+ (0, import_core11.isFormulaEmbed)(selectedEmbed.embed) ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
6225
+ "button",
6226
+ {
6227
+ type: "button",
6228
+ className: "ed-toolbar-btn",
6229
+ title: "Editar f\xF3rmula",
6230
+ onMouseDown: stop,
6231
+ onClick: (e) => {
6232
+ e.preventDefault();
6233
+ if (!(0, import_core11.isFormulaEmbed)(selectedEmbed.embed)) return;
6234
+ const f = selectedEmbed.embed.formula;
6235
+ void editor.requestFormula(f.latex, f.display).then((r) => {
6236
+ if (!r) return;
6237
+ void editor.insertFormula(r.latex, r.display);
6238
+ });
6239
+ },
6240
+ children: "Editar f\xF3rmula"
6241
+ }
6242
+ ) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5288
6243
  "button",
5289
6244
  {
5290
6245
  type: "button",
@@ -5314,7 +6269,7 @@ function Toolbar({ className }) {
5314
6269
  }
5315
6270
  )
5316
6271
  ] }),
5317
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6272
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5318
6273
  "button",
5319
6274
  {
5320
6275
  type: "button",
@@ -5334,11 +6289,11 @@ function Toolbar({ className }) {
5334
6289
  }
5335
6290
  function AnswerLinesMenu() {
5336
6291
  const editor = useEditorContext();
5337
- const [open, setOpen] = (0, import_react15.useState)(false);
5338
- const [count, setCount] = (0, import_react15.useState)(5);
5339
- const [spacing, setSpacing] = (0, import_react15.useState)(1.5);
5340
- const rootRef = (0, import_react15.useRef)(null);
5341
- (0, import_react15.useEffect)(() => {
6292
+ const [open, setOpen] = (0, import_react16.useState)(false);
6293
+ const [count, setCount] = (0, import_react16.useState)(5);
6294
+ const [spacing, setSpacing] = (0, import_react16.useState)(1.5);
6295
+ const rootRef = (0, import_react16.useRef)(null);
6296
+ (0, import_react16.useEffect)(() => {
5342
6297
  if (!open) return;
5343
6298
  const onDown = (e) => {
5344
6299
  if (!rootRef.current) return;
@@ -5348,9 +6303,9 @@ function AnswerLinesMenu() {
5348
6303
  document.addEventListener("mousedown", onDown);
5349
6304
  return () => document.removeEventListener("mousedown", onDown);
5350
6305
  }, [open]);
5351
- const clamped = Math.max(1, Math.min(import_core9.ANSWER_LINE_MAX, Math.trunc(count) || 1));
5352
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { ref: rootRef, className: "ed-toolbar-tablemenu", children: [
5353
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6306
+ const clamped = Math.max(1, Math.min(import_core11.ANSWER_LINE_MAX, Math.trunc(count) || 1));
6307
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { ref: rootRef, className: "ed-toolbar-tablemenu", children: [
6308
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5354
6309
  "button",
5355
6310
  {
5356
6311
  type: "button",
@@ -5365,7 +6320,7 @@ function AnswerLinesMenu() {
5365
6320
  children: "\u2630"
5366
6321
  }
5367
6322
  ),
5368
- open && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6323
+ open && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5369
6324
  "div",
5370
6325
  {
5371
6326
  className: "ed-table-popover ed-answerlines-popover",
@@ -5374,37 +6329,37 @@ function AnswerLinesMenu() {
5374
6329
  if (!keepsOwnMouseDown(e.target)) e.preventDefault();
5375
6330
  },
5376
6331
  children: [
5377
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label", children: [
6332
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "ed-toolbar-label", children: [
5378
6333
  "Quantidade",
5379
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6334
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5380
6335
  "input",
5381
6336
  {
5382
6337
  type: "number",
5383
6338
  min: 1,
5384
- max: import_core9.ANSWER_LINE_MAX,
6339
+ max: import_core11.ANSWER_LINE_MAX,
5385
6340
  value: count,
5386
6341
  onChange: (e) => setCount(Number(e.target.value)),
5387
6342
  "aria-label": "Quantidade de linhas"
5388
6343
  }
5389
6344
  )
5390
6345
  ] }),
5391
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label", children: [
6346
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "ed-toolbar-label", children: [
5392
6347
  "Entrelinha",
5393
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6348
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5394
6349
  "select",
5395
6350
  {
5396
6351
  value: String(spacing),
5397
6352
  onChange: (e) => setSpacing(Number(e.target.value)),
5398
6353
  "aria-label": "Entrelinha",
5399
6354
  children: [
5400
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "1", children: "Simples" }),
5401
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "1.5", children: "1,5" }),
5402
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "2", children: "Duplo" })
6355
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: "1", children: "Simples" }),
6356
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: "1.5", children: "1,5" }),
6357
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: "2", children: "Duplo" })
5403
6358
  ]
5404
6359
  }
5405
6360
  )
5406
6361
  ] }),
5407
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6362
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5408
6363
  "button",
5409
6364
  {
5410
6365
  type: "button",
@@ -5428,9 +6383,10 @@ function AnswerLinesMenu() {
5428
6383
  function TableMenu() {
5429
6384
  const editor = useEditorContext();
5430
6385
  const inTable = editor.isInTable();
5431
- const [open, setOpen] = (0, import_react15.useState)(false);
5432
- const rootRef = (0, import_react15.useRef)(null);
5433
- (0, import_react15.useEffect)(() => {
6386
+ const [open, setOpen] = (0, import_react16.useState)(false);
6387
+ const [bordersOpen, setBordersOpen] = (0, import_react16.useState)(false);
6388
+ const rootRef = (0, import_react16.useRef)(null);
6389
+ (0, import_react16.useEffect)(() => {
5434
6390
  if (!open) return;
5435
6391
  const onDown = (e) => {
5436
6392
  if (!rootRef.current) return;
@@ -5440,8 +6396,11 @@ function TableMenu() {
5440
6396
  document.addEventListener("mousedown", onDown);
5441
6397
  return () => document.removeEventListener("mousedown", onDown);
5442
6398
  }, [open]);
5443
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { ref: rootRef, className: "ed-toolbar-tablemenu", children: [
5444
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6399
+ (0, import_react16.useEffect)(() => {
6400
+ if (!open) setBordersOpen(false);
6401
+ }, [open]);
6402
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { ref: rootRef, className: "ed-toolbar-tablemenu", children: [
6403
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5445
6404
  "button",
5446
6405
  {
5447
6406
  type: "button",
@@ -5456,7 +6415,7 @@ function TableMenu() {
5456
6415
  children: "\u25A6"
5457
6416
  }
5458
6417
  ),
5459
- open && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6418
+ open && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5460
6419
  "div",
5461
6420
  {
5462
6421
  className: "ed-table-popover",
@@ -5465,7 +6424,7 @@ function TableMenu() {
5465
6424
  if (!keepsOwnMouseDown(e.target)) e.preventDefault();
5466
6425
  },
5467
6426
  children: [
5468
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6427
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5469
6428
  TableSizePicker,
5470
6429
  {
5471
6430
  onPick: (rows, cols) => {
@@ -5474,34 +6433,34 @@ function TableMenu() {
5474
6433
  }
5475
6434
  }
5476
6435
  ),
5477
- inTable && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ed-table-actions", children: [
5478
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", {}),
5479
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6436
+ inTable && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "ed-table-actions", children: [
6437
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", {}),
6438
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5480
6439
  setOpen(false);
5481
6440
  editor.insertRowAbove();
5482
6441
  }, children: "Inserir linha acima" }),
5483
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6442
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5484
6443
  setOpen(false);
5485
6444
  editor.insertRowBelow();
5486
6445
  }, children: "Inserir linha abaixo" }),
5487
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6446
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5488
6447
  setOpen(false);
5489
6448
  editor.insertColumnLeft();
5490
6449
  }, children: "Inserir coluna \xE0 esquerda" }),
5491
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6450
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5492
6451
  setOpen(false);
5493
6452
  editor.insertColumnRight();
5494
6453
  }, children: "Inserir coluna \xE0 direita" }),
5495
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6454
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5496
6455
  setOpen(false);
5497
6456
  editor.deleteCurrentRow();
5498
6457
  }, children: "Excluir linha" }),
5499
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6458
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5500
6459
  setOpen(false);
5501
6460
  editor.deleteCurrentColumn();
5502
6461
  }, children: "Excluir coluna" }),
5503
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", {}),
5504
- editor.hasTableRectSelection() && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6462
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", {}),
6463
+ editor.hasTableRectSelection() && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5505
6464
  "button",
5506
6465
  {
5507
6466
  type: "button",
@@ -5512,21 +6471,21 @@ function TableMenu() {
5512
6471
  children: "Mesclar c\xE9lulas selecionadas"
5513
6472
  }
5514
6473
  ),
5515
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6474
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5516
6475
  setOpen(false);
5517
6476
  editor.mergeRight();
5518
6477
  }, children: "Mesclar com c\xE9lula \xE0 direita" }),
5519
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6478
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5520
6479
  setOpen(false);
5521
6480
  editor.mergeDown();
5522
6481
  }, children: "Mesclar com c\xE9lula abaixo" }),
5523
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6482
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5524
6483
  setOpen(false);
5525
6484
  editor.splitCell();
5526
6485
  }, children: "Dividir c\xE9lulas mescladas" }),
5527
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", {}),
5528
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label ed-table-bgcolor", children: [
5529
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6486
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", {}),
6487
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "ed-toolbar-label ed-table-bgcolor", children: [
6488
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5530
6489
  "span",
5531
6490
  {
5532
6491
  className: "ed-toolbar-swatch",
@@ -5535,7 +6494,7 @@ function TableMenu() {
5535
6494
  }
5536
6495
  ),
5537
6496
  "Cor de fundo da c\xE9lula",
5538
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6497
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5539
6498
  "input",
5540
6499
  {
5541
6500
  type: "color",
@@ -5545,62 +6504,39 @@ function TableMenu() {
5545
6504
  }
5546
6505
  )
5547
6506
  ] }),
5548
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6507
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5549
6508
  setOpen(false);
5550
6509
  editor.setCellBackground(null);
5551
6510
  }, children: "Remover cor de fundo" }),
5552
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", {}),
5553
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label", children: [
5554
- "Bordas",
5555
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
5556
- "select",
5557
- {
5558
- value: editor.getTableBorderPreset(),
5559
- onChange: (e) => editor.setTableBorderPreset(e.target.value),
5560
- "aria-label": "Bordas da tabela",
5561
- children: [
5562
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "all", children: "Todas" }),
5563
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "outer", children: "S\xF3 externas" }),
5564
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "horizontal", children: "S\xF3 horizontais" }),
5565
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "vertical", children: "S\xF3 verticais" }),
5566
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "none", children: "Nenhuma" })
5567
- ]
5568
- }
5569
- )
5570
- ] }),
5571
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label ed-table-bgcolor", children: [
5572
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5573
- "span",
5574
- {
5575
- className: "ed-toolbar-swatch",
5576
- "aria-hidden": true,
5577
- style: { background: editor.getTableBorderColor() ?? import_core9.TABLE_BORDER_COLOR }
5578
- }
5579
- ),
5580
- "Cor da borda",
5581
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5582
- "input",
5583
- {
5584
- type: "color",
5585
- value: editor.getTableBorderColor() ?? import_core9.TABLE_BORDER_COLOR,
5586
- onChange: (e) => editor.setTableBorderColor(e.target.value),
5587
- "aria-label": "Cor da borda"
5588
- }
5589
- )
5590
- ] }),
5591
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6511
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", {}),
6512
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5592
6513
  "button",
5593
6514
  {
5594
6515
  type: "button",
5595
- onClick: () => {
5596
- setOpen(false);
5597
- editor.setTableBorderColor(null);
6516
+ className: "ed-border-toggle",
6517
+ "aria-pressed": bordersOpen,
6518
+ "aria-expanded": bordersOpen,
6519
+ title: "Bordas da tabela",
6520
+ "aria-label": "Bordas da tabela",
6521
+ onClick: (e) => {
6522
+ e.preventDefault();
6523
+ setBordersOpen((v) => !v);
5598
6524
  },
5599
- children: "Restaurar cor padr\xE3o"
6525
+ children: BORDER_MENU_GLYPH
6526
+ }
6527
+ ),
6528
+ bordersOpen && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
6529
+ TableBorderPanel,
6530
+ {
6531
+ preset: editor.getTableBorderPreset(),
6532
+ color: editor.getTableBorderColor() ?? import_core11.TABLE_BORDER_COLOR,
6533
+ onPreset: (p) => editor.setTableBorderPreset(p),
6534
+ onColor: (c) => editor.setTableBorderColor(c),
6535
+ onResetColor: () => editor.setTableBorderColor(null)
5600
6536
  }
5601
6537
  ),
5602
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", {}),
5603
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6538
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", {}),
6539
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5604
6540
  "button",
5605
6541
  {
5606
6542
  type: "button",
@@ -5621,11 +6557,11 @@ function TableMenu() {
5621
6557
  var PICKER_MAX_ROWS = 8;
5622
6558
  var PICKER_MAX_COLS = 10;
5623
6559
  function TableSizePicker({ onPick }) {
5624
- const [hover, setHover] = (0, import_react15.useState)(null);
6560
+ const [hover, setHover] = (0, import_react16.useState)(null);
5625
6561
  const label = hover ? `${hover.r + 1} \xD7 ${hover.c + 1}` : "Inserir tabela";
5626
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ed-table-picker", children: [
5627
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ed-table-picker-label", children: label }),
5628
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6562
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "ed-table-picker", children: [
6563
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "ed-table-picker-label", children: label }),
6564
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5629
6565
  "div",
5630
6566
  {
5631
6567
  className: "ed-table-picker-grid",
@@ -5638,7 +6574,7 @@ function TableSizePicker({ onPick }) {
5638
6574
  { length: PICKER_MAX_ROWS },
5639
6575
  (_, r) => Array.from({ length: PICKER_MAX_COLS }, (_2, c) => {
5640
6576
  const filled = hover != null && r <= hover.r && c <= hover.c;
5641
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6577
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5642
6578
  "button",
5643
6579
  {
5644
6580
  type: "button",
@@ -5668,10 +6604,10 @@ function blockSelectValue(type, level) {
5668
6604
  return type;
5669
6605
  }
5670
6606
  function Group({ children }) {
5671
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ed-toolbar-group", children });
6607
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "ed-toolbar-group", children });
5672
6608
  }
5673
6609
  function MarkButton({ title, pressed, onClick, children }) {
5674
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6610
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5675
6611
  "button",
5676
6612
  {
5677
6613
  type: "button",
@@ -5689,6 +6625,7 @@ function MarkButton({ title, pressed, onClick, children }) {
5689
6625
  A4_PAGE,
5690
6626
  Editor,
5691
6627
  EditorProvider,
6628
+ FormulaDialog,
5692
6629
  ImageCaptionDialog,
5693
6630
  LinkDialog,
5694
6631
  NodeView,