@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.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // src/Editor.tsx
2
2
  import {
3
- useCallback as useCallback7,
4
- useEffect as useEffect9,
3
+ useCallback as useCallback8,
4
+ useEffect as useEffect10,
5
5
  useLayoutEffect as useLayoutEffect5,
6
6
  useMemo as useMemo4,
7
- useRef as useRef11,
8
- useState as useState10
7
+ useRef as useRef12,
8
+ useState as useState11
9
9
  } from "react";
10
10
  import {
11
11
  collapsedSelection as collapsedSelection2,
@@ -17,6 +17,7 @@ import {
17
17
  insertSlice,
18
18
  insertText,
19
19
  isEmbedAdjacentToCaret,
20
+ isFormulaEmbed as isFormulaEmbed2,
20
21
  serializeSelection,
21
22
  sliceToText,
22
23
  SOFER_MIME as SOFER_MIME2
@@ -1802,15 +1803,376 @@ function ImageCaptionDialog() {
1802
1803
  );
1803
1804
  }
1804
1805
 
1805
- // src/EditorContext.tsx
1806
+ // src/FormulaDialog.tsx
1807
+ import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef4, useState as useState5 } from "react";
1808
+
1809
+ // src/formulaSnippet.ts
1810
+ var PALETA = [
1811
+ {
1812
+ nome: "Estruturas",
1813
+ colunas: 4,
1814
+ itens: [
1815
+ { label: "Fra\xE7\xE3o", snippet: "\\frac{}{}" },
1816
+ { label: "Expoente", snippet: "^{}" },
1817
+ { label: "\xCDndice", snippet: "_{}" },
1818
+ { label: "Raiz", snippet: "\\sqrt{}" },
1819
+ { label: "Raiz n-\xE9sima", snippet: "\\sqrt[{}]{}" },
1820
+ { label: "Somat\xF3rio", snippet: "\\sum_{}^{}" },
1821
+ { label: "Produt\xF3rio", snippet: "\\prod_{}^{}" },
1822
+ { label: "Integral", snippet: "\\int_{}^{}" },
1823
+ { label: "Limite", snippet: "\\lim_{{} \\to {}}" },
1824
+ { label: "Derivada", snippet: "\\frac{d}{d{}}" },
1825
+ {
1826
+ label: "Matriz 2\xD72",
1827
+ snippet: "\\begin{pmatrix} {} & {} \\\\ {} & {} \\end{pmatrix}"
1828
+ },
1829
+ { label: "Sistema", snippet: "\\begin{cases} {} \\\\ \\end{cases}" },
1830
+ { label: "Par\xEAnteses", snippet: "\\left({}\\right)" },
1831
+ { label: "Binomial", snippet: "\\binom{}{}" },
1832
+ { label: "M\xF3dulo", snippet: "\\left|{}\\right|" }
1833
+ ]
1834
+ },
1835
+ {
1836
+ nome: "S\xEDmbolos",
1837
+ colunas: 6,
1838
+ itens: [
1839
+ { label: "\xB1", snippet: "\\pm", titulo: "mais ou menos" },
1840
+ { label: "\xD7", snippet: "\\times", titulo: "multiplica\xE7\xE3o" },
1841
+ { label: "\xF7", snippet: "\\div", titulo: "divis\xE3o" },
1842
+ { label: "\xB7", snippet: "\\cdot", titulo: "multiplica\xE7\xE3o (ponto)" },
1843
+ { label: "\u221E", snippet: "\\infty", titulo: "infinito" },
1844
+ { label: "\xB0", snippet: "^\\circ", titulo: "grau" },
1845
+ { label: "%", snippet: "\\%", titulo: "por cento" },
1846
+ { label: ",", snippet: "{,}", titulo: "v\xEDrgula decimal" }
1847
+ ]
1848
+ },
1849
+ {
1850
+ nome: "Rela\xE7\xF5es",
1851
+ colunas: 6,
1852
+ itens: [
1853
+ { label: "\u2260", snippet: "\\neq", titulo: "diferente de" },
1854
+ { label: "\u2248", snippet: "\\approx", titulo: "aproximadamente" },
1855
+ { label: "\u2261", snippet: "\\equiv", titulo: "id\xEAntico a" },
1856
+ { label: "\u2264", snippet: "\\leq", titulo: "menor ou igual a" },
1857
+ { label: "\u2265", snippet: "\\geq", titulo: "maior ou igual a" },
1858
+ { label: "\u221D", snippet: "\\propto", titulo: "proporcional a" },
1859
+ { label: "\u22A5", snippet: "\\perp", titulo: "perpendicular a" },
1860
+ { label: "\u2225", snippet: "\\parallel", titulo: "paralelo a" },
1861
+ { label: "\u2245", snippet: "\\cong", titulo: "congruente a" },
1862
+ { label: "\u223C", snippet: "\\sim", titulo: "semelhante a" }
1863
+ ]
1864
+ },
1865
+ {
1866
+ nome: "Gregas",
1867
+ colunas: 6,
1868
+ itens: [
1869
+ { label: "\u03B1", snippet: "\\alpha", titulo: "alfa" },
1870
+ { label: "\u03B2", snippet: "\\beta", titulo: "beta" },
1871
+ { label: "\u03B3", snippet: "\\gamma", titulo: "gama" },
1872
+ { label: "\u03B4", snippet: "\\delta", titulo: "delta" },
1873
+ { label: "\u03B5", snippet: "\\varepsilon", titulo: "\xE9psilon" },
1874
+ { label: "\u03B8", snippet: "\\theta", titulo: "teta" },
1875
+ { label: "\u03BB", snippet: "\\lambda", titulo: "lambda" },
1876
+ { label: "\u03BC", snippet: "\\mu", titulo: "mi" },
1877
+ { label: "\u03C0", snippet: "\\pi", titulo: "pi" },
1878
+ { label: "\u03C1", snippet: "\\rho", titulo: "r\xF4" },
1879
+ { label: "\u03C3", snippet: "\\sigma", titulo: "sigma" },
1880
+ { label: "\u03C6", snippet: "\\varphi", titulo: "fi" },
1881
+ { label: "\u03C9", snippet: "\\omega", titulo: "\xF4mega" },
1882
+ { label: "\u0394", snippet: "\\Delta", titulo: "delta mai\xFAsculo" },
1883
+ {
1884
+ label: "\u03A3",
1885
+ snippet: "\\Sigma",
1886
+ titulo: "sigma mai\xFAsculo \u2014 letra grega; para somat\xF3rio use Estruturas"
1887
+ },
1888
+ {
1889
+ label: "\u03A0",
1890
+ snippet: "\\Pi",
1891
+ titulo: "pi mai\xFAsculo \u2014 letra grega; para produt\xF3rio use Estruturas"
1892
+ },
1893
+ { label: "\u03A9", snippet: "\\Omega", titulo: "\xF4mega mai\xFAsculo" },
1894
+ { label: "\u03A6", snippet: "\\Phi", titulo: "fi mai\xFAsculo" }
1895
+ ]
1896
+ },
1897
+ {
1898
+ nome: "Conjuntos",
1899
+ colunas: 6,
1900
+ itens: [
1901
+ { label: "\u2208", snippet: "\\in", titulo: "pertence a" },
1902
+ { label: "\u2209", snippet: "\\notin", titulo: "n\xE3o pertence a" },
1903
+ { label: "\u2282", snippet: "\\subset", titulo: "contido em" },
1904
+ { label: "\u2286", snippet: "\\subseteq", titulo: "contido ou igual a" },
1905
+ { label: "\u222A", snippet: "\\cup", titulo: "uni\xE3o" },
1906
+ { label: "\u2229", snippet: "\\cap", titulo: "interse\xE7\xE3o" },
1907
+ { label: "\u2205", snippet: "\\varnothing", titulo: "conjunto vazio" },
1908
+ { label: "\u2115", snippet: "\\mathbb{N}", titulo: "conjunto dos naturais" },
1909
+ { label: "\u2124", snippet: "\\mathbb{Z}", titulo: "conjunto dos inteiros" },
1910
+ { label: "\u211A", snippet: "\\mathbb{Q}", titulo: "conjunto dos racionais" },
1911
+ { label: "\u211D", snippet: "\\mathbb{R}", titulo: "conjunto dos reais" },
1912
+ { label: "\u2102", snippet: "\\mathbb{C}", titulo: "conjunto dos complexos" },
1913
+ { label: "\u2200", snippet: "\\forall", titulo: "para todo" },
1914
+ { label: "\u2203", snippet: "\\exists", titulo: "existe" },
1915
+ { label: "{ }", snippet: "\\{{}\\}", titulo: "chaves de conjunto" }
1916
+ ]
1917
+ },
1918
+ {
1919
+ nome: "Fun\xE7\xF5es",
1920
+ colunas: 6,
1921
+ itens: [
1922
+ { label: "sen", snippet: "\\operatorname{sen}", titulo: "seno" },
1923
+ { label: "cos", snippet: "\\cos", titulo: "cosseno" },
1924
+ { label: "tg", snippet: "\\operatorname{tg}", titulo: "tangente" },
1925
+ { label: "cotg", snippet: "\\operatorname{cotg}", titulo: "cotangente" },
1926
+ { label: "log", snippet: "\\log_{}", titulo: "logaritmo" },
1927
+ { label: "ln", snippet: "\\ln", titulo: "logaritmo natural" },
1928
+ { label: "exp", snippet: "\\exp", titulo: "exponencial" }
1929
+ ]
1930
+ },
1931
+ {
1932
+ nome: "Setas",
1933
+ colunas: 6,
1934
+ itens: [
1935
+ { label: "\u2192", snippet: "\\to", titulo: "tende a / vai para" },
1936
+ { label: "\u2190", snippet: "\\leftarrow", titulo: "vem de / sentido inverso" },
1937
+ { label: "\u21D2", snippet: "\\Rightarrow", titulo: "implica em" },
1938
+ { label: "\u21D4", snippet: "\\Leftrightarrow", titulo: "se e somente se" },
1939
+ { label: "\u21CC", snippet: "\\rightleftharpoons", titulo: "equil\xEDbrio qu\xEDmico" },
1940
+ { label: "vetor AB", snippet: "\\overrightarrow{}", titulo: "vetor entre dois pontos (AB)" },
1941
+ { label: "vetor", snippet: "\\vec{}", titulo: "vetor (f\xEDsica)" },
1942
+ { label: "\u2220", snippet: "\\angle", titulo: "\xE2ngulo" },
1943
+ { label: "\u25B3", snippet: "\\triangle", titulo: "tri\xE2ngulo" }
1944
+ ]
1945
+ }
1946
+ ];
1947
+ function paraMathlive(snippet) {
1948
+ return snippet.replaceAll("{}", "{#?}");
1949
+ }
1950
+ function paraMarkup(snippet) {
1951
+ return snippet.replaceAll("{}", "{\u25A1}");
1952
+ }
1953
+ function conteudoDoBotao(markup, snippet, label) {
1954
+ if (!markup) return { children: label };
1955
+ return { dangerouslySetInnerHTML: { __html: markup(paraMarkup(snippet)) } };
1956
+ }
1957
+
1958
+ // src/formulaGuarda.ts
1959
+ var PLACEHOLDER = "\\placeholder{}";
1960
+ var GRUPO_VAZIO = /\{\s*\}/;
1961
+ var CELULA_VAZIA = /(?:\\begin\{[a-zA-Z]+\*?\}|&|\\\\)\s*(?:&|\\\\|\\end\{)/;
1962
+ function podeInserir(latex, preview) {
1963
+ if (motivoBloqueio(latex, preview) !== null) return false;
1964
+ return latex.trim() !== "" && preview?.ok === true;
1965
+ }
1966
+ function motivoBloqueio(latex, preview) {
1967
+ if (latex.includes(PLACEHOLDER) || GRUPO_VAZIO.test(latex) || CELULA_VAZIA.test(latex)) {
1968
+ return "Preencha os campos em branco da f\xF3rmula.";
1969
+ }
1970
+ if (preview && !preview.ok) return preview.error ?? null;
1971
+ return null;
1972
+ }
1973
+
1974
+ // src/FormulaDialog.tsx
1806
1975
  import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1976
+ var CIRCUNFLEXO_DE_TECLA_MORTA = /* @__PURE__ */ new Set(["\u02C6", "\u0302"]);
1977
+ function FormulaDialog({
1978
+ fontsDirectory
1979
+ }) {
1980
+ const { formulaRequest, resolveFormulaRequest } = useEditorContext();
1981
+ const dialogRef = useRef4(null);
1982
+ const hostRef = useRef4(null);
1983
+ const fieldRef = useRef4(null);
1984
+ const [latex, setLatex] = useState5("");
1985
+ const [display, setDisplay] = useState5(false);
1986
+ const [abaAtiva, setAbaAtiva] = useState5(0);
1987
+ useEffect5(() => {
1988
+ const dialog = dialogRef.current;
1989
+ if (!dialog) return;
1990
+ if (formulaRequest) {
1991
+ setLatex(formulaRequest.initialLatex);
1992
+ setDisplay(formulaRequest.initialDisplay);
1993
+ setAbaAtiva(0);
1994
+ if (!dialog.open) dialog.showModal();
1995
+ } else if (dialog.open) {
1996
+ dialog.close();
1997
+ }
1998
+ }, [formulaRequest]);
1999
+ const rendererRef = useRef4(null);
2000
+ const mathfieldCtorRef = useRef4(null);
2001
+ const markupRef = useRef4(null);
2002
+ const [preview, setPreview] = useState5(null);
2003
+ const [carregando, setCarregando] = useState5(false);
2004
+ const [erroCarregando, setErroCarregando] = useState5(null);
2005
+ useEffect5(() => {
2006
+ if (!formulaRequest || rendererRef.current) return;
2007
+ setCarregando(true);
2008
+ setErroCarregando(null);
2009
+ void Promise.all([import("@sofereditor/math"), import("mathlive")]).then(([math, mathlive]) => {
2010
+ rendererRef.current = math.renderLatexToSvg;
2011
+ mathfieldCtorRef.current = mathlive.MathfieldElement;
2012
+ markupRef.current = mathlive.convertLatexToMarkup;
2013
+ mathlive.MathfieldElement.soundsDirectory = null;
2014
+ if (fontsDirectory) {
2015
+ mathlive.MathfieldElement.fontsDirectory = fontsDirectory;
2016
+ }
2017
+ setCarregando(false);
2018
+ }).catch(() => {
2019
+ setCarregando(false);
2020
+ setErroCarregando(
2021
+ "N\xE3o foi poss\xEDvel carregar o editor de f\xF3rmulas. Recarregue a p\xE1gina e tente de novo."
2022
+ );
2023
+ });
2024
+ }, [formulaRequest]);
2025
+ useEffect5(() => {
2026
+ const render = rendererRef.current;
2027
+ if (!render || !latex.trim()) {
2028
+ setPreview(null);
2029
+ return;
2030
+ }
2031
+ setPreview(render(latex, display));
2032
+ }, [latex, display, carregando]);
2033
+ const onCircunflexoMorto = useCallback2((e) => {
2034
+ const ev = e;
2035
+ if (!ev.data || !CIRCUNFLEXO_DE_TECLA_MORTA.has(ev.data)) return;
2036
+ ev.preventDefault();
2037
+ ev.stopPropagation();
2038
+ fieldRef.current?.insert("^{#?}", { focus: true });
2039
+ }, []);
2040
+ useEffect5(() => {
2041
+ const Ctor = mathfieldCtorRef.current;
2042
+ const host = hostRef.current;
2043
+ if (!Ctor || !host || !formulaRequest) return;
2044
+ const mf = new Ctor();
2045
+ mf.className = "ed-formula-field";
2046
+ const onInput = () => setLatex(mf.getValue("latex"));
2047
+ mf.addEventListener("input", onInput);
2048
+ mf.addEventListener("beforeinput", onCircunflexoMorto, true);
2049
+ host.appendChild(mf);
2050
+ mf.mathVirtualKeyboardPolicy = "manual";
2051
+ mf.inlineShortcuts = {
2052
+ ...mf.inlineShortcuts,
2053
+ sen: "\\operatorname{sen}",
2054
+ tg: "\\operatorname{tg}",
2055
+ cotg: "\\operatorname{cotg}",
2056
+ // Vírgula decimal. Em modo matemático a vírgula crua é átomo de
2057
+ // pontuação e ganha espaço DEPOIS de si: digitar "3,14" sai impresso
2058
+ // como "3, 14" (medido: 4.4ex contra 4.023ex do agrupado). A paleta
2059
+ // tem um botão `{,}`, mas ninguém clica num botão para uma tecla que
2060
+ // está no teclado — e decimal aparece em toda prova de matemática,
2061
+ // física e química.
2062
+ //
2063
+ // O `after: "digit"` é o que separa os dois usos da vírgula, e foi
2064
+ // verificado no navegador: "3,14" vira `3{,}14` e "f(x,y)" continua
2065
+ // `f\left(x,y\right)`, com a vírgula de lista intacta — que é o
2066
+ // comportamento certo, ali ela É pontuação.
2067
+ ",": { after: "digit", value: "{,}" }
2068
+ };
2069
+ mf.setValue(formulaRequest.initialLatex);
2070
+ setLatex(mf.getValue("latex"));
2071
+ fieldRef.current = mf;
2072
+ queueMicrotask(() => mf.focus());
2073
+ return () => {
2074
+ mf.removeEventListener("input", onInput);
2075
+ mf.removeEventListener("beforeinput", onCircunflexoMorto, true);
2076
+ mf.remove();
2077
+ fieldRef.current = null;
2078
+ };
2079
+ }, [formulaRequest, carregando]);
2080
+ if (!formulaRequest) return null;
2081
+ const markup = markupRef.current;
2082
+ const motivo = motivoBloqueio(latex, preview);
2083
+ const podeSubmeter = podeInserir(latex, preview);
2084
+ const onSubmit = (e) => {
2085
+ e.preventDefault();
2086
+ if (!podeSubmeter) return;
2087
+ resolveFormulaRequest({ latex, display });
2088
+ };
2089
+ const onCancel = () => resolveFormulaRequest(null);
2090
+ const onPaleta = (snippet) => {
2091
+ const mf = fieldRef.current;
2092
+ if (!mf) return;
2093
+ mf.insert(paraMathlive(snippet), { focus: true });
2094
+ setLatex(mf.getValue("latex"));
2095
+ };
2096
+ return /* @__PURE__ */ jsx6(
2097
+ "dialog",
2098
+ {
2099
+ ref: dialogRef,
2100
+ className: "ed-formula-dialog ed-link-dialog",
2101
+ style: DIALOG_CENTER_STYLE,
2102
+ onClose: onCancel,
2103
+ onCancel: (e) => {
2104
+ e.preventDefault();
2105
+ onCancel();
2106
+ },
2107
+ children: /* @__PURE__ */ jsxs6("form", { onSubmit, className: "ed-formula-form", children: [
2108
+ /* @__PURE__ */ jsx6("div", { className: "ed-formula-abas", role: "tablist", children: PALETA.map((cat, i) => /* @__PURE__ */ jsx6(
2109
+ "button",
2110
+ {
2111
+ type: "button",
2112
+ role: "tab",
2113
+ "aria-selected": i === abaAtiva,
2114
+ className: "ed-formula-aba",
2115
+ onClick: () => setAbaAtiva(i),
2116
+ children: cat.nome
2117
+ },
2118
+ cat.nome
2119
+ )) }),
2120
+ /* @__PURE__ */ jsx6(
2121
+ "div",
2122
+ {
2123
+ className: "ed-formula-paleta",
2124
+ role: "tabpanel",
2125
+ style: { gridTemplateColumns: `repeat(${PALETA[abaAtiva].colunas}, 1fr)` },
2126
+ children: PALETA[abaAtiva].itens.map((p) => /* @__PURE__ */ jsx6(
2127
+ "button",
2128
+ {
2129
+ type: "button",
2130
+ className: "ed-formula-paleta-btn",
2131
+ title: p.titulo ?? p.label,
2132
+ "aria-label": p.titulo ?? p.label,
2133
+ onClick: () => onPaleta(p.snippet),
2134
+ ...conteudoDoBotao(markup, p.snippet, p.label)
2135
+ },
2136
+ p.label
2137
+ ))
2138
+ }
2139
+ ),
2140
+ /* @__PURE__ */ jsx6("div", { ref: hostRef, className: "ed-formula-host" }),
2141
+ /* @__PURE__ */ jsxs6("label", { className: "ed-formula-display", children: [
2142
+ /* @__PURE__ */ jsx6(
2143
+ "input",
2144
+ {
2145
+ type: "checkbox",
2146
+ checked: display,
2147
+ onChange: (e) => setDisplay(e.target.checked)
2148
+ }
2149
+ ),
2150
+ "F\xF3rmula em bloco (centralizada, limites acima e abaixo)"
2151
+ ] }),
2152
+ /* @__PURE__ */ jsx6("div", { className: "ed-formula-preview", "aria-live": "polite", children: carregando ? /* @__PURE__ */ jsx6("span", { className: "ed-formula-vazio", children: "Carregando o editor\u2026" }) : erroCarregando ? /* @__PURE__ */ jsx6("span", { className: "ed-formula-erro", role: "alert", children: erroCarregando }) : motivo ? /* @__PURE__ */ jsx6("span", { className: "ed-formula-erro", role: "alert", children: motivo }) : null }),
2153
+ /* @__PURE__ */ jsxs6("div", { className: "ed-formula-acoes", children: [
2154
+ /* @__PURE__ */ jsx6("button", { type: "button", onClick: onCancel, children: "Cancelar" }),
2155
+ /* @__PURE__ */ jsx6("button", { type: "submit", disabled: !podeSubmeter, children: "Inserir" })
2156
+ ] })
2157
+ ] })
2158
+ }
2159
+ );
2160
+ }
2161
+
2162
+ // src/EditorContext.tsx
2163
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1807
2164
  var EditorContext = createContext(null);
1808
- function EditorProvider({ editor, children }) {
1809
- return /* @__PURE__ */ jsxs6(EditorContext.Provider, { value: editor, children: [
2165
+ function EditorProvider({
2166
+ editor,
2167
+ children,
2168
+ mathliveFontsDirectory
2169
+ }) {
2170
+ return /* @__PURE__ */ jsxs7(EditorContext.Provider, { value: editor, children: [
1810
2171
  children,
1811
- /* @__PURE__ */ jsx6(LinkDialog, {}),
1812
- /* @__PURE__ */ jsx6(PageConfigDialog, {}),
1813
- /* @__PURE__ */ jsx6(ImageCaptionDialog, {})
2172
+ /* @__PURE__ */ jsx7(LinkDialog, {}),
2173
+ /* @__PURE__ */ jsx7(PageConfigDialog, {}),
2174
+ /* @__PURE__ */ jsx7(ImageCaptionDialog, {}),
2175
+ /* @__PURE__ */ jsx7(FormulaDialog, { fontsDirectory: mathliveFontsDirectory })
1814
2176
  ] });
1815
2177
  }
1816
2178
  function useEditorContext() {
@@ -1823,13 +2185,13 @@ function useEditorContext() {
1823
2185
 
1824
2186
  // src/ImageResizeOverlay.tsx
1825
2187
  import {
1826
- useCallback as useCallback2,
1827
- useEffect as useEffect5,
2188
+ useCallback as useCallback3,
2189
+ useEffect as useEffect6,
1828
2190
  useLayoutEffect as useLayoutEffect2,
1829
- useRef as useRef4,
1830
- useState as useState5
2191
+ useRef as useRef5,
2192
+ useState as useState6
1831
2193
  } from "react";
1832
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
2194
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1833
2195
  function ImageResizeOverlay({
1834
2196
  rootRef,
1835
2197
  blockIndex,
@@ -1840,10 +2202,10 @@ function ImageResizeOverlay({
1840
2202
  onCommitMove,
1841
2203
  onReanchor
1842
2204
  }) {
1843
- const [rect, setRect] = useState5(null);
1844
- const [isMoving, setIsMoving] = useState5(false);
1845
- const imgRef = useRef4(null);
1846
- const locateImage = useCallback2(() => {
2205
+ const [rect, setRect] = useState6(null);
2206
+ const [isMoving, setIsMoving] = useState6(false);
2207
+ const imgRef = useRef5(null);
2208
+ const locateImage = useCallback3(() => {
1847
2209
  const root = rootRef.current;
1848
2210
  if (!root) return null;
1849
2211
  let container = null;
@@ -1861,7 +2223,7 @@ function ImageResizeOverlay({
1861
2223
  `img[data-embed="image"][data-embed-offset="${localOffset}"]`
1862
2224
  );
1863
2225
  }, [rootRef, blockIndex, offset, cellIndex]);
1864
- const measure = useCallback2(() => {
2226
+ const measure = useCallback3(() => {
1865
2227
  const img = locateImage();
1866
2228
  if (!img) {
1867
2229
  setRect((prev) => prev === null ? prev : null);
@@ -1912,7 +2274,7 @@ function ImageResizeOverlay({
1912
2274
  embed.offsetX,
1913
2275
  embed.offsetY
1914
2276
  ]);
1915
- useEffect5(() => {
2277
+ useEffect6(() => {
1916
2278
  const root = rootRef.current;
1917
2279
  if (!root) return;
1918
2280
  const onScroll = () => measure();
@@ -1923,7 +2285,7 @@ function ImageResizeOverlay({
1923
2285
  root.removeEventListener("scroll", onScroll);
1924
2286
  };
1925
2287
  }, [measure, rootRef]);
1926
- useEffect5(() => {
2288
+ useEffect6(() => {
1927
2289
  if (typeof ResizeObserver === "undefined") return;
1928
2290
  const img = locateImage();
1929
2291
  const root = rootRef.current;
@@ -1936,7 +2298,7 @@ function ImageResizeOverlay({
1936
2298
  if (!rect) return null;
1937
2299
  const layout = embed.layout ?? "inline";
1938
2300
  const movable = layout !== "inline" && onCommitMove !== void 0;
1939
- return /* @__PURE__ */ jsxs7(
2301
+ return /* @__PURE__ */ jsxs8(
1940
2302
  "div",
1941
2303
  {
1942
2304
  className: "ed-image-overlay",
@@ -1947,7 +2309,7 @@ function ImageResizeOverlay({
1947
2309
  // follows the cursor, so the image stays visible while it crosses the
1948
2310
  // page boundary (the real, clipped figure is hidden during the drag).
1949
2311
  // Inline styles only — the package does not ship CSS.
1950
- /* @__PURE__ */ jsx7(
2312
+ /* @__PURE__ */ jsx8(
1951
2313
  "img",
1952
2314
  {
1953
2315
  src: embed.src,
@@ -1965,7 +2327,7 @@ function ImageResizeOverlay({
1965
2327
  }
1966
2328
  }
1967
2329
  ),
1968
- movable && /* @__PURE__ */ jsx7(
2330
+ movable && /* @__PURE__ */ jsx8(
1969
2331
  MoveHandle,
1970
2332
  {
1971
2333
  layout,
@@ -1983,7 +2345,7 @@ function ImageResizeOverlay({
1983
2345
  onMoveEnd: () => setIsMoving(false)
1984
2346
  }
1985
2347
  ),
1986
- /* @__PURE__ */ jsx7(
2348
+ /* @__PURE__ */ jsx8(
1987
2349
  Handle,
1988
2350
  {
1989
2351
  corner: "nw",
@@ -1994,7 +2356,7 @@ function ImageResizeOverlay({
1994
2356
  onLiveChange: measure
1995
2357
  }
1996
2358
  ),
1997
- /* @__PURE__ */ jsx7(
2359
+ /* @__PURE__ */ jsx8(
1998
2360
  Handle,
1999
2361
  {
2000
2362
  corner: "ne",
@@ -2005,7 +2367,7 @@ function ImageResizeOverlay({
2005
2367
  onLiveChange: measure
2006
2368
  }
2007
2369
  ),
2008
- /* @__PURE__ */ jsx7(
2370
+ /* @__PURE__ */ jsx8(
2009
2371
  Handle,
2010
2372
  {
2011
2373
  corner: "sw",
@@ -2016,7 +2378,7 @@ function ImageResizeOverlay({
2016
2378
  onLiveChange: measure
2017
2379
  }
2018
2380
  ),
2019
- /* @__PURE__ */ jsx7(
2381
+ /* @__PURE__ */ jsx8(
2020
2382
  Handle,
2021
2383
  {
2022
2384
  corner: "se",
@@ -2046,7 +2408,7 @@ function MoveHandle({
2046
2408
  onMoveStart,
2047
2409
  onMoveEnd
2048
2410
  }) {
2049
- const dragRef = useRef4(null);
2411
+ const dragRef = useRef5(null);
2050
2412
  const onPointerDown = (e) => {
2051
2413
  if (e.button !== 0) return;
2052
2414
  if (!imgRef.current) return;
@@ -2196,7 +2558,7 @@ function MoveHandle({
2196
2558
  newOffsetY
2197
2559
  );
2198
2560
  };
2199
- return /* @__PURE__ */ jsx7(
2561
+ return /* @__PURE__ */ jsx8(
2200
2562
  "div",
2201
2563
  {
2202
2564
  className: "ed-image-move",
@@ -2216,7 +2578,7 @@ function Handle({
2216
2578
  onCommit,
2217
2579
  onLiveChange
2218
2580
  }) {
2219
- const dragRef = useRef4(null);
2581
+ const dragRef = useRef5(null);
2220
2582
  const onPointerDown = (e) => {
2221
2583
  if (e.button !== 0) return;
2222
2584
  if (!imgRef.current) return;
@@ -2259,7 +2621,7 @@ function Handle({
2259
2621
  }
2260
2622
  onCommit(Math.round(d.liveW), Math.round(d.liveH));
2261
2623
  };
2262
- return /* @__PURE__ */ jsx7(
2624
+ return /* @__PURE__ */ jsx8(
2263
2625
  "div",
2264
2626
  {
2265
2627
  className: `ed-image-handle ${corner}`,
@@ -2273,15 +2635,15 @@ function Handle({
2273
2635
 
2274
2636
  // src/RemoteCursorsOverlay.tsx
2275
2637
  import {
2276
- useCallback as useCallback3,
2277
- useEffect as useEffect6,
2278
- useRef as useRef5,
2279
- useState as useState6
2638
+ useCallback as useCallback4,
2639
+ useEffect as useEffect7,
2640
+ useRef as useRef6,
2641
+ useState as useState7
2280
2642
  } from "react";
2281
2643
  import {
2282
2644
  decodeSelection
2283
2645
  } from "@sofereditor/core";
2284
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
2646
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2285
2647
  var DEFAULT_COLOR = "#3b82f6";
2286
2648
  function RemoteCursorsOverlay({
2287
2649
  rootRef,
@@ -2289,9 +2651,9 @@ function RemoteCursorsOverlay({
2289
2651
  awareness,
2290
2652
  revision
2291
2653
  }) {
2292
- const [views, setViews] = useState6([]);
2293
- const rafRef = useRef5(null);
2294
- const measure = useCallback3(() => {
2654
+ const [views, setViews] = useState7([]);
2655
+ const rafRef = useRef6(null);
2656
+ const measure = useCallback4(() => {
2295
2657
  const root = rootRef.current;
2296
2658
  if (!root) {
2297
2659
  setViews((prev) => prev.length === 0 ? prev : []);
@@ -2356,7 +2718,7 @@ function RemoteCursorsOverlay({
2356
2718
  });
2357
2719
  setViews(out);
2358
2720
  }, [rootRef, doc, awareness]);
2359
- const scheduleMeasure = useCallback3(() => {
2721
+ const scheduleMeasure = useCallback4(() => {
2360
2722
  if (rafRef.current != null) return;
2361
2723
  const raf = typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb) => setTimeout(() => cb(0), 16);
2362
2724
  rafRef.current = raf(() => {
@@ -2364,16 +2726,16 @@ function RemoteCursorsOverlay({
2364
2726
  measure();
2365
2727
  });
2366
2728
  }, [measure]);
2367
- useEffect6(() => {
2729
+ useEffect7(() => {
2368
2730
  const onChange = () => scheduleMeasure();
2369
2731
  awareness.on("change", onChange);
2370
2732
  scheduleMeasure();
2371
2733
  return () => awareness.off("change", onChange);
2372
2734
  }, [awareness, scheduleMeasure]);
2373
- useEffect6(() => {
2735
+ useEffect7(() => {
2374
2736
  scheduleMeasure();
2375
2737
  }, [revision, scheduleMeasure]);
2376
- useEffect6(() => {
2738
+ useEffect7(() => {
2377
2739
  const root = rootRef.current;
2378
2740
  if (!root) return;
2379
2741
  const onScroll = () => scheduleMeasure();
@@ -2395,8 +2757,8 @@ function RemoteCursorsOverlay({
2395
2757
  pointerEvents: "none",
2396
2758
  zIndex: 6
2397
2759
  };
2398
- return /* @__PURE__ */ jsx8("div", { className: "ed-remote-cursors", "aria-hidden": true, style: layer, children: views.map((v) => /* @__PURE__ */ jsxs8("div", { children: [
2399
- v.selection.map((r, i) => /* @__PURE__ */ jsx8(
2760
+ return /* @__PURE__ */ jsx9("div", { className: "ed-remote-cursors", "aria-hidden": true, style: layer, children: views.map((v) => /* @__PURE__ */ jsxs9("div", { children: [
2761
+ v.selection.map((r, i) => /* @__PURE__ */ jsx9(
2400
2762
  "div",
2401
2763
  {
2402
2764
  style: {
@@ -2412,7 +2774,7 @@ function RemoteCursorsOverlay({
2412
2774
  },
2413
2775
  i
2414
2776
  )),
2415
- v.caret && /* @__PURE__ */ jsx8(
2777
+ v.caret && /* @__PURE__ */ jsx9(
2416
2778
  "div",
2417
2779
  {
2418
2780
  style: {
@@ -2423,7 +2785,7 @@ function RemoteCursorsOverlay({
2423
2785
  width: 2,
2424
2786
  background: v.color
2425
2787
  },
2426
- children: /* @__PURE__ */ jsx8(
2788
+ children: /* @__PURE__ */ jsx9(
2427
2789
  "span",
2428
2790
  {
2429
2791
  style: {
@@ -2449,10 +2811,11 @@ function RemoteCursorsOverlay({
2449
2811
  }
2450
2812
 
2451
2813
  // src/NodeView.tsx
2452
- import { useMemo as useMemo2, useRef as useRef7 } from "react";
2814
+ import { useMemo as useMemo2, useRef as useRef8 } from "react";
2453
2815
  import {
2454
2816
  answerLineStyle,
2455
2817
  cellBorderStyle,
2818
+ normalizarLarguras as normalizarLarguras2,
2456
2819
  tableRectSelection
2457
2820
  } from "@sofereditor/core";
2458
2821
 
@@ -2463,10 +2826,10 @@ import {
2463
2826
  isImageEmbed as isImageEmbed3,
2464
2827
  splitUnderscoreRuns
2465
2828
  } from "@sofereditor/core";
2466
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2829
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
2467
2830
  function renderInline(delta, keyPrefix) {
2468
2831
  if (delta.length === 0 || delta.length === 1 && typeof delta[0].insert === "string" && delta[0].insert === "") {
2469
- return /* @__PURE__ */ jsx9("br", { "data-empty": "true" });
2832
+ return /* @__PURE__ */ jsx10("br", { "data-empty": "true" });
2470
2833
  }
2471
2834
  let offset = 0;
2472
2835
  const wrapAnchors = [];
@@ -2476,7 +2839,7 @@ function renderInline(delta, keyPrefix) {
2476
2839
  const text = op.insert;
2477
2840
  if (text.length === 0) continue;
2478
2841
  const key = `${keyPrefix}-${offset}`;
2479
- body.push(/* @__PURE__ */ jsx9(Fragment3, { children: wrap(text, op.attributes) }, key));
2842
+ body.push(/* @__PURE__ */ jsx10(Fragment3, { children: wrap(text, op.attributes) }, key));
2480
2843
  offset += text.length;
2481
2844
  } else if (isImageEmbed3(op.insert)) {
2482
2845
  const key = `${keyPrefix}-${offset}`;
@@ -2484,10 +2847,10 @@ function renderInline(delta, keyPrefix) {
2484
2847
  const commentMarkId = op.attributes?.comment?.markId;
2485
2848
  if (layout === "wrap-left" || layout === "wrap-right") {
2486
2849
  wrapAnchors.push(
2487
- /* @__PURE__ */ jsx9(ImageEmbedView, { embed: op.insert, offset, wrapAnchor: true }, `${key}-anchor`)
2850
+ /* @__PURE__ */ jsx10(ImageEmbedView, { embed: op.insert, offset, wrapAnchor: true }, `${key}-anchor`)
2488
2851
  );
2489
2852
  body.push(
2490
- /* @__PURE__ */ jsx9(
2853
+ /* @__PURE__ */ jsx10(
2491
2854
  "span",
2492
2855
  {
2493
2856
  "data-embed-phantom": "true",
@@ -2499,10 +2862,10 @@ function renderInline(delta, keyPrefix) {
2499
2862
  )
2500
2863
  );
2501
2864
  } else {
2502
- const imgNode = /* @__PURE__ */ jsx9(ImageEmbedView, { embed: op.insert, offset }, key);
2865
+ const imgNode = /* @__PURE__ */ jsx10(ImageEmbedView, { embed: op.insert, offset }, key);
2503
2866
  if (commentMarkId) {
2504
2867
  body.push(
2505
- /* @__PURE__ */ jsx9("span", { "data-comment-id": commentMarkId, className: "ed-comment", children: imgNode }, `${key}-cmt`)
2868
+ /* @__PURE__ */ jsx10("span", { "data-comment-id": commentMarkId, className: "ed-comment", children: imgNode }, `${key}-cmt`)
2506
2869
  );
2507
2870
  } else {
2508
2871
  body.push(imgNode);
@@ -2513,7 +2876,7 @@ function renderInline(delta, keyPrefix) {
2513
2876
  offset += 1;
2514
2877
  }
2515
2878
  }
2516
- if (wrapAnchors.length === 0 && body.length === 0) return /* @__PURE__ */ jsx9("br", { "data-empty": "true" });
2879
+ if (wrapAnchors.length === 0 && body.length === 0) return /* @__PURE__ */ jsx10("br", { "data-empty": "true" });
2517
2880
  return [...wrapAnchors, ...body];
2518
2881
  }
2519
2882
  var PHANTOM_STYLE = {
@@ -2588,7 +2951,9 @@ function ImageEmbedViewImpl({
2588
2951
  marginRight: align === "right" ? 0 : "auto"
2589
2952
  } : {
2590
2953
  display: "inline-block",
2591
- verticalAlign: "text-bottom",
2954
+ // Fórmula inline traz o deslocamento de base que o MathJax mediu;
2955
+ // sem ele a fórmula flutua no topo da linha em vez de sentar nela.
2956
+ verticalAlign: embed.formula?.vAlign ?? "text-bottom",
2592
2957
  width: embed.width
2593
2958
  };
2594
2959
  break;
@@ -2598,7 +2963,7 @@ function ImageEmbedViewImpl({
2598
2963
  height: embed.height,
2599
2964
  display: "block"
2600
2965
  };
2601
- const img = /* @__PURE__ */ jsx9(
2966
+ const img = /* @__PURE__ */ jsx10(
2602
2967
  "img",
2603
2968
  {
2604
2969
  src: embed.src,
@@ -2618,7 +2983,7 @@ function ImageEmbedViewImpl({
2618
2983
  }
2619
2984
  );
2620
2985
  const captionAlign = embed.captionAlign ?? "center";
2621
- return /* @__PURE__ */ jsxs9(
2986
+ return /* @__PURE__ */ jsxs10(
2622
2987
  "figure",
2623
2988
  {
2624
2989
  className: "ed-figure",
@@ -2628,7 +2993,7 @@ function ImageEmbedViewImpl({
2628
2993
  style: outerStyle,
2629
2994
  children: [
2630
2995
  img,
2631
- hasCaption && /* @__PURE__ */ jsx9(
2996
+ hasCaption && /* @__PURE__ */ jsx10(
2632
2997
  "figcaption",
2633
2998
  {
2634
2999
  className: "ed-figcaption",
@@ -2645,26 +3010,26 @@ function decorateBlanks(text) {
2645
3010
  const segs = splitUnderscoreRuns(text);
2646
3011
  if (segs.length === 1 && !segs[0].blank) return text;
2647
3012
  return segs.map(
2648
- (s, i) => s.blank ? /* @__PURE__ */ jsx9("span", { "data-blank": "true", style: BLANK_STYLE, children: s.text }, i) : /* @__PURE__ */ jsx9(Fragment3, { children: s.text }, i)
3013
+ (s, i) => s.blank ? /* @__PURE__ */ jsx10("span", { "data-blank": "true", style: BLANK_STYLE, children: s.text }, i) : /* @__PURE__ */ jsx10(Fragment3, { children: s.text }, i)
2649
3014
  );
2650
3015
  }
2651
3016
  function wrap(text, attrs) {
2652
3017
  let node = decorateBlanks(text);
2653
3018
  if (!attrs) return node;
2654
- if (attrs.bold) node = /* @__PURE__ */ jsx9("strong", { children: node });
2655
- if (attrs.italic) node = /* @__PURE__ */ jsx9("em", { children: node });
2656
- if (attrs.underline) node = /* @__PURE__ */ jsx9("u", { children: node });
2657
- if (attrs.strike) node = /* @__PURE__ */ jsx9("s", { children: node });
3019
+ if (attrs.bold) node = /* @__PURE__ */ jsx10("strong", { children: node });
3020
+ if (attrs.italic) node = /* @__PURE__ */ jsx10("em", { children: node });
3021
+ if (attrs.underline) node = /* @__PURE__ */ jsx10("u", { children: node });
3022
+ if (attrs.strike) node = /* @__PURE__ */ jsx10("s", { children: node });
2658
3023
  const styleParts = {};
2659
3024
  if (attrs.color) styleParts.color = attrs.color;
2660
3025
  if (attrs.highlight) styleParts.backgroundColor = attrs.highlight;
2661
3026
  if (attrs.fontFamily) styleParts.fontFamily = attrs.fontFamily;
2662
3027
  if (attrs.fontSize) styleParts.fontSize = attrs.fontSize;
2663
3028
  if (Object.keys(styleParts).length > 0) {
2664
- node = /* @__PURE__ */ jsx9("span", { style: styleParts, children: node });
3029
+ node = /* @__PURE__ */ jsx10("span", { style: styleParts, children: node });
2665
3030
  }
2666
3031
  if (attrs.link?.href) {
2667
- node = /* @__PURE__ */ jsx9(
3032
+ node = /* @__PURE__ */ jsx10(
2668
3033
  "a",
2669
3034
  {
2670
3035
  href: attrs.link.href,
@@ -2683,7 +3048,7 @@ function wrap(text, attrs) {
2683
3048
  );
2684
3049
  }
2685
3050
  if (attrs.comment?.markId) {
2686
- node = /* @__PURE__ */ jsx9("span", { "data-comment-id": attrs.comment.markId, className: "ed-comment", children: node });
3051
+ node = /* @__PURE__ */ jsx10("span", { "data-comment-id": attrs.comment.markId, className: "ed-comment", children: node });
2687
3052
  }
2688
3053
  return node;
2689
3054
  }
@@ -2728,21 +3093,30 @@ function sliceDelta(delta, start, end) {
2728
3093
 
2729
3094
  // src/TableResizeOverlay.tsx
2730
3095
  import {
2731
- useCallback as useCallback4,
2732
- useEffect as useEffect7,
3096
+ useCallback as useCallback5,
3097
+ useEffect as useEffect8,
2733
3098
  useLayoutEffect as useLayoutEffect3,
2734
- useRef as useRef6,
2735
- useState as useState7
3099
+ useRef as useRef7,
3100
+ useState as useState8
2736
3101
  } from "react";
2737
- import { Fragment as Fragment4, jsx as jsx10 } from "react/jsx-runtime";
2738
- function TableResizeOverlay({ tableRef, blockIndex, cols }) {
3102
+ import { MIN_LINHA_PX, normalizarLarguras } from "@sofereditor/core";
3103
+ import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
3104
+ function deltaPctDoArrasto(dxPx, larguraTabelaPx) {
3105
+ if (!(larguraTabelaPx > 0)) return 0;
3106
+ return dxPx / larguraTabelaPx * 100;
3107
+ }
3108
+ function distribuirAltura(base, deltaPx) {
3109
+ if (base.length === 0) return base;
3110
+ const fatia = deltaPx / base.length;
3111
+ return base.map((h) => Math.max(MIN_LINHA_PX, Math.round(h + fatia)));
3112
+ }
3113
+ function TableResizeOverlay({ tableRef, blockIndex, cols, rows }) {
2739
3114
  const editor = useEditorContext();
2740
- const [positions, setPositions] = useState7(null);
2741
- const [layout, setLayout] = useState7(null);
2742
- const draggingRef = useRef6(null);
2743
- const measure = useCallback4(() => {
3115
+ const [layout, setLayout] = useState8(null);
3116
+ const arrastoRef = useRef7(null);
3117
+ const measureNow = useCallback5(() => {
2744
3118
  const table = tableRef.current;
2745
- if (!table) return;
3119
+ if (!table) return null;
2746
3120
  const tableRect = table.getBoundingClientRect();
2747
3121
  const cgCols = table.querySelectorAll("colgroup > col");
2748
3122
  let rights = [];
@@ -2765,55 +3139,160 @@ function TableResizeOverlay({ tableRef, blockIndex, cols }) {
2765
3139
  });
2766
3140
  }
2767
3141
  if (rights.length !== cols) {
2768
- setLayout(null);
2769
- return;
3142
+ return null;
2770
3143
  }
2771
- setLayout({ rights, height: tableRect.height });
2772
- }, [cols, tableRef]);
3144
+ const trs = table.querySelectorAll("tbody > tr");
3145
+ const bottoms = [];
3146
+ let accY = 0;
3147
+ trs.forEach((tr) => {
3148
+ accY += tr.getBoundingClientRect().height;
3149
+ bottoms.push(accY);
3150
+ });
3151
+ return {
3152
+ rights,
3153
+ bottoms: trs.length === rows ? bottoms : [],
3154
+ width: tableRect.width,
3155
+ height: tableRect.height
3156
+ };
3157
+ }, [cols, rows, tableRef]);
3158
+ const measure = useCallback5(() => {
3159
+ setLayout(measureNow());
3160
+ }, [measureNow]);
2773
3161
  useLayoutEffect3(() => {
2774
3162
  measure();
2775
3163
  }, [measure]);
2776
- useEffect7(() => {
3164
+ useEffect8(() => {
2777
3165
  const table = tableRef.current;
2778
3166
  if (!table) return;
2779
3167
  const ro = new ResizeObserver(() => measure());
2780
3168
  ro.observe(table);
2781
3169
  return () => ro.disconnect();
2782
3170
  }, [measure, tableRef]);
2783
- const onPointerDown = useCallback4(
2784
- (col) => (e) => {
3171
+ const onPointerUp = useCallback5(
3172
+ (e) => {
3173
+ arrastoRef.current = null;
3174
+ measure();
3175
+ try {
3176
+ e.currentTarget.releasePointerCapture(e.pointerId);
3177
+ } catch {
3178
+ }
3179
+ },
3180
+ [measure]
3181
+ );
3182
+ const onPointerMove = useCallback5(
3183
+ (e) => {
3184
+ const d = arrastoRef.current;
3185
+ if (!d) return;
3186
+ switch (d.tipo) {
3187
+ case "coluna": {
3188
+ const dPct = deltaPctDoArrasto(e.clientX - d.startX, d.tableWidthPx);
3189
+ editor.setColumnBoundary(blockIndex, d.boundary, dPct, d.baseWidths);
3190
+ break;
3191
+ }
3192
+ case "larguraTotal": {
3193
+ const dPct = deltaPctDoArrasto(e.clientX - d.startX, d.utilPx);
3194
+ editor.setTableWidth(blockIndex, d.baseWidthPct + dPct);
3195
+ break;
3196
+ }
3197
+ case "linha": {
3198
+ editor.setRowHeight(blockIndex, d.row, d.baseHeightPx + (e.clientY - d.startY));
3199
+ break;
3200
+ }
3201
+ case "alturaTotal": {
3202
+ editor.setRowHeights(blockIndex, distribuirAltura(d.baseHeights, e.clientY - d.startY));
3203
+ break;
3204
+ }
3205
+ case "canto": {
3206
+ const dPct = deltaPctDoArrasto(e.clientX - d.startX, d.utilPx);
3207
+ editor.setTableWidth(blockIndex, d.baseWidthPct + dPct);
3208
+ editor.setRowHeights(blockIndex, distribuirAltura(d.baseHeights, e.clientY - d.startY));
3209
+ break;
3210
+ }
3211
+ }
3212
+ },
3213
+ [blockIndex, editor]
3214
+ );
3215
+ const containerWidthPxOf = useCallback5((table, tableWidthPx) => {
3216
+ return table.parentElement?.getBoundingClientRect().width || tableWidthPx;
3217
+ }, []);
3218
+ const onColumnPointerDown = useCallback5(
3219
+ (boundary) => (e) => {
2785
3220
  e.preventDefault();
2786
3221
  e.stopPropagation();
2787
3222
  const table = tableRef.current;
2788
3223
  if (!table) return;
2789
- const cgCols = table.querySelectorAll("colgroup > col");
2790
- const startWidth = cgCols[col]?.getBoundingClientRect().width ?? 100;
2791
- draggingRef.current = { col, startX: e.clientX, startWidth };
2792
- setPositions({ x: e.clientX, height: layout?.height ?? 0 });
3224
+ const tableWidthPx = table.getBoundingClientRect().width || 1;
3225
+ const attrs = editor.doc.getBlockAttrs(blockIndex);
3226
+ const baseWidths = normalizarLarguras(attrs.colWidths, cols);
3227
+ arrastoRef.current = { tipo: "coluna", boundary, startX: e.clientX, baseWidths, tableWidthPx };
2793
3228
  e.currentTarget.setPointerCapture(e.pointerId);
2794
3229
  },
2795
- [layout, tableRef]
3230
+ [tableRef, editor, blockIndex, cols]
2796
3231
  );
2797
- const onPointerMove = useCallback4(
3232
+ const onTableWidthPointerDown = useCallback5(
2798
3233
  (e) => {
2799
- const d = draggingRef.current;
2800
- if (!d) return;
2801
- const dx = e.clientX - d.startX;
2802
- const next = Math.max(40, d.startWidth + dx);
2803
- editor.setColumnWidth(blockIndex, d.col, next);
3234
+ e.preventDefault();
3235
+ e.stopPropagation();
3236
+ const table = tableRef.current;
3237
+ if (!table) return;
3238
+ const tableWidthPx = table.getBoundingClientRect().width || 1;
3239
+ const utilPx = containerWidthPxOf(table, tableWidthPx);
3240
+ const attrs = editor.doc.getBlockAttrs(blockIndex);
3241
+ const baseWidthPct = typeof attrs.tableWidth === "number" ? attrs.tableWidth : 100;
3242
+ arrastoRef.current = { tipo: "larguraTotal", startX: e.clientX, baseWidthPct, utilPx };
3243
+ e.currentTarget.setPointerCapture(e.pointerId);
2804
3244
  },
2805
- [blockIndex, editor]
3245
+ [tableRef, editor, blockIndex, containerWidthPxOf]
3246
+ );
3247
+ const heightsFromBottoms = (bottoms) => bottoms.map((b, i) => b - (i === 0 ? 0 : bottoms[i - 1]));
3248
+ const onRowPointerDown = useCallback5(
3249
+ (row) => (e) => {
3250
+ e.preventDefault();
3251
+ e.stopPropagation();
3252
+ const m = measureNow();
3253
+ if (!m || m.bottoms.length === 0) return;
3254
+ const baseHeightPx = m.bottoms[row] - (row === 0 ? 0 : m.bottoms[row - 1]);
3255
+ arrastoRef.current = { tipo: "linha", row, startY: e.clientY, baseHeightPx };
3256
+ e.currentTarget.setPointerCapture(e.pointerId);
3257
+ },
3258
+ [measureNow]
3259
+ );
3260
+ const onTableHeightPointerDown = useCallback5(
3261
+ (e) => {
3262
+ e.preventDefault();
3263
+ e.stopPropagation();
3264
+ const m = measureNow();
3265
+ if (!m || m.bottoms.length === 0) return;
3266
+ arrastoRef.current = { tipo: "alturaTotal", startY: e.clientY, baseHeights: heightsFromBottoms(m.bottoms) };
3267
+ e.currentTarget.setPointerCapture(e.pointerId);
3268
+ },
3269
+ [measureNow]
3270
+ );
3271
+ const onCornerPointerDown = useCallback5(
3272
+ (e) => {
3273
+ e.preventDefault();
3274
+ e.stopPropagation();
3275
+ const table = tableRef.current;
3276
+ const m = measureNow();
3277
+ if (!table || !m) return;
3278
+ const tableWidthPx = table.getBoundingClientRect().width || 1;
3279
+ const utilPx = containerWidthPxOf(table, tableWidthPx);
3280
+ const attrs = editor.doc.getBlockAttrs(blockIndex);
3281
+ const baseWidthPct = typeof attrs.tableWidth === "number" ? attrs.tableWidth : 100;
3282
+ arrastoRef.current = {
3283
+ tipo: "canto",
3284
+ startX: e.clientX,
3285
+ startY: e.clientY,
3286
+ baseWidthPct,
3287
+ utilPx,
3288
+ baseHeights: heightsFromBottoms(m.bottoms)
3289
+ };
3290
+ e.currentTarget.setPointerCapture(e.pointerId);
3291
+ },
3292
+ [tableRef, editor, blockIndex, measureNow, containerWidthPxOf]
2806
3293
  );
2807
- const onPointerUp = useCallback4((e) => {
2808
- draggingRef.current = null;
2809
- setPositions(null);
2810
- try {
2811
- e.currentTarget.releasePointerCapture(e.pointerId);
2812
- } catch {
2813
- }
2814
- }, []);
2815
3294
  if (!layout) return null;
2816
- const handleStyle = (x) => ({
3295
+ const colHandleStyle = (x) => ({
2817
3296
  position: "absolute",
2818
3297
  top: 0,
2819
3298
  left: `${x - 3}px`,
@@ -2822,28 +3301,104 @@ function TableResizeOverlay({ tableRef, blockIndex, cols }) {
2822
3301
  cursor: "col-resize",
2823
3302
  zIndex: 5
2824
3303
  });
2825
- void positions;
2826
- return /* @__PURE__ */ jsx10(Fragment4, { children: layout.rights.map((x, c) => /* @__PURE__ */ jsx10(
2827
- "div",
2828
- {
2829
- contentEditable: false,
2830
- className: "ed-col-resize-handle",
2831
- style: handleStyle(x),
2832
- onPointerDown: onPointerDown(c),
2833
- onPointerMove,
2834
- onPointerUp,
2835
- "aria-label": `Redimensionar coluna ${c + 1}`,
2836
- role: "separator"
2837
- },
2838
- c
2839
- )) });
3304
+ const rowHandleStyle = (y) => ({
3305
+ position: "absolute",
3306
+ left: 0,
3307
+ top: `${y - 3}px`,
3308
+ width: `${layout.width}px`,
3309
+ height: "6px",
3310
+ cursor: "row-resize",
3311
+ zIndex: 5
3312
+ });
3313
+ const cornerHandleStyle = {
3314
+ position: "absolute",
3315
+ left: `${layout.width - 5}px`,
3316
+ top: `${layout.height - 5}px`,
3317
+ width: "10px",
3318
+ height: "10px",
3319
+ cursor: "nwse-resize",
3320
+ zIndex: 6
3321
+ };
3322
+ return /* @__PURE__ */ jsxs11(Fragment4, { children: [
3323
+ layout.rights.map(
3324
+ (x, c) => c < cols - 1 ? /* @__PURE__ */ jsx11(
3325
+ "div",
3326
+ {
3327
+ contentEditable: false,
3328
+ className: "ed-col-resize-handle",
3329
+ style: colHandleStyle(x),
3330
+ onPointerDown: onColumnPointerDown(c),
3331
+ onPointerMove,
3332
+ onPointerUp,
3333
+ "aria-label": `Redimensionar coluna ${c + 1}`,
3334
+ role: "separator"
3335
+ },
3336
+ `col-${c}`
3337
+ ) : /* @__PURE__ */ jsx11(
3338
+ "div",
3339
+ {
3340
+ contentEditable: false,
3341
+ className: "ed-col-resize-handle",
3342
+ style: colHandleStyle(x),
3343
+ onPointerDown: onTableWidthPointerDown,
3344
+ onPointerMove,
3345
+ onPointerUp,
3346
+ "aria-label": "Largura da tabela",
3347
+ role: "separator"
3348
+ },
3349
+ "col-total"
3350
+ )
3351
+ ),
3352
+ layout.bottoms.map(
3353
+ (y, r) => r < rows - 1 ? /* @__PURE__ */ jsx11(
3354
+ "div",
3355
+ {
3356
+ contentEditable: false,
3357
+ className: "ed-row-resize-handle",
3358
+ style: rowHandleStyle(y),
3359
+ onPointerDown: onRowPointerDown(r),
3360
+ onPointerMove,
3361
+ onPointerUp,
3362
+ "aria-label": `Redimensionar linha ${r + 1}`,
3363
+ role: "separator"
3364
+ },
3365
+ `row-${r}`
3366
+ ) : /* @__PURE__ */ jsx11(
3367
+ "div",
3368
+ {
3369
+ contentEditable: false,
3370
+ className: "ed-row-resize-handle",
3371
+ style: rowHandleStyle(y),
3372
+ onPointerDown: onTableHeightPointerDown,
3373
+ onPointerMove,
3374
+ onPointerUp,
3375
+ "aria-label": "Altura da tabela",
3376
+ role: "separator"
3377
+ },
3378
+ "row-total"
3379
+ )
3380
+ ),
3381
+ /* @__PURE__ */ jsx11(
3382
+ "div",
3383
+ {
3384
+ contentEditable: false,
3385
+ className: "ed-table-corner-handle",
3386
+ style: cornerHandleStyle,
3387
+ onPointerDown: onCornerPointerDown,
3388
+ onPointerMove,
3389
+ onPointerUp,
3390
+ "aria-label": "Redimensionar tabela",
3391
+ role: "separator"
3392
+ }
3393
+ )
3394
+ ] });
2840
3395
  }
2841
3396
 
2842
3397
  // src/NodeView.tsx
2843
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
3398
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
2844
3399
  function NodeView({ block, index, children, fragment, tableFragment }) {
2845
3400
  if (block.type === "table") {
2846
- return /* @__PURE__ */ jsx11(TableView, { block, index, tableFragment });
3401
+ return /* @__PURE__ */ jsx12(TableView, { block, index, tableFragment });
2847
3402
  }
2848
3403
  const inline = fragment ? renderInline(sliceDelta(block.delta, fragment.start, fragment.end), index) : renderInline(block.delta, index);
2849
3404
  const common = commonBlockProps(block.attrs, index, block.type, fragment);
@@ -2851,7 +3406,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2851
3406
  case "heading": {
2852
3407
  const level = clampLevel2(block.attrs.level);
2853
3408
  const Tag = `h${level}`;
2854
- return /* @__PURE__ */ jsx11(
3409
+ return /* @__PURE__ */ jsx12(
2855
3410
  Tag,
2856
3411
  {
2857
3412
  ...common,
@@ -2861,7 +3416,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2861
3416
  );
2862
3417
  }
2863
3418
  case "blockquote":
2864
- return /* @__PURE__ */ jsx11(
3419
+ return /* @__PURE__ */ jsx12(
2865
3420
  "blockquote",
2866
3421
  {
2867
3422
  ...common,
@@ -2870,18 +3425,18 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2870
3425
  }
2871
3426
  );
2872
3427
  case "codeBlock":
2873
- return /* @__PURE__ */ jsx11(
3428
+ return /* @__PURE__ */ jsx12(
2874
3429
  "pre",
2875
3430
  {
2876
3431
  ...common,
2877
3432
  "data-language": block.attrs.language ?? void 0,
2878
3433
  className: `ed-block ed-codeblock${alignClass(block.attrs.align)}`,
2879
- children: /* @__PURE__ */ jsx11("code", { children: inline })
3434
+ children: /* @__PURE__ */ jsx12("code", { children: inline })
2880
3435
  }
2881
3436
  );
2882
3437
  case "listItem": {
2883
3438
  const level = clampListLevel(block.attrs.listLevel);
2884
- return /* @__PURE__ */ jsxs10(
3439
+ return /* @__PURE__ */ jsxs12(
2885
3440
  "li",
2886
3441
  {
2887
3442
  ...common,
@@ -2897,7 +3452,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2897
3452
  }
2898
3453
  case "paragraph":
2899
3454
  default:
2900
- return /* @__PURE__ */ jsx11(
3455
+ return /* @__PURE__ */ jsx12(
2901
3456
  "div",
2902
3457
  {
2903
3458
  ...common,
@@ -2948,8 +3503,10 @@ function TableView({ block, index, tableFragment }) {
2948
3503
  const rows = clampPositive(block.attrs.rows);
2949
3504
  const cols = clampPositive(block.attrs.cols);
2950
3505
  const cells = block.cells ?? [];
2951
- const widths = readColWidths(block.attrs.colWidths, cols);
2952
- const tableRef = useRef7(null);
3506
+ const widths = normalizarLarguras2(block.attrs.colWidths, cols);
3507
+ const tableWidth = block.attrs.tableWidth;
3508
+ const rowHeights = block.attrs.rowHeights;
3509
+ const tableRef = useRef8(null);
2953
3510
  const rowStart = tableFragment?.rowStart ?? 0;
2954
3511
  const rowEnd = tableFragment?.rowEnd ?? rows;
2955
3512
  const isFirstFragment = !tableFragment || tableFragment.index === 0;
@@ -2959,69 +3516,69 @@ function TableView({ block, index, tableFragment }) {
2959
3516
  if (editor.selection.focus.blockIndex !== index) return null;
2960
3517
  return tableRectSelection(editor.doc, editor.selection);
2961
3518
  }, [editor.doc, editor.selection, index]);
2962
- return /* @__PURE__ */ jsxs10("div", { className: "ed-table-wrap", children: [
2963
- /* @__PURE__ */ jsxs10(
3519
+ return /* @__PURE__ */ jsxs12("div", { className: "ed-table-wrap", children: [
3520
+ /* @__PURE__ */ jsxs12(
2964
3521
  "table",
2965
3522
  {
2966
3523
  ref: tableRef,
2967
3524
  "data-block-index": index,
2968
3525
  "data-block-type": "table",
2969
3526
  className: "ed-block ed-table",
3527
+ style: typeof tableWidth === "number" ? { width: `${tableWidth}%` } : void 0,
2970
3528
  children: [
2971
- widths && /* @__PURE__ */ jsx11("colgroup", { children: widths.map((w, c) => /* @__PURE__ */ jsx11("col", { style: w != null ? { width: `${w}px` } : void 0 }, c)) }),
2972
- /* @__PURE__ */ jsx11("tbody", { children: Array.from({ length: rowEnd - rowStart }, (_, i) => {
3529
+ /* @__PURE__ */ jsx12("colgroup", { children: widths.map((w, c) => /* @__PURE__ */ jsx12("col", { style: { width: `${w}%` } }, c)) }),
3530
+ /* @__PURE__ */ jsx12("tbody", { children: Array.from({ length: rowEnd - rowStart }, (_, i) => {
2973
3531
  const r = rowStart + i;
2974
- return /* @__PURE__ */ jsx11("tr", { "data-cell-row": r, children: Array.from({ length: cols }, (_2, c) => {
2975
- const flat = r * cols + c;
2976
- const cell = cells[flat];
2977
- if (cell?.attrs.covered === true) return null;
2978
- const rowspan = spanAttr(cell?.attrs.rowspan);
2979
- const colspan = spanAttr(cell?.attrs.colspan);
2980
- const delta = cell?.delta ?? [];
2981
- const inRect = rect !== null && r >= rect.top && r <= rect.bottom && c >= rect.left && c <= rect.right;
2982
- return /* @__PURE__ */ jsx11(
2983
- "td",
2984
- {
2985
- "data-cell-index": flat,
2986
- "data-cell-row": r,
2987
- "data-cell-col": c,
2988
- "data-cell-rowspan": rowspan,
2989
- "data-cell-colspan": colspan,
2990
- rowSpan: rowspan > 1 ? rowspan : void 0,
2991
- colSpan: colspan > 1 ? colspan : void 0,
2992
- style: cellStyle(
2993
- cell?.attrs,
2994
- // rowStart/rowEnd são os limites do FRAGMENTO: numa tabela
2995
- // quebrada entre páginas, cada página fecha a própria caixa.
2996
- cellBorderStyle(
2997
- block.attrs.borderPreset,
2998
- { row: r, col: c, rowspan, colspan, cols, rowStart, rowEnd },
2999
- "screen",
3000
- block.attrs.borderColor
3001
- )
3002
- ),
3003
- className: inRect ? "ed-cell ed-cell--selected" : "ed-cell",
3004
- children: renderInline(delta, `t${index}-c${flat}`)
3005
- },
3006
- c
3007
- );
3008
- }) }, r);
3532
+ return /* @__PURE__ */ jsx12(
3533
+ "tr",
3534
+ {
3535
+ "data-cell-row": r,
3536
+ style: typeof rowHeights?.[r] === "number" ? { height: `${rowHeights[r]}px` } : void 0,
3537
+ children: Array.from({ length: cols }, (_2, c) => {
3538
+ const flat = r * cols + c;
3539
+ const cell = cells[flat];
3540
+ if (cell?.attrs.covered === true) return null;
3541
+ const rowspan = spanAttr(cell?.attrs.rowspan);
3542
+ const colspan = spanAttr(cell?.attrs.colspan);
3543
+ const delta = cell?.delta ?? [];
3544
+ const inRect = rect !== null && r >= rect.top && r <= rect.bottom && c >= rect.left && c <= rect.right;
3545
+ return /* @__PURE__ */ jsx12(
3546
+ "td",
3547
+ {
3548
+ "data-cell-index": flat,
3549
+ "data-cell-row": r,
3550
+ "data-cell-col": c,
3551
+ "data-cell-rowspan": rowspan,
3552
+ "data-cell-colspan": colspan,
3553
+ rowSpan: rowspan > 1 ? rowspan : void 0,
3554
+ colSpan: colspan > 1 ? colspan : void 0,
3555
+ style: cellStyle(
3556
+ cell?.attrs,
3557
+ // rowStart/rowEnd são os limites do FRAGMENTO: numa tabela
3558
+ // quebrada entre páginas, cada página fecha a própria caixa.
3559
+ cellBorderStyle(
3560
+ block.attrs.borderPreset,
3561
+ { row: r, col: c, rowspan, colspan, cols, rowStart, rowEnd },
3562
+ "screen",
3563
+ block.attrs.borderColor
3564
+ )
3565
+ ),
3566
+ className: inRect ? "ed-cell ed-cell--selected" : "ed-cell",
3567
+ children: renderInline(delta, `t${index}-c${flat}`)
3568
+ },
3569
+ c
3570
+ );
3571
+ })
3572
+ },
3573
+ r
3574
+ );
3009
3575
  }) })
3010
3576
  ]
3011
3577
  }
3012
3578
  ),
3013
- isFirstFragment && /* @__PURE__ */ jsx11(TableResizeOverlay, { tableRef, blockIndex: index, cols })
3579
+ isFirstFragment && /* @__PURE__ */ jsx12(TableResizeOverlay, { tableRef, blockIndex: index, cols, rows })
3014
3580
  ] });
3015
3581
  }
3016
- function readColWidths(raw, cols) {
3017
- if (!Array.isArray(raw)) return null;
3018
- const out = [];
3019
- for (let i = 0; i < cols; i++) {
3020
- const v = raw[i];
3021
- out.push(typeof v === "number" && Number.isFinite(v) && v > 0 ? v : null);
3022
- }
3023
- return out;
3024
- }
3025
3582
  function spanAttr(v) {
3026
3583
  if (typeof v !== "number" || !Number.isFinite(v) || v < 1) return 1;
3027
3584
  return Math.trunc(v);
@@ -3032,7 +3589,7 @@ function clampPositive(n) {
3032
3589
  }
3033
3590
 
3034
3591
  // src/usePagination.ts
3035
- import { useLayoutEffect as useLayoutEffect4, useRef as useRef8, useState as useState8 } from "react";
3592
+ import { useLayoutEffect as useLayoutEffect4, useRef as useRef9, useState as useState9 } from "react";
3036
3593
  var A4_PAGE = {
3037
3594
  width: 794,
3038
3595
  height: 1123,
@@ -3058,9 +3615,9 @@ function defaultPageLayout(topLevelCount) {
3058
3615
  };
3059
3616
  }
3060
3617
  function usePageLayout(rootRef, geometry, topLevelCount, deps) {
3061
- const [phase, setPhase] = useState8("measure");
3062
- const [layout, setLayout] = useState8(() => defaultPageLayout(topLevelCount));
3063
- const lastDepsRef = useRef8(null);
3618
+ const [phase, setPhase] = useState9("measure");
3619
+ const [layout, setLayout] = useState9(() => defaultPageLayout(topLevelCount));
3620
+ const lastDepsRef = useRef9(null);
3064
3621
  useLayoutEffect4(() => {
3065
3622
  const currentDeps = [...deps, topLevelCount, geometry];
3066
3623
  if (lastDepsRef.current !== null && shallowArrayEqual(lastDepsRef.current, currentDeps)) {
@@ -3545,17 +4102,17 @@ function layoutsDeepEqual(a, b) {
3545
4102
  }
3546
4103
 
3547
4104
  // src/useEditor.ts
3548
- import { useCallback as useCallback6, useEffect as useEffect8, useMemo as useMemo3, useRef as useRef10, useState as useState9 } from "react";
4105
+ import { useCallback as useCallback7, useEffect as useEffect9, useMemo as useMemo3, useRef as useRef11, useState as useState10 } from "react";
3549
4106
 
3550
4107
  // src/usePageSettings.ts
3551
- import { useCallback as useCallback5, useRef as useRef9, useSyncExternalStore } from "react";
4108
+ import { useCallback as useCallback6, useRef as useRef10, useSyncExternalStore } from "react";
3552
4109
  function usePageSettings(doc) {
3553
- const cacheRef = useRef9(null);
3554
- const subscribe = useCallback5(
4110
+ const cacheRef = useRef10(null);
4111
+ const subscribe = useCallback6(
3555
4112
  (notify) => doc.observePageSettings(notify),
3556
4113
  [doc]
3557
4114
  );
3558
- const getSnapshot = useCallback5(() => {
4115
+ const getSnapshot = useCallback6(() => {
3559
4116
  const next = doc.getPageSettings();
3560
4117
  const prev = cacheRef.current;
3561
4118
  if (prev && shallowEqual(prev, next)) return prev;
@@ -3583,8 +4140,10 @@ import {
3583
4140
  mergeSelection as cmdMergeSelection,
3584
4141
  moveEmbedAnchor as cmdMoveEmbedAnchor,
3585
4142
  setBlockAttrAtIndex as cmdSetBlockAttrAtIndex,
3586
- setColumnWidth as cmdSetColumnWidth,
4143
+ setColumnBoundary as cmdSetColumnBoundary,
3587
4144
  setImageAttrs as cmdSetImageAttrs,
4145
+ setRowHeight as cmdSetRowHeight,
4146
+ setRowHeights as cmdSetRowHeights,
3588
4147
  splitCell as cmdSplitCell,
3589
4148
  tableRectSelection as tableRectSelection2,
3590
4149
  getMarksInRange,
@@ -3593,6 +4152,7 @@ import {
3593
4152
  insertTable as cmdInsertTable,
3594
4153
  insertTableColumn as cmdInsertColumn,
3595
4154
  insertTableRow as cmdInsertRow,
4155
+ isFormulaEmbed,
3596
4156
  isImageEmbed as isImageEmbed4,
3597
4157
  isMarkUniformInRange,
3598
4158
  moveToNextCell as cmdMoveNextCell,
@@ -3603,6 +4163,7 @@ import {
3603
4163
  setCellAttr as cmdSetCellAttr,
3604
4164
  setBlockType as cmdSetBlockType,
3605
4165
  setMark as cmdSetMark,
4166
+ setTableWidth as cmdSetTableWidth,
3606
4167
  splitListItem as cmdSplitListItem,
3607
4168
  tableLocationOf,
3608
4169
  toggleList as cmdToggleList,
@@ -3611,19 +4172,19 @@ import {
3611
4172
  function useEditor(opts = {}) {
3612
4173
  const doc = useMemo3(() => opts.document ?? new EditorDocument(), [opts.document]);
3613
4174
  const history = useMemo3(() => new EditorHistory(doc), [doc]);
3614
- const [snapshot, setSnapshot] = useState9(() => doc.toJSON());
3615
- const [selection, setSelectionState] = useState9(
4175
+ const [snapshot, setSnapshot] = useState10(() => doc.toJSON());
4176
+ const [selection, setSelectionState] = useState10(
3616
4177
  () => collapsedSelection({ blockIndex: 0, offset: 0 })
3617
4178
  );
3618
- const selectionRef = useRef10(selection);
4179
+ const selectionRef = useRef11(selection);
3619
4180
  selectionRef.current = selection;
3620
- const pendingMarksRef = useRef10({});
3621
- const [pendingMarks, setPendingMarksState] = useState9({});
3622
- const setPendingMarks = useCallback6((next) => {
4181
+ const pendingMarksRef = useRef11({});
4182
+ const [pendingMarks, setPendingMarksState] = useState10({});
4183
+ const setPendingMarks = useCallback7((next) => {
3623
4184
  pendingMarksRef.current = next;
3624
4185
  setPendingMarksState(next);
3625
4186
  }, []);
3626
- useEffect8(() => {
4187
+ useEffect9(() => {
3627
4188
  let scheduled = false;
3628
4189
  let cancelled = false;
3629
4190
  let frame = 0;
@@ -3650,8 +4211,8 @@ function useEditor(opts = {}) {
3650
4211
  doc.ydoc.off("afterTransaction", schedule);
3651
4212
  };
3652
4213
  }, [doc]);
3653
- const getSelection = useCallback6(() => selectionRef.current, []);
3654
- const setSelection = useCallback6(
4214
+ const getSelection = useCallback7(() => selectionRef.current, []);
4215
+ const setSelection = useCallback7(
3655
4216
  (sel) => {
3656
4217
  const prev = selectionRef.current;
3657
4218
  selectionRef.current = sel;
@@ -3666,16 +4227,16 @@ function useEditor(opts = {}) {
3666
4227
  },
3667
4228
  []
3668
4229
  );
3669
- const ctxRef = useRef10({ doc, getSelection, setSelection });
4230
+ const ctxRef = useRef11({ doc, getSelection, setSelection });
3670
4231
  ctxRef.current = { doc, getSelection, setSelection };
3671
- const consumePendingMarks = useCallback6(() => {
4232
+ const consumePendingMarks = useCallback7(() => {
3672
4233
  const current = pendingMarksRef.current;
3673
4234
  if (Object.keys(current).length === 0) return void 0;
3674
4235
  pendingMarksRef.current = {};
3675
4236
  setPendingMarksState({});
3676
4237
  return current;
3677
4238
  }, []);
3678
- const isMarkActive = useCallback6(
4239
+ const isMarkActive = useCallback7(
3679
4240
  (name, value) => {
3680
4241
  const sel = selectionRef.current;
3681
4242
  const { start, end } = orderedRange(sel);
@@ -3706,7 +4267,7 @@ function useEditor(opts = {}) {
3706
4267
  },
3707
4268
  [doc]
3708
4269
  );
3709
- const getActiveMarks = useCallback6(() => {
4270
+ const getActiveMarks = useCallback7(() => {
3710
4271
  const sel = selectionRef.current;
3711
4272
  const { start, end } = orderedRange(sel);
3712
4273
  if (start.blockIndex !== end.blockIndex) {
@@ -3720,7 +4281,7 @@ function useEditor(opts = {}) {
3720
4281
  }
3721
4282
  return getMarksInRange(yText, start.offset, end.offset);
3722
4283
  }, [doc]);
3723
- const toggleMark = useCallback6(
4284
+ const toggleMark = useCallback7(
3724
4285
  (name, value) => {
3725
4286
  const sel = selectionRef.current;
3726
4287
  const { start, end } = orderedRange(sel);
@@ -3740,7 +4301,7 @@ function useEditor(opts = {}) {
3740
4301
  },
3741
4302
  [isMarkActive, setPendingMarks]
3742
4303
  );
3743
- const setMark = useCallback6(
4304
+ const setMark = useCallback7(
3744
4305
  (name, value) => {
3745
4306
  const sel = selectionRef.current;
3746
4307
  const { start, end } = orderedRange(sel);
@@ -3753,7 +4314,7 @@ function useEditor(opts = {}) {
3753
4314
  },
3754
4315
  [setPendingMarks]
3755
4316
  );
3756
- const removeMark = useCallback6(
4317
+ const removeMark = useCallback7(
3757
4318
  (name) => {
3758
4319
  const sel = selectionRef.current;
3759
4320
  const { start, end } = orderedRange(sel);
@@ -3766,7 +4327,7 @@ function useEditor(opts = {}) {
3766
4327
  },
3767
4328
  [setPendingMarks]
3768
4329
  );
3769
- const getBlockType = useCallback6(() => {
4330
+ const getBlockType = useCallback7(() => {
3770
4331
  const sel = selectionRef.current;
3771
4332
  const { start, end } = orderedRange(sel);
3772
4333
  const first = doc.getBlockType(start.blockIndex);
@@ -3776,7 +4337,7 @@ function useEditor(opts = {}) {
3776
4337
  }
3777
4338
  return first;
3778
4339
  }, [doc]);
3779
- const getBlockAttr = useCallback6(
4340
+ const getBlockAttr = useCallback7(
3780
4341
  (key) => {
3781
4342
  const sel = selectionRef.current;
3782
4343
  const { start, end } = orderedRange(sel);
@@ -3789,57 +4350,57 @@ function useEditor(opts = {}) {
3789
4350
  },
3790
4351
  [doc]
3791
4352
  );
3792
- const setBlockType = useCallback6((type, attrs) => {
4353
+ const setBlockType = useCallback7((type, attrs) => {
3793
4354
  cmdSetBlockType(ctxRef.current, type, attrs);
3794
4355
  }, []);
3795
- const setBlockAttr = useCallback6(
4356
+ const setBlockAttr = useCallback7(
3796
4357
  (key, value) => {
3797
4358
  cmdSetBlockAttr(ctxRef.current, key, value);
3798
4359
  },
3799
4360
  []
3800
4361
  );
3801
- const setAlign = useCallback6((value) => {
4362
+ const setAlign = useCallback7((value) => {
3802
4363
  const sel = selectionRef.current;
3803
4364
  const inCell = sel.focus.cellIndex != null;
3804
4365
  if (inCell) cmdSetCellAttr(ctxRef.current, "align", value);
3805
4366
  else cmdSetBlockAttr(ctxRef.current, "align", value);
3806
4367
  }, []);
3807
- const getAlign = useCallback6(() => {
4368
+ const getAlign = useCallback7(() => {
3808
4369
  const sel = selectionRef.current;
3809
4370
  if (sel.focus.cellIndex != null && doc.isTable(sel.focus.blockIndex)) {
3810
4371
  return doc.getCellAttrs(sel.focus.blockIndex, sel.focus.cellIndex).align;
3811
4372
  }
3812
4373
  return getBlockAttr("align");
3813
4374
  }, [doc, getBlockAttr]);
3814
- const setCellBackground = useCallback6((color) => {
4375
+ const setCellBackground = useCallback7((color) => {
3815
4376
  cmdSetCellAttr(ctxRef.current, "bgColor", color);
3816
4377
  }, []);
3817
- const getCellBackground = useCallback6(() => {
4378
+ const getCellBackground = useCallback7(() => {
3818
4379
  const sel = selectionRef.current;
3819
4380
  if (sel.focus.cellIndex == null || !doc.isTable(sel.focus.blockIndex)) return void 0;
3820
4381
  return doc.getCellAttrs(sel.focus.blockIndex, sel.focus.cellIndex).bgColor;
3821
4382
  }, [doc]);
3822
- const setTableBorderPreset = useCallback6((preset) => {
4383
+ const setTableBorderPreset = useCallback7((preset) => {
3823
4384
  const sel = selectionRef.current;
3824
4385
  if (!doc.isTable(sel.focus.blockIndex)) return;
3825
4386
  cmdSetBlockAttrAtIndex(ctxRef.current, sel.focus.blockIndex, "borderPreset", preset);
3826
4387
  }, [doc]);
3827
- const getTableBorderPreset = useCallback6(() => {
4388
+ const getTableBorderPreset = useCallback7(() => {
3828
4389
  const sel = selectionRef.current;
3829
4390
  if (!doc.isTable(sel.focus.blockIndex)) return "all";
3830
4391
  return doc.getBlockAttrs(sel.focus.blockIndex).borderPreset ?? "all";
3831
4392
  }, [doc]);
3832
- const setTableBorderColor = useCallback6((color) => {
4393
+ const setTableBorderColor = useCallback7((color) => {
3833
4394
  const sel = selectionRef.current;
3834
4395
  if (!doc.isTable(sel.focus.blockIndex)) return;
3835
4396
  cmdSetBlockAttrAtIndex(ctxRef.current, sel.focus.blockIndex, "borderColor", color);
3836
4397
  }, [doc]);
3837
- const getTableBorderColor = useCallback6(() => {
4398
+ const getTableBorderColor = useCallback7(() => {
3838
4399
  const sel = selectionRef.current;
3839
4400
  if (!doc.isTable(sel.focus.blockIndex)) return void 0;
3840
4401
  return doc.getBlockAttrs(sel.focus.blockIndex).borderColor;
3841
4402
  }, [doc]);
3842
- const isListActive = useCallback6(
4403
+ const isListActive = useCallback7(
3843
4404
  (kind) => {
3844
4405
  const sel = selectionRef.current;
3845
4406
  const { start, end } = orderedRange(sel);
@@ -3851,119 +4412,128 @@ function useEditor(opts = {}) {
3851
4412
  },
3852
4413
  [doc]
3853
4414
  );
3854
- const toggleList = useCallback6((kind) => {
4415
+ const toggleList = useCallback7((kind) => {
3855
4416
  cmdToggleList(ctxRef.current, kind);
3856
4417
  }, []);
3857
- const indentList = useCallback6(() => {
4418
+ const indentList = useCallback7(() => {
3858
4419
  cmdIndentList(ctxRef.current);
3859
4420
  }, []);
3860
- const dedentList = useCallback6(() => {
4421
+ const dedentList = useCallback7(() => {
3861
4422
  cmdDedentList(ctxRef.current);
3862
4423
  }, []);
3863
- const splitListItem = useCallback6(() => {
4424
+ const splitListItem = useCallback7(() => {
3864
4425
  return cmdSplitListItem(ctxRef.current);
3865
4426
  }, []);
3866
- const isInTable = useCallback6(() => {
4427
+ const isInTable = useCallback7(() => {
3867
4428
  return selectionRef.current.focus.cellIndex != null;
3868
4429
  }, []);
3869
- const getTableLocation = useCallback6(() => {
4430
+ const getTableLocation = useCallback7(() => {
3870
4431
  return tableLocationOf(doc, selectionRef.current.focus);
3871
4432
  }, [doc]);
3872
- const insertTable = useCallback6((rows, cols) => {
4433
+ const insertTable = useCallback7((rows, cols) => {
3873
4434
  cmdInsertTable(ctxRef.current, rows, cols);
3874
4435
  }, []);
3875
- const insertAnswerLines = useCallback6((count, spacing) => {
4436
+ const insertAnswerLines = useCallback7((count, spacing) => {
3876
4437
  cmdInsertAnswerLines(ctxRef.current, count, spacing);
3877
4438
  }, []);
3878
- const deleteTable = useCallback6((blockIndex) => {
4439
+ const deleteTable = useCallback7((blockIndex) => {
3879
4440
  const idx = blockIndex ?? selectionRef.current.focus.blockIndex;
3880
4441
  cmdDeleteTable(ctxRef.current, idx);
3881
4442
  }, []);
3882
- const insertRowAbove = useCallback6(() => {
4443
+ const insertRowAbove = useCallback7(() => {
3883
4444
  const loc = tableLocationOf(doc, selectionRef.current.focus);
3884
4445
  if (!loc) return;
3885
4446
  cmdInsertRow(ctxRef.current, loc.blockIndex, loc.row, "before");
3886
4447
  }, [doc]);
3887
- const insertRowBelow = useCallback6(() => {
4448
+ const insertRowBelow = useCallback7(() => {
3888
4449
  const loc = tableLocationOf(doc, selectionRef.current.focus);
3889
4450
  if (!loc) return;
3890
4451
  cmdInsertRow(ctxRef.current, loc.blockIndex, loc.row, "after");
3891
4452
  }, [doc]);
3892
- const deleteCurrentRow = useCallback6(() => {
4453
+ const deleteCurrentRow = useCallback7(() => {
3893
4454
  const loc = tableLocationOf(doc, selectionRef.current.focus);
3894
4455
  if (!loc) return;
3895
4456
  cmdDeleteRow(ctxRef.current, loc.blockIndex, loc.row);
3896
4457
  }, [doc]);
3897
- const insertColumnLeft = useCallback6(() => {
4458
+ const insertColumnLeft = useCallback7(() => {
3898
4459
  const loc = tableLocationOf(doc, selectionRef.current.focus);
3899
4460
  if (!loc) return;
3900
4461
  cmdInsertColumn(ctxRef.current, loc.blockIndex, loc.col, "before");
3901
4462
  }, [doc]);
3902
- const insertColumnRight = useCallback6(() => {
4463
+ const insertColumnRight = useCallback7(() => {
3903
4464
  const loc = tableLocationOf(doc, selectionRef.current.focus);
3904
4465
  if (!loc) return;
3905
4466
  cmdInsertColumn(ctxRef.current, loc.blockIndex, loc.col, "after");
3906
4467
  }, [doc]);
3907
- const deleteCurrentColumn = useCallback6(() => {
4468
+ const deleteCurrentColumn = useCallback7(() => {
3908
4469
  const loc = tableLocationOf(doc, selectionRef.current.focus);
3909
4470
  if (!loc) return;
3910
4471
  cmdDeleteColumn(ctxRef.current, loc.blockIndex, loc.col);
3911
4472
  }, [doc]);
3912
- const moveToNextCell = useCallback6(() => {
4473
+ const moveToNextCell = useCallback7(() => {
3913
4474
  cmdMoveNextCell(ctxRef.current);
3914
4475
  }, []);
3915
- const moveToPrevCell = useCallback6(() => {
4476
+ const moveToPrevCell = useCallback7(() => {
3916
4477
  cmdMovePrevCell(ctxRef.current);
3917
4478
  }, []);
3918
- const mergeRight = useCallback6(() => {
4479
+ const mergeRight = useCallback7(() => {
3919
4480
  const loc = tableLocationOf(doc, selectionRef.current.focus);
3920
4481
  if (!loc) return false;
3921
4482
  return cmdMergeRight(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3922
4483
  }, [doc]);
3923
- const mergeDown = useCallback6(() => {
4484
+ const mergeDown = useCallback7(() => {
3924
4485
  const loc = tableLocationOf(doc, selectionRef.current.focus);
3925
4486
  if (!loc) return false;
3926
4487
  return cmdMergeDown(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3927
4488
  }, [doc]);
3928
- const splitCell = useCallback6(() => {
4489
+ const splitCell = useCallback7(() => {
3929
4490
  const loc = tableLocationOf(doc, selectionRef.current.focus);
3930
4491
  if (!loc) return false;
3931
4492
  return cmdSplitCell(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3932
4493
  }, [doc]);
3933
- const setColumnWidth = useCallback6(
3934
- (blockIndex, col, widthPx) => {
3935
- cmdSetColumnWidth(ctxRef.current, blockIndex, col, widthPx);
4494
+ const setColumnBoundary = useCallback7(
4495
+ (blockIndex, boundary, deltaPct, base) => {
4496
+ cmdSetColumnBoundary(ctxRef.current, blockIndex, boundary, deltaPct, base);
3936
4497
  },
3937
4498
  []
3938
4499
  );
3939
- const getTableRect = useCallback6(
4500
+ const setTableWidth = useCallback7((blockIndex, pct) => {
4501
+ cmdSetTableWidth(ctxRef.current, blockIndex, pct);
4502
+ }, []);
4503
+ const setRowHeight = useCallback7((blockIndex, row, px) => {
4504
+ cmdSetRowHeight(ctxRef.current, blockIndex, row, px);
4505
+ }, []);
4506
+ const setRowHeights = useCallback7((blockIndex, heights) => {
4507
+ cmdSetRowHeights(ctxRef.current, blockIndex, heights);
4508
+ }, []);
4509
+ const getTableRect = useCallback7(
3940
4510
  () => tableRectSelection2(doc, selectionRef.current),
3941
4511
  [doc]
3942
4512
  );
3943
- const hasTableRectSelection = useCallback6(() => {
4513
+ const hasTableRectSelection = useCallback7(() => {
3944
4514
  return tableRectSelection2(doc, selectionRef.current) !== null;
3945
4515
  }, [doc]);
3946
- const mergeSelection = useCallback6(() => {
4516
+ const mergeSelection = useCallback7(() => {
3947
4517
  return cmdMergeSelection(ctxRef.current);
3948
4518
  }, []);
3949
- const insertImage = useCallback6((embed) => {
4519
+ const insertImage = useCallback7((embed) => {
3950
4520
  cmdInsertImage(ctxRef.current, embed);
3951
4521
  }, []);
3952
- const setImageAttrs = useCallback6(
4522
+ const setImageAttrs = useCallback7(
3953
4523
  (blockIndex, offset, partial, cellIndex, newOffset) => {
3954
4524
  cmdSetImageAttrs(ctxRef.current, blockIndex, offset, partial, cellIndex, newOffset);
3955
4525
  },
3956
4526
  []
3957
4527
  );
3958
- const moveEmbedAnchor = useCallback6(
4528
+ const moveEmbedAnchor = useCallback7(
3959
4529
  (from, to, newOffsetX, newOffsetY) => {
3960
4530
  cmdMoveEmbedAnchor(ctxRef.current, from, to, newOffsetX, newOffsetY);
3961
4531
  },
3962
4532
  []
3963
4533
  );
3964
- const uploadImageRef = useRef10(opts.uploadImage);
4534
+ const uploadImageRef = useRef11(opts.uploadImage);
3965
4535
  uploadImageRef.current = opts.uploadImage;
3966
- const insertImageFromFile = useCallback6(async (file) => {
4536
+ const insertImageFromFile = useCallback7(async (file) => {
3967
4537
  if (!file.type.startsWith("image/")) return;
3968
4538
  const dataUrl = await readAsDataURL(file);
3969
4539
  const dims = await readImageDimensions(dataUrl);
@@ -3977,7 +4547,7 @@ function useEditor(opts = {}) {
3977
4547
  const src = upload ? await upload(file) : dataUrl;
3978
4548
  cmdInsertImage(ctxRef.current, { type: "image", src, width: w, height: h });
3979
4549
  }, []);
3980
- const getSelectedEmbed = useCallback6(() => {
4550
+ const getSelectedEmbed = useCallback7(() => {
3981
4551
  const sel = selectionRef.current;
3982
4552
  if (sel.anchor.blockIndex !== sel.focus.blockIndex) return null;
3983
4553
  if ((sel.anchor.cellIndex ?? -1) !== (sel.focus.cellIndex ?? -1)) return null;
@@ -4006,16 +4576,16 @@ function useEditor(opts = {}) {
4006
4576
  }
4007
4577
  return null;
4008
4578
  }, [doc]);
4009
- const [linkRequest, setLinkRequest] = useState9(null);
4010
- const linkRequestRef = useRef10(null);
4011
- const requestLink = useCallback6((initialHref = "") => {
4579
+ const [linkRequest, setLinkRequest] = useState10(null);
4580
+ const linkRequestRef = useRef11(null);
4581
+ const requestLink = useCallback7((initialHref = "") => {
4012
4582
  return new Promise((resolve) => {
4013
4583
  const req = { initialHref, resolve, selection: selectionRef.current };
4014
4584
  linkRequestRef.current = req;
4015
4585
  setLinkRequest(req);
4016
4586
  });
4017
4587
  }, []);
4018
- const resolveLinkRequest = useCallback6(
4588
+ const resolveLinkRequest = useCallback7(
4019
4589
  (href) => {
4020
4590
  const req = linkRequestRef.current;
4021
4591
  linkRequestRef.current = null;
@@ -4028,26 +4598,26 @@ function useEditor(opts = {}) {
4028
4598
  [setSelection]
4029
4599
  );
4030
4600
  const pageSettings = usePageSettings(doc);
4031
- const setPageSettings = useCallback6(
4601
+ const setPageSettings = useCallback7(
4032
4602
  (partial) => {
4033
4603
  doc.setPageSettings(partial);
4034
4604
  },
4035
4605
  [doc]
4036
4606
  );
4037
- const [pageConfigRequest, setPageConfigRequest] = useState9(null);
4038
- const requestPageConfig = useCallback6(() => {
4607
+ const [pageConfigRequest, setPageConfigRequest] = useState10(null);
4608
+ const requestPageConfig = useCallback7(() => {
4039
4609
  return new Promise((resolve) => {
4040
4610
  setPageConfigRequest({ initial: doc.getPageSettings(), resolve });
4041
4611
  });
4042
4612
  }, [doc]);
4043
- const resolvePageConfigRequest = useCallback6((applied) => {
4613
+ const resolvePageConfigRequest = useCallback7((applied) => {
4044
4614
  setPageConfigRequest((prev) => {
4045
4615
  if (prev) prev.resolve(applied);
4046
4616
  return null;
4047
4617
  });
4048
4618
  }, []);
4049
- const [imageCaptionRequest, setImageCaptionRequest] = useState9(null);
4050
- const requestImageCaption = useCallback6(
4619
+ const [imageCaptionRequest, setImageCaptionRequest] = useState10(null);
4620
+ const requestImageCaption = useCallback7(
4051
4621
  (initialCaption = "", initialAlign = "center") => {
4052
4622
  return new Promise((resolve) => {
4053
4623
  setImageCaptionRequest({ initialCaption, initialAlign, resolve });
@@ -4055,12 +4625,82 @@ function useEditor(opts = {}) {
4055
4625
  },
4056
4626
  []
4057
4627
  );
4058
- const resolveImageCaptionRequest = useCallback6((result) => {
4628
+ const resolveImageCaptionRequest = useCallback7((result) => {
4059
4629
  setImageCaptionRequest((prev) => {
4060
4630
  if (prev) prev.resolve(result);
4061
4631
  return null;
4062
4632
  });
4063
4633
  }, []);
4634
+ const [formulaRequest, setFormulaRequest] = useState10(null);
4635
+ const requestFormula = useCallback7(
4636
+ (initialLatex = "", initialDisplay = false) => {
4637
+ return new Promise((resolve) => {
4638
+ setFormulaRequest({ initialLatex, initialDisplay, resolve });
4639
+ });
4640
+ },
4641
+ []
4642
+ );
4643
+ const resolveFormulaRequest = useCallback7((result) => {
4644
+ setFormulaRequest((prev) => {
4645
+ if (prev) prev.resolve(result);
4646
+ return null;
4647
+ });
4648
+ }, []);
4649
+ const insertFormula = useCallback7(
4650
+ async (latex, display) => {
4651
+ const selectionAtCall = ctxRef.current.getSelection();
4652
+ const embedAtCall = getSelectedEmbed();
4653
+ let mathModule;
4654
+ try {
4655
+ mathModule = await import("@sofereditor/math");
4656
+ } catch {
4657
+ return;
4658
+ }
4659
+ const { renderLatexToSvg, measureExInPx, svgToDataUrl, svgToPngDataUrl } = mathModule;
4660
+ const r = renderLatexToSvg(latex, display);
4661
+ if (!r.ok) return;
4662
+ const root = document.querySelector(".ed-root");
4663
+ const exPx = root ? measureExInPx(root) : 8;
4664
+ let w = Math.round(r.widthEx * exPx);
4665
+ let h = Math.round(r.heightEx * exPx);
4666
+ let vAlignScale = 1;
4667
+ if (w > MAX_INSERT_WIDTH) {
4668
+ vAlignScale = MAX_INSERT_WIDTH / w;
4669
+ h = Math.round(h * MAX_INSERT_WIDTH / w);
4670
+ w = MAX_INSERT_WIDTH;
4671
+ }
4672
+ const src = svgToDataUrl(r.svg);
4673
+ let svgFallback;
4674
+ try {
4675
+ svgFallback = await svgToPngDataUrl(r.svg, w, h);
4676
+ } catch {
4677
+ svgFallback = void 0;
4678
+ }
4679
+ ctxRef.current.setSelection(selectionAtCall);
4680
+ const inheritedLayout = {};
4681
+ if (isFormulaEmbed(embedAtCall?.embed)) {
4682
+ const prev = embedAtCall.embed;
4683
+ if (prev.layout !== void 0) inheritedLayout.layout = prev.layout;
4684
+ if (prev.offsetX !== void 0) inheritedLayout.offsetX = prev.offsetX;
4685
+ if (prev.offsetY !== void 0) inheritedLayout.offsetY = prev.offsetY;
4686
+ }
4687
+ cmdInsertImage(ctxRef.current, {
4688
+ type: "image",
4689
+ src,
4690
+ width: w,
4691
+ height: h,
4692
+ ...inheritedLayout,
4693
+ ...display ? { align: "center" } : {},
4694
+ formula: {
4695
+ latex,
4696
+ display,
4697
+ ...display ? {} : { vAlign: `${r.vAlignEx * vAlignScale}ex` }
4698
+ },
4699
+ ...svgFallback ? { svgFallback } : {}
4700
+ });
4701
+ },
4702
+ [getSelectedEmbed]
4703
+ );
4064
4704
  return {
4065
4705
  doc,
4066
4706
  history,
@@ -4111,7 +4751,10 @@ function useEditor(opts = {}) {
4111
4751
  mergeRight,
4112
4752
  mergeDown,
4113
4753
  splitCell,
4114
- setColumnWidth,
4754
+ setColumnBoundary,
4755
+ setTableWidth,
4756
+ setRowHeight,
4757
+ setRowHeights,
4115
4758
  getTableRect,
4116
4759
  hasTableRectSelection,
4117
4760
  mergeSelection,
@@ -4128,6 +4771,10 @@ function useEditor(opts = {}) {
4128
4771
  imageCaptionRequest,
4129
4772
  requestImageCaption,
4130
4773
  resolveImageCaptionRequest,
4774
+ formulaRequest,
4775
+ requestFormula,
4776
+ resolveFormulaRequest,
4777
+ insertFormula,
4131
4778
  uploadImage: opts.uploadImage
4132
4779
  };
4133
4780
  }
@@ -4160,7 +4807,7 @@ function sameValue(a, b) {
4160
4807
  }
4161
4808
 
4162
4809
  // src/Editor.tsx
4163
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
4810
+ import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
4164
4811
  var defaultFooter = ({ pageNumber, pageCount }) => `${pageNumber} / ${pageCount}`;
4165
4812
  function Editor({
4166
4813
  editor: providedEditor,
@@ -4173,15 +4820,15 @@ function Editor({
4173
4820
  const internal = useEditor();
4174
4821
  const editor = providedEditor ?? internal;
4175
4822
  const { doc, history, snapshot, getSelection, setSelection } = editor;
4176
- const rootRef = useRef11(null);
4177
- const isComposingRef = useRef11(false);
4178
- const pasteInFlightRef = useRef11(false);
4179
- const [hoveredBehind, setHoveredBehind] = useState10(null);
4180
- const hoveredBehindRef = useRef11(null);
4181
- const [hoveredLink, setHoveredLink] = useState10(null);
4182
- const hoveredLinkElRef = useRef11(null);
4183
- const suppressSelectionSyncRef = useRef11(false);
4184
- useEffect9(() => {
4823
+ const rootRef = useRef12(null);
4824
+ const isComposingRef = useRef12(false);
4825
+ const pasteInFlightRef = useRef12(false);
4826
+ const [hoveredBehind, setHoveredBehind] = useState11(null);
4827
+ const hoveredBehindRef = useRef12(null);
4828
+ const [hoveredLink, setHoveredLink] = useState11(null);
4829
+ const hoveredLinkElRef = useRef12(null);
4830
+ const suppressSelectionSyncRef = useRef12(false);
4831
+ useEffect10(() => {
4185
4832
  if (!awareness) return;
4186
4833
  const root = rootRef.current;
4187
4834
  if (!root) return;
@@ -4211,11 +4858,11 @@ function Editor({
4211
4858
  awareness.setLocalStateField("cursor", null);
4212
4859
  };
4213
4860
  }, [awareness, doc]);
4214
- const ctxRef = useRef11({ doc, getSelection, setSelection });
4861
+ const ctxRef = useRef12({ doc, getSelection, setSelection });
4215
4862
  ctxRef.current = { doc, getSelection, setSelection };
4216
- const historyRef = useRef11(history);
4863
+ const historyRef = useRef12(history);
4217
4864
  historyRef.current = history;
4218
- const editorRef = useRef11(editor);
4865
+ const editorRef = useRef12(editor);
4219
4866
  editorRef.current = editor;
4220
4867
  useLayoutEffect5(() => {
4221
4868
  const root = rootRef.current;
@@ -4232,7 +4879,7 @@ function Editor({
4232
4879
  suppressSelectionSyncRef.current = true;
4233
4880
  applyDomSelection(root, editor.selection);
4234
4881
  });
4235
- useEffect9(() => {
4882
+ useEffect10(() => {
4236
4883
  const root = rootRef.current;
4237
4884
  if (!root) return;
4238
4885
  const handler = () => {
@@ -4253,7 +4900,7 @@ function Editor({
4253
4900
  document.addEventListener("selectionchange", handler);
4254
4901
  return () => document.removeEventListener("selectionchange", handler);
4255
4902
  }, [setSelection]);
4256
- useEffect9(() => {
4903
+ useEffect10(() => {
4257
4904
  const root = rootRef.current;
4258
4905
  if (!root) return;
4259
4906
  let drag = null;
@@ -4324,7 +4971,7 @@ function Editor({
4324
4971
  document.removeEventListener("pointerup", onPointerUp);
4325
4972
  };
4326
4973
  }, []);
4327
- useEffect9(() => {
4974
+ useEffect10(() => {
4328
4975
  const root = rootRef.current;
4329
4976
  if (!root) return;
4330
4977
  const onDragOver = (e) => {
@@ -4362,7 +5009,7 @@ function Editor({
4362
5009
  root.removeEventListener("drop", onDrop);
4363
5010
  };
4364
5011
  }, []);
4365
- useEffect9(() => {
5012
+ useEffect10(() => {
4366
5013
  const root = rootRef.current;
4367
5014
  if (!root) return;
4368
5015
  const onPointerDown = (e) => {
@@ -4390,7 +5037,27 @@ function Editor({
4390
5037
  root.addEventListener("pointerdown", onPointerDown);
4391
5038
  return () => root.removeEventListener("pointerdown", onPointerDown);
4392
5039
  }, []);
4393
- useEffect9(() => {
5040
+ useEffect10(() => {
5041
+ const root = rootRef.current;
5042
+ if (!root) return;
5043
+ const onDoubleClick = (e) => {
5044
+ const target = e.target;
5045
+ if (!(target instanceof Element)) return;
5046
+ if (!target.closest('img[data-embed="image"]')) return;
5047
+ const ed = editorRef.current;
5048
+ const sel = ed.getSelectedEmbed();
5049
+ if (!sel || !isFormulaEmbed2(sel.embed)) return;
5050
+ e.preventDefault();
5051
+ const { latex, display } = sel.embed.formula;
5052
+ void ed.requestFormula(latex, display).then((r) => {
5053
+ if (!r) return;
5054
+ void ed.insertFormula(r.latex, r.display);
5055
+ });
5056
+ };
5057
+ root.addEventListener("dblclick", onDoubleClick);
5058
+ return () => root.removeEventListener("dblclick", onDoubleClick);
5059
+ }, []);
5060
+ useEffect10(() => {
4394
5061
  const root = rootRef.current;
4395
5062
  if (!root) return;
4396
5063
  const same = (a, b) => a === b || !!a && !!b && a.blockIndex === b.blockIndex && a.offset === b.offset && (a.cellIndex ?? -1) === (b.cellIndex ?? -1);
@@ -4443,7 +5110,7 @@ function Editor({
4443
5110
  if (raf) cancelAnimationFrame(raf);
4444
5111
  };
4445
5112
  }, []);
4446
- useEffect9(() => {
5113
+ useEffect10(() => {
4447
5114
  const root = rootRef.current;
4448
5115
  if (!root) return;
4449
5116
  const clear = () => {
@@ -4478,7 +5145,7 @@ function Editor({
4478
5145
  window.removeEventListener("scroll", clear, true);
4479
5146
  };
4480
5147
  }, []);
4481
- useEffect9(() => {
5148
+ useEffect10(() => {
4482
5149
  const root = rootRef.current;
4483
5150
  if (!root) return;
4484
5151
  const handler = (e) => {
@@ -4591,7 +5258,7 @@ function Editor({
4591
5258
  root.addEventListener("beforeinput", handler);
4592
5259
  return () => root.removeEventListener("beforeinput", handler);
4593
5260
  }, []);
4594
- useEffect9(() => {
5261
+ useEffect10(() => {
4595
5262
  const root = rootRef.current;
4596
5263
  if (!root) return;
4597
5264
  const writeSlice = (e) => {
@@ -4684,7 +5351,7 @@ function Editor({
4684
5351
  root.removeEventListener("paste", onPaste);
4685
5352
  };
4686
5353
  }, []);
4687
- const onKeyDown = useCallback7((e) => {
5354
+ const onKeyDown = useCallback8((e) => {
4688
5355
  const ed = editorRef.current;
4689
5356
  const mod = e.metaKey || e.ctrlKey;
4690
5357
  if (e.key === "Tab") {
@@ -4769,10 +5436,10 @@ function Editor({
4769
5436
  });
4770
5437
  }
4771
5438
  }, []);
4772
- const onCompositionStart = useCallback7(() => {
5439
+ const onCompositionStart = useCallback8(() => {
4773
5440
  isComposingRef.current = true;
4774
5441
  }, []);
4775
- const onCompositionEnd = useCallback7((e) => {
5442
+ const onCompositionEnd = useCallback8((e) => {
4776
5443
  isComposingRef.current = false;
4777
5444
  if (e.data && e.data.length > 0) {
4778
5445
  insertText(ctxRef.current, e.data);
@@ -4820,7 +5487,7 @@ function Editor({
4820
5487
  geom.marginRight
4821
5488
  ]
4822
5489
  );
4823
- const body = /* @__PURE__ */ jsxs11(
5490
+ const body = /* @__PURE__ */ jsxs13(
4824
5491
  "div",
4825
5492
  {
4826
5493
  ref: rootRef,
@@ -4846,7 +5513,7 @@ function Editor({
4846
5513
  const pageInlineStyle = pi === 0 && geom.firstPageExtraTop ? {
4847
5514
  "--ed-page-margin-top": `${geom.marginTop + geom.firstPageExtraTop}px`
4848
5515
  } : void 0;
4849
- return /* @__PURE__ */ jsxs11(
5516
+ return /* @__PURE__ */ jsxs13(
4850
5517
  "div",
4851
5518
  {
4852
5519
  className: "ed-page",
@@ -4854,15 +5521,15 @@ function Editor({
4854
5521
  "data-page-total": ctx.pageCount,
4855
5522
  style: pageInlineStyle,
4856
5523
  children: [
4857
- renderPageHeader && /* @__PURE__ */ jsx12("div", { className: "ed-page-header", contentEditable: false, children: renderPageHeader(ctx) }),
4858
- /* @__PURE__ */ jsx12("div", { className: "ed-page-content", children: page.slots.map((slot) => renderSlot(slot, topLevels)) }),
4859
- renderPageFooter && /* @__PURE__ */ jsx12("div", { className: "ed-page-footer", contentEditable: false, children: renderPageFooter(ctx) })
5524
+ renderPageHeader && /* @__PURE__ */ jsx13("div", { className: "ed-page-header", contentEditable: false, children: renderPageHeader(ctx) }),
5525
+ /* @__PURE__ */ jsx13("div", { className: "ed-page-content", children: page.slots.map((slot) => renderSlot(slot, topLevels)) }),
5526
+ renderPageFooter && /* @__PURE__ */ jsx13("div", { className: "ed-page-footer", contentEditable: false, children: renderPageFooter(ctx) })
4860
5527
  ]
4861
5528
  },
4862
5529
  `page-${pi}`
4863
5530
  );
4864
5531
  }) : topLevels.map((t) => renderTopLevel(t)),
4865
- selectedEmbed && /* @__PURE__ */ jsx12(
5532
+ selectedEmbed && /* @__PURE__ */ jsx13(
4866
5533
  ImageResizeOverlay,
4867
5534
  {
4868
5535
  rootRef,
@@ -4894,7 +5561,7 @@ function Editor({
4894
5561
  )
4895
5562
  }
4896
5563
  ),
4897
- hoveredBehind && !(selectedEmbed && selectedEmbed.blockIndex === hoveredBehind.blockIndex && selectedEmbed.offset === hoveredBehind.offset && (selectedEmbed.cellIndex ?? -1) === (hoveredBehind.cellIndex ?? -1)) && /* @__PURE__ */ jsx12(
5564
+ hoveredBehind && !(selectedEmbed && selectedEmbed.blockIndex === hoveredBehind.blockIndex && selectedEmbed.offset === hoveredBehind.offset && (selectedEmbed.cellIndex ?? -1) === (hoveredBehind.cellIndex ?? -1)) && /* @__PURE__ */ jsx13(
4898
5565
  BehindImageSelectAffordance,
4899
5566
  {
4900
5567
  rootRef,
@@ -4915,8 +5582,8 @@ function Editor({
4915
5582
  })
4916
5583
  }
4917
5584
  ),
4918
- hoveredLink && hoveredLink.href && /* @__PURE__ */ jsx12(LinkHoverTooltip, { href: hoveredLink.href, rect: hoveredLink.rect }),
4919
- awareness && /* @__PURE__ */ jsx12(
5585
+ hoveredLink && hoveredLink.href && /* @__PURE__ */ jsx13(LinkHoverTooltip, { href: hoveredLink.href, rect: hoveredLink.rect }),
5586
+ awareness && /* @__PURE__ */ jsx13(
4920
5587
  RemoteCursorsOverlay,
4921
5588
  {
4922
5589
  rootRef,
@@ -4928,7 +5595,7 @@ function Editor({
4928
5595
  ]
4929
5596
  }
4930
5597
  );
4931
- return /* @__PURE__ */ jsx12(EditorProvider, { editor, children: body });
5598
+ return /* @__PURE__ */ jsx13(EditorProvider, { editor, children: body });
4932
5599
  }
4933
5600
  function groupTopLevels(snapshot) {
4934
5601
  const out = [];
@@ -4982,7 +5649,7 @@ function renderSlot(slot, topLevels) {
4982
5649
  start: slot.fragment.start,
4983
5650
  end: slot.fragment.end
4984
5651
  };
4985
- return /* @__PURE__ */ jsx12(
5652
+ return /* @__PURE__ */ jsx13(
4986
5653
  NodeView,
4987
5654
  {
4988
5655
  block: top.block,
@@ -4993,7 +5660,7 @@ function renderSlot(slot, topLevels) {
4993
5660
  );
4994
5661
  }
4995
5662
  if (slot.tableFragment && top.kind === "block" && top.block.type === "table") {
4996
- return /* @__PURE__ */ jsx12(
5663
+ return /* @__PURE__ */ jsx13(
4997
5664
  NodeView,
4998
5665
  {
4999
5666
  block: top.block,
@@ -5013,7 +5680,7 @@ function renderTopLevel(top) {
5013
5680
  const tree = buildListTree(top.items);
5014
5681
  return renderListTree(tree, top, top.ordinalStart, `list-${top.key}`);
5015
5682
  }
5016
- return /* @__PURE__ */ jsx12(NodeView, { block: top.block, index: top.blockIndex }, top.key);
5683
+ return /* @__PURE__ */ jsx13(NodeView, { block: top.block, index: top.blockIndex }, top.key);
5017
5684
  }
5018
5685
  function renderListFragment(top, frag) {
5019
5686
  const ranges = topLevelItemRanges(top.items);
@@ -5055,9 +5722,9 @@ function buildListTree(items) {
5055
5722
  function renderListTree(tree, top, start, key) {
5056
5723
  const className = `ed-list ed-list-${top.listKind}`;
5057
5724
  const style = top.listStyle ? { listStyleType: top.listStyle } : void 0;
5058
- const items = tree.map((node) => /* @__PURE__ */ jsx12(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));
5725
+ const items = tree.map((node) => /* @__PURE__ */ jsx13(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));
5059
5726
  if (top.listKind === "ordered") {
5060
- return /* @__PURE__ */ jsx12(
5727
+ return /* @__PURE__ */ jsx13(
5061
5728
  "ol",
5062
5729
  {
5063
5730
  className,
@@ -5069,12 +5736,12 @@ function renderListTree(tree, top, start, key) {
5069
5736
  key
5070
5737
  );
5071
5738
  }
5072
- return /* @__PURE__ */ jsx12("ul", { className, "data-list-kind": "bullet", style, children: items }, key);
5739
+ return /* @__PURE__ */ jsx13("ul", { className, "data-list-kind": "bullet", style, children: items }, key);
5073
5740
  }
5074
5741
  function renderNestedListTree(tree, key) {
5075
5742
  const kind = tree[0]?.entry.block.attrs.listKind === "ordered" ? "ordered" : "bullet";
5076
5743
  const Tag = kind === "ordered" ? "ol" : "ul";
5077
- return /* @__PURE__ */ jsx12(Tag, { className: `ed-list ed-list-${kind}`, "data-list-kind": kind, children: tree.map((node) => /* @__PURE__ */ jsx12(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);
5744
+ return /* @__PURE__ */ jsx13(Tag, { className: `ed-list ed-list-${kind}`, "data-list-kind": kind, children: tree.map((node) => /* @__PURE__ */ jsx13(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);
5078
5745
  }
5079
5746
  function clampListLevel2(l) {
5080
5747
  if (typeof l !== "number" || !Number.isFinite(l)) return 0;
@@ -5103,13 +5770,80 @@ function caretRangeFromPoint(x, y) {
5103
5770
 
5104
5771
  // src/Toolbar.tsx
5105
5772
  import {
5106
- useCallback as useCallback8,
5107
- useEffect as useEffect10,
5108
- useRef as useRef12,
5109
- useState as useState11
5773
+ useCallback as useCallback9,
5774
+ useEffect as useEffect11,
5775
+ useRef as useRef13,
5776
+ useState as useState12
5110
5777
  } from "react";
5111
- import { ANSWER_LINE_MAX, TABLE_BORDER_COLOR } from "@sofereditor/core";
5112
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
5778
+ import { ANSWER_LINE_MAX, isFormulaEmbed as isFormulaEmbed3, TABLE_BORDER_COLOR } from "@sofereditor/core";
5779
+
5780
+ // src/TableBorderPanel.tsx
5781
+ import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
5782
+ var BORDER_PRESETS = [
5783
+ { key: "all", label: "Todas", glyph: "\u229E" },
5784
+ { key: "outer", label: "S\xF3 externas", glyph: "\u25A1" },
5785
+ { key: "horizontal", label: "S\xF3 horizontais", glyph: "\u25A4" },
5786
+ { key: "vertical", label: "S\xF3 verticais", glyph: "\u25A5" },
5787
+ { key: "none", label: "Nenhuma", glyph: "\u2B1A" }
5788
+ ];
5789
+ var BORDER_MENU_GLYPH = "\u229E";
5790
+ function TableBorderPanel({
5791
+ preset,
5792
+ color,
5793
+ onPreset,
5794
+ onColor,
5795
+ onResetColor
5796
+ }) {
5797
+ return /* @__PURE__ */ jsxs14("div", { className: "ed-border-panel", children: [
5798
+ /* @__PURE__ */ jsx14("div", { className: "ed-border-presets", children: BORDER_PRESETS.map((p) => /* @__PURE__ */ jsxs14(
5799
+ "button",
5800
+ {
5801
+ type: "button",
5802
+ className: "ed-border-preset",
5803
+ "aria-pressed": preset === p.key,
5804
+ title: p.label,
5805
+ onClick: (e) => {
5806
+ e.preventDefault();
5807
+ onPreset(p.key);
5808
+ },
5809
+ children: [
5810
+ /* @__PURE__ */ jsx14("span", { className: "ed-border-glyph", "aria-hidden": true, children: p.glyph }),
5811
+ p.label
5812
+ ]
5813
+ },
5814
+ p.key
5815
+ )) }),
5816
+ /* @__PURE__ */ jsx14("hr", {}),
5817
+ /* @__PURE__ */ jsxs14("label", { className: "ed-toolbar-label ed-border-color", children: [
5818
+ /* @__PURE__ */ jsx14("span", { className: "ed-toolbar-swatch", "aria-hidden": true, style: { background: color } }),
5819
+ "Cor da linha",
5820
+ /* @__PURE__ */ jsx14(
5821
+ "input",
5822
+ {
5823
+ type: "color",
5824
+ value: color,
5825
+ onChange: (e) => onColor(e.target.value),
5826
+ "aria-label": "Cor da linha da borda"
5827
+ }
5828
+ )
5829
+ ] }),
5830
+ /* @__PURE__ */ jsx14(
5831
+ "button",
5832
+ {
5833
+ type: "button",
5834
+ className: "ed-border-reset",
5835
+ onClick: (e) => {
5836
+ e.preventDefault();
5837
+ onResetColor();
5838
+ },
5839
+ children: "Padr\xE3o"
5840
+ }
5841
+ )
5842
+ ] });
5843
+ }
5844
+
5845
+ // src/Toolbar.tsx
5846
+ import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
5113
5847
  var FONT_FAMILIES = ["Arial"];
5114
5848
  var FONT_SIZES = ["8pt", "10pt", "11pt", "12pt", "14pt", "16pt", "18pt", "24pt", "32pt", "48pt"];
5115
5849
  var BLOCK_OPTIONS = [
@@ -5213,14 +5947,14 @@ function Toolbar({ className }) {
5213
5947
  }
5214
5948
  setAlign(value);
5215
5949
  };
5216
- const onInsertImageClick = useCallback8(
5950
+ const onInsertImageClick = useCallback9(
5217
5951
  (e) => {
5218
5952
  e.preventDefault();
5219
5953
  imageInputRef.current?.click();
5220
5954
  },
5221
5955
  []
5222
5956
  );
5223
- const onImageInputChange = useCallback8(
5957
+ const onImageInputChange = useCallback9(
5224
5958
  (e) => {
5225
5959
  const file = e.target.files?.[0];
5226
5960
  if (file) void editor.insertImageFromFile(file);
@@ -5228,14 +5962,14 @@ function Toolbar({ className }) {
5228
5962
  },
5229
5963
  [editor]
5230
5964
  );
5231
- const imageInputRef = useRef12(null);
5965
+ const imageInputRef = useRef13(null);
5232
5966
  const onToggleDir = (e) => {
5233
5967
  e.preventDefault();
5234
5968
  const next = blockDir === "rtl" ? "ltr" : "rtl";
5235
5969
  setBlockAttr("dir", next);
5236
5970
  };
5237
5971
  const linkActive = isMarkActive("link");
5238
- const onLinkClick = useCallback8(
5972
+ const onLinkClick = useCallback9(
5239
5973
  (e) => {
5240
5974
  e.preventDefault();
5241
5975
  const currentHref = active.link && typeof active.link === "object" && "href" in active.link ? active.link.href : "";
@@ -5266,7 +6000,7 @@ function Toolbar({ className }) {
5266
6000
  sel.cellIndex
5267
6001
  );
5268
6002
  };
5269
- return /* @__PURE__ */ jsxs12(
6003
+ return /* @__PURE__ */ jsxs15(
5270
6004
  "div",
5271
6005
  {
5272
6006
  className: className ?? "ed-toolbar",
@@ -5274,7 +6008,7 @@ function Toolbar({ className }) {
5274
6008
  "aria-label": "Editor toolbar",
5275
6009
  onMouseDown: stop,
5276
6010
  children: [
5277
- /* @__PURE__ */ jsx13(Group, { children: /* @__PURE__ */ jsxs12(
6011
+ /* @__PURE__ */ jsx15(Group, { children: /* @__PURE__ */ jsxs15(
5278
6012
  "select",
5279
6013
  {
5280
6014
  className: "ed-toolbar-select",
@@ -5283,23 +6017,23 @@ function Toolbar({ className }) {
5283
6017
  onMouseDown: stop,
5284
6018
  "aria-label": "Tipo de bloco",
5285
6019
  children: [
5286
- blockValue === "" && /* @__PURE__ */ jsx13("option", { value: "", children: "\u2014 (misto)" }),
5287
- BLOCK_OPTIONS.map((o) => /* @__PURE__ */ jsx13("option", { value: o.value, children: o.label }, o.value))
6020
+ blockValue === "" && /* @__PURE__ */ jsx15("option", { value: "", children: "\u2014 (misto)" }),
6021
+ BLOCK_OPTIONS.map((o) => /* @__PURE__ */ jsx15("option", { value: o.value, children: o.label }, o.value))
5288
6022
  ]
5289
6023
  }
5290
6024
  ) }),
5291
- /* @__PURE__ */ jsxs12(Group, { children: [
5292
- /* @__PURE__ */ jsx13(MarkButton, { title: "Negrito (\u2318B)", pressed: isMarkActive("bold"), onClick: onToggle("bold"), children: /* @__PURE__ */ jsx13("strong", { children: "B" }) }),
5293
- /* @__PURE__ */ jsx13(MarkButton, { title: "It\xE1lico (\u2318I)", pressed: isMarkActive("italic"), onClick: onToggle("italic"), children: /* @__PURE__ */ jsx13("em", { children: "I" }) }),
5294
- /* @__PURE__ */ jsx13(MarkButton, { title: "Sublinhado (\u2318U)", pressed: isMarkActive("underline"), onClick: onToggle("underline"), children: /* @__PURE__ */ jsx13("u", { children: "U" }) }),
5295
- /* @__PURE__ */ jsx13(MarkButton, { title: "Tachado (\u2318\u21E7X)", pressed: isMarkActive("strike"), onClick: onToggle("strike"), children: /* @__PURE__ */ jsx13("s", { children: "S" }) })
6025
+ /* @__PURE__ */ jsxs15(Group, { children: [
6026
+ /* @__PURE__ */ jsx15(MarkButton, { title: "Negrito (\u2318B)", pressed: isMarkActive("bold"), onClick: onToggle("bold"), children: /* @__PURE__ */ jsx15("strong", { children: "B" }) }),
6027
+ /* @__PURE__ */ jsx15(MarkButton, { title: "It\xE1lico (\u2318I)", pressed: isMarkActive("italic"), onClick: onToggle("italic"), children: /* @__PURE__ */ jsx15("em", { children: "I" }) }),
6028
+ /* @__PURE__ */ jsx15(MarkButton, { title: "Sublinhado (\u2318U)", pressed: isMarkActive("underline"), onClick: onToggle("underline"), children: /* @__PURE__ */ jsx15("u", { children: "U" }) }),
6029
+ /* @__PURE__ */ jsx15(MarkButton, { title: "Tachado (\u2318\u21E7X)", pressed: isMarkActive("strike"), onClick: onToggle("strike"), children: /* @__PURE__ */ jsx15("s", { children: "S" }) })
5296
6030
  ] }),
5297
- /* @__PURE__ */ jsxs12(Group, { children: [
5298
- /* @__PURE__ */ jsxs12("label", { className: "ed-toolbar-label", children: [
5299
- /* @__PURE__ */ jsx13("span", { className: "ed-toolbar-swatch", "aria-hidden": true, style: { background: colorValue } }),
5300
- /* @__PURE__ */ jsx13("input", { type: "color", value: colorValue, onChange: onColorChange, onMouseDown: stop, "aria-label": "Cor do texto" })
6031
+ /* @__PURE__ */ jsxs15(Group, { children: [
6032
+ /* @__PURE__ */ jsxs15("label", { className: "ed-toolbar-label", children: [
6033
+ /* @__PURE__ */ jsx15("span", { className: "ed-toolbar-swatch", "aria-hidden": true, style: { background: colorValue } }),
6034
+ /* @__PURE__ */ jsx15("input", { type: "color", value: colorValue, onChange: onColorChange, onMouseDown: stop, "aria-label": "Cor do texto" })
5301
6035
  ] }),
5302
- /* @__PURE__ */ jsx13(
6036
+ /* @__PURE__ */ jsx15(
5303
6037
  "button",
5304
6038
  {
5305
6039
  type: "button",
@@ -5313,8 +6047,8 @@ function Toolbar({ className }) {
5313
6047
  children: "\u232B"
5314
6048
  }
5315
6049
  ),
5316
- /* @__PURE__ */ jsxs12("label", { className: "ed-toolbar-label", title: "Marca-texto", children: [
5317
- /* @__PURE__ */ jsx13(
6050
+ /* @__PURE__ */ jsxs15("label", { className: "ed-toolbar-label", title: "Marca-texto", children: [
6051
+ /* @__PURE__ */ jsx15(
5318
6052
  "span",
5319
6053
  {
5320
6054
  className: "ed-toolbar-swatch ed-toolbar-swatch--highlight",
@@ -5322,7 +6056,7 @@ function Toolbar({ className }) {
5322
6056
  style: { background: highlightValue }
5323
6057
  }
5324
6058
  ),
5325
- /* @__PURE__ */ jsx13(
6059
+ /* @__PURE__ */ jsx15(
5326
6060
  "input",
5327
6061
  {
5328
6062
  type: "color",
@@ -5333,7 +6067,7 @@ function Toolbar({ className }) {
5333
6067
  }
5334
6068
  )
5335
6069
  ] }),
5336
- /* @__PURE__ */ jsx13(
6070
+ /* @__PURE__ */ jsx15(
5337
6071
  "button",
5338
6072
  {
5339
6073
  type: "button",
@@ -5348,8 +6082,8 @@ function Toolbar({ className }) {
5348
6082
  }
5349
6083
  )
5350
6084
  ] }),
5351
- /* @__PURE__ */ jsxs12(Group, { children: [
5352
- /* @__PURE__ */ jsxs12(
6085
+ /* @__PURE__ */ jsxs15(Group, { children: [
6086
+ /* @__PURE__ */ jsxs15(
5353
6087
  "select",
5354
6088
  {
5355
6089
  className: "ed-toolbar-select",
@@ -5358,12 +6092,12 @@ function Toolbar({ className }) {
5358
6092
  onMouseDown: stop,
5359
6093
  "aria-label": "Fam\xEDlia da fonte",
5360
6094
  children: [
5361
- /* @__PURE__ */ jsx13("option", { value: "", children: "Fonte\u2026" }),
5362
- FONT_FAMILIES.map((f) => /* @__PURE__ */ jsx13("option", { value: f, children: f }, f))
6095
+ /* @__PURE__ */ jsx15("option", { value: "", children: "Fonte\u2026" }),
6096
+ FONT_FAMILIES.map((f) => /* @__PURE__ */ jsx15("option", { value: f, children: f }, f))
5363
6097
  ]
5364
6098
  }
5365
6099
  ),
5366
- /* @__PURE__ */ jsxs12(
6100
+ /* @__PURE__ */ jsxs15(
5367
6101
  "select",
5368
6102
  {
5369
6103
  className: "ed-toolbar-select",
@@ -5372,13 +6106,13 @@ function Toolbar({ className }) {
5372
6106
  onMouseDown: stop,
5373
6107
  "aria-label": "Tamanho da fonte",
5374
6108
  children: [
5375
- /* @__PURE__ */ jsx13("option", { value: "", children: "Tamanho\u2026" }),
5376
- FONT_SIZES.map((s) => /* @__PURE__ */ jsx13("option", { value: s, children: s }, s))
6109
+ /* @__PURE__ */ jsx15("option", { value: "", children: "Tamanho\u2026" }),
6110
+ FONT_SIZES.map((s) => /* @__PURE__ */ jsx15("option", { value: s, children: s }, s))
5377
6111
  ]
5378
6112
  }
5379
6113
  )
5380
6114
  ] }),
5381
- /* @__PURE__ */ jsx13(Group, { children: ALIGN_OPTIONS.map((a) => /* @__PURE__ */ jsx13(
6115
+ /* @__PURE__ */ jsx15(Group, { children: ALIGN_OPTIONS.map((a) => /* @__PURE__ */ jsx15(
5382
6116
  "button",
5383
6117
  {
5384
6118
  type: "button",
@@ -5391,7 +6125,7 @@ function Toolbar({ className }) {
5391
6125
  },
5392
6126
  a.value
5393
6127
  )) }),
5394
- /* @__PURE__ */ jsx13(Group, { children: /* @__PURE__ */ jsx13(
6128
+ /* @__PURE__ */ jsx15(Group, { children: /* @__PURE__ */ jsx15(
5395
6129
  "button",
5396
6130
  {
5397
6131
  type: "button",
@@ -5403,8 +6137,8 @@ function Toolbar({ className }) {
5403
6137
  children: blockDir === "rtl" ? "RTL" : "LTR"
5404
6138
  }
5405
6139
  ) }),
5406
- /* @__PURE__ */ jsxs12(Group, { children: [
5407
- /* @__PURE__ */ jsx13(
6140
+ /* @__PURE__ */ jsxs15(Group, { children: [
6141
+ /* @__PURE__ */ jsx15(
5408
6142
  "button",
5409
6143
  {
5410
6144
  type: "button",
@@ -5419,7 +6153,7 @@ function Toolbar({ className }) {
5419
6153
  children: "\u2022"
5420
6154
  }
5421
6155
  ),
5422
- /* @__PURE__ */ jsx13(
6156
+ /* @__PURE__ */ jsx15(
5423
6157
  "button",
5424
6158
  {
5425
6159
  type: "button",
@@ -5434,7 +6168,7 @@ function Toolbar({ className }) {
5434
6168
  children: "1."
5435
6169
  }
5436
6170
  ),
5437
- /* @__PURE__ */ jsx13(
6171
+ /* @__PURE__ */ jsx15(
5438
6172
  "button",
5439
6173
  {
5440
6174
  type: "button",
@@ -5448,7 +6182,7 @@ function Toolbar({ className }) {
5448
6182
  children: "\u21E4"
5449
6183
  }
5450
6184
  ),
5451
- /* @__PURE__ */ jsx13(
6185
+ /* @__PURE__ */ jsx15(
5452
6186
  "button",
5453
6187
  {
5454
6188
  type: "button",
@@ -5463,7 +6197,7 @@ function Toolbar({ className }) {
5463
6197
  }
5464
6198
  )
5465
6199
  ] }),
5466
- /* @__PURE__ */ jsx13(Group, { children: /* @__PURE__ */ jsx13(
6200
+ /* @__PURE__ */ jsx15(Group, { children: /* @__PURE__ */ jsx15(
5467
6201
  "button",
5468
6202
  {
5469
6203
  type: "button",
@@ -5475,12 +6209,12 @@ function Toolbar({ className }) {
5475
6209
  children: "\u{1F517}"
5476
6210
  }
5477
6211
  ) }),
5478
- /* @__PURE__ */ jsxs12(Group, { children: [
5479
- /* @__PURE__ */ jsx13(TableMenu, {}),
5480
- /* @__PURE__ */ jsx13(AnswerLinesMenu, {})
6212
+ /* @__PURE__ */ jsxs15(Group, { children: [
6213
+ /* @__PURE__ */ jsx15(TableMenu, {}),
6214
+ /* @__PURE__ */ jsx15(AnswerLinesMenu, {})
5481
6215
  ] }),
5482
- /* @__PURE__ */ jsxs12(Group, { children: [
5483
- /* @__PURE__ */ jsx13(
6216
+ /* @__PURE__ */ jsxs15(Group, { children: [
6217
+ /* @__PURE__ */ jsx15(
5484
6218
  "button",
5485
6219
  {
5486
6220
  type: "button",
@@ -5491,7 +6225,7 @@ function Toolbar({ className }) {
5491
6225
  children: "\u{1F5BC}"
5492
6226
  }
5493
6227
  ),
5494
- /* @__PURE__ */ jsx13(
6228
+ /* @__PURE__ */ jsx15(
5495
6229
  "input",
5496
6230
  {
5497
6231
  ref: imageInputRef,
@@ -5500,10 +6234,26 @@ function Toolbar({ className }) {
5500
6234
  hidden: true,
5501
6235
  onChange: onImageInputChange
5502
6236
  }
6237
+ ),
6238
+ /* @__PURE__ */ jsx15(
6239
+ "button",
6240
+ {
6241
+ type: "button",
6242
+ className: "ed-toolbar-btn",
6243
+ title: "Inserir f\xF3rmula",
6244
+ onMouseDown: stop,
6245
+ onClick: (e) => {
6246
+ e.preventDefault();
6247
+ void editor.requestFormula().then((r) => r ? editor.insertFormula(r.latex, r.display) : void 0).catch((err) => {
6248
+ console.error("Falha ao inserir f\xF3rmula:", err);
6249
+ });
6250
+ },
6251
+ children: "\u221Ax"
6252
+ }
5503
6253
  )
5504
6254
  ] }),
5505
- selectedEmbed && /* @__PURE__ */ jsxs12(Group, { children: [
5506
- IMAGE_LAYOUT_OPTIONS.map((opt) => /* @__PURE__ */ jsx13(
6255
+ selectedEmbed && /* @__PURE__ */ jsxs15(Group, { children: [
6256
+ IMAGE_LAYOUT_OPTIONS.map((opt) => /* @__PURE__ */ jsx15(
5507
6257
  "button",
5508
6258
  {
5509
6259
  type: "button",
@@ -5516,7 +6266,25 @@ function Toolbar({ className }) {
5516
6266
  },
5517
6267
  opt.value
5518
6268
  )),
5519
- /* @__PURE__ */ jsx13(
6269
+ isFormulaEmbed3(selectedEmbed.embed) ? /* @__PURE__ */ jsx15(
6270
+ "button",
6271
+ {
6272
+ type: "button",
6273
+ className: "ed-toolbar-btn",
6274
+ title: "Editar f\xF3rmula",
6275
+ onMouseDown: stop,
6276
+ onClick: (e) => {
6277
+ e.preventDefault();
6278
+ if (!isFormulaEmbed3(selectedEmbed.embed)) return;
6279
+ const f = selectedEmbed.embed.formula;
6280
+ void editor.requestFormula(f.latex, f.display).then((r) => {
6281
+ if (!r) return;
6282
+ void editor.insertFormula(r.latex, r.display);
6283
+ });
6284
+ },
6285
+ children: "Editar f\xF3rmula"
6286
+ }
6287
+ ) : /* @__PURE__ */ jsx15(
5520
6288
  "button",
5521
6289
  {
5522
6290
  type: "button",
@@ -5546,7 +6314,7 @@ function Toolbar({ className }) {
5546
6314
  }
5547
6315
  )
5548
6316
  ] }),
5549
- /* @__PURE__ */ jsx13(Group, { children: /* @__PURE__ */ jsx13(
6317
+ /* @__PURE__ */ jsx15(Group, { children: /* @__PURE__ */ jsx15(
5550
6318
  "button",
5551
6319
  {
5552
6320
  type: "button",
@@ -5566,11 +6334,11 @@ function Toolbar({ className }) {
5566
6334
  }
5567
6335
  function AnswerLinesMenu() {
5568
6336
  const editor = useEditorContext();
5569
- const [open, setOpen] = useState11(false);
5570
- const [count, setCount] = useState11(5);
5571
- const [spacing, setSpacing] = useState11(1.5);
5572
- const rootRef = useRef12(null);
5573
- useEffect10(() => {
6337
+ const [open, setOpen] = useState12(false);
6338
+ const [count, setCount] = useState12(5);
6339
+ const [spacing, setSpacing] = useState12(1.5);
6340
+ const rootRef = useRef13(null);
6341
+ useEffect11(() => {
5574
6342
  if (!open) return;
5575
6343
  const onDown = (e) => {
5576
6344
  if (!rootRef.current) return;
@@ -5581,8 +6349,8 @@ function AnswerLinesMenu() {
5581
6349
  return () => document.removeEventListener("mousedown", onDown);
5582
6350
  }, [open]);
5583
6351
  const clamped = Math.max(1, Math.min(ANSWER_LINE_MAX, Math.trunc(count) || 1));
5584
- return /* @__PURE__ */ jsxs12("div", { ref: rootRef, className: "ed-toolbar-tablemenu", children: [
5585
- /* @__PURE__ */ jsx13(
6352
+ return /* @__PURE__ */ jsxs15("div", { ref: rootRef, className: "ed-toolbar-tablemenu", children: [
6353
+ /* @__PURE__ */ jsx15(
5586
6354
  "button",
5587
6355
  {
5588
6356
  type: "button",
@@ -5597,7 +6365,7 @@ function AnswerLinesMenu() {
5597
6365
  children: "\u2630"
5598
6366
  }
5599
6367
  ),
5600
- open && /* @__PURE__ */ jsxs12(
6368
+ open && /* @__PURE__ */ jsxs15(
5601
6369
  "div",
5602
6370
  {
5603
6371
  className: "ed-table-popover ed-answerlines-popover",
@@ -5606,9 +6374,9 @@ function AnswerLinesMenu() {
5606
6374
  if (!keepsOwnMouseDown(e.target)) e.preventDefault();
5607
6375
  },
5608
6376
  children: [
5609
- /* @__PURE__ */ jsxs12("label", { className: "ed-toolbar-label", children: [
6377
+ /* @__PURE__ */ jsxs15("label", { className: "ed-toolbar-label", children: [
5610
6378
  "Quantidade",
5611
- /* @__PURE__ */ jsx13(
6379
+ /* @__PURE__ */ jsx15(
5612
6380
  "input",
5613
6381
  {
5614
6382
  type: "number",
@@ -5620,23 +6388,23 @@ function AnswerLinesMenu() {
5620
6388
  }
5621
6389
  )
5622
6390
  ] }),
5623
- /* @__PURE__ */ jsxs12("label", { className: "ed-toolbar-label", children: [
6391
+ /* @__PURE__ */ jsxs15("label", { className: "ed-toolbar-label", children: [
5624
6392
  "Entrelinha",
5625
- /* @__PURE__ */ jsxs12(
6393
+ /* @__PURE__ */ jsxs15(
5626
6394
  "select",
5627
6395
  {
5628
6396
  value: String(spacing),
5629
6397
  onChange: (e) => setSpacing(Number(e.target.value)),
5630
6398
  "aria-label": "Entrelinha",
5631
6399
  children: [
5632
- /* @__PURE__ */ jsx13("option", { value: "1", children: "Simples" }),
5633
- /* @__PURE__ */ jsx13("option", { value: "1.5", children: "1,5" }),
5634
- /* @__PURE__ */ jsx13("option", { value: "2", children: "Duplo" })
6400
+ /* @__PURE__ */ jsx15("option", { value: "1", children: "Simples" }),
6401
+ /* @__PURE__ */ jsx15("option", { value: "1.5", children: "1,5" }),
6402
+ /* @__PURE__ */ jsx15("option", { value: "2", children: "Duplo" })
5635
6403
  ]
5636
6404
  }
5637
6405
  )
5638
6406
  ] }),
5639
- /* @__PURE__ */ jsxs12(
6407
+ /* @__PURE__ */ jsxs15(
5640
6408
  "button",
5641
6409
  {
5642
6410
  type: "button",
@@ -5660,9 +6428,10 @@ function AnswerLinesMenu() {
5660
6428
  function TableMenu() {
5661
6429
  const editor = useEditorContext();
5662
6430
  const inTable = editor.isInTable();
5663
- const [open, setOpen] = useState11(false);
5664
- const rootRef = useRef12(null);
5665
- useEffect10(() => {
6431
+ const [open, setOpen] = useState12(false);
6432
+ const [bordersOpen, setBordersOpen] = useState12(false);
6433
+ const rootRef = useRef13(null);
6434
+ useEffect11(() => {
5666
6435
  if (!open) return;
5667
6436
  const onDown = (e) => {
5668
6437
  if (!rootRef.current) return;
@@ -5672,8 +6441,11 @@ function TableMenu() {
5672
6441
  document.addEventListener("mousedown", onDown);
5673
6442
  return () => document.removeEventListener("mousedown", onDown);
5674
6443
  }, [open]);
5675
- return /* @__PURE__ */ jsxs12("div", { ref: rootRef, className: "ed-toolbar-tablemenu", children: [
5676
- /* @__PURE__ */ jsx13(
6444
+ useEffect11(() => {
6445
+ if (!open) setBordersOpen(false);
6446
+ }, [open]);
6447
+ return /* @__PURE__ */ jsxs15("div", { ref: rootRef, className: "ed-toolbar-tablemenu", children: [
6448
+ /* @__PURE__ */ jsx15(
5677
6449
  "button",
5678
6450
  {
5679
6451
  type: "button",
@@ -5688,7 +6460,7 @@ function TableMenu() {
5688
6460
  children: "\u25A6"
5689
6461
  }
5690
6462
  ),
5691
- open && /* @__PURE__ */ jsxs12(
6463
+ open && /* @__PURE__ */ jsxs15(
5692
6464
  "div",
5693
6465
  {
5694
6466
  className: "ed-table-popover",
@@ -5697,7 +6469,7 @@ function TableMenu() {
5697
6469
  if (!keepsOwnMouseDown(e.target)) e.preventDefault();
5698
6470
  },
5699
6471
  children: [
5700
- /* @__PURE__ */ jsx13(
6472
+ /* @__PURE__ */ jsx15(
5701
6473
  TableSizePicker,
5702
6474
  {
5703
6475
  onPick: (rows, cols) => {
@@ -5706,34 +6478,34 @@ function TableMenu() {
5706
6478
  }
5707
6479
  }
5708
6480
  ),
5709
- inTable && /* @__PURE__ */ jsxs12("div", { className: "ed-table-actions", children: [
5710
- /* @__PURE__ */ jsx13("hr", {}),
5711
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => {
6481
+ inTable && /* @__PURE__ */ jsxs15("div", { className: "ed-table-actions", children: [
6482
+ /* @__PURE__ */ jsx15("hr", {}),
6483
+ /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => {
5712
6484
  setOpen(false);
5713
6485
  editor.insertRowAbove();
5714
6486
  }, children: "Inserir linha acima" }),
5715
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => {
6487
+ /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => {
5716
6488
  setOpen(false);
5717
6489
  editor.insertRowBelow();
5718
6490
  }, children: "Inserir linha abaixo" }),
5719
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => {
6491
+ /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => {
5720
6492
  setOpen(false);
5721
6493
  editor.insertColumnLeft();
5722
6494
  }, children: "Inserir coluna \xE0 esquerda" }),
5723
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => {
6495
+ /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => {
5724
6496
  setOpen(false);
5725
6497
  editor.insertColumnRight();
5726
6498
  }, children: "Inserir coluna \xE0 direita" }),
5727
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => {
6499
+ /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => {
5728
6500
  setOpen(false);
5729
6501
  editor.deleteCurrentRow();
5730
6502
  }, children: "Excluir linha" }),
5731
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => {
6503
+ /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => {
5732
6504
  setOpen(false);
5733
6505
  editor.deleteCurrentColumn();
5734
6506
  }, children: "Excluir coluna" }),
5735
- /* @__PURE__ */ jsx13("hr", {}),
5736
- editor.hasTableRectSelection() && /* @__PURE__ */ jsx13(
6507
+ /* @__PURE__ */ jsx15("hr", {}),
6508
+ editor.hasTableRectSelection() && /* @__PURE__ */ jsx15(
5737
6509
  "button",
5738
6510
  {
5739
6511
  type: "button",
@@ -5744,21 +6516,21 @@ function TableMenu() {
5744
6516
  children: "Mesclar c\xE9lulas selecionadas"
5745
6517
  }
5746
6518
  ),
5747
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => {
6519
+ /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => {
5748
6520
  setOpen(false);
5749
6521
  editor.mergeRight();
5750
6522
  }, children: "Mesclar com c\xE9lula \xE0 direita" }),
5751
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => {
6523
+ /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => {
5752
6524
  setOpen(false);
5753
6525
  editor.mergeDown();
5754
6526
  }, children: "Mesclar com c\xE9lula abaixo" }),
5755
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => {
6527
+ /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => {
5756
6528
  setOpen(false);
5757
6529
  editor.splitCell();
5758
6530
  }, children: "Dividir c\xE9lulas mescladas" }),
5759
- /* @__PURE__ */ jsx13("hr", {}),
5760
- /* @__PURE__ */ jsxs12("label", { className: "ed-toolbar-label ed-table-bgcolor", children: [
5761
- /* @__PURE__ */ jsx13(
6531
+ /* @__PURE__ */ jsx15("hr", {}),
6532
+ /* @__PURE__ */ jsxs15("label", { className: "ed-toolbar-label ed-table-bgcolor", children: [
6533
+ /* @__PURE__ */ jsx15(
5762
6534
  "span",
5763
6535
  {
5764
6536
  className: "ed-toolbar-swatch",
@@ -5767,7 +6539,7 @@ function TableMenu() {
5767
6539
  }
5768
6540
  ),
5769
6541
  "Cor de fundo da c\xE9lula",
5770
- /* @__PURE__ */ jsx13(
6542
+ /* @__PURE__ */ jsx15(
5771
6543
  "input",
5772
6544
  {
5773
6545
  type: "color",
@@ -5777,62 +6549,39 @@ function TableMenu() {
5777
6549
  }
5778
6550
  )
5779
6551
  ] }),
5780
- /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => {
6552
+ /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => {
5781
6553
  setOpen(false);
5782
6554
  editor.setCellBackground(null);
5783
6555
  }, children: "Remover cor de fundo" }),
5784
- /* @__PURE__ */ jsx13("hr", {}),
5785
- /* @__PURE__ */ jsxs12("label", { className: "ed-toolbar-label", children: [
5786
- "Bordas",
5787
- /* @__PURE__ */ jsxs12(
5788
- "select",
5789
- {
5790
- value: editor.getTableBorderPreset(),
5791
- onChange: (e) => editor.setTableBorderPreset(e.target.value),
5792
- "aria-label": "Bordas da tabela",
5793
- children: [
5794
- /* @__PURE__ */ jsx13("option", { value: "all", children: "Todas" }),
5795
- /* @__PURE__ */ jsx13("option", { value: "outer", children: "S\xF3 externas" }),
5796
- /* @__PURE__ */ jsx13("option", { value: "horizontal", children: "S\xF3 horizontais" }),
5797
- /* @__PURE__ */ jsx13("option", { value: "vertical", children: "S\xF3 verticais" }),
5798
- /* @__PURE__ */ jsx13("option", { value: "none", children: "Nenhuma" })
5799
- ]
5800
- }
5801
- )
5802
- ] }),
5803
- /* @__PURE__ */ jsxs12("label", { className: "ed-toolbar-label ed-table-bgcolor", children: [
5804
- /* @__PURE__ */ jsx13(
5805
- "span",
5806
- {
5807
- className: "ed-toolbar-swatch",
5808
- "aria-hidden": true,
5809
- style: { background: editor.getTableBorderColor() ?? TABLE_BORDER_COLOR }
5810
- }
5811
- ),
5812
- "Cor da borda",
5813
- /* @__PURE__ */ jsx13(
5814
- "input",
5815
- {
5816
- type: "color",
5817
- value: editor.getTableBorderColor() ?? TABLE_BORDER_COLOR,
5818
- onChange: (e) => editor.setTableBorderColor(e.target.value),
5819
- "aria-label": "Cor da borda"
5820
- }
5821
- )
5822
- ] }),
5823
- /* @__PURE__ */ jsx13(
6556
+ /* @__PURE__ */ jsx15("hr", {}),
6557
+ /* @__PURE__ */ jsx15(
5824
6558
  "button",
5825
6559
  {
5826
6560
  type: "button",
5827
- onClick: () => {
5828
- setOpen(false);
5829
- editor.setTableBorderColor(null);
6561
+ className: "ed-border-toggle",
6562
+ "aria-pressed": bordersOpen,
6563
+ "aria-expanded": bordersOpen,
6564
+ title: "Bordas da tabela",
6565
+ "aria-label": "Bordas da tabela",
6566
+ onClick: (e) => {
6567
+ e.preventDefault();
6568
+ setBordersOpen((v) => !v);
5830
6569
  },
5831
- children: "Restaurar cor padr\xE3o"
6570
+ children: BORDER_MENU_GLYPH
6571
+ }
6572
+ ),
6573
+ bordersOpen && /* @__PURE__ */ jsx15(
6574
+ TableBorderPanel,
6575
+ {
6576
+ preset: editor.getTableBorderPreset(),
6577
+ color: editor.getTableBorderColor() ?? TABLE_BORDER_COLOR,
6578
+ onPreset: (p) => editor.setTableBorderPreset(p),
6579
+ onColor: (c) => editor.setTableBorderColor(c),
6580
+ onResetColor: () => editor.setTableBorderColor(null)
5832
6581
  }
5833
6582
  ),
5834
- /* @__PURE__ */ jsx13("hr", {}),
5835
- /* @__PURE__ */ jsx13(
6583
+ /* @__PURE__ */ jsx15("hr", {}),
6584
+ /* @__PURE__ */ jsx15(
5836
6585
  "button",
5837
6586
  {
5838
6587
  type: "button",
@@ -5853,11 +6602,11 @@ function TableMenu() {
5853
6602
  var PICKER_MAX_ROWS = 8;
5854
6603
  var PICKER_MAX_COLS = 10;
5855
6604
  function TableSizePicker({ onPick }) {
5856
- const [hover, setHover] = useState11(null);
6605
+ const [hover, setHover] = useState12(null);
5857
6606
  const label = hover ? `${hover.r + 1} \xD7 ${hover.c + 1}` : "Inserir tabela";
5858
- return /* @__PURE__ */ jsxs12("div", { className: "ed-table-picker", children: [
5859
- /* @__PURE__ */ jsx13("div", { className: "ed-table-picker-label", children: label }),
5860
- /* @__PURE__ */ jsx13(
6607
+ return /* @__PURE__ */ jsxs15("div", { className: "ed-table-picker", children: [
6608
+ /* @__PURE__ */ jsx15("div", { className: "ed-table-picker-label", children: label }),
6609
+ /* @__PURE__ */ jsx15(
5861
6610
  "div",
5862
6611
  {
5863
6612
  className: "ed-table-picker-grid",
@@ -5870,7 +6619,7 @@ function TableSizePicker({ onPick }) {
5870
6619
  { length: PICKER_MAX_ROWS },
5871
6620
  (_, r) => Array.from({ length: PICKER_MAX_COLS }, (_2, c) => {
5872
6621
  const filled = hover != null && r <= hover.r && c <= hover.c;
5873
- return /* @__PURE__ */ jsx13(
6622
+ return /* @__PURE__ */ jsx15(
5874
6623
  "button",
5875
6624
  {
5876
6625
  type: "button",
@@ -5900,10 +6649,10 @@ function blockSelectValue(type, level) {
5900
6649
  return type;
5901
6650
  }
5902
6651
  function Group({ children }) {
5903
- return /* @__PURE__ */ jsx13("div", { className: "ed-toolbar-group", children });
6652
+ return /* @__PURE__ */ jsx15("div", { className: "ed-toolbar-group", children });
5904
6653
  }
5905
6654
  function MarkButton({ title, pressed, onClick, children }) {
5906
- return /* @__PURE__ */ jsx13(
6655
+ return /* @__PURE__ */ jsx15(
5907
6656
  "button",
5908
6657
  {
5909
6658
  type: "button",
@@ -5920,6 +6669,7 @@ export {
5920
6669
  A4_PAGE,
5921
6670
  Editor,
5922
6671
  EditorProvider,
6672
+ FormulaDialog,
5923
6673
  ImageCaptionDialog,
5924
6674
  LinkDialog,
5925
6675
  NodeView,