@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/api-reference.json +1 -1
- package/dist/index.cjs +592 -234
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +571 -213
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -27548,8 +27548,8 @@ function useLocale2() {
|
|
|
27548
27548
|
}
|
|
27549
27549
|
|
|
27550
27550
|
// src/components/UEditor/UEditor.tsx
|
|
27551
|
-
var
|
|
27552
|
-
var
|
|
27551
|
+
var import_react80 = __toESM(require("react"), 1);
|
|
27552
|
+
var import_react81 = require("@tiptap/react");
|
|
27553
27553
|
|
|
27554
27554
|
// src/components/UEditor/extensions.ts
|
|
27555
27555
|
var import_core16 = require("@tiptap/core");
|
|
@@ -30067,11 +30067,17 @@ function isInTableCell(editor) {
|
|
|
30067
30067
|
}
|
|
30068
30068
|
function buildFormulaSuggestionItems({ query }) {
|
|
30069
30069
|
const normalizedQuery = query.trim().toUpperCase();
|
|
30070
|
+
if (!isFormulaFunctionSuggestionQuery(normalizedQuery)) {
|
|
30071
|
+
return [];
|
|
30072
|
+
}
|
|
30070
30073
|
if (!normalizedQuery) {
|
|
30071
30074
|
return FORMULA_FUNCTIONS;
|
|
30072
30075
|
}
|
|
30073
30076
|
return FORMULA_FUNCTIONS.filter((item) => item.name.startsWith(normalizedQuery));
|
|
30074
30077
|
}
|
|
30078
|
+
function isFormulaFunctionSuggestionQuery(query) {
|
|
30079
|
+
return /^[A-Z]*$/i.test(query.trim());
|
|
30080
|
+
}
|
|
30075
30081
|
var FormulaSuggestionList = (0, import_react62.forwardRef)((props, ref) => {
|
|
30076
30082
|
const t = useSmartTranslations("UEditor");
|
|
30077
30083
|
const [selectedIndex, setSelectedIndex] = import_react62.default.useState(0);
|
|
@@ -30142,7 +30148,11 @@ var FormulaSuggestion = import_core9.Extension.create({
|
|
|
30142
30148
|
editor: this.editor,
|
|
30143
30149
|
char: "=",
|
|
30144
30150
|
pluginKey: new import_state4.PluginKey("formulaSuggestion"),
|
|
30145
|
-
allow: ({ editor }) =>
|
|
30151
|
+
allow: ({ editor, range }) => {
|
|
30152
|
+
if (!isInTableCell(editor)) return false;
|
|
30153
|
+
const suggestionText = editor.state.doc.textBetween(range.from, range.to, "", "");
|
|
30154
|
+
return suggestionText.startsWith("=") && isFormulaFunctionSuggestionQuery(suggestionText.slice(1));
|
|
30155
|
+
},
|
|
30146
30156
|
command: ({ editor, range, props }) => {
|
|
30147
30157
|
insertFormulaFunction(editor, range, props);
|
|
30148
30158
|
},
|
|
@@ -34071,51 +34081,98 @@ function buildTableFormulaDependencyGraph(cells) {
|
|
|
34071
34081
|
return { dependencies, dependents, formulas };
|
|
34072
34082
|
}
|
|
34073
34083
|
function getTableFormulaCircularReferences(graph) {
|
|
34074
|
-
const visiting = /* @__PURE__ */ new Set();
|
|
34075
|
-
const visited = /* @__PURE__ */ new Set();
|
|
34076
34084
|
const circular = /* @__PURE__ */ new Set();
|
|
34077
|
-
const
|
|
34078
|
-
const
|
|
34079
|
-
|
|
34080
|
-
|
|
34081
|
-
|
|
34082
|
-
|
|
34085
|
+
const visited = /* @__PURE__ */ new Set();
|
|
34086
|
+
const finishOrder = [];
|
|
34087
|
+
for (const startLabel of graph.formulas.keys()) {
|
|
34088
|
+
if (visited.has(startLabel)) continue;
|
|
34089
|
+
visited.add(startLabel);
|
|
34090
|
+
const stack = [
|
|
34091
|
+
{
|
|
34092
|
+
label: startLabel,
|
|
34093
|
+
references: Array.from(graph.dependencies.get(startLabel) ?? []).filter((ref) => graph.formulas.has(ref)),
|
|
34094
|
+
nextIndex: 0
|
|
34083
34095
|
}
|
|
34084
|
-
|
|
34085
|
-
|
|
34086
|
-
|
|
34087
|
-
|
|
34088
|
-
|
|
34089
|
-
|
|
34090
|
-
|
|
34091
|
-
|
|
34096
|
+
];
|
|
34097
|
+
while (stack.length > 0) {
|
|
34098
|
+
const frame = stack[stack.length - 1];
|
|
34099
|
+
if (!frame) break;
|
|
34100
|
+
const reference = frame.references[frame.nextIndex];
|
|
34101
|
+
if (reference) {
|
|
34102
|
+
frame.nextIndex += 1;
|
|
34103
|
+
if (!visited.has(reference)) {
|
|
34104
|
+
visited.add(reference);
|
|
34105
|
+
stack.push({
|
|
34106
|
+
label: reference,
|
|
34107
|
+
references: Array.from(graph.dependencies.get(reference) ?? []).filter((ref) => graph.formulas.has(ref)),
|
|
34108
|
+
nextIndex: 0
|
|
34109
|
+
});
|
|
34110
|
+
}
|
|
34111
|
+
continue;
|
|
34092
34112
|
}
|
|
34113
|
+
stack.pop();
|
|
34114
|
+
finishOrder.push(frame.label);
|
|
34115
|
+
}
|
|
34116
|
+
}
|
|
34117
|
+
const assigned = /* @__PURE__ */ new Set();
|
|
34118
|
+
for (let index = finishOrder.length - 1; index >= 0; index -= 1) {
|
|
34119
|
+
const startLabel = finishOrder[index];
|
|
34120
|
+
if (!startLabel || assigned.has(startLabel)) continue;
|
|
34121
|
+
const component = [];
|
|
34122
|
+
const stack = [startLabel];
|
|
34123
|
+
assigned.add(startLabel);
|
|
34124
|
+
while (stack.length > 0) {
|
|
34125
|
+
const label = stack.pop();
|
|
34126
|
+
if (!label) continue;
|
|
34127
|
+
component.push(label);
|
|
34128
|
+
for (const dependent of graph.dependents.get(label) ?? []) {
|
|
34129
|
+
if (!graph.formulas.has(dependent) || assigned.has(dependent)) continue;
|
|
34130
|
+
assigned.add(dependent);
|
|
34131
|
+
stack.push(dependent);
|
|
34132
|
+
}
|
|
34133
|
+
}
|
|
34134
|
+
if (component.length > 1) {
|
|
34135
|
+
for (const label of component) circular.add(label);
|
|
34136
|
+
} else {
|
|
34137
|
+
const label = component[0];
|
|
34138
|
+
if (label && graph.dependencies.get(label)?.has(label)) circular.add(label);
|
|
34093
34139
|
}
|
|
34094
|
-
stack.pop();
|
|
34095
|
-
visiting.delete(label);
|
|
34096
|
-
visited.add(label);
|
|
34097
|
-
};
|
|
34098
|
-
for (const label of graph.formulas.keys()) {
|
|
34099
|
-
visit(label);
|
|
34100
34140
|
}
|
|
34101
34141
|
return circular;
|
|
34102
34142
|
}
|
|
34103
34143
|
function getTableFormulaRecalculationOrder(graph) {
|
|
34104
34144
|
const circular = getTableFormulaCircularReferences(graph);
|
|
34145
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
34105
34146
|
const visited = /* @__PURE__ */ new Set();
|
|
34106
34147
|
const order = [];
|
|
34107
|
-
const
|
|
34108
|
-
if (visited.has(
|
|
34109
|
-
|
|
34110
|
-
|
|
34111
|
-
|
|
34112
|
-
|
|
34148
|
+
for (const startLabel of graph.formulas.keys()) {
|
|
34149
|
+
if (visited.has(startLabel) || circular.has(startLabel)) continue;
|
|
34150
|
+
const stack = [];
|
|
34151
|
+
const push = (label) => {
|
|
34152
|
+
visiting.add(label);
|
|
34153
|
+
stack.push({
|
|
34154
|
+
label,
|
|
34155
|
+
references: Array.from(graph.dependencies.get(label) ?? []).filter((ref) => graph.formulas.has(ref) && !circular.has(ref)),
|
|
34156
|
+
nextIndex: 0
|
|
34157
|
+
});
|
|
34158
|
+
};
|
|
34159
|
+
push(startLabel);
|
|
34160
|
+
while (stack.length > 0) {
|
|
34161
|
+
const frame = stack[stack.length - 1];
|
|
34162
|
+
if (!frame) break;
|
|
34163
|
+
const reference = frame.references[frame.nextIndex];
|
|
34164
|
+
if (reference) {
|
|
34165
|
+
frame.nextIndex += 1;
|
|
34166
|
+
if (!visited.has(reference) && !visiting.has(reference)) {
|
|
34167
|
+
push(reference);
|
|
34168
|
+
}
|
|
34169
|
+
continue;
|
|
34113
34170
|
}
|
|
34171
|
+
stack.pop();
|
|
34172
|
+
visiting.delete(frame.label);
|
|
34173
|
+
visited.add(frame.label);
|
|
34174
|
+
order.push(frame.label);
|
|
34114
34175
|
}
|
|
34115
|
-
order.push(label);
|
|
34116
|
-
};
|
|
34117
|
-
for (const label of graph.formulas.keys()) {
|
|
34118
|
-
visit(label);
|
|
34119
34176
|
}
|
|
34120
34177
|
return { order, circular };
|
|
34121
34178
|
}
|
|
@@ -34174,9 +34231,11 @@ function tokenizeFormula(formula) {
|
|
|
34174
34231
|
index += 1;
|
|
34175
34232
|
continue;
|
|
34176
34233
|
}
|
|
34177
|
-
const numberMatch = formula.slice(index).match(
|
|
34234
|
+
const numberMatch = formula.slice(index).match(/^(?:\d+(?:\.\d*)?|\.\d+)/);
|
|
34178
34235
|
if (numberMatch?.[0]) {
|
|
34179
|
-
|
|
34236
|
+
const value = Number.parseFloat(numberMatch[0]);
|
|
34237
|
+
if (!Number.isFinite(value)) return null;
|
|
34238
|
+
tokens.push({ type: "number", value });
|
|
34180
34239
|
index += numberMatch[0].length;
|
|
34181
34240
|
continue;
|
|
34182
34241
|
}
|
|
@@ -34194,6 +34253,28 @@ function tokenizeFormula(formula) {
|
|
|
34194
34253
|
}
|
|
34195
34254
|
return tokens;
|
|
34196
34255
|
}
|
|
34256
|
+
function toFiniteFormulaResult(value) {
|
|
34257
|
+
return Number.isFinite(value) ? { value, error: null } : { value: null, error: "invalid-formula" };
|
|
34258
|
+
}
|
|
34259
|
+
function parseTableCellNumericValue(value) {
|
|
34260
|
+
if (typeof value === "number") {
|
|
34261
|
+
return Number.isFinite(value) ? value : null;
|
|
34262
|
+
}
|
|
34263
|
+
let normalized = String(value ?? "").trim();
|
|
34264
|
+
if (!normalized || normalized.startsWith("#")) return null;
|
|
34265
|
+
const isPercent = normalized.endsWith("%");
|
|
34266
|
+
if (isPercent) normalized = normalized.slice(0, -1).trim();
|
|
34267
|
+
const currencyMatch = normalized.match(/^([+-]?)\$(.+)$/);
|
|
34268
|
+
if (currencyMatch) {
|
|
34269
|
+
normalized = `${currencyMatch[1] ?? ""}${currencyMatch[2] ?? ""}`.trim();
|
|
34270
|
+
}
|
|
34271
|
+
const groupedNumber = /^[+-]?\d{1,3}(?:,\d{3})+(?:\.\d*)?(?:[eE][+-]?\d+)?$/;
|
|
34272
|
+
const plainNumber = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/;
|
|
34273
|
+
if (!groupedNumber.test(normalized) && !plainNumber.test(normalized)) return null;
|
|
34274
|
+
const parsed = Number(normalized.replace(/,/g, ""));
|
|
34275
|
+
if (!Number.isFinite(parsed)) return null;
|
|
34276
|
+
return isPercent ? parsed / 100 : parsed;
|
|
34277
|
+
}
|
|
34197
34278
|
var FormulaParser = class {
|
|
34198
34279
|
constructor(tokens, getCellValue) {
|
|
34199
34280
|
this.tokens = tokens;
|
|
@@ -34211,10 +34292,7 @@ var FormulaParser = class {
|
|
|
34211
34292
|
this.index += 1;
|
|
34212
34293
|
const right = this.parseTerm();
|
|
34213
34294
|
if (right.error) return right;
|
|
34214
|
-
left =
|
|
34215
|
-
value: operator.value === "+" ? left.value + right.value : left.value - right.value,
|
|
34216
|
-
error: null
|
|
34217
|
-
};
|
|
34295
|
+
left = toFiniteFormulaResult(operator.value === "+" ? left.value + right.value : left.value - right.value);
|
|
34218
34296
|
}
|
|
34219
34297
|
return left;
|
|
34220
34298
|
}
|
|
@@ -34229,10 +34307,7 @@ var FormulaParser = class {
|
|
|
34229
34307
|
if (operator.value === "/" && right.value === 0) {
|
|
34230
34308
|
return { value: null, error: "division-by-zero" };
|
|
34231
34309
|
}
|
|
34232
|
-
left =
|
|
34233
|
-
value: operator.value === "*" ? left.value * right.value : left.value / right.value,
|
|
34234
|
-
error: null
|
|
34235
|
-
};
|
|
34310
|
+
left = toFiniteFormulaResult(operator.value === "*" ? left.value * right.value : left.value / right.value);
|
|
34236
34311
|
}
|
|
34237
34312
|
return left;
|
|
34238
34313
|
}
|
|
@@ -34241,11 +34316,11 @@ var FormulaParser = class {
|
|
|
34241
34316
|
if (!token) {
|
|
34242
34317
|
return { value: null, error: "invalid-formula" };
|
|
34243
34318
|
}
|
|
34244
|
-
if (token.type === "operator" && token.value === "-") {
|
|
34319
|
+
if (token.type === "operator" && (token.value === "-" || token.value === "+")) {
|
|
34245
34320
|
this.index += 1;
|
|
34246
34321
|
const value = this.parseFactor();
|
|
34247
34322
|
if (value.error) return value;
|
|
34248
|
-
return
|
|
34323
|
+
return toFiniteFormulaResult(token.value === "-" ? -value.value : value.value);
|
|
34249
34324
|
}
|
|
34250
34325
|
if (token.type === "number") {
|
|
34251
34326
|
this.index += 1;
|
|
@@ -34290,11 +34365,10 @@ var FormulaParser = class {
|
|
|
34290
34365
|
if (cellValue2 != null) values.push(cellValue2);
|
|
34291
34366
|
continue;
|
|
34292
34367
|
}
|
|
34293
|
-
const cellValue = this.
|
|
34294
|
-
if (cellValue
|
|
34295
|
-
values.push(cellValue.value);
|
|
34368
|
+
const cellValue = this.readOptionalCellNumber(label);
|
|
34369
|
+
if (cellValue != null) values.push(cellValue);
|
|
34296
34370
|
}
|
|
34297
|
-
} else if (
|
|
34371
|
+
} else if (token.type === "cell") {
|
|
34298
34372
|
this.index += 1;
|
|
34299
34373
|
const cellValue = this.readOptionalCellNumber(token.value);
|
|
34300
34374
|
if (cellValue != null) values.push(cellValue);
|
|
@@ -34311,28 +34385,24 @@ var FormulaParser = class {
|
|
|
34311
34385
|
}
|
|
34312
34386
|
return { value: null, error: "invalid-formula" };
|
|
34313
34387
|
}
|
|
34314
|
-
if (values.
|
|
34315
|
-
|
|
34388
|
+
if (name === "SUM") return toFiniteFormulaResult(values.reduce((sum, value) => sum + value, 0));
|
|
34389
|
+
if (name === "AVG") {
|
|
34390
|
+
return values.length > 0 ? toFiniteFormulaResult(values.reduce((sum, value) => sum + value, 0) / values.length) : { value: null, error: "division-by-zero" };
|
|
34316
34391
|
}
|
|
34317
|
-
if (name === "
|
|
34318
|
-
if (name === "
|
|
34319
|
-
if (name === "MIN") return { value: Math.min(...values), error: null };
|
|
34320
|
-
if (name === "MAX") return { value: Math.max(...values), error: null };
|
|
34392
|
+
if (name === "MIN") return toFiniteFormulaResult(values.length > 0 ? Math.min(...values) : 0);
|
|
34393
|
+
if (name === "MAX") return toFiniteFormulaResult(values.length > 0 ? Math.max(...values) : 0);
|
|
34321
34394
|
if (name === "COUNT") return { value: values.length, error: null };
|
|
34322
34395
|
return { value: null, error: "invalid-formula" };
|
|
34323
34396
|
}
|
|
34324
34397
|
readCellNumber(label) {
|
|
34325
|
-
const
|
|
34326
|
-
|
|
34327
|
-
if (!Number.isFinite(parsed)) {
|
|
34398
|
+
const parsed = parseTableCellNumericValue(this.getCellValue(label));
|
|
34399
|
+
if (parsed == null) {
|
|
34328
34400
|
return { value: null, error: "invalid-reference" };
|
|
34329
34401
|
}
|
|
34330
34402
|
return { value: parsed, error: null };
|
|
34331
34403
|
}
|
|
34332
34404
|
readOptionalCellNumber(label) {
|
|
34333
|
-
|
|
34334
|
-
const parsed = typeof value === "number" ? value : Number.parseFloat(String(value ?? "").trim());
|
|
34335
|
-
return Number.isFinite(parsed) ? parsed : null;
|
|
34405
|
+
return parseTableCellNumericValue(this.getCellValue(label));
|
|
34336
34406
|
}
|
|
34337
34407
|
peekOperator(operators) {
|
|
34338
34408
|
const token = this.tokens[this.index];
|
|
@@ -35448,7 +35518,7 @@ var CustomBubbleMenu = ({
|
|
|
35448
35518
|
const BUBBLE_MENU_ESTIMATED_HEIGHT = 44;
|
|
35449
35519
|
const [isVisible, setIsVisible] = (0, import_react72.useState)(false);
|
|
35450
35520
|
const [linkInputOpen, setLinkInputOpen] = (0, import_react72.useState)(false);
|
|
35451
|
-
const [position,
|
|
35521
|
+
const [position, setPosition2] = (0, import_react72.useState)({
|
|
35452
35522
|
top: 0,
|
|
35453
35523
|
left: 0,
|
|
35454
35524
|
placement: "top"
|
|
@@ -35520,7 +35590,7 @@ var CustomBubbleMenu = ({
|
|
|
35520
35590
|
Math.max(viewportPadding, (start.left + end.left) / 2)
|
|
35521
35591
|
);
|
|
35522
35592
|
const top = placement === "top" ? Math.max(viewportPadding, selectionTop - BUBBLE_MENU_OFFSET) : Math.min(window.innerHeight - viewportPadding, selectionBottom + BUBBLE_MENU_OFFSET);
|
|
35523
|
-
|
|
35593
|
+
setPosition2({ top, left, placement });
|
|
35524
35594
|
if (keepOpenRef.current) {
|
|
35525
35595
|
clearShowTimeout();
|
|
35526
35596
|
setIsVisible(true);
|
|
@@ -42038,9 +42108,402 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
42038
42108
|
};
|
|
42039
42109
|
}
|
|
42040
42110
|
|
|
42111
|
+
// src/components/UEditor/use-formula-coordinate-overlay.ts
|
|
42112
|
+
var import_react77 = require("react");
|
|
42113
|
+
var import_tables8 = require("@tiptap/pm/tables");
|
|
42114
|
+
|
|
42115
|
+
// src/components/UEditor/table-formula-range-picker.ts
|
|
42116
|
+
var import_state10 = require("@tiptap/pm/state");
|
|
42117
|
+
var import_tables7 = require("@tiptap/pm/tables");
|
|
42118
|
+
function getCellText2(cellNode) {
|
|
42119
|
+
return cellNode.textBetween(0, cellNode.content.size, "\n").trim();
|
|
42120
|
+
}
|
|
42121
|
+
function getFormulaEditingTableContext(view) {
|
|
42122
|
+
const { $from } = view.state.selection;
|
|
42123
|
+
for (let depth = $from.depth; depth > 0; depth -= 1) {
|
|
42124
|
+
const node = $from.node(depth);
|
|
42125
|
+
if (node.type.name !== "tableCell" && node.type.name !== "tableHeader") continue;
|
|
42126
|
+
if (!getCellText2(node).startsWith("=")) return null;
|
|
42127
|
+
const cellPos = $from.before(depth);
|
|
42128
|
+
const cellDom = view.nodeDOM(cellPos);
|
|
42129
|
+
if (!(cellDom instanceof HTMLTableCellElement)) return null;
|
|
42130
|
+
const tableDepth = depth - 2;
|
|
42131
|
+
const tableNode = tableDepth > 0 ? $from.node(tableDepth) : null;
|
|
42132
|
+
if (!tableNode || tableNode.type.name !== "table") return null;
|
|
42133
|
+
const tableDom = cellDom.closest("table");
|
|
42134
|
+
if (!(tableDom instanceof HTMLTableElement)) return null;
|
|
42135
|
+
return {
|
|
42136
|
+
cellContentEnd: $from.end(depth),
|
|
42137
|
+
cellContentStart: $from.start(depth),
|
|
42138
|
+
cellDom,
|
|
42139
|
+
formula: getCellText2(node),
|
|
42140
|
+
tableDom,
|
|
42141
|
+
tableNode,
|
|
42142
|
+
tablePos: $from.before(tableDepth)
|
|
42143
|
+
};
|
|
42144
|
+
}
|
|
42145
|
+
return null;
|
|
42146
|
+
}
|
|
42147
|
+
function cancelFormulaEditing(view) {
|
|
42148
|
+
const context = getFormulaEditingTableContext(view);
|
|
42149
|
+
if (!context) return false;
|
|
42150
|
+
let tr = view.state.tr.delete(context.cellContentStart, context.cellContentEnd);
|
|
42151
|
+
const selectionPos = Math.min(context.cellContentStart, tr.doc.content.size);
|
|
42152
|
+
tr = tr.setSelection(import_state10.TextSelection.near(tr.doc.resolve(selectionPos)));
|
|
42153
|
+
view.dispatch(tr);
|
|
42154
|
+
view.focus();
|
|
42155
|
+
return true;
|
|
42156
|
+
}
|
|
42157
|
+
function getReferenceInsertionPrefix(view, cellContentStart, insertionPos) {
|
|
42158
|
+
const textBeforeCursor = view.state.doc.textBetween(cellContentStart, insertionPos, "", "");
|
|
42159
|
+
const isInsideFunctionArguments = /[A-Z]+\([^)]*$/i.test(textBeforeCursor);
|
|
42160
|
+
const followsReference = /[A-Z]+[1-9]\d*(?::[A-Z]+[1-9]\d*)?\s*$/i.test(textBeforeCursor);
|
|
42161
|
+
return isInsideFunctionArguments && followsReference ? "," : "";
|
|
42162
|
+
}
|
|
42163
|
+
function findTableForPos(view, pos) {
|
|
42164
|
+
const $pos = view.state.doc.resolve(pos);
|
|
42165
|
+
for (let depth = $pos.depth; depth > 0; depth -= 1) {
|
|
42166
|
+
const node = $pos.node(depth);
|
|
42167
|
+
if (node.type.name === "table") {
|
|
42168
|
+
return {
|
|
42169
|
+
node,
|
|
42170
|
+
pos: $pos.before(depth),
|
|
42171
|
+
start: $pos.start(depth)
|
|
42172
|
+
};
|
|
42173
|
+
}
|
|
42174
|
+
}
|
|
42175
|
+
return null;
|
|
42176
|
+
}
|
|
42177
|
+
function getCellRelativePosFromDomPos2(map, tableStart, domPos) {
|
|
42178
|
+
const relativeDomPos = domPos - tableStart;
|
|
42179
|
+
const seen = /* @__PURE__ */ new Set();
|
|
42180
|
+
for (const relativeCellPos of map.map) {
|
|
42181
|
+
if (seen.has(relativeCellPos)) continue;
|
|
42182
|
+
seen.add(relativeCellPos);
|
|
42183
|
+
if (relativeDomPos === relativeCellPos || relativeDomPos === relativeCellPos + 1) {
|
|
42184
|
+
return relativeCellPos;
|
|
42185
|
+
}
|
|
42186
|
+
}
|
|
42187
|
+
return null;
|
|
42188
|
+
}
|
|
42189
|
+
function getFormulaTableCellInfo(view, target, tablePos) {
|
|
42190
|
+
const element = resolveEventElement(target);
|
|
42191
|
+
const cell = element?.closest?.("th,td");
|
|
42192
|
+
if (!(cell instanceof HTMLTableCellElement)) return null;
|
|
42193
|
+
const domPos = view.posAtDOM(cell, 0);
|
|
42194
|
+
const tableInfo = findTableForPos(view, domPos);
|
|
42195
|
+
if (!tableInfo || tableInfo.pos !== tablePos) return null;
|
|
42196
|
+
const map = import_tables7.TableMap.get(tableInfo.node);
|
|
42197
|
+
const relativeCellPos = getCellRelativePosFromDomPos2(map, tableInfo.start, domPos);
|
|
42198
|
+
if (relativeCellPos == null) return null;
|
|
42199
|
+
const rect = map.findCell(relativeCellPos);
|
|
42200
|
+
return {
|
|
42201
|
+
cell,
|
|
42202
|
+
label: `${indexToColumnName(rect.left)}${rect.top + 1}`,
|
|
42203
|
+
rect
|
|
42204
|
+
};
|
|
42205
|
+
}
|
|
42206
|
+
function normalizeFormulaRangeLabel(fromLabel, toLabel) {
|
|
42207
|
+
return fromLabel === toLabel ? fromLabel : `${fromLabel}:${toLabel}`;
|
|
42208
|
+
}
|
|
42209
|
+
function replacePickedLabel(view, pickState, nextLabel, currentCell) {
|
|
42210
|
+
if (nextLabel === pickState.currentLabel && currentCell === pickState.currentCell) return pickState;
|
|
42211
|
+
if (nextLabel === pickState.currentLabel) {
|
|
42212
|
+
return {
|
|
42213
|
+
...pickState,
|
|
42214
|
+
currentCell
|
|
42215
|
+
};
|
|
42216
|
+
}
|
|
42217
|
+
let tr = view.state.tr.insertText(nextLabel, pickState.insertedFrom, pickState.insertedTo);
|
|
42218
|
+
const nextTo = pickState.insertedFrom + nextLabel.length;
|
|
42219
|
+
tr = tr.setSelection(import_state10.TextSelection.create(tr.doc, nextTo));
|
|
42220
|
+
view.dispatch(tr);
|
|
42221
|
+
return {
|
|
42222
|
+
...pickState,
|
|
42223
|
+
insertedTo: nextTo,
|
|
42224
|
+
currentLabel: nextLabel,
|
|
42225
|
+
currentCell
|
|
42226
|
+
};
|
|
42227
|
+
}
|
|
42228
|
+
function beginFormulaRangePick(view, event) {
|
|
42229
|
+
if (event.button !== 0) return null;
|
|
42230
|
+
const formulaCell = getFormulaEditingTableContext(view);
|
|
42231
|
+
if (!formulaCell) return null;
|
|
42232
|
+
const picked = getFormulaTableCellInfo(view, event.target, formulaCell.tablePos);
|
|
42233
|
+
if (!picked || picked.cell === formulaCell.cellDom) return null;
|
|
42234
|
+
const { from, to } = view.state.selection;
|
|
42235
|
+
const prefix = from === to ? getReferenceInsertionPrefix(view, formulaCell.cellContentStart, from) : "";
|
|
42236
|
+
const insertedText = `${prefix}${picked.label}`;
|
|
42237
|
+
const insertedFrom = from + prefix.length;
|
|
42238
|
+
let tr = view.state.tr.insertText(insertedText, from, to);
|
|
42239
|
+
tr = tr.setSelection(import_state10.TextSelection.create(tr.doc, from + insertedText.length));
|
|
42240
|
+
view.dispatch(tr);
|
|
42241
|
+
view.focus();
|
|
42242
|
+
event.preventDefault();
|
|
42243
|
+
event.stopPropagation();
|
|
42244
|
+
return {
|
|
42245
|
+
anchorLabel: picked.label,
|
|
42246
|
+
anchorCell: picked.cell,
|
|
42247
|
+
tablePos: formulaCell.tablePos,
|
|
42248
|
+
insertedFrom,
|
|
42249
|
+
insertedTo: insertedFrom + picked.label.length,
|
|
42250
|
+
currentLabel: picked.label,
|
|
42251
|
+
currentCell: picked.cell
|
|
42252
|
+
};
|
|
42253
|
+
}
|
|
42254
|
+
function updateFormulaRangePick(view, pickState, event) {
|
|
42255
|
+
const picked = getFormulaTableCellInfo(view, event.target, pickState.tablePos);
|
|
42256
|
+
if (!picked) return pickState;
|
|
42257
|
+
event.preventDefault();
|
|
42258
|
+
event.stopPropagation();
|
|
42259
|
+
return replacePickedLabel(
|
|
42260
|
+
view,
|
|
42261
|
+
pickState,
|
|
42262
|
+
normalizeFormulaRangeLabel(pickState.anchorLabel, picked.label),
|
|
42263
|
+
picked.cell
|
|
42264
|
+
);
|
|
42265
|
+
}
|
|
42266
|
+
function getFormulaRangePickHighlight(container, pickState) {
|
|
42267
|
+
if (!container.contains(pickState.anchorCell) || !container.contains(pickState.currentCell)) return null;
|
|
42268
|
+
const containerRect = container.getBoundingClientRect();
|
|
42269
|
+
const anchorRect = pickState.anchorCell.getBoundingClientRect();
|
|
42270
|
+
const currentRect = pickState.currentCell.getBoundingClientRect();
|
|
42271
|
+
const left = Math.min(anchorRect.left, currentRect.left) - containerRect.left + container.scrollLeft;
|
|
42272
|
+
const top = Math.min(anchorRect.top, currentRect.top) - containerRect.top + container.scrollTop;
|
|
42273
|
+
const right = Math.max(anchorRect.right, currentRect.right) - containerRect.left + container.scrollLeft;
|
|
42274
|
+
const bottom = Math.max(anchorRect.bottom, currentRect.bottom) - containerRect.top + container.scrollTop;
|
|
42275
|
+
return {
|
|
42276
|
+
left,
|
|
42277
|
+
top,
|
|
42278
|
+
width: Math.max(0, right - left),
|
|
42279
|
+
height: Math.max(0, bottom - top)
|
|
42280
|
+
};
|
|
42281
|
+
}
|
|
42282
|
+
|
|
42283
|
+
// src/components/UEditor/use-formula-coordinate-overlay.ts
|
|
42284
|
+
function setPosition(element, left, top, width, height) {
|
|
42285
|
+
element.style.left = `${left}px`;
|
|
42286
|
+
element.style.top = `${top}px`;
|
|
42287
|
+
if (width != null) element.style.width = `${Math.max(0, width)}px`;
|
|
42288
|
+
if (height != null) element.style.height = `${Math.max(0, height)}px`;
|
|
42289
|
+
}
|
|
42290
|
+
function createCoordinateLabel(kind, label) {
|
|
42291
|
+
const element = document.createElement("span");
|
|
42292
|
+
element.dataset.ueditorFormulaCoordinate = kind;
|
|
42293
|
+
element.textContent = label;
|
|
42294
|
+
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";
|
|
42295
|
+
return element;
|
|
42296
|
+
}
|
|
42297
|
+
function createReferenceHighlight(label) {
|
|
42298
|
+
const element = document.createElement("span");
|
|
42299
|
+
element.dataset.ueditorFormulaReference = label;
|
|
42300
|
+
element.className = "pointer-events-none absolute z-[21] rounded-[2px] border-2 border-emerald-500 bg-emerald-500/15";
|
|
42301
|
+
return element;
|
|
42302
|
+
}
|
|
42303
|
+
function useFormulaCoordinateOverlay(editor, containerRef, labels) {
|
|
42304
|
+
const overlayRef = (0, import_react77.useRef)(null);
|
|
42305
|
+
(0, import_react77.useEffect)(() => {
|
|
42306
|
+
if (!editor) return void 0;
|
|
42307
|
+
const overlay = overlayRef.current;
|
|
42308
|
+
const container = containerRef.current;
|
|
42309
|
+
if (!overlay || !container) return void 0;
|
|
42310
|
+
let animationFrame = null;
|
|
42311
|
+
let activeTable = null;
|
|
42312
|
+
let activeTablePos = null;
|
|
42313
|
+
let hoverLabel = null;
|
|
42314
|
+
const clearOverlay = () => {
|
|
42315
|
+
activeTable = null;
|
|
42316
|
+
activeTablePos = null;
|
|
42317
|
+
hoverLabel = null;
|
|
42318
|
+
overlay.replaceChildren();
|
|
42319
|
+
overlay.style.display = "none";
|
|
42320
|
+
};
|
|
42321
|
+
const syncOverlay = () => {
|
|
42322
|
+
animationFrame = null;
|
|
42323
|
+
if (editor.isDestroyed) return;
|
|
42324
|
+
const context = getFormulaEditingTableContext(editor.view);
|
|
42325
|
+
if (!context) {
|
|
42326
|
+
clearOverlay();
|
|
42327
|
+
return;
|
|
42328
|
+
}
|
|
42329
|
+
const containerRect = container.getBoundingClientRect();
|
|
42330
|
+
const tableRect = context.tableDom.getBoundingClientRect();
|
|
42331
|
+
const tableLeft = tableRect.left - containerRect.left + container.scrollLeft;
|
|
42332
|
+
const tableTop = tableRect.top - containerRect.top + container.scrollTop;
|
|
42333
|
+
const map = import_tables8.TableMap.get(context.tableNode);
|
|
42334
|
+
const columnSegments = Array(map.width);
|
|
42335
|
+
const rowSegments = Array(map.height);
|
|
42336
|
+
const cellInfos = [];
|
|
42337
|
+
for (const cell of context.tableDom.querySelectorAll("th,td")) {
|
|
42338
|
+
if (!(cell instanceof HTMLTableCellElement)) continue;
|
|
42339
|
+
const info = getFormulaTableCellInfo(editor.view, cell, context.tablePos);
|
|
42340
|
+
if (!info) continue;
|
|
42341
|
+
cellInfos.push(info);
|
|
42342
|
+
const cellRect = cell.getBoundingClientRect();
|
|
42343
|
+
const columnSpan = Math.max(1, info.rect.right - info.rect.left);
|
|
42344
|
+
const rowSpan = Math.max(1, info.rect.bottom - info.rect.top);
|
|
42345
|
+
const columnWidth = cellRect.width / columnSpan;
|
|
42346
|
+
const rowHeight = cellRect.height / rowSpan;
|
|
42347
|
+
for (let column = info.rect.left; column < info.rect.right; column += 1) {
|
|
42348
|
+
if (!columnSegments[column] || columnSpan < columnSegments[column].span) {
|
|
42349
|
+
columnSegments[column] = {
|
|
42350
|
+
start: cellRect.left - containerRect.left + container.scrollLeft + (column - info.rect.left) * columnWidth,
|
|
42351
|
+
size: columnWidth,
|
|
42352
|
+
span: columnSpan
|
|
42353
|
+
};
|
|
42354
|
+
}
|
|
42355
|
+
}
|
|
42356
|
+
for (let row = info.rect.top; row < info.rect.bottom; row += 1) {
|
|
42357
|
+
if (!rowSegments[row] || rowSpan < rowSegments[row].span) {
|
|
42358
|
+
rowSegments[row] = {
|
|
42359
|
+
start: cellRect.top - containerRect.top + container.scrollTop + (row - info.rect.top) * rowHeight,
|
|
42360
|
+
size: rowHeight,
|
|
42361
|
+
span: rowSpan
|
|
42362
|
+
};
|
|
42363
|
+
}
|
|
42364
|
+
}
|
|
42365
|
+
}
|
|
42366
|
+
const fallbackColumnWidth = map.width > 0 ? tableRect.width / map.width : 0;
|
|
42367
|
+
const fallbackRowHeight = map.height > 0 ? tableRect.height / map.height : 0;
|
|
42368
|
+
const children = [];
|
|
42369
|
+
const actions = document.createElement("div");
|
|
42370
|
+
actions.dataset.ueditorFormulaActions = "";
|
|
42371
|
+
actions.className = "pointer-events-auto absolute z-50 flex items-center gap-1 rounded-md border border-border bg-background p-1 shadow-md";
|
|
42372
|
+
const formulaCellRect = context.cellDom.getBoundingClientRect();
|
|
42373
|
+
setPosition(
|
|
42374
|
+
actions,
|
|
42375
|
+
formulaCellRect.left - containerRect.left + container.scrollLeft,
|
|
42376
|
+
formulaCellRect.bottom - containerRect.top + container.scrollTop + 4
|
|
42377
|
+
);
|
|
42378
|
+
const applyButton = document.createElement("button");
|
|
42379
|
+
applyButton.type = "button";
|
|
42380
|
+
applyButton.dataset.ueditorFormulaApply = "";
|
|
42381
|
+
applyButton.disabled = isDraftTableFormula(context.formula);
|
|
42382
|
+
applyButton.textContent = `${applyButton.disabled ? "" : "\u2713 "}${labels.apply} (Enter)`;
|
|
42383
|
+
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";
|
|
42384
|
+
const cancelButton = document.createElement("button");
|
|
42385
|
+
cancelButton.type = "button";
|
|
42386
|
+
cancelButton.dataset.ueditorFormulaCancel = "";
|
|
42387
|
+
cancelButton.textContent = `${labels.cancel} (Esc)`;
|
|
42388
|
+
cancelButton.className = "rounded px-2.5 py-1 text-xs font-medium text-foreground hover:bg-muted";
|
|
42389
|
+
const preserveSelection = (event) => {
|
|
42390
|
+
event.preventDefault();
|
|
42391
|
+
event.stopPropagation();
|
|
42392
|
+
};
|
|
42393
|
+
applyButton.addEventListener("mousedown", preserveSelection);
|
|
42394
|
+
cancelButton.addEventListener("mousedown", preserveSelection);
|
|
42395
|
+
applyButton.addEventListener("click", (event) => {
|
|
42396
|
+
event.preventDefault();
|
|
42397
|
+
event.stopPropagation();
|
|
42398
|
+
if (!applyButton.disabled) recalculateActiveTableFormulas(editor);
|
|
42399
|
+
});
|
|
42400
|
+
cancelButton.addEventListener("click", (event) => {
|
|
42401
|
+
event.preventDefault();
|
|
42402
|
+
event.stopPropagation();
|
|
42403
|
+
cancelFormulaEditing(editor.view);
|
|
42404
|
+
});
|
|
42405
|
+
actions.append(applyButton, cancelButton);
|
|
42406
|
+
children.push(actions);
|
|
42407
|
+
for (let column = 0; column < map.width; column += 1) {
|
|
42408
|
+
const segment = columnSegments[column] ?? {
|
|
42409
|
+
start: tableLeft + column * fallbackColumnWidth,
|
|
42410
|
+
size: fallbackColumnWidth,
|
|
42411
|
+
span: map.width
|
|
42412
|
+
};
|
|
42413
|
+
const label = createCoordinateLabel("column", indexToColumnName(column));
|
|
42414
|
+
setPosition(label, segment.start, Math.max(0, tableTop - 22), segment.size, 20);
|
|
42415
|
+
children.push(label);
|
|
42416
|
+
}
|
|
42417
|
+
for (let row = 0; row < map.height; row += 1) {
|
|
42418
|
+
const segment = rowSegments[row] ?? {
|
|
42419
|
+
start: tableTop + row * fallbackRowHeight,
|
|
42420
|
+
size: fallbackRowHeight,
|
|
42421
|
+
span: map.height
|
|
42422
|
+
};
|
|
42423
|
+
const label = createCoordinateLabel("row", String(row + 1));
|
|
42424
|
+
setPosition(label, Math.max(0, tableLeft - 28), segment.start, 26, segment.size);
|
|
42425
|
+
children.push(label);
|
|
42426
|
+
}
|
|
42427
|
+
const references = new Set(getTableFormulaReferences(context.formula));
|
|
42428
|
+
for (const info of cellInfos) {
|
|
42429
|
+
if (!info || !references.has(info.label)) continue;
|
|
42430
|
+
const cellRect = info.cell.getBoundingClientRect();
|
|
42431
|
+
const highlight = createReferenceHighlight(info.label);
|
|
42432
|
+
setPosition(
|
|
42433
|
+
highlight,
|
|
42434
|
+
cellRect.left - containerRect.left + container.scrollLeft + 2,
|
|
42435
|
+
cellRect.top - containerRect.top + container.scrollTop + 2,
|
|
42436
|
+
cellRect.width - 4,
|
|
42437
|
+
cellRect.height - 4
|
|
42438
|
+
);
|
|
42439
|
+
children.push(highlight);
|
|
42440
|
+
}
|
|
42441
|
+
hoverLabel = document.createElement("span");
|
|
42442
|
+
hoverLabel.dataset.ueditorFormulaHoverLabel = "";
|
|
42443
|
+
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";
|
|
42444
|
+
children.push(hoverLabel);
|
|
42445
|
+
overlay.replaceChildren(...children);
|
|
42446
|
+
overlay.style.display = "block";
|
|
42447
|
+
activeTable = context.tableDom;
|
|
42448
|
+
activeTablePos = context.tablePos;
|
|
42449
|
+
};
|
|
42450
|
+
const scheduleSync = () => {
|
|
42451
|
+
if (animationFrame != null) return;
|
|
42452
|
+
animationFrame = window.requestAnimationFrame(syncOverlay);
|
|
42453
|
+
};
|
|
42454
|
+
const handleMouseMove2 = (event) => {
|
|
42455
|
+
if (!activeTable || activeTablePos == null || !hoverLabel) return;
|
|
42456
|
+
const target = event.target instanceof Element ? event.target.closest("th,td") : null;
|
|
42457
|
+
if (!(target instanceof HTMLTableCellElement) || target.closest("table") !== activeTable) {
|
|
42458
|
+
hoverLabel.style.display = "none";
|
|
42459
|
+
return;
|
|
42460
|
+
}
|
|
42461
|
+
const info = getFormulaTableCellInfo(editor.view, target, activeTablePos);
|
|
42462
|
+
if (!info) {
|
|
42463
|
+
hoverLabel.style.display = "none";
|
|
42464
|
+
return;
|
|
42465
|
+
}
|
|
42466
|
+
const containerRect = container.getBoundingClientRect();
|
|
42467
|
+
const cellRect = target.getBoundingClientRect();
|
|
42468
|
+
hoverLabel.textContent = info.label;
|
|
42469
|
+
hoverLabel.style.display = "block";
|
|
42470
|
+
setPosition(
|
|
42471
|
+
hoverLabel,
|
|
42472
|
+
cellRect.left - containerRect.left + container.scrollLeft + 4,
|
|
42473
|
+
cellRect.top - containerRect.top + container.scrollTop + 4
|
|
42474
|
+
);
|
|
42475
|
+
};
|
|
42476
|
+
const handleMouseLeave2 = () => {
|
|
42477
|
+
if (hoverLabel) hoverLabel.style.display = "none";
|
|
42478
|
+
};
|
|
42479
|
+
editor.on("selectionUpdate", scheduleSync);
|
|
42480
|
+
editor.on("update", scheduleSync);
|
|
42481
|
+
editor.on("focus", scheduleSync);
|
|
42482
|
+
editor.on("blur", scheduleSync);
|
|
42483
|
+
editor.view.dom.addEventListener("mousemove", handleMouseMove2);
|
|
42484
|
+
editor.view.dom.addEventListener("mouseleave", handleMouseLeave2);
|
|
42485
|
+
container.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleSync);
|
|
42486
|
+
window.addEventListener("resize", scheduleSync);
|
|
42487
|
+
scheduleSync();
|
|
42488
|
+
return () => {
|
|
42489
|
+
editor.off("selectionUpdate", scheduleSync);
|
|
42490
|
+
editor.off("update", scheduleSync);
|
|
42491
|
+
editor.off("focus", scheduleSync);
|
|
42492
|
+
editor.off("blur", scheduleSync);
|
|
42493
|
+
editor.view.dom.removeEventListener("mousemove", handleMouseMove2);
|
|
42494
|
+
editor.view.dom.removeEventListener("mouseleave", handleMouseLeave2);
|
|
42495
|
+
container.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleSync);
|
|
42496
|
+
window.removeEventListener("resize", scheduleSync);
|
|
42497
|
+
if (animationFrame != null) window.cancelAnimationFrame(animationFrame);
|
|
42498
|
+
clearOverlay();
|
|
42499
|
+
};
|
|
42500
|
+
}, [containerRef, editor, labels.apply, labels.cancel]);
|
|
42501
|
+
return overlayRef;
|
|
42502
|
+
}
|
|
42503
|
+
|
|
42041
42504
|
// src/components/UEditor/menu-bar.tsx
|
|
42042
|
-
var
|
|
42043
|
-
var
|
|
42505
|
+
var import_react78 = __toESM(require("react"), 1);
|
|
42506
|
+
var import_react79 = require("@tiptap/react");
|
|
42044
42507
|
var import_lucide_react58 = require("lucide-react");
|
|
42045
42508
|
|
|
42046
42509
|
// src/components/UEditor/preview-html.ts
|
|
@@ -42221,7 +42684,7 @@ function renderMenuItems(items) {
|
|
|
42221
42684
|
case "sub":
|
|
42222
42685
|
return /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(DropdownMenuSub, { label: item.label, icon: item.icon, disabled: item.disabled, children: renderMenuItems(item.items) }, i);
|
|
42223
42686
|
case "custom":
|
|
42224
|
-
return /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(
|
|
42687
|
+
return /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(import_react78.default.Fragment, { children: item.render() }, item.key);
|
|
42225
42688
|
}
|
|
42226
42689
|
});
|
|
42227
42690
|
}
|
|
@@ -42597,7 +43060,7 @@ function buildTableMenuItems(t, editor, onInsertTable) {
|
|
|
42597
43060
|
}
|
|
42598
43061
|
];
|
|
42599
43062
|
}
|
|
42600
|
-
var MenuBarTrigger =
|
|
43063
|
+
var MenuBarTrigger = import_react78.default.forwardRef(
|
|
42601
43064
|
({ children, className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(
|
|
42602
43065
|
"button",
|
|
42603
43066
|
{
|
|
@@ -42629,18 +43092,18 @@ var MenuBar = ({
|
|
|
42629
43092
|
onPreview
|
|
42630
43093
|
}) => {
|
|
42631
43094
|
const t = useSmartTranslations("UEditor");
|
|
42632
|
-
(0,
|
|
43095
|
+
(0, import_react79.useEditorState)({
|
|
42633
43096
|
editor,
|
|
42634
43097
|
selector: ({ transactionNumber }) => transactionNumber
|
|
42635
43098
|
});
|
|
42636
|
-
const fileInputRef = (0,
|
|
42637
|
-
const [showImageInput, setShowImageInput] = (0,
|
|
42638
|
-
const [showLinkInput, setShowLinkInput] = (0,
|
|
42639
|
-
const [isInsertMenuOpen, setIsInsertMenuOpen] = (0,
|
|
42640
|
-
const [showSourceDialog, setShowSourceDialog] = (0,
|
|
42641
|
-
const [sourceHtml, setSourceHtml] = (0,
|
|
42642
|
-
const [showPreviewDialog, setShowPreviewDialog] = (0,
|
|
42643
|
-
const previewHtml = (0,
|
|
43099
|
+
const fileInputRef = (0, import_react78.useRef)(null);
|
|
43100
|
+
const [showImageInput, setShowImageInput] = (0, import_react78.useState)(false);
|
|
43101
|
+
const [showLinkInput, setShowLinkInput] = (0, import_react78.useState)(false);
|
|
43102
|
+
const [isInsertMenuOpen, setIsInsertMenuOpen] = (0, import_react78.useState)(false);
|
|
43103
|
+
const [showSourceDialog, setShowSourceDialog] = (0, import_react78.useState)(false);
|
|
43104
|
+
const [sourceHtml, setSourceHtml] = (0, import_react78.useState)("");
|
|
43105
|
+
const [showPreviewDialog, setShowPreviewDialog] = (0, import_react78.useState)(false);
|
|
43106
|
+
const previewHtml = (0, import_react78.useMemo)(
|
|
42644
43107
|
() => showPreviewDialog ? prepareUEditorPreviewHtml(editor.getHTML()) : "",
|
|
42645
43108
|
[editor, showPreviewDialog]
|
|
42646
43109
|
);
|
|
@@ -42922,149 +43385,9 @@ var MenuBar = ({
|
|
|
42922
43385
|
] });
|
|
42923
43386
|
};
|
|
42924
43387
|
|
|
42925
|
-
// src/components/UEditor/table-formula-range-picker.ts
|
|
42926
|
-
var import_state10 = require("@tiptap/pm/state");
|
|
42927
|
-
var import_tables7 = require("@tiptap/pm/tables");
|
|
42928
|
-
function getCellText2(cellNode) {
|
|
42929
|
-
return cellNode.textBetween(0, cellNode.content.size, "\n").trim();
|
|
42930
|
-
}
|
|
42931
|
-
function findSelectionFormulaCell(view) {
|
|
42932
|
-
const { $from } = view.state.selection;
|
|
42933
|
-
for (let depth = $from.depth; depth > 0; depth -= 1) {
|
|
42934
|
-
const node = $from.node(depth);
|
|
42935
|
-
if (node.type.name !== "tableCell" && node.type.name !== "tableHeader") continue;
|
|
42936
|
-
if (!getCellText2(node).startsWith("=")) return null;
|
|
42937
|
-
const cellPos = $from.before(depth);
|
|
42938
|
-
const cellDom = view.nodeDOM(cellPos);
|
|
42939
|
-
const tableDepth = depth - 2;
|
|
42940
|
-
const tableNode = tableDepth > 0 ? $from.node(tableDepth) : null;
|
|
42941
|
-
if (!tableNode || tableNode.type.name !== "table") return null;
|
|
42942
|
-
return {
|
|
42943
|
-
cellDom: cellDom instanceof HTMLTableCellElement ? cellDom : null,
|
|
42944
|
-
tablePos: $from.before(tableDepth)
|
|
42945
|
-
};
|
|
42946
|
-
}
|
|
42947
|
-
return null;
|
|
42948
|
-
}
|
|
42949
|
-
function findTableForPos(view, pos) {
|
|
42950
|
-
const $pos = view.state.doc.resolve(pos);
|
|
42951
|
-
for (let depth = $pos.depth; depth > 0; depth -= 1) {
|
|
42952
|
-
const node = $pos.node(depth);
|
|
42953
|
-
if (node.type.name === "table") {
|
|
42954
|
-
return {
|
|
42955
|
-
node,
|
|
42956
|
-
pos: $pos.before(depth),
|
|
42957
|
-
start: $pos.start(depth)
|
|
42958
|
-
};
|
|
42959
|
-
}
|
|
42960
|
-
}
|
|
42961
|
-
return null;
|
|
42962
|
-
}
|
|
42963
|
-
function getCellRelativePosFromDomPos2(map, tableStart, domPos) {
|
|
42964
|
-
const relativeDomPos = domPos - tableStart;
|
|
42965
|
-
const seen = /* @__PURE__ */ new Set();
|
|
42966
|
-
for (const relativeCellPos of map.map) {
|
|
42967
|
-
if (seen.has(relativeCellPos)) continue;
|
|
42968
|
-
seen.add(relativeCellPos);
|
|
42969
|
-
if (relativeDomPos === relativeCellPos || relativeDomPos === relativeCellPos + 1) {
|
|
42970
|
-
return relativeCellPos;
|
|
42971
|
-
}
|
|
42972
|
-
}
|
|
42973
|
-
return null;
|
|
42974
|
-
}
|
|
42975
|
-
function getPickedCellLabel(view, target, tablePos) {
|
|
42976
|
-
const element = resolveEventElement(target);
|
|
42977
|
-
const cell = element?.closest?.("th,td");
|
|
42978
|
-
if (!(cell instanceof HTMLTableCellElement)) return null;
|
|
42979
|
-
const domPos = view.posAtDOM(cell, 0);
|
|
42980
|
-
const tableInfo = findTableForPos(view, domPos);
|
|
42981
|
-
if (!tableInfo || tableInfo.pos !== tablePos) return null;
|
|
42982
|
-
const map = import_tables7.TableMap.get(tableInfo.node);
|
|
42983
|
-
const relativeCellPos = getCellRelativePosFromDomPos2(map, tableInfo.start, domPos);
|
|
42984
|
-
if (relativeCellPos == null) return null;
|
|
42985
|
-
const rect = map.findCell(relativeCellPos);
|
|
42986
|
-
return {
|
|
42987
|
-
cell,
|
|
42988
|
-
label: `${indexToColumnName(rect.left)}${rect.top + 1}`
|
|
42989
|
-
};
|
|
42990
|
-
}
|
|
42991
|
-
function normalizeFormulaRangeLabel(fromLabel, toLabel) {
|
|
42992
|
-
return fromLabel === toLabel ? fromLabel : `${fromLabel}:${toLabel}`;
|
|
42993
|
-
}
|
|
42994
|
-
function replacePickedLabel(view, pickState, nextLabel, currentCell) {
|
|
42995
|
-
if (nextLabel === pickState.currentLabel && currentCell === pickState.currentCell) return pickState;
|
|
42996
|
-
if (nextLabel === pickState.currentLabel) {
|
|
42997
|
-
return {
|
|
42998
|
-
...pickState,
|
|
42999
|
-
currentCell
|
|
43000
|
-
};
|
|
43001
|
-
}
|
|
43002
|
-
let tr = view.state.tr.insertText(nextLabel, pickState.insertedFrom, pickState.insertedTo);
|
|
43003
|
-
const nextTo = pickState.insertedFrom + nextLabel.length;
|
|
43004
|
-
tr = tr.setSelection(import_state10.TextSelection.create(tr.doc, nextTo));
|
|
43005
|
-
view.dispatch(tr);
|
|
43006
|
-
return {
|
|
43007
|
-
...pickState,
|
|
43008
|
-
insertedTo: nextTo,
|
|
43009
|
-
currentLabel: nextLabel,
|
|
43010
|
-
currentCell
|
|
43011
|
-
};
|
|
43012
|
-
}
|
|
43013
|
-
function beginFormulaRangePick(view, event) {
|
|
43014
|
-
if (event.button !== 0) return null;
|
|
43015
|
-
const formulaCell = findSelectionFormulaCell(view);
|
|
43016
|
-
if (!formulaCell) return null;
|
|
43017
|
-
const picked = getPickedCellLabel(view, event.target, formulaCell.tablePos);
|
|
43018
|
-
if (!picked || picked.cell === formulaCell.cellDom) return null;
|
|
43019
|
-
const { from, to } = view.state.selection;
|
|
43020
|
-
let tr = view.state.tr.insertText(picked.label, from, to);
|
|
43021
|
-
tr = tr.setSelection(import_state10.TextSelection.create(tr.doc, from + picked.label.length));
|
|
43022
|
-
view.dispatch(tr);
|
|
43023
|
-
view.focus();
|
|
43024
|
-
event.preventDefault();
|
|
43025
|
-
event.stopPropagation();
|
|
43026
|
-
return {
|
|
43027
|
-
anchorLabel: picked.label,
|
|
43028
|
-
anchorCell: picked.cell,
|
|
43029
|
-
tablePos: formulaCell.tablePos,
|
|
43030
|
-
insertedFrom: from,
|
|
43031
|
-
insertedTo: from + picked.label.length,
|
|
43032
|
-
currentLabel: picked.label,
|
|
43033
|
-
currentCell: picked.cell
|
|
43034
|
-
};
|
|
43035
|
-
}
|
|
43036
|
-
function updateFormulaRangePick(view, pickState, event) {
|
|
43037
|
-
const picked = getPickedCellLabel(view, event.target, pickState.tablePos);
|
|
43038
|
-
if (!picked) return pickState;
|
|
43039
|
-
event.preventDefault();
|
|
43040
|
-
event.stopPropagation();
|
|
43041
|
-
return replacePickedLabel(
|
|
43042
|
-
view,
|
|
43043
|
-
pickState,
|
|
43044
|
-
normalizeFormulaRangeLabel(pickState.anchorLabel, picked.label),
|
|
43045
|
-
picked.cell
|
|
43046
|
-
);
|
|
43047
|
-
}
|
|
43048
|
-
function getFormulaRangePickHighlight(container, pickState) {
|
|
43049
|
-
if (!container.contains(pickState.anchorCell) || !container.contains(pickState.currentCell)) return null;
|
|
43050
|
-
const containerRect = container.getBoundingClientRect();
|
|
43051
|
-
const anchorRect = pickState.anchorCell.getBoundingClientRect();
|
|
43052
|
-
const currentRect = pickState.currentCell.getBoundingClientRect();
|
|
43053
|
-
const left = Math.min(anchorRect.left, currentRect.left) - containerRect.left + container.scrollLeft;
|
|
43054
|
-
const top = Math.min(anchorRect.top, currentRect.top) - containerRect.top + container.scrollTop;
|
|
43055
|
-
const right = Math.max(anchorRect.right, currentRect.right) - containerRect.left + container.scrollLeft;
|
|
43056
|
-
const bottom = Math.max(anchorRect.bottom, currentRect.bottom) - containerRect.top + container.scrollTop;
|
|
43057
|
-
return {
|
|
43058
|
-
left,
|
|
43059
|
-
top,
|
|
43060
|
-
width: Math.max(0, right - left),
|
|
43061
|
-
height: Math.max(0, bottom - top)
|
|
43062
|
-
};
|
|
43063
|
-
}
|
|
43064
|
-
|
|
43065
43388
|
// src/components/UEditor/UEditor.tsx
|
|
43066
43389
|
var import_jsx_runtime100 = require("react/jsx-runtime");
|
|
43067
|
-
var UEditor =
|
|
43390
|
+
var UEditor = import_react80.default.forwardRef(({
|
|
43068
43391
|
content = "",
|
|
43069
43392
|
onChange,
|
|
43070
43393
|
onHtmlChange,
|
|
@@ -43105,13 +43428,14 @@ var UEditor = import_react79.default.forwardRef(({
|
|
|
43105
43428
|
}, ref) => {
|
|
43106
43429
|
const t = useSmartTranslations("UEditor");
|
|
43107
43430
|
const effectivePlaceholder = placeholder ?? t("placeholder");
|
|
43108
|
-
const inFlightPrepareRef = (0,
|
|
43109
|
-
const lastAppliedContentRef = (0,
|
|
43110
|
-
const scheduledFormulaRecalculateRef = (0,
|
|
43111
|
-
const
|
|
43112
|
-
const
|
|
43113
|
-
const
|
|
43114
|
-
const
|
|
43431
|
+
const inFlightPrepareRef = (0, import_react80.useRef)(null);
|
|
43432
|
+
const lastAppliedContentRef = (0, import_react80.useRef)(content ?? "");
|
|
43433
|
+
const scheduledFormulaRecalculateRef = (0, import_react80.useRef)(false);
|
|
43434
|
+
const editorInstanceRef = (0, import_react80.useRef)(null);
|
|
43435
|
+
const formulaRangePickRef = (0, import_react80.useRef)(null);
|
|
43436
|
+
const formulaRangeSurfaceRef = (0, import_react80.useRef)(null);
|
|
43437
|
+
const [formulaRangeHighlight, setFormulaRangeHighlight] = import_react80.default.useState(null);
|
|
43438
|
+
const scheduleFormulaRecalculate = import_react80.default.useCallback((editor2, options) => {
|
|
43115
43439
|
if (editor2.isDestroyed || scheduledFormulaRecalculateRef.current) return;
|
|
43116
43440
|
if (!options?.force && isEditingTableFormulaText(editor2)) return;
|
|
43117
43441
|
scheduledFormulaRecalculateRef.current = true;
|
|
@@ -43122,7 +43446,7 @@ var UEditor = import_react79.default.forwardRef(({
|
|
|
43122
43446
|
}
|
|
43123
43447
|
});
|
|
43124
43448
|
}, []);
|
|
43125
|
-
const resolvedUploadFile = (0,
|
|
43449
|
+
const resolvedUploadFile = (0, import_react80.useMemo)(() => {
|
|
43126
43450
|
if (uploadFile) return uploadFile;
|
|
43127
43451
|
if (uploadFileForSave) {
|
|
43128
43452
|
return async (file) => {
|
|
@@ -43132,7 +43456,7 @@ var UEditor = import_react79.default.forwardRef(({
|
|
|
43132
43456
|
}
|
|
43133
43457
|
return uploadImage;
|
|
43134
43458
|
}, [uploadFile, uploadFileForSave, uploadImage]);
|
|
43135
|
-
const extensions = (0,
|
|
43459
|
+
const extensions = (0, import_react80.useMemo)(
|
|
43136
43460
|
() => [
|
|
43137
43461
|
...buildUEditorExtensions({
|
|
43138
43462
|
placeholder: effectivePlaceholder,
|
|
@@ -43151,11 +43475,11 @@ var UEditor = import_react79.default.forwardRef(({
|
|
|
43151
43475
|
],
|
|
43152
43476
|
[effectivePlaceholder, t, maxCharacters, uploadImage, resolvedUploadFile, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable, fetchMetadata, extraExtensions]
|
|
43153
43477
|
);
|
|
43154
|
-
const syncFormulaRangeHighlight =
|
|
43478
|
+
const syncFormulaRangeHighlight = import_react80.default.useCallback((pickState) => {
|
|
43155
43479
|
const container = formulaRangeSurfaceRef.current;
|
|
43156
43480
|
setFormulaRangeHighlight(container && pickState ? getFormulaRangePickHighlight(container, pickState) : null);
|
|
43157
43481
|
}, []);
|
|
43158
|
-
const editor = (0,
|
|
43482
|
+
const editor = (0, import_react81.useEditor)({
|
|
43159
43483
|
immediatelyRender: false,
|
|
43160
43484
|
extensions,
|
|
43161
43485
|
content,
|
|
@@ -43196,6 +43520,22 @@ var UEditor = import_react79.default.forwardRef(({
|
|
|
43196
43520
|
},
|
|
43197
43521
|
keydown: (_view, event) => {
|
|
43198
43522
|
if (!(event instanceof KeyboardEvent)) return false;
|
|
43523
|
+
const formulaContext = getFormulaEditingTableContext(_view);
|
|
43524
|
+
if (formulaContext && event.key === "Enter") {
|
|
43525
|
+
event.preventDefault();
|
|
43526
|
+
event.stopPropagation();
|
|
43527
|
+
const activeEditor = editorInstanceRef.current;
|
|
43528
|
+
if (activeEditor && !isDraftTableFormula(formulaContext.formula)) {
|
|
43529
|
+
recalculateActiveTableFormulas(activeEditor);
|
|
43530
|
+
}
|
|
43531
|
+
return true;
|
|
43532
|
+
}
|
|
43533
|
+
if (formulaContext && event.key === "Escape") {
|
|
43534
|
+
event.preventDefault();
|
|
43535
|
+
event.stopPropagation();
|
|
43536
|
+
cancelFormulaEditing(_view);
|
|
43537
|
+
return true;
|
|
43538
|
+
}
|
|
43199
43539
|
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
43200
43540
|
event.stopPropagation();
|
|
43201
43541
|
}
|
|
@@ -43236,13 +43576,23 @@ var UEditor = import_react79.default.forwardRef(({
|
|
|
43236
43576
|
scheduleFormulaRecalculate(editor2, { force: true });
|
|
43237
43577
|
}
|
|
43238
43578
|
});
|
|
43579
|
+
(0, import_react80.useEffect)(() => {
|
|
43580
|
+
editorInstanceRef.current = editor;
|
|
43581
|
+
return () => {
|
|
43582
|
+
if (editorInstanceRef.current === editor) editorInstanceRef.current = null;
|
|
43583
|
+
};
|
|
43584
|
+
}, [editor]);
|
|
43239
43585
|
const {
|
|
43240
43586
|
editorContentRef,
|
|
43241
43587
|
tableColumnGuideRef,
|
|
43242
43588
|
tableRowGuideRef,
|
|
43243
43589
|
activeTableCellHighlightRef
|
|
43244
43590
|
} = useUEditorTableInteractions(editor, editable);
|
|
43245
|
-
(
|
|
43591
|
+
const formulaCoordinateOverlayRef = useFormulaCoordinateOverlay(editor, editorContentRef, {
|
|
43592
|
+
apply: t("tableMenu.apply"),
|
|
43593
|
+
cancel: t("imageInput.cancelBtn")
|
|
43594
|
+
});
|
|
43595
|
+
(0, import_react80.useImperativeHandle)(
|
|
43246
43596
|
ref,
|
|
43247
43597
|
() => ({
|
|
43248
43598
|
editor,
|
|
@@ -43267,7 +43617,7 @@ var UEditor = import_react79.default.forwardRef(({
|
|
|
43267
43617
|
}),
|
|
43268
43618
|
[content, editor, uploadImageForSave, uploadFileForSave, uploadImageConcurrency]
|
|
43269
43619
|
);
|
|
43270
|
-
(0,
|
|
43620
|
+
(0, import_react80.useEffect)(() => {
|
|
43271
43621
|
if (!editor) return;
|
|
43272
43622
|
queueMicrotask(() => {
|
|
43273
43623
|
if (!editor.isDestroyed) {
|
|
@@ -43275,7 +43625,7 @@ var UEditor = import_react79.default.forwardRef(({
|
|
|
43275
43625
|
}
|
|
43276
43626
|
});
|
|
43277
43627
|
}, [editor]);
|
|
43278
|
-
(0,
|
|
43628
|
+
(0, import_react80.useEffect)(() => {
|
|
43279
43629
|
if (!editor) return;
|
|
43280
43630
|
const nextContent = content ?? "";
|
|
43281
43631
|
if (lastAppliedContentRef.current === nextContent) return;
|
|
@@ -43395,6 +43745,14 @@ var UEditor = import_react79.default.forwardRef(({
|
|
|
43395
43745
|
className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10"
|
|
43396
43746
|
}
|
|
43397
43747
|
),
|
|
43748
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43749
|
+
"div",
|
|
43750
|
+
{
|
|
43751
|
+
ref: formulaCoordinateOverlayRef,
|
|
43752
|
+
"data-ueditor-formula-coordinate-overlay": "",
|
|
43753
|
+
className: "pointer-events-none absolute inset-0 z-[21] hidden overflow-visible"
|
|
43754
|
+
}
|
|
43755
|
+
),
|
|
43398
43756
|
formulaRangeHighlight && /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43399
43757
|
"span",
|
|
43400
43758
|
{
|
|
@@ -43411,7 +43769,7 @@ var UEditor = import_react79.default.forwardRef(({
|
|
|
43411
43769
|
),
|
|
43412
43770
|
editable && /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(TableControls, { editor, containerRef: editorContentRef }),
|
|
43413
43771
|
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43414
|
-
|
|
43772
|
+
import_react81.EditorContent,
|
|
43415
43773
|
{
|
|
43416
43774
|
editor,
|
|
43417
43775
|
className: "min-h-full"
|