@underverse-ui/underverse 1.0.183 → 1.0.184

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
@@ -27369,7 +27369,7 @@ function useLocale2() {
27369
27369
  }
27370
27370
 
27371
27371
  // src/components/UEditor/UEditor.tsx
27372
- import React87, { useEffect as useEffect39, useImperativeHandle as useImperativeHandle4, useMemo as useMemo27, useRef as useRef38 } from "react";
27372
+ import React87, { useEffect as useEffect40, useImperativeHandle as useImperativeHandle4, useMemo as useMemo27, useRef as useRef39 } from "react";
27373
27373
  import { useEditor, EditorContent } from "@tiptap/react";
27374
27374
 
27375
27375
  // src/components/UEditor/extensions.ts
@@ -29905,11 +29905,17 @@ function isInTableCell(editor) {
29905
29905
  }
29906
29906
  function buildFormulaSuggestionItems({ query }) {
29907
29907
  const normalizedQuery = query.trim().toUpperCase();
29908
+ if (!isFormulaFunctionSuggestionQuery(normalizedQuery)) {
29909
+ return [];
29910
+ }
29908
29911
  if (!normalizedQuery) {
29909
29912
  return FORMULA_FUNCTIONS;
29910
29913
  }
29911
29914
  return FORMULA_FUNCTIONS.filter((item) => item.name.startsWith(normalizedQuery));
29912
29915
  }
29916
+ function isFormulaFunctionSuggestionQuery(query) {
29917
+ return /^[A-Z]*$/i.test(query.trim());
29918
+ }
29913
29919
  var FormulaSuggestionList = forwardRef16((props, ref) => {
29914
29920
  const t = useSmartTranslations("UEditor");
29915
29921
  const [selectedIndex, setSelectedIndex] = React76.useState(0);
@@ -29980,7 +29986,11 @@ var FormulaSuggestion = Extension4.create({
29980
29986
  editor: this.editor,
29981
29987
  char: "=",
29982
29988
  pluginKey: new PluginKey3("formulaSuggestion"),
29983
- allow: ({ editor }) => isInTableCell(editor),
29989
+ allow: ({ editor, range }) => {
29990
+ if (!isInTableCell(editor)) return false;
29991
+ const suggestionText = editor.state.doc.textBetween(range.from, range.to, "", "");
29992
+ return suggestionText.startsWith("=") && isFormulaFunctionSuggestionQuery(suggestionText.slice(1));
29993
+ },
29984
29994
  command: ({ editor, range, props }) => {
29985
29995
  insertFormulaFunction(editor, range, props);
29986
29996
  },
@@ -33983,51 +33993,98 @@ function buildTableFormulaDependencyGraph(cells) {
33983
33993
  return { dependencies, dependents, formulas };
33984
33994
  }
33985
33995
  function getTableFormulaCircularReferences(graph) {
33986
- const visiting = /* @__PURE__ */ new Set();
33987
- const visited = /* @__PURE__ */ new Set();
33988
33996
  const circular = /* @__PURE__ */ new Set();
33989
- const stack = [];
33990
- const visit = (label) => {
33991
- if (visiting.has(label)) {
33992
- const start = stack.indexOf(label);
33993
- for (const cycleLabel of start >= 0 ? stack.slice(start) : [label]) {
33994
- circular.add(cycleLabel);
33997
+ const visited = /* @__PURE__ */ new Set();
33998
+ const finishOrder = [];
33999
+ for (const startLabel of graph.formulas.keys()) {
34000
+ if (visited.has(startLabel)) continue;
34001
+ visited.add(startLabel);
34002
+ const stack = [
34003
+ {
34004
+ label: startLabel,
34005
+ references: Array.from(graph.dependencies.get(startLabel) ?? []).filter((ref) => graph.formulas.has(ref)),
34006
+ nextIndex: 0
33995
34007
  }
33996
- return;
33997
- }
33998
- if (visited.has(label)) return;
33999
- visiting.add(label);
34000
- stack.push(label);
34001
- for (const ref of graph.dependencies.get(label) ?? []) {
34002
- if (graph.formulas.has(ref)) {
34003
- visit(ref);
34008
+ ];
34009
+ while (stack.length > 0) {
34010
+ const frame = stack[stack.length - 1];
34011
+ if (!frame) break;
34012
+ const reference = frame.references[frame.nextIndex];
34013
+ if (reference) {
34014
+ frame.nextIndex += 1;
34015
+ if (!visited.has(reference)) {
34016
+ visited.add(reference);
34017
+ stack.push({
34018
+ label: reference,
34019
+ references: Array.from(graph.dependencies.get(reference) ?? []).filter((ref) => graph.formulas.has(ref)),
34020
+ nextIndex: 0
34021
+ });
34022
+ }
34023
+ continue;
34004
34024
  }
34025
+ stack.pop();
34026
+ finishOrder.push(frame.label);
34027
+ }
34028
+ }
34029
+ const assigned = /* @__PURE__ */ new Set();
34030
+ for (let index = finishOrder.length - 1; index >= 0; index -= 1) {
34031
+ const startLabel = finishOrder[index];
34032
+ if (!startLabel || assigned.has(startLabel)) continue;
34033
+ const component = [];
34034
+ const stack = [startLabel];
34035
+ assigned.add(startLabel);
34036
+ while (stack.length > 0) {
34037
+ const label = stack.pop();
34038
+ if (!label) continue;
34039
+ component.push(label);
34040
+ for (const dependent of graph.dependents.get(label) ?? []) {
34041
+ if (!graph.formulas.has(dependent) || assigned.has(dependent)) continue;
34042
+ assigned.add(dependent);
34043
+ stack.push(dependent);
34044
+ }
34045
+ }
34046
+ if (component.length > 1) {
34047
+ for (const label of component) circular.add(label);
34048
+ } else {
34049
+ const label = component[0];
34050
+ if (label && graph.dependencies.get(label)?.has(label)) circular.add(label);
34005
34051
  }
34006
- stack.pop();
34007
- visiting.delete(label);
34008
- visited.add(label);
34009
- };
34010
- for (const label of graph.formulas.keys()) {
34011
- visit(label);
34012
34052
  }
34013
34053
  return circular;
34014
34054
  }
34015
34055
  function getTableFormulaRecalculationOrder(graph) {
34016
34056
  const circular = getTableFormulaCircularReferences(graph);
34057
+ const visiting = /* @__PURE__ */ new Set();
34017
34058
  const visited = /* @__PURE__ */ new Set();
34018
34059
  const order = [];
34019
- const visit = (label) => {
34020
- if (visited.has(label) || circular.has(label)) return;
34021
- visited.add(label);
34022
- for (const ref of graph.dependencies.get(label) ?? []) {
34023
- if (graph.formulas.has(ref)) {
34024
- visit(ref);
34060
+ for (const startLabel of graph.formulas.keys()) {
34061
+ if (visited.has(startLabel) || circular.has(startLabel)) continue;
34062
+ const stack = [];
34063
+ const push = (label) => {
34064
+ visiting.add(label);
34065
+ stack.push({
34066
+ label,
34067
+ references: Array.from(graph.dependencies.get(label) ?? []).filter((ref) => graph.formulas.has(ref) && !circular.has(ref)),
34068
+ nextIndex: 0
34069
+ });
34070
+ };
34071
+ push(startLabel);
34072
+ while (stack.length > 0) {
34073
+ const frame = stack[stack.length - 1];
34074
+ if (!frame) break;
34075
+ const reference = frame.references[frame.nextIndex];
34076
+ if (reference) {
34077
+ frame.nextIndex += 1;
34078
+ if (!visited.has(reference) && !visiting.has(reference)) {
34079
+ push(reference);
34080
+ }
34081
+ continue;
34025
34082
  }
34083
+ stack.pop();
34084
+ visiting.delete(frame.label);
34085
+ visited.add(frame.label);
34086
+ order.push(frame.label);
34026
34087
  }
34027
- order.push(label);
34028
- };
34029
- for (const label of graph.formulas.keys()) {
34030
- visit(label);
34031
34088
  }
34032
34089
  return { order, circular };
34033
34090
  }
@@ -34086,9 +34143,11 @@ function tokenizeFormula(formula) {
34086
34143
  index += 1;
34087
34144
  continue;
34088
34145
  }
34089
- const numberMatch = formula.slice(index).match(/^\d+(?:\.\d+)?/);
34146
+ const numberMatch = formula.slice(index).match(/^(?:\d+(?:\.\d*)?|\.\d+)/);
34090
34147
  if (numberMatch?.[0]) {
34091
- tokens.push({ type: "number", value: Number.parseFloat(numberMatch[0]) });
34148
+ const value = Number.parseFloat(numberMatch[0]);
34149
+ if (!Number.isFinite(value)) return null;
34150
+ tokens.push({ type: "number", value });
34092
34151
  index += numberMatch[0].length;
34093
34152
  continue;
34094
34153
  }
@@ -34106,6 +34165,28 @@ function tokenizeFormula(formula) {
34106
34165
  }
34107
34166
  return tokens;
34108
34167
  }
34168
+ function toFiniteFormulaResult(value) {
34169
+ return Number.isFinite(value) ? { value, error: null } : { value: null, error: "invalid-formula" };
34170
+ }
34171
+ function parseTableCellNumericValue(value) {
34172
+ if (typeof value === "number") {
34173
+ return Number.isFinite(value) ? value : null;
34174
+ }
34175
+ let normalized = String(value ?? "").trim();
34176
+ if (!normalized || normalized.startsWith("#")) return null;
34177
+ const isPercent = normalized.endsWith("%");
34178
+ if (isPercent) normalized = normalized.slice(0, -1).trim();
34179
+ const currencyMatch = normalized.match(/^([+-]?)\$(.+)$/);
34180
+ if (currencyMatch) {
34181
+ normalized = `${currencyMatch[1] ?? ""}${currencyMatch[2] ?? ""}`.trim();
34182
+ }
34183
+ const groupedNumber = /^[+-]?\d{1,3}(?:,\d{3})+(?:\.\d*)?(?:[eE][+-]?\d+)?$/;
34184
+ const plainNumber = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/;
34185
+ if (!groupedNumber.test(normalized) && !plainNumber.test(normalized)) return null;
34186
+ const parsed = Number(normalized.replace(/,/g, ""));
34187
+ if (!Number.isFinite(parsed)) return null;
34188
+ return isPercent ? parsed / 100 : parsed;
34189
+ }
34109
34190
  var FormulaParser = class {
34110
34191
  constructor(tokens, getCellValue) {
34111
34192
  this.tokens = tokens;
@@ -34123,10 +34204,7 @@ var FormulaParser = class {
34123
34204
  this.index += 1;
34124
34205
  const right = this.parseTerm();
34125
34206
  if (right.error) return right;
34126
- left = {
34127
- value: operator.value === "+" ? left.value + right.value : left.value - right.value,
34128
- error: null
34129
- };
34207
+ left = toFiniteFormulaResult(operator.value === "+" ? left.value + right.value : left.value - right.value);
34130
34208
  }
34131
34209
  return left;
34132
34210
  }
@@ -34141,10 +34219,7 @@ var FormulaParser = class {
34141
34219
  if (operator.value === "/" && right.value === 0) {
34142
34220
  return { value: null, error: "division-by-zero" };
34143
34221
  }
34144
- left = {
34145
- value: operator.value === "*" ? left.value * right.value : left.value / right.value,
34146
- error: null
34147
- };
34222
+ left = toFiniteFormulaResult(operator.value === "*" ? left.value * right.value : left.value / right.value);
34148
34223
  }
34149
34224
  return left;
34150
34225
  }
@@ -34153,11 +34228,11 @@ var FormulaParser = class {
34153
34228
  if (!token) {
34154
34229
  return { value: null, error: "invalid-formula" };
34155
34230
  }
34156
- if (token.type === "operator" && token.value === "-") {
34231
+ if (token.type === "operator" && (token.value === "-" || token.value === "+")) {
34157
34232
  this.index += 1;
34158
34233
  const value = this.parseFactor();
34159
34234
  if (value.error) return value;
34160
- return { value: -value.value, error: null };
34235
+ return toFiniteFormulaResult(token.value === "-" ? -value.value : value.value);
34161
34236
  }
34162
34237
  if (token.type === "number") {
34163
34238
  this.index += 1;
@@ -34202,11 +34277,10 @@ var FormulaParser = class {
34202
34277
  if (cellValue2 != null) values.push(cellValue2);
34203
34278
  continue;
34204
34279
  }
34205
- const cellValue = this.readCellNumber(label);
34206
- if (cellValue.error) return cellValue;
34207
- values.push(cellValue.value);
34280
+ const cellValue = this.readOptionalCellNumber(label);
34281
+ if (cellValue != null) values.push(cellValue);
34208
34282
  }
34209
- } else if (name === "COUNT" && token.type === "cell") {
34283
+ } else if (token.type === "cell") {
34210
34284
  this.index += 1;
34211
34285
  const cellValue = this.readOptionalCellNumber(token.value);
34212
34286
  if (cellValue != null) values.push(cellValue);
@@ -34223,28 +34297,24 @@ var FormulaParser = class {
34223
34297
  }
34224
34298
  return { value: null, error: "invalid-formula" };
34225
34299
  }
34226
- if (values.length === 0 && name !== "COUNT") {
34227
- return { value: null, error: "invalid-formula" };
34300
+ if (name === "SUM") return toFiniteFormulaResult(values.reduce((sum, value) => sum + value, 0));
34301
+ if (name === "AVG") {
34302
+ return values.length > 0 ? toFiniteFormulaResult(values.reduce((sum, value) => sum + value, 0) / values.length) : { value: null, error: "division-by-zero" };
34228
34303
  }
34229
- if (name === "SUM") return { value: values.reduce((sum, value) => sum + value, 0), error: null };
34230
- if (name === "AVG") return { value: values.reduce((sum, value) => sum + value, 0) / values.length, error: null };
34231
- if (name === "MIN") return { value: Math.min(...values), error: null };
34232
- if (name === "MAX") return { value: Math.max(...values), error: null };
34304
+ if (name === "MIN") return toFiniteFormulaResult(values.length > 0 ? Math.min(...values) : 0);
34305
+ if (name === "MAX") return toFiniteFormulaResult(values.length > 0 ? Math.max(...values) : 0);
34233
34306
  if (name === "COUNT") return { value: values.length, error: null };
34234
34307
  return { value: null, error: "invalid-formula" };
34235
34308
  }
34236
34309
  readCellNumber(label) {
34237
- const value = this.getCellValue(label);
34238
- const parsed = typeof value === "number" ? value : Number.parseFloat(String(value ?? "").trim());
34239
- if (!Number.isFinite(parsed)) {
34310
+ const parsed = parseTableCellNumericValue(this.getCellValue(label));
34311
+ if (parsed == null) {
34240
34312
  return { value: null, error: "invalid-reference" };
34241
34313
  }
34242
34314
  return { value: parsed, error: null };
34243
34315
  }
34244
34316
  readOptionalCellNumber(label) {
34245
- const value = this.getCellValue(label);
34246
- const parsed = typeof value === "number" ? value : Number.parseFloat(String(value ?? "").trim());
34247
- return Number.isFinite(parsed) ? parsed : null;
34317
+ return parseTableCellNumericValue(this.getCellValue(label));
34248
34318
  }
34249
34319
  peekOperator(operators) {
34250
34320
  const token = this.tokens[this.index];
@@ -35360,7 +35430,7 @@ var CustomBubbleMenu = ({
35360
35430
  const BUBBLE_MENU_ESTIMATED_HEIGHT = 44;
35361
35431
  const [isVisible, setIsVisible] = useState50(false);
35362
35432
  const [linkInputOpen, setLinkInputOpen] = useState50(false);
35363
- const [position, setPosition] = useState50({
35433
+ const [position, setPosition2] = useState50({
35364
35434
  top: 0,
35365
35435
  left: 0,
35366
35436
  placement: "top"
@@ -35432,7 +35502,7 @@ var CustomBubbleMenu = ({
35432
35502
  Math.max(viewportPadding, (start.left + end.left) / 2)
35433
35503
  );
35434
35504
  const top = placement === "top" ? Math.max(viewportPadding, selectionTop - BUBBLE_MENU_OFFSET) : Math.min(window.innerHeight - viewportPadding, selectionBottom + BUBBLE_MENU_OFFSET);
35435
- setPosition({ top, left, placement });
35505
+ setPosition2({ top, left, placement });
35436
35506
  if (keepOpenRef.current) {
35437
35507
  clearShowTimeout();
35438
35508
  setIsVisible(true);
@@ -41961,8 +42031,401 @@ function useUEditorTableInteractions(editor, editable = true) {
41961
42031
  };
41962
42032
  }
41963
42033
 
42034
+ // src/components/UEditor/use-formula-coordinate-overlay.ts
42035
+ import { useEffect as useEffect39, useRef as useRef37 } from "react";
42036
+ import { TableMap as TableMap6 } from "@tiptap/pm/tables";
42037
+
42038
+ // src/components/UEditor/table-formula-range-picker.ts
42039
+ import { TextSelection as TextSelection4 } from "@tiptap/pm/state";
42040
+ import { TableMap as TableMap5 } from "@tiptap/pm/tables";
42041
+ function getCellText2(cellNode) {
42042
+ return cellNode.textBetween(0, cellNode.content.size, "\n").trim();
42043
+ }
42044
+ function getFormulaEditingTableContext(view) {
42045
+ const { $from } = view.state.selection;
42046
+ for (let depth = $from.depth; depth > 0; depth -= 1) {
42047
+ const node = $from.node(depth);
42048
+ if (node.type.name !== "tableCell" && node.type.name !== "tableHeader") continue;
42049
+ if (!getCellText2(node).startsWith("=")) return null;
42050
+ const cellPos = $from.before(depth);
42051
+ const cellDom = view.nodeDOM(cellPos);
42052
+ if (!(cellDom instanceof HTMLTableCellElement)) return null;
42053
+ const tableDepth = depth - 2;
42054
+ const tableNode = tableDepth > 0 ? $from.node(tableDepth) : null;
42055
+ if (!tableNode || tableNode.type.name !== "table") return null;
42056
+ const tableDom = cellDom.closest("table");
42057
+ if (!(tableDom instanceof HTMLTableElement)) return null;
42058
+ return {
42059
+ cellContentEnd: $from.end(depth),
42060
+ cellContentStart: $from.start(depth),
42061
+ cellDom,
42062
+ formula: getCellText2(node),
42063
+ tableDom,
42064
+ tableNode,
42065
+ tablePos: $from.before(tableDepth)
42066
+ };
42067
+ }
42068
+ return null;
42069
+ }
42070
+ function cancelFormulaEditing(view) {
42071
+ const context = getFormulaEditingTableContext(view);
42072
+ if (!context) return false;
42073
+ let tr = view.state.tr.delete(context.cellContentStart, context.cellContentEnd);
42074
+ const selectionPos = Math.min(context.cellContentStart, tr.doc.content.size);
42075
+ tr = tr.setSelection(TextSelection4.near(tr.doc.resolve(selectionPos)));
42076
+ view.dispatch(tr);
42077
+ view.focus();
42078
+ return true;
42079
+ }
42080
+ function getReferenceInsertionPrefix(view, cellContentStart, insertionPos) {
42081
+ const textBeforeCursor = view.state.doc.textBetween(cellContentStart, insertionPos, "", "");
42082
+ const isInsideFunctionArguments = /[A-Z]+\([^)]*$/i.test(textBeforeCursor);
42083
+ const followsReference = /[A-Z]+[1-9]\d*(?::[A-Z]+[1-9]\d*)?\s*$/i.test(textBeforeCursor);
42084
+ return isInsideFunctionArguments && followsReference ? "," : "";
42085
+ }
42086
+ function findTableForPos(view, pos) {
42087
+ const $pos = view.state.doc.resolve(pos);
42088
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
42089
+ const node = $pos.node(depth);
42090
+ if (node.type.name === "table") {
42091
+ return {
42092
+ node,
42093
+ pos: $pos.before(depth),
42094
+ start: $pos.start(depth)
42095
+ };
42096
+ }
42097
+ }
42098
+ return null;
42099
+ }
42100
+ function getCellRelativePosFromDomPos2(map, tableStart, domPos) {
42101
+ const relativeDomPos = domPos - tableStart;
42102
+ const seen = /* @__PURE__ */ new Set();
42103
+ for (const relativeCellPos of map.map) {
42104
+ if (seen.has(relativeCellPos)) continue;
42105
+ seen.add(relativeCellPos);
42106
+ if (relativeDomPos === relativeCellPos || relativeDomPos === relativeCellPos + 1) {
42107
+ return relativeCellPos;
42108
+ }
42109
+ }
42110
+ return null;
42111
+ }
42112
+ function getFormulaTableCellInfo(view, target, tablePos) {
42113
+ const element = resolveEventElement(target);
42114
+ const cell = element?.closest?.("th,td");
42115
+ if (!(cell instanceof HTMLTableCellElement)) return null;
42116
+ const domPos = view.posAtDOM(cell, 0);
42117
+ const tableInfo = findTableForPos(view, domPos);
42118
+ if (!tableInfo || tableInfo.pos !== tablePos) return null;
42119
+ const map = TableMap5.get(tableInfo.node);
42120
+ const relativeCellPos = getCellRelativePosFromDomPos2(map, tableInfo.start, domPos);
42121
+ if (relativeCellPos == null) return null;
42122
+ const rect = map.findCell(relativeCellPos);
42123
+ return {
42124
+ cell,
42125
+ label: `${indexToColumnName(rect.left)}${rect.top + 1}`,
42126
+ rect
42127
+ };
42128
+ }
42129
+ function normalizeFormulaRangeLabel(fromLabel, toLabel) {
42130
+ return fromLabel === toLabel ? fromLabel : `${fromLabel}:${toLabel}`;
42131
+ }
42132
+ function replacePickedLabel(view, pickState, nextLabel, currentCell) {
42133
+ if (nextLabel === pickState.currentLabel && currentCell === pickState.currentCell) return pickState;
42134
+ if (nextLabel === pickState.currentLabel) {
42135
+ return {
42136
+ ...pickState,
42137
+ currentCell
42138
+ };
42139
+ }
42140
+ let tr = view.state.tr.insertText(nextLabel, pickState.insertedFrom, pickState.insertedTo);
42141
+ const nextTo = pickState.insertedFrom + nextLabel.length;
42142
+ tr = tr.setSelection(TextSelection4.create(tr.doc, nextTo));
42143
+ view.dispatch(tr);
42144
+ return {
42145
+ ...pickState,
42146
+ insertedTo: nextTo,
42147
+ currentLabel: nextLabel,
42148
+ currentCell
42149
+ };
42150
+ }
42151
+ function beginFormulaRangePick(view, event) {
42152
+ if (event.button !== 0) return null;
42153
+ const formulaCell = getFormulaEditingTableContext(view);
42154
+ if (!formulaCell) return null;
42155
+ const picked = getFormulaTableCellInfo(view, event.target, formulaCell.tablePos);
42156
+ if (!picked || picked.cell === formulaCell.cellDom) return null;
42157
+ const { from, to } = view.state.selection;
42158
+ const prefix = from === to ? getReferenceInsertionPrefix(view, formulaCell.cellContentStart, from) : "";
42159
+ const insertedText = `${prefix}${picked.label}`;
42160
+ const insertedFrom = from + prefix.length;
42161
+ let tr = view.state.tr.insertText(insertedText, from, to);
42162
+ tr = tr.setSelection(TextSelection4.create(tr.doc, from + insertedText.length));
42163
+ view.dispatch(tr);
42164
+ view.focus();
42165
+ event.preventDefault();
42166
+ event.stopPropagation();
42167
+ return {
42168
+ anchorLabel: picked.label,
42169
+ anchorCell: picked.cell,
42170
+ tablePos: formulaCell.tablePos,
42171
+ insertedFrom,
42172
+ insertedTo: insertedFrom + picked.label.length,
42173
+ currentLabel: picked.label,
42174
+ currentCell: picked.cell
42175
+ };
42176
+ }
42177
+ function updateFormulaRangePick(view, pickState, event) {
42178
+ const picked = getFormulaTableCellInfo(view, event.target, pickState.tablePos);
42179
+ if (!picked) return pickState;
42180
+ event.preventDefault();
42181
+ event.stopPropagation();
42182
+ return replacePickedLabel(
42183
+ view,
42184
+ pickState,
42185
+ normalizeFormulaRangeLabel(pickState.anchorLabel, picked.label),
42186
+ picked.cell
42187
+ );
42188
+ }
42189
+ function getFormulaRangePickHighlight(container, pickState) {
42190
+ if (!container.contains(pickState.anchorCell) || !container.contains(pickState.currentCell)) return null;
42191
+ const containerRect = container.getBoundingClientRect();
42192
+ const anchorRect = pickState.anchorCell.getBoundingClientRect();
42193
+ const currentRect = pickState.currentCell.getBoundingClientRect();
42194
+ const left = Math.min(anchorRect.left, currentRect.left) - containerRect.left + container.scrollLeft;
42195
+ const top = Math.min(anchorRect.top, currentRect.top) - containerRect.top + container.scrollTop;
42196
+ const right = Math.max(anchorRect.right, currentRect.right) - containerRect.left + container.scrollLeft;
42197
+ const bottom = Math.max(anchorRect.bottom, currentRect.bottom) - containerRect.top + container.scrollTop;
42198
+ return {
42199
+ left,
42200
+ top,
42201
+ width: Math.max(0, right - left),
42202
+ height: Math.max(0, bottom - top)
42203
+ };
42204
+ }
42205
+
42206
+ // src/components/UEditor/use-formula-coordinate-overlay.ts
42207
+ function setPosition(element, left, top, width, height) {
42208
+ element.style.left = `${left}px`;
42209
+ element.style.top = `${top}px`;
42210
+ if (width != null) element.style.width = `${Math.max(0, width)}px`;
42211
+ if (height != null) element.style.height = `${Math.max(0, height)}px`;
42212
+ }
42213
+ function createCoordinateLabel(kind, label) {
42214
+ const element = document.createElement("span");
42215
+ element.dataset.ueditorFormulaCoordinate = kind;
42216
+ element.textContent = label;
42217
+ element.className = "pointer-events-none absolute z-30 flex items-center justify-center rounded-[3px] border border-primary/35 bg-primary/90 px-1 font-mono text-[10px] font-semibold leading-none text-primary-foreground shadow-sm";
42218
+ return element;
42219
+ }
42220
+ function createReferenceHighlight(label) {
42221
+ const element = document.createElement("span");
42222
+ element.dataset.ueditorFormulaReference = label;
42223
+ element.className = "pointer-events-none absolute z-[21] rounded-[2px] border-2 border-emerald-500 bg-emerald-500/15";
42224
+ return element;
42225
+ }
42226
+ function useFormulaCoordinateOverlay(editor, containerRef, labels) {
42227
+ const overlayRef = useRef37(null);
42228
+ useEffect39(() => {
42229
+ if (!editor) return void 0;
42230
+ const overlay = overlayRef.current;
42231
+ const container = containerRef.current;
42232
+ if (!overlay || !container) return void 0;
42233
+ let animationFrame = null;
42234
+ let activeTable = null;
42235
+ let activeTablePos = null;
42236
+ let hoverLabel = null;
42237
+ const clearOverlay = () => {
42238
+ activeTable = null;
42239
+ activeTablePos = null;
42240
+ hoverLabel = null;
42241
+ overlay.replaceChildren();
42242
+ overlay.style.display = "none";
42243
+ };
42244
+ const syncOverlay = () => {
42245
+ animationFrame = null;
42246
+ if (editor.isDestroyed) return;
42247
+ const context = getFormulaEditingTableContext(editor.view);
42248
+ if (!context) {
42249
+ clearOverlay();
42250
+ return;
42251
+ }
42252
+ const containerRect = container.getBoundingClientRect();
42253
+ const tableRect = context.tableDom.getBoundingClientRect();
42254
+ const tableLeft = tableRect.left - containerRect.left + container.scrollLeft;
42255
+ const tableTop = tableRect.top - containerRect.top + container.scrollTop;
42256
+ const map = TableMap6.get(context.tableNode);
42257
+ const columnSegments = Array(map.width);
42258
+ const rowSegments = Array(map.height);
42259
+ const cellInfos = [];
42260
+ for (const cell of context.tableDom.querySelectorAll("th,td")) {
42261
+ if (!(cell instanceof HTMLTableCellElement)) continue;
42262
+ const info = getFormulaTableCellInfo(editor.view, cell, context.tablePos);
42263
+ if (!info) continue;
42264
+ cellInfos.push(info);
42265
+ const cellRect = cell.getBoundingClientRect();
42266
+ const columnSpan = Math.max(1, info.rect.right - info.rect.left);
42267
+ const rowSpan = Math.max(1, info.rect.bottom - info.rect.top);
42268
+ const columnWidth = cellRect.width / columnSpan;
42269
+ const rowHeight = cellRect.height / rowSpan;
42270
+ for (let column = info.rect.left; column < info.rect.right; column += 1) {
42271
+ if (!columnSegments[column] || columnSpan < columnSegments[column].span) {
42272
+ columnSegments[column] = {
42273
+ start: cellRect.left - containerRect.left + container.scrollLeft + (column - info.rect.left) * columnWidth,
42274
+ size: columnWidth,
42275
+ span: columnSpan
42276
+ };
42277
+ }
42278
+ }
42279
+ for (let row = info.rect.top; row < info.rect.bottom; row += 1) {
42280
+ if (!rowSegments[row] || rowSpan < rowSegments[row].span) {
42281
+ rowSegments[row] = {
42282
+ start: cellRect.top - containerRect.top + container.scrollTop + (row - info.rect.top) * rowHeight,
42283
+ size: rowHeight,
42284
+ span: rowSpan
42285
+ };
42286
+ }
42287
+ }
42288
+ }
42289
+ const fallbackColumnWidth = map.width > 0 ? tableRect.width / map.width : 0;
42290
+ const fallbackRowHeight = map.height > 0 ? tableRect.height / map.height : 0;
42291
+ const children = [];
42292
+ const actions = document.createElement("div");
42293
+ actions.dataset.ueditorFormulaActions = "";
42294
+ actions.className = "pointer-events-auto absolute z-50 flex items-center gap-1 rounded-md border border-border bg-background p-1 shadow-md";
42295
+ const formulaCellRect = context.cellDom.getBoundingClientRect();
42296
+ setPosition(
42297
+ actions,
42298
+ formulaCellRect.left - containerRect.left + container.scrollLeft,
42299
+ formulaCellRect.bottom - containerRect.top + container.scrollTop + 4
42300
+ );
42301
+ const applyButton = document.createElement("button");
42302
+ applyButton.type = "button";
42303
+ applyButton.dataset.ueditorFormulaApply = "";
42304
+ applyButton.disabled = isDraftTableFormula(context.formula);
42305
+ applyButton.textContent = `${applyButton.disabled ? "" : "\u2713 "}${labels.apply} (Enter)`;
42306
+ applyButton.className = "rounded bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-45";
42307
+ const cancelButton = document.createElement("button");
42308
+ cancelButton.type = "button";
42309
+ cancelButton.dataset.ueditorFormulaCancel = "";
42310
+ cancelButton.textContent = `${labels.cancel} (Esc)`;
42311
+ cancelButton.className = "rounded px-2.5 py-1 text-xs font-medium text-foreground hover:bg-muted";
42312
+ const preserveSelection = (event) => {
42313
+ event.preventDefault();
42314
+ event.stopPropagation();
42315
+ };
42316
+ applyButton.addEventListener("mousedown", preserveSelection);
42317
+ cancelButton.addEventListener("mousedown", preserveSelection);
42318
+ applyButton.addEventListener("click", (event) => {
42319
+ event.preventDefault();
42320
+ event.stopPropagation();
42321
+ if (!applyButton.disabled) recalculateActiveTableFormulas(editor);
42322
+ });
42323
+ cancelButton.addEventListener("click", (event) => {
42324
+ event.preventDefault();
42325
+ event.stopPropagation();
42326
+ cancelFormulaEditing(editor.view);
42327
+ });
42328
+ actions.append(applyButton, cancelButton);
42329
+ children.push(actions);
42330
+ for (let column = 0; column < map.width; column += 1) {
42331
+ const segment = columnSegments[column] ?? {
42332
+ start: tableLeft + column * fallbackColumnWidth,
42333
+ size: fallbackColumnWidth,
42334
+ span: map.width
42335
+ };
42336
+ const label = createCoordinateLabel("column", indexToColumnName(column));
42337
+ setPosition(label, segment.start, Math.max(0, tableTop - 22), segment.size, 20);
42338
+ children.push(label);
42339
+ }
42340
+ for (let row = 0; row < map.height; row += 1) {
42341
+ const segment = rowSegments[row] ?? {
42342
+ start: tableTop + row * fallbackRowHeight,
42343
+ size: fallbackRowHeight,
42344
+ span: map.height
42345
+ };
42346
+ const label = createCoordinateLabel("row", String(row + 1));
42347
+ setPosition(label, Math.max(0, tableLeft - 28), segment.start, 26, segment.size);
42348
+ children.push(label);
42349
+ }
42350
+ const references = new Set(getTableFormulaReferences(context.formula));
42351
+ for (const info of cellInfos) {
42352
+ if (!info || !references.has(info.label)) continue;
42353
+ const cellRect = info.cell.getBoundingClientRect();
42354
+ const highlight = createReferenceHighlight(info.label);
42355
+ setPosition(
42356
+ highlight,
42357
+ cellRect.left - containerRect.left + container.scrollLeft + 2,
42358
+ cellRect.top - containerRect.top + container.scrollTop + 2,
42359
+ cellRect.width - 4,
42360
+ cellRect.height - 4
42361
+ );
42362
+ children.push(highlight);
42363
+ }
42364
+ hoverLabel = document.createElement("span");
42365
+ hoverLabel.dataset.ueditorFormulaHoverLabel = "";
42366
+ hoverLabel.className = "pointer-events-none absolute z-40 hidden rounded bg-foreground px-1.5 py-1 font-mono text-[10px] font-semibold leading-none text-background shadow-md";
42367
+ children.push(hoverLabel);
42368
+ overlay.replaceChildren(...children);
42369
+ overlay.style.display = "block";
42370
+ activeTable = context.tableDom;
42371
+ activeTablePos = context.tablePos;
42372
+ };
42373
+ const scheduleSync = () => {
42374
+ if (animationFrame != null) return;
42375
+ animationFrame = window.requestAnimationFrame(syncOverlay);
42376
+ };
42377
+ const handleMouseMove2 = (event) => {
42378
+ if (!activeTable || activeTablePos == null || !hoverLabel) return;
42379
+ const target = event.target instanceof Element ? event.target.closest("th,td") : null;
42380
+ if (!(target instanceof HTMLTableCellElement) || target.closest("table") !== activeTable) {
42381
+ hoverLabel.style.display = "none";
42382
+ return;
42383
+ }
42384
+ const info = getFormulaTableCellInfo(editor.view, target, activeTablePos);
42385
+ if (!info) {
42386
+ hoverLabel.style.display = "none";
42387
+ return;
42388
+ }
42389
+ const containerRect = container.getBoundingClientRect();
42390
+ const cellRect = target.getBoundingClientRect();
42391
+ hoverLabel.textContent = info.label;
42392
+ hoverLabel.style.display = "block";
42393
+ setPosition(
42394
+ hoverLabel,
42395
+ cellRect.left - containerRect.left + container.scrollLeft + 4,
42396
+ cellRect.top - containerRect.top + container.scrollTop + 4
42397
+ );
42398
+ };
42399
+ const handleMouseLeave2 = () => {
42400
+ if (hoverLabel) hoverLabel.style.display = "none";
42401
+ };
42402
+ editor.on("selectionUpdate", scheduleSync);
42403
+ editor.on("update", scheduleSync);
42404
+ editor.on("focus", scheduleSync);
42405
+ editor.on("blur", scheduleSync);
42406
+ editor.view.dom.addEventListener("mousemove", handleMouseMove2);
42407
+ editor.view.dom.addEventListener("mouseleave", handleMouseLeave2);
42408
+ container.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleSync);
42409
+ window.addEventListener("resize", scheduleSync);
42410
+ scheduleSync();
42411
+ return () => {
42412
+ editor.off("selectionUpdate", scheduleSync);
42413
+ editor.off("update", scheduleSync);
42414
+ editor.off("focus", scheduleSync);
42415
+ editor.off("blur", scheduleSync);
42416
+ editor.view.dom.removeEventListener("mousemove", handleMouseMove2);
42417
+ editor.view.dom.removeEventListener("mouseleave", handleMouseLeave2);
42418
+ container.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleSync);
42419
+ window.removeEventListener("resize", scheduleSync);
42420
+ if (animationFrame != null) window.cancelAnimationFrame(animationFrame);
42421
+ clearOverlay();
42422
+ };
42423
+ }, [containerRef, editor, labels.apply, labels.cancel]);
42424
+ return overlayRef;
42425
+ }
42426
+
41964
42427
  // src/components/UEditor/menu-bar.tsx
41965
- import React86, { useMemo as useMemo26, useRef as useRef37, useState as useState51 } from "react";
42428
+ import React86, { useMemo as useMemo26, useRef as useRef38, useState as useState51 } from "react";
41966
42429
  import { useEditorState as useEditorState3 } from "@tiptap/react";
41967
42430
  import {
41968
42431
  AlignCenter as AlignCenter4,
@@ -42586,7 +43049,7 @@ var MenuBar = ({
42586
43049
  editor,
42587
43050
  selector: ({ transactionNumber }) => transactionNumber
42588
43051
  });
42589
- const fileInputRef = useRef37(null);
43052
+ const fileInputRef = useRef38(null);
42590
43053
  const [showImageInput, setShowImageInput] = useState51(false);
42591
43054
  const [showLinkInput, setShowLinkInput] = useState51(false);
42592
43055
  const [isInsertMenuOpen, setIsInsertMenuOpen] = useState51(false);
@@ -42875,146 +43338,6 @@ var MenuBar = ({
42875
43338
  ] });
42876
43339
  };
42877
43340
 
42878
- // src/components/UEditor/table-formula-range-picker.ts
42879
- import { TextSelection as TextSelection4 } from "@tiptap/pm/state";
42880
- import { TableMap as TableMap5 } from "@tiptap/pm/tables";
42881
- function getCellText2(cellNode) {
42882
- return cellNode.textBetween(0, cellNode.content.size, "\n").trim();
42883
- }
42884
- function findSelectionFormulaCell(view) {
42885
- const { $from } = view.state.selection;
42886
- for (let depth = $from.depth; depth > 0; depth -= 1) {
42887
- const node = $from.node(depth);
42888
- if (node.type.name !== "tableCell" && node.type.name !== "tableHeader") continue;
42889
- if (!getCellText2(node).startsWith("=")) return null;
42890
- const cellPos = $from.before(depth);
42891
- const cellDom = view.nodeDOM(cellPos);
42892
- const tableDepth = depth - 2;
42893
- const tableNode = tableDepth > 0 ? $from.node(tableDepth) : null;
42894
- if (!tableNode || tableNode.type.name !== "table") return null;
42895
- return {
42896
- cellDom: cellDom instanceof HTMLTableCellElement ? cellDom : null,
42897
- tablePos: $from.before(tableDepth)
42898
- };
42899
- }
42900
- return null;
42901
- }
42902
- function findTableForPos(view, pos) {
42903
- const $pos = view.state.doc.resolve(pos);
42904
- for (let depth = $pos.depth; depth > 0; depth -= 1) {
42905
- const node = $pos.node(depth);
42906
- if (node.type.name === "table") {
42907
- return {
42908
- node,
42909
- pos: $pos.before(depth),
42910
- start: $pos.start(depth)
42911
- };
42912
- }
42913
- }
42914
- return null;
42915
- }
42916
- function getCellRelativePosFromDomPos2(map, tableStart, domPos) {
42917
- const relativeDomPos = domPos - tableStart;
42918
- const seen = /* @__PURE__ */ new Set();
42919
- for (const relativeCellPos of map.map) {
42920
- if (seen.has(relativeCellPos)) continue;
42921
- seen.add(relativeCellPos);
42922
- if (relativeDomPos === relativeCellPos || relativeDomPos === relativeCellPos + 1) {
42923
- return relativeCellPos;
42924
- }
42925
- }
42926
- return null;
42927
- }
42928
- function getPickedCellLabel(view, target, tablePos) {
42929
- const element = resolveEventElement(target);
42930
- const cell = element?.closest?.("th,td");
42931
- if (!(cell instanceof HTMLTableCellElement)) return null;
42932
- const domPos = view.posAtDOM(cell, 0);
42933
- const tableInfo = findTableForPos(view, domPos);
42934
- if (!tableInfo || tableInfo.pos !== tablePos) return null;
42935
- const map = TableMap5.get(tableInfo.node);
42936
- const relativeCellPos = getCellRelativePosFromDomPos2(map, tableInfo.start, domPos);
42937
- if (relativeCellPos == null) return null;
42938
- const rect = map.findCell(relativeCellPos);
42939
- return {
42940
- cell,
42941
- label: `${indexToColumnName(rect.left)}${rect.top + 1}`
42942
- };
42943
- }
42944
- function normalizeFormulaRangeLabel(fromLabel, toLabel) {
42945
- return fromLabel === toLabel ? fromLabel : `${fromLabel}:${toLabel}`;
42946
- }
42947
- function replacePickedLabel(view, pickState, nextLabel, currentCell) {
42948
- if (nextLabel === pickState.currentLabel && currentCell === pickState.currentCell) return pickState;
42949
- if (nextLabel === pickState.currentLabel) {
42950
- return {
42951
- ...pickState,
42952
- currentCell
42953
- };
42954
- }
42955
- let tr = view.state.tr.insertText(nextLabel, pickState.insertedFrom, pickState.insertedTo);
42956
- const nextTo = pickState.insertedFrom + nextLabel.length;
42957
- tr = tr.setSelection(TextSelection4.create(tr.doc, nextTo));
42958
- view.dispatch(tr);
42959
- return {
42960
- ...pickState,
42961
- insertedTo: nextTo,
42962
- currentLabel: nextLabel,
42963
- currentCell
42964
- };
42965
- }
42966
- function beginFormulaRangePick(view, event) {
42967
- if (event.button !== 0) return null;
42968
- const formulaCell = findSelectionFormulaCell(view);
42969
- if (!formulaCell) return null;
42970
- const picked = getPickedCellLabel(view, event.target, formulaCell.tablePos);
42971
- if (!picked || picked.cell === formulaCell.cellDom) return null;
42972
- const { from, to } = view.state.selection;
42973
- let tr = view.state.tr.insertText(picked.label, from, to);
42974
- tr = tr.setSelection(TextSelection4.create(tr.doc, from + picked.label.length));
42975
- view.dispatch(tr);
42976
- view.focus();
42977
- event.preventDefault();
42978
- event.stopPropagation();
42979
- return {
42980
- anchorLabel: picked.label,
42981
- anchorCell: picked.cell,
42982
- tablePos: formulaCell.tablePos,
42983
- insertedFrom: from,
42984
- insertedTo: from + picked.label.length,
42985
- currentLabel: picked.label,
42986
- currentCell: picked.cell
42987
- };
42988
- }
42989
- function updateFormulaRangePick(view, pickState, event) {
42990
- const picked = getPickedCellLabel(view, event.target, pickState.tablePos);
42991
- if (!picked) return pickState;
42992
- event.preventDefault();
42993
- event.stopPropagation();
42994
- return replacePickedLabel(
42995
- view,
42996
- pickState,
42997
- normalizeFormulaRangeLabel(pickState.anchorLabel, picked.label),
42998
- picked.cell
42999
- );
43000
- }
43001
- function getFormulaRangePickHighlight(container, pickState) {
43002
- if (!container.contains(pickState.anchorCell) || !container.contains(pickState.currentCell)) return null;
43003
- const containerRect = container.getBoundingClientRect();
43004
- const anchorRect = pickState.anchorCell.getBoundingClientRect();
43005
- const currentRect = pickState.currentCell.getBoundingClientRect();
43006
- const left = Math.min(anchorRect.left, currentRect.left) - containerRect.left + container.scrollLeft;
43007
- const top = Math.min(anchorRect.top, currentRect.top) - containerRect.top + container.scrollTop;
43008
- const right = Math.max(anchorRect.right, currentRect.right) - containerRect.left + container.scrollLeft;
43009
- const bottom = Math.max(anchorRect.bottom, currentRect.bottom) - containerRect.top + container.scrollTop;
43010
- return {
43011
- left,
43012
- top,
43013
- width: Math.max(0, right - left),
43014
- height: Math.max(0, bottom - top)
43015
- };
43016
- }
43017
-
43018
43341
  // src/components/UEditor/UEditor.tsx
43019
43342
  import { jsx as jsx99, jsxs as jsxs82 } from "react/jsx-runtime";
43020
43343
  var UEditor = React87.forwardRef(({
@@ -43058,11 +43381,12 @@ var UEditor = React87.forwardRef(({
43058
43381
  }, ref) => {
43059
43382
  const t = useSmartTranslations("UEditor");
43060
43383
  const effectivePlaceholder = placeholder ?? t("placeholder");
43061
- const inFlightPrepareRef = useRef38(null);
43062
- const lastAppliedContentRef = useRef38(content ?? "");
43063
- const scheduledFormulaRecalculateRef = useRef38(false);
43064
- const formulaRangePickRef = useRef38(null);
43065
- const formulaRangeSurfaceRef = useRef38(null);
43384
+ const inFlightPrepareRef = useRef39(null);
43385
+ const lastAppliedContentRef = useRef39(content ?? "");
43386
+ const scheduledFormulaRecalculateRef = useRef39(false);
43387
+ const editorInstanceRef = useRef39(null);
43388
+ const formulaRangePickRef = useRef39(null);
43389
+ const formulaRangeSurfaceRef = useRef39(null);
43066
43390
  const [formulaRangeHighlight, setFormulaRangeHighlight] = React87.useState(null);
43067
43391
  const scheduleFormulaRecalculate = React87.useCallback((editor2, options) => {
43068
43392
  if (editor2.isDestroyed || scheduledFormulaRecalculateRef.current) return;
@@ -43149,6 +43473,22 @@ var UEditor = React87.forwardRef(({
43149
43473
  },
43150
43474
  keydown: (_view, event) => {
43151
43475
  if (!(event instanceof KeyboardEvent)) return false;
43476
+ const formulaContext = getFormulaEditingTableContext(_view);
43477
+ if (formulaContext && event.key === "Enter") {
43478
+ event.preventDefault();
43479
+ event.stopPropagation();
43480
+ const activeEditor = editorInstanceRef.current;
43481
+ if (activeEditor && !isDraftTableFormula(formulaContext.formula)) {
43482
+ recalculateActiveTableFormulas(activeEditor);
43483
+ }
43484
+ return true;
43485
+ }
43486
+ if (formulaContext && event.key === "Escape") {
43487
+ event.preventDefault();
43488
+ event.stopPropagation();
43489
+ cancelFormulaEditing(_view);
43490
+ return true;
43491
+ }
43152
43492
  if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
43153
43493
  event.stopPropagation();
43154
43494
  }
@@ -43189,12 +43529,22 @@ var UEditor = React87.forwardRef(({
43189
43529
  scheduleFormulaRecalculate(editor2, { force: true });
43190
43530
  }
43191
43531
  });
43532
+ useEffect40(() => {
43533
+ editorInstanceRef.current = editor;
43534
+ return () => {
43535
+ if (editorInstanceRef.current === editor) editorInstanceRef.current = null;
43536
+ };
43537
+ }, [editor]);
43192
43538
  const {
43193
43539
  editorContentRef,
43194
43540
  tableColumnGuideRef,
43195
43541
  tableRowGuideRef,
43196
43542
  activeTableCellHighlightRef
43197
43543
  } = useUEditorTableInteractions(editor, editable);
43544
+ const formulaCoordinateOverlayRef = useFormulaCoordinateOverlay(editor, editorContentRef, {
43545
+ apply: t("tableMenu.apply"),
43546
+ cancel: t("imageInput.cancelBtn")
43547
+ });
43198
43548
  useImperativeHandle4(
43199
43549
  ref,
43200
43550
  () => ({
@@ -43220,7 +43570,7 @@ var UEditor = React87.forwardRef(({
43220
43570
  }),
43221
43571
  [content, editor, uploadImageForSave, uploadFileForSave, uploadImageConcurrency]
43222
43572
  );
43223
- useEffect39(() => {
43573
+ useEffect40(() => {
43224
43574
  if (!editor) return;
43225
43575
  queueMicrotask(() => {
43226
43576
  if (!editor.isDestroyed) {
@@ -43228,7 +43578,7 @@ var UEditor = React87.forwardRef(({
43228
43578
  }
43229
43579
  });
43230
43580
  }, [editor]);
43231
- useEffect39(() => {
43581
+ useEffect40(() => {
43232
43582
  if (!editor) return;
43233
43583
  const nextContent = content ?? "";
43234
43584
  if (lastAppliedContentRef.current === nextContent) return;
@@ -43348,6 +43698,14 @@ var UEditor = React87.forwardRef(({
43348
43698
  className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10"
43349
43699
  }
43350
43700
  ),
43701
+ /* @__PURE__ */ jsx99(
43702
+ "div",
43703
+ {
43704
+ ref: formulaCoordinateOverlayRef,
43705
+ "data-ueditor-formula-coordinate-overlay": "",
43706
+ className: "pointer-events-none absolute inset-0 z-[21] hidden overflow-visible"
43707
+ }
43708
+ ),
43351
43709
  formulaRangeHighlight && /* @__PURE__ */ jsx99(
43352
43710
  "span",
43353
43711
  {