@underverse-ui/underverse 2.0.29 → 2.0.30
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/{EmojiPicker-NV3GQYWI.js → EmojiPicker-ISJ6RXYG.js} +4 -4
- package/dist/{chunk-LK6YWBI6.js → chunk-2P7TSXEE.js} +82 -25
- package/dist/chunk-2P7TSXEE.js.map +1 -0
- package/dist/{chunk-5QWYO527.js → chunk-37MHVJMV.js} +846 -90
- package/dist/chunk-37MHVJMV.js.map +1 -0
- package/dist/{chunk-XTZTUDRE.js → chunk-57BKIC6J.js} +711 -800
- package/dist/chunk-57BKIC6J.js.map +1 -0
- package/dist/{chunk-LRIRY4DG.js → chunk-5W63IHIN.js} +11 -3
- package/dist/chunk-5W63IHIN.js.map +1 -0
- package/dist/{chunk-F7MX3XXK.js → chunk-S4UHFRL3.js} +3 -3
- package/dist/{chunk-A4GUPKHM.js → chunk-ZP7F4ZD7.js} +63 -43
- package/dist/chunk-ZP7F4ZD7.js.map +1 -0
- package/dist/index.cjs +2225 -1311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +23 -10
- package/dist/index.js.map +1 -1
- package/dist/{menu-bar-AHG64PEB.js → menu-bar-DPCNNUX5.js} +193 -47
- package/dist/menu-bar-DPCNNUX5.js.map +1 -0
- package/dist/ueditor.cjs +9407 -8506
- package/dist/ueditor.cjs.map +1 -1
- package/dist/ueditor.d.cts +10 -0
- package/dist/ueditor.d.ts +10 -0
- package/dist/ueditor.js +4 -4
- package/package.json +2 -1
- package/dist/chunk-5QWYO527.js.map +0 -1
- package/dist/chunk-A4GUPKHM.js.map +0 -1
- package/dist/chunk-LK6YWBI6.js.map +0 -1
- package/dist/chunk-LRIRY4DG.js.map +0 -1
- package/dist/chunk-XTZTUDRE.js.map +0 -1
- package/dist/menu-bar-AHG64PEB.js.map +0 -1
- /package/dist/{EmojiPicker-NV3GQYWI.js.map → EmojiPicker-ISJ6RXYG.js.map} +0 -0
- /package/dist/{chunk-F7MX3XXK.js.map → chunk-S4UHFRL3.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EmojiGridButton,
|
|
3
3
|
formatEmojiCountLabel
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-5W63IHIN.js";
|
|
5
5
|
import {
|
|
6
6
|
COLUMN_RESIZE_LINE_THICKNESS,
|
|
7
7
|
CellBgColorIcon,
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
applyImageLayout,
|
|
29
29
|
applyImageWidthPreset,
|
|
30
30
|
applyTableAlignment,
|
|
31
|
+
buildTableFormulaDependencyGraph,
|
|
31
32
|
clampResponsiveTableWidthBp,
|
|
32
33
|
clearTableColumnAt,
|
|
33
34
|
clearTableRowAt,
|
|
@@ -36,10 +37,14 @@ import {
|
|
|
36
37
|
dispatchTableLayoutChange,
|
|
37
38
|
duplicateTableColumnAt,
|
|
38
39
|
duplicateTableRowAt,
|
|
40
|
+
evaluateBasicTableFormula,
|
|
39
41
|
expandTableFromCell,
|
|
40
42
|
findTableNodeInfoFromState,
|
|
41
43
|
findTableRowNodeInfo,
|
|
42
44
|
formatBasisPointsAsPercentage,
|
|
45
|
+
formatFormulaError,
|
|
46
|
+
formatTableFormulaDisplayValue,
|
|
47
|
+
getAffectedTableFormulaLabels,
|
|
43
48
|
getDefaultFontSizes,
|
|
44
49
|
getDefaultLineHeights,
|
|
45
50
|
getLegacyTableColumnWeights,
|
|
@@ -50,7 +55,11 @@ import {
|
|
|
50
55
|
getResponsiveTableOffsetBp,
|
|
51
56
|
getResponsiveTableWidthBp,
|
|
52
57
|
getSelectionTableCell,
|
|
58
|
+
getTableCellRangeLabels,
|
|
53
59
|
getTableColumnRatios,
|
|
60
|
+
getTableFormulaRecalculationOrder,
|
|
61
|
+
getTableFormulaReferences,
|
|
62
|
+
indexToColumnName,
|
|
54
63
|
insertResponsiveColumnLayout,
|
|
55
64
|
isCrossRealmElement,
|
|
56
65
|
isCrossRealmHTMLElement,
|
|
@@ -58,6 +67,7 @@ import {
|
|
|
58
67
|
isCrossRealmTable,
|
|
59
68
|
isCrossRealmTableCell,
|
|
60
69
|
isCrossRealmTableRow,
|
|
70
|
+
isDraftTableFormula,
|
|
61
71
|
isPointOverRenderedText,
|
|
62
72
|
isRowResizeHotspot,
|
|
63
73
|
isRowResizingGlobal,
|
|
@@ -66,19 +76,24 @@ import {
|
|
|
66
76
|
moveResponsiveColumnRatio,
|
|
67
77
|
normalizeColumnRatios,
|
|
68
78
|
normalizeStyleValue,
|
|
79
|
+
normalizeTableFormula,
|
|
69
80
|
normalizeTableWidthMode,
|
|
70
81
|
parseColumnRatios,
|
|
71
82
|
parsePercentageToBasisPoints,
|
|
83
|
+
parseTableCellRange,
|
|
72
84
|
resetImageSize,
|
|
73
85
|
resolveColumnResizeTarget,
|
|
74
86
|
resolveEventElement,
|
|
75
87
|
resolveResponsiveTableOffsetBp,
|
|
76
88
|
resolveRowResizeTarget,
|
|
89
|
+
rewriteTableNodeFormulaReferencesForDeletion,
|
|
90
|
+
rewriteTableNodeFormulaReferencesForInsertion,
|
|
91
|
+
rewriteTableNodeFormulaReferencesForMove,
|
|
77
92
|
runTableCommandAtCellPos,
|
|
78
93
|
sanitizeUEditorUrl,
|
|
79
94
|
useEditorColors,
|
|
80
95
|
useSharedEditorUiRenderState
|
|
81
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-37MHVJMV.js";
|
|
82
97
|
import {
|
|
83
98
|
Tooltip,
|
|
84
99
|
UEditorPortalProvider,
|
|
@@ -88,7 +103,7 @@ import {
|
|
|
88
103
|
resolveUEditorPortalContainer,
|
|
89
104
|
useSmartTranslations,
|
|
90
105
|
useUEditorPortalContainerGetter
|
|
91
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-ZP7F4ZD7.js";
|
|
92
107
|
|
|
93
108
|
// src/components/UEditor/prepare-content-for-save.ts
|
|
94
109
|
var MIME_EXTENSION_MAP = {
|
|
@@ -141,16 +156,16 @@ function createFileFromDataImageUrl(dataUrl, index) {
|
|
|
141
156
|
const name = `ueditor-image-${index + 1}.${extension}`;
|
|
142
157
|
return new File([bytes], name, { type: parsed.mime });
|
|
143
158
|
}
|
|
144
|
-
function normalizeUploadResult(result) {
|
|
159
|
+
function normalizeUploadResult(result, kind) {
|
|
145
160
|
if (typeof result === "string") {
|
|
146
|
-
const url2 = sanitizeUEditorUrl(result,
|
|
161
|
+
const url2 = sanitizeUEditorUrl(result, kind);
|
|
147
162
|
if (!url2) throw new Error("Upload handler returned an empty URL.");
|
|
148
163
|
return { url: url2 };
|
|
149
164
|
}
|
|
150
165
|
if (!result || typeof result !== "object") {
|
|
151
166
|
throw new Error("Upload handler returned invalid result.");
|
|
152
167
|
}
|
|
153
|
-
const url = typeof result.url === "string" ? sanitizeUEditorUrl(result.url,
|
|
168
|
+
const url = typeof result.url === "string" ? sanitizeUEditorUrl(result.url, kind) : "";
|
|
154
169
|
if (!url) throw new Error("Upload handler object result is missing `url`.");
|
|
155
170
|
const { url: _ignoredUrl, ...rest } = result;
|
|
156
171
|
const meta = Object.keys(rest).length > 0 ? rest : void 0;
|
|
@@ -205,11 +220,13 @@ function normalizeImageUrl(url) {
|
|
|
205
220
|
}
|
|
206
221
|
function replaceSrcInTag(match, nextSrc) {
|
|
207
222
|
if (!match.srcAttr) return match.tag;
|
|
208
|
-
const { start, end
|
|
209
|
-
const
|
|
210
|
-
const srcAttr = quote ? `src=${quote}${escaped}${quote}` : `src=${escaped}`;
|
|
223
|
+
const { start, end } = match.srcAttr;
|
|
224
|
+
const srcAttr = `src="${escapeHtmlAttribute(nextSrc)}"`;
|
|
211
225
|
return `${match.tag.slice(0, start)}${srcAttr}${match.tag.slice(end)}`;
|
|
212
226
|
}
|
|
227
|
+
function escapeHtmlAttribute(value) {
|
|
228
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
229
|
+
}
|
|
213
230
|
function collectImgTagMatches(html) {
|
|
214
231
|
const matches = [];
|
|
215
232
|
const imgRegex = /<img\b[^>]*>/gi;
|
|
@@ -327,13 +344,14 @@ function collectFileCardMatches(html) {
|
|
|
327
344
|
}
|
|
328
345
|
function replaceFileCardAttrs(tag, nextUrl) {
|
|
329
346
|
let result = tag;
|
|
347
|
+
const escapedUrl = escapeHtmlAttribute(nextUrl);
|
|
330
348
|
const hrefRegex = /(\bhref\s*=\s*)(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+)/i;
|
|
331
349
|
const dataSrcRegex = /(\bdata-src\s*=\s*)(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+)/i;
|
|
332
350
|
if (hrefRegex.test(result)) {
|
|
333
|
-
result = result.replace(hrefRegex, `$1"${
|
|
351
|
+
result = result.replace(hrefRegex, `$1"${escapedUrl}"`);
|
|
334
352
|
}
|
|
335
353
|
if (dataSrcRegex.test(result)) {
|
|
336
|
-
result = result.replace(dataSrcRegex, `$1"${
|
|
354
|
+
result = result.replace(dataSrcRegex, `$1"${escapedUrl}"`);
|
|
337
355
|
}
|
|
338
356
|
return result;
|
|
339
357
|
}
|
|
@@ -403,7 +421,7 @@ async function prepareUEditorContentForSave({
|
|
|
403
421
|
try {
|
|
404
422
|
const file = createFileFromDataImageUrl(candidate.src, candidate.index);
|
|
405
423
|
const uploadResult = await uploadImageForSave(file);
|
|
406
|
-
const normalized = normalizeUploadResult(uploadResult);
|
|
424
|
+
const normalized = normalizeUploadResult(uploadResult, "image");
|
|
407
425
|
return { candidate, file, ...normalized };
|
|
408
426
|
} catch (error) {
|
|
409
427
|
return { candidate, error: getErrorReason(error) };
|
|
@@ -450,7 +468,7 @@ async function prepareUEditorContentForSave({
|
|
|
450
468
|
try {
|
|
451
469
|
const file = createFileFromDataUrl(candidate.src, candidate.fileName);
|
|
452
470
|
const uploadResult = await uploadFn(file);
|
|
453
|
-
const normalized = normalizeUploadResult(uploadResult);
|
|
471
|
+
const normalized = normalizeUploadResult(uploadResult, "file");
|
|
454
472
|
return { candidate, file, ...normalized };
|
|
455
473
|
} catch (error) {
|
|
456
474
|
return { candidate, error: getErrorReason(error) };
|
|
@@ -503,7 +521,7 @@ async function prepareUEditorContentForSave({
|
|
|
503
521
|
}
|
|
504
522
|
|
|
505
523
|
// src/components/UEditor/UEditor.tsx
|
|
506
|
-
import
|
|
524
|
+
import React17, { useEffect as useEffect10, useImperativeHandle as useImperativeHandle4, useMemo as useMemo2, useRef as useRef10 } from "react";
|
|
507
525
|
import { useEditor, EditorContent } from "@tiptap/react";
|
|
508
526
|
|
|
509
527
|
// src/components/UEditor/extensions.ts
|
|
@@ -538,7 +556,7 @@ import { NodeViewWrapper, NodeViewContent } from "@tiptap/react";
|
|
|
538
556
|
import React from "react";
|
|
539
557
|
import { jsx } from "react/jsx-runtime";
|
|
540
558
|
var LazyBaseEmojiPicker = React.lazy(async () => {
|
|
541
|
-
const { EmojiPicker: EmojiPicker2 } = await import("./EmojiPicker-
|
|
559
|
+
const { EmojiPicker: EmojiPicker2 } = await import("./EmojiPicker-ISJ6RXYG.js");
|
|
542
560
|
return { default: EmojiPicker2 };
|
|
543
561
|
});
|
|
544
562
|
var EmojiPicker = ({ onSelect }) => {
|
|
@@ -575,7 +593,8 @@ var CalloutView = ({ node, updateAttributes, selected }) => {
|
|
|
575
593
|
"button",
|
|
576
594
|
{
|
|
577
595
|
type: "button",
|
|
578
|
-
|
|
596
|
+
"aria-label": t("callout.selectEmoji"),
|
|
597
|
+
className: "flex items-center justify-center text-2xl h-9 w-9 hover:bg-muted-foreground/10 active:scale-95 rounded-lg transition-[background-color,transform] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring motion-reduce:transition-none",
|
|
579
598
|
children: currentEmoji
|
|
580
599
|
}
|
|
581
600
|
),
|
|
@@ -589,9 +608,11 @@ var CalloutView = ({ node, updateAttributes, selected }) => {
|
|
|
589
608
|
{
|
|
590
609
|
type: "button",
|
|
591
610
|
title: col.name,
|
|
611
|
+
"aria-label": `${t("callout.backgroundColor")}: ${col.name}`,
|
|
612
|
+
"aria-pressed": currentBgColor === col.color,
|
|
592
613
|
onClick: () => updateAttributes({ backgroundColor: col.color }),
|
|
593
614
|
className: cn(
|
|
594
|
-
"h-6 w-6 rounded-full border transition-
|
|
615
|
+
"h-6 w-6 rounded-full border transition-[transform,border-color,box-shadow] active:scale-90 hover:scale-105 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring motion-reduce:transition-none",
|
|
595
616
|
currentBgColor === col.color ? "border-primary ring-2 ring-primary/30" : "border-border/60"
|
|
596
617
|
),
|
|
597
618
|
style: { backgroundColor: col.color }
|
|
@@ -1079,12 +1100,13 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
1079
1100
|
e.preventDefault();
|
|
1080
1101
|
e.stopPropagation();
|
|
1081
1102
|
if (!safeSrc) return;
|
|
1082
|
-
const
|
|
1103
|
+
const ownerDocument = editor.view.dom.ownerDocument;
|
|
1104
|
+
const link = ownerDocument.createElement("a");
|
|
1083
1105
|
link.href = safeSrc;
|
|
1084
1106
|
link.download = fileName || "download";
|
|
1085
|
-
|
|
1107
|
+
ownerDocument.body.appendChild(link);
|
|
1086
1108
|
link.click();
|
|
1087
|
-
|
|
1109
|
+
ownerDocument.body.removeChild(link);
|
|
1088
1110
|
};
|
|
1089
1111
|
const hasInlineUpload = safeSrc.startsWith("data:") && Boolean(uploadFn);
|
|
1090
1112
|
const handleRetryUpload = (event) => {
|
|
@@ -1098,18 +1120,19 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
1098
1120
|
NodeViewWrapper3,
|
|
1099
1121
|
{
|
|
1100
1122
|
className: cn(
|
|
1101
|
-
"my-4 flex items-center justify-between rounded-xl border border-border/60 bg-card p-4 hover:bg-muted/15 transition-
|
|
1123
|
+
"my-4 flex items-center justify-between rounded-xl border border-border/60 bg-card p-4 hover:bg-muted/15 transition-[background-color,border-color,box-shadow] duration-200 select-none",
|
|
1102
1124
|
selected && "ring-2 ring-primary/45 border-primary/20 shadow-sm"
|
|
1103
1125
|
),
|
|
1104
|
-
|
|
1126
|
+
role: "group",
|
|
1127
|
+
"aria-label": fileName || t("fileCard.unnamed"),
|
|
1105
1128
|
children: [
|
|
1106
1129
|
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3.5 min-w-0", children: [
|
|
1107
|
-
/* @__PURE__ */ jsx4("div", { className: "flex h-11 w-11 items-center justify-center rounded-lg bg-primary/10 text-primary flex-shrink-0", children: /* @__PURE__ */ jsx4(FileIcon, { className: "h-6 w-6" }) }),
|
|
1130
|
+
/* @__PURE__ */ jsx4("div", { className: "flex h-11 w-11 items-center justify-center rounded-lg bg-primary/10 text-primary flex-shrink-0", children: /* @__PURE__ */ jsx4(FileIcon, { "aria-hidden": "true", className: "h-6 w-6" }) }),
|
|
1108
1131
|
/* @__PURE__ */ jsxs3("div", { className: "min-w-0", children: [
|
|
1109
1132
|
/* @__PURE__ */ jsx4("div", { className: "text-sm font-semibold text-foreground truncate break-all", children: fileName || t("fileCard.unnamed") }),
|
|
1110
1133
|
/* @__PURE__ */ jsxs3("div", { className: "text-xs text-muted-foreground flex items-center gap-2 mt-0.5", children: [
|
|
1111
1134
|
fileSize ? /* @__PURE__ */ jsx4("span", { children: formatBytes(fileSize) }) : null,
|
|
1112
|
-
hasInlineUpload && /* @__PURE__ */ jsx4("span", { className: cn(
|
|
1135
|
+
hasInlineUpload && /* @__PURE__ */ jsx4("span", { "aria-live": "polite", className: cn(
|
|
1113
1136
|
"font-medium truncate max-w-50",
|
|
1114
1137
|
uploadError ? "text-destructive" : "text-primary animate-pulse"
|
|
1115
1138
|
), children: uploadError ? `${t("fileCard.uploadFailed") || "T\u1EA3i l\xEAn th\u1EA5t b\u1EA1i"}: ${uploadError}` : t("fileCard.uploading") }),
|
|
@@ -1120,7 +1143,7 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
1120
1143
|
onClick: handleRetryUpload,
|
|
1121
1144
|
className: "inline-flex items-center gap-1 rounded-md border border-destructive/30 px-1.5 py-0.5 text-[11px] font-medium text-destructive hover:bg-destructive/10",
|
|
1122
1145
|
children: [
|
|
1123
|
-
/* @__PURE__ */ jsx4(RefreshCw2, { className: "h-3 w-3" }),
|
|
1146
|
+
/* @__PURE__ */ jsx4(RefreshCw2, { "aria-hidden": "true", className: "h-3 w-3" }),
|
|
1124
1147
|
t("fileCard.retryUpload")
|
|
1125
1148
|
]
|
|
1126
1149
|
}
|
|
@@ -1133,8 +1156,9 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
1133
1156
|
{
|
|
1134
1157
|
type: "button",
|
|
1135
1158
|
onClick: handleDownload,
|
|
1136
|
-
|
|
1137
|
-
|
|
1159
|
+
"aria-label": t("fileCard.download").replace("{name}", fileName || t("fileCard.unnamed")),
|
|
1160
|
+
className: "flex h-8 w-8 items-center justify-center rounded-lg border border-border bg-background text-muted-foreground hover:text-foreground hover:bg-muted active:scale-95 transition-[color,background-color,transform] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
1161
|
+
children: /* @__PURE__ */ jsx4(Download, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
1138
1162
|
}
|
|
1139
1163
|
)
|
|
1140
1164
|
]
|
|
@@ -1392,6 +1416,7 @@ import { Node as Node5, mergeAttributes as mergeAttributes5 } from "@tiptap/core
|
|
|
1392
1416
|
import { ReactNodeViewRenderer as ReactNodeViewRenderer5 } from "@tiptap/react";
|
|
1393
1417
|
|
|
1394
1418
|
// src/components/UEditor/FormRadioView.tsx
|
|
1419
|
+
import { useId } from "react";
|
|
1395
1420
|
import { NodeViewWrapper as NodeViewWrapper5 } from "@tiptap/react";
|
|
1396
1421
|
import { Settings } from "lucide-react";
|
|
1397
1422
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
@@ -1400,6 +1425,8 @@ var FormRadioView = ({ node, updateAttributes, editor, selected }) => {
|
|
|
1400
1425
|
const isChecked = !!node.attrs.checked;
|
|
1401
1426
|
const isEditable = editor.isEditable;
|
|
1402
1427
|
const groupName = node.attrs.name || "radio-group";
|
|
1428
|
+
const groupInputId = useId();
|
|
1429
|
+
const radioLabel = `${t("menubar.formRadio")} \u2014 ${node.attrs.value || groupName}`;
|
|
1403
1430
|
const handleSelect = (e) => {
|
|
1404
1431
|
e.preventDefault();
|
|
1405
1432
|
e.stopPropagation();
|
|
@@ -1425,6 +1452,7 @@ var FormRadioView = ({ node, updateAttributes, editor, selected }) => {
|
|
|
1425
1452
|
{
|
|
1426
1453
|
role: "radio",
|
|
1427
1454
|
"aria-checked": isChecked,
|
|
1455
|
+
"aria-label": radioLabel,
|
|
1428
1456
|
tabIndex: isEditable ? 0 : -1,
|
|
1429
1457
|
onClick: handleSelect,
|
|
1430
1458
|
onKeyDown: handleKeyDown2,
|
|
@@ -1453,17 +1481,21 @@ var FormRadioView = ({ node, updateAttributes, editor, selected }) => {
|
|
|
1453
1481
|
"button",
|
|
1454
1482
|
{
|
|
1455
1483
|
type: "button",
|
|
1484
|
+
"aria-label": t("radio.editGroup") || "Edit Group",
|
|
1456
1485
|
className: "p-0.5 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors outline-none cursor-pointer",
|
|
1457
1486
|
title: t("radio.editGroup") || "Edit Group",
|
|
1458
1487
|
children: /* @__PURE__ */ jsx6(Settings, { className: "w-3.5 h-3.5" })
|
|
1459
1488
|
}
|
|
1460
1489
|
),
|
|
1461
1490
|
children: /* @__PURE__ */ jsxs4("div", { className: "p-3 w-52 flex flex-col gap-2 bg-card border rounded-xl shadow-lg text-card-foreground", children: [
|
|
1462
|
-
/* @__PURE__ */ jsx6("label", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: t("radio.groupName") || "Group Name" }),
|
|
1491
|
+
/* @__PURE__ */ jsx6("label", { htmlFor: groupInputId, className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: t("radio.groupName") || "Group Name" }),
|
|
1463
1492
|
/* @__PURE__ */ jsx6(
|
|
1464
1493
|
"input",
|
|
1465
1494
|
{
|
|
1466
1495
|
type: "text",
|
|
1496
|
+
id: groupInputId,
|
|
1497
|
+
name: "radio-group-name",
|
|
1498
|
+
autoComplete: "off",
|
|
1467
1499
|
value: groupName,
|
|
1468
1500
|
onChange: (e) => updateAttributes({ name: e.target.value }),
|
|
1469
1501
|
className: `w-full rounded-lg bg-background px-2 py-1.5 text-sm text-foreground ${formControlOutlineClass}`
|
|
@@ -1478,6 +1510,12 @@ var FormRadioView = ({ node, updateAttributes, editor, selected }) => {
|
|
|
1478
1510
|
};
|
|
1479
1511
|
|
|
1480
1512
|
// src/components/UEditor/form-radio.ts
|
|
1513
|
+
var formRadioIdSequence = 0;
|
|
1514
|
+
function createFormRadioId() {
|
|
1515
|
+
formRadioIdSequence += 1;
|
|
1516
|
+
const randomId = globalThis.crypto?.randomUUID?.();
|
|
1517
|
+
return randomId ? `rad-${randomId}` : `rad-${Date.now().toString(36)}-${formRadioIdSequence.toString(36)}`;
|
|
1518
|
+
}
|
|
1481
1519
|
var FormRadio = Node5.create({
|
|
1482
1520
|
name: "formRadio",
|
|
1483
1521
|
group: "inline",
|
|
@@ -1510,7 +1548,7 @@ var FormRadio = Node5.create({
|
|
|
1510
1548
|
},
|
|
1511
1549
|
id: {
|
|
1512
1550
|
default: null,
|
|
1513
|
-
parseHTML: (element) => element.getAttribute("data-id") || element.getAttribute("id") ||
|
|
1551
|
+
parseHTML: (element) => element.getAttribute("data-id") || element.getAttribute("id") || createFormRadioId(),
|
|
1514
1552
|
renderHTML: (attributes) => {
|
|
1515
1553
|
if (!attributes.id) return {};
|
|
1516
1554
|
return {
|
|
@@ -1569,10 +1607,15 @@ var FormRadio = Node5.create({
|
|
|
1569
1607
|
setFormRadio: (attributes) => ({ commands }) => {
|
|
1570
1608
|
return commands.insertContent({
|
|
1571
1609
|
type: this.name,
|
|
1572
|
-
attrs:
|
|
1610
|
+
attrs: {
|
|
1611
|
+
...attributes,
|
|
1612
|
+
id: attributes?.id || createFormRadioId(),
|
|
1613
|
+
name: attributes?.name || "radio-group"
|
|
1614
|
+
}
|
|
1573
1615
|
});
|
|
1574
1616
|
},
|
|
1575
1617
|
checkFormRadio: (id) => ({ tr, dispatch }) => {
|
|
1618
|
+
if (!id) return false;
|
|
1576
1619
|
if (!dispatch) return true;
|
|
1577
1620
|
let targetGroupName = "";
|
|
1578
1621
|
let targetPos = -1;
|
|
@@ -1624,7 +1667,7 @@ import { Gapcursor } from "@tiptap/extension-gapcursor";
|
|
|
1624
1667
|
import { Extension } from "@tiptap/core";
|
|
1625
1668
|
import { Suggestion } from "@tiptap/suggestion";
|
|
1626
1669
|
import { ReactRenderer } from "@tiptap/react";
|
|
1627
|
-
import
|
|
1670
|
+
import React5, { forwardRef, useEffect as useEffect3, useImperativeHandle, useRef as useRef2 } from "react";
|
|
1628
1671
|
import {
|
|
1629
1672
|
FileCode,
|
|
1630
1673
|
Heading1,
|
|
@@ -1709,9 +1752,9 @@ var DEFAULT_MESSAGES = {
|
|
|
1709
1752
|
formRadioDesc: "Insert an interactive radio button field"
|
|
1710
1753
|
};
|
|
1711
1754
|
function useResettingIndex(resetToken) {
|
|
1712
|
-
const [state, setState] =
|
|
1755
|
+
const [state, setState] = React5.useState({ resetToken, index: 0 });
|
|
1713
1756
|
const selectedIndex = Object.is(state.resetToken, resetToken) ? state.index : 0;
|
|
1714
|
-
const setSelectedIndex =
|
|
1757
|
+
const setSelectedIndex = React5.useCallback((nextIndex) => {
|
|
1715
1758
|
setState((prev) => {
|
|
1716
1759
|
const prevIndex = Object.is(prev.resetToken, resetToken) ? prev.index : 0;
|
|
1717
1760
|
return {
|
|
@@ -1927,7 +1970,7 @@ function buildSlashCommandItems({
|
|
|
1927
1970
|
title: messages.formRadio,
|
|
1928
1971
|
description: messages.formRadioDesc,
|
|
1929
1972
|
command: run(({ editor, range }) => {
|
|
1930
|
-
getCommandChain(editor, range).setFormRadio(
|
|
1973
|
+
getCommandChain(editor, range).setFormRadio().run();
|
|
1931
1974
|
})
|
|
1932
1975
|
}
|
|
1933
1976
|
].filter((item) => {
|
|
@@ -1939,6 +1982,7 @@ function buildSlashCommandItems({
|
|
|
1939
1982
|
var SlashCommandList = forwardRef((props, ref) => {
|
|
1940
1983
|
const [selectedIndex, setSelectedIndex] = useResettingIndex(props.items);
|
|
1941
1984
|
const listRef = useRef2(null);
|
|
1985
|
+
const listId = React5.useId();
|
|
1942
1986
|
useEffect3(() => {
|
|
1943
1987
|
const selectedElement = listRef.current?.querySelector(`[data-index="${selectedIndex}"]`);
|
|
1944
1988
|
selectedElement?.scrollIntoView({ block: "nearest" });
|
|
@@ -1969,41 +2013,56 @@ var SlashCommandList = forwardRef((props, ref) => {
|
|
|
1969
2013
|
}
|
|
1970
2014
|
}));
|
|
1971
2015
|
if (props.items.length === 0) {
|
|
1972
|
-
return /* @__PURE__ */ jsx7("div", { className: "w-72 p-4 text-center text-sm text-muted-foreground", children: props.messages.noResults });
|
|
2016
|
+
return /* @__PURE__ */ jsx7("div", { role: "status", className: "w-72 p-4 text-center text-sm text-muted-foreground", children: props.messages.noResults });
|
|
1973
2017
|
}
|
|
1974
|
-
return /* @__PURE__ */ jsxs5(
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
2018
|
+
return /* @__PURE__ */ jsxs5(
|
|
2019
|
+
"div",
|
|
2020
|
+
{
|
|
2021
|
+
ref: listRef,
|
|
2022
|
+
id: listId,
|
|
2023
|
+
role: "listbox",
|
|
2024
|
+
"aria-label": props.messages.basicBlocks,
|
|
2025
|
+
"aria-activedescendant": `${listId}-option-${selectedIndex}`,
|
|
2026
|
+
className: "w-72 max-h-80 overflow-y-auto bg-card border border-border/50 rounded-2xl shadow-lg",
|
|
2027
|
+
children: [
|
|
2028
|
+
/* @__PURE__ */ jsx7("div", { className: "px-3 py-2 border-b", children: /* @__PURE__ */ jsx7("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: props.messages.basicBlocks }) }),
|
|
2029
|
+
/* @__PURE__ */ jsx7("div", { className: "p-1", children: props.items.map((item, index) => /* @__PURE__ */ jsxs5(
|
|
2030
|
+
"button",
|
|
2031
|
+
{
|
|
2032
|
+
type: "button",
|
|
2033
|
+
id: `${listId}-option-${index}`,
|
|
2034
|
+
role: "option",
|
|
2035
|
+
"aria-selected": selectedIndex === index,
|
|
2036
|
+
tabIndex: -1,
|
|
2037
|
+
"data-index": index,
|
|
2038
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
2039
|
+
onClick: () => props.command(item),
|
|
2040
|
+
className: cn(
|
|
2041
|
+
"flex items-center w-full px-3 py-2.5 rounded-lg transition-colors group",
|
|
2042
|
+
selectedIndex === index ? "bg-accent" : "hover:bg-accent/50"
|
|
2043
|
+
),
|
|
2044
|
+
children: [
|
|
2045
|
+
/* @__PURE__ */ jsx7(
|
|
2046
|
+
"div",
|
|
2047
|
+
{
|
|
2048
|
+
className: cn(
|
|
2049
|
+
"flex items-center justify-center w-10 h-10 rounded-lg mr-3 transition-colors",
|
|
2050
|
+
selectedIndex === index ? "bg-primary/10" : "bg-muted/50 group-hover:bg-muted"
|
|
2051
|
+
),
|
|
2052
|
+
children: /* @__PURE__ */ jsx7(item.icon, { "aria-hidden": "true", className: cn("w-5 h-5", selectedIndex === index ? "text-primary" : "text-muted-foreground") })
|
|
2053
|
+
}
|
|
1994
2054
|
),
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
] });
|
|
2055
|
+
/* @__PURE__ */ jsxs5("div", { className: "text-left", children: [
|
|
2056
|
+
/* @__PURE__ */ jsx7("div", { className: cn("text-sm font-medium", selectedIndex === index && "text-primary"), children: item.title }),
|
|
2057
|
+
/* @__PURE__ */ jsx7("div", { className: "text-xs text-muted-foreground", children: item.description })
|
|
2058
|
+
] })
|
|
2059
|
+
]
|
|
2060
|
+
},
|
|
2061
|
+
item.title
|
|
2062
|
+
)) })
|
|
2063
|
+
]
|
|
2064
|
+
}
|
|
2065
|
+
);
|
|
2007
2066
|
});
|
|
2008
2067
|
SlashCommandList.displayName = "SlashCommandList";
|
|
2009
2068
|
var SlashCommand = Extension.create({
|
|
@@ -2087,13 +2146,13 @@ import { Extension as Extension2 } from "@tiptap/core";
|
|
|
2087
2146
|
import { Suggestion as Suggestion2 } from "@tiptap/suggestion";
|
|
2088
2147
|
import { ReactRenderer as ReactRenderer2 } from "@tiptap/react";
|
|
2089
2148
|
import { PluginKey as PluginKey2 } from "@tiptap/pm/state";
|
|
2090
|
-
import
|
|
2149
|
+
import React6, { forwardRef as forwardRef2, useImperativeHandle as useImperativeHandle2 } from "react";
|
|
2091
2150
|
import { Smile } from "lucide-react";
|
|
2092
2151
|
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2093
2152
|
function useResettingIndex2(resetToken) {
|
|
2094
|
-
const [state, setState] =
|
|
2153
|
+
const [state, setState] = React6.useState({ resetToken, index: 0 });
|
|
2095
2154
|
const selectedIndex = Object.is(state.resetToken, resetToken) ? state.index : 0;
|
|
2096
|
-
const setSelectedIndex =
|
|
2155
|
+
const setSelectedIndex = React6.useCallback((nextIndex) => {
|
|
2097
2156
|
setState((prev) => {
|
|
2098
2157
|
const prevIndex = Object.is(prev.resetToken, resetToken) ? prev.index : 0;
|
|
2099
2158
|
return {
|
|
@@ -2107,6 +2166,7 @@ function useResettingIndex2(resetToken) {
|
|
|
2107
2166
|
var EmojiList = forwardRef2((props, ref) => {
|
|
2108
2167
|
const t = useSmartTranslations("UEditor");
|
|
2109
2168
|
const [selectedIndex, setSelectedIndex] = useResettingIndex2(props.items);
|
|
2169
|
+
const listId = React6.useId();
|
|
2110
2170
|
const showingCountLabel = formatEmojiCountLabel(t("emojiSuggestion.showingCount"), 64, props.items.length);
|
|
2111
2171
|
useImperativeHandle2(ref, () => ({
|
|
2112
2172
|
onKeyDown: (keyProps) => {
|
|
@@ -2139,28 +2199,42 @@ var EmojiList = forwardRef2((props, ref) => {
|
|
|
2139
2199
|
}
|
|
2140
2200
|
}));
|
|
2141
2201
|
if (props.items.length === 0) {
|
|
2142
|
-
return /* @__PURE__ */ jsx8("div", { className: "w-80 p-4 text-center text-sm text-muted-foreground bg-card border border-border/50 rounded-2xl shadow-lg", children: t("emojiSuggestion.noResults") });
|
|
2143
|
-
}
|
|
2144
|
-
return /* @__PURE__ */ jsxs6(
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2202
|
+
return /* @__PURE__ */ jsx8("div", { role: "status", className: "w-80 p-4 text-center text-sm text-muted-foreground bg-card border border-border/50 rounded-2xl shadow-lg", children: t("emojiSuggestion.noResults") });
|
|
2203
|
+
}
|
|
2204
|
+
return /* @__PURE__ */ jsxs6(
|
|
2205
|
+
"div",
|
|
2206
|
+
{
|
|
2207
|
+
id: listId,
|
|
2208
|
+
role: "listbox",
|
|
2209
|
+
"aria-label": t("emojiSuggestion.title"),
|
|
2210
|
+
"aria-activedescendant": `${listId}-option-${selectedIndex}`,
|
|
2211
|
+
className: "w-80 max-h-80 overflow-y-auto bg-card border border-border/50 rounded-2xl shadow-lg",
|
|
2212
|
+
children: [
|
|
2213
|
+
/* @__PURE__ */ jsx8("div", { className: "px-3 py-2 border-b bg-muted/30", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
|
|
2214
|
+
/* @__PURE__ */ jsx8(Smile, { className: "w-4 h-4 text-primary" }),
|
|
2215
|
+
/* @__PURE__ */ jsx8("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: t("emojiSuggestion.title") })
|
|
2216
|
+
] }) }),
|
|
2217
|
+
/* @__PURE__ */ jsxs6("div", { className: "p-3", children: [
|
|
2218
|
+
/* @__PURE__ */ jsx8("div", { className: "grid grid-cols-8 gap-1", children: props.items.slice(0, 64).map((item, index) => /* @__PURE__ */ jsx8(
|
|
2219
|
+
EmojiGridButton,
|
|
2220
|
+
{
|
|
2221
|
+
id: `${listId}-option-${index}`,
|
|
2222
|
+
role: "option",
|
|
2223
|
+
"aria-selected": selectedIndex === index,
|
|
2224
|
+
tabIndex: -1,
|
|
2225
|
+
emoji: item.emoji,
|
|
2226
|
+
name: item.name,
|
|
2227
|
+
onClick: () => props.command(item),
|
|
2228
|
+
active: selectedIndex === index,
|
|
2229
|
+
className: "text-xl"
|
|
2230
|
+
},
|
|
2231
|
+
item.name
|
|
2232
|
+
)) }),
|
|
2233
|
+
props.items.length > 64 && /* @__PURE__ */ jsx8("div", { className: "mt-2 text-xs text-center text-muted-foreground", children: showingCountLabel })
|
|
2234
|
+
] })
|
|
2235
|
+
]
|
|
2236
|
+
}
|
|
2237
|
+
);
|
|
2164
2238
|
});
|
|
2165
2239
|
EmojiList.displayName = "EmojiList";
|
|
2166
2240
|
var allEmojiItemsPromise = null;
|
|
@@ -2250,7 +2324,7 @@ import { Extension as Extension3 } from "@tiptap/core";
|
|
|
2250
2324
|
import { Suggestion as Suggestion3 } from "@tiptap/suggestion";
|
|
2251
2325
|
import { ReactRenderer as ReactRenderer3 } from "@tiptap/react";
|
|
2252
2326
|
import { PluginKey as PluginKey3 } from "@tiptap/pm/state";
|
|
2253
|
-
import
|
|
2327
|
+
import React7, { forwardRef as forwardRef3, useImperativeHandle as useImperativeHandle3 } from "react";
|
|
2254
2328
|
import { Sigma } from "lucide-react";
|
|
2255
2329
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2256
2330
|
var FORMULA_FUNCTIONS = [
|
|
@@ -2305,8 +2379,9 @@ function isFormulaFunctionSuggestionQuery(query) {
|
|
|
2305
2379
|
}
|
|
2306
2380
|
var FormulaSuggestionList = forwardRef3((props, ref) => {
|
|
2307
2381
|
const t = useSmartTranslations("UEditor");
|
|
2308
|
-
const [selectedIndex, setSelectedIndex] =
|
|
2309
|
-
|
|
2382
|
+
const [selectedIndex, setSelectedIndex] = React7.useState(0);
|
|
2383
|
+
const listId = React7.useId();
|
|
2384
|
+
React7.useEffect(() => {
|
|
2310
2385
|
setSelectedIndex(0);
|
|
2311
2386
|
}, [props.items]);
|
|
2312
2387
|
useImperativeHandle3(ref, () => ({
|
|
@@ -2331,32 +2406,46 @@ var FormulaSuggestionList = forwardRef3((props, ref) => {
|
|
|
2331
2406
|
}
|
|
2332
2407
|
}));
|
|
2333
2408
|
if (props.items.length === 0) {
|
|
2334
|
-
return /* @__PURE__ */ jsx9("div", { className: "w-72 p-3 text-sm text-muted-foreground bg-card border border-border/50 rounded-lg shadow-lg", children: t("formulaSuggestion.noResults") });
|
|
2335
|
-
}
|
|
2336
|
-
return /* @__PURE__ */ jsxs7(
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
"
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
className:
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
children:
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2409
|
+
return /* @__PURE__ */ jsx9("div", { role: "status", className: "w-72 p-3 text-sm text-muted-foreground bg-card border border-border/50 rounded-lg shadow-lg", children: t("formulaSuggestion.noResults") });
|
|
2410
|
+
}
|
|
2411
|
+
return /* @__PURE__ */ jsxs7(
|
|
2412
|
+
"div",
|
|
2413
|
+
{
|
|
2414
|
+
id: listId,
|
|
2415
|
+
role: "listbox",
|
|
2416
|
+
"aria-label": t("formulaSuggestion.title"),
|
|
2417
|
+
"aria-activedescendant": `${listId}-option-${selectedIndex}`,
|
|
2418
|
+
className: "w-72 max-h-80 overflow-y-auto bg-card border border-border/50 rounded-lg shadow-lg",
|
|
2419
|
+
children: [
|
|
2420
|
+
/* @__PURE__ */ jsx9("div", { className: "px-3 py-2 border-b bg-muted/30", children: /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
|
|
2421
|
+
/* @__PURE__ */ jsx9(Sigma, { className: "w-4 h-4 text-primary" }),
|
|
2422
|
+
/* @__PURE__ */ jsx9("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: t("formulaSuggestion.title") })
|
|
2423
|
+
] }) }),
|
|
2424
|
+
/* @__PURE__ */ jsx9("div", { className: "p-1.5", children: props.items.map((item, index) => /* @__PURE__ */ jsxs7(
|
|
2425
|
+
"button",
|
|
2426
|
+
{
|
|
2427
|
+
type: "button",
|
|
2428
|
+
id: `${listId}-option-${index}`,
|
|
2429
|
+
role: "option",
|
|
2430
|
+
"aria-selected": selectedIndex === index,
|
|
2431
|
+
tabIndex: -1,
|
|
2432
|
+
className: `w-full rounded-md px-2.5 py-2 text-left transition-colors ${selectedIndex === index ? "bg-primary/10 text-primary" : "text-foreground hover:bg-muted"}`,
|
|
2433
|
+
onMouseEnter: () => setSelectedIndex(index),
|
|
2434
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
2435
|
+
onClick: () => props.command(item),
|
|
2436
|
+
children: [
|
|
2437
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-3", children: [
|
|
2438
|
+
/* @__PURE__ */ jsx9("span", { className: "font-mono text-sm font-semibold", children: item.name }),
|
|
2439
|
+
/* @__PURE__ */ jsx9("span", { className: "font-mono text-xs text-muted-foreground", children: item.signature })
|
|
2440
|
+
] }),
|
|
2441
|
+
/* @__PURE__ */ jsx9("div", { className: "mt-0.5 text-xs text-muted-foreground", children: t(item.descriptionKey) })
|
|
2442
|
+
]
|
|
2443
|
+
},
|
|
2444
|
+
item.name
|
|
2445
|
+
)) })
|
|
2446
|
+
]
|
|
2447
|
+
}
|
|
2448
|
+
);
|
|
2360
2449
|
});
|
|
2361
2450
|
FormulaSuggestionList.displayName = "FormulaSuggestionList";
|
|
2362
2451
|
function insertFormulaFunction(editor, range, item) {
|
|
@@ -3360,7 +3449,10 @@ import { Plugin as Plugin4, PluginKey as PluginKey5, TextSelection } from "@tipt
|
|
|
3360
3449
|
import {
|
|
3361
3450
|
addColumnAfter as addColumnAfterCommand,
|
|
3362
3451
|
addColumnBefore as addColumnBeforeCommand,
|
|
3452
|
+
addRowAfter as addRowAfterCommand,
|
|
3453
|
+
addRowBefore as addRowBeforeCommand,
|
|
3363
3454
|
deleteColumn as deleteColumnCommand,
|
|
3455
|
+
deleteRow as deleteRowCommand,
|
|
3364
3456
|
selectedRect,
|
|
3365
3457
|
tableEditing,
|
|
3366
3458
|
tableNodeTypes as tableNodeTypes2
|
|
@@ -3938,19 +4030,25 @@ function createUEditorColGroup(node, widthMode) {
|
|
|
3938
4030
|
tableWidth: totalWidth > 0 ? `${totalWidth}px` : ""
|
|
3939
4031
|
};
|
|
3940
4032
|
}
|
|
3941
|
-
function runResponsiveColumnStructureCommand(state, dispatch, command, updateLayout) {
|
|
4033
|
+
function runResponsiveColumnStructureCommand(state, dispatch, command, updateLayout, rewriteFormulas) {
|
|
3942
4034
|
const tableInfo = findTableNodeInfoFromState(state);
|
|
3943
|
-
if (!tableInfo
|
|
4035
|
+
if (!tableInfo) {
|
|
3944
4036
|
return command(state, dispatch);
|
|
3945
4037
|
}
|
|
3946
|
-
|
|
3947
|
-
|
|
4038
|
+
let rect;
|
|
4039
|
+
try {
|
|
4040
|
+
rect = selectedRect(state);
|
|
4041
|
+
} catch {
|
|
4042
|
+
return false;
|
|
4043
|
+
}
|
|
4044
|
+
const responsive = normalizeTableWidthMode(tableInfo.node.attrs.widthMode) === "responsive";
|
|
4045
|
+
const nextLayout = responsive ? updateLayout({
|
|
3948
4046
|
widthBp: getResponsiveTableWidthBp(tableInfo.node),
|
|
3949
4047
|
columnRatios: getTableColumnRatios(tableInfo.node)
|
|
3950
|
-
}, rect);
|
|
4048
|
+
}, rect) : null;
|
|
3951
4049
|
return command(state, dispatch ? (transaction) => {
|
|
3952
|
-
|
|
3953
|
-
if (nextTable?.type.name === "table" && nextLayout.columnRatios.length > 0) {
|
|
4050
|
+
let nextTable = transaction.doc.nodeAt(tableInfo.pos);
|
|
4051
|
+
if (nextTable?.type.name === "table" && nextLayout && nextLayout.columnRatios.length > 0) {
|
|
3954
4052
|
const widthBp = clampResponsiveTableWidthBp(nextLayout.widthBp);
|
|
3955
4053
|
const tableAlign = normalizeTableAlign(nextTable.attrs.textAlign);
|
|
3956
4054
|
const offsetBp = resolveResponsiveTableOffsetBp(
|
|
@@ -3968,6 +4066,33 @@ function runResponsiveColumnStructureCommand(state, dispatch, command, updateLay
|
|
|
3968
4066
|
getLogicalTableColumnCount(nextTable)
|
|
3969
4067
|
)
|
|
3970
4068
|
});
|
|
4069
|
+
nextTable = transaction.doc.nodeAt(tableInfo.pos);
|
|
4070
|
+
}
|
|
4071
|
+
if (nextTable?.type.name === "table") {
|
|
4072
|
+
const rewrittenTable = rewriteFormulas(nextTable, rect);
|
|
4073
|
+
if (rewrittenTable !== nextTable) {
|
|
4074
|
+
transaction.replaceWith(tableInfo.pos, tableInfo.pos + nextTable.nodeSize, rewrittenTable);
|
|
4075
|
+
}
|
|
4076
|
+
}
|
|
4077
|
+
dispatch(transaction);
|
|
4078
|
+
} : void 0);
|
|
4079
|
+
}
|
|
4080
|
+
function runRowStructureCommand(state, dispatch, command, rewriteFormulas) {
|
|
4081
|
+
const tableInfo = findTableNodeInfoFromState(state);
|
|
4082
|
+
if (!tableInfo) return command(state, dispatch);
|
|
4083
|
+
let rect;
|
|
4084
|
+
try {
|
|
4085
|
+
rect = selectedRect(state);
|
|
4086
|
+
} catch {
|
|
4087
|
+
return false;
|
|
4088
|
+
}
|
|
4089
|
+
return command(state, dispatch ? (transaction) => {
|
|
4090
|
+
const nextTable = transaction.doc.nodeAt(tableInfo.pos);
|
|
4091
|
+
if (nextTable?.type.name === "table") {
|
|
4092
|
+
const rewrittenTable = rewriteFormulas(nextTable, rect);
|
|
4093
|
+
if (rewrittenTable !== nextTable) {
|
|
4094
|
+
transaction.replaceWith(tableInfo.pos, tableInfo.pos + nextTable.nodeSize, rewrittenTable);
|
|
4095
|
+
}
|
|
3971
4096
|
}
|
|
3972
4097
|
dispatch(transaction);
|
|
3973
4098
|
} : void 0);
|
|
@@ -4091,7 +4216,8 @@ var UEditorTable = Table2.extend({
|
|
|
4091
4216
|
layout.columnRatios,
|
|
4092
4217
|
rect.left,
|
|
4093
4218
|
rect.left
|
|
4094
|
-
)
|
|
4219
|
+
),
|
|
4220
|
+
(tableNode, rect) => rewriteTableNodeFormulaReferencesForInsertion(tableNode, "column", rect.left)
|
|
4095
4221
|
);
|
|
4096
4222
|
},
|
|
4097
4223
|
addColumnAfter: () => ({ state, dispatch }) => {
|
|
@@ -4104,7 +4230,8 @@ var UEditorTable = Table2.extend({
|
|
|
4104
4230
|
layout.columnRatios,
|
|
4105
4231
|
rect.right,
|
|
4106
4232
|
rect.right - 1
|
|
4107
|
-
)
|
|
4233
|
+
),
|
|
4234
|
+
(tableNode, rect) => rewriteTableNodeFormulaReferencesForInsertion(tableNode, "column", rect.right)
|
|
4108
4235
|
);
|
|
4109
4236
|
},
|
|
4110
4237
|
deleteColumn: () => ({ state, dispatch }) => {
|
|
@@ -4122,9 +4249,38 @@ var UEditorTable = Table2.extend({
|
|
|
4122
4249
|
);
|
|
4123
4250
|
}
|
|
4124
4251
|
return nextLayout;
|
|
4125
|
-
}
|
|
4252
|
+
},
|
|
4253
|
+
(tableNode, rect) => rewriteTableNodeFormulaReferencesForDeletion(
|
|
4254
|
+
tableNode,
|
|
4255
|
+
"column",
|
|
4256
|
+
rect.left,
|
|
4257
|
+
rect.right - rect.left
|
|
4258
|
+
)
|
|
4126
4259
|
);
|
|
4127
4260
|
},
|
|
4261
|
+
addRowBefore: () => ({ state, dispatch }) => runRowStructureCommand(
|
|
4262
|
+
state,
|
|
4263
|
+
dispatch,
|
|
4264
|
+
addRowBeforeCommand,
|
|
4265
|
+
(tableNode, rect) => rewriteTableNodeFormulaReferencesForInsertion(tableNode, "row", rect.top)
|
|
4266
|
+
),
|
|
4267
|
+
addRowAfter: () => ({ state, dispatch }) => runRowStructureCommand(
|
|
4268
|
+
state,
|
|
4269
|
+
dispatch,
|
|
4270
|
+
addRowAfterCommand,
|
|
4271
|
+
(tableNode, rect) => rewriteTableNodeFormulaReferencesForInsertion(tableNode, "row", rect.bottom)
|
|
4272
|
+
),
|
|
4273
|
+
deleteRow: () => ({ state, dispatch }) => runRowStructureCommand(
|
|
4274
|
+
state,
|
|
4275
|
+
dispatch,
|
|
4276
|
+
deleteRowCommand,
|
|
4277
|
+
(tableNode, rect) => rewriteTableNodeFormulaReferencesForDeletion(
|
|
4278
|
+
tableNode,
|
|
4279
|
+
"row",
|
|
4280
|
+
rect.top,
|
|
4281
|
+
rect.bottom - rect.top
|
|
4282
|
+
)
|
|
4283
|
+
),
|
|
4128
4284
|
setTableAlign: (tableAlign) => ({ state, dispatch }) => {
|
|
4129
4285
|
const tableInfo = findTableNodeInfoFromState(state);
|
|
4130
4286
|
if (!tableInfo) return false;
|
|
@@ -4275,7 +4431,7 @@ var UEditorTable = Table2.extend({
|
|
|
4275
4431
|
var table_align_default = UEditorTable;
|
|
4276
4432
|
|
|
4277
4433
|
// src/components/UEditor/CodeBlockView.tsx
|
|
4278
|
-
import
|
|
4434
|
+
import React9, { useState as useState4 } from "react";
|
|
4279
4435
|
import { NodeViewWrapper as NodeViewWrapper7, NodeViewContent as NodeViewContent2 } from "@tiptap/react";
|
|
4280
4436
|
import { Check as Check2, Copy, ChevronDown } from "lucide-react";
|
|
4281
4437
|
import { Fragment, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
@@ -4302,10 +4458,11 @@ var CodeBlockView = ({
|
|
|
4302
4458
|
}) => {
|
|
4303
4459
|
const [copied, setCopied] = useState4(false);
|
|
4304
4460
|
const [isDropdownOpen, setIsDropdownOpen] = useState4(false);
|
|
4305
|
-
const timeoutRef =
|
|
4461
|
+
const timeoutRef = React9.useRef(null);
|
|
4462
|
+
const t = useSmartTranslations("UEditor");
|
|
4306
4463
|
const currentLangValue = node.attrs.language || "text";
|
|
4307
4464
|
const currentLangLabel = LANGUAGES.find((lang) => lang.value === currentLangValue)?.label || "Plain Text";
|
|
4308
|
-
|
|
4465
|
+
React9.useEffect(() => {
|
|
4309
4466
|
return () => {
|
|
4310
4467
|
if (timeoutRef.current) {
|
|
4311
4468
|
clearTimeout(timeoutRef.current);
|
|
@@ -4339,10 +4496,12 @@ var CodeBlockView = ({
|
|
|
4339
4496
|
{
|
|
4340
4497
|
type: "button",
|
|
4341
4498
|
onClick: () => setIsDropdownOpen(!isDropdownOpen),
|
|
4342
|
-
|
|
4499
|
+
"aria-haspopup": "listbox",
|
|
4500
|
+
"aria-expanded": isDropdownOpen,
|
|
4501
|
+
className: "flex items-center gap-1.5 rounded-lg border border-border bg-background px-2.5 py-1 text-xs text-muted-foreground hover:text-foreground hover:bg-muted active:scale-95 transition-[color,background-color,transform] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
4343
4502
|
children: [
|
|
4344
4503
|
currentLangLabel,
|
|
4345
|
-
/* @__PURE__ */ jsx11(ChevronDown, { className: "h-3 w-3" })
|
|
4504
|
+
/* @__PURE__ */ jsx11(ChevronDown, { "aria-hidden": "true", className: "h-3 w-3" })
|
|
4346
4505
|
]
|
|
4347
4506
|
}
|
|
4348
4507
|
),
|
|
@@ -4354,10 +4513,12 @@ var CodeBlockView = ({
|
|
|
4354
4513
|
onClick: () => setIsDropdownOpen(false)
|
|
4355
4514
|
}
|
|
4356
4515
|
),
|
|
4357
|
-
/* @__PURE__ */ jsx11("div", { className: "absolute right-0 mt-1 max-h-56 w-36 overflow-y-auto rounded-lg border border-border/50 bg-popover p-1 shadow-lg z-30 [scrollbar-width:thin] animate-in fade-in-0 zoom-in-95", children: LANGUAGES.map((lang) => /* @__PURE__ */ jsx11(
|
|
4516
|
+
/* @__PURE__ */ jsx11("div", { role: "listbox", "aria-label": currentLangLabel, className: "absolute right-0 mt-1 max-h-56 w-36 overflow-y-auto rounded-lg border border-border/50 bg-popover p-1 shadow-lg z-30 [scrollbar-width:thin] animate-in fade-in-0 zoom-in-95 motion-reduce:animate-none", children: LANGUAGES.map((lang) => /* @__PURE__ */ jsx11(
|
|
4358
4517
|
"button",
|
|
4359
4518
|
{
|
|
4360
4519
|
type: "button",
|
|
4520
|
+
role: "option",
|
|
4521
|
+
"aria-selected": currentLangValue === lang.value,
|
|
4361
4522
|
onClick: () => {
|
|
4362
4523
|
updateAttributes({ language: lang.value });
|
|
4363
4524
|
setIsDropdownOpen(false);
|
|
@@ -4377,9 +4538,10 @@ var CodeBlockView = ({
|
|
|
4377
4538
|
{
|
|
4378
4539
|
type: "button",
|
|
4379
4540
|
onClick: handleCopy,
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4541
|
+
"aria-label": t("menubar.copy"),
|
|
4542
|
+
className: "flex h-7 w-7 items-center justify-center rounded-lg border border-border bg-background text-muted-foreground hover:text-foreground hover:bg-muted active:scale-95 transition-[color,background-color,transform] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
4543
|
+
title: t("menubar.copy"),
|
|
4544
|
+
children: copied ? /* @__PURE__ */ jsx11(Check2, { "aria-hidden": "true", className: "h-3.5 w-3.5 text-success animate-in fade-in-0 zoom-in-75 motion-reduce:animate-none" }) : /* @__PURE__ */ jsx11(Copy, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
|
|
4383
4545
|
}
|
|
4384
4546
|
)
|
|
4385
4547
|
]
|
|
@@ -4584,527 +4746,6 @@ import { Plugin as Plugin6 } from "@tiptap/pm/state";
|
|
|
4584
4746
|
// src/components/UEditor/table-formula-commands.ts
|
|
4585
4747
|
import { TextSelection as TextSelection2 } from "@tiptap/pm/state";
|
|
4586
4748
|
import { selectedRect as selectedRect2, setCellAttr, TableMap as TableMap2 } from "@tiptap/pm/tables";
|
|
4587
|
-
|
|
4588
|
-
// src/components/UEditor/table-formula.ts
|
|
4589
|
-
var CELL_ADDRESS_RE = /^([A-Z]+)([1-9]\d*)$/i;
|
|
4590
|
-
var CELL_RANGE_RE = /^([A-Z]+[1-9]\d*):([A-Z]+[1-9]\d*)$/i;
|
|
4591
|
-
var SUPPORTED_FUNCTIONS = /* @__PURE__ */ new Set(["SUM", "AVG", "MIN", "MAX", "COUNT"]);
|
|
4592
|
-
function columnNameToIndex(columnName) {
|
|
4593
|
-
const normalized = columnName.trim().toUpperCase();
|
|
4594
|
-
if (!/^[A-Z]+$/.test(normalized)) {
|
|
4595
|
-
return -1;
|
|
4596
|
-
}
|
|
4597
|
-
let index = 0;
|
|
4598
|
-
for (const char of normalized) {
|
|
4599
|
-
index = index * 26 + char.charCodeAt(0) - 64;
|
|
4600
|
-
}
|
|
4601
|
-
return index - 1;
|
|
4602
|
-
}
|
|
4603
|
-
function indexToColumnName(index) {
|
|
4604
|
-
if (!Number.isInteger(index) || index < 0) {
|
|
4605
|
-
return "";
|
|
4606
|
-
}
|
|
4607
|
-
let value = index + 1;
|
|
4608
|
-
let name = "";
|
|
4609
|
-
while (value > 0) {
|
|
4610
|
-
const remainder = (value - 1) % 26;
|
|
4611
|
-
name = String.fromCharCode(65 + remainder) + name;
|
|
4612
|
-
value = Math.floor((value - 1) / 26);
|
|
4613
|
-
}
|
|
4614
|
-
return name;
|
|
4615
|
-
}
|
|
4616
|
-
function parseTableCellAddress(input) {
|
|
4617
|
-
const match = input.trim().match(CELL_ADDRESS_RE);
|
|
4618
|
-
if (!match) {
|
|
4619
|
-
return null;
|
|
4620
|
-
}
|
|
4621
|
-
const column = columnNameToIndex(match[1] ?? "");
|
|
4622
|
-
const row = Number.parseInt(match[2] ?? "", 10) - 1;
|
|
4623
|
-
if (column < 0 || row < 0) {
|
|
4624
|
-
return null;
|
|
4625
|
-
}
|
|
4626
|
-
return {
|
|
4627
|
-
column,
|
|
4628
|
-
row,
|
|
4629
|
-
label: `${indexToColumnName(column)}${row + 1}`
|
|
4630
|
-
};
|
|
4631
|
-
}
|
|
4632
|
-
function parseTableCellRange(input) {
|
|
4633
|
-
const match = input.trim().match(CELL_RANGE_RE);
|
|
4634
|
-
if (!match) {
|
|
4635
|
-
return null;
|
|
4636
|
-
}
|
|
4637
|
-
const from = parseTableCellAddress(match[1] ?? "");
|
|
4638
|
-
const to = parseTableCellAddress(match[2] ?? "");
|
|
4639
|
-
if (!from || !to) {
|
|
4640
|
-
return null;
|
|
4641
|
-
}
|
|
4642
|
-
return { from, to };
|
|
4643
|
-
}
|
|
4644
|
-
function getTableCellRangeLabels(range) {
|
|
4645
|
-
const startColumn = Math.min(range.from.column, range.to.column);
|
|
4646
|
-
const endColumn = Math.max(range.from.column, range.to.column);
|
|
4647
|
-
const startRow = Math.min(range.from.row, range.to.row);
|
|
4648
|
-
const endRow = Math.max(range.from.row, range.to.row);
|
|
4649
|
-
const labels = [];
|
|
4650
|
-
for (let row = startRow; row <= endRow; row += 1) {
|
|
4651
|
-
for (let column = startColumn; column <= endColumn; column += 1) {
|
|
4652
|
-
labels.push(`${indexToColumnName(column)}${row + 1}`);
|
|
4653
|
-
}
|
|
4654
|
-
}
|
|
4655
|
-
return labels;
|
|
4656
|
-
}
|
|
4657
|
-
function normalizeTableFormula(formula) {
|
|
4658
|
-
return formula.trim().replace(/^=/, "").trim();
|
|
4659
|
-
}
|
|
4660
|
-
function isDraftTableFormula(formula) {
|
|
4661
|
-
const normalized = normalizeTableFormula(formula);
|
|
4662
|
-
if (!normalized) return true;
|
|
4663
|
-
let depth = 0;
|
|
4664
|
-
for (const char of normalized) {
|
|
4665
|
-
if (char === "(") depth += 1;
|
|
4666
|
-
if (char === ")") depth -= 1;
|
|
4667
|
-
if (depth < 0) return false;
|
|
4668
|
-
}
|
|
4669
|
-
if (depth > 0) return true;
|
|
4670
|
-
if (/^[A-Z]+\(\s*\)$/i.test(normalized)) return true;
|
|
4671
|
-
if (/[+\-*/,(]\s*$/.test(normalized)) return true;
|
|
4672
|
-
return false;
|
|
4673
|
-
}
|
|
4674
|
-
function formatFormulaError(error) {
|
|
4675
|
-
return `#${error.toUpperCase()}`;
|
|
4676
|
-
}
|
|
4677
|
-
function normalizeTableNumberFormat(format) {
|
|
4678
|
-
return format === "text" || format === "number" || format === "currency" || format === "percent" || format === "date" ? format : "text";
|
|
4679
|
-
}
|
|
4680
|
-
function formatTableFormulaDisplayValue(value, numberFormat) {
|
|
4681
|
-
const stringValue = String(value);
|
|
4682
|
-
if (stringValue.startsWith("#")) {
|
|
4683
|
-
return stringValue;
|
|
4684
|
-
}
|
|
4685
|
-
const normalizedFormat = normalizeTableNumberFormat(numberFormat);
|
|
4686
|
-
if (normalizedFormat === "text") {
|
|
4687
|
-
return stringValue;
|
|
4688
|
-
}
|
|
4689
|
-
const numericValue = typeof value === "number" ? value : Number.parseFloat(stringValue.replace(/,/g, ""));
|
|
4690
|
-
if (!Number.isFinite(numericValue)) {
|
|
4691
|
-
return stringValue;
|
|
4692
|
-
}
|
|
4693
|
-
if (normalizedFormat === "number") {
|
|
4694
|
-
return new Intl.NumberFormat("en-US", { maximumFractionDigits: 6 }).format(numericValue);
|
|
4695
|
-
}
|
|
4696
|
-
if (normalizedFormat === "currency") {
|
|
4697
|
-
return new Intl.NumberFormat("en-US", {
|
|
4698
|
-
style: "currency",
|
|
4699
|
-
currency: "USD",
|
|
4700
|
-
maximumFractionDigits: 2
|
|
4701
|
-
}).format(numericValue);
|
|
4702
|
-
}
|
|
4703
|
-
if (normalizedFormat === "percent") {
|
|
4704
|
-
return new Intl.NumberFormat("en-US", {
|
|
4705
|
-
style: "percent",
|
|
4706
|
-
maximumFractionDigits: 2
|
|
4707
|
-
}).format(numericValue);
|
|
4708
|
-
}
|
|
4709
|
-
const excelEpochMs = Date.UTC(1899, 11, 30);
|
|
4710
|
-
const date = new Date(excelEpochMs + numericValue * 24 * 60 * 60 * 1e3);
|
|
4711
|
-
if (Number.isNaN(date.getTime())) {
|
|
4712
|
-
return stringValue;
|
|
4713
|
-
}
|
|
4714
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
4715
|
-
year: "numeric",
|
|
4716
|
-
month: "2-digit",
|
|
4717
|
-
day: "2-digit",
|
|
4718
|
-
timeZone: "UTC"
|
|
4719
|
-
}).format(date);
|
|
4720
|
-
}
|
|
4721
|
-
function getTableFormulaReferences(formula) {
|
|
4722
|
-
const normalized = normalizeTableFormula(formula);
|
|
4723
|
-
if (!normalized) return [];
|
|
4724
|
-
const tokens = tokenizeFormula(normalized);
|
|
4725
|
-
if (!tokens) return [];
|
|
4726
|
-
const references = /* @__PURE__ */ new Set();
|
|
4727
|
-
for (const token of tokens) {
|
|
4728
|
-
if (token.type === "cell") {
|
|
4729
|
-
references.add(token.value);
|
|
4730
|
-
} else if (token.type === "range") {
|
|
4731
|
-
const range = parseTableCellRange(token.value);
|
|
4732
|
-
if (!range) continue;
|
|
4733
|
-
for (const label of getTableCellRangeLabels(range)) {
|
|
4734
|
-
references.add(label);
|
|
4735
|
-
}
|
|
4736
|
-
}
|
|
4737
|
-
}
|
|
4738
|
-
return Array.from(references);
|
|
4739
|
-
}
|
|
4740
|
-
function buildTableFormulaDependencyGraph(cells) {
|
|
4741
|
-
const dependencies = /* @__PURE__ */ new Map();
|
|
4742
|
-
const dependents = /* @__PURE__ */ new Map();
|
|
4743
|
-
const formulas = /* @__PURE__ */ new Map();
|
|
4744
|
-
for (const cell of cells) {
|
|
4745
|
-
const label = cell.label.toUpperCase();
|
|
4746
|
-
formulas.set(label, cell.formula);
|
|
4747
|
-
dependencies.set(label, new Set(getTableFormulaReferences(cell.formula)));
|
|
4748
|
-
if (!dependents.has(label)) {
|
|
4749
|
-
dependents.set(label, /* @__PURE__ */ new Set());
|
|
4750
|
-
}
|
|
4751
|
-
}
|
|
4752
|
-
for (const [label, refs] of dependencies) {
|
|
4753
|
-
for (const ref of refs) {
|
|
4754
|
-
if (!dependents.has(ref)) {
|
|
4755
|
-
dependents.set(ref, /* @__PURE__ */ new Set());
|
|
4756
|
-
}
|
|
4757
|
-
dependents.get(ref)?.add(label);
|
|
4758
|
-
}
|
|
4759
|
-
}
|
|
4760
|
-
return { dependencies, dependents, formulas };
|
|
4761
|
-
}
|
|
4762
|
-
function getTableFormulaCircularReferences(graph) {
|
|
4763
|
-
const circular = /* @__PURE__ */ new Set();
|
|
4764
|
-
const visited = /* @__PURE__ */ new Set();
|
|
4765
|
-
const finishOrder = [];
|
|
4766
|
-
for (const startLabel of graph.formulas.keys()) {
|
|
4767
|
-
if (visited.has(startLabel)) continue;
|
|
4768
|
-
visited.add(startLabel);
|
|
4769
|
-
const stack = [
|
|
4770
|
-
{
|
|
4771
|
-
label: startLabel,
|
|
4772
|
-
references: Array.from(graph.dependencies.get(startLabel) ?? []).filter((ref) => graph.formulas.has(ref)),
|
|
4773
|
-
nextIndex: 0
|
|
4774
|
-
}
|
|
4775
|
-
];
|
|
4776
|
-
while (stack.length > 0) {
|
|
4777
|
-
const frame = stack[stack.length - 1];
|
|
4778
|
-
if (!frame) break;
|
|
4779
|
-
const reference = frame.references[frame.nextIndex];
|
|
4780
|
-
if (reference) {
|
|
4781
|
-
frame.nextIndex += 1;
|
|
4782
|
-
if (!visited.has(reference)) {
|
|
4783
|
-
visited.add(reference);
|
|
4784
|
-
stack.push({
|
|
4785
|
-
label: reference,
|
|
4786
|
-
references: Array.from(graph.dependencies.get(reference) ?? []).filter((ref) => graph.formulas.has(ref)),
|
|
4787
|
-
nextIndex: 0
|
|
4788
|
-
});
|
|
4789
|
-
}
|
|
4790
|
-
continue;
|
|
4791
|
-
}
|
|
4792
|
-
stack.pop();
|
|
4793
|
-
finishOrder.push(frame.label);
|
|
4794
|
-
}
|
|
4795
|
-
}
|
|
4796
|
-
const assigned = /* @__PURE__ */ new Set();
|
|
4797
|
-
for (let index = finishOrder.length - 1; index >= 0; index -= 1) {
|
|
4798
|
-
const startLabel = finishOrder[index];
|
|
4799
|
-
if (!startLabel || assigned.has(startLabel)) continue;
|
|
4800
|
-
const component = [];
|
|
4801
|
-
const stack = [startLabel];
|
|
4802
|
-
assigned.add(startLabel);
|
|
4803
|
-
while (stack.length > 0) {
|
|
4804
|
-
const label = stack.pop();
|
|
4805
|
-
if (!label) continue;
|
|
4806
|
-
component.push(label);
|
|
4807
|
-
for (const dependent of graph.dependents.get(label) ?? []) {
|
|
4808
|
-
if (!graph.formulas.has(dependent) || assigned.has(dependent)) continue;
|
|
4809
|
-
assigned.add(dependent);
|
|
4810
|
-
stack.push(dependent);
|
|
4811
|
-
}
|
|
4812
|
-
}
|
|
4813
|
-
if (component.length > 1) {
|
|
4814
|
-
for (const label of component) circular.add(label);
|
|
4815
|
-
} else {
|
|
4816
|
-
const label = component[0];
|
|
4817
|
-
if (label && graph.dependencies.get(label)?.has(label)) circular.add(label);
|
|
4818
|
-
}
|
|
4819
|
-
}
|
|
4820
|
-
return circular;
|
|
4821
|
-
}
|
|
4822
|
-
function getTableFormulaRecalculationOrder(graph) {
|
|
4823
|
-
const circular = getTableFormulaCircularReferences(graph);
|
|
4824
|
-
const visiting = /* @__PURE__ */ new Set();
|
|
4825
|
-
const visited = /* @__PURE__ */ new Set();
|
|
4826
|
-
const order = [];
|
|
4827
|
-
for (const startLabel of graph.formulas.keys()) {
|
|
4828
|
-
if (visited.has(startLabel) || circular.has(startLabel)) continue;
|
|
4829
|
-
const stack = [];
|
|
4830
|
-
const push = (label) => {
|
|
4831
|
-
visiting.add(label);
|
|
4832
|
-
stack.push({
|
|
4833
|
-
label,
|
|
4834
|
-
references: Array.from(graph.dependencies.get(label) ?? []).filter((ref) => graph.formulas.has(ref) && !circular.has(ref)),
|
|
4835
|
-
nextIndex: 0
|
|
4836
|
-
});
|
|
4837
|
-
};
|
|
4838
|
-
push(startLabel);
|
|
4839
|
-
while (stack.length > 0) {
|
|
4840
|
-
const frame = stack[stack.length - 1];
|
|
4841
|
-
if (!frame) break;
|
|
4842
|
-
const reference = frame.references[frame.nextIndex];
|
|
4843
|
-
if (reference) {
|
|
4844
|
-
frame.nextIndex += 1;
|
|
4845
|
-
if (!visited.has(reference) && !visiting.has(reference)) {
|
|
4846
|
-
push(reference);
|
|
4847
|
-
}
|
|
4848
|
-
continue;
|
|
4849
|
-
}
|
|
4850
|
-
stack.pop();
|
|
4851
|
-
visiting.delete(frame.label);
|
|
4852
|
-
visited.add(frame.label);
|
|
4853
|
-
order.push(frame.label);
|
|
4854
|
-
}
|
|
4855
|
-
}
|
|
4856
|
-
return { order, circular };
|
|
4857
|
-
}
|
|
4858
|
-
function getAffectedTableFormulaLabels(graph, changedLabels) {
|
|
4859
|
-
const affected = /* @__PURE__ */ new Set();
|
|
4860
|
-
const queue = Array.from(changedLabels, (label) => label.toUpperCase());
|
|
4861
|
-
for (const label of queue) {
|
|
4862
|
-
if (graph.formulas.has(label)) {
|
|
4863
|
-
affected.add(label);
|
|
4864
|
-
}
|
|
4865
|
-
}
|
|
4866
|
-
for (let index = 0; index < queue.length; index += 1) {
|
|
4867
|
-
const label = queue[index];
|
|
4868
|
-
if (!label) continue;
|
|
4869
|
-
for (const dependent of graph.dependents.get(label) ?? []) {
|
|
4870
|
-
if (affected.has(dependent)) continue;
|
|
4871
|
-
affected.add(dependent);
|
|
4872
|
-
queue.push(dependent);
|
|
4873
|
-
}
|
|
4874
|
-
}
|
|
4875
|
-
return affected;
|
|
4876
|
-
}
|
|
4877
|
-
function evaluateBasicTableFormula(formula, getCellValue) {
|
|
4878
|
-
const normalized = normalizeTableFormula(formula);
|
|
4879
|
-
if (!normalized) {
|
|
4880
|
-
return { value: null, error: "empty" };
|
|
4881
|
-
}
|
|
4882
|
-
const tokens = tokenizeFormula(normalized);
|
|
4883
|
-
if (!tokens) {
|
|
4884
|
-
return { value: null, error: "invalid-formula" };
|
|
4885
|
-
}
|
|
4886
|
-
const parser = new FormulaParser(tokens, getCellValue);
|
|
4887
|
-
const result = parser.parseExpression();
|
|
4888
|
-
if (result.error) {
|
|
4889
|
-
return result;
|
|
4890
|
-
}
|
|
4891
|
-
if (!parser.isComplete()) {
|
|
4892
|
-
return { value: null, error: "invalid-formula" };
|
|
4893
|
-
}
|
|
4894
|
-
return result;
|
|
4895
|
-
}
|
|
4896
|
-
function tokenizeFormula(formula) {
|
|
4897
|
-
const tokens = [];
|
|
4898
|
-
let index = 0;
|
|
4899
|
-
while (index < formula.length) {
|
|
4900
|
-
const char = formula[index];
|
|
4901
|
-
if (!char) break;
|
|
4902
|
-
if (/\s/.test(char)) {
|
|
4903
|
-
index += 1;
|
|
4904
|
-
continue;
|
|
4905
|
-
}
|
|
4906
|
-
if (char === "," || char === "+" || char === "-" || char === "*" || char === "/" || char === "(" || char === ")") {
|
|
4907
|
-
if (char === ",") tokens.push({ type: "comma", value: char });
|
|
4908
|
-
else if (char === "(" || char === ")") tokens.push({ type: "paren", value: char });
|
|
4909
|
-
else tokens.push({ type: "operator", value: char });
|
|
4910
|
-
index += 1;
|
|
4911
|
-
continue;
|
|
4912
|
-
}
|
|
4913
|
-
const numberMatch = formula.slice(index).match(/^(?:\d+(?:\.\d*)?|\.\d+)/);
|
|
4914
|
-
if (numberMatch?.[0]) {
|
|
4915
|
-
const value = Number.parseFloat(numberMatch[0]);
|
|
4916
|
-
if (!Number.isFinite(value)) return null;
|
|
4917
|
-
tokens.push({ type: "number", value });
|
|
4918
|
-
index += numberMatch[0].length;
|
|
4919
|
-
continue;
|
|
4920
|
-
}
|
|
4921
|
-
const identifierMatch = formula.slice(index).match(/^[A-Z]+[1-9]\d*(?::[A-Z]+[1-9]\d*)?|^[A-Z]+/i);
|
|
4922
|
-
if (identifierMatch?.[0]) {
|
|
4923
|
-
const value = identifierMatch[0].toUpperCase();
|
|
4924
|
-
if (CELL_RANGE_RE.test(value)) tokens.push({ type: "range", value });
|
|
4925
|
-
else if (parseTableCellAddress(value)) tokens.push({ type: "cell", value });
|
|
4926
|
-
else if (SUPPORTED_FUNCTIONS.has(value)) tokens.push({ type: "function", value });
|
|
4927
|
-
else return null;
|
|
4928
|
-
index += identifierMatch[0].length;
|
|
4929
|
-
continue;
|
|
4930
|
-
}
|
|
4931
|
-
return null;
|
|
4932
|
-
}
|
|
4933
|
-
return tokens;
|
|
4934
|
-
}
|
|
4935
|
-
function toFiniteFormulaResult(value) {
|
|
4936
|
-
return Number.isFinite(value) ? { value, error: null } : { value: null, error: "invalid-formula" };
|
|
4937
|
-
}
|
|
4938
|
-
function parseTableCellNumericValue(value) {
|
|
4939
|
-
if (typeof value === "number") {
|
|
4940
|
-
return Number.isFinite(value) ? value : null;
|
|
4941
|
-
}
|
|
4942
|
-
let normalized = String(value ?? "").trim();
|
|
4943
|
-
if (!normalized || normalized.startsWith("#")) return null;
|
|
4944
|
-
const isPercent = normalized.endsWith("%");
|
|
4945
|
-
if (isPercent) normalized = normalized.slice(0, -1).trim();
|
|
4946
|
-
const currencyMatch = normalized.match(/^([+-]?)\$(.+)$/);
|
|
4947
|
-
if (currencyMatch) {
|
|
4948
|
-
normalized = `${currencyMatch[1] ?? ""}${currencyMatch[2] ?? ""}`.trim();
|
|
4949
|
-
}
|
|
4950
|
-
const groupedNumber = /^[+-]?\d{1,3}(?:,\d{3})+(?:\.\d*)?(?:[eE][+-]?\d+)?$/;
|
|
4951
|
-
const plainNumber = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/;
|
|
4952
|
-
if (!groupedNumber.test(normalized) && !plainNumber.test(normalized)) return null;
|
|
4953
|
-
const parsed = Number(normalized.replace(/,/g, ""));
|
|
4954
|
-
if (!Number.isFinite(parsed)) return null;
|
|
4955
|
-
return isPercent ? parsed / 100 : parsed;
|
|
4956
|
-
}
|
|
4957
|
-
var FormulaParser = class {
|
|
4958
|
-
constructor(tokens, getCellValue) {
|
|
4959
|
-
this.tokens = tokens;
|
|
4960
|
-
this.getCellValue = getCellValue;
|
|
4961
|
-
this.index = 0;
|
|
4962
|
-
}
|
|
4963
|
-
isComplete() {
|
|
4964
|
-
return this.index >= this.tokens.length;
|
|
4965
|
-
}
|
|
4966
|
-
parseExpression() {
|
|
4967
|
-
let left = this.parseTerm();
|
|
4968
|
-
while (!left.error) {
|
|
4969
|
-
const operator = this.peekOperator(["+", "-"]);
|
|
4970
|
-
if (!operator) break;
|
|
4971
|
-
this.index += 1;
|
|
4972
|
-
const right = this.parseTerm();
|
|
4973
|
-
if (right.error) return right;
|
|
4974
|
-
left = toFiniteFormulaResult(operator.value === "+" ? left.value + right.value : left.value - right.value);
|
|
4975
|
-
}
|
|
4976
|
-
return left;
|
|
4977
|
-
}
|
|
4978
|
-
parseTerm() {
|
|
4979
|
-
let left = this.parseFactor();
|
|
4980
|
-
while (!left.error) {
|
|
4981
|
-
const operator = this.peekOperator(["*", "/"]);
|
|
4982
|
-
if (!operator) break;
|
|
4983
|
-
this.index += 1;
|
|
4984
|
-
const right = this.parseFactor();
|
|
4985
|
-
if (right.error) return right;
|
|
4986
|
-
if (operator.value === "/" && right.value === 0) {
|
|
4987
|
-
return { value: null, error: "division-by-zero" };
|
|
4988
|
-
}
|
|
4989
|
-
left = toFiniteFormulaResult(operator.value === "*" ? left.value * right.value : left.value / right.value);
|
|
4990
|
-
}
|
|
4991
|
-
return left;
|
|
4992
|
-
}
|
|
4993
|
-
parseFactor() {
|
|
4994
|
-
const token = this.tokens[this.index];
|
|
4995
|
-
if (!token) {
|
|
4996
|
-
return { value: null, error: "invalid-formula" };
|
|
4997
|
-
}
|
|
4998
|
-
if (token.type === "operator" && (token.value === "-" || token.value === "+")) {
|
|
4999
|
-
this.index += 1;
|
|
5000
|
-
const value = this.parseFactor();
|
|
5001
|
-
if (value.error) return value;
|
|
5002
|
-
return toFiniteFormulaResult(token.value === "-" ? -value.value : value.value);
|
|
5003
|
-
}
|
|
5004
|
-
if (token.type === "number") {
|
|
5005
|
-
this.index += 1;
|
|
5006
|
-
return { value: token.value, error: null };
|
|
5007
|
-
}
|
|
5008
|
-
if (token.type === "cell") {
|
|
5009
|
-
this.index += 1;
|
|
5010
|
-
return this.readCellNumber(token.value);
|
|
5011
|
-
}
|
|
5012
|
-
if (token.type === "function") {
|
|
5013
|
-
return this.parseFunction(token.value);
|
|
5014
|
-
}
|
|
5015
|
-
if (token.type === "paren" && token.value === "(") {
|
|
5016
|
-
this.index += 1;
|
|
5017
|
-
const value = this.parseExpression();
|
|
5018
|
-
if (value.error) return value;
|
|
5019
|
-
if (!this.consumeParen(")")) {
|
|
5020
|
-
return { value: null, error: "invalid-formula" };
|
|
5021
|
-
}
|
|
5022
|
-
return value;
|
|
5023
|
-
}
|
|
5024
|
-
return { value: null, error: "invalid-formula" };
|
|
5025
|
-
}
|
|
5026
|
-
parseFunction(name) {
|
|
5027
|
-
this.index += 1;
|
|
5028
|
-
if (!this.consumeParen("(")) {
|
|
5029
|
-
return { value: null, error: "invalid-formula" };
|
|
5030
|
-
}
|
|
5031
|
-
const values = [];
|
|
5032
|
-
while (true) {
|
|
5033
|
-
const token = this.tokens[this.index];
|
|
5034
|
-
if (!token) {
|
|
5035
|
-
return { value: null, error: "invalid-formula" };
|
|
5036
|
-
}
|
|
5037
|
-
if (token.type === "range") {
|
|
5038
|
-
this.index += 1;
|
|
5039
|
-
const range = parseTableCellRange(token.value);
|
|
5040
|
-
if (!range) return { value: null, error: "invalid-reference" };
|
|
5041
|
-
for (const label of getTableCellRangeLabels(range)) {
|
|
5042
|
-
if (name === "COUNT") {
|
|
5043
|
-
const cellValue2 = this.readOptionalCellNumber(label);
|
|
5044
|
-
if (cellValue2 != null) values.push(cellValue2);
|
|
5045
|
-
continue;
|
|
5046
|
-
}
|
|
5047
|
-
const cellValue = this.readOptionalCellNumber(label);
|
|
5048
|
-
if (cellValue != null) values.push(cellValue);
|
|
5049
|
-
}
|
|
5050
|
-
} else if (token.type === "cell") {
|
|
5051
|
-
this.index += 1;
|
|
5052
|
-
const cellValue = this.readOptionalCellNumber(token.value);
|
|
5053
|
-
if (cellValue != null) values.push(cellValue);
|
|
5054
|
-
} else {
|
|
5055
|
-
const value = this.parseExpression();
|
|
5056
|
-
if (value.error) return value;
|
|
5057
|
-
values.push(value.value);
|
|
5058
|
-
}
|
|
5059
|
-
if (this.consumeComma()) {
|
|
5060
|
-
continue;
|
|
5061
|
-
}
|
|
5062
|
-
if (this.consumeParen(")")) {
|
|
5063
|
-
break;
|
|
5064
|
-
}
|
|
5065
|
-
return { value: null, error: "invalid-formula" };
|
|
5066
|
-
}
|
|
5067
|
-
if (name === "SUM") return toFiniteFormulaResult(values.reduce((sum, value) => sum + value, 0));
|
|
5068
|
-
if (name === "AVG") {
|
|
5069
|
-
return values.length > 0 ? toFiniteFormulaResult(values.reduce((sum, value) => sum + value, 0) / values.length) : { value: null, error: "division-by-zero" };
|
|
5070
|
-
}
|
|
5071
|
-
if (name === "MIN") return toFiniteFormulaResult(values.length > 0 ? Math.min(...values) : 0);
|
|
5072
|
-
if (name === "MAX") return toFiniteFormulaResult(values.length > 0 ? Math.max(...values) : 0);
|
|
5073
|
-
if (name === "COUNT") return { value: values.length, error: null };
|
|
5074
|
-
return { value: null, error: "invalid-formula" };
|
|
5075
|
-
}
|
|
5076
|
-
readCellNumber(label) {
|
|
5077
|
-
const parsed = parseTableCellNumericValue(this.getCellValue(label));
|
|
5078
|
-
if (parsed == null) {
|
|
5079
|
-
return { value: null, error: "invalid-reference" };
|
|
5080
|
-
}
|
|
5081
|
-
return { value: parsed, error: null };
|
|
5082
|
-
}
|
|
5083
|
-
readOptionalCellNumber(label) {
|
|
5084
|
-
return parseTableCellNumericValue(this.getCellValue(label));
|
|
5085
|
-
}
|
|
5086
|
-
peekOperator(operators) {
|
|
5087
|
-
const token = this.tokens[this.index];
|
|
5088
|
-
return token?.type === "operator" && operators.includes(token.value) ? token : null;
|
|
5089
|
-
}
|
|
5090
|
-
consumeComma() {
|
|
5091
|
-
if (this.tokens[this.index]?.type !== "comma") {
|
|
5092
|
-
return false;
|
|
5093
|
-
}
|
|
5094
|
-
this.index += 1;
|
|
5095
|
-
return true;
|
|
5096
|
-
}
|
|
5097
|
-
consumeParen(value) {
|
|
5098
|
-
const token = this.tokens[this.index];
|
|
5099
|
-
if (token?.type !== "paren" || token.value !== value) {
|
|
5100
|
-
return false;
|
|
5101
|
-
}
|
|
5102
|
-
this.index += 1;
|
|
5103
|
-
return true;
|
|
5104
|
-
}
|
|
5105
|
-
};
|
|
5106
|
-
|
|
5107
|
-
// src/components/UEditor/table-formula-commands.ts
|
|
5108
4749
|
var UEDITOR_TABLE_FORMULA_RECALCULATE_META = "ueditorTableFormulaRecalculate";
|
|
5109
4750
|
var TABLE_FORMULA_PLAN_CACHE_LIMIT = 50;
|
|
5110
4751
|
var tableFormulaPlanCache = /* @__PURE__ */ new Map();
|
|
@@ -5984,6 +5625,7 @@ function buildUEditorExtensions({
|
|
|
5984
5625
|
maxImageFileSize,
|
|
5985
5626
|
allowedImageMimeTypes,
|
|
5986
5627
|
fallbackToDataUrl,
|
|
5628
|
+
onImageUploadError,
|
|
5987
5629
|
editable = true,
|
|
5988
5630
|
fetchMetadata
|
|
5989
5631
|
}) {
|
|
@@ -6051,7 +5693,8 @@ function buildUEditorExtensions({
|
|
|
6051
5693
|
insertMode: imageInsertMode,
|
|
6052
5694
|
...maxImageFileSize !== void 0 ? { maxFileSize: maxImageFileSize } : {},
|
|
6053
5695
|
...allowedImageMimeTypes ? { allowedMimeTypes: allowedImageMimeTypes } : {},
|
|
6054
|
-
...fallbackToDataUrl !== void 0 ? { fallbackToDataUrl } : {}
|
|
5696
|
+
...fallbackToDataUrl !== void 0 ? { fallbackToDataUrl } : {},
|
|
5697
|
+
onError: onImageUploadError
|
|
6055
5698
|
}),
|
|
6056
5699
|
TextStyle,
|
|
6057
5700
|
font_family_default,
|
|
@@ -7494,6 +7137,8 @@ var CustomBubbleMenu = ({
|
|
|
7494
7137
|
editor.on("transaction", schedulePositionUpdate);
|
|
7495
7138
|
editor.on("focus", schedulePositionUpdate);
|
|
7496
7139
|
editor.on("blur", handleBlur);
|
|
7140
|
+
editorWindow?.addEventListener("resize", schedulePositionUpdate);
|
|
7141
|
+
editorWindow?.addEventListener("scroll", schedulePositionUpdate, true);
|
|
7497
7142
|
updatePositionRef.current = updatePosition;
|
|
7498
7143
|
schedulePositionUpdate();
|
|
7499
7144
|
return () => {
|
|
@@ -7504,6 +7149,8 @@ var CustomBubbleMenu = ({
|
|
|
7504
7149
|
editor.off("transaction", schedulePositionUpdate);
|
|
7505
7150
|
editor.off("focus", schedulePositionUpdate);
|
|
7506
7151
|
editor.off("blur", handleBlur);
|
|
7152
|
+
editorWindow?.removeEventListener("resize", schedulePositionUpdate);
|
|
7153
|
+
editorWindow?.removeEventListener("scroll", schedulePositionUpdate, true);
|
|
7507
7154
|
};
|
|
7508
7155
|
}, [editor, editorDocument, editorWindow]);
|
|
7509
7156
|
useEffect5(() => {
|
|
@@ -7637,12 +7284,16 @@ var CustomFloatingMenu = ({ editor }) => {
|
|
|
7637
7284
|
editor.on("transaction", schedulePositionUpdate);
|
|
7638
7285
|
editor.on("focus", schedulePositionUpdate);
|
|
7639
7286
|
editor.on("blur", handleBlur);
|
|
7287
|
+
editorWindow?.addEventListener("resize", schedulePositionUpdate);
|
|
7288
|
+
editorWindow?.addEventListener("scroll", schedulePositionUpdate, true);
|
|
7640
7289
|
schedulePositionUpdate();
|
|
7641
7290
|
return () => {
|
|
7642
7291
|
if (animationFrameId !== null) editorWindow?.cancelAnimationFrame(animationFrameId);
|
|
7643
7292
|
editor.off("transaction", schedulePositionUpdate);
|
|
7644
7293
|
editor.off("focus", schedulePositionUpdate);
|
|
7645
7294
|
editor.off("blur", handleBlur);
|
|
7295
|
+
editorWindow?.removeEventListener("resize", schedulePositionUpdate);
|
|
7296
|
+
editorWindow?.removeEventListener("scroll", schedulePositionUpdate, true);
|
|
7646
7297
|
};
|
|
7647
7298
|
}, [editor, editorWindow]);
|
|
7648
7299
|
if (!isVisible || !portalContainer) return null;
|
|
@@ -7701,7 +7352,7 @@ var CharacterCountDisplay = ({ editor, maxCharacters }) => {
|
|
|
7701
7352
|
};
|
|
7702
7353
|
|
|
7703
7354
|
// src/components/UEditor/table-controls.tsx
|
|
7704
|
-
import
|
|
7355
|
+
import React11 from "react";
|
|
7705
7356
|
|
|
7706
7357
|
// node_modules/prosemirror-model/dist/index.js
|
|
7707
7358
|
function findDiffStart(a, b, pos) {
|
|
@@ -12357,6 +12008,8 @@ function TableAddRails({
|
|
|
12357
12008
|
layout,
|
|
12358
12009
|
onStartAddColumn,
|
|
12359
12010
|
onStartAddRow,
|
|
12011
|
+
onAddColumn,
|
|
12012
|
+
onAddRow,
|
|
12360
12013
|
quickAddColumnLabel,
|
|
12361
12014
|
quickAddRowLabel
|
|
12362
12015
|
}) {
|
|
@@ -12379,17 +12032,16 @@ function TableAddRails({
|
|
|
12379
12032
|
type: "button",
|
|
12380
12033
|
"data-table-control": "add-column",
|
|
12381
12034
|
"aria-label": quickAddColumnLabel,
|
|
12382
|
-
|
|
12383
|
-
|
|
12384
|
-
|
|
12385
|
-
if (
|
|
12386
|
-
onStartAddColumn();
|
|
12035
|
+
tabIndex: showColumnRail ? 0 : -1,
|
|
12036
|
+
onPointerDown: onStartAddColumn,
|
|
12037
|
+
onClick: (event) => {
|
|
12038
|
+
if (event.detail === 0 && canExpandTable) onAddColumn();
|
|
12387
12039
|
},
|
|
12388
12040
|
disabled: !canExpandTable,
|
|
12389
12041
|
className: cn(
|
|
12390
12042
|
"absolute z-30 inline-flex items-center justify-center rounded-md",
|
|
12391
12043
|
"border border-border/70 bg-muted/40 text-muted-foreground shadow-sm backdrop-blur",
|
|
12392
|
-
"transition-[opacity,transform,
|
|
12044
|
+
"transition-[opacity,transform,color,border-color,background-color] duration-200 delay-100 ease-out motion-reduce:transition-none cursor-pointer hover:bg-accent hover:text-foreground disabled:opacity-50 disabled:cursor-not-allowed"
|
|
12393
12045
|
),
|
|
12394
12046
|
style: {
|
|
12395
12047
|
top: columnRailTop,
|
|
@@ -12416,17 +12068,16 @@ function TableAddRails({
|
|
|
12416
12068
|
type: "button",
|
|
12417
12069
|
"data-table-control": "add-row",
|
|
12418
12070
|
"aria-label": quickAddRowLabel,
|
|
12419
|
-
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
if (
|
|
12423
|
-
onStartAddRow();
|
|
12071
|
+
tabIndex: showRowRail ? 0 : -1,
|
|
12072
|
+
onPointerDown: onStartAddRow,
|
|
12073
|
+
onClick: (event) => {
|
|
12074
|
+
if (event.detail === 0 && canExpandTable) onAddRow();
|
|
12424
12075
|
},
|
|
12425
12076
|
disabled: !canExpandTable,
|
|
12426
12077
|
className: cn(
|
|
12427
12078
|
"absolute z-30 inline-flex items-center justify-center rounded-md",
|
|
12428
12079
|
"border border-border/70 bg-muted/40 text-muted-foreground shadow-sm backdrop-blur",
|
|
12429
|
-
"transition-[opacity,transform,
|
|
12080
|
+
"transition-[opacity,transform,color,border-color,background-color] duration-200 delay-100 ease-out motion-reduce:transition-none cursor-pointer hover:bg-accent hover:text-foreground disabled:opacity-50 disabled:cursor-not-allowed"
|
|
12430
12081
|
),
|
|
12431
12082
|
style: {
|
|
12432
12083
|
top: rowRailTop,
|
|
@@ -12519,6 +12170,7 @@ function TableRowHandles({
|
|
|
12519
12170
|
getMenuItems,
|
|
12520
12171
|
hoverRowHandleIndex,
|
|
12521
12172
|
onOpenMenuChange,
|
|
12173
|
+
onMove,
|
|
12522
12174
|
onStartDrag,
|
|
12523
12175
|
openMenuKey,
|
|
12524
12176
|
rowDragLabel,
|
|
@@ -12559,13 +12211,16 @@ function TableRowHandles({
|
|
|
12559
12211
|
{
|
|
12560
12212
|
type: "button",
|
|
12561
12213
|
"aria-label": `${rowDragLabel} ${rowHandle.index + 1}`,
|
|
12562
|
-
|
|
12214
|
+
tabIndex: visible ? 0 : -1,
|
|
12215
|
+
onPointerDown: (event) => onStartDrag(event, rowHandle),
|
|
12216
|
+
onKeyDown: (event) => {
|
|
12217
|
+
if (!event.altKey || event.key !== "ArrowUp" && event.key !== "ArrowDown") return;
|
|
12563
12218
|
event.preventDefault();
|
|
12564
12219
|
event.stopPropagation();
|
|
12565
|
-
|
|
12220
|
+
onMove(rowHandle, event.key === "ArrowUp" ? -1 : 1);
|
|
12566
12221
|
},
|
|
12567
12222
|
className: cn(
|
|
12568
|
-
"inline-flex h-6 w-6 items-center justify-center rounded-full transition-[opacity,transform,
|
|
12223
|
+
"inline-flex h-6 w-6 items-center justify-center rounded-full transition-[opacity,transform,color,border-color,background-color] duration-200 delay-100 ease-out motion-reduce:transition-none",
|
|
12569
12224
|
visible ? "border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur hover:bg-accent hover:text-foreground cursor-grab active:cursor-grabbing" : "border-transparent bg-transparent cursor-pointer"
|
|
12570
12225
|
),
|
|
12571
12226
|
style: {
|
|
@@ -12576,7 +12231,7 @@ function TableRowHandles({
|
|
|
12576
12231
|
// selection near the first character of a table cell.
|
|
12577
12232
|
pointerEvents: visible ? "auto" : "none"
|
|
12578
12233
|
},
|
|
12579
|
-
children: visible ? /* @__PURE__ */ jsx16(GripVertical, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx16("div", { className: "h-3 w-1 rounded-full bg-muted-foreground/50 hover:bg-muted-foreground" })
|
|
12234
|
+
children: visible ? /* @__PURE__ */ jsx16(GripVertical, { "aria-hidden": "true", className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx16("div", { className: "h-3 w-1 rounded-full bg-muted-foreground/50 hover:bg-muted-foreground" })
|
|
12580
12235
|
}
|
|
12581
12236
|
)
|
|
12582
12237
|
}
|
|
@@ -12597,6 +12252,7 @@ function TableColumnHandles({
|
|
|
12597
12252
|
getMenuItems,
|
|
12598
12253
|
hoverColumnHandleIndex,
|
|
12599
12254
|
onOpenMenuChange,
|
|
12255
|
+
onMove,
|
|
12600
12256
|
onStartDrag,
|
|
12601
12257
|
openMenuKey
|
|
12602
12258
|
}) {
|
|
@@ -12634,13 +12290,16 @@ function TableColumnHandles({
|
|
|
12634
12290
|
{
|
|
12635
12291
|
type: "button",
|
|
12636
12292
|
"aria-label": `${columnDragLabel} ${columnHandle.index + 1}`,
|
|
12637
|
-
|
|
12293
|
+
tabIndex: visible ? 0 : -1,
|
|
12294
|
+
onPointerDown: (event) => onStartDrag(event, columnHandle),
|
|
12295
|
+
onKeyDown: (event) => {
|
|
12296
|
+
if (!event.altKey || event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
12638
12297
|
event.preventDefault();
|
|
12639
12298
|
event.stopPropagation();
|
|
12640
|
-
|
|
12299
|
+
onMove(columnHandle, event.key === "ArrowLeft" ? -1 : 1);
|
|
12641
12300
|
},
|
|
12642
12301
|
className: cn(
|
|
12643
|
-
"inline-flex h-6 w-6 items-center justify-center rounded-full transition-[opacity,transform,
|
|
12302
|
+
"inline-flex h-6 w-6 items-center justify-center rounded-full transition-[opacity,transform,color,border-color,background-color] duration-200 delay-100 ease-out motion-reduce:transition-none",
|
|
12644
12303
|
visible ? "border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur hover:bg-accent hover:text-foreground cursor-grab active:cursor-grabbing" : "border-transparent bg-transparent cursor-pointer"
|
|
12645
12304
|
),
|
|
12646
12305
|
style: {
|
|
@@ -12648,7 +12307,7 @@ function TableColumnHandles({
|
|
|
12648
12307
|
transform: isShown ? "scale(1)" : `scale(${IDLE_HANDLE_SCALE})`,
|
|
12649
12308
|
pointerEvents: visible ? "auto" : "none"
|
|
12650
12309
|
},
|
|
12651
|
-
children: visible ? /* @__PURE__ */ jsx16(GripHorizontal, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx16("div", { className: "h-1 w-3 rounded-full bg-muted-foreground/50 hover:bg-muted-foreground" })
|
|
12310
|
+
children: visible ? /* @__PURE__ */ jsx16(GripHorizontal, { "aria-hidden": "true", className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx16("div", { className: "h-1 w-3 rounded-full bg-muted-foreground/50 hover:bg-muted-foreground" })
|
|
12652
12311
|
}
|
|
12653
12312
|
)
|
|
12654
12313
|
}
|
|
@@ -12676,12 +12335,25 @@ var EDGE_HANDLE_CLASS = cn(
|
|
|
12676
12335
|
"border-transparent transition-colors duration-150 hover:border-primary",
|
|
12677
12336
|
"focus-visible:border-primary focus-visible:outline-none"
|
|
12678
12337
|
);
|
|
12338
|
+
function formatTableResizeDimensionLabel({
|
|
12339
|
+
width,
|
|
12340
|
+
height,
|
|
12341
|
+
widthBp,
|
|
12342
|
+
widthMode,
|
|
12343
|
+
viewportWidth
|
|
12344
|
+
}) {
|
|
12345
|
+
const widthLabel = widthMode === "responsive" ? formatBasisPointsAsPercentage(
|
|
12346
|
+
widthBp ?? Math.max(1, width) / Math.max(1, viewportWidth) * TABLE_WIDTH_BASIS_POINTS
|
|
12347
|
+
) : `${Math.round(width)}px`;
|
|
12348
|
+
return `${widthLabel} \xD7 ${Math.round(height)}px`;
|
|
12349
|
+
}
|
|
12679
12350
|
function TableResizeHandles({
|
|
12680
12351
|
active,
|
|
12681
12352
|
ctrlHint,
|
|
12682
12353
|
frameRef,
|
|
12683
12354
|
layout,
|
|
12684
12355
|
onFitWidth,
|
|
12356
|
+
onKeyboardResize,
|
|
12685
12357
|
onStartResize,
|
|
12686
12358
|
resizeBothLabel
|
|
12687
12359
|
}) {
|
|
@@ -12714,7 +12386,8 @@ function TableResizeHandles({
|
|
|
12714
12386
|
EDGE_HANDLE_CLASS,
|
|
12715
12387
|
"left-0 border-l-2"
|
|
12716
12388
|
),
|
|
12717
|
-
onPointerDown: (event) => onStartResize(event, "left")
|
|
12389
|
+
onPointerDown: (event) => onStartResize(event, "left"),
|
|
12390
|
+
onKeyDown: (event) => onKeyboardResize(event, "left")
|
|
12718
12391
|
}
|
|
12719
12392
|
),
|
|
12720
12393
|
/* @__PURE__ */ jsx17(
|
|
@@ -12728,7 +12401,8 @@ function TableResizeHandles({
|
|
|
12728
12401
|
EDGE_HANDLE_CLASS,
|
|
12729
12402
|
"right-0 border-r-2"
|
|
12730
12403
|
),
|
|
12731
|
-
onPointerDown: (event) => onStartResize(event, "right")
|
|
12404
|
+
onPointerDown: (event) => onStartResize(event, "right"),
|
|
12405
|
+
onKeyDown: (event) => onKeyboardResize(event, "right")
|
|
12732
12406
|
}
|
|
12733
12407
|
)
|
|
12734
12408
|
] }) : null,
|
|
@@ -12745,7 +12419,11 @@ function TableResizeHandles({
|
|
|
12745
12419
|
active && "bg-primary text-primary-foreground shadow-md"
|
|
12746
12420
|
),
|
|
12747
12421
|
onDoubleClick: onFitWidth,
|
|
12422
|
+
onClick: (event) => {
|
|
12423
|
+
if (event.detail === 0) onFitWidth(event);
|
|
12424
|
+
},
|
|
12748
12425
|
onPointerDown: (event) => onStartResize(event, "both"),
|
|
12426
|
+
onKeyDown: (event) => onKeyboardResize(event, "both"),
|
|
12749
12427
|
children: /* @__PURE__ */ jsx17(MoveDiagonal2, { "aria-hidden": "true", className: "h-3.5 w-3.5", strokeWidth: 2.25 })
|
|
12750
12428
|
}
|
|
12751
12429
|
),
|
|
@@ -12756,7 +12434,12 @@ function TableResizeHandles({
|
|
|
12756
12434
|
"aria-live": "polite",
|
|
12757
12435
|
"data-table-resize-dimensions": "",
|
|
12758
12436
|
className: "absolute bottom-2 right-2 rounded bg-foreground/85 px-1.5 py-0.5 text-[10px] font-medium text-background shadow-sm",
|
|
12759
|
-
children:
|
|
12437
|
+
children: formatTableResizeDimensionLabel({
|
|
12438
|
+
width: layout.tableWidth,
|
|
12439
|
+
height: layout.tableHeight,
|
|
12440
|
+
widthMode: layout.widthMode,
|
|
12441
|
+
viewportWidth: layout.viewportWidth
|
|
12442
|
+
})
|
|
12760
12443
|
}
|
|
12761
12444
|
) : null
|
|
12762
12445
|
]
|
|
@@ -12997,6 +12680,9 @@ function applyTableSize(editor, snapshot, dimensions, options = {}) {
|
|
|
12997
12680
|
import { Fragment as Fragment7, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
12998
12681
|
var TABLE_MENU_TOP_OFFSET = 10;
|
|
12999
12682
|
var AXIS_HANDLE_RADIUS = 12;
|
|
12683
|
+
function clamp2(value, min, max) {
|
|
12684
|
+
return Math.min(Math.max(value, min), max);
|
|
12685
|
+
}
|
|
13000
12686
|
function nearestIndex(centers, position) {
|
|
13001
12687
|
let bestIndex = 0;
|
|
13002
12688
|
let bestDistance = Number.POSITIVE_INFINITY;
|
|
@@ -13027,21 +12713,21 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13027
12713
|
const t = useSmartTranslations("UEditor");
|
|
13028
12714
|
const editorDocument = editor.view.dom.ownerDocument;
|
|
13029
12715
|
const editorWindow = editorDocument.defaultView;
|
|
13030
|
-
const [layout, setLayout] =
|
|
13031
|
-
const [dragPreview, setDragPreview] =
|
|
13032
|
-
const [tableResizeActive, setTableResizeActive] =
|
|
13033
|
-
const [hoverState, setHoverState] =
|
|
13034
|
-
const [openMenuKey, setOpenMenuKey] =
|
|
13035
|
-
const layoutRef =
|
|
13036
|
-
const dragStateRef =
|
|
13037
|
-
const syncFrameRef =
|
|
13038
|
-
const layoutRefreshFrameRef =
|
|
13039
|
-
const tableResizeFrameRef =
|
|
13040
|
-
const tableResizePreviewFrameRef =
|
|
13041
|
-
|
|
12716
|
+
const [layout, setLayout] = React11.useState(null);
|
|
12717
|
+
const [dragPreview, setDragPreview] = React11.useState(null);
|
|
12718
|
+
const [tableResizeActive, setTableResizeActive] = React11.useState(false);
|
|
12719
|
+
const [hoverState, setHoverState] = React11.useState(DEFAULT_TABLE_HOVER_STATE);
|
|
12720
|
+
const [openMenuKey, setOpenMenuKey] = React11.useState(null);
|
|
12721
|
+
const layoutRef = React11.useRef(null);
|
|
12722
|
+
const dragStateRef = React11.useRef(null);
|
|
12723
|
+
const syncFrameRef = React11.useRef(null);
|
|
12724
|
+
const layoutRefreshFrameRef = React11.useRef(null);
|
|
12725
|
+
const tableResizeFrameRef = React11.useRef(null);
|
|
12726
|
+
const tableResizePreviewFrameRef = React11.useRef(null);
|
|
12727
|
+
React11.useEffect(() => {
|
|
13042
12728
|
layoutRef.current = layout;
|
|
13043
12729
|
}, [layout]);
|
|
13044
|
-
const syncFromCell =
|
|
12730
|
+
const syncFromCell = React11.useCallback((cell) => {
|
|
13045
12731
|
const surface = containerRef.current;
|
|
13046
12732
|
if (!surface || !cell) {
|
|
13047
12733
|
layoutRef.current = null;
|
|
@@ -13052,10 +12738,10 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13052
12738
|
layoutRef.current = nextLayout;
|
|
13053
12739
|
setLayout(nextLayout);
|
|
13054
12740
|
}, [containerRef, editor]);
|
|
13055
|
-
const syncFromSelection =
|
|
12741
|
+
const syncFromSelection = React11.useCallback(() => {
|
|
13056
12742
|
syncFromCell(getSelectedCell(editor));
|
|
13057
12743
|
}, [editor, syncFromCell]);
|
|
13058
|
-
const scheduleSyncFromSelection =
|
|
12744
|
+
const scheduleSyncFromSelection = React11.useCallback(() => {
|
|
13059
12745
|
if (syncFrameRef.current !== null) return;
|
|
13060
12746
|
if (!editorWindow) return;
|
|
13061
12747
|
syncFrameRef.current = editorWindow.requestAnimationFrame(() => {
|
|
@@ -13063,13 +12749,13 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13063
12749
|
syncFromSelection();
|
|
13064
12750
|
});
|
|
13065
12751
|
}, [editorWindow, syncFromSelection]);
|
|
13066
|
-
|
|
12752
|
+
React11.useEffect(() => () => {
|
|
13067
12753
|
if (syncFrameRef.current !== null) {
|
|
13068
12754
|
editorWindow?.cancelAnimationFrame(syncFrameRef.current);
|
|
13069
12755
|
syncFrameRef.current = null;
|
|
13070
12756
|
}
|
|
13071
12757
|
}, [editorWindow]);
|
|
13072
|
-
const refreshCurrentLayout =
|
|
12758
|
+
const refreshCurrentLayout = React11.useCallback(() => {
|
|
13073
12759
|
const currentLayout = layoutRef.current;
|
|
13074
12760
|
if (!currentLayout) return;
|
|
13075
12761
|
const surface = containerRef.current;
|
|
@@ -13084,7 +12770,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13084
12770
|
layoutRef.current = nextLayout;
|
|
13085
12771
|
setLayout(nextLayout);
|
|
13086
12772
|
}, [containerRef, editor]);
|
|
13087
|
-
const scheduleCurrentLayoutRefresh =
|
|
12773
|
+
const scheduleCurrentLayoutRefresh = React11.useCallback(() => {
|
|
13088
12774
|
if (!layoutRef.current || layoutRefreshFrameRef.current !== null) return;
|
|
13089
12775
|
if (!editorWindow) return;
|
|
13090
12776
|
layoutRefreshFrameRef.current = editorWindow.requestAnimationFrame(() => {
|
|
@@ -13092,13 +12778,13 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13092
12778
|
refreshCurrentLayout();
|
|
13093
12779
|
});
|
|
13094
12780
|
}, [editorWindow, refreshCurrentLayout]);
|
|
13095
|
-
|
|
12781
|
+
React11.useEffect(() => () => {
|
|
13096
12782
|
if (layoutRefreshFrameRef.current !== null) {
|
|
13097
12783
|
editorWindow?.cancelAnimationFrame(layoutRefreshFrameRef.current);
|
|
13098
12784
|
layoutRefreshFrameRef.current = null;
|
|
13099
12785
|
}
|
|
13100
12786
|
}, [editorWindow]);
|
|
13101
|
-
const updateTableResizePreview =
|
|
12787
|
+
const updateTableResizePreview = React11.useCallback((dimensions) => {
|
|
13102
12788
|
const frame = tableResizeFrameRef.current;
|
|
13103
12789
|
if (!frame) return;
|
|
13104
12790
|
frame.style.width = `${dimensions.width}px`;
|
|
@@ -13108,11 +12794,17 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13108
12794
|
frame.style.left = `${activeLayout.tableLeft + (dimensions.leftDelta ?? 0)}px`;
|
|
13109
12795
|
}
|
|
13110
12796
|
const dimensionsLabel = frame.querySelector("[data-table-resize-dimensions]");
|
|
13111
|
-
if (dimensionsLabel) {
|
|
13112
|
-
dimensionsLabel.textContent =
|
|
12797
|
+
if (dimensionsLabel && activeLayout) {
|
|
12798
|
+
dimensionsLabel.textContent = formatTableResizeDimensionLabel({
|
|
12799
|
+
width: dimensions.width,
|
|
12800
|
+
height: dimensions.height,
|
|
12801
|
+
widthBp: dimensions.widthBp,
|
|
12802
|
+
widthMode: activeLayout.widthMode,
|
|
12803
|
+
viewportWidth: activeLayout.viewportWidth
|
|
12804
|
+
});
|
|
13113
12805
|
}
|
|
13114
12806
|
}, []);
|
|
13115
|
-
const resetTableResizePreview =
|
|
12807
|
+
const resetTableResizePreview = React11.useCallback(() => {
|
|
13116
12808
|
const activeLayout = layoutRef.current;
|
|
13117
12809
|
if (!activeLayout) return;
|
|
13118
12810
|
updateTableResizePreview({
|
|
@@ -13121,7 +12813,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13121
12813
|
leftDelta: 0
|
|
13122
12814
|
});
|
|
13123
12815
|
}, [updateTableResizePreview]);
|
|
13124
|
-
const clearDrag =
|
|
12816
|
+
const clearDrag = React11.useCallback(() => {
|
|
13125
12817
|
const dragState = dragStateRef.current;
|
|
13126
12818
|
if (dragState?.kind === "resize-table") {
|
|
13127
12819
|
try {
|
|
@@ -13141,7 +12833,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13141
12833
|
resetTableResizePreview();
|
|
13142
12834
|
setDocumentCursor(editorDocument, "");
|
|
13143
12835
|
}, [editorDocument, editorWindow, resetTableResizePreview]);
|
|
13144
|
-
const updateHoverState =
|
|
12836
|
+
const updateHoverState = React11.useCallback((event) => {
|
|
13145
12837
|
const activeLayout = layoutRef.current;
|
|
13146
12838
|
const surface = containerRef.current;
|
|
13147
12839
|
if (!activeLayout || !surface || dragStateRef.current || event.buttons !== 0) {
|
|
@@ -13157,7 +12849,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13157
12849
|
return areTableHoverStatesEqual(prev, nextState) ? prev : nextState;
|
|
13158
12850
|
});
|
|
13159
12851
|
}, [containerRef]);
|
|
13160
|
-
|
|
12852
|
+
React11.useEffect(() => {
|
|
13161
12853
|
const proseMirror = editor.view.dom;
|
|
13162
12854
|
const surface = containerRef.current;
|
|
13163
12855
|
if (!surface) return void 0;
|
|
@@ -13244,37 +12936,37 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13244
12936
|
editor.off("update", scheduleCurrentLayoutRefresh);
|
|
13245
12937
|
};
|
|
13246
12938
|
}, [clearDrag, containerRef, editor, editorWindow, scheduleCurrentLayoutRefresh, scheduleSyncFromSelection, syncFromCell, syncFromSelection, updateHoverState]);
|
|
13247
|
-
const runAtCellPos =
|
|
12939
|
+
const runAtCellPos = React11.useCallback((cellPos, command, options) => {
|
|
13248
12940
|
const result = runTableCommandAtCellPos(editor, cellPos, command);
|
|
13249
12941
|
if (options?.sync !== false) {
|
|
13250
12942
|
scheduleSyncFromSelection();
|
|
13251
12943
|
}
|
|
13252
12944
|
return result;
|
|
13253
12945
|
}, [editor, scheduleSyncFromSelection]);
|
|
13254
|
-
const runAtActiveCell =
|
|
12946
|
+
const runAtActiveCell = React11.useCallback((command, options) => {
|
|
13255
12947
|
return runAtCellPos(layoutRef.current?.cellPos ?? null, command, options);
|
|
13256
12948
|
}, [runAtCellPos]);
|
|
13257
|
-
const duplicateRowAt =
|
|
12949
|
+
const duplicateRowAt = React11.useCallback((rowIndex, cellPos) => {
|
|
13258
12950
|
const result = duplicateTableRowAt(editor, rowIndex, cellPos);
|
|
13259
12951
|
scheduleSyncFromSelection();
|
|
13260
12952
|
return result;
|
|
13261
12953
|
}, [editor, scheduleSyncFromSelection]);
|
|
13262
|
-
const clearRowAt =
|
|
12954
|
+
const clearRowAt = React11.useCallback((rowIndex, cellPos) => {
|
|
13263
12955
|
const result = clearTableRowAt(editor, rowIndex, cellPos);
|
|
13264
12956
|
scheduleSyncFromSelection();
|
|
13265
12957
|
return result;
|
|
13266
12958
|
}, [editor, scheduleSyncFromSelection]);
|
|
13267
|
-
const duplicateColumnAt =
|
|
12959
|
+
const duplicateColumnAt = React11.useCallback((columnIndex, cellPos) => {
|
|
13268
12960
|
const result = duplicateTableColumnAt(editor, columnIndex, cellPos);
|
|
13269
12961
|
scheduleSyncFromSelection();
|
|
13270
12962
|
return result;
|
|
13271
12963
|
}, [editor, scheduleSyncFromSelection]);
|
|
13272
|
-
const clearColumnAt =
|
|
12964
|
+
const clearColumnAt = React11.useCallback((columnIndex, cellPos) => {
|
|
13273
12965
|
const result = clearTableColumnAt(editor, columnIndex, cellPos);
|
|
13274
12966
|
scheduleSyncFromSelection();
|
|
13275
12967
|
return result;
|
|
13276
12968
|
}, [editor, scheduleSyncFromSelection]);
|
|
13277
|
-
const expandTableBy =
|
|
12969
|
+
const expandTableBy = React11.useCallback((rows, cols) => {
|
|
13278
12970
|
const activeCellPos = layoutRef.current?.cellPos ?? editor.state.selection.from;
|
|
13279
12971
|
const result = expandTableFromCell(editor, activeCellPos, rows, cols);
|
|
13280
12972
|
scheduleSyncFromSelection();
|
|
@@ -13283,7 +12975,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13283
12975
|
const canExpandTable = Boolean(layout);
|
|
13284
12976
|
const controlsVisible = false;
|
|
13285
12977
|
const tableMenuOpen = openMenuKey === "table";
|
|
13286
|
-
const startTableResize =
|
|
12978
|
+
const startTableResize = React11.useCallback((event, edge) => {
|
|
13287
12979
|
if (event.button !== 0 || dragStateRef.current) return;
|
|
13288
12980
|
const activeLayout = layoutRef.current;
|
|
13289
12981
|
if (!activeLayout) return;
|
|
@@ -13321,7 +13013,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13321
13013
|
updateTableResizePreview(pendingDimensions);
|
|
13322
13014
|
setDocumentCursor(editorDocument, edge === "both" ? "nwse-resize" : "ew-resize");
|
|
13323
13015
|
}, [editor, editorDocument, updateTableResizePreview]);
|
|
13324
|
-
const fitTableToEditorWidth =
|
|
13016
|
+
const fitTableToEditorWidth = React11.useCallback((event) => {
|
|
13325
13017
|
if (event.button !== 0 || dragStateRef.current) return;
|
|
13326
13018
|
const activeLayout = layoutRef.current;
|
|
13327
13019
|
if (!activeLayout) return;
|
|
@@ -13346,19 +13038,57 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13346
13038
|
scheduleSyncFromSelection();
|
|
13347
13039
|
}
|
|
13348
13040
|
}, [editor, scheduleSyncFromSelection]);
|
|
13349
|
-
const
|
|
13041
|
+
const resizeTableWithKeyboard = React11.useCallback((event, edge) => {
|
|
13042
|
+
const horizontal = event.key === "ArrowLeft" || event.key === "ArrowRight";
|
|
13043
|
+
const vertical = event.key === "ArrowUp" || event.key === "ArrowDown";
|
|
13044
|
+
if (!horizontal && !vertical || edge !== "both" && !horizontal) return;
|
|
13045
|
+
const activeLayout = layoutRef.current;
|
|
13046
|
+
if (!activeLayout) return;
|
|
13047
|
+
const snapshot = createTableSizeSnapshot(
|
|
13048
|
+
editor,
|
|
13049
|
+
activeLayout.cellPos,
|
|
13050
|
+
activeLayout.tableWidth,
|
|
13051
|
+
activeLayout.tableHeight,
|
|
13052
|
+
activeLayout.viewportWidth
|
|
13053
|
+
);
|
|
13054
|
+
if (!snapshot) return;
|
|
13055
|
+
event.preventDefault();
|
|
13056
|
+
event.stopPropagation();
|
|
13057
|
+
const step = event.shiftKey ? 20 : 5;
|
|
13058
|
+
const dimensions = resolveTableResizeDimensions({
|
|
13059
|
+
deltaX: event.key === "ArrowLeft" ? -step : event.key === "ArrowRight" ? step : 0,
|
|
13060
|
+
deltaY: event.key === "ArrowUp" ? -step : event.key === "ArrowDown" ? step : 0,
|
|
13061
|
+
edge,
|
|
13062
|
+
lockAxis: false,
|
|
13063
|
+
preserveRatio: false,
|
|
13064
|
+
snapshot
|
|
13065
|
+
});
|
|
13066
|
+
if (applyTableSize(editor, snapshot, dimensions, { widthMode: snapshot.widthMode })) {
|
|
13067
|
+
scheduleSyncFromSelection();
|
|
13068
|
+
}
|
|
13069
|
+
}, [editor, scheduleSyncFromSelection]);
|
|
13070
|
+
const startAddColumnDrag = React11.useCallback((event) => {
|
|
13071
|
+
if (event.button !== 0 || dragStateRef.current) return;
|
|
13072
|
+
event.preventDefault();
|
|
13073
|
+
event.stopPropagation();
|
|
13350
13074
|
setOpenMenuKey(null);
|
|
13351
13075
|
dragStateRef.current = { kind: "add-column", previewCols: 1 };
|
|
13352
13076
|
setDragPreview({ kind: "add-column", previewCols: 1 });
|
|
13353
13077
|
setDocumentCursor(editorDocument, "ew-resize");
|
|
13354
13078
|
}, [editorDocument]);
|
|
13355
|
-
const startAddRowDrag =
|
|
13079
|
+
const startAddRowDrag = React11.useCallback((event) => {
|
|
13080
|
+
if (event.button !== 0 || dragStateRef.current) return;
|
|
13081
|
+
event.preventDefault();
|
|
13082
|
+
event.stopPropagation();
|
|
13356
13083
|
setOpenMenuKey(null);
|
|
13357
13084
|
dragStateRef.current = { kind: "add-row", previewRows: 1 };
|
|
13358
13085
|
setDragPreview({ kind: "add-row", previewRows: 1 });
|
|
13359
13086
|
setDocumentCursor(editorDocument, "ns-resize");
|
|
13360
13087
|
}, [editorDocument]);
|
|
13361
|
-
const startRowDrag =
|
|
13088
|
+
const startRowDrag = React11.useCallback((event, rowHandle) => {
|
|
13089
|
+
if (event.button !== 0 || dragStateRef.current) return;
|
|
13090
|
+
event.preventDefault();
|
|
13091
|
+
event.stopPropagation();
|
|
13362
13092
|
setOpenMenuKey(null);
|
|
13363
13093
|
dragStateRef.current = {
|
|
13364
13094
|
kind: "row",
|
|
@@ -13375,7 +13105,10 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13375
13105
|
});
|
|
13376
13106
|
setDocumentCursor(editorDocument, "grabbing");
|
|
13377
13107
|
}, [editorDocument]);
|
|
13378
|
-
const startColumnDrag =
|
|
13108
|
+
const startColumnDrag = React11.useCallback((event, columnHandle) => {
|
|
13109
|
+
if (event.button !== 0 || dragStateRef.current) return;
|
|
13110
|
+
event.preventDefault();
|
|
13111
|
+
event.stopPropagation();
|
|
13379
13112
|
setOpenMenuKey(null);
|
|
13380
13113
|
dragStateRef.current = {
|
|
13381
13114
|
kind: "column",
|
|
@@ -13392,9 +13125,62 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13392
13125
|
});
|
|
13393
13126
|
setDocumentCursor(editorDocument, "grabbing");
|
|
13394
13127
|
}, [editorDocument]);
|
|
13395
|
-
|
|
13128
|
+
const moveRowWithKeyboard = React11.useCallback((rowHandle, direction) => {
|
|
13129
|
+
const targetIndex = clamp2(rowHandle.index + direction, 0, (layoutRef.current?.rowHandles.length ?? 1) - 1);
|
|
13130
|
+
if (targetIndex === rowHandle.index) return;
|
|
13131
|
+
const tableInfo = findTableInfo(editor, rowHandle.cellPos);
|
|
13132
|
+
moveTableRow({
|
|
13133
|
+
from: rowHandle.index,
|
|
13134
|
+
to: targetIndex,
|
|
13135
|
+
pos: rowHandle.cellPos,
|
|
13136
|
+
select: true
|
|
13137
|
+
})(editor.state, (transaction) => {
|
|
13138
|
+
const nextTable = tableInfo ? transaction.doc.nodeAt(tableInfo.pos) : null;
|
|
13139
|
+
if (tableInfo && nextTable?.type.name === "table") {
|
|
13140
|
+
const rewrittenTable = rewriteTableNodeFormulaReferencesForMove(nextTable, "row", rowHandle.index, targetIndex);
|
|
13141
|
+
if (rewrittenTable !== nextTable) {
|
|
13142
|
+
transaction.replaceWith(tableInfo.pos, tableInfo.pos + nextTable.nodeSize, rewrittenTable);
|
|
13143
|
+
}
|
|
13144
|
+
}
|
|
13145
|
+
editor.view.dispatch(transaction);
|
|
13146
|
+
});
|
|
13147
|
+
scheduleSyncFromSelection();
|
|
13148
|
+
}, [editor, scheduleSyncFromSelection]);
|
|
13149
|
+
const moveColumnWithKeyboard = React11.useCallback((columnHandle, direction) => {
|
|
13150
|
+
const targetIndex = clamp2(columnHandle.index + direction, 0, (layoutRef.current?.columnHandles.length ?? 1) - 1);
|
|
13151
|
+
if (targetIndex === columnHandle.index) return;
|
|
13152
|
+
const tableInfo = findTableInfo(editor, columnHandle.cellPos);
|
|
13153
|
+
const responsiveRatios = tableInfo && normalizeTableWidthMode(tableInfo.node.attrs.widthMode) === "responsive" ? moveResponsiveColumnRatio(getTableColumnRatios(tableInfo.node), columnHandle.index, targetIndex) : null;
|
|
13154
|
+
moveTableColumn({
|
|
13155
|
+
from: columnHandle.index,
|
|
13156
|
+
to: targetIndex,
|
|
13157
|
+
pos: columnHandle.cellPos,
|
|
13158
|
+
select: true
|
|
13159
|
+
})(editor.state, (transaction) => {
|
|
13160
|
+
if (tableInfo && responsiveRatios) {
|
|
13161
|
+
const nextTable2 = transaction.doc.nodeAt(tableInfo.pos);
|
|
13162
|
+
if (nextTable2?.type.name === "table") {
|
|
13163
|
+
transaction.setNodeMarkup(tableInfo.pos, void 0, {
|
|
13164
|
+
...nextTable2.attrs,
|
|
13165
|
+
widthMode: "responsive",
|
|
13166
|
+
columnRatios: responsiveRatios
|
|
13167
|
+
});
|
|
13168
|
+
}
|
|
13169
|
+
}
|
|
13170
|
+
const nextTable = tableInfo ? transaction.doc.nodeAt(tableInfo.pos) : null;
|
|
13171
|
+
if (tableInfo && nextTable?.type.name === "table") {
|
|
13172
|
+
const rewrittenTable = rewriteTableNodeFormulaReferencesForMove(nextTable, "column", columnHandle.index, targetIndex);
|
|
13173
|
+
if (rewrittenTable !== nextTable) {
|
|
13174
|
+
transaction.replaceWith(tableInfo.pos, tableInfo.pos + nextTable.nodeSize, rewrittenTable);
|
|
13175
|
+
}
|
|
13176
|
+
}
|
|
13177
|
+
editor.view.dispatch(transaction);
|
|
13178
|
+
});
|
|
13179
|
+
scheduleSyncFromSelection();
|
|
13180
|
+
}, [editor, scheduleSyncFromSelection]);
|
|
13181
|
+
React11.useEffect(() => {
|
|
13396
13182
|
if (!editorWindow) return;
|
|
13397
|
-
const
|
|
13183
|
+
const handlePointerMove = (event) => {
|
|
13398
13184
|
const dragState = dragStateRef.current;
|
|
13399
13185
|
const activeLayout = layoutRef.current;
|
|
13400
13186
|
const surface = containerRef.current;
|
|
@@ -13447,16 +13233,31 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13447
13233
|
setDragPreview({ kind: "add-row", previewRows });
|
|
13448
13234
|
setDocumentCursor(editorDocument, "ns-resize");
|
|
13449
13235
|
};
|
|
13450
|
-
const
|
|
13236
|
+
const handlePointerUp = () => {
|
|
13451
13237
|
const dragState = dragStateRef.current;
|
|
13452
13238
|
if (!dragState || dragState.kind === "resize-table") return;
|
|
13453
13239
|
if (dragState.kind === "row" && dragState.originIndex !== dragState.targetIndex) {
|
|
13240
|
+
const tableInfo = findTableInfo(editor, dragState.anchorPos);
|
|
13454
13241
|
moveTableRow({
|
|
13455
13242
|
from: dragState.originIndex,
|
|
13456
13243
|
to: dragState.targetIndex,
|
|
13457
13244
|
pos: dragState.anchorPos,
|
|
13458
13245
|
select: true
|
|
13459
|
-
})(editor.state,
|
|
13246
|
+
})(editor.state, (transaction) => {
|
|
13247
|
+
const nextTable = tableInfo ? transaction.doc.nodeAt(tableInfo.pos) : null;
|
|
13248
|
+
if (tableInfo && nextTable?.type.name === "table") {
|
|
13249
|
+
const rewrittenTable = rewriteTableNodeFormulaReferencesForMove(
|
|
13250
|
+
nextTable,
|
|
13251
|
+
"row",
|
|
13252
|
+
dragState.originIndex,
|
|
13253
|
+
dragState.targetIndex
|
|
13254
|
+
);
|
|
13255
|
+
if (rewrittenTable !== nextTable) {
|
|
13256
|
+
transaction.replaceWith(tableInfo.pos, tableInfo.pos + nextTable.nodeSize, rewrittenTable);
|
|
13257
|
+
}
|
|
13258
|
+
}
|
|
13259
|
+
editor.view.dispatch(transaction);
|
|
13260
|
+
});
|
|
13460
13261
|
scheduleSyncFromSelection();
|
|
13461
13262
|
}
|
|
13462
13263
|
if (dragState.kind === "column" && dragState.originIndex !== dragState.targetIndex) {
|
|
@@ -13473,15 +13274,27 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13473
13274
|
select: true
|
|
13474
13275
|
})(editor.state, (transaction) => {
|
|
13475
13276
|
if (tableInfo && responsiveRatios) {
|
|
13476
|
-
const
|
|
13477
|
-
if (
|
|
13277
|
+
const nextTable2 = transaction.doc.nodeAt(tableInfo.pos);
|
|
13278
|
+
if (nextTable2?.type.name === "table") {
|
|
13478
13279
|
transaction.setNodeMarkup(tableInfo.pos, void 0, {
|
|
13479
|
-
...
|
|
13280
|
+
...nextTable2.attrs,
|
|
13480
13281
|
widthMode: "responsive",
|
|
13481
13282
|
columnRatios: responsiveRatios
|
|
13482
13283
|
});
|
|
13483
13284
|
}
|
|
13484
13285
|
}
|
|
13286
|
+
const nextTable = tableInfo ? transaction.doc.nodeAt(tableInfo.pos) : null;
|
|
13287
|
+
if (tableInfo && nextTable?.type.name === "table") {
|
|
13288
|
+
const rewrittenTable = rewriteTableNodeFormulaReferencesForMove(
|
|
13289
|
+
nextTable,
|
|
13290
|
+
"column",
|
|
13291
|
+
dragState.originIndex,
|
|
13292
|
+
dragState.targetIndex
|
|
13293
|
+
);
|
|
13294
|
+
if (rewrittenTable !== nextTable) {
|
|
13295
|
+
transaction.replaceWith(tableInfo.pos, tableInfo.pos + nextTable.nodeSize, rewrittenTable);
|
|
13296
|
+
}
|
|
13297
|
+
}
|
|
13485
13298
|
editor.view.dispatch(transaction);
|
|
13486
13299
|
});
|
|
13487
13300
|
scheduleSyncFromSelection();
|
|
@@ -13494,20 +13307,23 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13494
13307
|
}
|
|
13495
13308
|
clearDrag();
|
|
13496
13309
|
};
|
|
13497
|
-
const
|
|
13310
|
+
const unsubscribePointerMove = subscribeSharedGlobalEvent(
|
|
13498
13311
|
editorWindow,
|
|
13499
|
-
"
|
|
13500
|
-
|
|
13312
|
+
"pointermove",
|
|
13313
|
+
handlePointerMove,
|
|
13314
|
+
{ passive: false }
|
|
13501
13315
|
);
|
|
13502
|
-
const
|
|
13316
|
+
const unsubscribePointerUp = subscribeSharedGlobalEvent(editorWindow, "pointerup", handlePointerUp);
|
|
13317
|
+
const unsubscribePointerCancel = subscribeSharedGlobalEvent(editorWindow, "pointercancel", clearDrag);
|
|
13503
13318
|
const unsubscribeBlur = subscribeSharedGlobalEvent(editorWindow, "blur", clearDrag);
|
|
13504
13319
|
return () => {
|
|
13505
|
-
|
|
13506
|
-
|
|
13320
|
+
unsubscribePointerMove();
|
|
13321
|
+
unsubscribePointerUp();
|
|
13322
|
+
unsubscribePointerCancel();
|
|
13507
13323
|
unsubscribeBlur();
|
|
13508
13324
|
};
|
|
13509
13325
|
}, [clearDrag, containerRef, editor, editorDocument, editorWindow, expandTableBy, scheduleSyncFromSelection]);
|
|
13510
|
-
|
|
13326
|
+
React11.useEffect(() => {
|
|
13511
13327
|
if (!editorWindow) return;
|
|
13512
13328
|
const handlePointerMove = (event) => {
|
|
13513
13329
|
const dragState = dragStateRef.current;
|
|
@@ -13578,7 +13394,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13578
13394
|
}
|
|
13579
13395
|
};
|
|
13580
13396
|
}, [clearDrag, editor, editorDocument, editorWindow, scheduleSyncFromSelection, updateTableResizePreview]);
|
|
13581
|
-
const openCellInspector =
|
|
13397
|
+
const openCellInspector = React11.useCallback(() => {
|
|
13582
13398
|
const cellPos = layoutRef.current?.cellPos;
|
|
13583
13399
|
if (!showCellInspector || cellPos == null) return;
|
|
13584
13400
|
const didSelect = editor.commands.setCellSelection({
|
|
@@ -13590,7 +13406,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13590
13406
|
if (!editor.isDestroyed) editor.view.focus();
|
|
13591
13407
|
});
|
|
13592
13408
|
}, [editor, editorWindow, showCellInspector]);
|
|
13593
|
-
const menuItems =
|
|
13409
|
+
const menuItems = React11.useMemo(() => {
|
|
13594
13410
|
if (!layout) return [];
|
|
13595
13411
|
return [
|
|
13596
13412
|
...showCellInspector ? [{
|
|
@@ -13663,7 +13479,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13663
13479
|
}
|
|
13664
13480
|
];
|
|
13665
13481
|
}, [editor, layout, openCellInspector, runAtActiveCell, showCellInspector, t]);
|
|
13666
|
-
const getRowHandleMenuItems =
|
|
13482
|
+
const getRowHandleMenuItems = React11.useCallback((rowHandle) => [
|
|
13667
13483
|
{
|
|
13668
13484
|
label: t("tableMenu.addRowBefore"),
|
|
13669
13485
|
icon: ArrowUp,
|
|
@@ -13691,7 +13507,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13691
13507
|
destructive: true
|
|
13692
13508
|
}
|
|
13693
13509
|
], [clearRowAt, duplicateRowAt, runAtCellPos, t]);
|
|
13694
|
-
const getColumnHandleMenuItems =
|
|
13510
|
+
const getColumnHandleMenuItems = React11.useCallback((columnHandle) => [
|
|
13695
13511
|
{
|
|
13696
13512
|
label: t("tableMenu.addColumnBefore"),
|
|
13697
13513
|
icon: ArrowLeft,
|
|
@@ -13737,6 +13553,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13737
13553
|
onOpenMenuChange: (menuKey, open) => {
|
|
13738
13554
|
setOpenMenuKey((prev) => open ? menuKey : prev === menuKey ? null : prev);
|
|
13739
13555
|
},
|
|
13556
|
+
onMove: moveRowWithKeyboard,
|
|
13740
13557
|
onStartDrag: startRowDrag,
|
|
13741
13558
|
openMenuKey,
|
|
13742
13559
|
rowDragLabel: t("tableMenu.dragRow"),
|
|
@@ -13757,6 +13574,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13757
13574
|
onOpenMenuChange: (menuKey, open) => {
|
|
13758
13575
|
setOpenMenuKey((prev) => open ? menuKey : prev === menuKey ? null : prev);
|
|
13759
13576
|
},
|
|
13577
|
+
onMove: moveColumnWithKeyboard,
|
|
13760
13578
|
onStartDrag: startColumnDrag,
|
|
13761
13579
|
openMenuKey
|
|
13762
13580
|
}
|
|
@@ -13784,6 +13602,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13784
13602
|
frameRef: tableResizeFrameRef,
|
|
13785
13603
|
layout,
|
|
13786
13604
|
onFitWidth: fitTableToEditorWidth,
|
|
13605
|
+
onKeyboardResize: resizeTableWithKeyboard,
|
|
13787
13606
|
onStartResize: startTableResize,
|
|
13788
13607
|
resizeBothLabel: t("tableMenu.resizeBoth")
|
|
13789
13608
|
}
|
|
@@ -13798,6 +13617,8 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13798
13617
|
layout,
|
|
13799
13618
|
onStartAddColumn: startAddColumnDrag,
|
|
13800
13619
|
onStartAddRow: startAddRowDrag,
|
|
13620
|
+
onAddColumn: () => expandTableBy(0, 1),
|
|
13621
|
+
onAddRow: () => expandTableBy(1, 0),
|
|
13801
13622
|
quickAddColumnLabel: t("tableMenu.quickAddColumnAfter"),
|
|
13802
13623
|
quickAddRowLabel: t("tableMenu.quickAddRowAfter")
|
|
13803
13624
|
}
|
|
@@ -13815,10 +13636,10 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13815
13636
|
}
|
|
13816
13637
|
|
|
13817
13638
|
// src/components/UEditor/use-table-interactions.ts
|
|
13818
|
-
import
|
|
13639
|
+
import React13, { useEffect as useEffect6, useRef as useRef6 } from "react";
|
|
13819
13640
|
|
|
13820
13641
|
// src/components/UEditor/use-table-row-resize.ts
|
|
13821
|
-
import
|
|
13642
|
+
import React12, { useRef as useRef5 } from "react";
|
|
13822
13643
|
function setRowResizeBodyState(ownerDocument, active) {
|
|
13823
13644
|
ownerDocument.body.style.userSelect = active ? "none" : "";
|
|
13824
13645
|
ownerDocument.body.style.cursor = active ? "row-resize" : "";
|
|
@@ -13832,15 +13653,15 @@ function useTableRowResize({
|
|
|
13832
13653
|
scheduleTableLayoutSync
|
|
13833
13654
|
}) {
|
|
13834
13655
|
const stateRef = useRef5(null);
|
|
13835
|
-
const syncActiveGuide =
|
|
13656
|
+
const syncActiveGuide = React12.useCallback(() => {
|
|
13836
13657
|
const state = stateRef.current;
|
|
13837
13658
|
if (!state) return false;
|
|
13838
13659
|
setHoveredTableCell(state.cellElement);
|
|
13839
13660
|
showRowGuide(state.tableElement, state.rowElement, state.cellElement, state.pendingHeight);
|
|
13840
13661
|
return true;
|
|
13841
13662
|
}, [setHoveredTableCell, showRowGuide]);
|
|
13842
|
-
const isResizing =
|
|
13843
|
-
const beginResize =
|
|
13663
|
+
const isResizing = React12.useCallback(() => stateRef.current !== null, []);
|
|
13664
|
+
const beginResize = React12.useCallback((event, table, row, cell) => {
|
|
13844
13665
|
if (!editor || !isRowResizeHotspot(cell, event.clientX, event.clientY)) {
|
|
13845
13666
|
return false;
|
|
13846
13667
|
}
|
|
@@ -13869,7 +13690,7 @@ function useTableRowResize({
|
|
|
13869
13690
|
event.stopPropagation();
|
|
13870
13691
|
return true;
|
|
13871
13692
|
}, [editor, setHoveredTableCell, showRowGuide]);
|
|
13872
|
-
const handlePointerMove =
|
|
13693
|
+
const handlePointerMove = React12.useCallback((event) => {
|
|
13873
13694
|
const state = stateRef.current;
|
|
13874
13695
|
if (!state) return;
|
|
13875
13696
|
const nextHeight = Math.max(
|
|
@@ -13886,7 +13707,7 @@ function useTableRowResize({
|
|
|
13886
13707
|
setRowResizeBodyState(state.rowElement.ownerDocument, true);
|
|
13887
13708
|
showRowGuide(state.tableElement, state.rowElement, state.cellElement, nextHeight);
|
|
13888
13709
|
}, [showRowGuide]);
|
|
13889
|
-
const handlePointerUp =
|
|
13710
|
+
const handlePointerUp = React12.useCallback((event) => {
|
|
13890
13711
|
if (!editor) return;
|
|
13891
13712
|
const state = stateRef.current;
|
|
13892
13713
|
if (!state) return;
|
|
@@ -13911,7 +13732,7 @@ function useTableRowResize({
|
|
|
13911
13732
|
clearAllTableResizeHover();
|
|
13912
13733
|
scheduleTableLayoutSync();
|
|
13913
13734
|
}, [clearAllTableResizeHover, clearHoveredTableCell, editor, scheduleTableLayoutSync]);
|
|
13914
|
-
const cancelResize =
|
|
13735
|
+
const cancelResize = React12.useCallback(() => {
|
|
13915
13736
|
const state = stateRef.current;
|
|
13916
13737
|
if (!state) return;
|
|
13917
13738
|
stateRef.current = null;
|
|
@@ -13921,7 +13742,7 @@ function useTableRowResize({
|
|
|
13921
13742
|
clearAllTableResizeHover();
|
|
13922
13743
|
scheduleTableLayoutSync();
|
|
13923
13744
|
}, [clearAllTableResizeHover, clearHoveredTableCell, scheduleTableLayoutSync]);
|
|
13924
|
-
const cleanup =
|
|
13745
|
+
const cleanup = React12.useCallback(() => {
|
|
13925
13746
|
const editorDocument = stateRef.current?.rowElement.ownerDocument ?? editor?.view.dom.ownerDocument;
|
|
13926
13747
|
stateRef.current = null;
|
|
13927
13748
|
isRowResizingGlobal.active = false;
|
|
@@ -13950,16 +13771,16 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
13950
13771
|
const activeTableCellRef = useRef6(null);
|
|
13951
13772
|
const suppressActiveCellHighlightRef = useRef6(false);
|
|
13952
13773
|
const tableLayoutSyncFrameRef = useRef6(null);
|
|
13953
|
-
const getProseMirrorElement =
|
|
13774
|
+
const getProseMirrorElement = React13.useCallback(() => {
|
|
13954
13775
|
return editorContentRef.current?.querySelector(".ProseMirror");
|
|
13955
13776
|
}, []);
|
|
13956
|
-
const setEditorResizeCursor =
|
|
13777
|
+
const setEditorResizeCursor = React13.useCallback((cursor) => {
|
|
13957
13778
|
const proseMirror = getProseMirrorElement();
|
|
13958
13779
|
if (proseMirror) {
|
|
13959
13780
|
proseMirror.style.cursor = cursor;
|
|
13960
13781
|
}
|
|
13961
13782
|
}, [getProseMirrorElement]);
|
|
13962
|
-
const hideColumnGuide =
|
|
13783
|
+
const hideColumnGuide = React13.useCallback(() => {
|
|
13963
13784
|
editorContentRef.current?.classList.remove("resize-cursor");
|
|
13964
13785
|
getProseMirrorElement()?.classList.remove("resize-cursor");
|
|
13965
13786
|
const guide = tableColumnGuideRef.current;
|
|
@@ -13967,7 +13788,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
13967
13788
|
guide.style.opacity = "0";
|
|
13968
13789
|
}
|
|
13969
13790
|
}, [getProseMirrorElement]);
|
|
13970
|
-
const hideRowGuide =
|
|
13791
|
+
const hideRowGuide = React13.useCallback(() => {
|
|
13971
13792
|
editorContentRef.current?.classList.remove("resize-row-cursor");
|
|
13972
13793
|
getProseMirrorElement()?.classList.remove("resize-row-cursor");
|
|
13973
13794
|
const guide = tableRowGuideRef.current;
|
|
@@ -13977,21 +13798,21 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
13977
13798
|
}, [getProseMirrorElement]);
|
|
13978
13799
|
const hotspotTimerRef = useRef6(null);
|
|
13979
13800
|
const activeHotspotKeyRef = useRef6(null);
|
|
13980
|
-
const clearHotspotTimer =
|
|
13801
|
+
const clearHotspotTimer = React13.useCallback(() => {
|
|
13981
13802
|
if (hotspotTimerRef.current !== null) {
|
|
13982
13803
|
const realm = editorContentRef.current?.ownerDocument.defaultView;
|
|
13983
13804
|
realm?.clearTimeout(hotspotTimerRef.current);
|
|
13984
13805
|
hotspotTimerRef.current = null;
|
|
13985
13806
|
}
|
|
13986
13807
|
}, []);
|
|
13987
|
-
const clearAllTableResizeHover =
|
|
13808
|
+
const clearAllTableResizeHover = React13.useCallback(() => {
|
|
13988
13809
|
clearHotspotTimer();
|
|
13989
13810
|
activeHotspotKeyRef.current = null;
|
|
13990
13811
|
setEditorResizeCursor("");
|
|
13991
13812
|
hideColumnGuide();
|
|
13992
13813
|
hideRowGuide();
|
|
13993
13814
|
}, [clearHotspotTimer, hideColumnGuide, hideRowGuide, setEditorResizeCursor]);
|
|
13994
|
-
const updateActiveCellHighlight =
|
|
13815
|
+
const updateActiveCellHighlight = React13.useCallback((cell) => {
|
|
13995
13816
|
const surface = editorContentRef.current;
|
|
13996
13817
|
const highlight = activeTableCellHighlightRef.current;
|
|
13997
13818
|
if (!highlight) return;
|
|
@@ -14006,7 +13827,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
14006
13827
|
highlight.style.width = `${metrics.width}px`;
|
|
14007
13828
|
highlight.style.height = `${metrics.height}px`;
|
|
14008
13829
|
}, []);
|
|
14009
|
-
const scheduleTableLayoutSync =
|
|
13830
|
+
const scheduleTableLayoutSync = React13.useCallback(() => {
|
|
14010
13831
|
if (!activeTableCellRef.current || tableLayoutSyncFrameRef.current !== null) return;
|
|
14011
13832
|
const realm = editorContentRef.current?.ownerDocument.defaultView;
|
|
14012
13833
|
if (!realm) return;
|
|
@@ -14018,7 +13839,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
14018
13839
|
editorContentRef.current?.dispatchEvent(new realm.CustomEvent(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT));
|
|
14019
13840
|
});
|
|
14020
13841
|
}, [updateActiveCellHighlight]);
|
|
14021
|
-
const setActiveTableCell =
|
|
13842
|
+
const setActiveTableCell = React13.useCallback((cell) => {
|
|
14022
13843
|
if (activeTableCellRef.current === cell) {
|
|
14023
13844
|
updateActiveCellHighlight(cell);
|
|
14024
13845
|
return;
|
|
@@ -14026,17 +13847,17 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
14026
13847
|
activeTableCellRef.current = cell;
|
|
14027
13848
|
updateActiveCellHighlight(activeTableCellRef.current);
|
|
14028
13849
|
}, [updateActiveCellHighlight]);
|
|
14029
|
-
const clearActiveTableCell =
|
|
13850
|
+
const clearActiveTableCell = React13.useCallback(() => {
|
|
14030
13851
|
activeTableCellRef.current = null;
|
|
14031
13852
|
updateActiveCellHighlight(null);
|
|
14032
13853
|
}, [updateActiveCellHighlight]);
|
|
14033
|
-
const setHoveredTableCell =
|
|
13854
|
+
const setHoveredTableCell = React13.useCallback((cell) => {
|
|
14034
13855
|
hoveredTableCellRef.current = cell;
|
|
14035
13856
|
}, []);
|
|
14036
|
-
const clearHoveredTableCell =
|
|
13857
|
+
const clearHoveredTableCell = React13.useCallback(() => {
|
|
14037
13858
|
hoveredTableCellRef.current = null;
|
|
14038
13859
|
}, []);
|
|
14039
|
-
const showColumnGuide =
|
|
13860
|
+
const showColumnGuide = React13.useCallback((table, row, cell) => {
|
|
14040
13861
|
const surface = editorContentRef.current;
|
|
14041
13862
|
const guide = tableColumnGuideRef.current;
|
|
14042
13863
|
if (!surface || !guide) return;
|
|
@@ -14050,7 +13871,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
14050
13871
|
getProseMirrorElement()?.classList.add("resize-cursor");
|
|
14051
13872
|
setEditorResizeCursor("col-resize");
|
|
14052
13873
|
}, [getProseMirrorElement, setEditorResizeCursor]);
|
|
14053
|
-
const showRowGuide =
|
|
13874
|
+
const showRowGuide = React13.useCallback((table, row, cell, previewHeight) => {
|
|
14054
13875
|
const surface = editorContentRef.current;
|
|
14055
13876
|
const guide = tableRowGuideRef.current;
|
|
14056
13877
|
if (!surface || !guide) return;
|
|
@@ -14082,7 +13903,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
14082
13903
|
clearAllTableResizeHover,
|
|
14083
13904
|
scheduleTableLayoutSync
|
|
14084
13905
|
});
|
|
14085
|
-
const syncActiveTableCellFromSelection =
|
|
13906
|
+
const syncActiveTableCellFromSelection = React13.useCallback(() => {
|
|
14086
13907
|
if (!editor) return;
|
|
14087
13908
|
if (!editor.isFocused) {
|
|
14088
13909
|
clearActiveTableCell();
|
|
@@ -14423,7 +14244,7 @@ function cancelFormulaEditing(view) {
|
|
|
14423
14244
|
function getReferenceInsertionPrefix(view, cellContentStart, insertionPos) {
|
|
14424
14245
|
const textBeforeCursor = view.state.doc.textBetween(cellContentStart, insertionPos, "", "");
|
|
14425
14246
|
const isInsideFunctionArguments = /[A-Z]+\([^)]*$/i.test(textBeforeCursor);
|
|
14426
|
-
const followsReference =
|
|
14247
|
+
const followsReference = /\$?[A-Z]+\$?[1-9]\d*(?::\$?[A-Z]+\$?[1-9]\d*)?\s*$/i.test(textBeforeCursor);
|
|
14427
14248
|
return isInsideFunctionArguments && followsReference ? "," : "";
|
|
14428
14249
|
}
|
|
14429
14250
|
function findTableForPos(view, pos) {
|
|
@@ -14974,7 +14795,7 @@ function TableFormulaBar({ editor }) {
|
|
|
14974
14795
|
}
|
|
14975
14796
|
|
|
14976
14797
|
// src/components/UEditor/use-editor-output.ts
|
|
14977
|
-
import * as
|
|
14798
|
+
import * as React15 from "react";
|
|
14978
14799
|
function normalizeDebounceMs(value) {
|
|
14979
14800
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
14980
14801
|
}
|
|
@@ -14984,18 +14805,18 @@ function useUEditorOutput({
|
|
|
14984
14805
|
onJsonChange,
|
|
14985
14806
|
outputDebounceMs
|
|
14986
14807
|
}) {
|
|
14987
|
-
const callbacksRef =
|
|
14808
|
+
const callbacksRef = React15.useRef({
|
|
14988
14809
|
onChange,
|
|
14989
14810
|
onHtmlChange,
|
|
14990
14811
|
onJsonChange
|
|
14991
14812
|
});
|
|
14992
|
-
const pendingEditorRef =
|
|
14993
|
-
const timeoutRef =
|
|
14813
|
+
const pendingEditorRef = React15.useRef(null);
|
|
14814
|
+
const timeoutRef = React15.useRef(null);
|
|
14994
14815
|
const debounceMs = normalizeDebounceMs(outputDebounceMs);
|
|
14995
|
-
|
|
14816
|
+
React15.useLayoutEffect(() => {
|
|
14996
14817
|
callbacksRef.current = { onChange, onHtmlChange, onJsonChange };
|
|
14997
14818
|
}, [onChange, onHtmlChange, onJsonChange]);
|
|
14998
|
-
const flushOutputUpdates =
|
|
14819
|
+
const flushOutputUpdates = React15.useCallback(() => {
|
|
14999
14820
|
if (timeoutRef.current !== null) {
|
|
15000
14821
|
clearTimeout(timeoutRef.current);
|
|
15001
14822
|
timeoutRef.current = null;
|
|
@@ -15013,7 +14834,7 @@ function useUEditorOutput({
|
|
|
15013
14834
|
callbacks.onJsonChange(editor.getJSON());
|
|
15014
14835
|
}
|
|
15015
14836
|
}, []);
|
|
15016
|
-
const scheduleOutputUpdate =
|
|
14837
|
+
const scheduleOutputUpdate = React15.useCallback((editor) => {
|
|
15017
14838
|
const callbacks = callbacksRef.current;
|
|
15018
14839
|
if (!callbacks.onChange && !callbacks.onHtmlChange && !callbacks.onJsonChange) return;
|
|
15019
14840
|
pendingEditorRef.current = editor;
|
|
@@ -15027,32 +14848,98 @@ function useUEditorOutput({
|
|
|
15027
14848
|
}
|
|
15028
14849
|
timeoutRef.current = setTimeout(flushOutputUpdates, debounceMs);
|
|
15029
14850
|
}, [debounceMs, flushOutputUpdates]);
|
|
15030
|
-
|
|
14851
|
+
React15.useEffect(() => {
|
|
15031
14852
|
if (!pendingEditorRef.current || timeoutRef.current === null) return;
|
|
15032
14853
|
clearTimeout(timeoutRef.current);
|
|
15033
14854
|
timeoutRef.current = debounceMs === 0 ? null : setTimeout(flushOutputUpdates, debounceMs);
|
|
15034
14855
|
if (debounceMs === 0) flushOutputUpdates();
|
|
15035
14856
|
}, [debounceMs, flushOutputUpdates]);
|
|
15036
|
-
|
|
14857
|
+
React15.useEffect(() => () => {
|
|
14858
|
+
flushOutputUpdates();
|
|
15037
14859
|
if (timeoutRef.current !== null) {
|
|
15038
14860
|
clearTimeout(timeoutRef.current);
|
|
15039
14861
|
timeoutRef.current = null;
|
|
15040
14862
|
}
|
|
15041
14863
|
pendingEditorRef.current = null;
|
|
15042
|
-
}, []);
|
|
14864
|
+
}, [flushOutputUpdates]);
|
|
15043
14865
|
return {
|
|
15044
14866
|
flushOutputUpdates,
|
|
15045
14867
|
scheduleOutputUpdate
|
|
15046
14868
|
};
|
|
15047
14869
|
}
|
|
15048
14870
|
|
|
14871
|
+
// src/components/UEditor/use-wide-table-layout.ts
|
|
14872
|
+
import React16 from "react";
|
|
14873
|
+
function useWideTableLayout(editor, enabled, widthBoundaryRef, editorShellRef, editorSurfaceRef) {
|
|
14874
|
+
React16.useLayoutEffect(() => {
|
|
14875
|
+
const boundary = widthBoundaryRef.current;
|
|
14876
|
+
const shell = editorShellRef.current;
|
|
14877
|
+
const surface = editorSurfaceRef.current;
|
|
14878
|
+
if (!editor || !boundary || !shell || !surface) return;
|
|
14879
|
+
const editorDocument = editor.view.dom.ownerDocument;
|
|
14880
|
+
const editorWindow = editorDocument.defaultView;
|
|
14881
|
+
if (!editorWindow) return;
|
|
14882
|
+
const editorDom = editor.view.dom;
|
|
14883
|
+
let frame = 0;
|
|
14884
|
+
const resetWidths = () => {
|
|
14885
|
+
shell.style.removeProperty("width");
|
|
14886
|
+
editorDom.style.removeProperty("width");
|
|
14887
|
+
};
|
|
14888
|
+
const sync = () => {
|
|
14889
|
+
frame = 0;
|
|
14890
|
+
resetWidths();
|
|
14891
|
+
if (!enabled || editor.isDestroyed) return;
|
|
14892
|
+
const boundaryWidth = boundary.getBoundingClientRect().width || boundary.clientWidth;
|
|
14893
|
+
const surfaceWidth = surface.getBoundingClientRect().width || surface.clientWidth;
|
|
14894
|
+
if (boundaryWidth <= 0 || surfaceWidth <= 0) return;
|
|
14895
|
+
editorDom.style.width = `${surfaceWidth}px`;
|
|
14896
|
+
const shellRect = shell.getBoundingClientRect();
|
|
14897
|
+
let requiredWidth = boundaryWidth;
|
|
14898
|
+
editorDom.querySelectorAll("table").forEach((table) => {
|
|
14899
|
+
const tableRect = table.getBoundingClientRect();
|
|
14900
|
+
if (tableRect.width > 0) {
|
|
14901
|
+
requiredWidth = Math.max(requiredWidth, tableRect.right - shellRect.left + 32);
|
|
14902
|
+
return;
|
|
14903
|
+
}
|
|
14904
|
+
const widthBp = Number(table.getAttribute("data-table-width-bp"));
|
|
14905
|
+
if (Number.isFinite(widthBp) && widthBp > 1e4) {
|
|
14906
|
+
requiredWidth = Math.max(requiredWidth, surfaceWidth * widthBp / 1e4 + 32);
|
|
14907
|
+
}
|
|
14908
|
+
});
|
|
14909
|
+
if (requiredWidth <= boundaryWidth + 1) {
|
|
14910
|
+
editorDom.style.removeProperty("width");
|
|
14911
|
+
return;
|
|
14912
|
+
}
|
|
14913
|
+
shell.style.width = `${Math.ceil(requiredWidth)}px`;
|
|
14914
|
+
};
|
|
14915
|
+
const schedule = () => {
|
|
14916
|
+
if (frame) editorWindow.cancelAnimationFrame(frame);
|
|
14917
|
+
frame = editorWindow.requestAnimationFrame(sync);
|
|
14918
|
+
};
|
|
14919
|
+
const resizeObserver = typeof editorWindow.ResizeObserver === "function" ? new editorWindow.ResizeObserver(schedule) : null;
|
|
14920
|
+
resizeObserver?.observe(boundary);
|
|
14921
|
+
editor.on("transaction", schedule);
|
|
14922
|
+
surface.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, schedule);
|
|
14923
|
+
editorWindow.addEventListener("resize", schedule);
|
|
14924
|
+
schedule();
|
|
14925
|
+
return () => {
|
|
14926
|
+
if (frame) editorWindow.cancelAnimationFrame(frame);
|
|
14927
|
+
resizeObserver?.disconnect();
|
|
14928
|
+
editor.off("transaction", schedule);
|
|
14929
|
+
surface.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, schedule);
|
|
14930
|
+
editorWindow.removeEventListener("resize", schedule);
|
|
14931
|
+
resetWidths();
|
|
14932
|
+
};
|
|
14933
|
+
}, [editor, editorShellRef, editorSurfaceRef, enabled, widthBoundaryRef]);
|
|
14934
|
+
}
|
|
14935
|
+
|
|
15049
14936
|
// src/components/UEditor/UEditor.tsx
|
|
15050
14937
|
import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
15051
|
-
var LazyMenuBar =
|
|
15052
|
-
const { MenuBar } = await import("./menu-bar-
|
|
14938
|
+
var LazyMenuBar = React17.lazy(async () => {
|
|
14939
|
+
const { MenuBar } = await import("./menu-bar-DPCNNUX5.js");
|
|
15053
14940
|
return { default: MenuBar };
|
|
15054
14941
|
});
|
|
15055
|
-
var UEditor =
|
|
14942
|
+
var UEditor = React17.forwardRef(({
|
|
15056
14943
|
getPortalContainer,
|
|
15057
14944
|
content = "",
|
|
15058
14945
|
onChange,
|
|
@@ -15066,7 +14953,11 @@ var UEditor = React15.forwardRef(({
|
|
|
15066
14953
|
maxImageFileSize,
|
|
15067
14954
|
allowedImageMimeTypes,
|
|
15068
14955
|
fallbackToDataUrl,
|
|
14956
|
+
onImageUploadError,
|
|
15069
14957
|
placeholder,
|
|
14958
|
+
ariaLabel,
|
|
14959
|
+
ariaLabelledBy,
|
|
14960
|
+
ariaDescribedBy,
|
|
15070
14961
|
className,
|
|
15071
14962
|
editable = true,
|
|
15072
14963
|
autofocus = false,
|
|
@@ -15078,6 +14969,7 @@ var UEditor = React15.forwardRef(({
|
|
|
15078
14969
|
maxCharacters,
|
|
15079
14970
|
minHeight = "200px",
|
|
15080
14971
|
maxHeight = "auto",
|
|
14972
|
+
expandWideTables = true,
|
|
15081
14973
|
variant = "default",
|
|
15082
14974
|
rounded = true,
|
|
15083
14975
|
fontFamilies,
|
|
@@ -15105,8 +14997,10 @@ var UEditor = React15.forwardRef(({
|
|
|
15105
14997
|
const editorInstanceRef = useRef10(null);
|
|
15106
14998
|
const formulaRangePickRef = useRef10(null);
|
|
15107
14999
|
const formulaRangeSurfaceRef = useRef10(null);
|
|
15108
|
-
const [formulaRangeHighlight, setFormulaRangeHighlight] =
|
|
15109
|
-
const [isMenuBarVisible, setIsMenuBarVisible] =
|
|
15000
|
+
const [formulaRangeHighlight, setFormulaRangeHighlight] = React17.useState(null);
|
|
15001
|
+
const [isMenuBarVisible, setIsMenuBarVisible] = React17.useState(showMenuBar);
|
|
15002
|
+
const widthBoundaryRef = useRef10(null);
|
|
15003
|
+
const editorShellRef = useRef10(null);
|
|
15110
15004
|
useEffect10(() => {
|
|
15111
15005
|
setIsMenuBarVisible(showMenuBar);
|
|
15112
15006
|
}, [showMenuBar]);
|
|
@@ -15116,7 +15010,7 @@ var UEditor = React15.forwardRef(({
|
|
|
15116
15010
|
onJsonChange,
|
|
15117
15011
|
outputDebounceMs
|
|
15118
15012
|
});
|
|
15119
|
-
const scheduleFormulaRecalculate =
|
|
15013
|
+
const scheduleFormulaRecalculate = React17.useCallback((editor2, options) => {
|
|
15120
15014
|
if (editor2.isDestroyed || scheduledFormulaRecalculateRef.current) return;
|
|
15121
15015
|
if (!options?.force && isEditingTableFormulaText(editor2)) return;
|
|
15122
15016
|
scheduledFormulaRecalculateRef.current = true;
|
|
@@ -15150,14 +15044,15 @@ var UEditor = React15.forwardRef(({
|
|
|
15150
15044
|
maxImageFileSize,
|
|
15151
15045
|
allowedImageMimeTypes,
|
|
15152
15046
|
fallbackToDataUrl,
|
|
15047
|
+
onImageUploadError,
|
|
15153
15048
|
editable,
|
|
15154
15049
|
fetchMetadata
|
|
15155
15050
|
}),
|
|
15156
15051
|
...extraExtensions ?? []
|
|
15157
15052
|
],
|
|
15158
|
-
[getPortalContainer, effectivePlaceholder, t, maxCharacters, uploadImage, resolvedUploadFile, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable, fetchMetadata, extraExtensions]
|
|
15053
|
+
[getPortalContainer, effectivePlaceholder, t, maxCharacters, uploadImage, resolvedUploadFile, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, onImageUploadError, editable, fetchMetadata, extraExtensions]
|
|
15159
15054
|
);
|
|
15160
|
-
const syncFormulaRangeHighlight =
|
|
15055
|
+
const syncFormulaRangeHighlight = React17.useCallback((pickState) => {
|
|
15161
15056
|
const container = formulaRangeSurfaceRef.current;
|
|
15162
15057
|
setFormulaRangeHighlight(container && pickState ? getFormulaRangePickHighlight(container, pickState) : null);
|
|
15163
15058
|
}, []);
|
|
@@ -15229,9 +15124,6 @@ var UEditor = React15.forwardRef(({
|
|
|
15229
15124
|
clearSelectedTableCellFormula(activeEditor);
|
|
15230
15125
|
return true;
|
|
15231
15126
|
}
|
|
15232
|
-
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
15233
|
-
event.stopPropagation();
|
|
15234
|
-
}
|
|
15235
15127
|
return false;
|
|
15236
15128
|
},
|
|
15237
15129
|
click: (view, event) => {
|
|
@@ -15251,7 +15143,11 @@ var UEditor = React15.forwardRef(({
|
|
|
15251
15143
|
}
|
|
15252
15144
|
},
|
|
15253
15145
|
attributes: {
|
|
15254
|
-
class: UEDITOR_PROSEMIRROR_CLASS_NAME
|
|
15146
|
+
class: UEDITOR_PROSEMIRROR_CLASS_NAME,
|
|
15147
|
+
role: editable ? "textbox" : "document",
|
|
15148
|
+
...editable ? { "aria-multiline": "true" } : { "aria-readonly": "true" },
|
|
15149
|
+
...ariaLabelledBy ? { "aria-labelledby": ariaLabelledBy } : { "aria-label": ariaLabel ?? t("accessibility.editorLabel") },
|
|
15150
|
+
...ariaDescribedBy ? { "aria-describedby": ariaDescribedBy } : null
|
|
15255
15151
|
}
|
|
15256
15152
|
},
|
|
15257
15153
|
onUpdate: ({ editor: editor2, transaction, appendedTransactions }) => {
|
|
@@ -15297,23 +15193,28 @@ var UEditor = React15.forwardRef(({
|
|
|
15297
15193
|
apply: t("tableMenu.apply"),
|
|
15298
15194
|
cancel: t("imageInput.cancelBtn")
|
|
15299
15195
|
});
|
|
15196
|
+
useWideTableLayout(editor, expandWideTables, widthBoundaryRef, editorShellRef, editorContentRef);
|
|
15300
15197
|
useImperativeHandle4(
|
|
15301
15198
|
ref,
|
|
15302
15199
|
() => ({
|
|
15303
15200
|
editor,
|
|
15304
15201
|
prepareContentForSave: async ({ throwOnError = false } = {}) => {
|
|
15305
|
-
|
|
15306
|
-
|
|
15307
|
-
|
|
15202
|
+
const htmlSnapshot = editor?.getHTML() ?? content ?? "";
|
|
15203
|
+
if (!inFlightPrepareRef.current || inFlightPrepareRef.current.html !== htmlSnapshot) {
|
|
15204
|
+
let trackedPromise;
|
|
15205
|
+
trackedPromise = prepareUEditorContentForSave({
|
|
15308
15206
|
html: htmlSnapshot,
|
|
15309
15207
|
uploadImageForSave,
|
|
15310
15208
|
uploadFileForSave,
|
|
15311
15209
|
uploadConcurrency: uploadImageConcurrency
|
|
15312
15210
|
}).finally(() => {
|
|
15313
|
-
inFlightPrepareRef.current
|
|
15211
|
+
if (inFlightPrepareRef.current?.promise === trackedPromise) {
|
|
15212
|
+
inFlightPrepareRef.current = null;
|
|
15213
|
+
}
|
|
15314
15214
|
});
|
|
15215
|
+
inFlightPrepareRef.current = { html: htmlSnapshot, promise: trackedPromise };
|
|
15315
15216
|
}
|
|
15316
|
-
const result = await inFlightPrepareRef.current;
|
|
15217
|
+
const result = await inFlightPrepareRef.current.promise;
|
|
15317
15218
|
if (throwOnError && result.errors.length > 0) {
|
|
15318
15219
|
throw new UEditorPrepareContentForSaveError(result);
|
|
15319
15220
|
}
|
|
@@ -15352,15 +15253,18 @@ var UEditor = React15.forwardRef(({
|
|
|
15352
15253
|
return /* @__PURE__ */ jsx20(UEditorPortalProvider, { getPortalContainer, children: /* @__PURE__ */ jsx20(
|
|
15353
15254
|
"div",
|
|
15354
15255
|
{
|
|
15256
|
+
role: "status",
|
|
15257
|
+
"aria-live": "polite",
|
|
15355
15258
|
className: cn("w-full border bg-background flex items-center justify-center text-muted-foreground", className),
|
|
15356
15259
|
style: { minHeight },
|
|
15357
15260
|
children: t("loading")
|
|
15358
15261
|
}
|
|
15359
15262
|
) });
|
|
15360
15263
|
}
|
|
15361
|
-
return /* @__PURE__ */ jsx20(UEditorPortalProvider, { getPortalContainer, children: /* @__PURE__ */ jsxs17(
|
|
15264
|
+
return /* @__PURE__ */ jsx20(UEditorPortalProvider, { getPortalContainer, children: /* @__PURE__ */ jsx20("div", { ref: widthBoundaryRef, "data-ueditor-width-boundary": "", className: "w-full", children: /* @__PURE__ */ jsxs17(
|
|
15362
15265
|
"div",
|
|
15363
15266
|
{
|
|
15267
|
+
ref: editorShellRef,
|
|
15364
15268
|
className: cn(
|
|
15365
15269
|
"group relative flex flex-col text-card-foreground",
|
|
15366
15270
|
editable ? [
|
|
@@ -15375,7 +15279,7 @@ var UEditor = React15.forwardRef(({
|
|
|
15375
15279
|
),
|
|
15376
15280
|
children: [
|
|
15377
15281
|
editable && (showMenuBar || showToolbar || showBubbleMenu) ? /* @__PURE__ */ jsxs17(EditorUiRenderStateProvider, { editor, children: [
|
|
15378
|
-
isMenuBarVisible && /* @__PURE__ */ jsx20(
|
|
15282
|
+
isMenuBarVisible && /* @__PURE__ */ jsx20(React17.Suspense, { fallback: null, children: /* @__PURE__ */ jsx20(
|
|
15379
15283
|
LazyMenuBar,
|
|
15380
15284
|
{
|
|
15381
15285
|
editor,
|
|
@@ -15384,6 +15288,8 @@ var UEditor = React15.forwardRef(({
|
|
|
15384
15288
|
imageInsertMode,
|
|
15385
15289
|
maxImageFileSize,
|
|
15386
15290
|
allowedImageMimeTypes,
|
|
15291
|
+
onImageUploadError,
|
|
15292
|
+
fallbackToDataUrl,
|
|
15387
15293
|
onSave,
|
|
15388
15294
|
onExport,
|
|
15389
15295
|
onSourceCode,
|
|
@@ -15402,6 +15308,8 @@ var UEditor = React15.forwardRef(({
|
|
|
15402
15308
|
imageInsertMode,
|
|
15403
15309
|
maxImageFileSize,
|
|
15404
15310
|
allowedImageMimeTypes,
|
|
15311
|
+
onImageUploadError,
|
|
15312
|
+
fallbackToDataUrl,
|
|
15405
15313
|
fontFamilies,
|
|
15406
15314
|
defaultFontFamily,
|
|
15407
15315
|
fontSizes,
|
|
@@ -15427,7 +15335,10 @@ var UEditor = React15.forwardRef(({
|
|
|
15427
15335
|
editorContentRef.current = node;
|
|
15428
15336
|
formulaRangeSurfaceRef.current = node;
|
|
15429
15337
|
},
|
|
15430
|
-
className:
|
|
15338
|
+
className: cn(
|
|
15339
|
+
"relative flex-1 overflow-y-auto",
|
|
15340
|
+
expandWideTables && "[&_.tableWrapper]:!overflow-visible [&_.tableWrapper]:!pb-0"
|
|
15341
|
+
),
|
|
15431
15342
|
style: {
|
|
15432
15343
|
fontFamily: defaultFontFamily,
|
|
15433
15344
|
minHeight: editable ? minHeight : void 0,
|
|
@@ -15506,7 +15417,7 @@ var UEditor = React15.forwardRef(({
|
|
|
15506
15417
|
showFooter && showCharacterCount && /* @__PURE__ */ jsx20(CharacterCountDisplay, { editor, maxCharacters })
|
|
15507
15418
|
]
|
|
15508
15419
|
}
|
|
15509
|
-
) });
|
|
15420
|
+
) }) });
|
|
15510
15421
|
});
|
|
15511
15422
|
UEditor.displayName = "UEditor";
|
|
15512
15423
|
var UEditor_default = UEditor;
|
|
@@ -15518,4 +15429,4 @@ export {
|
|
|
15518
15429
|
prepareUEditorContentForSave,
|
|
15519
15430
|
UEditor_default
|
|
15520
15431
|
};
|
|
15521
|
-
//# sourceMappingURL=chunk-
|
|
15432
|
+
//# sourceMappingURL=chunk-57BKIC6J.js.map
|