@sofereditor/react 0.7.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_core9 = 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) {
@@ -1293,7 +1304,7 @@ function LinkHoverTooltip({ href, rect }) {
1293
1304
  }
1294
1305
 
1295
1306
  // src/EditorContext.tsx
1296
- var import_react5 = require("react");
1307
+ var import_react6 = require("react");
1297
1308
 
1298
1309
  // src/LinkDialog.tsx
1299
1310
  var import_react2 = require("react");
@@ -1822,19 +1833,380 @@ function ImageCaptionDialog() {
1822
1833
  );
1823
1834
  }
1824
1835
 
1825
- // 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
1826
2005
  var import_jsx_runtime6 = require("react/jsx-runtime");
1827
- var EditorContext = (0, import_react5.createContext)(null);
1828
- function EditorProvider({ editor, children }) {
1829
- 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: [
1830
2201
  children,
1831
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(LinkDialog, {}),
1832
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PageConfigDialog, {}),
1833
- /* @__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 })
1834
2206
  ] });
1835
2207
  }
1836
2208
  function useEditorContext() {
1837
- const ctx = (0, import_react5.useContext)(EditorContext);
2209
+ const ctx = (0, import_react6.useContext)(EditorContext);
1838
2210
  if (!ctx) {
1839
2211
  throw new Error("useEditorContext must be used inside an <EditorProvider>");
1840
2212
  }
@@ -1842,8 +2214,8 @@ function useEditorContext() {
1842
2214
  }
1843
2215
 
1844
2216
  // src/ImageResizeOverlay.tsx
1845
- var import_react6 = require("react");
1846
- var import_jsx_runtime7 = require("react/jsx-runtime");
2217
+ var import_react7 = require("react");
2218
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1847
2219
  function ImageResizeOverlay({
1848
2220
  rootRef,
1849
2221
  blockIndex,
@@ -1854,10 +2226,10 @@ function ImageResizeOverlay({
1854
2226
  onCommitMove,
1855
2227
  onReanchor
1856
2228
  }) {
1857
- const [rect, setRect] = (0, import_react6.useState)(null);
1858
- const [isMoving, setIsMoving] = (0, import_react6.useState)(false);
1859
- const imgRef = (0, import_react6.useRef)(null);
1860
- 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)(() => {
1861
2233
  const root = rootRef.current;
1862
2234
  if (!root) return null;
1863
2235
  let container = null;
@@ -1875,7 +2247,7 @@ function ImageResizeOverlay({
1875
2247
  `img[data-embed="image"][data-embed-offset="${localOffset}"]`
1876
2248
  );
1877
2249
  }, [rootRef, blockIndex, offset, cellIndex]);
1878
- const measure = (0, import_react6.useCallback)(() => {
2250
+ const measure = (0, import_react7.useCallback)(() => {
1879
2251
  const img = locateImage();
1880
2252
  if (!img) {
1881
2253
  setRect((prev) => prev === null ? prev : null);
@@ -1896,7 +2268,7 @@ function ImageResizeOverlay({
1896
2268
  (prev) => prev && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
1897
2269
  );
1898
2270
  }, [locateImage, rootRef]);
1899
- (0, import_react6.useLayoutEffect)(() => {
2271
+ (0, import_react7.useLayoutEffect)(() => {
1900
2272
  measure();
1901
2273
  let cancelled = false;
1902
2274
  let frame = 0;
@@ -1926,7 +2298,7 @@ function ImageResizeOverlay({
1926
2298
  embed.offsetX,
1927
2299
  embed.offsetY
1928
2300
  ]);
1929
- (0, import_react6.useEffect)(() => {
2301
+ (0, import_react7.useEffect)(() => {
1930
2302
  const root = rootRef.current;
1931
2303
  if (!root) return;
1932
2304
  const onScroll = () => measure();
@@ -1937,7 +2309,7 @@ function ImageResizeOverlay({
1937
2309
  root.removeEventListener("scroll", onScroll);
1938
2310
  };
1939
2311
  }, [measure, rootRef]);
1940
- (0, import_react6.useEffect)(() => {
2312
+ (0, import_react7.useEffect)(() => {
1941
2313
  if (typeof ResizeObserver === "undefined") return;
1942
2314
  const img = locateImage();
1943
2315
  const root = rootRef.current;
@@ -1950,7 +2322,7 @@ function ImageResizeOverlay({
1950
2322
  if (!rect) return null;
1951
2323
  const layout = embed.layout ?? "inline";
1952
2324
  const movable = layout !== "inline" && onCommitMove !== void 0;
1953
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2325
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1954
2326
  "div",
1955
2327
  {
1956
2328
  className: "ed-image-overlay",
@@ -1961,7 +2333,7 @@ function ImageResizeOverlay({
1961
2333
  // follows the cursor, so the image stays visible while it crosses the
1962
2334
  // page boundary (the real, clipped figure is hidden during the drag).
1963
2335
  // Inline styles only — the package does not ship CSS.
1964
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2336
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1965
2337
  "img",
1966
2338
  {
1967
2339
  src: embed.src,
@@ -1979,7 +2351,7 @@ function ImageResizeOverlay({
1979
2351
  }
1980
2352
  }
1981
2353
  ),
1982
- movable && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2354
+ movable && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1983
2355
  MoveHandle,
1984
2356
  {
1985
2357
  layout,
@@ -1997,7 +2369,7 @@ function ImageResizeOverlay({
1997
2369
  onMoveEnd: () => setIsMoving(false)
1998
2370
  }
1999
2371
  ),
2000
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2372
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2001
2373
  Handle,
2002
2374
  {
2003
2375
  corner: "nw",
@@ -2008,7 +2380,7 @@ function ImageResizeOverlay({
2008
2380
  onLiveChange: measure
2009
2381
  }
2010
2382
  ),
2011
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2383
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2012
2384
  Handle,
2013
2385
  {
2014
2386
  corner: "ne",
@@ -2019,7 +2391,7 @@ function ImageResizeOverlay({
2019
2391
  onLiveChange: measure
2020
2392
  }
2021
2393
  ),
2022
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2394
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2023
2395
  Handle,
2024
2396
  {
2025
2397
  corner: "sw",
@@ -2030,7 +2402,7 @@ function ImageResizeOverlay({
2030
2402
  onLiveChange: measure
2031
2403
  }
2032
2404
  ),
2033
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2405
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2034
2406
  Handle,
2035
2407
  {
2036
2408
  corner: "se",
@@ -2060,7 +2432,7 @@ function MoveHandle({
2060
2432
  onMoveStart,
2061
2433
  onMoveEnd
2062
2434
  }) {
2063
- const dragRef = (0, import_react6.useRef)(null);
2435
+ const dragRef = (0, import_react7.useRef)(null);
2064
2436
  const onPointerDown = (e) => {
2065
2437
  if (e.button !== 0) return;
2066
2438
  if (!imgRef.current) return;
@@ -2210,7 +2582,7 @@ function MoveHandle({
2210
2582
  newOffsetY
2211
2583
  );
2212
2584
  };
2213
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2585
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2214
2586
  "div",
2215
2587
  {
2216
2588
  className: "ed-image-move",
@@ -2230,7 +2602,7 @@ function Handle({
2230
2602
  onCommit,
2231
2603
  onLiveChange
2232
2604
  }) {
2233
- const dragRef = (0, import_react6.useRef)(null);
2605
+ const dragRef = (0, import_react7.useRef)(null);
2234
2606
  const onPointerDown = (e) => {
2235
2607
  if (e.button !== 0) return;
2236
2608
  if (!imgRef.current) return;
@@ -2273,7 +2645,7 @@ function Handle({
2273
2645
  }
2274
2646
  onCommit(Math.round(d.liveW), Math.round(d.liveH));
2275
2647
  };
2276
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2648
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2277
2649
  "div",
2278
2650
  {
2279
2651
  className: `ed-image-handle ${corner}`,
@@ -2286,9 +2658,9 @@ function Handle({
2286
2658
  }
2287
2659
 
2288
2660
  // src/RemoteCursorsOverlay.tsx
2289
- var import_react7 = require("react");
2661
+ var import_react8 = require("react");
2290
2662
  var import_core5 = require("@sofereditor/core");
2291
- var import_jsx_runtime8 = require("react/jsx-runtime");
2663
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2292
2664
  var DEFAULT_COLOR = "#3b82f6";
2293
2665
  function RemoteCursorsOverlay({
2294
2666
  rootRef,
@@ -2296,9 +2668,9 @@ function RemoteCursorsOverlay({
2296
2668
  awareness,
2297
2669
  revision
2298
2670
  }) {
2299
- const [views, setViews] = (0, import_react7.useState)([]);
2300
- const rafRef = (0, import_react7.useRef)(null);
2301
- 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)(() => {
2302
2674
  const root = rootRef.current;
2303
2675
  if (!root) {
2304
2676
  setViews((prev) => prev.length === 0 ? prev : []);
@@ -2363,7 +2735,7 @@ function RemoteCursorsOverlay({
2363
2735
  });
2364
2736
  setViews(out);
2365
2737
  }, [rootRef, doc, awareness]);
2366
- const scheduleMeasure = (0, import_react7.useCallback)(() => {
2738
+ const scheduleMeasure = (0, import_react8.useCallback)(() => {
2367
2739
  if (rafRef.current != null) return;
2368
2740
  const raf = typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb) => setTimeout(() => cb(0), 16);
2369
2741
  rafRef.current = raf(() => {
@@ -2371,16 +2743,16 @@ function RemoteCursorsOverlay({
2371
2743
  measure();
2372
2744
  });
2373
2745
  }, [measure]);
2374
- (0, import_react7.useEffect)(() => {
2746
+ (0, import_react8.useEffect)(() => {
2375
2747
  const onChange = () => scheduleMeasure();
2376
2748
  awareness.on("change", onChange);
2377
2749
  scheduleMeasure();
2378
2750
  return () => awareness.off("change", onChange);
2379
2751
  }, [awareness, scheduleMeasure]);
2380
- (0, import_react7.useEffect)(() => {
2752
+ (0, import_react8.useEffect)(() => {
2381
2753
  scheduleMeasure();
2382
2754
  }, [revision, scheduleMeasure]);
2383
- (0, import_react7.useEffect)(() => {
2755
+ (0, import_react8.useEffect)(() => {
2384
2756
  const root = rootRef.current;
2385
2757
  if (!root) return;
2386
2758
  const onScroll = () => scheduleMeasure();
@@ -2402,8 +2774,8 @@ function RemoteCursorsOverlay({
2402
2774
  pointerEvents: "none",
2403
2775
  zIndex: 6
2404
2776
  };
2405
- 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: [
2406
- 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)(
2407
2779
  "div",
2408
2780
  {
2409
2781
  style: {
@@ -2419,7 +2791,7 @@ function RemoteCursorsOverlay({
2419
2791
  },
2420
2792
  i
2421
2793
  )),
2422
- v.caret && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2794
+ v.caret && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2423
2795
  "div",
2424
2796
  {
2425
2797
  style: {
@@ -2430,7 +2802,7 @@ function RemoteCursorsOverlay({
2430
2802
  width: 2,
2431
2803
  background: v.color
2432
2804
  },
2433
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2805
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2434
2806
  "span",
2435
2807
  {
2436
2808
  style: {
@@ -2456,16 +2828,16 @@ function RemoteCursorsOverlay({
2456
2828
  }
2457
2829
 
2458
2830
  // src/NodeView.tsx
2459
- var import_react10 = require("react");
2460
- var import_core7 = require("@sofereditor/core");
2831
+ var import_react11 = require("react");
2832
+ var import_core8 = require("@sofereditor/core");
2461
2833
 
2462
2834
  // src/renderInline.tsx
2463
- var import_react8 = require("react");
2835
+ var import_react9 = require("react");
2464
2836
  var import_core6 = require("@sofereditor/core");
2465
- var import_jsx_runtime9 = require("react/jsx-runtime");
2837
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2466
2838
  function renderInline(delta, keyPrefix) {
2467
2839
  if (delta.length === 0 || delta.length === 1 && typeof delta[0].insert === "string" && delta[0].insert === "") {
2468
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("br", { "data-empty": "true" });
2840
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("br", { "data-empty": "true" });
2469
2841
  }
2470
2842
  let offset = 0;
2471
2843
  const wrapAnchors = [];
@@ -2475,7 +2847,7 @@ function renderInline(delta, keyPrefix) {
2475
2847
  const text = op.insert;
2476
2848
  if (text.length === 0) continue;
2477
2849
  const key = `${keyPrefix}-${offset}`;
2478
- 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));
2479
2851
  offset += text.length;
2480
2852
  } else if ((0, import_core6.isImageEmbed)(op.insert)) {
2481
2853
  const key = `${keyPrefix}-${offset}`;
@@ -2483,10 +2855,10 @@ function renderInline(delta, keyPrefix) {
2483
2855
  const commentMarkId = op.attributes?.comment?.markId;
2484
2856
  if (layout === "wrap-left" || layout === "wrap-right") {
2485
2857
  wrapAnchors.push(
2486
- /* @__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`)
2487
2859
  );
2488
2860
  body.push(
2489
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2861
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2490
2862
  "span",
2491
2863
  {
2492
2864
  "data-embed-phantom": "true",
@@ -2498,10 +2870,10 @@ function renderInline(delta, keyPrefix) {
2498
2870
  )
2499
2871
  );
2500
2872
  } else {
2501
- 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);
2502
2874
  if (commentMarkId) {
2503
2875
  body.push(
2504
- /* @__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`)
2505
2877
  );
2506
2878
  } else {
2507
2879
  body.push(imgNode);
@@ -2512,7 +2884,7 @@ function renderInline(delta, keyPrefix) {
2512
2884
  offset += 1;
2513
2885
  }
2514
2886
  }
2515
- 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" });
2516
2888
  return [...wrapAnchors, ...body];
2517
2889
  }
2518
2890
  var PHANTOM_STYLE = {
@@ -2537,7 +2909,7 @@ function imageEmbedPropsEqual(a, b) {
2537
2909
  // because Y.js stores the embed in its content map and re-exposes it.
2538
2910
  x.src === y.src;
2539
2911
  }
2540
- var ImageEmbedView = (0, import_react8.memo)(ImageEmbedViewImpl, imageEmbedPropsEqual);
2912
+ var ImageEmbedView = (0, import_react9.memo)(ImageEmbedViewImpl, imageEmbedPropsEqual);
2541
2913
  function ImageEmbedViewImpl({
2542
2914
  embed,
2543
2915
  offset,
@@ -2587,7 +2959,9 @@ function ImageEmbedViewImpl({
2587
2959
  marginRight: align === "right" ? 0 : "auto"
2588
2960
  } : {
2589
2961
  display: "inline-block",
2590
- 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",
2591
2965
  width: embed.width
2592
2966
  };
2593
2967
  break;
@@ -2597,7 +2971,7 @@ function ImageEmbedViewImpl({
2597
2971
  height: embed.height,
2598
2972
  display: "block"
2599
2973
  };
2600
- const img = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2974
+ const img = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2601
2975
  "img",
2602
2976
  {
2603
2977
  src: embed.src,
@@ -2617,7 +2991,7 @@ function ImageEmbedViewImpl({
2617
2991
  }
2618
2992
  );
2619
2993
  const captionAlign = embed.captionAlign ?? "center";
2620
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2994
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2621
2995
  "figure",
2622
2996
  {
2623
2997
  className: "ed-figure",
@@ -2627,7 +3001,7 @@ function ImageEmbedViewImpl({
2627
3001
  style: outerStyle,
2628
3002
  children: [
2629
3003
  img,
2630
- hasCaption && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3004
+ hasCaption && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2631
3005
  "figcaption",
2632
3006
  {
2633
3007
  className: "ed-figcaption",
@@ -2644,26 +3018,26 @@ function decorateBlanks(text) {
2644
3018
  const segs = (0, import_core6.splitUnderscoreRuns)(text);
2645
3019
  if (segs.length === 1 && !segs[0].blank) return text;
2646
3020
  return segs.map(
2647
- (s, i) => s.blank ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-blank": "true", style: import_core6.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)
2648
3022
  );
2649
3023
  }
2650
3024
  function wrap(text, attrs) {
2651
3025
  let node = decorateBlanks(text);
2652
3026
  if (!attrs) return node;
2653
- if (attrs.bold) node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: node });
2654
- if (attrs.italic) node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("em", { children: node });
2655
- if (attrs.underline) node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("u", { children: node });
2656
- 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 });
2657
3031
  const styleParts = {};
2658
3032
  if (attrs.color) styleParts.color = attrs.color;
2659
3033
  if (attrs.highlight) styleParts.backgroundColor = attrs.highlight;
2660
3034
  if (attrs.fontFamily) styleParts.fontFamily = attrs.fontFamily;
2661
3035
  if (attrs.fontSize) styleParts.fontSize = attrs.fontSize;
2662
3036
  if (Object.keys(styleParts).length > 0) {
2663
- 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 });
2664
3038
  }
2665
3039
  if (attrs.link?.href) {
2666
- node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3040
+ node = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2667
3041
  "a",
2668
3042
  {
2669
3043
  href: attrs.link.href,
@@ -2682,7 +3056,7 @@ function wrap(text, attrs) {
2682
3056
  );
2683
3057
  }
2684
3058
  if (attrs.comment?.markId) {
2685
- 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 });
2686
3060
  }
2687
3061
  return node;
2688
3062
  }
@@ -2726,16 +3100,25 @@ function sliceDelta(delta, start, end) {
2726
3100
  }
2727
3101
 
2728
3102
  // src/TableResizeOverlay.tsx
2729
- var import_react9 = require("react");
2730
- var import_jsx_runtime10 = require("react/jsx-runtime");
2731
- 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 }) {
2732
3116
  const editor = useEditorContext();
2733
- const [positions, setPositions] = (0, import_react9.useState)(null);
2734
- const [layout, setLayout] = (0, import_react9.useState)(null);
2735
- const draggingRef = (0, import_react9.useRef)(null);
2736
- 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)(() => {
2737
3120
  const table = tableRef.current;
2738
- if (!table) return;
3121
+ if (!table) return null;
2739
3122
  const tableRect = table.getBoundingClientRect();
2740
3123
  const cgCols = table.querySelectorAll("colgroup > col");
2741
3124
  let rights = [];
@@ -2758,55 +3141,160 @@ function TableResizeOverlay({ tableRef, blockIndex, cols }) {
2758
3141
  });
2759
3142
  }
2760
3143
  if (rights.length !== cols) {
2761
- setLayout(null);
2762
- return;
3144
+ return null;
2763
3145
  }
2764
- setLayout({ rights, height: tableRect.height });
2765
- }, [cols, tableRef]);
2766
- (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)(() => {
2767
3164
  measure();
2768
3165
  }, [measure]);
2769
- (0, import_react9.useEffect)(() => {
3166
+ (0, import_react10.useEffect)(() => {
2770
3167
  const table = tableRef.current;
2771
3168
  if (!table) return;
2772
3169
  const ro = new ResizeObserver(() => measure());
2773
3170
  ro.observe(table);
2774
3171
  return () => ro.disconnect();
2775
3172
  }, [measure, tableRef]);
2776
- const onPointerDown = (0, import_react9.useCallback)(
2777
- (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) => {
2778
3222
  e.preventDefault();
2779
3223
  e.stopPropagation();
2780
3224
  const table = tableRef.current;
2781
3225
  if (!table) return;
2782
- const cgCols = table.querySelectorAll("colgroup > col");
2783
- const startWidth = cgCols[col]?.getBoundingClientRect().width ?? 100;
2784
- draggingRef.current = { col, startX: e.clientX, startWidth };
2785
- 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 };
2786
3230
  e.currentTarget.setPointerCapture(e.pointerId);
2787
3231
  },
2788
- [layout, tableRef]
3232
+ [tableRef, editor, blockIndex, cols]
2789
3233
  );
2790
- const onPointerMove = (0, import_react9.useCallback)(
3234
+ const onTableWidthPointerDown = (0, import_react10.useCallback)(
2791
3235
  (e) => {
2792
- const d = draggingRef.current;
2793
- if (!d) return;
2794
- const dx = e.clientX - d.startX;
2795
- const next = Math.max(40, d.startWidth + dx);
2796
- 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);
2797
3246
  },
2798
- [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]
2799
3295
  );
2800
- const onPointerUp = (0, import_react9.useCallback)((e) => {
2801
- draggingRef.current = null;
2802
- setPositions(null);
2803
- try {
2804
- e.currentTarget.releasePointerCapture(e.pointerId);
2805
- } catch {
2806
- }
2807
- }, []);
2808
3296
  if (!layout) return null;
2809
- const handleStyle = (x) => ({
3297
+ const colHandleStyle = (x) => ({
2810
3298
  position: "absolute",
2811
3299
  top: 0,
2812
3300
  left: `${x - 3}px`,
@@ -2815,28 +3303,104 @@ function TableResizeOverlay({ tableRef, blockIndex, cols }) {
2815
3303
  cursor: "col-resize",
2816
3304
  zIndex: 5
2817
3305
  });
2818
- void positions;
2819
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: layout.rights.map((x, c) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2820
- "div",
2821
- {
2822
- contentEditable: false,
2823
- className: "ed-col-resize-handle",
2824
- style: handleStyle(x),
2825
- onPointerDown: onPointerDown(c),
2826
- onPointerMove,
2827
- onPointerUp,
2828
- "aria-label": `Redimensionar coluna ${c + 1}`,
2829
- role: "separator"
2830
- },
2831
- c
2832
- )) });
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
+ ] });
2833
3397
  }
2834
3398
 
2835
3399
  // src/NodeView.tsx
2836
- var import_jsx_runtime11 = require("react/jsx-runtime");
3400
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2837
3401
  function NodeView({ block, index, children, fragment, tableFragment }) {
2838
3402
  if (block.type === "table") {
2839
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TableView, { block, index, tableFragment });
3403
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableView, { block, index, tableFragment });
2840
3404
  }
2841
3405
  const inline = fragment ? renderInline(sliceDelta(block.delta, fragment.start, fragment.end), index) : renderInline(block.delta, index);
2842
3406
  const common = commonBlockProps(block.attrs, index, block.type, fragment);
@@ -2844,7 +3408,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2844
3408
  case "heading": {
2845
3409
  const level = clampLevel2(block.attrs.level);
2846
3410
  const Tag = `h${level}`;
2847
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3411
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2848
3412
  Tag,
2849
3413
  {
2850
3414
  ...common,
@@ -2854,7 +3418,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2854
3418
  );
2855
3419
  }
2856
3420
  case "blockquote":
2857
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3421
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2858
3422
  "blockquote",
2859
3423
  {
2860
3424
  ...common,
@@ -2863,18 +3427,18 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2863
3427
  }
2864
3428
  );
2865
3429
  case "codeBlock":
2866
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3430
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2867
3431
  "pre",
2868
3432
  {
2869
3433
  ...common,
2870
3434
  "data-language": block.attrs.language ?? void 0,
2871
3435
  className: `ed-block ed-codeblock${alignClass(block.attrs.align)}`,
2872
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("code", { children: inline })
3436
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("code", { children: inline })
2873
3437
  }
2874
3438
  );
2875
3439
  case "listItem": {
2876
3440
  const level = clampListLevel(block.attrs.listLevel);
2877
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3441
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2878
3442
  "li",
2879
3443
  {
2880
3444
  ...common,
@@ -2890,7 +3454,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2890
3454
  }
2891
3455
  case "paragraph":
2892
3456
  default:
2893
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3457
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2894
3458
  "div",
2895
3459
  {
2896
3460
  ...common,
@@ -2903,7 +3467,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2903
3467
  function commonBlockProps(attrs, index, type, fragment) {
2904
3468
  const style = {};
2905
3469
  if (attrs.align) style.textAlign = attrs.align;
2906
- Object.assign(style, (0, import_core7.answerLineStyle)(attrs) ?? {});
3470
+ Object.assign(style, (0, import_core8.answerLineStyle)(attrs) ?? {});
2907
3471
  const base = {
2908
3472
  "data-block-index": index,
2909
3473
  "data-block-type": type,
@@ -2941,80 +3505,82 @@ function TableView({ block, index, tableFragment }) {
2941
3505
  const rows = clampPositive(block.attrs.rows);
2942
3506
  const cols = clampPositive(block.attrs.cols);
2943
3507
  const cells = block.cells ?? [];
2944
- const widths = readColWidths(block.attrs.colWidths, cols);
2945
- 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);
2946
3512
  const rowStart = tableFragment?.rowStart ?? 0;
2947
3513
  const rowEnd = tableFragment?.rowEnd ?? rows;
2948
3514
  const isFirstFragment = !tableFragment || tableFragment.index === 0;
2949
3515
  const editor = useEditorContext();
2950
- const rect = (0, import_react10.useMemo)(() => {
3516
+ const rect = (0, import_react11.useMemo)(() => {
2951
3517
  if (editor.selection.anchor.blockIndex !== index) return null;
2952
3518
  if (editor.selection.focus.blockIndex !== index) return null;
2953
- return (0, import_core7.tableRectSelection)(editor.doc, editor.selection);
3519
+ return (0, import_core8.tableRectSelection)(editor.doc, editor.selection);
2954
3520
  }, [editor.doc, editor.selection, index]);
2955
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ed-table-wrap", children: [
2956
- /* @__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)(
2957
3523
  "table",
2958
3524
  {
2959
3525
  ref: tableRef,
2960
3526
  "data-block-index": index,
2961
3527
  "data-block-type": "table",
2962
3528
  className: "ed-block ed-table",
3529
+ style: typeof tableWidth === "number" ? { width: `${tableWidth}%` } : void 0,
2963
3530
  children: [
2964
- 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)) }),
2965
- /* @__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) => {
2966
3533
  const r = rowStart + i;
2967
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tr", { "data-cell-row": r, children: Array.from({ length: cols }, (_2, c) => {
2968
- const flat = r * cols + c;
2969
- const cell = cells[flat];
2970
- if (cell?.attrs.covered === true) return null;
2971
- const rowspan = spanAttr(cell?.attrs.rowspan);
2972
- const colspan = spanAttr(cell?.attrs.colspan);
2973
- const delta = cell?.delta ?? [];
2974
- const inRect = rect !== null && r >= rect.top && r <= rect.bottom && c >= rect.left && c <= rect.right;
2975
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2976
- "td",
2977
- {
2978
- "data-cell-index": flat,
2979
- "data-cell-row": r,
2980
- "data-cell-col": c,
2981
- "data-cell-rowspan": rowspan,
2982
- "data-cell-colspan": colspan,
2983
- rowSpan: rowspan > 1 ? rowspan : void 0,
2984
- colSpan: colspan > 1 ? colspan : void 0,
2985
- style: cellStyle(
2986
- cell?.attrs,
2987
- // rowStart/rowEnd são os limites do FRAGMENTO: numa tabela
2988
- // quebrada entre páginas, cada página fecha a própria caixa.
2989
- (0, import_core7.cellBorderStyle)(
2990
- block.attrs.borderPreset,
2991
- { row: r, col: c, rowspan, colspan, cols, rowStart, rowEnd },
2992
- "screen",
2993
- block.attrs.borderColor
2994
- )
2995
- ),
2996
- className: inRect ? "ed-cell ed-cell--selected" : "ed-cell",
2997
- children: renderInline(delta, `t${index}-c${flat}`)
2998
- },
2999
- c
3000
- );
3001
- }) }, 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
+ );
3002
3577
  }) })
3003
3578
  ]
3004
3579
  }
3005
3580
  ),
3006
- 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 })
3007
3582
  ] });
3008
3583
  }
3009
- function readColWidths(raw, cols) {
3010
- if (!Array.isArray(raw)) return null;
3011
- const out = [];
3012
- for (let i = 0; i < cols; i++) {
3013
- const v = raw[i];
3014
- out.push(typeof v === "number" && Number.isFinite(v) && v > 0 ? v : null);
3015
- }
3016
- return out;
3017
- }
3018
3584
  function spanAttr(v) {
3019
3585
  if (typeof v !== "number" || !Number.isFinite(v) || v < 1) return 1;
3020
3586
  return Math.trunc(v);
@@ -3025,7 +3591,7 @@ function clampPositive(n) {
3025
3591
  }
3026
3592
 
3027
3593
  // src/usePagination.ts
3028
- var import_react11 = require("react");
3594
+ var import_react12 = require("react");
3029
3595
  var A4_PAGE = {
3030
3596
  width: 794,
3031
3597
  height: 1123,
@@ -3051,10 +3617,10 @@ function defaultPageLayout(topLevelCount) {
3051
3617
  };
3052
3618
  }
3053
3619
  function usePageLayout(rootRef, geometry, topLevelCount, deps) {
3054
- const [phase, setPhase] = (0, import_react11.useState)("measure");
3055
- const [layout, setLayout] = (0, import_react11.useState)(() => defaultPageLayout(topLevelCount));
3056
- const lastDepsRef = (0, import_react11.useRef)(null);
3057
- (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)(() => {
3058
3624
  const currentDeps = [...deps, topLevelCount, geometry];
3059
3625
  if (lastDepsRef.current !== null && shallowArrayEqual(lastDepsRef.current, currentDeps)) {
3060
3626
  return;
@@ -3066,7 +3632,7 @@ function usePageLayout(rootRef, geometry, topLevelCount, deps) {
3066
3632
  });
3067
3633
  setPhase("measure");
3068
3634
  });
3069
- (0, import_react11.useLayoutEffect)(() => {
3635
+ (0, import_react12.useLayoutEffect)(() => {
3070
3636
  if (phase !== "measure") return;
3071
3637
  const root = rootRef.current;
3072
3638
  if (!root) return;
@@ -3538,47 +4104,47 @@ function layoutsDeepEqual(a, b) {
3538
4104
  }
3539
4105
 
3540
4106
  // src/useEditor.ts
3541
- var import_react13 = require("react");
4107
+ var import_react14 = require("react");
3542
4108
 
3543
4109
  // src/usePageSettings.ts
3544
- var import_react12 = require("react");
4110
+ var import_react13 = require("react");
3545
4111
  function usePageSettings(doc) {
3546
- const cacheRef = (0, import_react12.useRef)(null);
3547
- const subscribe = (0, import_react12.useCallback)(
4112
+ const cacheRef = (0, import_react13.useRef)(null);
4113
+ const subscribe = (0, import_react13.useCallback)(
3548
4114
  (notify) => doc.observePageSettings(notify),
3549
4115
  [doc]
3550
4116
  );
3551
- const getSnapshot = (0, import_react12.useCallback)(() => {
4117
+ const getSnapshot = (0, import_react13.useCallback)(() => {
3552
4118
  const next = doc.getPageSettings();
3553
4119
  const prev = cacheRef.current;
3554
4120
  if (prev && shallowEqual(prev, next)) return prev;
3555
4121
  cacheRef.current = next;
3556
4122
  return next;
3557
4123
  }, [doc]);
3558
- return (0, import_react12.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
4124
+ return (0, import_react13.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
3559
4125
  }
3560
4126
  function shallowEqual(a, b) {
3561
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;
3562
4128
  }
3563
4129
 
3564
4130
  // src/useEditor.ts
3565
- var import_core8 = require("@sofereditor/core");
4131
+ var import_core9 = require("@sofereditor/core");
3566
4132
  function useEditor(opts = {}) {
3567
- const doc = (0, import_react13.useMemo)(() => opts.document ?? new import_core8.EditorDocument(), [opts.document]);
3568
- const history = (0, import_react13.useMemo)(() => new import_core8.EditorHistory(doc), [doc]);
3569
- const [snapshot, setSnapshot] = (0, import_react13.useState)(() => doc.toJSON());
3570
- const [selection, setSelectionState] = (0, import_react13.useState)(
3571
- () => (0, import_core8.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 })
3572
4138
  );
3573
- const selectionRef = (0, import_react13.useRef)(selection);
4139
+ const selectionRef = (0, import_react14.useRef)(selection);
3574
4140
  selectionRef.current = selection;
3575
- const pendingMarksRef = (0, import_react13.useRef)({});
3576
- const [pendingMarks, setPendingMarksState] = (0, import_react13.useState)({});
3577
- 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) => {
3578
4144
  pendingMarksRef.current = next;
3579
4145
  setPendingMarksState(next);
3580
4146
  }, []);
3581
- (0, import_react13.useEffect)(() => {
4147
+ (0, import_react14.useEffect)(() => {
3582
4148
  let scheduled = false;
3583
4149
  let cancelled = false;
3584
4150
  let frame = 0;
@@ -3605,8 +4171,8 @@ function useEditor(opts = {}) {
3605
4171
  doc.ydoc.off("afterTransaction", schedule);
3606
4172
  };
3607
4173
  }, [doc]);
3608
- const getSelection = (0, import_react13.useCallback)(() => selectionRef.current, []);
3609
- const setSelection = (0, import_react13.useCallback)(
4174
+ const getSelection = (0, import_react14.useCallback)(() => selectionRef.current, []);
4175
+ const setSelection = (0, import_react14.useCallback)(
3610
4176
  (sel) => {
3611
4177
  const prev = selectionRef.current;
3612
4178
  selectionRef.current = sel;
@@ -3621,19 +4187,19 @@ function useEditor(opts = {}) {
3621
4187
  },
3622
4188
  []
3623
4189
  );
3624
- const ctxRef = (0, import_react13.useRef)({ doc, getSelection, setSelection });
4190
+ const ctxRef = (0, import_react14.useRef)({ doc, getSelection, setSelection });
3625
4191
  ctxRef.current = { doc, getSelection, setSelection };
3626
- const consumePendingMarks = (0, import_react13.useCallback)(() => {
4192
+ const consumePendingMarks = (0, import_react14.useCallback)(() => {
3627
4193
  const current = pendingMarksRef.current;
3628
4194
  if (Object.keys(current).length === 0) return void 0;
3629
4195
  pendingMarksRef.current = {};
3630
4196
  setPendingMarksState({});
3631
4197
  return current;
3632
4198
  }, []);
3633
- const isMarkActive = (0, import_react13.useCallback)(
4199
+ const isMarkActive = (0, import_react14.useCallback)(
3634
4200
  (name, value) => {
3635
4201
  const sel = selectionRef.current;
3636
- const { start, end } = (0, import_core8.orderedRange)(sel);
4202
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3637
4203
  if (start.blockIndex === end.blockIndex && start.offset === end.offset) {
3638
4204
  const pending = pendingMarksRef.current[name];
3639
4205
  if (pending !== void 0) {
@@ -3642,7 +4208,7 @@ function useEditor(opts = {}) {
3642
4208
  }
3643
4209
  const yText2 = doc.getBlockText(start.blockIndex);
3644
4210
  if (!yText2 || start.offset === 0) return false;
3645
- return (0, import_core8.isMarkUniformInRange)(yText2, start.offset - 1, start.offset, name, value);
4211
+ return (0, import_core9.isMarkUniformInRange)(yText2, start.offset - 1, start.offset, name, value);
3646
4212
  }
3647
4213
  if (start.blockIndex !== end.blockIndex) {
3648
4214
  for (let i = start.blockIndex; i <= end.blockIndex; i++) {
@@ -3651,19 +4217,19 @@ function useEditor(opts = {}) {
3651
4217
  const s = i === start.blockIndex ? start.offset : 0;
3652
4218
  const e = i === end.blockIndex ? end.offset : yText2.length;
3653
4219
  if (s >= e) continue;
3654
- if (!(0, import_core8.isMarkUniformInRange)(yText2, s, e, name, value)) return false;
4220
+ if (!(0, import_core9.isMarkUniformInRange)(yText2, s, e, name, value)) return false;
3655
4221
  }
3656
4222
  return true;
3657
4223
  }
3658
4224
  const yText = doc.getBlockText(start.blockIndex);
3659
4225
  if (!yText) return false;
3660
- return (0, import_core8.isMarkUniformInRange)(yText, start.offset, end.offset, name, value);
4226
+ return (0, import_core9.isMarkUniformInRange)(yText, start.offset, end.offset, name, value);
3661
4227
  },
3662
4228
  [doc]
3663
4229
  );
3664
- const getActiveMarks = (0, import_react13.useCallback)(() => {
4230
+ const getActiveMarks = (0, import_react14.useCallback)(() => {
3665
4231
  const sel = selectionRef.current;
3666
- const { start, end } = (0, import_core8.orderedRange)(sel);
4232
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3667
4233
  if (start.blockIndex !== end.blockIndex) {
3668
4234
  return {};
3669
4235
  }
@@ -3671,14 +4237,14 @@ function useEditor(opts = {}) {
3671
4237
  if (!yText) return {};
3672
4238
  if (start.offset === end.offset) {
3673
4239
  if (start.offset === 0) return {};
3674
- return (0, import_core8.getMarksInRange)(yText, start.offset - 1, start.offset);
4240
+ return (0, import_core9.getMarksInRange)(yText, start.offset - 1, start.offset);
3675
4241
  }
3676
- return (0, import_core8.getMarksInRange)(yText, start.offset, end.offset);
4242
+ return (0, import_core9.getMarksInRange)(yText, start.offset, end.offset);
3677
4243
  }, [doc]);
3678
- const toggleMark = (0, import_react13.useCallback)(
4244
+ const toggleMark = (0, import_react14.useCallback)(
3679
4245
  (name, value) => {
3680
4246
  const sel = selectionRef.current;
3681
- const { start, end } = (0, import_core8.orderedRange)(sel);
4247
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3682
4248
  const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;
3683
4249
  if (isCollapsed) {
3684
4250
  const next = { ...pendingMarksRef.current };
@@ -3691,39 +4257,39 @@ function useEditor(opts = {}) {
3691
4257
  setPendingMarks(next);
3692
4258
  return;
3693
4259
  }
3694
- (0, import_core8.toggleMark)(ctxRef.current, name, value);
4260
+ (0, import_core9.toggleMark)(ctxRef.current, name, value);
3695
4261
  },
3696
4262
  [isMarkActive, setPendingMarks]
3697
4263
  );
3698
- const setMark = (0, import_react13.useCallback)(
4264
+ const setMark = (0, import_react14.useCallback)(
3699
4265
  (name, value) => {
3700
4266
  const sel = selectionRef.current;
3701
- const { start, end } = (0, import_core8.orderedRange)(sel);
4267
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3702
4268
  const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;
3703
4269
  if (isCollapsed) {
3704
4270
  setPendingMarks({ ...pendingMarksRef.current, [name]: value });
3705
4271
  return;
3706
4272
  }
3707
- (0, import_core8.setMark)(ctxRef.current, name, value);
4273
+ (0, import_core9.setMark)(ctxRef.current, name, value);
3708
4274
  },
3709
4275
  [setPendingMarks]
3710
4276
  );
3711
- const removeMark = (0, import_react13.useCallback)(
4277
+ const removeMark = (0, import_react14.useCallback)(
3712
4278
  (name) => {
3713
4279
  const sel = selectionRef.current;
3714
- const { start, end } = (0, import_core8.orderedRange)(sel);
4280
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3715
4281
  const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;
3716
4282
  if (isCollapsed) {
3717
4283
  setPendingMarks({ ...pendingMarksRef.current, [name]: null });
3718
4284
  return;
3719
4285
  }
3720
- (0, import_core8.removeMark)(ctxRef.current, name);
4286
+ (0, import_core9.removeMark)(ctxRef.current, name);
3721
4287
  },
3722
4288
  [setPendingMarks]
3723
4289
  );
3724
- const getBlockType = (0, import_react13.useCallback)(() => {
4290
+ const getBlockType = (0, import_react14.useCallback)(() => {
3725
4291
  const sel = selectionRef.current;
3726
- const { start, end } = (0, import_core8.orderedRange)(sel);
4292
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3727
4293
  const first = doc.getBlockType(start.blockIndex);
3728
4294
  if (first === void 0) return "paragraph";
3729
4295
  for (let i = start.blockIndex + 1; i <= end.blockIndex; i++) {
@@ -3731,10 +4297,10 @@ function useEditor(opts = {}) {
3731
4297
  }
3732
4298
  return first;
3733
4299
  }, [doc]);
3734
- const getBlockAttr = (0, import_react13.useCallback)(
4300
+ const getBlockAttr = (0, import_react14.useCallback)(
3735
4301
  (key) => {
3736
4302
  const sel = selectionRef.current;
3737
- const { start, end } = (0, import_core8.orderedRange)(sel);
4303
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3738
4304
  const first = doc.getBlockAttrs(start.blockIndex)[key];
3739
4305
  for (let i = start.blockIndex + 1; i <= end.blockIndex; i++) {
3740
4306
  const next = doc.getBlockAttrs(i)[key];
@@ -3744,60 +4310,60 @@ function useEditor(opts = {}) {
3744
4310
  },
3745
4311
  [doc]
3746
4312
  );
3747
- const setBlockType = (0, import_react13.useCallback)((type, attrs) => {
3748
- (0, import_core8.setBlockType)(ctxRef.current, type, attrs);
4313
+ const setBlockType = (0, import_react14.useCallback)((type, attrs) => {
4314
+ (0, import_core9.setBlockType)(ctxRef.current, type, attrs);
3749
4315
  }, []);
3750
- const setBlockAttr = (0, import_react13.useCallback)(
4316
+ const setBlockAttr = (0, import_react14.useCallback)(
3751
4317
  (key, value) => {
3752
- (0, import_core8.setBlockAttr)(ctxRef.current, key, value);
4318
+ (0, import_core9.setBlockAttr)(ctxRef.current, key, value);
3753
4319
  },
3754
4320
  []
3755
4321
  );
3756
- const setAlign = (0, import_react13.useCallback)((value) => {
4322
+ const setAlign = (0, import_react14.useCallback)((value) => {
3757
4323
  const sel = selectionRef.current;
3758
4324
  const inCell = sel.focus.cellIndex != null;
3759
- if (inCell) (0, import_core8.setCellAttr)(ctxRef.current, "align", value);
3760
- else (0, import_core8.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);
3761
4327
  }, []);
3762
- const getAlign = (0, import_react13.useCallback)(() => {
4328
+ const getAlign = (0, import_react14.useCallback)(() => {
3763
4329
  const sel = selectionRef.current;
3764
4330
  if (sel.focus.cellIndex != null && doc.isTable(sel.focus.blockIndex)) {
3765
4331
  return doc.getCellAttrs(sel.focus.blockIndex, sel.focus.cellIndex).align;
3766
4332
  }
3767
4333
  return getBlockAttr("align");
3768
4334
  }, [doc, getBlockAttr]);
3769
- const setCellBackground = (0, import_react13.useCallback)((color) => {
3770
- (0, import_core8.setCellAttr)(ctxRef.current, "bgColor", color);
4335
+ const setCellBackground = (0, import_react14.useCallback)((color) => {
4336
+ (0, import_core9.setCellAttr)(ctxRef.current, "bgColor", color);
3771
4337
  }, []);
3772
- const getCellBackground = (0, import_react13.useCallback)(() => {
4338
+ const getCellBackground = (0, import_react14.useCallback)(() => {
3773
4339
  const sel = selectionRef.current;
3774
4340
  if (sel.focus.cellIndex == null || !doc.isTable(sel.focus.blockIndex)) return void 0;
3775
4341
  return doc.getCellAttrs(sel.focus.blockIndex, sel.focus.cellIndex).bgColor;
3776
4342
  }, [doc]);
3777
- const setTableBorderPreset = (0, import_react13.useCallback)((preset) => {
4343
+ const setTableBorderPreset = (0, import_react14.useCallback)((preset) => {
3778
4344
  const sel = selectionRef.current;
3779
4345
  if (!doc.isTable(sel.focus.blockIndex)) return;
3780
- (0, import_core8.setBlockAttrAtIndex)(ctxRef.current, sel.focus.blockIndex, "borderPreset", preset);
4346
+ (0, import_core9.setBlockAttrAtIndex)(ctxRef.current, sel.focus.blockIndex, "borderPreset", preset);
3781
4347
  }, [doc]);
3782
- const getTableBorderPreset = (0, import_react13.useCallback)(() => {
4348
+ const getTableBorderPreset = (0, import_react14.useCallback)(() => {
3783
4349
  const sel = selectionRef.current;
3784
4350
  if (!doc.isTable(sel.focus.blockIndex)) return "all";
3785
4351
  return doc.getBlockAttrs(sel.focus.blockIndex).borderPreset ?? "all";
3786
4352
  }, [doc]);
3787
- const setTableBorderColor = (0, import_react13.useCallback)((color) => {
4353
+ const setTableBorderColor = (0, import_react14.useCallback)((color) => {
3788
4354
  const sel = selectionRef.current;
3789
4355
  if (!doc.isTable(sel.focus.blockIndex)) return;
3790
- (0, import_core8.setBlockAttrAtIndex)(ctxRef.current, sel.focus.blockIndex, "borderColor", color);
4356
+ (0, import_core9.setBlockAttrAtIndex)(ctxRef.current, sel.focus.blockIndex, "borderColor", color);
3791
4357
  }, [doc]);
3792
- const getTableBorderColor = (0, import_react13.useCallback)(() => {
4358
+ const getTableBorderColor = (0, import_react14.useCallback)(() => {
3793
4359
  const sel = selectionRef.current;
3794
4360
  if (!doc.isTable(sel.focus.blockIndex)) return void 0;
3795
4361
  return doc.getBlockAttrs(sel.focus.blockIndex).borderColor;
3796
4362
  }, [doc]);
3797
- const isListActive = (0, import_react13.useCallback)(
4363
+ const isListActive = (0, import_react14.useCallback)(
3798
4364
  (kind) => {
3799
4365
  const sel = selectionRef.current;
3800
- const { start, end } = (0, import_core8.orderedRange)(sel);
4366
+ const { start, end } = (0, import_core9.orderedRange)(sel);
3801
4367
  for (let i = start.blockIndex; i <= end.blockIndex; i++) {
3802
4368
  if (doc.getBlockType(i) !== "listItem") return false;
3803
4369
  if (doc.getBlockAttrs(i).listKind !== kind) return false;
@@ -3806,119 +4372,128 @@ function useEditor(opts = {}) {
3806
4372
  },
3807
4373
  [doc]
3808
4374
  );
3809
- const toggleList = (0, import_react13.useCallback)((kind) => {
3810
- (0, import_core8.toggleList)(ctxRef.current, kind);
4375
+ const toggleList = (0, import_react14.useCallback)((kind) => {
4376
+ (0, import_core9.toggleList)(ctxRef.current, kind);
3811
4377
  }, []);
3812
- const indentList = (0, import_react13.useCallback)(() => {
3813
- (0, import_core8.indentList)(ctxRef.current);
4378
+ const indentList = (0, import_react14.useCallback)(() => {
4379
+ (0, import_core9.indentList)(ctxRef.current);
3814
4380
  }, []);
3815
- const dedentList = (0, import_react13.useCallback)(() => {
3816
- (0, import_core8.dedentList)(ctxRef.current);
4381
+ const dedentList = (0, import_react14.useCallback)(() => {
4382
+ (0, import_core9.dedentList)(ctxRef.current);
3817
4383
  }, []);
3818
- const splitListItem = (0, import_react13.useCallback)(() => {
3819
- return (0, import_core8.splitListItem)(ctxRef.current);
4384
+ const splitListItem = (0, import_react14.useCallback)(() => {
4385
+ return (0, import_core9.splitListItem)(ctxRef.current);
3820
4386
  }, []);
3821
- const isInTable = (0, import_react13.useCallback)(() => {
4387
+ const isInTable = (0, import_react14.useCallback)(() => {
3822
4388
  return selectionRef.current.focus.cellIndex != null;
3823
4389
  }, []);
3824
- const getTableLocation = (0, import_react13.useCallback)(() => {
3825
- return (0, import_core8.tableLocationOf)(doc, selectionRef.current.focus);
4390
+ const getTableLocation = (0, import_react14.useCallback)(() => {
4391
+ return (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3826
4392
  }, [doc]);
3827
- const insertTable = (0, import_react13.useCallback)((rows, cols) => {
3828
- (0, import_core8.insertTable)(ctxRef.current, rows, cols);
4393
+ const insertTable = (0, import_react14.useCallback)((rows, cols) => {
4394
+ (0, import_core9.insertTable)(ctxRef.current, rows, cols);
3829
4395
  }, []);
3830
- const insertAnswerLines = (0, import_react13.useCallback)((count, spacing) => {
3831
- (0, import_core8.insertAnswerLines)(ctxRef.current, count, spacing);
4396
+ const insertAnswerLines = (0, import_react14.useCallback)((count, spacing) => {
4397
+ (0, import_core9.insertAnswerLines)(ctxRef.current, count, spacing);
3832
4398
  }, []);
3833
- const deleteTable = (0, import_react13.useCallback)((blockIndex) => {
4399
+ const deleteTable = (0, import_react14.useCallback)((blockIndex) => {
3834
4400
  const idx = blockIndex ?? selectionRef.current.focus.blockIndex;
3835
- (0, import_core8.deleteTable)(ctxRef.current, idx);
4401
+ (0, import_core9.deleteTable)(ctxRef.current, idx);
3836
4402
  }, []);
3837
- const insertRowAbove = (0, import_react13.useCallback)(() => {
3838
- const loc = (0, import_core8.tableLocationOf)(doc, selectionRef.current.focus);
4403
+ const insertRowAbove = (0, import_react14.useCallback)(() => {
4404
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3839
4405
  if (!loc) return;
3840
- (0, import_core8.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "before");
4406
+ (0, import_core9.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "before");
3841
4407
  }, [doc]);
3842
- const insertRowBelow = (0, import_react13.useCallback)(() => {
3843
- const loc = (0, import_core8.tableLocationOf)(doc, selectionRef.current.focus);
4408
+ const insertRowBelow = (0, import_react14.useCallback)(() => {
4409
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3844
4410
  if (!loc) return;
3845
- (0, import_core8.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "after");
4411
+ (0, import_core9.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "after");
3846
4412
  }, [doc]);
3847
- const deleteCurrentRow = (0, import_react13.useCallback)(() => {
3848
- const loc = (0, import_core8.tableLocationOf)(doc, selectionRef.current.focus);
4413
+ const deleteCurrentRow = (0, import_react14.useCallback)(() => {
4414
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3849
4415
  if (!loc) return;
3850
- (0, import_core8.deleteTableRow)(ctxRef.current, loc.blockIndex, loc.row);
4416
+ (0, import_core9.deleteTableRow)(ctxRef.current, loc.blockIndex, loc.row);
3851
4417
  }, [doc]);
3852
- const insertColumnLeft = (0, import_react13.useCallback)(() => {
3853
- const loc = (0, import_core8.tableLocationOf)(doc, selectionRef.current.focus);
4418
+ const insertColumnLeft = (0, import_react14.useCallback)(() => {
4419
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3854
4420
  if (!loc) return;
3855
- (0, import_core8.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "before");
4421
+ (0, import_core9.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "before");
3856
4422
  }, [doc]);
3857
- const insertColumnRight = (0, import_react13.useCallback)(() => {
3858
- const loc = (0, import_core8.tableLocationOf)(doc, selectionRef.current.focus);
4423
+ const insertColumnRight = (0, import_react14.useCallback)(() => {
4424
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3859
4425
  if (!loc) return;
3860
- (0, import_core8.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "after");
4426
+ (0, import_core9.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "after");
3861
4427
  }, [doc]);
3862
- const deleteCurrentColumn = (0, import_react13.useCallback)(() => {
3863
- const loc = (0, import_core8.tableLocationOf)(doc, selectionRef.current.focus);
4428
+ const deleteCurrentColumn = (0, import_react14.useCallback)(() => {
4429
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3864
4430
  if (!loc) return;
3865
- (0, import_core8.deleteTableColumn)(ctxRef.current, loc.blockIndex, loc.col);
4431
+ (0, import_core9.deleteTableColumn)(ctxRef.current, loc.blockIndex, loc.col);
3866
4432
  }, [doc]);
3867
- const moveToNextCell = (0, import_react13.useCallback)(() => {
3868
- (0, import_core8.moveToNextCell)(ctxRef.current);
4433
+ const moveToNextCell = (0, import_react14.useCallback)(() => {
4434
+ (0, import_core9.moveToNextCell)(ctxRef.current);
3869
4435
  }, []);
3870
- const moveToPrevCell = (0, import_react13.useCallback)(() => {
3871
- (0, import_core8.moveToPrevCell)(ctxRef.current);
4436
+ const moveToPrevCell = (0, import_react14.useCallback)(() => {
4437
+ (0, import_core9.moveToPrevCell)(ctxRef.current);
3872
4438
  }, []);
3873
- const mergeRight = (0, import_react13.useCallback)(() => {
3874
- const loc = (0, import_core8.tableLocationOf)(doc, selectionRef.current.focus);
4439
+ const mergeRight = (0, import_react14.useCallback)(() => {
4440
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3875
4441
  if (!loc) return false;
3876
- return (0, import_core8.mergeRight)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
4442
+ return (0, import_core9.mergeRight)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3877
4443
  }, [doc]);
3878
- const mergeDown = (0, import_react13.useCallback)(() => {
3879
- const loc = (0, import_core8.tableLocationOf)(doc, selectionRef.current.focus);
4444
+ const mergeDown = (0, import_react14.useCallback)(() => {
4445
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3880
4446
  if (!loc) return false;
3881
- return (0, import_core8.mergeDown)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
4447
+ return (0, import_core9.mergeDown)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3882
4448
  }, [doc]);
3883
- const splitCell = (0, import_react13.useCallback)(() => {
3884
- const loc = (0, import_core8.tableLocationOf)(doc, selectionRef.current.focus);
4449
+ const splitCell = (0, import_react14.useCallback)(() => {
4450
+ const loc = (0, import_core9.tableLocationOf)(doc, selectionRef.current.focus);
3885
4451
  if (!loc) return false;
3886
- return (0, import_core8.splitCell)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
4452
+ return (0, import_core9.splitCell)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3887
4453
  }, [doc]);
3888
- const setColumnWidth = (0, import_react13.useCallback)(
3889
- (blockIndex, col, widthPx) => {
3890
- (0, import_core8.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);
3891
4457
  },
3892
4458
  []
3893
4459
  );
3894
- const getTableRect = (0, import_react13.useCallback)(
3895
- () => (0, import_core8.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),
3896
4471
  [doc]
3897
4472
  );
3898
- const hasTableRectSelection = (0, import_react13.useCallback)(() => {
3899
- return (0, import_core8.tableRectSelection)(doc, selectionRef.current) !== null;
4473
+ const hasTableRectSelection = (0, import_react14.useCallback)(() => {
4474
+ return (0, import_core9.tableRectSelection)(doc, selectionRef.current) !== null;
3900
4475
  }, [doc]);
3901
- const mergeSelection = (0, import_react13.useCallback)(() => {
3902
- return (0, import_core8.mergeSelection)(ctxRef.current);
4476
+ const mergeSelection = (0, import_react14.useCallback)(() => {
4477
+ return (0, import_core9.mergeSelection)(ctxRef.current);
3903
4478
  }, []);
3904
- const insertImage = (0, import_react13.useCallback)((embed) => {
3905
- (0, import_core8.insertImage)(ctxRef.current, embed);
4479
+ const insertImage = (0, import_react14.useCallback)((embed) => {
4480
+ (0, import_core9.insertImage)(ctxRef.current, embed);
3906
4481
  }, []);
3907
- const setImageAttrs = (0, import_react13.useCallback)(
4482
+ const setImageAttrs = (0, import_react14.useCallback)(
3908
4483
  (blockIndex, offset, partial, cellIndex, newOffset) => {
3909
- (0, import_core8.setImageAttrs)(ctxRef.current, blockIndex, offset, partial, cellIndex, newOffset);
4484
+ (0, import_core9.setImageAttrs)(ctxRef.current, blockIndex, offset, partial, cellIndex, newOffset);
3910
4485
  },
3911
4486
  []
3912
4487
  );
3913
- const moveEmbedAnchor = (0, import_react13.useCallback)(
4488
+ const moveEmbedAnchor = (0, import_react14.useCallback)(
3914
4489
  (from, to, newOffsetX, newOffsetY) => {
3915
- (0, import_core8.moveEmbedAnchor)(ctxRef.current, from, to, newOffsetX, newOffsetY);
4490
+ (0, import_core9.moveEmbedAnchor)(ctxRef.current, from, to, newOffsetX, newOffsetY);
3916
4491
  },
3917
4492
  []
3918
4493
  );
3919
- const uploadImageRef = (0, import_react13.useRef)(opts.uploadImage);
4494
+ const uploadImageRef = (0, import_react14.useRef)(opts.uploadImage);
3920
4495
  uploadImageRef.current = opts.uploadImage;
3921
- const insertImageFromFile = (0, import_react13.useCallback)(async (file) => {
4496
+ const insertImageFromFile = (0, import_react14.useCallback)(async (file) => {
3922
4497
  if (!file.type.startsWith("image/")) return;
3923
4498
  const dataUrl = await readAsDataURL(file);
3924
4499
  const dims = await readImageDimensions(dataUrl);
@@ -3930,9 +4505,9 @@ function useEditor(opts = {}) {
3930
4505
  }
3931
4506
  const upload = uploadImageRef.current;
3932
4507
  const src = upload ? await upload(file) : dataUrl;
3933
- (0, import_core8.insertImage)(ctxRef.current, { type: "image", src, width: w, height: h });
4508
+ (0, import_core9.insertImage)(ctxRef.current, { type: "image", src, width: w, height: h });
3934
4509
  }, []);
3935
- const getSelectedEmbed = (0, import_react13.useCallback)(() => {
4510
+ const getSelectedEmbed = (0, import_react14.useCallback)(() => {
3936
4511
  const sel = selectionRef.current;
3937
4512
  if (sel.anchor.blockIndex !== sel.focus.blockIndex) return null;
3938
4513
  if ((sel.anchor.cellIndex ?? -1) !== (sel.focus.cellIndex ?? -1)) return null;
@@ -3949,7 +4524,7 @@ function useEditor(opts = {}) {
3949
4524
  cursor += op.insert.length;
3950
4525
  continue;
3951
4526
  }
3952
- if (cursor === start && (0, import_core8.isImageEmbed)(op.insert)) {
4527
+ if (cursor === start && (0, import_core9.isImageEmbed)(op.insert)) {
3953
4528
  return {
3954
4529
  blockIndex: sel.anchor.blockIndex,
3955
4530
  cellIndex: sel.anchor.cellIndex,
@@ -3961,16 +4536,16 @@ function useEditor(opts = {}) {
3961
4536
  }
3962
4537
  return null;
3963
4538
  }, [doc]);
3964
- const [linkRequest, setLinkRequest] = (0, import_react13.useState)(null);
3965
- const linkRequestRef = (0, import_react13.useRef)(null);
3966
- 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 = "") => {
3967
4542
  return new Promise((resolve) => {
3968
4543
  const req = { initialHref, resolve, selection: selectionRef.current };
3969
4544
  linkRequestRef.current = req;
3970
4545
  setLinkRequest(req);
3971
4546
  });
3972
4547
  }, []);
3973
- const resolveLinkRequest = (0, import_react13.useCallback)(
4548
+ const resolveLinkRequest = (0, import_react14.useCallback)(
3974
4549
  (href) => {
3975
4550
  const req = linkRequestRef.current;
3976
4551
  linkRequestRef.current = null;
@@ -3983,26 +4558,26 @@ function useEditor(opts = {}) {
3983
4558
  [setSelection]
3984
4559
  );
3985
4560
  const pageSettings = usePageSettings(doc);
3986
- const setPageSettings = (0, import_react13.useCallback)(
4561
+ const setPageSettings = (0, import_react14.useCallback)(
3987
4562
  (partial) => {
3988
4563
  doc.setPageSettings(partial);
3989
4564
  },
3990
4565
  [doc]
3991
4566
  );
3992
- const [pageConfigRequest, setPageConfigRequest] = (0, import_react13.useState)(null);
3993
- const requestPageConfig = (0, import_react13.useCallback)(() => {
4567
+ const [pageConfigRequest, setPageConfigRequest] = (0, import_react14.useState)(null);
4568
+ const requestPageConfig = (0, import_react14.useCallback)(() => {
3994
4569
  return new Promise((resolve) => {
3995
4570
  setPageConfigRequest({ initial: doc.getPageSettings(), resolve });
3996
4571
  });
3997
4572
  }, [doc]);
3998
- const resolvePageConfigRequest = (0, import_react13.useCallback)((applied) => {
4573
+ const resolvePageConfigRequest = (0, import_react14.useCallback)((applied) => {
3999
4574
  setPageConfigRequest((prev) => {
4000
4575
  if (prev) prev.resolve(applied);
4001
4576
  return null;
4002
4577
  });
4003
4578
  }, []);
4004
- const [imageCaptionRequest, setImageCaptionRequest] = (0, import_react13.useState)(null);
4005
- const requestImageCaption = (0, import_react13.useCallback)(
4579
+ const [imageCaptionRequest, setImageCaptionRequest] = (0, import_react14.useState)(null);
4580
+ const requestImageCaption = (0, import_react14.useCallback)(
4006
4581
  (initialCaption = "", initialAlign = "center") => {
4007
4582
  return new Promise((resolve) => {
4008
4583
  setImageCaptionRequest({ initialCaption, initialAlign, resolve });
@@ -4010,12 +4585,82 @@ function useEditor(opts = {}) {
4010
4585
  },
4011
4586
  []
4012
4587
  );
4013
- const resolveImageCaptionRequest = (0, import_react13.useCallback)((result) => {
4588
+ const resolveImageCaptionRequest = (0, import_react14.useCallback)((result) => {
4014
4589
  setImageCaptionRequest((prev) => {
4015
4590
  if (prev) prev.resolve(result);
4016
4591
  return null;
4017
4592
  });
4018
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
+ );
4019
4664
  return {
4020
4665
  doc,
4021
4666
  history,
@@ -4066,7 +4711,10 @@ function useEditor(opts = {}) {
4066
4711
  mergeRight,
4067
4712
  mergeDown,
4068
4713
  splitCell,
4069
- setColumnWidth,
4714
+ setColumnBoundary,
4715
+ setTableWidth,
4716
+ setRowHeight,
4717
+ setRowHeights,
4070
4718
  getTableRect,
4071
4719
  hasTableRectSelection,
4072
4720
  mergeSelection,
@@ -4083,6 +4731,10 @@ function useEditor(opts = {}) {
4083
4731
  imageCaptionRequest,
4084
4732
  requestImageCaption,
4085
4733
  resolveImageCaptionRequest,
4734
+ formulaRequest,
4735
+ requestFormula,
4736
+ resolveFormulaRequest,
4737
+ insertFormula,
4086
4738
  uploadImage: opts.uploadImage
4087
4739
  };
4088
4740
  }
@@ -4115,7 +4767,7 @@ function sameValue(a, b) {
4115
4767
  }
4116
4768
 
4117
4769
  // src/Editor.tsx
4118
- var import_jsx_runtime12 = require("react/jsx-runtime");
4770
+ var import_jsx_runtime13 = require("react/jsx-runtime");
4119
4771
  var defaultFooter = ({ pageNumber, pageCount }) => `${pageNumber} / ${pageCount}`;
4120
4772
  function Editor({
4121
4773
  editor: providedEditor,
@@ -4128,15 +4780,15 @@ function Editor({
4128
4780
  const internal = useEditor();
4129
4781
  const editor = providedEditor ?? internal;
4130
4782
  const { doc, history, snapshot, getSelection, setSelection } = editor;
4131
- const rootRef = (0, import_react14.useRef)(null);
4132
- const isComposingRef = (0, import_react14.useRef)(false);
4133
- const pasteInFlightRef = (0, import_react14.useRef)(false);
4134
- const [hoveredBehind, setHoveredBehind] = (0, import_react14.useState)(null);
4135
- const hoveredBehindRef = (0, import_react14.useRef)(null);
4136
- const [hoveredLink, setHoveredLink] = (0, import_react14.useState)(null);
4137
- const hoveredLinkElRef = (0, import_react14.useRef)(null);
4138
- const suppressSelectionSyncRef = (0, import_react14.useRef)(false);
4139
- (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)(() => {
4140
4792
  if (!awareness) return;
4141
4793
  const root = rootRef.current;
4142
4794
  if (!root) return;
@@ -4146,7 +4798,7 @@ function Editor({
4146
4798
  const sel = readDomSelection(root);
4147
4799
  awareness.setLocalStateField(
4148
4800
  "cursor",
4149
- sel ? (0, import_core9.encodeSelection)(doc, sel) ?? null : null
4801
+ sel ? (0, import_core10.encodeSelection)(doc, sel) ?? null : null
4150
4802
  );
4151
4803
  };
4152
4804
  const onSelChange = () => {
@@ -4166,13 +4818,13 @@ function Editor({
4166
4818
  awareness.setLocalStateField("cursor", null);
4167
4819
  };
4168
4820
  }, [awareness, doc]);
4169
- const ctxRef = (0, import_react14.useRef)({ doc, getSelection, setSelection });
4821
+ const ctxRef = (0, import_react15.useRef)({ doc, getSelection, setSelection });
4170
4822
  ctxRef.current = { doc, getSelection, setSelection };
4171
- const historyRef = (0, import_react14.useRef)(history);
4823
+ const historyRef = (0, import_react15.useRef)(history);
4172
4824
  historyRef.current = history;
4173
- const editorRef = (0, import_react14.useRef)(editor);
4825
+ const editorRef = (0, import_react15.useRef)(editor);
4174
4826
  editorRef.current = editor;
4175
- (0, import_react14.useLayoutEffect)(() => {
4827
+ (0, import_react15.useLayoutEffect)(() => {
4176
4828
  const root = rootRef.current;
4177
4829
  if (!root) return;
4178
4830
  if (isComposingRef.current) return;
@@ -4187,7 +4839,7 @@ function Editor({
4187
4839
  suppressSelectionSyncRef.current = true;
4188
4840
  applyDomSelection(root, editor.selection);
4189
4841
  });
4190
- (0, import_react14.useEffect)(() => {
4842
+ (0, import_react15.useEffect)(() => {
4191
4843
  const root = rootRef.current;
4192
4844
  if (!root) return;
4193
4845
  const handler = () => {
@@ -4208,7 +4860,7 @@ function Editor({
4208
4860
  document.addEventListener("selectionchange", handler);
4209
4861
  return () => document.removeEventListener("selectionchange", handler);
4210
4862
  }, [setSelection]);
4211
- (0, import_react14.useEffect)(() => {
4863
+ (0, import_react15.useEffect)(() => {
4212
4864
  const root = rootRef.current;
4213
4865
  if (!root) return;
4214
4866
  let drag = null;
@@ -4279,7 +4931,7 @@ function Editor({
4279
4931
  document.removeEventListener("pointerup", onPointerUp);
4280
4932
  };
4281
4933
  }, []);
4282
- (0, import_react14.useEffect)(() => {
4934
+ (0, import_react15.useEffect)(() => {
4283
4935
  const root = rootRef.current;
4284
4936
  if (!root) return;
4285
4937
  const onDragOver = (e) => {
@@ -4317,7 +4969,7 @@ function Editor({
4317
4969
  root.removeEventListener("drop", onDrop);
4318
4970
  };
4319
4971
  }, []);
4320
- (0, import_react14.useEffect)(() => {
4972
+ (0, import_react15.useEffect)(() => {
4321
4973
  const root = rootRef.current;
4322
4974
  if (!root) return;
4323
4975
  const onPointerDown = (e) => {
@@ -4345,7 +4997,27 @@ function Editor({
4345
4997
  root.addEventListener("pointerdown", onPointerDown);
4346
4998
  return () => root.removeEventListener("pointerdown", onPointerDown);
4347
4999
  }, []);
4348
- (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)(() => {
4349
5021
  const root = rootRef.current;
4350
5022
  if (!root) return;
4351
5023
  const same = (a, b) => a === b || !!a && !!b && a.blockIndex === b.blockIndex && a.offset === b.offset && (a.cellIndex ?? -1) === (b.cellIndex ?? -1);
@@ -4398,7 +5070,7 @@ function Editor({
4398
5070
  if (raf) cancelAnimationFrame(raf);
4399
5071
  };
4400
5072
  }, []);
4401
- (0, import_react14.useEffect)(() => {
5073
+ (0, import_react15.useEffect)(() => {
4402
5074
  const root = rootRef.current;
4403
5075
  if (!root) return;
4404
5076
  const clear = () => {
@@ -4433,7 +5105,7 @@ function Editor({
4433
5105
  window.removeEventListener("scroll", clear, true);
4434
5106
  };
4435
5107
  }, []);
4436
- (0, import_react14.useEffect)(() => {
5108
+ (0, import_react15.useEffect)(() => {
4437
5109
  const root = rootRef.current;
4438
5110
  if (!root) return;
4439
5111
  const handler = (e) => {
@@ -4447,14 +5119,14 @@ function Editor({
4447
5119
  const data = e.data ?? "";
4448
5120
  if (data.length > 0) {
4449
5121
  e.preventDefault();
4450
- (0, import_core9.insertText)(ctx, data, ed.consumePendingMarks());
5122
+ (0, import_core10.insertText)(ctx, data, ed.consumePendingMarks());
4451
5123
  }
4452
5124
  return;
4453
5125
  }
4454
5126
  case "insertLineBreak": {
4455
5127
  e.preventDefault();
4456
5128
  if (ed.getBlockType() === "listItem") {
4457
- (0, import_core9.insertText)(ctx, "\n", ed.consumePendingMarks());
5129
+ (0, import_core10.insertText)(ctx, "\n", ed.consumePendingMarks());
4458
5130
  return;
4459
5131
  }
4460
5132
  const selEmbed = ed.getSelectedEmbed();
@@ -4474,7 +5146,7 @@ function Editor({
4474
5146
  });
4475
5147
  }
4476
5148
  if (ed.splitListItem()) return;
4477
- (0, import_core9.insertParagraph)(ctx);
5149
+ (0, import_core10.insertParagraph)(ctx);
4478
5150
  return;
4479
5151
  }
4480
5152
  case "insertParagraph": {
@@ -4496,14 +5168,14 @@ function Editor({
4496
5168
  });
4497
5169
  }
4498
5170
  if (ed.splitListItem()) return;
4499
- (0, import_core9.insertParagraph)(ctx);
5171
+ (0, import_core10.insertParagraph)(ctx);
4500
5172
  return;
4501
5173
  }
4502
5174
  case "insertReplacementText": {
4503
5175
  const text = e.data ?? e.dataTransfer?.getData("text/plain") ?? "";
4504
5176
  if (text.length > 0) {
4505
5177
  e.preventDefault();
4506
- (0, import_core9.insertText)(ctx, text, ed.consumePendingMarks());
5178
+ (0, import_core10.insertText)(ctx, text, ed.consumePendingMarks());
4507
5179
  }
4508
5180
  return;
4509
5181
  }
@@ -4516,7 +5188,7 @@ function Editor({
4516
5188
  case "deleteSoftLineBackward":
4517
5189
  case "deleteHardLineBackward": {
4518
5190
  e.preventDefault();
4519
- (0, import_core9.deleteBackward)(ctx);
5191
+ (0, import_core10.deleteBackward)(ctx);
4520
5192
  return;
4521
5193
  }
4522
5194
  case "deleteContentForward":
@@ -4524,7 +5196,7 @@ function Editor({
4524
5196
  case "deleteSoftLineForward":
4525
5197
  case "deleteHardLineForward": {
4526
5198
  e.preventDefault();
4527
- (0, import_core9.deleteForward)(ctx);
5199
+ (0, import_core10.deleteForward)(ctx);
4528
5200
  return;
4529
5201
  }
4530
5202
  case "historyUndo": {
@@ -4546,15 +5218,15 @@ function Editor({
4546
5218
  root.addEventListener("beforeinput", handler);
4547
5219
  return () => root.removeEventListener("beforeinput", handler);
4548
5220
  }, []);
4549
- (0, import_react14.useEffect)(() => {
5221
+ (0, import_react15.useEffect)(() => {
4550
5222
  const root = rootRef.current;
4551
5223
  if (!root) return;
4552
5224
  const writeSlice = (e) => {
4553
5225
  const ctx = ctxRef.current;
4554
- const slice = (0, import_core9.serializeSelection)(ctx.doc, ctx.getSelection());
5226
+ const slice = (0, import_core10.serializeSelection)(ctx.doc, ctx.getSelection());
4555
5227
  if (!slice || !e.clipboardData) return false;
4556
- e.clipboardData.setData(import_core9.SOFER_MIME, JSON.stringify(slice));
4557
- e.clipboardData.setData("text/plain", (0, import_core9.sliceToText)(slice));
5228
+ e.clipboardData.setData(import_core10.SOFER_MIME, JSON.stringify(slice));
5229
+ e.clipboardData.setData("text/plain", (0, import_core10.sliceToText)(slice));
4558
5230
  return true;
4559
5231
  };
4560
5232
  const onCopy = (e) => {
@@ -4562,7 +5234,7 @@ function Editor({
4562
5234
  };
4563
5235
  const onCut = (e) => {
4564
5236
  e.preventDefault();
4565
- if (writeSlice(e)) (0, import_core9.deleteSelection)(ctxRef.current);
5237
+ if (writeSlice(e)) (0, import_core10.deleteSelection)(ctxRef.current);
4566
5238
  };
4567
5239
  const onPaste = (e) => {
4568
5240
  const ctx = ctxRef.current;
@@ -4573,11 +5245,11 @@ function Editor({
4573
5245
  e.preventDefault();
4574
5246
  switch (plan.kind) {
4575
5247
  case "sofer":
4576
- (0, import_core9.insertSlice)(ctx, plan.slice);
5248
+ (0, import_core10.insertSlice)(ctx, plan.slice);
4577
5249
  return;
4578
5250
  case "html": {
4579
5251
  if (!sliceHasDataImageEmbeds(plan.slice)) {
4580
- (0, import_core9.insertSlice)(ctx, plan.slice);
5252
+ (0, import_core10.insertSlice)(ctx, plan.slice);
4581
5253
  return;
4582
5254
  }
4583
5255
  if (pasteInFlightRef.current) {
@@ -4602,10 +5274,10 @@ function Editor({
4602
5274
  );
4603
5275
  const lastIndex = Math.max(0, ctxRef.current.doc.blockCount() - 1);
4604
5276
  const lastText = ctxRef.current.doc.getBlockText(lastIndex);
4605
- insertAt = (0, import_core9.collapsedSelection)({ blockIndex: lastIndex, offset: lastText ? lastText.length : 0 });
5277
+ insertAt = (0, import_core10.collapsedSelection)({ blockIndex: lastIndex, offset: lastText ? lastText.length : 0 });
4606
5278
  }
4607
5279
  ctxRef.current.setSelection(insertAt);
4608
- (0, import_core9.insertSlice)(ctxRef.current, resolved);
5280
+ (0, import_core10.insertSlice)(ctxRef.current, resolved);
4609
5281
  if (userMovedAway) {
4610
5282
  ctxRef.current.setSelection(liveSelection);
4611
5283
  }
@@ -4623,8 +5295,8 @@ function Editor({
4623
5295
  case "text": {
4624
5296
  const lines = plan.text.split(/\r\n|\r|\n/);
4625
5297
  lines.forEach((line, i) => {
4626
- if (i > 0) (0, import_core9.insertParagraph)(ctx);
4627
- if (line.length > 0) (0, import_core9.insertText)(ctx, line);
5298
+ if (i > 0) (0, import_core10.insertParagraph)(ctx);
5299
+ if (line.length > 0) (0, import_core10.insertText)(ctx, line);
4628
5300
  });
4629
5301
  return;
4630
5302
  }
@@ -4639,7 +5311,7 @@ function Editor({
4639
5311
  root.removeEventListener("paste", onPaste);
4640
5312
  };
4641
5313
  }, []);
4642
- const onKeyDown = (0, import_react14.useCallback)((e) => {
5314
+ const onKeyDown = (0, import_react15.useCallback)((e) => {
4643
5315
  const ed = editorRef.current;
4644
5316
  const mod = e.metaKey || e.ctrlKey;
4645
5317
  if (e.key === "Tab") {
@@ -4670,11 +5342,11 @@ function Editor({
4670
5342
  if (!mod && (e.key === "Backspace" || e.key === "Delete")) {
4671
5343
  if (isComposingRef.current) return;
4672
5344
  const direction = e.key === "Backspace" ? "backward" : "forward";
4673
- const shouldIntercept = ed.getSelectedEmbed() != null || (0, import_core9.isEmbedAdjacentToCaret)(ctxRef.current, direction);
5345
+ const shouldIntercept = ed.getSelectedEmbed() != null || (0, import_core10.isEmbedAdjacentToCaret)(ctxRef.current, direction);
4674
5346
  if (shouldIntercept) {
4675
5347
  e.preventDefault();
4676
- if (direction === "backward") (0, import_core9.deleteBackward)(ctxRef.current);
4677
- else (0, import_core9.deleteForward)(ctxRef.current);
5348
+ if (direction === "backward") (0, import_core10.deleteBackward)(ctxRef.current);
5349
+ else (0, import_core10.deleteForward)(ctxRef.current);
4678
5350
  }
4679
5351
  return;
4680
5352
  }
@@ -4724,17 +5396,17 @@ function Editor({
4724
5396
  });
4725
5397
  }
4726
5398
  }, []);
4727
- const onCompositionStart = (0, import_react14.useCallback)(() => {
5399
+ const onCompositionStart = (0, import_react15.useCallback)(() => {
4728
5400
  isComposingRef.current = true;
4729
5401
  }, []);
4730
- const onCompositionEnd = (0, import_react14.useCallback)((e) => {
5402
+ const onCompositionEnd = (0, import_react15.useCallback)((e) => {
4731
5403
  isComposingRef.current = false;
4732
5404
  if (e.data && e.data.length > 0) {
4733
- (0, import_core9.insertText)(ctxRef.current, e.data);
5405
+ (0, import_core10.insertText)(ctxRef.current, e.data);
4734
5406
  }
4735
5407
  }, []);
4736
- const topLevels = (0, import_react14.useMemo)(() => groupTopLevels(snapshot.blocks), [snapshot]);
4737
- const topLevelsStructuralKey = (0, import_react14.useMemo)(
5408
+ const topLevels = (0, import_react15.useMemo)(() => groupTopLevels(snapshot.blocks), [snapshot]);
5409
+ const topLevelsStructuralKey = (0, import_react15.useMemo)(
4738
5410
  () => topLevels.map(
4739
5411
  (t) => t.kind === "list" ? `L:${t.listKind}:${t.items.length}:${t.ordinalStart}` : `B:${t.block.type}:${t.block.attrs.level ?? ""}`
4740
5412
  ).join("|"),
@@ -4756,7 +5428,7 @@ function Editor({
4756
5428
  [topLevelsStructuralKey, pageGeometry]
4757
5429
  );
4758
5430
  const effectiveLayout = paginated ? layout : defaultPageLayout(topLevels.length);
4759
- const pageStyle = (0, import_react14.useMemo)(
5431
+ const pageStyle = (0, import_react15.useMemo)(
4760
5432
  () => paginated ? {
4761
5433
  "--ed-page-width": `${geom.width}px`,
4762
5434
  "--ed-page-height": `${geom.height}px`,
@@ -4775,7 +5447,7 @@ function Editor({
4775
5447
  geom.marginRight
4776
5448
  ]
4777
5449
  );
4778
- const body = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5450
+ const body = /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4779
5451
  "div",
4780
5452
  {
4781
5453
  ref: rootRef,
@@ -4801,7 +5473,7 @@ function Editor({
4801
5473
  const pageInlineStyle = pi === 0 && geom.firstPageExtraTop ? {
4802
5474
  "--ed-page-margin-top": `${geom.marginTop + geom.firstPageExtraTop}px`
4803
5475
  } : void 0;
4804
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5476
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4805
5477
  "div",
4806
5478
  {
4807
5479
  className: "ed-page",
@@ -4809,15 +5481,15 @@ function Editor({
4809
5481
  "data-page-total": ctx.pageCount,
4810
5482
  style: pageInlineStyle,
4811
5483
  children: [
4812
- renderPageHeader && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ed-page-header", contentEditable: false, children: renderPageHeader(ctx) }),
4813
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ed-page-content", children: page.slots.map((slot) => renderSlot(slot, topLevels)) }),
4814
- 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) })
4815
5487
  ]
4816
5488
  },
4817
5489
  `page-${pi}`
4818
5490
  );
4819
5491
  }) : topLevels.map((t) => renderTopLevel(t)),
4820
- selectedEmbed && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5492
+ selectedEmbed && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4821
5493
  ImageResizeOverlay,
4822
5494
  {
4823
5495
  rootRef,
@@ -4849,7 +5521,7 @@ function Editor({
4849
5521
  )
4850
5522
  }
4851
5523
  ),
4852
- 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)(
4853
5525
  BehindImageSelectAffordance,
4854
5526
  {
4855
5527
  rootRef,
@@ -4870,8 +5542,8 @@ function Editor({
4870
5542
  })
4871
5543
  }
4872
5544
  ),
4873
- hoveredLink && hoveredLink.href && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LinkHoverTooltip, { href: hoveredLink.href, rect: hoveredLink.rect }),
4874
- 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)(
4875
5547
  RemoteCursorsOverlay,
4876
5548
  {
4877
5549
  rootRef,
@@ -4883,7 +5555,7 @@ function Editor({
4883
5555
  ]
4884
5556
  }
4885
5557
  );
4886
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(EditorProvider, { editor, children: body });
5558
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(EditorProvider, { editor, children: body });
4887
5559
  }
4888
5560
  function groupTopLevels(snapshot) {
4889
5561
  const out = [];
@@ -4937,7 +5609,7 @@ function renderSlot(slot, topLevels) {
4937
5609
  start: slot.fragment.start,
4938
5610
  end: slot.fragment.end
4939
5611
  };
4940
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5612
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4941
5613
  NodeView,
4942
5614
  {
4943
5615
  block: top.block,
@@ -4948,7 +5620,7 @@ function renderSlot(slot, topLevels) {
4948
5620
  );
4949
5621
  }
4950
5622
  if (slot.tableFragment && top.kind === "block" && top.block.type === "table") {
4951
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5623
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4952
5624
  NodeView,
4953
5625
  {
4954
5626
  block: top.block,
@@ -4968,7 +5640,7 @@ function renderTopLevel(top) {
4968
5640
  const tree = buildListTree(top.items);
4969
5641
  return renderListTree(tree, top, top.ordinalStart, `list-${top.key}`);
4970
5642
  }
4971
- 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);
4972
5644
  }
4973
5645
  function renderListFragment(top, frag) {
4974
5646
  const ranges = topLevelItemRanges(top.items);
@@ -5010,9 +5682,9 @@ function buildListTree(items) {
5010
5682
  function renderListTree(tree, top, start, key) {
5011
5683
  const className = `ed-list ed-list-${top.listKind}`;
5012
5684
  const style = top.listStyle ? { listStyleType: top.listStyle } : void 0;
5013
- 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));
5014
5686
  if (top.listKind === "ordered") {
5015
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5687
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5016
5688
  "ol",
5017
5689
  {
5018
5690
  className,
@@ -5024,12 +5696,12 @@ function renderListTree(tree, top, start, key) {
5024
5696
  key
5025
5697
  );
5026
5698
  }
5027
- 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);
5028
5700
  }
5029
5701
  function renderNestedListTree(tree, key) {
5030
5702
  const kind = tree[0]?.entry.block.attrs.listKind === "ordered" ? "ordered" : "bullet";
5031
5703
  const Tag = kind === "ordered" ? "ol" : "ul";
5032
- 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);
5033
5705
  }
5034
5706
  function clampListLevel2(l) {
5035
5707
  if (typeof l !== "number" || !Number.isFinite(l)) return 0;
@@ -5057,9 +5729,76 @@ function caretRangeFromPoint(x, y) {
5057
5729
  }
5058
5730
 
5059
5731
  // src/Toolbar.tsx
5060
- var import_react15 = require("react");
5061
- var import_core10 = require("@sofereditor/core");
5062
- 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");
5063
5802
  var FONT_FAMILIES = ["Arial"];
5064
5803
  var FONT_SIZES = ["8pt", "10pt", "11pt", "12pt", "14pt", "16pt", "18pt", "24pt", "32pt", "48pt"];
5065
5804
  var BLOCK_OPTIONS = [
@@ -5163,14 +5902,14 @@ function Toolbar({ className }) {
5163
5902
  }
5164
5903
  setAlign(value);
5165
5904
  };
5166
- const onInsertImageClick = (0, import_react15.useCallback)(
5905
+ const onInsertImageClick = (0, import_react16.useCallback)(
5167
5906
  (e) => {
5168
5907
  e.preventDefault();
5169
5908
  imageInputRef.current?.click();
5170
5909
  },
5171
5910
  []
5172
5911
  );
5173
- const onImageInputChange = (0, import_react15.useCallback)(
5912
+ const onImageInputChange = (0, import_react16.useCallback)(
5174
5913
  (e) => {
5175
5914
  const file = e.target.files?.[0];
5176
5915
  if (file) void editor.insertImageFromFile(file);
@@ -5178,14 +5917,14 @@ function Toolbar({ className }) {
5178
5917
  },
5179
5918
  [editor]
5180
5919
  );
5181
- const imageInputRef = (0, import_react15.useRef)(null);
5920
+ const imageInputRef = (0, import_react16.useRef)(null);
5182
5921
  const onToggleDir = (e) => {
5183
5922
  e.preventDefault();
5184
5923
  const next = blockDir === "rtl" ? "ltr" : "rtl";
5185
5924
  setBlockAttr("dir", next);
5186
5925
  };
5187
5926
  const linkActive = isMarkActive("link");
5188
- const onLinkClick = (0, import_react15.useCallback)(
5927
+ const onLinkClick = (0, import_react16.useCallback)(
5189
5928
  (e) => {
5190
5929
  e.preventDefault();
5191
5930
  const currentHref = active.link && typeof active.link === "object" && "href" in active.link ? active.link.href : "";
@@ -5216,7 +5955,7 @@ function Toolbar({ className }) {
5216
5955
  sel.cellIndex
5217
5956
  );
5218
5957
  };
5219
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
5958
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5220
5959
  "div",
5221
5960
  {
5222
5961
  className: className ?? "ed-toolbar",
@@ -5224,7 +5963,7 @@ function Toolbar({ className }) {
5224
5963
  "aria-label": "Editor toolbar",
5225
5964
  onMouseDown: stop,
5226
5965
  children: [
5227
- /* @__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)(
5228
5967
  "select",
5229
5968
  {
5230
5969
  className: "ed-toolbar-select",
@@ -5233,23 +5972,23 @@ function Toolbar({ className }) {
5233
5972
  onMouseDown: stop,
5234
5973
  "aria-label": "Tipo de bloco",
5235
5974
  children: [
5236
- blockValue === "" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "", children: "\u2014 (misto)" }),
5237
- 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))
5238
5977
  ]
5239
5978
  }
5240
5979
  ) }),
5241
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5242
- /* @__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" }) }),
5243
- /* @__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" }) }),
5244
- /* @__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" }) }),
5245
- /* @__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" }) })
5246
5985
  ] }),
5247
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5248
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label", children: [
5249
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ed-toolbar-swatch", "aria-hidden": true, style: { background: colorValue } }),
5250
- /* @__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" })
5251
5990
  ] }),
5252
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5991
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5253
5992
  "button",
5254
5993
  {
5255
5994
  type: "button",
@@ -5263,8 +6002,8 @@ function Toolbar({ className }) {
5263
6002
  children: "\u232B"
5264
6003
  }
5265
6004
  ),
5266
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label", title: "Marca-texto", children: [
5267
- /* @__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)(
5268
6007
  "span",
5269
6008
  {
5270
6009
  className: "ed-toolbar-swatch ed-toolbar-swatch--highlight",
@@ -5272,7 +6011,7 @@ function Toolbar({ className }) {
5272
6011
  style: { background: highlightValue }
5273
6012
  }
5274
6013
  ),
5275
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6014
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5276
6015
  "input",
5277
6016
  {
5278
6017
  type: "color",
@@ -5283,7 +6022,7 @@ function Toolbar({ className }) {
5283
6022
  }
5284
6023
  )
5285
6024
  ] }),
5286
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6025
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5287
6026
  "button",
5288
6027
  {
5289
6028
  type: "button",
@@ -5298,8 +6037,8 @@ function Toolbar({ className }) {
5298
6037
  }
5299
6038
  )
5300
6039
  ] }),
5301
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5302
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6040
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Group, { children: [
6041
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5303
6042
  "select",
5304
6043
  {
5305
6044
  className: "ed-toolbar-select",
@@ -5308,12 +6047,12 @@ function Toolbar({ className }) {
5308
6047
  onMouseDown: stop,
5309
6048
  "aria-label": "Fam\xEDlia da fonte",
5310
6049
  children: [
5311
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "", children: "Fonte\u2026" }),
5312
- 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))
5313
6052
  ]
5314
6053
  }
5315
6054
  ),
5316
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6055
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5317
6056
  "select",
5318
6057
  {
5319
6058
  className: "ed-toolbar-select",
@@ -5322,13 +6061,13 @@ function Toolbar({ className }) {
5322
6061
  onMouseDown: stop,
5323
6062
  "aria-label": "Tamanho da fonte",
5324
6063
  children: [
5325
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "", children: "Tamanho\u2026" }),
5326
- 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))
5327
6066
  ]
5328
6067
  }
5329
6068
  )
5330
6069
  ] }),
5331
- /* @__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)(
5332
6071
  "button",
5333
6072
  {
5334
6073
  type: "button",
@@ -5341,7 +6080,7 @@ function Toolbar({ className }) {
5341
6080
  },
5342
6081
  a.value
5343
6082
  )) }),
5344
- /* @__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)(
5345
6084
  "button",
5346
6085
  {
5347
6086
  type: "button",
@@ -5353,8 +6092,8 @@ function Toolbar({ className }) {
5353
6092
  children: blockDir === "rtl" ? "RTL" : "LTR"
5354
6093
  }
5355
6094
  ) }),
5356
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5357
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6095
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Group, { children: [
6096
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5358
6097
  "button",
5359
6098
  {
5360
6099
  type: "button",
@@ -5369,7 +6108,7 @@ function Toolbar({ className }) {
5369
6108
  children: "\u2022"
5370
6109
  }
5371
6110
  ),
5372
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6111
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5373
6112
  "button",
5374
6113
  {
5375
6114
  type: "button",
@@ -5384,7 +6123,7 @@ function Toolbar({ className }) {
5384
6123
  children: "1."
5385
6124
  }
5386
6125
  ),
5387
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6126
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5388
6127
  "button",
5389
6128
  {
5390
6129
  type: "button",
@@ -5398,7 +6137,7 @@ function Toolbar({ className }) {
5398
6137
  children: "\u21E4"
5399
6138
  }
5400
6139
  ),
5401
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6140
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5402
6141
  "button",
5403
6142
  {
5404
6143
  type: "button",
@@ -5413,7 +6152,7 @@ function Toolbar({ className }) {
5413
6152
  }
5414
6153
  )
5415
6154
  ] }),
5416
- /* @__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)(
5417
6156
  "button",
5418
6157
  {
5419
6158
  type: "button",
@@ -5425,12 +6164,12 @@ function Toolbar({ className }) {
5425
6164
  children: "\u{1F517}"
5426
6165
  }
5427
6166
  ) }),
5428
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5429
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TableMenu, {}),
5430
- /* @__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, {})
5431
6170
  ] }),
5432
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5433
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6171
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Group, { children: [
6172
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5434
6173
  "button",
5435
6174
  {
5436
6175
  type: "button",
@@ -5441,7 +6180,7 @@ function Toolbar({ className }) {
5441
6180
  children: "\u{1F5BC}"
5442
6181
  }
5443
6182
  ),
5444
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6183
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5445
6184
  "input",
5446
6185
  {
5447
6186
  ref: imageInputRef,
@@ -5450,10 +6189,26 @@ function Toolbar({ className }) {
5450
6189
  hidden: true,
5451
6190
  onChange: onImageInputChange
5452
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
+ }
5453
6208
  )
5454
6209
  ] }),
5455
- selectedEmbed && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
5456
- 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)(
5457
6212
  "button",
5458
6213
  {
5459
6214
  type: "button",
@@ -5466,7 +6221,25 @@ function Toolbar({ className }) {
5466
6221
  },
5467
6222
  opt.value
5468
6223
  )),
5469
- /* @__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)(
5470
6243
  "button",
5471
6244
  {
5472
6245
  type: "button",
@@ -5496,7 +6269,7 @@ function Toolbar({ className }) {
5496
6269
  }
5497
6270
  )
5498
6271
  ] }),
5499
- /* @__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)(
5500
6273
  "button",
5501
6274
  {
5502
6275
  type: "button",
@@ -5516,11 +6289,11 @@ function Toolbar({ className }) {
5516
6289
  }
5517
6290
  function AnswerLinesMenu() {
5518
6291
  const editor = useEditorContext();
5519
- const [open, setOpen] = (0, import_react15.useState)(false);
5520
- const [count, setCount] = (0, import_react15.useState)(5);
5521
- const [spacing, setSpacing] = (0, import_react15.useState)(1.5);
5522
- const rootRef = (0, import_react15.useRef)(null);
5523
- (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)(() => {
5524
6297
  if (!open) return;
5525
6298
  const onDown = (e) => {
5526
6299
  if (!rootRef.current) return;
@@ -5530,9 +6303,9 @@ function AnswerLinesMenu() {
5530
6303
  document.addEventListener("mousedown", onDown);
5531
6304
  return () => document.removeEventListener("mousedown", onDown);
5532
6305
  }, [open]);
5533
- const clamped = Math.max(1, Math.min(import_core10.ANSWER_LINE_MAX, Math.trunc(count) || 1));
5534
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { ref: rootRef, className: "ed-toolbar-tablemenu", children: [
5535
- /* @__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)(
5536
6309
  "button",
5537
6310
  {
5538
6311
  type: "button",
@@ -5547,7 +6320,7 @@ function AnswerLinesMenu() {
5547
6320
  children: "\u2630"
5548
6321
  }
5549
6322
  ),
5550
- open && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6323
+ open && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5551
6324
  "div",
5552
6325
  {
5553
6326
  className: "ed-table-popover ed-answerlines-popover",
@@ -5556,37 +6329,37 @@ function AnswerLinesMenu() {
5556
6329
  if (!keepsOwnMouseDown(e.target)) e.preventDefault();
5557
6330
  },
5558
6331
  children: [
5559
- /* @__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: [
5560
6333
  "Quantidade",
5561
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6334
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5562
6335
  "input",
5563
6336
  {
5564
6337
  type: "number",
5565
6338
  min: 1,
5566
- max: import_core10.ANSWER_LINE_MAX,
6339
+ max: import_core11.ANSWER_LINE_MAX,
5567
6340
  value: count,
5568
6341
  onChange: (e) => setCount(Number(e.target.value)),
5569
6342
  "aria-label": "Quantidade de linhas"
5570
6343
  }
5571
6344
  )
5572
6345
  ] }),
5573
- /* @__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: [
5574
6347
  "Entrelinha",
5575
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6348
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5576
6349
  "select",
5577
6350
  {
5578
6351
  value: String(spacing),
5579
6352
  onChange: (e) => setSpacing(Number(e.target.value)),
5580
6353
  "aria-label": "Entrelinha",
5581
6354
  children: [
5582
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "1", children: "Simples" }),
5583
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "1.5", children: "1,5" }),
5584
- /* @__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" })
5585
6358
  ]
5586
6359
  }
5587
6360
  )
5588
6361
  ] }),
5589
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6362
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5590
6363
  "button",
5591
6364
  {
5592
6365
  type: "button",
@@ -5610,9 +6383,10 @@ function AnswerLinesMenu() {
5610
6383
  function TableMenu() {
5611
6384
  const editor = useEditorContext();
5612
6385
  const inTable = editor.isInTable();
5613
- const [open, setOpen] = (0, import_react15.useState)(false);
5614
- const rootRef = (0, import_react15.useRef)(null);
5615
- (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)(() => {
5616
6390
  if (!open) return;
5617
6391
  const onDown = (e) => {
5618
6392
  if (!rootRef.current) return;
@@ -5622,8 +6396,11 @@ function TableMenu() {
5622
6396
  document.addEventListener("mousedown", onDown);
5623
6397
  return () => document.removeEventListener("mousedown", onDown);
5624
6398
  }, [open]);
5625
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { ref: rootRef, className: "ed-toolbar-tablemenu", children: [
5626
- /* @__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)(
5627
6404
  "button",
5628
6405
  {
5629
6406
  type: "button",
@@ -5638,7 +6415,7 @@ function TableMenu() {
5638
6415
  children: "\u25A6"
5639
6416
  }
5640
6417
  ),
5641
- open && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6418
+ open && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5642
6419
  "div",
5643
6420
  {
5644
6421
  className: "ed-table-popover",
@@ -5647,7 +6424,7 @@ function TableMenu() {
5647
6424
  if (!keepsOwnMouseDown(e.target)) e.preventDefault();
5648
6425
  },
5649
6426
  children: [
5650
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6427
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5651
6428
  TableSizePicker,
5652
6429
  {
5653
6430
  onPick: (rows, cols) => {
@@ -5656,34 +6433,34 @@ function TableMenu() {
5656
6433
  }
5657
6434
  }
5658
6435
  ),
5659
- inTable && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ed-table-actions", children: [
5660
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", {}),
5661
- /* @__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: () => {
5662
6439
  setOpen(false);
5663
6440
  editor.insertRowAbove();
5664
6441
  }, children: "Inserir linha acima" }),
5665
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6442
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5666
6443
  setOpen(false);
5667
6444
  editor.insertRowBelow();
5668
6445
  }, children: "Inserir linha abaixo" }),
5669
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6446
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5670
6447
  setOpen(false);
5671
6448
  editor.insertColumnLeft();
5672
6449
  }, children: "Inserir coluna \xE0 esquerda" }),
5673
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6450
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5674
6451
  setOpen(false);
5675
6452
  editor.insertColumnRight();
5676
6453
  }, children: "Inserir coluna \xE0 direita" }),
5677
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6454
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5678
6455
  setOpen(false);
5679
6456
  editor.deleteCurrentRow();
5680
6457
  }, children: "Excluir linha" }),
5681
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6458
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5682
6459
  setOpen(false);
5683
6460
  editor.deleteCurrentColumn();
5684
6461
  }, children: "Excluir coluna" }),
5685
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", {}),
5686
- 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)(
5687
6464
  "button",
5688
6465
  {
5689
6466
  type: "button",
@@ -5694,21 +6471,21 @@ function TableMenu() {
5694
6471
  children: "Mesclar c\xE9lulas selecionadas"
5695
6472
  }
5696
6473
  ),
5697
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6474
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5698
6475
  setOpen(false);
5699
6476
  editor.mergeRight();
5700
6477
  }, children: "Mesclar com c\xE9lula \xE0 direita" }),
5701
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6478
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5702
6479
  setOpen(false);
5703
6480
  editor.mergeDown();
5704
6481
  }, children: "Mesclar com c\xE9lula abaixo" }),
5705
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6482
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5706
6483
  setOpen(false);
5707
6484
  editor.splitCell();
5708
6485
  }, children: "Dividir c\xE9lulas mescladas" }),
5709
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", {}),
5710
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label ed-table-bgcolor", children: [
5711
- /* @__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)(
5712
6489
  "span",
5713
6490
  {
5714
6491
  className: "ed-toolbar-swatch",
@@ -5717,7 +6494,7 @@ function TableMenu() {
5717
6494
  }
5718
6495
  ),
5719
6496
  "Cor de fundo da c\xE9lula",
5720
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6497
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5721
6498
  "input",
5722
6499
  {
5723
6500
  type: "color",
@@ -5727,62 +6504,39 @@ function TableMenu() {
5727
6504
  }
5728
6505
  )
5729
6506
  ] }),
5730
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
6507
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: () => {
5731
6508
  setOpen(false);
5732
6509
  editor.setCellBackground(null);
5733
6510
  }, children: "Remover cor de fundo" }),
5734
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", {}),
5735
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label", children: [
5736
- "Bordas",
5737
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
5738
- "select",
5739
- {
5740
- value: editor.getTableBorderPreset(),
5741
- onChange: (e) => editor.setTableBorderPreset(e.target.value),
5742
- "aria-label": "Bordas da tabela",
5743
- children: [
5744
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "all", children: "Todas" }),
5745
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "outer", children: "S\xF3 externas" }),
5746
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "horizontal", children: "S\xF3 horizontais" }),
5747
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "vertical", children: "S\xF3 verticais" }),
5748
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "none", children: "Nenhuma" })
5749
- ]
5750
- }
5751
- )
5752
- ] }),
5753
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label ed-table-bgcolor", children: [
5754
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5755
- "span",
5756
- {
5757
- className: "ed-toolbar-swatch",
5758
- "aria-hidden": true,
5759
- style: { background: editor.getTableBorderColor() ?? import_core10.TABLE_BORDER_COLOR }
5760
- }
5761
- ),
5762
- "Cor da borda",
5763
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5764
- "input",
5765
- {
5766
- type: "color",
5767
- value: editor.getTableBorderColor() ?? import_core10.TABLE_BORDER_COLOR,
5768
- onChange: (e) => editor.setTableBorderColor(e.target.value),
5769
- "aria-label": "Cor da borda"
5770
- }
5771
- )
5772
- ] }),
5773
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6511
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", {}),
6512
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5774
6513
  "button",
5775
6514
  {
5776
6515
  type: "button",
5777
- onClick: () => {
5778
- setOpen(false);
5779
- 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);
5780
6524
  },
5781
- 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)
5782
6536
  }
5783
6537
  ),
5784
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", {}),
5785
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6538
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("hr", {}),
6539
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5786
6540
  "button",
5787
6541
  {
5788
6542
  type: "button",
@@ -5803,11 +6557,11 @@ function TableMenu() {
5803
6557
  var PICKER_MAX_ROWS = 8;
5804
6558
  var PICKER_MAX_COLS = 10;
5805
6559
  function TableSizePicker({ onPick }) {
5806
- const [hover, setHover] = (0, import_react15.useState)(null);
6560
+ const [hover, setHover] = (0, import_react16.useState)(null);
5807
6561
  const label = hover ? `${hover.r + 1} \xD7 ${hover.c + 1}` : "Inserir tabela";
5808
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ed-table-picker", children: [
5809
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ed-table-picker-label", children: label }),
5810
- /* @__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)(
5811
6565
  "div",
5812
6566
  {
5813
6567
  className: "ed-table-picker-grid",
@@ -5820,7 +6574,7 @@ function TableSizePicker({ onPick }) {
5820
6574
  { length: PICKER_MAX_ROWS },
5821
6575
  (_, r) => Array.from({ length: PICKER_MAX_COLS }, (_2, c) => {
5822
6576
  const filled = hover != null && r <= hover.r && c <= hover.c;
5823
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6577
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5824
6578
  "button",
5825
6579
  {
5826
6580
  type: "button",
@@ -5850,10 +6604,10 @@ function blockSelectValue(type, level) {
5850
6604
  return type;
5851
6605
  }
5852
6606
  function Group({ children }) {
5853
- 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 });
5854
6608
  }
5855
6609
  function MarkButton({ title, pressed, onClick, children }) {
5856
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6610
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5857
6611
  "button",
5858
6612
  {
5859
6613
  type: "button",
@@ -5871,6 +6625,7 @@ function MarkButton({ title, pressed, onClick, children }) {
5871
6625
  A4_PAGE,
5872
6626
  Editor,
5873
6627
  EditorProvider,
6628
+ FormulaDialog,
5874
6629
  ImageCaptionDialog,
5875
6630
  LinkDialog,
5876
6631
  NodeView,