@underverse-ui/underverse 1.0.156 → 1.0.157
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/api-reference.json +1 -1
- package/dist/index.cjs +311 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +311 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28861,6 +28861,20 @@ function createEmptyCellNode(cellNode) {
|
|
|
28861
28861
|
function createCellCopyForColumnDuplicate(cellNode) {
|
|
28862
28862
|
return cellNode.type.create(cellNode.attrs, cellNode.content);
|
|
28863
28863
|
}
|
|
28864
|
+
function createCellWithDuplicatedLogicalColumn(cellNode, widthIndex) {
|
|
28865
|
+
const colspan = Math.max(1, Number(cellNode.attrs.colspan) || 1);
|
|
28866
|
+
let nextColwidth = null;
|
|
28867
|
+
if (Array.isArray(cellNode.attrs.colwidth)) {
|
|
28868
|
+
nextColwidth = [...cellNode.attrs.colwidth];
|
|
28869
|
+
const duplicateWidth = nextColwidth[widthIndex];
|
|
28870
|
+
nextColwidth.splice(widthIndex + 1, 0, typeof duplicateWidth === "number" ? duplicateWidth : 0);
|
|
28871
|
+
}
|
|
28872
|
+
return cellNode.type.create({
|
|
28873
|
+
...cellNode.attrs,
|
|
28874
|
+
colspan: colspan + 1,
|
|
28875
|
+
...nextColwidth ? { colwidth: nextColwidth } : null
|
|
28876
|
+
}, cellNode.content);
|
|
28877
|
+
}
|
|
28864
28878
|
function getTableRows(tableNode) {
|
|
28865
28879
|
const rows = [];
|
|
28866
28880
|
tableNode.forEach((rowNode, rowOffset) => {
|
|
@@ -29036,6 +29050,11 @@ function duplicateTableColumnAt(editor, columnIndex, cellPos) {
|
|
|
29036
29050
|
return rect && rect.top === rowIndex && rect.left <= columnIndex && columnIndex < rect.right;
|
|
29037
29051
|
});
|
|
29038
29052
|
if (!sourceCell) return rowInfo.node;
|
|
29053
|
+
const sourceRect = safeFindCell(map, sourceCell.relativePos);
|
|
29054
|
+
if (sourceRect && (sourceRect.left < columnIndex || sourceRect.right > columnIndex + 1)) {
|
|
29055
|
+
cells[sourceCell.index] = createCellWithDuplicatedLogicalColumn(sourceCell.node, columnIndex - sourceRect.left);
|
|
29056
|
+
return rowInfo.node.type.create(rowInfo.node.attrs, cells);
|
|
29057
|
+
}
|
|
29039
29058
|
cells.splice(sourceCell.index + 1, 0, createCellCopyForColumnDuplicate(sourceCell.node));
|
|
29040
29059
|
return rowInfo.node.type.create(rowInfo.node.attrs, cells);
|
|
29041
29060
|
});
|
|
@@ -30357,6 +30376,25 @@ function getTableFormulaRecalculationOrder(graph) {
|
|
|
30357
30376
|
}
|
|
30358
30377
|
return { order, circular };
|
|
30359
30378
|
}
|
|
30379
|
+
function getAffectedTableFormulaLabels(graph, changedLabels) {
|
|
30380
|
+
const affected = /* @__PURE__ */ new Set();
|
|
30381
|
+
const queue = Array.from(changedLabels, (label) => label.toUpperCase());
|
|
30382
|
+
for (const label of queue) {
|
|
30383
|
+
if (graph.formulas.has(label)) {
|
|
30384
|
+
affected.add(label);
|
|
30385
|
+
}
|
|
30386
|
+
}
|
|
30387
|
+
for (let index = 0; index < queue.length; index += 1) {
|
|
30388
|
+
const label = queue[index];
|
|
30389
|
+
if (!label) continue;
|
|
30390
|
+
for (const dependent of graph.dependents.get(label) ?? []) {
|
|
30391
|
+
if (affected.has(dependent)) continue;
|
|
30392
|
+
affected.add(dependent);
|
|
30393
|
+
queue.push(dependent);
|
|
30394
|
+
}
|
|
30395
|
+
}
|
|
30396
|
+
return affected;
|
|
30397
|
+
}
|
|
30360
30398
|
function evaluateBasicTableFormula(formula, getCellValue) {
|
|
30361
30399
|
const normalized = normalizeTableFormula(formula);
|
|
30362
30400
|
if (!normalized) {
|
|
@@ -30504,10 +30542,19 @@ var FormulaParser = class {
|
|
|
30504
30542
|
const range = parseTableCellRange(token.value);
|
|
30505
30543
|
if (!range) return { value: null, error: "invalid-reference" };
|
|
30506
30544
|
for (const label of getTableCellRangeLabels(range)) {
|
|
30545
|
+
if (name === "COUNT") {
|
|
30546
|
+
const cellValue2 = this.readOptionalCellNumber(label);
|
|
30547
|
+
if (cellValue2 != null) values.push(cellValue2);
|
|
30548
|
+
continue;
|
|
30549
|
+
}
|
|
30507
30550
|
const cellValue = this.readCellNumber(label);
|
|
30508
30551
|
if (cellValue.error) return cellValue;
|
|
30509
30552
|
values.push(cellValue.value);
|
|
30510
30553
|
}
|
|
30554
|
+
} else if (name === "COUNT" && token.type === "cell") {
|
|
30555
|
+
this.index += 1;
|
|
30556
|
+
const cellValue = this.readOptionalCellNumber(token.value);
|
|
30557
|
+
if (cellValue != null) values.push(cellValue);
|
|
30511
30558
|
} else {
|
|
30512
30559
|
const value = this.parseExpression();
|
|
30513
30560
|
if (value.error) return value;
|
|
@@ -30521,7 +30568,7 @@ var FormulaParser = class {
|
|
|
30521
30568
|
}
|
|
30522
30569
|
return { value: null, error: "invalid-formula" };
|
|
30523
30570
|
}
|
|
30524
|
-
if (values.length === 0) {
|
|
30571
|
+
if (values.length === 0 && name !== "COUNT") {
|
|
30525
30572
|
return { value: null, error: "invalid-formula" };
|
|
30526
30573
|
}
|
|
30527
30574
|
if (name === "SUM") return { value: values.reduce((sum, value) => sum + value, 0), error: null };
|
|
@@ -30539,6 +30586,11 @@ var FormulaParser = class {
|
|
|
30539
30586
|
}
|
|
30540
30587
|
return { value: parsed, error: null };
|
|
30541
30588
|
}
|
|
30589
|
+
readOptionalCellNumber(label) {
|
|
30590
|
+
const value = this.getCellValue(label);
|
|
30591
|
+
const parsed = typeof value === "number" ? value : Number.parseFloat(String(value ?? "").trim());
|
|
30592
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
30593
|
+
}
|
|
30542
30594
|
peekOperator(operators) {
|
|
30543
30595
|
const token = this.tokens[this.index];
|
|
30544
30596
|
return token?.type === "operator" && operators.includes(token.value) ? token : null;
|
|
@@ -30602,6 +30654,41 @@ function getSelectionTableCellNode(editor) {
|
|
|
30602
30654
|
}
|
|
30603
30655
|
return null;
|
|
30604
30656
|
}
|
|
30657
|
+
function getSelectionTableInfo(editor) {
|
|
30658
|
+
const { $from } = editor.state.selection;
|
|
30659
|
+
for (let depth = $from.depth; depth > 0; depth -= 1) {
|
|
30660
|
+
const node = $from.node(depth);
|
|
30661
|
+
if (node.type.name === "table") {
|
|
30662
|
+
return {
|
|
30663
|
+
node,
|
|
30664
|
+
pos: $from.before(depth)
|
|
30665
|
+
};
|
|
30666
|
+
}
|
|
30667
|
+
}
|
|
30668
|
+
return null;
|
|
30669
|
+
}
|
|
30670
|
+
function getSelectionTableCellLabel(editor) {
|
|
30671
|
+
const { $from } = editor.state.selection;
|
|
30672
|
+
let cellDepth = -1;
|
|
30673
|
+
let tableDepth = -1;
|
|
30674
|
+
for (let depth = $from.depth; depth > 0; depth -= 1) {
|
|
30675
|
+
const node = $from.node(depth);
|
|
30676
|
+
if (cellDepth < 0 && (node.type.name === "tableCell" || node.type.name === "tableHeader")) {
|
|
30677
|
+
cellDepth = depth;
|
|
30678
|
+
}
|
|
30679
|
+
if (node.type.name === "table") {
|
|
30680
|
+
tableDepth = depth;
|
|
30681
|
+
break;
|
|
30682
|
+
}
|
|
30683
|
+
}
|
|
30684
|
+
if (cellDepth < 0 || tableDepth < 0) return null;
|
|
30685
|
+
const tableNode = $from.node(tableDepth);
|
|
30686
|
+
const tableStart = $from.start(tableDepth);
|
|
30687
|
+
const relativeCellPos = $from.before(cellDepth) - tableStart;
|
|
30688
|
+
const rect = safeFindCell2(TableMap2.get(tableNode), relativeCellPos);
|
|
30689
|
+
if (!rect) return null;
|
|
30690
|
+
return `${indexToColumnName(rect.left)}${rect.top + 1}`;
|
|
30691
|
+
}
|
|
30605
30692
|
function isEditingTableFormulaText(editor) {
|
|
30606
30693
|
const cellNode = getSelectionTableCellNode(editor);
|
|
30607
30694
|
return Boolean(cellNode && getCellText(cellNode).startsWith("="));
|
|
@@ -30613,20 +30700,6 @@ function createCellDisplayContent(cellNode, displayValue) {
|
|
|
30613
30700
|
}
|
|
30614
30701
|
return [paragraphType.create(null, cellNode.type.schema.text(displayValue))];
|
|
30615
30702
|
}
|
|
30616
|
-
function buildTableValueGetter(tableNode) {
|
|
30617
|
-
const map = TableMap2.get(tableNode);
|
|
30618
|
-
const values = /* @__PURE__ */ new Map();
|
|
30619
|
-
for (const rowInfo of getTableRows2(tableNode)) {
|
|
30620
|
-
for (const entry of rowInfo.cells) {
|
|
30621
|
-
const rect = safeFindCell2(map, entry.relativePos);
|
|
30622
|
-
if (!rect) continue;
|
|
30623
|
-
const label = `${indexToColumnName(rect.left)}${rect.top + 1}`;
|
|
30624
|
-
const computedValue = entry.node.attrs.computedValue;
|
|
30625
|
-
values.set(label, typeof computedValue === "string" && computedValue.trim() ? computedValue : getCellText(entry.node));
|
|
30626
|
-
}
|
|
30627
|
-
}
|
|
30628
|
-
return (label) => values.get(label.toUpperCase());
|
|
30629
|
-
}
|
|
30630
30703
|
function buildTableValueMap(tableNode) {
|
|
30631
30704
|
const map = TableMap2.get(tableNode);
|
|
30632
30705
|
const values = /* @__PURE__ */ new Map();
|
|
@@ -30641,10 +30714,6 @@ function buildTableValueMap(tableNode) {
|
|
|
30641
30714
|
}
|
|
30642
30715
|
return values;
|
|
30643
30716
|
}
|
|
30644
|
-
function getFormulaComputedValue(formula, tableNode) {
|
|
30645
|
-
const result = evaluateBasicTableFormula(formula, buildTableValueGetter(tableNode));
|
|
30646
|
-
return result.error ? `#${result.error.toUpperCase()}` : String(result.value);
|
|
30647
|
-
}
|
|
30648
30717
|
function normalizeFormulaInput(formula) {
|
|
30649
30718
|
const trimmed = formula.trim();
|
|
30650
30719
|
if (!trimmed) return "";
|
|
@@ -30655,19 +30724,19 @@ function setSelectedTableCellFormula(editor, formula) {
|
|
|
30655
30724
|
const { state, view } = editor;
|
|
30656
30725
|
if (!normalized) {
|
|
30657
30726
|
const clearedFormula = setCellAttr("formula", null)(state, view.dispatch.bind(view));
|
|
30658
|
-
const
|
|
30659
|
-
if (clearedFormula ||
|
|
30727
|
+
const clearedValue2 = setCellAttr("computedValue", null)(editor.state, view.dispatch.bind(view));
|
|
30728
|
+
if (clearedFormula || clearedValue2) {
|
|
30729
|
+
recalculateActiveTableFormulas(editor);
|
|
30660
30730
|
view.focus();
|
|
30661
30731
|
dispatchTableLayoutChange(editor);
|
|
30662
30732
|
return true;
|
|
30663
30733
|
}
|
|
30664
30734
|
return false;
|
|
30665
30735
|
}
|
|
30666
|
-
const rect = selectedRect2(state);
|
|
30667
|
-
const computedValue = getFormulaComputedValue(normalized, rect.table);
|
|
30668
30736
|
const appliedFormula = setCellAttr("formula", normalized)(state, view.dispatch.bind(view));
|
|
30669
|
-
const
|
|
30670
|
-
if (appliedFormula ||
|
|
30737
|
+
const clearedValue = setCellAttr("computedValue", null)(editor.state, view.dispatch.bind(view));
|
|
30738
|
+
if (appliedFormula || clearedValue) {
|
|
30739
|
+
recalculateActiveTableFormulas(editor);
|
|
30671
30740
|
view.focus();
|
|
30672
30741
|
dispatchTableLayoutChange(editor);
|
|
30673
30742
|
return true;
|
|
@@ -30749,7 +30818,7 @@ function promoteFormulaTextInTableNode(tableNode) {
|
|
|
30749
30818
|
changed
|
|
30750
30819
|
};
|
|
30751
30820
|
}
|
|
30752
|
-
function recalculateTableNode(tableNode) {
|
|
30821
|
+
function recalculateTableNode(tableNode, options) {
|
|
30753
30822
|
const promoted = promoteFormulaTextInTableNode(tableNode);
|
|
30754
30823
|
tableNode = promoted.tableNode;
|
|
30755
30824
|
const map = TableMap2.get(tableNode);
|
|
@@ -30779,13 +30848,16 @@ function recalculateTableNode(tableNode) {
|
|
|
30779
30848
|
}))
|
|
30780
30849
|
);
|
|
30781
30850
|
const { order, circular } = getTableFormulaRecalculationOrder(graph);
|
|
30851
|
+
const affectedLabels = options?.changedLabels ? getAffectedTableFormulaLabels(graph, options.changedLabels) : null;
|
|
30782
30852
|
const computedValues = /* @__PURE__ */ new Map();
|
|
30783
30853
|
const getCellValue = (label) => values.get(label.toUpperCase());
|
|
30784
30854
|
for (const label of circular) {
|
|
30855
|
+
if (affectedLabels && !affectedLabels.has(label)) continue;
|
|
30785
30856
|
computedValues.set(label, formatFormulaError("circular-reference"));
|
|
30786
30857
|
values.set(label, formatFormulaError("circular-reference"));
|
|
30787
30858
|
}
|
|
30788
30859
|
for (const label of order) {
|
|
30860
|
+
if (affectedLabels && !affectedLabels.has(label)) continue;
|
|
30789
30861
|
const entry = formulaEntries.get(label);
|
|
30790
30862
|
if (!entry) continue;
|
|
30791
30863
|
const result = evaluateBasicTableFormula(entry.formula, getCellValue);
|
|
@@ -30830,6 +30902,22 @@ function recalculateSelectedTable(editor) {
|
|
|
30830
30902
|
dispatchTableLayoutChange(editor);
|
|
30831
30903
|
return true;
|
|
30832
30904
|
}
|
|
30905
|
+
function recalculateActiveTableFormulas(editor) {
|
|
30906
|
+
const tableInfo = getSelectionTableInfo(editor);
|
|
30907
|
+
if (!tableInfo) {
|
|
30908
|
+
return recalculateAllTableFormulas(editor);
|
|
30909
|
+
}
|
|
30910
|
+
const activeCellLabel = getSelectionTableCellLabel(editor);
|
|
30911
|
+
const nextTable = recalculateTableNode(tableInfo.node, {
|
|
30912
|
+
changedLabels: activeCellLabel ? [activeCellLabel] : null
|
|
30913
|
+
});
|
|
30914
|
+
if (!nextTable) return false;
|
|
30915
|
+
editor.view.dispatch(
|
|
30916
|
+
editor.state.tr.replaceWith(tableInfo.pos, tableInfo.pos + tableInfo.node.nodeSize, nextTable).setMeta(UEDITOR_TABLE_FORMULA_RECALCULATE_META, true)
|
|
30917
|
+
);
|
|
30918
|
+
dispatchTableLayoutChange(editor);
|
|
30919
|
+
return true;
|
|
30920
|
+
}
|
|
30833
30921
|
function recalculateAllTableFormulas(editor) {
|
|
30834
30922
|
const replacements = [];
|
|
30835
30923
|
editor.state.doc.descendants((node, pos) => {
|
|
@@ -38865,6 +38953,146 @@ var MenuBar = ({
|
|
|
38865
38953
|
] });
|
|
38866
38954
|
};
|
|
38867
38955
|
|
|
38956
|
+
// src/components/UEditor/table-formula-range-picker.ts
|
|
38957
|
+
import { TextSelection as TextSelection4 } from "@tiptap/pm/state";
|
|
38958
|
+
import { TableMap as TableMap4 } from "@tiptap/pm/tables";
|
|
38959
|
+
function getCellText2(cellNode) {
|
|
38960
|
+
return cellNode.textBetween(0, cellNode.content.size, "\n").trim();
|
|
38961
|
+
}
|
|
38962
|
+
function findSelectionFormulaCell(view) {
|
|
38963
|
+
const { $from } = view.state.selection;
|
|
38964
|
+
for (let depth = $from.depth; depth > 0; depth -= 1) {
|
|
38965
|
+
const node = $from.node(depth);
|
|
38966
|
+
if (node.type.name !== "tableCell" && node.type.name !== "tableHeader") continue;
|
|
38967
|
+
if (!getCellText2(node).startsWith("=")) return null;
|
|
38968
|
+
const cellPos = $from.before(depth);
|
|
38969
|
+
const cellDom = view.nodeDOM(cellPos);
|
|
38970
|
+
const tableDepth = depth - 2;
|
|
38971
|
+
const tableNode = tableDepth > 0 ? $from.node(tableDepth) : null;
|
|
38972
|
+
if (!tableNode || tableNode.type.name !== "table") return null;
|
|
38973
|
+
return {
|
|
38974
|
+
cellDom: cellDom instanceof HTMLTableCellElement ? cellDom : null,
|
|
38975
|
+
tablePos: $from.before(tableDepth)
|
|
38976
|
+
};
|
|
38977
|
+
}
|
|
38978
|
+
return null;
|
|
38979
|
+
}
|
|
38980
|
+
function findTableForPos(view, pos) {
|
|
38981
|
+
const $pos = view.state.doc.resolve(pos);
|
|
38982
|
+
for (let depth = $pos.depth; depth > 0; depth -= 1) {
|
|
38983
|
+
const node = $pos.node(depth);
|
|
38984
|
+
if (node.type.name === "table") {
|
|
38985
|
+
return {
|
|
38986
|
+
node,
|
|
38987
|
+
pos: $pos.before(depth),
|
|
38988
|
+
start: $pos.start(depth)
|
|
38989
|
+
};
|
|
38990
|
+
}
|
|
38991
|
+
}
|
|
38992
|
+
return null;
|
|
38993
|
+
}
|
|
38994
|
+
function getCellRelativePosFromDomPos2(map, tableStart, domPos) {
|
|
38995
|
+
const relativeDomPos = domPos - tableStart;
|
|
38996
|
+
const seen = /* @__PURE__ */ new Set();
|
|
38997
|
+
for (const relativeCellPos of map.map) {
|
|
38998
|
+
if (seen.has(relativeCellPos)) continue;
|
|
38999
|
+
seen.add(relativeCellPos);
|
|
39000
|
+
if (relativeDomPos === relativeCellPos || relativeDomPos === relativeCellPos + 1) {
|
|
39001
|
+
return relativeCellPos;
|
|
39002
|
+
}
|
|
39003
|
+
}
|
|
39004
|
+
return null;
|
|
39005
|
+
}
|
|
39006
|
+
function getPickedCellLabel(view, target, tablePos) {
|
|
39007
|
+
const element = resolveEventElement(target);
|
|
39008
|
+
const cell = element?.closest?.("th,td");
|
|
39009
|
+
if (!(cell instanceof HTMLTableCellElement)) return null;
|
|
39010
|
+
const domPos = view.posAtDOM(cell, 0);
|
|
39011
|
+
const tableInfo = findTableForPos(view, domPos);
|
|
39012
|
+
if (!tableInfo || tableInfo.pos !== tablePos) return null;
|
|
39013
|
+
const map = TableMap4.get(tableInfo.node);
|
|
39014
|
+
const relativeCellPos = getCellRelativePosFromDomPos2(map, tableInfo.start, domPos);
|
|
39015
|
+
if (relativeCellPos == null) return null;
|
|
39016
|
+
const rect = map.findCell(relativeCellPos);
|
|
39017
|
+
return {
|
|
39018
|
+
cell,
|
|
39019
|
+
label: `${indexToColumnName(rect.left)}${rect.top + 1}`
|
|
39020
|
+
};
|
|
39021
|
+
}
|
|
39022
|
+
function normalizeFormulaRangeLabel(fromLabel, toLabel) {
|
|
39023
|
+
return fromLabel === toLabel ? fromLabel : `${fromLabel}:${toLabel}`;
|
|
39024
|
+
}
|
|
39025
|
+
function replacePickedLabel(view, pickState, nextLabel, currentCell) {
|
|
39026
|
+
if (nextLabel === pickState.currentLabel && currentCell === pickState.currentCell) return pickState;
|
|
39027
|
+
if (nextLabel === pickState.currentLabel) {
|
|
39028
|
+
return {
|
|
39029
|
+
...pickState,
|
|
39030
|
+
currentCell
|
|
39031
|
+
};
|
|
39032
|
+
}
|
|
39033
|
+
let tr = view.state.tr.insertText(nextLabel, pickState.insertedFrom, pickState.insertedTo);
|
|
39034
|
+
const nextTo = pickState.insertedFrom + nextLabel.length;
|
|
39035
|
+
tr = tr.setSelection(TextSelection4.create(tr.doc, nextTo));
|
|
39036
|
+
view.dispatch(tr);
|
|
39037
|
+
return {
|
|
39038
|
+
...pickState,
|
|
39039
|
+
insertedTo: nextTo,
|
|
39040
|
+
currentLabel: nextLabel,
|
|
39041
|
+
currentCell
|
|
39042
|
+
};
|
|
39043
|
+
}
|
|
39044
|
+
function beginFormulaRangePick(view, event) {
|
|
39045
|
+
if (event.button !== 0) return null;
|
|
39046
|
+
const formulaCell = findSelectionFormulaCell(view);
|
|
39047
|
+
if (!formulaCell) return null;
|
|
39048
|
+
const picked = getPickedCellLabel(view, event.target, formulaCell.tablePos);
|
|
39049
|
+
if (!picked || picked.cell === formulaCell.cellDom) return null;
|
|
39050
|
+
const { from, to } = view.state.selection;
|
|
39051
|
+
let tr = view.state.tr.insertText(picked.label, from, to);
|
|
39052
|
+
tr = tr.setSelection(TextSelection4.create(tr.doc, from + picked.label.length));
|
|
39053
|
+
view.dispatch(tr);
|
|
39054
|
+
view.focus();
|
|
39055
|
+
event.preventDefault();
|
|
39056
|
+
event.stopPropagation();
|
|
39057
|
+
return {
|
|
39058
|
+
anchorLabel: picked.label,
|
|
39059
|
+
anchorCell: picked.cell,
|
|
39060
|
+
tablePos: formulaCell.tablePos,
|
|
39061
|
+
insertedFrom: from,
|
|
39062
|
+
insertedTo: from + picked.label.length,
|
|
39063
|
+
currentLabel: picked.label,
|
|
39064
|
+
currentCell: picked.cell
|
|
39065
|
+
};
|
|
39066
|
+
}
|
|
39067
|
+
function updateFormulaRangePick(view, pickState, event) {
|
|
39068
|
+
const picked = getPickedCellLabel(view, event.target, pickState.tablePos);
|
|
39069
|
+
if (!picked) return pickState;
|
|
39070
|
+
event.preventDefault();
|
|
39071
|
+
event.stopPropagation();
|
|
39072
|
+
return replacePickedLabel(
|
|
39073
|
+
view,
|
|
39074
|
+
pickState,
|
|
39075
|
+
normalizeFormulaRangeLabel(pickState.anchorLabel, picked.label),
|
|
39076
|
+
picked.cell
|
|
39077
|
+
);
|
|
39078
|
+
}
|
|
39079
|
+
function getFormulaRangePickHighlight(container, pickState) {
|
|
39080
|
+
if (!container.contains(pickState.anchorCell) || !container.contains(pickState.currentCell)) return null;
|
|
39081
|
+
const containerRect = container.getBoundingClientRect();
|
|
39082
|
+
const anchorRect = pickState.anchorCell.getBoundingClientRect();
|
|
39083
|
+
const currentRect = pickState.currentCell.getBoundingClientRect();
|
|
39084
|
+
const left = Math.min(anchorRect.left, currentRect.left) - containerRect.left + container.scrollLeft;
|
|
39085
|
+
const top = Math.min(anchorRect.top, currentRect.top) - containerRect.top + container.scrollTop;
|
|
39086
|
+
const right = Math.max(anchorRect.right, currentRect.right) - containerRect.left + container.scrollLeft;
|
|
39087
|
+
const bottom = Math.max(anchorRect.bottom, currentRect.bottom) - containerRect.top + container.scrollTop;
|
|
39088
|
+
return {
|
|
39089
|
+
left,
|
|
39090
|
+
top,
|
|
39091
|
+
width: Math.max(0, right - left),
|
|
39092
|
+
height: Math.max(0, bottom - top)
|
|
39093
|
+
};
|
|
39094
|
+
}
|
|
39095
|
+
|
|
38868
39096
|
// src/components/UEditor/UEditor.tsx
|
|
38869
39097
|
import { jsx as jsx94, jsxs as jsxs79 } from "react/jsx-runtime";
|
|
38870
39098
|
var UEditor = React83.forwardRef(({
|
|
@@ -38909,6 +39137,9 @@ var UEditor = React83.forwardRef(({
|
|
|
38909
39137
|
const inFlightPrepareRef = useRef37(null);
|
|
38910
39138
|
const lastAppliedContentRef = useRef37(content ?? "");
|
|
38911
39139
|
const scheduledFormulaRecalculateRef = useRef37(false);
|
|
39140
|
+
const formulaRangePickRef = useRef37(null);
|
|
39141
|
+
const formulaRangeSurfaceRef = useRef37(null);
|
|
39142
|
+
const [formulaRangeHighlight, setFormulaRangeHighlight] = React83.useState(null);
|
|
38912
39143
|
const scheduleFormulaRecalculate = React83.useCallback((editor2, options) => {
|
|
38913
39144
|
if (editor2.isDestroyed || scheduledFormulaRecalculateRef.current) return;
|
|
38914
39145
|
if (!options?.force && isEditingTableFormulaText(editor2)) return;
|
|
@@ -38916,7 +39147,7 @@ var UEditor = React83.forwardRef(({
|
|
|
38916
39147
|
queueMicrotask(() => {
|
|
38917
39148
|
scheduledFormulaRecalculateRef.current = false;
|
|
38918
39149
|
if (!editor2.isDestroyed && (options?.force || !isEditingTableFormulaText(editor2))) {
|
|
38919
|
-
|
|
39150
|
+
recalculateActiveTableFormulas(editor2);
|
|
38920
39151
|
}
|
|
38921
39152
|
});
|
|
38922
39153
|
}, []);
|
|
@@ -38949,6 +39180,10 @@ var UEditor = React83.forwardRef(({
|
|
|
38949
39180
|
],
|
|
38950
39181
|
[effectivePlaceholder, t, maxCharacters, uploadImage, resolvedUploadFile, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable, fetchMetadata, extraExtensions]
|
|
38951
39182
|
);
|
|
39183
|
+
const syncFormulaRangeHighlight = React83.useCallback((pickState) => {
|
|
39184
|
+
const container = formulaRangeSurfaceRef.current;
|
|
39185
|
+
setFormulaRangeHighlight(container && pickState ? getFormulaRangePickHighlight(container, pickState) : null);
|
|
39186
|
+
}, []);
|
|
38952
39187
|
const editor = useEditor({
|
|
38953
39188
|
immediatelyRender: false,
|
|
38954
39189
|
extensions,
|
|
@@ -38957,6 +39192,37 @@ var UEditor = React83.forwardRef(({
|
|
|
38957
39192
|
autofocus,
|
|
38958
39193
|
editorProps: {
|
|
38959
39194
|
handleDOMEvents: {
|
|
39195
|
+
mousedown: (view, event) => {
|
|
39196
|
+
if (!(event instanceof MouseEvent)) return false;
|
|
39197
|
+
const pickState = beginFormulaRangePick(view, event);
|
|
39198
|
+
if (!pickState) return false;
|
|
39199
|
+
formulaRangePickRef.current = pickState;
|
|
39200
|
+
syncFormulaRangeHighlight(pickState);
|
|
39201
|
+
return true;
|
|
39202
|
+
},
|
|
39203
|
+
mousemove: (view, event) => {
|
|
39204
|
+
if (!(event instanceof MouseEvent)) return false;
|
|
39205
|
+
const pickState = formulaRangePickRef.current;
|
|
39206
|
+
if (!pickState) return false;
|
|
39207
|
+
if (event.buttons === 0) {
|
|
39208
|
+
formulaRangePickRef.current = null;
|
|
39209
|
+
syncFormulaRangeHighlight(null);
|
|
39210
|
+
return false;
|
|
39211
|
+
}
|
|
39212
|
+
const nextPickState = updateFormulaRangePick(view, pickState, event);
|
|
39213
|
+
formulaRangePickRef.current = nextPickState;
|
|
39214
|
+
syncFormulaRangeHighlight(nextPickState);
|
|
39215
|
+
return true;
|
|
39216
|
+
},
|
|
39217
|
+
mouseup: (_view, event) => {
|
|
39218
|
+
if (!(event instanceof MouseEvent)) return false;
|
|
39219
|
+
if (!formulaRangePickRef.current) return false;
|
|
39220
|
+
formulaRangePickRef.current = null;
|
|
39221
|
+
syncFormulaRangeHighlight(null);
|
|
39222
|
+
event.preventDefault();
|
|
39223
|
+
event.stopPropagation();
|
|
39224
|
+
return true;
|
|
39225
|
+
},
|
|
38960
39226
|
keydown: (_view, event) => {
|
|
38961
39227
|
if (!(event instanceof KeyboardEvent)) return false;
|
|
38962
39228
|
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
@@ -39122,7 +39388,10 @@ var UEditor = React83.forwardRef(({
|
|
|
39122
39388
|
/* @__PURE__ */ jsxs79(
|
|
39123
39389
|
"div",
|
|
39124
39390
|
{
|
|
39125
|
-
ref:
|
|
39391
|
+
ref: (node) => {
|
|
39392
|
+
editorContentRef.current = node;
|
|
39393
|
+
formulaRangeSurfaceRef.current = node;
|
|
39394
|
+
},
|
|
39126
39395
|
className: "relative flex-1 overflow-y-auto",
|
|
39127
39396
|
style: {
|
|
39128
39397
|
minHeight: editable ? minHeight : void 0,
|
|
@@ -39154,6 +39423,20 @@ var UEditor = React83.forwardRef(({
|
|
|
39154
39423
|
className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10"
|
|
39155
39424
|
}
|
|
39156
39425
|
),
|
|
39426
|
+
formulaRangeHighlight && /* @__PURE__ */ jsx94(
|
|
39427
|
+
"span",
|
|
39428
|
+
{
|
|
39429
|
+
"aria-hidden": "true",
|
|
39430
|
+
"data-ueditor-formula-range-highlight": "",
|
|
39431
|
+
className: "pointer-events-none absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10",
|
|
39432
|
+
style: {
|
|
39433
|
+
left: formulaRangeHighlight.left,
|
|
39434
|
+
top: formulaRangeHighlight.top,
|
|
39435
|
+
width: formulaRangeHighlight.width,
|
|
39436
|
+
height: formulaRangeHighlight.height
|
|
39437
|
+
}
|
|
39438
|
+
}
|
|
39439
|
+
),
|
|
39157
39440
|
editable && /* @__PURE__ */ jsx94(TableControls, { editor, containerRef: editorContentRef }),
|
|
39158
39441
|
/* @__PURE__ */ jsx94(
|
|
39159
39442
|
EditorContent,
|