@underverse-ui/underverse 1.0.151 → 1.0.153
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 +346 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +346 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/api-reference.json
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1030,6 +1030,9 @@ var en_default = {
|
|
|
1030
1030
|
borderColor: "Border Color",
|
|
1031
1031
|
clearBorder: "Clear Border",
|
|
1032
1032
|
formula: "Formula",
|
|
1033
|
+
numberFormat: "Number Format",
|
|
1034
|
+
formatText: "Text",
|
|
1035
|
+
formatDate: "Date",
|
|
1033
1036
|
apply: "Apply",
|
|
1034
1037
|
clear: "Clear",
|
|
1035
1038
|
recalculate: "Recalculate",
|
|
@@ -1410,6 +1413,9 @@ var vi_default = {
|
|
|
1410
1413
|
borderColor: "M\xE0u vi\u1EC1n",
|
|
1411
1414
|
clearBorder: "X\xF3a vi\u1EC1n",
|
|
1412
1415
|
formula: "C\xF4ng th\u1EE9c",
|
|
1416
|
+
numberFormat: "\u0110\u1ECBnh d\u1EA1ng s\u1ED1",
|
|
1417
|
+
formatText: "Ch\u1EEF",
|
|
1418
|
+
formatDate: "Ng\xE0y",
|
|
1413
1419
|
apply: "\xC1p d\u1EE5ng",
|
|
1414
1420
|
clear: "X\xF3a",
|
|
1415
1421
|
recalculate: "T\xEDnh l\u1EA1i",
|
|
@@ -26148,6 +26154,10 @@ function getTableCellAttrs(cell, styles, defaultBackgroundColor) {
|
|
|
26148
26154
|
if (borderAttrs.borderColor) attrs.borderColor = borderAttrs.borderColor;
|
|
26149
26155
|
if (borderAttrs.borderStyle) attrs.borderStyle = borderAttrs.borderStyle;
|
|
26150
26156
|
if (borderAttrs.borderWidth) attrs.borderWidth = borderAttrs.borderWidth;
|
|
26157
|
+
if (cell.getAttribute("data-cell-id")) attrs.cellId = cell.getAttribute("data-cell-id") ?? void 0;
|
|
26158
|
+
if (cell.getAttribute("data-number-format")) attrs.numberFormat = cell.getAttribute("data-number-format") ?? void 0;
|
|
26159
|
+
if (cell.getAttribute("data-formula")) attrs.formula = cell.getAttribute("data-formula") ?? void 0;
|
|
26160
|
+
if (cell.getAttribute("data-computed-value")) attrs.computedValue = cell.getAttribute("data-computed-value") ?? void 0;
|
|
26151
26161
|
if (colspan > 1) attrs.colspan = colspan;
|
|
26152
26162
|
if (rowspan > 1) attrs.rowspan = rowspan;
|
|
26153
26163
|
if (colwidth) attrs.colwidth = colwidth;
|
|
@@ -27775,6 +27785,16 @@ var CodeBlockView = ({
|
|
|
27775
27785
|
};
|
|
27776
27786
|
|
|
27777
27787
|
// src/components/UEditor/extensions.ts
|
|
27788
|
+
function getFormulaStateAttributes(attributes) {
|
|
27789
|
+
const formula = attributes["data-formula"];
|
|
27790
|
+
if (!formula) {
|
|
27791
|
+
return {};
|
|
27792
|
+
}
|
|
27793
|
+
const computedValue = String(attributes["data-computed-value"] ?? "");
|
|
27794
|
+
return {
|
|
27795
|
+
"data-formula-state": computedValue.startsWith("#") ? "error" : "computed"
|
|
27796
|
+
};
|
|
27797
|
+
}
|
|
27778
27798
|
var CustomTableCell = import_extension_table_cell.default.extend({
|
|
27779
27799
|
addAttributes() {
|
|
27780
27800
|
return {
|
|
@@ -27877,7 +27897,7 @@ var CustomTableCell = import_extension_table_cell.default.extend({
|
|
|
27877
27897
|
mergedStyle = mergedStyle.replace(/^;/, "").trim();
|
|
27878
27898
|
return [
|
|
27879
27899
|
"td",
|
|
27880
|
-
(0, import_core13.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, mergedStyle ? { style: mergedStyle } : {}),
|
|
27900
|
+
(0, import_core13.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, getFormulaStateAttributes(HTMLAttributes), mergedStyle ? { style: mergedStyle } : {}),
|
|
27881
27901
|
0
|
|
27882
27902
|
];
|
|
27883
27903
|
}
|
|
@@ -27984,7 +28004,7 @@ var CustomTableHeader = import_extension_table_header.default.extend({
|
|
|
27984
28004
|
mergedStyle = mergedStyle.replace(/^;/, "").trim();
|
|
27985
28005
|
return [
|
|
27986
28006
|
"th",
|
|
27987
|
-
(0, import_core13.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, mergedStyle ? { style: mergedStyle } : {}),
|
|
28007
|
+
(0, import_core13.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, getFormulaStateAttributes(HTMLAttributes), mergedStyle ? { style: mergedStyle } : {}),
|
|
27988
28008
|
0
|
|
27989
28009
|
];
|
|
27990
28010
|
}
|
|
@@ -30005,6 +30025,143 @@ function getTableCellRangeLabels(range) {
|
|
|
30005
30025
|
function normalizeTableFormula(formula) {
|
|
30006
30026
|
return formula.trim().replace(/^=/, "").trim();
|
|
30007
30027
|
}
|
|
30028
|
+
function formatFormulaError(error) {
|
|
30029
|
+
return `#${error.toUpperCase()}`;
|
|
30030
|
+
}
|
|
30031
|
+
function normalizeTableNumberFormat(format) {
|
|
30032
|
+
return format === "text" || format === "number" || format === "currency" || format === "percent" || format === "date" ? format : "text";
|
|
30033
|
+
}
|
|
30034
|
+
function formatTableFormulaDisplayValue(value, numberFormat) {
|
|
30035
|
+
const stringValue = String(value);
|
|
30036
|
+
if (stringValue.startsWith("#")) {
|
|
30037
|
+
return stringValue;
|
|
30038
|
+
}
|
|
30039
|
+
const normalizedFormat = normalizeTableNumberFormat(numberFormat);
|
|
30040
|
+
if (normalizedFormat === "text") {
|
|
30041
|
+
return stringValue;
|
|
30042
|
+
}
|
|
30043
|
+
const numericValue = typeof value === "number" ? value : Number.parseFloat(stringValue.replace(/,/g, ""));
|
|
30044
|
+
if (!Number.isFinite(numericValue)) {
|
|
30045
|
+
return stringValue;
|
|
30046
|
+
}
|
|
30047
|
+
if (normalizedFormat === "number") {
|
|
30048
|
+
return new Intl.NumberFormat("en-US", { maximumFractionDigits: 6 }).format(numericValue);
|
|
30049
|
+
}
|
|
30050
|
+
if (normalizedFormat === "currency") {
|
|
30051
|
+
return new Intl.NumberFormat("en-US", {
|
|
30052
|
+
style: "currency",
|
|
30053
|
+
currency: "USD",
|
|
30054
|
+
maximumFractionDigits: 2
|
|
30055
|
+
}).format(numericValue);
|
|
30056
|
+
}
|
|
30057
|
+
if (normalizedFormat === "percent") {
|
|
30058
|
+
return new Intl.NumberFormat("en-US", {
|
|
30059
|
+
style: "percent",
|
|
30060
|
+
maximumFractionDigits: 2
|
|
30061
|
+
}).format(numericValue);
|
|
30062
|
+
}
|
|
30063
|
+
const excelEpochMs = Date.UTC(1899, 11, 30);
|
|
30064
|
+
const date = new Date(excelEpochMs + numericValue * 24 * 60 * 60 * 1e3);
|
|
30065
|
+
if (Number.isNaN(date.getTime())) {
|
|
30066
|
+
return stringValue;
|
|
30067
|
+
}
|
|
30068
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
30069
|
+
year: "numeric",
|
|
30070
|
+
month: "2-digit",
|
|
30071
|
+
day: "2-digit",
|
|
30072
|
+
timeZone: "UTC"
|
|
30073
|
+
}).format(date);
|
|
30074
|
+
}
|
|
30075
|
+
function getTableFormulaReferences(formula) {
|
|
30076
|
+
const normalized = normalizeTableFormula(formula);
|
|
30077
|
+
if (!normalized) return [];
|
|
30078
|
+
const tokens = tokenizeFormula(normalized);
|
|
30079
|
+
if (!tokens) return [];
|
|
30080
|
+
const references = /* @__PURE__ */ new Set();
|
|
30081
|
+
for (const token of tokens) {
|
|
30082
|
+
if (token.type === "cell") {
|
|
30083
|
+
references.add(token.value);
|
|
30084
|
+
} else if (token.type === "range") {
|
|
30085
|
+
const range = parseTableCellRange(token.value);
|
|
30086
|
+
if (!range) continue;
|
|
30087
|
+
for (const label of getTableCellRangeLabels(range)) {
|
|
30088
|
+
references.add(label);
|
|
30089
|
+
}
|
|
30090
|
+
}
|
|
30091
|
+
}
|
|
30092
|
+
return Array.from(references);
|
|
30093
|
+
}
|
|
30094
|
+
function buildTableFormulaDependencyGraph(cells) {
|
|
30095
|
+
const dependencies = /* @__PURE__ */ new Map();
|
|
30096
|
+
const dependents = /* @__PURE__ */ new Map();
|
|
30097
|
+
const formulas = /* @__PURE__ */ new Map();
|
|
30098
|
+
for (const cell of cells) {
|
|
30099
|
+
const label = cell.label.toUpperCase();
|
|
30100
|
+
formulas.set(label, cell.formula);
|
|
30101
|
+
dependencies.set(label, new Set(getTableFormulaReferences(cell.formula)));
|
|
30102
|
+
if (!dependents.has(label)) {
|
|
30103
|
+
dependents.set(label, /* @__PURE__ */ new Set());
|
|
30104
|
+
}
|
|
30105
|
+
}
|
|
30106
|
+
for (const [label, refs] of dependencies) {
|
|
30107
|
+
for (const ref of refs) {
|
|
30108
|
+
if (!dependents.has(ref)) {
|
|
30109
|
+
dependents.set(ref, /* @__PURE__ */ new Set());
|
|
30110
|
+
}
|
|
30111
|
+
dependents.get(ref)?.add(label);
|
|
30112
|
+
}
|
|
30113
|
+
}
|
|
30114
|
+
return { dependencies, dependents, formulas };
|
|
30115
|
+
}
|
|
30116
|
+
function getTableFormulaCircularReferences(graph) {
|
|
30117
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
30118
|
+
const visited = /* @__PURE__ */ new Set();
|
|
30119
|
+
const circular = /* @__PURE__ */ new Set();
|
|
30120
|
+
const stack = [];
|
|
30121
|
+
const visit = (label) => {
|
|
30122
|
+
if (visiting.has(label)) {
|
|
30123
|
+
const start = stack.indexOf(label);
|
|
30124
|
+
for (const cycleLabel of start >= 0 ? stack.slice(start) : [label]) {
|
|
30125
|
+
circular.add(cycleLabel);
|
|
30126
|
+
}
|
|
30127
|
+
return;
|
|
30128
|
+
}
|
|
30129
|
+
if (visited.has(label)) return;
|
|
30130
|
+
visiting.add(label);
|
|
30131
|
+
stack.push(label);
|
|
30132
|
+
for (const ref of graph.dependencies.get(label) ?? []) {
|
|
30133
|
+
if (graph.formulas.has(ref)) {
|
|
30134
|
+
visit(ref);
|
|
30135
|
+
}
|
|
30136
|
+
}
|
|
30137
|
+
stack.pop();
|
|
30138
|
+
visiting.delete(label);
|
|
30139
|
+
visited.add(label);
|
|
30140
|
+
};
|
|
30141
|
+
for (const label of graph.formulas.keys()) {
|
|
30142
|
+
visit(label);
|
|
30143
|
+
}
|
|
30144
|
+
return circular;
|
|
30145
|
+
}
|
|
30146
|
+
function getTableFormulaRecalculationOrder(graph) {
|
|
30147
|
+
const circular = getTableFormulaCircularReferences(graph);
|
|
30148
|
+
const visited = /* @__PURE__ */ new Set();
|
|
30149
|
+
const order = [];
|
|
30150
|
+
const visit = (label) => {
|
|
30151
|
+
if (visited.has(label) || circular.has(label)) return;
|
|
30152
|
+
visited.add(label);
|
|
30153
|
+
for (const ref of graph.dependencies.get(label) ?? []) {
|
|
30154
|
+
if (graph.formulas.has(ref)) {
|
|
30155
|
+
visit(ref);
|
|
30156
|
+
}
|
|
30157
|
+
}
|
|
30158
|
+
order.push(label);
|
|
30159
|
+
};
|
|
30160
|
+
for (const label of graph.formulas.keys()) {
|
|
30161
|
+
visit(label);
|
|
30162
|
+
}
|
|
30163
|
+
return { order, circular };
|
|
30164
|
+
}
|
|
30008
30165
|
function evaluateBasicTableFormula(formula, getCellValue) {
|
|
30009
30166
|
const normalized = normalizeTableFormula(formula);
|
|
30010
30167
|
if (!normalized) {
|
|
@@ -30209,6 +30366,7 @@ var FormulaParser = class {
|
|
|
30209
30366
|
};
|
|
30210
30367
|
|
|
30211
30368
|
// src/components/UEditor/table-formula-commands.ts
|
|
30369
|
+
var UEDITOR_TABLE_FORMULA_RECALCULATE_META = "ueditorTableFormulaRecalculate";
|
|
30212
30370
|
function collectChildren2(node) {
|
|
30213
30371
|
const children = [];
|
|
30214
30372
|
node.forEach((child) => children.push(child));
|
|
@@ -30239,6 +30397,13 @@ function safeFindCell2(map, relativePos) {
|
|
|
30239
30397
|
function getCellText(cellNode) {
|
|
30240
30398
|
return cellNode.textBetween(0, cellNode.content.size, "\n").trim();
|
|
30241
30399
|
}
|
|
30400
|
+
function createCellDisplayContent(cellNode, displayValue) {
|
|
30401
|
+
const paragraphType = cellNode.type.schema.nodes.paragraph;
|
|
30402
|
+
if (!paragraphType || !displayValue) {
|
|
30403
|
+
return paragraphType ? [paragraphType.create()] : cellNode.content;
|
|
30404
|
+
}
|
|
30405
|
+
return [paragraphType.create(null, cellNode.type.schema.text(displayValue))];
|
|
30406
|
+
}
|
|
30242
30407
|
function buildTableValueGetter(tableNode) {
|
|
30243
30408
|
const map = import_tables2.TableMap.get(tableNode);
|
|
30244
30409
|
const values = /* @__PURE__ */ new Map();
|
|
@@ -30253,6 +30418,20 @@ function buildTableValueGetter(tableNode) {
|
|
|
30253
30418
|
}
|
|
30254
30419
|
return (label) => values.get(label.toUpperCase());
|
|
30255
30420
|
}
|
|
30421
|
+
function buildTableValueMap(tableNode) {
|
|
30422
|
+
const map = import_tables2.TableMap.get(tableNode);
|
|
30423
|
+
const values = /* @__PURE__ */ new Map();
|
|
30424
|
+
for (const rowInfo of getTableRows2(tableNode)) {
|
|
30425
|
+
for (const entry of rowInfo.cells) {
|
|
30426
|
+
const rect = safeFindCell2(map, entry.relativePos);
|
|
30427
|
+
if (!rect) continue;
|
|
30428
|
+
const label = `${indexToColumnName(rect.left)}${rect.top + 1}`;
|
|
30429
|
+
const computedValue = entry.node.attrs.computedValue;
|
|
30430
|
+
values.set(label, typeof computedValue === "string" && computedValue.trim() ? computedValue : getCellText(entry.node));
|
|
30431
|
+
}
|
|
30432
|
+
}
|
|
30433
|
+
return values;
|
|
30434
|
+
}
|
|
30256
30435
|
function getFormulaComputedValue(formula, tableNode) {
|
|
30257
30436
|
const result = evaluateBasicTableFormula(formula, buildTableValueGetter(tableNode));
|
|
30258
30437
|
return result.error ? `#${result.error.toUpperCase()}` : String(result.value);
|
|
@@ -30289,37 +30468,143 @@ function setSelectedTableCellFormula(editor, formula) {
|
|
|
30289
30468
|
function clearSelectedTableCellFormula(editor) {
|
|
30290
30469
|
return setSelectedTableCellFormula(editor, "");
|
|
30291
30470
|
}
|
|
30292
|
-
function
|
|
30293
|
-
const
|
|
30294
|
-
const
|
|
30295
|
-
const
|
|
30296
|
-
|
|
30471
|
+
function setSelectedTableCellNumberFormat(editor, numberFormat) {
|
|
30472
|
+
const value = numberFormat && numberFormat !== "text" ? numberFormat : null;
|
|
30473
|
+
const { state, view } = editor;
|
|
30474
|
+
const applied = (0, import_tables2.setCellAttr)("numberFormat", value)(state, view.dispatch.bind(view));
|
|
30475
|
+
if (!applied) return false;
|
|
30476
|
+
recalculateSelectedTable(editor);
|
|
30477
|
+
view.focus();
|
|
30478
|
+
dispatchTableLayoutChange(editor);
|
|
30479
|
+
return true;
|
|
30480
|
+
}
|
|
30481
|
+
function promoteFormulaTextInTableNode(tableNode) {
|
|
30297
30482
|
let changed = false;
|
|
30298
30483
|
const rows = getTableRows2(tableNode).map((rowInfo) => {
|
|
30299
30484
|
const cells = collectChildren2(rowInfo.node);
|
|
30485
|
+
for (const entry of rowInfo.cells) {
|
|
30486
|
+
const text = getCellText(entry.node);
|
|
30487
|
+
const formula = text.startsWith("=") ? normalizeFormulaInput(text) : "";
|
|
30488
|
+
if (!formula || entry.node.attrs.formula === formula) continue;
|
|
30489
|
+
cells[entry.index] = entry.node.type.create(
|
|
30490
|
+
{
|
|
30491
|
+
...entry.node.attrs,
|
|
30492
|
+
formula,
|
|
30493
|
+
computedValue: null
|
|
30494
|
+
},
|
|
30495
|
+
entry.node.content,
|
|
30496
|
+
entry.node.marks
|
|
30497
|
+
);
|
|
30498
|
+
changed = true;
|
|
30499
|
+
}
|
|
30500
|
+
return rowInfo.node.type.create(rowInfo.node.attrs, cells);
|
|
30501
|
+
});
|
|
30502
|
+
return {
|
|
30503
|
+
tableNode: changed ? tableNode.type.create(tableNode.attrs, rows) : tableNode,
|
|
30504
|
+
changed
|
|
30505
|
+
};
|
|
30506
|
+
}
|
|
30507
|
+
function recalculateTableNode(tableNode) {
|
|
30508
|
+
const promoted = promoteFormulaTextInTableNode(tableNode);
|
|
30509
|
+
tableNode = promoted.tableNode;
|
|
30510
|
+
const map = import_tables2.TableMap.get(tableNode);
|
|
30511
|
+
const values = buildTableValueMap(tableNode);
|
|
30512
|
+
const formulaEntries = /* @__PURE__ */ new Map();
|
|
30513
|
+
let changed = false;
|
|
30514
|
+
const rowInfos = getTableRows2(tableNode);
|
|
30515
|
+
for (const [rowIndex, rowInfo] of rowInfos.entries()) {
|
|
30300
30516
|
for (const entry of rowInfo.cells) {
|
|
30301
30517
|
const formula = typeof entry.node.attrs.formula === "string" ? entry.node.attrs.formula.trim() : "";
|
|
30302
30518
|
if (!formula) continue;
|
|
30303
30519
|
const rectForCell = safeFindCell2(map, entry.relativePos);
|
|
30304
30520
|
if (!rectForCell) continue;
|
|
30305
|
-
const
|
|
30306
|
-
|
|
30307
|
-
|
|
30521
|
+
const label = `${indexToColumnName(rectForCell.left)}${rectForCell.top + 1}`;
|
|
30522
|
+
formulaEntries.set(label, {
|
|
30523
|
+
rowIndex,
|
|
30524
|
+
cellIndex: entry.index,
|
|
30525
|
+
node: entry.node,
|
|
30526
|
+
formula
|
|
30527
|
+
});
|
|
30528
|
+
}
|
|
30529
|
+
}
|
|
30530
|
+
const graph = buildTableFormulaDependencyGraph(
|
|
30531
|
+
Array.from(formulaEntries, ([label, entry]) => ({
|
|
30532
|
+
label,
|
|
30533
|
+
formula: entry.formula
|
|
30534
|
+
}))
|
|
30535
|
+
);
|
|
30536
|
+
const { order, circular } = getTableFormulaRecalculationOrder(graph);
|
|
30537
|
+
const computedValues = /* @__PURE__ */ new Map();
|
|
30538
|
+
const getCellValue = (label) => values.get(label.toUpperCase());
|
|
30539
|
+
for (const label of circular) {
|
|
30540
|
+
computedValues.set(label, formatFormulaError("circular-reference"));
|
|
30541
|
+
values.set(label, formatFormulaError("circular-reference"));
|
|
30542
|
+
}
|
|
30543
|
+
for (const label of order) {
|
|
30544
|
+
const entry = formulaEntries.get(label);
|
|
30545
|
+
if (!entry) continue;
|
|
30546
|
+
const result = evaluateBasicTableFormula(entry.formula, getCellValue);
|
|
30547
|
+
const computedValue = result.error ? formatFormulaError(result.error) : String(result.value);
|
|
30548
|
+
computedValues.set(label, computedValue);
|
|
30549
|
+
values.set(label, computedValue);
|
|
30550
|
+
}
|
|
30551
|
+
const rows = rowInfos.map((rowInfo) => {
|
|
30552
|
+
const cells = collectChildren2(rowInfo.node);
|
|
30553
|
+
for (const entry of rowInfo.cells) {
|
|
30554
|
+
const rectForCell = safeFindCell2(map, entry.relativePos);
|
|
30555
|
+
if (!rectForCell) continue;
|
|
30556
|
+
const label = `${indexToColumnName(rectForCell.left)}${rectForCell.top + 1}`;
|
|
30557
|
+
const computedValue = computedValues.get(label);
|
|
30558
|
+
if (computedValue == null) continue;
|
|
30559
|
+
const displayValue = formatTableFormulaDisplayValue(computedValue, entry.node.attrs.numberFormat);
|
|
30560
|
+
const contentMatchesComputedValue = getCellText(entry.node) === displayValue;
|
|
30561
|
+
if (entry.node.attrs.computedValue === computedValue && contentMatchesComputedValue) continue;
|
|
30308
30562
|
cells[entry.index] = entry.node.type.create(
|
|
30309
30563
|
{
|
|
30310
30564
|
...entry.node.attrs,
|
|
30311
30565
|
computedValue
|
|
30312
30566
|
},
|
|
30313
|
-
entry.node
|
|
30567
|
+
createCellDisplayContent(entry.node, displayValue),
|
|
30314
30568
|
entry.node.marks
|
|
30315
30569
|
);
|
|
30316
30570
|
changed = true;
|
|
30317
30571
|
}
|
|
30318
30572
|
return rowInfo.node.type.create(rowInfo.node.attrs, cells);
|
|
30319
30573
|
});
|
|
30320
|
-
if (!changed) return
|
|
30321
|
-
|
|
30322
|
-
|
|
30574
|
+
if (!changed) return promoted.changed ? tableNode : null;
|
|
30575
|
+
return tableNode.type.create(tableNode.attrs, rows);
|
|
30576
|
+
}
|
|
30577
|
+
function recalculateSelectedTable(editor) {
|
|
30578
|
+
const rect = (0, import_tables2.selectedRect)(editor.state);
|
|
30579
|
+
const tableNode = rect.table;
|
|
30580
|
+
const nextTable = recalculateTableNode(tableNode);
|
|
30581
|
+
if (!nextTable) return false;
|
|
30582
|
+
editor.view.dispatch(
|
|
30583
|
+
editor.state.tr.replaceWith(rect.tableStart - 1, rect.tableStart - 1 + tableNode.nodeSize, nextTable).setMeta(UEDITOR_TABLE_FORMULA_RECALCULATE_META, true)
|
|
30584
|
+
);
|
|
30585
|
+
dispatchTableLayoutChange(editor);
|
|
30586
|
+
return true;
|
|
30587
|
+
}
|
|
30588
|
+
function recalculateAllTableFormulas(editor) {
|
|
30589
|
+
const replacements = [];
|
|
30590
|
+
editor.state.doc.descendants((node, pos) => {
|
|
30591
|
+
if (node.type.name !== "table") return true;
|
|
30592
|
+
const nextTable = recalculateTableNode(node);
|
|
30593
|
+
if (nextTable) {
|
|
30594
|
+
replacements.push({
|
|
30595
|
+
from: pos,
|
|
30596
|
+
to: pos + node.nodeSize,
|
|
30597
|
+
node: nextTable
|
|
30598
|
+
});
|
|
30599
|
+
}
|
|
30600
|
+
return false;
|
|
30601
|
+
});
|
|
30602
|
+
if (replacements.length === 0) return false;
|
|
30603
|
+
let tr = editor.state.tr;
|
|
30604
|
+
for (const replacement of replacements.reverse()) {
|
|
30605
|
+
tr = tr.replaceWith(replacement.from, replacement.to, replacement.node);
|
|
30606
|
+
}
|
|
30607
|
+
editor.view.dispatch(tr.setMeta(UEDITOR_TABLE_FORMULA_RECALCULATE_META, true));
|
|
30323
30608
|
dispatchTableLayoutChange(editor);
|
|
30324
30609
|
return true;
|
|
30325
30610
|
}
|
|
@@ -30368,6 +30653,7 @@ var BubbleMenuContent = ({
|
|
|
30368
30653
|
const currentHighlightColor = normalizeStyleValue(editor.getAttributes("highlight").color) || "";
|
|
30369
30654
|
const currentCellBgColor = normalizeStyleValue(editor.getAttributes("tableCell").backgroundColor || editor.getAttributes("tableHeader").backgroundColor) || "";
|
|
30370
30655
|
const currentCellFormula = normalizeStyleValue(editor.getAttributes("tableCell").formula || editor.getAttributes("tableHeader").formula) || "";
|
|
30656
|
+
const currentCellNumberFormat = normalizeStyleValue(editor.getAttributes("tableCell").numberFormat || editor.getAttributes("tableHeader").numberFormat) || "text";
|
|
30371
30657
|
const isInTable2 = (0, import_tables3.isInTable)(editor.state);
|
|
30372
30658
|
const canMergeCells = isInTable2 && editor.can().mergeCells();
|
|
30373
30659
|
const canSplitCell = isInTable2 && editor.can().splitCell();
|
|
@@ -30627,6 +30913,28 @@ var BubbleMenuContent = ({
|
|
|
30627
30913
|
className: "h-full min-w-0 flex-1 bg-transparent px-2 text-sm font-medium text-foreground outline-none"
|
|
30628
30914
|
}
|
|
30629
30915
|
) }),
|
|
30916
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "mt-2", children: [
|
|
30917
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "mb-1 px-1 text-[11px] font-medium text-muted-foreground", children: t("tableMenu.numberFormat") || "Number format" }),
|
|
30918
|
+
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "grid grid-cols-5 gap-1", children: [
|
|
30919
|
+
["text", "Text"],
|
|
30920
|
+
["number", "123"],
|
|
30921
|
+
["currency", "$"],
|
|
30922
|
+
["percent", "%"],
|
|
30923
|
+
["date", "Date"]
|
|
30924
|
+
].map(([format, label]) => /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
|
|
30925
|
+
"button",
|
|
30926
|
+
{
|
|
30927
|
+
type: "button",
|
|
30928
|
+
onClick: () => setSelectedTableCellNumberFormat(editor, format),
|
|
30929
|
+
className: cn(
|
|
30930
|
+
"h-8 rounded-md text-[11px] font-semibold transition-colors hover:bg-muted",
|
|
30931
|
+
currentCellNumberFormat === format || format === "text" && !currentCellNumberFormat ? "bg-primary/10 text-primary" : "bg-muted/40 text-foreground"
|
|
30932
|
+
),
|
|
30933
|
+
children: format === "text" ? t("tableMenu.formatText") || label : format === "date" ? t("tableMenu.formatDate") || label : label
|
|
30934
|
+
},
|
|
30935
|
+
format
|
|
30936
|
+
)) })
|
|
30937
|
+
] }),
|
|
30630
30938
|
/* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "mt-2 grid grid-cols-3 gap-1", children: [
|
|
30631
30939
|
/* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
|
|
30632
30940
|
"button",
|
|
@@ -38317,6 +38625,7 @@ var UEditor = import_react69.default.forwardRef(({
|
|
|
38317
38625
|
const effectivePlaceholder = placeholder ?? t("placeholder");
|
|
38318
38626
|
const inFlightPrepareRef = (0, import_react69.useRef)(null);
|
|
38319
38627
|
const lastAppliedContentRef = (0, import_react69.useRef)(content ?? "");
|
|
38628
|
+
const scheduledFormulaRecalculateRef = (0, import_react69.useRef)(false);
|
|
38320
38629
|
const resolvedUploadFile = (0, import_react69.useMemo)(() => {
|
|
38321
38630
|
if (uploadFile) return uploadFile;
|
|
38322
38631
|
if (uploadFileForSave) {
|
|
@@ -38380,7 +38689,16 @@ var UEditor = import_react69.default.forwardRef(({
|
|
|
38380
38689
|
class: UEDITOR_PROSEMIRROR_CLASS_NAME
|
|
38381
38690
|
}
|
|
38382
38691
|
},
|
|
38383
|
-
onUpdate: ({ editor: editor2 }) => {
|
|
38692
|
+
onUpdate: ({ editor: editor2, transaction }) => {
|
|
38693
|
+
if (!transaction.getMeta(UEDITOR_TABLE_FORMULA_RECALCULATE_META) && !scheduledFormulaRecalculateRef.current) {
|
|
38694
|
+
scheduledFormulaRecalculateRef.current = true;
|
|
38695
|
+
queueMicrotask(() => {
|
|
38696
|
+
scheduledFormulaRecalculateRef.current = false;
|
|
38697
|
+
if (!editor2.isDestroyed) {
|
|
38698
|
+
recalculateAllTableFormulas(editor2);
|
|
38699
|
+
}
|
|
38700
|
+
});
|
|
38701
|
+
}
|
|
38384
38702
|
const html = editor2.getHTML();
|
|
38385
38703
|
onChange?.(html);
|
|
38386
38704
|
onHtmlChange?.(html);
|
|
@@ -38418,6 +38736,14 @@ var UEditor = import_react69.default.forwardRef(({
|
|
|
38418
38736
|
}),
|
|
38419
38737
|
[content, editor, uploadImageForSave, uploadFileForSave, uploadImageConcurrency]
|
|
38420
38738
|
);
|
|
38739
|
+
(0, import_react69.useEffect)(() => {
|
|
38740
|
+
if (!editor) return;
|
|
38741
|
+
queueMicrotask(() => {
|
|
38742
|
+
if (!editor.isDestroyed) {
|
|
38743
|
+
recalculateAllTableFormulas(editor);
|
|
38744
|
+
}
|
|
38745
|
+
});
|
|
38746
|
+
}, [editor]);
|
|
38421
38747
|
(0, import_react69.useEffect)(() => {
|
|
38422
38748
|
if (!editor) return;
|
|
38423
38749
|
const nextContent = content ?? "";
|
|
@@ -38427,6 +38753,11 @@ var UEditor = import_react69.default.forwardRef(({
|
|
|
38427
38753
|
Promise.resolve().then(() => {
|
|
38428
38754
|
if (!editor.isDestroyed) {
|
|
38429
38755
|
editor.commands.setContent(nextContent, { emitUpdate: false });
|
|
38756
|
+
queueMicrotask(() => {
|
|
38757
|
+
if (!editor.isDestroyed) {
|
|
38758
|
+
recalculateAllTableFormulas(editor);
|
|
38759
|
+
}
|
|
38760
|
+
});
|
|
38430
38761
|
}
|
|
38431
38762
|
});
|
|
38432
38763
|
}
|