@underverse-ui/underverse 2.0.28 → 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-Y4X6CAZY.js → chunk-2P7TSXEE.js} +82 -25
- package/dist/chunk-2P7TSXEE.js.map +1 -0
- package/dist/{chunk-KTOXCD6J.js → chunk-37MHVJMV.js} +1078 -90
- package/dist/chunk-37MHVJMV.js.map +1 -0
- package/dist/{chunk-QYFXYDBK.js → chunk-57BKIC6J.js} +1306 -888
- 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 +3275 -1628
- 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-CFIWMBAA.js → menu-bar-DPCNNUX5.js} +227 -54
- package/dist/menu-bar-DPCNNUX5.js.map +1 -0
- package/dist/ueditor.cjs +9803 -8169
- 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-A4GUPKHM.js.map +0 -1
- package/dist/chunk-KTOXCD6J.js.map +0 -1
- package/dist/chunk-LRIRY4DG.js.map +0 -1
- package/dist/chunk-QYFXYDBK.js.map +0 -1
- package/dist/chunk-Y4X6CAZY.js.map +0 -1
- package/dist/menu-bar-CFIWMBAA.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,12 +1,13 @@
|
|
|
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,
|
|
8
8
|
CellBorderIcon,
|
|
9
9
|
ClipboardImages,
|
|
10
|
+
DEFAULT_RESPONSIVE_TABLE_WIDTH_BP,
|
|
10
11
|
DEFAULT_TABLE_ROW_HEIGHT,
|
|
11
12
|
DropdownMenu,
|
|
12
13
|
DropdownMenuItem,
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
MIN_TABLE_ROW_HEIGHT,
|
|
19
20
|
Popover,
|
|
20
21
|
ROW_RESIZE_LINE_THICKNESS,
|
|
22
|
+
TABLE_WIDTH_BASIS_POINTS,
|
|
21
23
|
TextColorIcon,
|
|
22
24
|
ToolbarButton,
|
|
23
25
|
UEDITOR_PROSEMIRROR_CLASS_NAME,
|
|
@@ -26,42 +28,72 @@ import {
|
|
|
26
28
|
applyImageLayout,
|
|
27
29
|
applyImageWidthPreset,
|
|
28
30
|
applyTableAlignment,
|
|
31
|
+
buildTableFormulaDependencyGraph,
|
|
32
|
+
clampResponsiveTableWidthBp,
|
|
29
33
|
clearTableColumnAt,
|
|
30
34
|
clearTableRowAt,
|
|
35
|
+
deleteResponsiveColumnLayout,
|
|
31
36
|
deleteSelectedImage,
|
|
32
37
|
dispatchTableLayoutChange,
|
|
33
38
|
duplicateTableColumnAt,
|
|
34
39
|
duplicateTableRowAt,
|
|
40
|
+
evaluateBasicTableFormula,
|
|
35
41
|
expandTableFromCell,
|
|
36
42
|
findTableNodeInfoFromState,
|
|
37
43
|
findTableRowNodeInfo,
|
|
44
|
+
formatBasisPointsAsPercentage,
|
|
45
|
+
formatFormulaError,
|
|
46
|
+
formatTableFormulaDisplayValue,
|
|
47
|
+
getAffectedTableFormulaLabels,
|
|
38
48
|
getDefaultFontSizes,
|
|
39
49
|
getDefaultLineHeights,
|
|
50
|
+
getLegacyTableColumnWeights,
|
|
51
|
+
getLogicalTableColumnCount,
|
|
40
52
|
getRelativeBoundaryMetrics,
|
|
41
53
|
getRelativeCellMetrics,
|
|
42
54
|
getRelativeSelectedCellsMetrics,
|
|
55
|
+
getResponsiveTableOffsetBp,
|
|
56
|
+
getResponsiveTableWidthBp,
|
|
43
57
|
getSelectionTableCell,
|
|
58
|
+
getTableCellRangeLabels,
|
|
59
|
+
getTableColumnRatios,
|
|
60
|
+
getTableFormulaRecalculationOrder,
|
|
61
|
+
getTableFormulaReferences,
|
|
62
|
+
indexToColumnName,
|
|
63
|
+
insertResponsiveColumnLayout,
|
|
44
64
|
isCrossRealmElement,
|
|
45
65
|
isCrossRealmHTMLElement,
|
|
46
66
|
isCrossRealmNode,
|
|
47
67
|
isCrossRealmTable,
|
|
48
68
|
isCrossRealmTableCell,
|
|
49
69
|
isCrossRealmTableRow,
|
|
70
|
+
isDraftTableFormula,
|
|
50
71
|
isPointOverRenderedText,
|
|
51
72
|
isRowResizeHotspot,
|
|
52
73
|
isRowResizingGlobal,
|
|
53
74
|
isSafeUEditorUrl,
|
|
54
75
|
mergeTableCellsPreservingColumnWidths,
|
|
76
|
+
moveResponsiveColumnRatio,
|
|
77
|
+
normalizeColumnRatios,
|
|
55
78
|
normalizeStyleValue,
|
|
79
|
+
normalizeTableFormula,
|
|
80
|
+
normalizeTableWidthMode,
|
|
81
|
+
parseColumnRatios,
|
|
82
|
+
parsePercentageToBasisPoints,
|
|
83
|
+
parseTableCellRange,
|
|
56
84
|
resetImageSize,
|
|
57
85
|
resolveColumnResizeTarget,
|
|
58
86
|
resolveEventElement,
|
|
87
|
+
resolveResponsiveTableOffsetBp,
|
|
59
88
|
resolveRowResizeTarget,
|
|
89
|
+
rewriteTableNodeFormulaReferencesForDeletion,
|
|
90
|
+
rewriteTableNodeFormulaReferencesForInsertion,
|
|
91
|
+
rewriteTableNodeFormulaReferencesForMove,
|
|
60
92
|
runTableCommandAtCellPos,
|
|
61
93
|
sanitizeUEditorUrl,
|
|
62
94
|
useEditorColors,
|
|
63
95
|
useSharedEditorUiRenderState
|
|
64
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-37MHVJMV.js";
|
|
65
97
|
import {
|
|
66
98
|
Tooltip,
|
|
67
99
|
UEditorPortalProvider,
|
|
@@ -71,7 +103,7 @@ import {
|
|
|
71
103
|
resolveUEditorPortalContainer,
|
|
72
104
|
useSmartTranslations,
|
|
73
105
|
useUEditorPortalContainerGetter
|
|
74
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-ZP7F4ZD7.js";
|
|
75
107
|
|
|
76
108
|
// src/components/UEditor/prepare-content-for-save.ts
|
|
77
109
|
var MIME_EXTENSION_MAP = {
|
|
@@ -124,16 +156,16 @@ function createFileFromDataImageUrl(dataUrl, index) {
|
|
|
124
156
|
const name = `ueditor-image-${index + 1}.${extension}`;
|
|
125
157
|
return new File([bytes], name, { type: parsed.mime });
|
|
126
158
|
}
|
|
127
|
-
function normalizeUploadResult(result) {
|
|
159
|
+
function normalizeUploadResult(result, kind) {
|
|
128
160
|
if (typeof result === "string") {
|
|
129
|
-
const url2 = sanitizeUEditorUrl(result,
|
|
161
|
+
const url2 = sanitizeUEditorUrl(result, kind);
|
|
130
162
|
if (!url2) throw new Error("Upload handler returned an empty URL.");
|
|
131
163
|
return { url: url2 };
|
|
132
164
|
}
|
|
133
165
|
if (!result || typeof result !== "object") {
|
|
134
166
|
throw new Error("Upload handler returned invalid result.");
|
|
135
167
|
}
|
|
136
|
-
const url = typeof result.url === "string" ? sanitizeUEditorUrl(result.url,
|
|
168
|
+
const url = typeof result.url === "string" ? sanitizeUEditorUrl(result.url, kind) : "";
|
|
137
169
|
if (!url) throw new Error("Upload handler object result is missing `url`.");
|
|
138
170
|
const { url: _ignoredUrl, ...rest } = result;
|
|
139
171
|
const meta = Object.keys(rest).length > 0 ? rest : void 0;
|
|
@@ -188,11 +220,13 @@ function normalizeImageUrl(url) {
|
|
|
188
220
|
}
|
|
189
221
|
function replaceSrcInTag(match, nextSrc) {
|
|
190
222
|
if (!match.srcAttr) return match.tag;
|
|
191
|
-
const { start, end
|
|
192
|
-
const
|
|
193
|
-
const srcAttr = quote ? `src=${quote}${escaped}${quote}` : `src=${escaped}`;
|
|
223
|
+
const { start, end } = match.srcAttr;
|
|
224
|
+
const srcAttr = `src="${escapeHtmlAttribute(nextSrc)}"`;
|
|
194
225
|
return `${match.tag.slice(0, start)}${srcAttr}${match.tag.slice(end)}`;
|
|
195
226
|
}
|
|
227
|
+
function escapeHtmlAttribute(value) {
|
|
228
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
229
|
+
}
|
|
196
230
|
function collectImgTagMatches(html) {
|
|
197
231
|
const matches = [];
|
|
198
232
|
const imgRegex = /<img\b[^>]*>/gi;
|
|
@@ -310,13 +344,14 @@ function collectFileCardMatches(html) {
|
|
|
310
344
|
}
|
|
311
345
|
function replaceFileCardAttrs(tag, nextUrl) {
|
|
312
346
|
let result = tag;
|
|
347
|
+
const escapedUrl = escapeHtmlAttribute(nextUrl);
|
|
313
348
|
const hrefRegex = /(\bhref\s*=\s*)(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+)/i;
|
|
314
349
|
const dataSrcRegex = /(\bdata-src\s*=\s*)(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+)/i;
|
|
315
350
|
if (hrefRegex.test(result)) {
|
|
316
|
-
result = result.replace(hrefRegex, `$1"${
|
|
351
|
+
result = result.replace(hrefRegex, `$1"${escapedUrl}"`);
|
|
317
352
|
}
|
|
318
353
|
if (dataSrcRegex.test(result)) {
|
|
319
|
-
result = result.replace(dataSrcRegex, `$1"${
|
|
354
|
+
result = result.replace(dataSrcRegex, `$1"${escapedUrl}"`);
|
|
320
355
|
}
|
|
321
356
|
return result;
|
|
322
357
|
}
|
|
@@ -386,7 +421,7 @@ async function prepareUEditorContentForSave({
|
|
|
386
421
|
try {
|
|
387
422
|
const file = createFileFromDataImageUrl(candidate.src, candidate.index);
|
|
388
423
|
const uploadResult = await uploadImageForSave(file);
|
|
389
|
-
const normalized = normalizeUploadResult(uploadResult);
|
|
424
|
+
const normalized = normalizeUploadResult(uploadResult, "image");
|
|
390
425
|
return { candidate, file, ...normalized };
|
|
391
426
|
} catch (error) {
|
|
392
427
|
return { candidate, error: getErrorReason(error) };
|
|
@@ -433,7 +468,7 @@ async function prepareUEditorContentForSave({
|
|
|
433
468
|
try {
|
|
434
469
|
const file = createFileFromDataUrl(candidate.src, candidate.fileName);
|
|
435
470
|
const uploadResult = await uploadFn(file);
|
|
436
|
-
const normalized = normalizeUploadResult(uploadResult);
|
|
471
|
+
const normalized = normalizeUploadResult(uploadResult, "file");
|
|
437
472
|
return { candidate, file, ...normalized };
|
|
438
473
|
} catch (error) {
|
|
439
474
|
return { candidate, error: getErrorReason(error) };
|
|
@@ -486,7 +521,7 @@ async function prepareUEditorContentForSave({
|
|
|
486
521
|
}
|
|
487
522
|
|
|
488
523
|
// src/components/UEditor/UEditor.tsx
|
|
489
|
-
import
|
|
524
|
+
import React17, { useEffect as useEffect10, useImperativeHandle as useImperativeHandle4, useMemo as useMemo2, useRef as useRef10 } from "react";
|
|
490
525
|
import { useEditor, EditorContent } from "@tiptap/react";
|
|
491
526
|
|
|
492
527
|
// src/components/UEditor/extensions.ts
|
|
@@ -521,7 +556,7 @@ import { NodeViewWrapper, NodeViewContent } from "@tiptap/react";
|
|
|
521
556
|
import React from "react";
|
|
522
557
|
import { jsx } from "react/jsx-runtime";
|
|
523
558
|
var LazyBaseEmojiPicker = React.lazy(async () => {
|
|
524
|
-
const { EmojiPicker: EmojiPicker2 } = await import("./EmojiPicker-
|
|
559
|
+
const { EmojiPicker: EmojiPicker2 } = await import("./EmojiPicker-ISJ6RXYG.js");
|
|
525
560
|
return { default: EmojiPicker2 };
|
|
526
561
|
});
|
|
527
562
|
var EmojiPicker = ({ onSelect }) => {
|
|
@@ -558,7 +593,8 @@ var CalloutView = ({ node, updateAttributes, selected }) => {
|
|
|
558
593
|
"button",
|
|
559
594
|
{
|
|
560
595
|
type: "button",
|
|
561
|
-
|
|
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",
|
|
562
598
|
children: currentEmoji
|
|
563
599
|
}
|
|
564
600
|
),
|
|
@@ -572,9 +608,11 @@ var CalloutView = ({ node, updateAttributes, selected }) => {
|
|
|
572
608
|
{
|
|
573
609
|
type: "button",
|
|
574
610
|
title: col.name,
|
|
611
|
+
"aria-label": `${t("callout.backgroundColor")}: ${col.name}`,
|
|
612
|
+
"aria-pressed": currentBgColor === col.color,
|
|
575
613
|
onClick: () => updateAttributes({ backgroundColor: col.color }),
|
|
576
614
|
className: cn(
|
|
577
|
-
"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",
|
|
578
616
|
currentBgColor === col.color ? "border-primary ring-2 ring-primary/30" : "border-border/60"
|
|
579
617
|
),
|
|
580
618
|
style: { backgroundColor: col.color }
|
|
@@ -1062,12 +1100,13 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
1062
1100
|
e.preventDefault();
|
|
1063
1101
|
e.stopPropagation();
|
|
1064
1102
|
if (!safeSrc) return;
|
|
1065
|
-
const
|
|
1103
|
+
const ownerDocument = editor.view.dom.ownerDocument;
|
|
1104
|
+
const link = ownerDocument.createElement("a");
|
|
1066
1105
|
link.href = safeSrc;
|
|
1067
1106
|
link.download = fileName || "download";
|
|
1068
|
-
|
|
1107
|
+
ownerDocument.body.appendChild(link);
|
|
1069
1108
|
link.click();
|
|
1070
|
-
|
|
1109
|
+
ownerDocument.body.removeChild(link);
|
|
1071
1110
|
};
|
|
1072
1111
|
const hasInlineUpload = safeSrc.startsWith("data:") && Boolean(uploadFn);
|
|
1073
1112
|
const handleRetryUpload = (event) => {
|
|
@@ -1081,18 +1120,19 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
1081
1120
|
NodeViewWrapper3,
|
|
1082
1121
|
{
|
|
1083
1122
|
className: cn(
|
|
1084
|
-
"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",
|
|
1085
1124
|
selected && "ring-2 ring-primary/45 border-primary/20 shadow-sm"
|
|
1086
1125
|
),
|
|
1087
|
-
|
|
1126
|
+
role: "group",
|
|
1127
|
+
"aria-label": fileName || t("fileCard.unnamed"),
|
|
1088
1128
|
children: [
|
|
1089
1129
|
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3.5 min-w-0", children: [
|
|
1090
|
-
/* @__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" }) }),
|
|
1091
1131
|
/* @__PURE__ */ jsxs3("div", { className: "min-w-0", children: [
|
|
1092
1132
|
/* @__PURE__ */ jsx4("div", { className: "text-sm font-semibold text-foreground truncate break-all", children: fileName || t("fileCard.unnamed") }),
|
|
1093
1133
|
/* @__PURE__ */ jsxs3("div", { className: "text-xs text-muted-foreground flex items-center gap-2 mt-0.5", children: [
|
|
1094
1134
|
fileSize ? /* @__PURE__ */ jsx4("span", { children: formatBytes(fileSize) }) : null,
|
|
1095
|
-
hasInlineUpload && /* @__PURE__ */ jsx4("span", { className: cn(
|
|
1135
|
+
hasInlineUpload && /* @__PURE__ */ jsx4("span", { "aria-live": "polite", className: cn(
|
|
1096
1136
|
"font-medium truncate max-w-50",
|
|
1097
1137
|
uploadError ? "text-destructive" : "text-primary animate-pulse"
|
|
1098
1138
|
), children: uploadError ? `${t("fileCard.uploadFailed") || "T\u1EA3i l\xEAn th\u1EA5t b\u1EA1i"}: ${uploadError}` : t("fileCard.uploading") }),
|
|
@@ -1103,7 +1143,7 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
1103
1143
|
onClick: handleRetryUpload,
|
|
1104
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",
|
|
1105
1145
|
children: [
|
|
1106
|
-
/* @__PURE__ */ jsx4(RefreshCw2, { className: "h-3 w-3" }),
|
|
1146
|
+
/* @__PURE__ */ jsx4(RefreshCw2, { "aria-hidden": "true", className: "h-3 w-3" }),
|
|
1107
1147
|
t("fileCard.retryUpload")
|
|
1108
1148
|
]
|
|
1109
1149
|
}
|
|
@@ -1116,8 +1156,9 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
1116
1156
|
{
|
|
1117
1157
|
type: "button",
|
|
1118
1158
|
onClick: handleDownload,
|
|
1119
|
-
|
|
1120
|
-
|
|
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" })
|
|
1121
1162
|
}
|
|
1122
1163
|
)
|
|
1123
1164
|
]
|
|
@@ -1375,6 +1416,7 @@ import { Node as Node5, mergeAttributes as mergeAttributes5 } from "@tiptap/core
|
|
|
1375
1416
|
import { ReactNodeViewRenderer as ReactNodeViewRenderer5 } from "@tiptap/react";
|
|
1376
1417
|
|
|
1377
1418
|
// src/components/UEditor/FormRadioView.tsx
|
|
1419
|
+
import { useId } from "react";
|
|
1378
1420
|
import { NodeViewWrapper as NodeViewWrapper5 } from "@tiptap/react";
|
|
1379
1421
|
import { Settings } from "lucide-react";
|
|
1380
1422
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
@@ -1383,6 +1425,8 @@ var FormRadioView = ({ node, updateAttributes, editor, selected }) => {
|
|
|
1383
1425
|
const isChecked = !!node.attrs.checked;
|
|
1384
1426
|
const isEditable = editor.isEditable;
|
|
1385
1427
|
const groupName = node.attrs.name || "radio-group";
|
|
1428
|
+
const groupInputId = useId();
|
|
1429
|
+
const radioLabel = `${t("menubar.formRadio")} \u2014 ${node.attrs.value || groupName}`;
|
|
1386
1430
|
const handleSelect = (e) => {
|
|
1387
1431
|
e.preventDefault();
|
|
1388
1432
|
e.stopPropagation();
|
|
@@ -1408,6 +1452,7 @@ var FormRadioView = ({ node, updateAttributes, editor, selected }) => {
|
|
|
1408
1452
|
{
|
|
1409
1453
|
role: "radio",
|
|
1410
1454
|
"aria-checked": isChecked,
|
|
1455
|
+
"aria-label": radioLabel,
|
|
1411
1456
|
tabIndex: isEditable ? 0 : -1,
|
|
1412
1457
|
onClick: handleSelect,
|
|
1413
1458
|
onKeyDown: handleKeyDown2,
|
|
@@ -1436,17 +1481,21 @@ var FormRadioView = ({ node, updateAttributes, editor, selected }) => {
|
|
|
1436
1481
|
"button",
|
|
1437
1482
|
{
|
|
1438
1483
|
type: "button",
|
|
1484
|
+
"aria-label": t("radio.editGroup") || "Edit Group",
|
|
1439
1485
|
className: "p-0.5 rounded hover:bg-muted text-muted-foreground hover:text-foreground transition-colors outline-none cursor-pointer",
|
|
1440
1486
|
title: t("radio.editGroup") || "Edit Group",
|
|
1441
1487
|
children: /* @__PURE__ */ jsx6(Settings, { className: "w-3.5 h-3.5" })
|
|
1442
1488
|
}
|
|
1443
1489
|
),
|
|
1444
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: [
|
|
1445
|
-
/* @__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" }),
|
|
1446
1492
|
/* @__PURE__ */ jsx6(
|
|
1447
1493
|
"input",
|
|
1448
1494
|
{
|
|
1449
1495
|
type: "text",
|
|
1496
|
+
id: groupInputId,
|
|
1497
|
+
name: "radio-group-name",
|
|
1498
|
+
autoComplete: "off",
|
|
1450
1499
|
value: groupName,
|
|
1451
1500
|
onChange: (e) => updateAttributes({ name: e.target.value }),
|
|
1452
1501
|
className: `w-full rounded-lg bg-background px-2 py-1.5 text-sm text-foreground ${formControlOutlineClass}`
|
|
@@ -1461,6 +1510,12 @@ var FormRadioView = ({ node, updateAttributes, editor, selected }) => {
|
|
|
1461
1510
|
};
|
|
1462
1511
|
|
|
1463
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
|
+
}
|
|
1464
1519
|
var FormRadio = Node5.create({
|
|
1465
1520
|
name: "formRadio",
|
|
1466
1521
|
group: "inline",
|
|
@@ -1493,7 +1548,7 @@ var FormRadio = Node5.create({
|
|
|
1493
1548
|
},
|
|
1494
1549
|
id: {
|
|
1495
1550
|
default: null,
|
|
1496
|
-
parseHTML: (element) => element.getAttribute("data-id") || element.getAttribute("id") ||
|
|
1551
|
+
parseHTML: (element) => element.getAttribute("data-id") || element.getAttribute("id") || createFormRadioId(),
|
|
1497
1552
|
renderHTML: (attributes) => {
|
|
1498
1553
|
if (!attributes.id) return {};
|
|
1499
1554
|
return {
|
|
@@ -1552,10 +1607,15 @@ var FormRadio = Node5.create({
|
|
|
1552
1607
|
setFormRadio: (attributes) => ({ commands }) => {
|
|
1553
1608
|
return commands.insertContent({
|
|
1554
1609
|
type: this.name,
|
|
1555
|
-
attrs:
|
|
1610
|
+
attrs: {
|
|
1611
|
+
...attributes,
|
|
1612
|
+
id: attributes?.id || createFormRadioId(),
|
|
1613
|
+
name: attributes?.name || "radio-group"
|
|
1614
|
+
}
|
|
1556
1615
|
});
|
|
1557
1616
|
},
|
|
1558
1617
|
checkFormRadio: (id) => ({ tr, dispatch }) => {
|
|
1618
|
+
if (!id) return false;
|
|
1559
1619
|
if (!dispatch) return true;
|
|
1560
1620
|
let targetGroupName = "";
|
|
1561
1621
|
let targetPos = -1;
|
|
@@ -1607,7 +1667,7 @@ import { Gapcursor } from "@tiptap/extension-gapcursor";
|
|
|
1607
1667
|
import { Extension } from "@tiptap/core";
|
|
1608
1668
|
import { Suggestion } from "@tiptap/suggestion";
|
|
1609
1669
|
import { ReactRenderer } from "@tiptap/react";
|
|
1610
|
-
import
|
|
1670
|
+
import React5, { forwardRef, useEffect as useEffect3, useImperativeHandle, useRef as useRef2 } from "react";
|
|
1611
1671
|
import {
|
|
1612
1672
|
FileCode,
|
|
1613
1673
|
Heading1,
|
|
@@ -1692,9 +1752,9 @@ var DEFAULT_MESSAGES = {
|
|
|
1692
1752
|
formRadioDesc: "Insert an interactive radio button field"
|
|
1693
1753
|
};
|
|
1694
1754
|
function useResettingIndex(resetToken) {
|
|
1695
|
-
const [state, setState] =
|
|
1755
|
+
const [state, setState] = React5.useState({ resetToken, index: 0 });
|
|
1696
1756
|
const selectedIndex = Object.is(state.resetToken, resetToken) ? state.index : 0;
|
|
1697
|
-
const setSelectedIndex =
|
|
1757
|
+
const setSelectedIndex = React5.useCallback((nextIndex) => {
|
|
1698
1758
|
setState((prev) => {
|
|
1699
1759
|
const prevIndex = Object.is(prev.resetToken, resetToken) ? prev.index : 0;
|
|
1700
1760
|
return {
|
|
@@ -1910,7 +1970,7 @@ function buildSlashCommandItems({
|
|
|
1910
1970
|
title: messages.formRadio,
|
|
1911
1971
|
description: messages.formRadioDesc,
|
|
1912
1972
|
command: run(({ editor, range }) => {
|
|
1913
|
-
getCommandChain(editor, range).setFormRadio(
|
|
1973
|
+
getCommandChain(editor, range).setFormRadio().run();
|
|
1914
1974
|
})
|
|
1915
1975
|
}
|
|
1916
1976
|
].filter((item) => {
|
|
@@ -1922,6 +1982,7 @@ function buildSlashCommandItems({
|
|
|
1922
1982
|
var SlashCommandList = forwardRef((props, ref) => {
|
|
1923
1983
|
const [selectedIndex, setSelectedIndex] = useResettingIndex(props.items);
|
|
1924
1984
|
const listRef = useRef2(null);
|
|
1985
|
+
const listId = React5.useId();
|
|
1925
1986
|
useEffect3(() => {
|
|
1926
1987
|
const selectedElement = listRef.current?.querySelector(`[data-index="${selectedIndex}"]`);
|
|
1927
1988
|
selectedElement?.scrollIntoView({ block: "nearest" });
|
|
@@ -1952,41 +2013,56 @@ var SlashCommandList = forwardRef((props, ref) => {
|
|
|
1952
2013
|
}
|
|
1953
2014
|
}));
|
|
1954
2015
|
if (props.items.length === 0) {
|
|
1955
|
-
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 });
|
|
1956
2017
|
}
|
|
1957
|
-
return /* @__PURE__ */ jsxs5(
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
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
|
+
}
|
|
1977
2054
|
),
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
] });
|
|
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
|
+
);
|
|
1990
2066
|
});
|
|
1991
2067
|
SlashCommandList.displayName = "SlashCommandList";
|
|
1992
2068
|
var SlashCommand = Extension.create({
|
|
@@ -2070,13 +2146,13 @@ import { Extension as Extension2 } from "@tiptap/core";
|
|
|
2070
2146
|
import { Suggestion as Suggestion2 } from "@tiptap/suggestion";
|
|
2071
2147
|
import { ReactRenderer as ReactRenderer2 } from "@tiptap/react";
|
|
2072
2148
|
import { PluginKey as PluginKey2 } from "@tiptap/pm/state";
|
|
2073
|
-
import
|
|
2149
|
+
import React6, { forwardRef as forwardRef2, useImperativeHandle as useImperativeHandle2 } from "react";
|
|
2074
2150
|
import { Smile } from "lucide-react";
|
|
2075
2151
|
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2076
2152
|
function useResettingIndex2(resetToken) {
|
|
2077
|
-
const [state, setState] =
|
|
2153
|
+
const [state, setState] = React6.useState({ resetToken, index: 0 });
|
|
2078
2154
|
const selectedIndex = Object.is(state.resetToken, resetToken) ? state.index : 0;
|
|
2079
|
-
const setSelectedIndex =
|
|
2155
|
+
const setSelectedIndex = React6.useCallback((nextIndex) => {
|
|
2080
2156
|
setState((prev) => {
|
|
2081
2157
|
const prevIndex = Object.is(prev.resetToken, resetToken) ? prev.index : 0;
|
|
2082
2158
|
return {
|
|
@@ -2090,6 +2166,7 @@ function useResettingIndex2(resetToken) {
|
|
|
2090
2166
|
var EmojiList = forwardRef2((props, ref) => {
|
|
2091
2167
|
const t = useSmartTranslations("UEditor");
|
|
2092
2168
|
const [selectedIndex, setSelectedIndex] = useResettingIndex2(props.items);
|
|
2169
|
+
const listId = React6.useId();
|
|
2093
2170
|
const showingCountLabel = formatEmojiCountLabel(t("emojiSuggestion.showingCount"), 64, props.items.length);
|
|
2094
2171
|
useImperativeHandle2(ref, () => ({
|
|
2095
2172
|
onKeyDown: (keyProps) => {
|
|
@@ -2122,28 +2199,42 @@ var EmojiList = forwardRef2((props, ref) => {
|
|
|
2122
2199
|
}
|
|
2123
2200
|
}));
|
|
2124
2201
|
if (props.items.length === 0) {
|
|
2125
|
-
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") });
|
|
2126
|
-
}
|
|
2127
|
-
return /* @__PURE__ */ jsxs6(
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
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
|
+
);
|
|
2147
2238
|
});
|
|
2148
2239
|
EmojiList.displayName = "EmojiList";
|
|
2149
2240
|
var allEmojiItemsPromise = null;
|
|
@@ -2233,7 +2324,7 @@ import { Extension as Extension3 } from "@tiptap/core";
|
|
|
2233
2324
|
import { Suggestion as Suggestion3 } from "@tiptap/suggestion";
|
|
2234
2325
|
import { ReactRenderer as ReactRenderer3 } from "@tiptap/react";
|
|
2235
2326
|
import { PluginKey as PluginKey3 } from "@tiptap/pm/state";
|
|
2236
|
-
import
|
|
2327
|
+
import React7, { forwardRef as forwardRef3, useImperativeHandle as useImperativeHandle3 } from "react";
|
|
2237
2328
|
import { Sigma } from "lucide-react";
|
|
2238
2329
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2239
2330
|
var FORMULA_FUNCTIONS = [
|
|
@@ -2288,8 +2379,9 @@ function isFormulaFunctionSuggestionQuery(query) {
|
|
|
2288
2379
|
}
|
|
2289
2380
|
var FormulaSuggestionList = forwardRef3((props, ref) => {
|
|
2290
2381
|
const t = useSmartTranslations("UEditor");
|
|
2291
|
-
const [selectedIndex, setSelectedIndex] =
|
|
2292
|
-
|
|
2382
|
+
const [selectedIndex, setSelectedIndex] = React7.useState(0);
|
|
2383
|
+
const listId = React7.useId();
|
|
2384
|
+
React7.useEffect(() => {
|
|
2293
2385
|
setSelectedIndex(0);
|
|
2294
2386
|
}, [props.items]);
|
|
2295
2387
|
useImperativeHandle3(ref, () => ({
|
|
@@ -2314,32 +2406,46 @@ var FormulaSuggestionList = forwardRef3((props, ref) => {
|
|
|
2314
2406
|
}
|
|
2315
2407
|
}));
|
|
2316
2408
|
if (props.items.length === 0) {
|
|
2317
|
-
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") });
|
|
2318
|
-
}
|
|
2319
|
-
return /* @__PURE__ */ jsxs7(
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
"
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
className:
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
children:
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
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
|
+
);
|
|
2343
2449
|
});
|
|
2344
2450
|
FormulaSuggestionList.displayName = "FormulaSuggestionList";
|
|
2345
2451
|
function insertFormulaFunction(editor, range, item) {
|
|
@@ -3339,8 +3445,18 @@ var indent_default = Indent;
|
|
|
3339
3445
|
// src/components/UEditor/table-align.ts
|
|
3340
3446
|
import { mergeAttributes as mergeAttributes7 } from "@tiptap/core";
|
|
3341
3447
|
import { Table as Table2 } from "@tiptap/extension-table";
|
|
3342
|
-
import { Plugin as Plugin4, PluginKey as PluginKey5 } from "@tiptap/pm/state";
|
|
3343
|
-
import {
|
|
3448
|
+
import { Plugin as Plugin4, PluginKey as PluginKey5, TextSelection } from "@tiptap/pm/state";
|
|
3449
|
+
import {
|
|
3450
|
+
addColumnAfter as addColumnAfterCommand,
|
|
3451
|
+
addColumnBefore as addColumnBeforeCommand,
|
|
3452
|
+
addRowAfter as addRowAfterCommand,
|
|
3453
|
+
addRowBefore as addRowBeforeCommand,
|
|
3454
|
+
deleteColumn as deleteColumnCommand,
|
|
3455
|
+
deleteRow as deleteRowCommand,
|
|
3456
|
+
selectedRect,
|
|
3457
|
+
tableEditing,
|
|
3458
|
+
tableNodeTypes as tableNodeTypes2
|
|
3459
|
+
} from "@tiptap/pm/tables";
|
|
3344
3460
|
|
|
3345
3461
|
// src/components/UEditor/table-column-resize.ts
|
|
3346
3462
|
import { Plugin as Plugin3 } from "@tiptap/pm/state";
|
|
@@ -3361,14 +3477,10 @@ function getColumnResizeMinWidth(configuredMinWidth) {
|
|
|
3361
3477
|
const normalizedMinWidth = Number.isFinite(configuredMinWidth) && configuredMinWidth > 0 ? Math.round(configuredMinWidth) : MIN_RESIZED_TABLE_COLUMN_WIDTH;
|
|
3362
3478
|
return Math.max(MIN_RESIZED_TABLE_COLUMN_WIDTH, normalizedMinWidth);
|
|
3363
3479
|
}
|
|
3364
|
-
function setColumnStyle(column, width) {
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
return;
|
|
3369
|
-
}
|
|
3370
|
-
column.style.width = `${Math.max(width, MIN_RESIZED_TABLE_COLUMN_WIDTH)}px`;
|
|
3371
|
-
column.style.minWidth = "";
|
|
3480
|
+
function setColumnStyle(column, width, ratio, explicit, responsive) {
|
|
3481
|
+
column.style.width = responsive ? formatBasisPointsAsPercentage(ratio) : `${width}px`;
|
|
3482
|
+
column.style.minWidth = responsive || explicit ? "" : `${width}px`;
|
|
3483
|
+
column.setAttribute("width", String(width));
|
|
3372
3484
|
}
|
|
3373
3485
|
function isTableColumnElement(node) {
|
|
3374
3486
|
return isCrossRealmElement(node) && String(node.tagName).toUpperCase() === "COL";
|
|
@@ -3377,6 +3489,7 @@ function updateDynamicColumns(node, colgroup, table, ownerDocument, overrideCol,
|
|
|
3377
3489
|
let totalWidth = 0;
|
|
3378
3490
|
let nextDOM = colgroup.firstChild;
|
|
3379
3491
|
const row = node.firstChild;
|
|
3492
|
+
const columns = [];
|
|
3380
3493
|
if (row) {
|
|
3381
3494
|
for (let rowCellIndex = 0, col = 0; rowCellIndex < row.childCount; rowCellIndex += 1) {
|
|
3382
3495
|
const { colspan, colwidth } = row.child(rowCellIndex).attrs;
|
|
@@ -3385,7 +3498,11 @@ function updateDynamicColumns(node, colgroup, table, ownerDocument, overrideCol,
|
|
|
3385
3498
|
const width = rawWidth ? Math.max(rawWidth, MIN_RESIZED_TABLE_COLUMN_WIDTH) : null;
|
|
3386
3499
|
totalWidth += width ?? DEFAULT_TABLE_COLUMN_WIDTH;
|
|
3387
3500
|
const colElement = isTableColumnElement(nextDOM) ? nextDOM : colgroup.appendChild(ownerDocument.createElement("col"));
|
|
3388
|
-
|
|
3501
|
+
columns.push({
|
|
3502
|
+
element: colElement,
|
|
3503
|
+
explicit: width !== null,
|
|
3504
|
+
width: width ?? DEFAULT_TABLE_COLUMN_WIDTH
|
|
3505
|
+
});
|
|
3389
3506
|
nextDOM = colElement.nextSibling;
|
|
3390
3507
|
}
|
|
3391
3508
|
}
|
|
@@ -3395,13 +3512,39 @@ function updateDynamicColumns(node, colgroup, table, ownerDocument, overrideCol,
|
|
|
3395
3512
|
nextDOM.parentNode?.removeChild(nextDOM);
|
|
3396
3513
|
nextDOM = after;
|
|
3397
3514
|
}
|
|
3398
|
-
const
|
|
3399
|
-
|
|
3515
|
+
const responsive = normalizeTableWidthMode(node.attrs.widthMode) === "responsive";
|
|
3516
|
+
const columnRatios = getTableColumnRatios(node);
|
|
3517
|
+
columns.forEach(({ element, explicit, width }, index) => {
|
|
3518
|
+
setColumnStyle(element, width, columnRatios[index] ?? 1, explicit, responsive);
|
|
3519
|
+
});
|
|
3520
|
+
if (responsive) {
|
|
3521
|
+
const widthBp = getResponsiveTableWidthBp(node);
|
|
3522
|
+
const offsetBp = getResponsiveTableOffsetBp(node);
|
|
3523
|
+
table.setAttribute("data-table-width-mode", "responsive");
|
|
3524
|
+
table.setAttribute("data-table-width", formatBasisPointsAsPercentage(widthBp));
|
|
3525
|
+
table.setAttribute("data-table-width-bp", String(widthBp));
|
|
3526
|
+
table.setAttribute("data-table-offset", formatBasisPointsAsPercentage(offsetBp));
|
|
3527
|
+
table.setAttribute("data-table-offset-bp", String(offsetBp));
|
|
3528
|
+
table.setAttribute("data-table-column-ratios", columnRatios.join(","));
|
|
3529
|
+
table.style.width = formatBasisPointsAsPercentage(widthBp);
|
|
3530
|
+
table.style.marginLeft = formatBasisPointsAsPercentage(offsetBp);
|
|
3531
|
+
table.style.marginRight = "auto";
|
|
3532
|
+
table.style.minWidth = `${Math.max(1, colgroup.childElementCount) * MIN_RESIZED_TABLE_COLUMN_WIDTH}px`;
|
|
3533
|
+
} else {
|
|
3534
|
+
table.removeAttribute("data-table-width-mode");
|
|
3535
|
+
table.removeAttribute("data-table-width");
|
|
3536
|
+
table.removeAttribute("data-table-width-bp");
|
|
3537
|
+
table.removeAttribute("data-table-offset");
|
|
3538
|
+
table.removeAttribute("data-table-offset-bp");
|
|
3539
|
+
table.removeAttribute("data-table-column-ratios");
|
|
3400
3540
|
table.style.width = `${totalWidth}px`;
|
|
3401
3541
|
table.style.minWidth = "";
|
|
3402
|
-
|
|
3403
|
-
table.style.
|
|
3542
|
+
const tableAlign = node.attrs.textAlign;
|
|
3543
|
+
table.style.marginLeft = tableAlign === "center" || tableAlign === "right" ? "auto" : "0px";
|
|
3544
|
+
table.style.marginRight = tableAlign === "center" ? "auto" : tableAlign === "right" ? "0px" : "auto";
|
|
3404
3545
|
}
|
|
3546
|
+
if (node.attrs.textAlign) table.setAttribute("data-table-align", String(node.attrs.textAlign));
|
|
3547
|
+
else table.removeAttribute("data-table-align");
|
|
3405
3548
|
}
|
|
3406
3549
|
var UEditorTableView = class {
|
|
3407
3550
|
constructor(node, _defaultColumnWidth, maybeView) {
|
|
@@ -3437,7 +3580,40 @@ var UEditorTableView = class {
|
|
|
3437
3580
|
};
|
|
3438
3581
|
function getDraggedWidth(dragging, event) {
|
|
3439
3582
|
const offset = event.clientX - dragging.startX;
|
|
3440
|
-
|
|
3583
|
+
const maximum = dragging.neighborStartWidth === void 0 ? Number.POSITIVE_INFINITY : dragging.startWidth + dragging.neighborStartWidth - dragging.minWidth;
|
|
3584
|
+
return Math.min(maximum, Math.max(dragging.minWidth, Math.round(dragging.startWidth + offset)));
|
|
3585
|
+
}
|
|
3586
|
+
function normalizeColumnWidthsToTotal(values, total, minimum) {
|
|
3587
|
+
const safeTotal = Math.max(values.length * minimum, Math.round(total));
|
|
3588
|
+
const weights = values.map((value) => Number.isFinite(value) && value > 0 ? value : DEFAULT_TABLE_COLUMN_WIDTH);
|
|
3589
|
+
const weightSum = weights.reduce((sum, value) => sum + value, 0);
|
|
3590
|
+
const widths = weights.map((value) => Math.max(minimum, Math.round(value / weightSum * safeTotal)));
|
|
3591
|
+
let difference = safeTotal - widths.reduce((sum, value) => sum + value, 0);
|
|
3592
|
+
while (difference !== 0) {
|
|
3593
|
+
let changed = false;
|
|
3594
|
+
for (let index = widths.length - 1; index >= 0 && difference !== 0; index -= 1) {
|
|
3595
|
+
if (difference < 0 && widths[index] <= minimum) continue;
|
|
3596
|
+
widths[index] += difference > 0 ? 1 : -1;
|
|
3597
|
+
difference += difference > 0 ? -1 : 1;
|
|
3598
|
+
changed = true;
|
|
3599
|
+
}
|
|
3600
|
+
if (!changed) break;
|
|
3601
|
+
}
|
|
3602
|
+
return widths;
|
|
3603
|
+
}
|
|
3604
|
+
function getResizeColumnInfo(state, cell) {
|
|
3605
|
+
const $cell = state.doc.resolve(cell);
|
|
3606
|
+
const table = $cell.node(-1);
|
|
3607
|
+
const map = TableMap.get(table);
|
|
3608
|
+
const start = $cell.start(-1);
|
|
3609
|
+
const nodeAfter = $cell.nodeAfter;
|
|
3610
|
+
if (!nodeAfter) return null;
|
|
3611
|
+
return {
|
|
3612
|
+
col: map.colCount($cell.pos - start) + nodeAfter.attrs.colspan - 1,
|
|
3613
|
+
map,
|
|
3614
|
+
start,
|
|
3615
|
+
table
|
|
3616
|
+
};
|
|
3441
3617
|
}
|
|
3442
3618
|
function getCurrentColWidth(view, cellPos, { colspan, colwidth }) {
|
|
3443
3619
|
const width = colwidth?.[colwidth.length - 1];
|
|
@@ -3506,6 +3682,12 @@ function handleMouseMove(view, event, handleWidth, lastColumnResizable) {
|
|
|
3506
3682
|
if (event.clientX - left <= handleWidth) cell = edgeCell(view, event, "left", handleWidth);
|
|
3507
3683
|
else if (right - event.clientX <= handleWidth) cell = edgeCell(view, event, "right", handleWidth);
|
|
3508
3684
|
}
|
|
3685
|
+
if (cell !== -1) {
|
|
3686
|
+
const info = getResizeColumnInfo(view.state, cell);
|
|
3687
|
+
if (info && normalizeTableWidthMode(info.table.attrs.widthMode) === "responsive" && info.col === info.map.width - 1) {
|
|
3688
|
+
cell = -1;
|
|
3689
|
+
}
|
|
3690
|
+
}
|
|
3509
3691
|
if (cell === pluginState.activeHandle) {
|
|
3510
3692
|
clearHandleHoverTimer();
|
|
3511
3693
|
return;
|
|
@@ -3552,33 +3734,47 @@ function handleMouseLeave(view) {
|
|
|
3552
3734
|
updateHandle(view, -1);
|
|
3553
3735
|
}
|
|
3554
3736
|
}
|
|
3555
|
-
function
|
|
3556
|
-
const
|
|
3557
|
-
|
|
3558
|
-
const map =
|
|
3559
|
-
const start = $cell.start(-1);
|
|
3560
|
-
const nodeAfter = $cell.nodeAfter;
|
|
3561
|
-
if (!nodeAfter) return;
|
|
3562
|
-
const col = map.colCount($cell.pos - start) + nodeAfter.attrs.colspan - 1;
|
|
3737
|
+
function updateColumnWidths(view, cell, widthsByColumn, columnRatios) {
|
|
3738
|
+
const info = getResizeColumnInfo(view.state, cell);
|
|
3739
|
+
if (!info) return;
|
|
3740
|
+
const { map, start, table } = info;
|
|
3563
3741
|
const tr = view.state.tr;
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
if (
|
|
3567
|
-
|
|
3742
|
+
const seenCellPositions = /* @__PURE__ */ new Set();
|
|
3743
|
+
for (const pos of map.map) {
|
|
3744
|
+
if (seenCellPositions.has(pos)) continue;
|
|
3745
|
+
seenCellPositions.add(pos);
|
|
3568
3746
|
const cellNode = table.nodeAt(pos);
|
|
3569
3747
|
if (!cellNode) continue;
|
|
3570
3748
|
const attrs = cellNode.attrs;
|
|
3571
|
-
const index = attrs.colspan === 1 ? 0 : col - map.colCount(pos);
|
|
3572
|
-
if (attrs.colwidth?.[index] === width) continue;
|
|
3573
3749
|
const colwidth = attrs.colwidth ? attrs.colwidth.slice() : Array.from({ length: attrs.colspan }, () => 0);
|
|
3574
|
-
|
|
3750
|
+
const cellStartColumn = map.colCount(pos);
|
|
3751
|
+
let changed = false;
|
|
3752
|
+
for (let index = 0; index < attrs.colspan; index += 1) {
|
|
3753
|
+
const width = widthsByColumn.get(cellStartColumn + index);
|
|
3754
|
+
if (width === void 0 || colwidth[index] === width) continue;
|
|
3755
|
+
colwidth[index] = width;
|
|
3756
|
+
changed = true;
|
|
3757
|
+
}
|
|
3758
|
+
if (!changed) continue;
|
|
3575
3759
|
tr.setNodeMarkup(start + pos, null, {
|
|
3576
3760
|
...attrs,
|
|
3577
3761
|
colwidth
|
|
3578
3762
|
});
|
|
3579
3763
|
}
|
|
3764
|
+
if (columnRatios) {
|
|
3765
|
+
tr.setNodeMarkup(start - 1, void 0, {
|
|
3766
|
+
...table.attrs,
|
|
3767
|
+
widthMode: "responsive",
|
|
3768
|
+
columnRatios: normalizeColumnRatios(columnRatios, map.width)
|
|
3769
|
+
});
|
|
3770
|
+
}
|
|
3580
3771
|
if (tr.docChanged) view.dispatch(tr);
|
|
3581
3772
|
}
|
|
3773
|
+
function updateColumnWidth(view, cell, width) {
|
|
3774
|
+
const info = getResizeColumnInfo(view.state, cell);
|
|
3775
|
+
if (!info) return;
|
|
3776
|
+
updateColumnWidths(view, cell, /* @__PURE__ */ new Map([[info.col, width]]));
|
|
3777
|
+
}
|
|
3582
3778
|
function getActiveDragging(state) {
|
|
3583
3779
|
const dragging = columnResizingPluginKey.getState(state)?.dragging;
|
|
3584
3780
|
return dragging ? dragging : null;
|
|
@@ -3630,16 +3826,36 @@ function handleMouseDown(view, event, cellMinWidth) {
|
|
|
3630
3826
|
if (!pluginState || pluginState.activeHandle === -1 || pluginState.dragging) return false;
|
|
3631
3827
|
const cell = view.state.doc.nodeAt(pluginState.activeHandle);
|
|
3632
3828
|
if (!cell) return false;
|
|
3829
|
+
const resizeInfo = getResizeColumnInfo(view.state, pluginState.activeHandle);
|
|
3830
|
+
if (!resizeInfo) return false;
|
|
3633
3831
|
const attrs = cell.attrs;
|
|
3634
|
-
|
|
3832
|
+
let width = getCurrentColWidth(view, pluginState.activeHandle, {
|
|
3635
3833
|
colspan: attrs.colspan ?? 1,
|
|
3636
3834
|
colwidth: attrs.colwidth
|
|
3637
3835
|
});
|
|
3638
3836
|
const minWidth = getColumnResizeMinWidth(cellMinWidth);
|
|
3837
|
+
let responsiveColumnWidths;
|
|
3838
|
+
let neighborStartWidth;
|
|
3839
|
+
if (normalizeTableWidthMode(resizeInfo.table.attrs.widthMode) === "responsive") {
|
|
3840
|
+
if (resizeInfo.col >= resizeInfo.map.width - 1) return false;
|
|
3841
|
+
const storedRatios = getTableColumnRatios(resizeInfo.table);
|
|
3842
|
+
const legacyWidths = getLegacyTableColumnWeights(resizeInfo.table, DEFAULT_TABLE_COLUMN_WIDTH);
|
|
3843
|
+
const storedTotal = legacyWidths.reduce((sum, value) => sum + value, 0);
|
|
3844
|
+
const tableElement = getTableElementAtCell(view, pluginState.activeHandle);
|
|
3845
|
+
const renderedWidth = tableElement?.getBoundingClientRect().width || storedTotal;
|
|
3846
|
+
responsiveColumnWidths = normalizeColumnWidthsToTotal(storedRatios, renderedWidth, minWidth);
|
|
3847
|
+
width = responsiveColumnWidths[resizeInfo.col];
|
|
3848
|
+
neighborStartWidth = responsiveColumnWidths[resizeInfo.col + 1];
|
|
3849
|
+
}
|
|
3639
3850
|
const dragging = {
|
|
3640
3851
|
startX: event.clientX,
|
|
3641
3852
|
startWidth: width,
|
|
3642
|
-
minWidth
|
|
3853
|
+
minWidth,
|
|
3854
|
+
...responsiveColumnWidths ? {
|
|
3855
|
+
columnIndex: resizeInfo.col,
|
|
3856
|
+
responsiveColumnWidths,
|
|
3857
|
+
neighborStartWidth
|
|
3858
|
+
} : null
|
|
3643
3859
|
};
|
|
3644
3860
|
view.dispatch(view.state.tr.setMeta(columnResizingPluginKey, { setDragging: dragging }));
|
|
3645
3861
|
function finish(nextEvent) {
|
|
@@ -3648,7 +3864,20 @@ function handleMouseDown(view, event, cellMinWidth) {
|
|
|
3648
3864
|
const activeDragging = getActiveDragging(view.state);
|
|
3649
3865
|
const activeHandle = columnResizingPluginKey.getState(view.state)?.activeHandle ?? -1;
|
|
3650
3866
|
if (activeDragging && activeHandle > -1) {
|
|
3651
|
-
|
|
3867
|
+
const nextWidth = getDraggedWidth(activeDragging, nextEvent);
|
|
3868
|
+
if (activeDragging.responsiveColumnWidths && activeDragging.columnIndex !== void 0 && activeDragging.neighborStartWidth !== void 0) {
|
|
3869
|
+
const nextColumnWidths = activeDragging.responsiveColumnWidths.slice();
|
|
3870
|
+
nextColumnWidths[activeDragging.columnIndex] = nextWidth;
|
|
3871
|
+
nextColumnWidths[activeDragging.columnIndex + 1] = activeDragging.startWidth + activeDragging.neighborStartWidth - nextWidth;
|
|
3872
|
+
updateColumnWidths(
|
|
3873
|
+
view,
|
|
3874
|
+
activeHandle,
|
|
3875
|
+
new Map(nextColumnWidths.map((columnWidth, index) => [index, columnWidth])),
|
|
3876
|
+
normalizeColumnRatios(nextColumnWidths, nextColumnWidths.length)
|
|
3877
|
+
);
|
|
3878
|
+
} else {
|
|
3879
|
+
updateColumnWidth(view, activeHandle, nextWidth);
|
|
3880
|
+
}
|
|
3652
3881
|
view.dispatch(view.state.tr.setMeta(columnResizingPluginKey, { setDragging: null }));
|
|
3653
3882
|
}
|
|
3654
3883
|
hideColumnResizeGhost(view);
|
|
@@ -3678,6 +3907,9 @@ function handleDecorations(state, cell, ownerDocument) {
|
|
|
3678
3907
|
const nodeAfter = $cell.nodeAfter;
|
|
3679
3908
|
if (!nodeAfter) return DecorationSet2.empty;
|
|
3680
3909
|
const col = map.colCount($cell.pos - start) + nodeAfter.attrs.colspan - 1;
|
|
3910
|
+
if (normalizeTableWidthMode(table.attrs.widthMode) === "responsive" && col === map.width - 1) {
|
|
3911
|
+
return DecorationSet2.empty;
|
|
3912
|
+
}
|
|
3681
3913
|
for (let row = 0; row < map.height; row += 1) {
|
|
3682
3914
|
const index = col + row * map.width;
|
|
3683
3915
|
if ((col === map.width - 1 || map.map[index] !== map.map[index + 1]) && (row === 0 || map.map[index] !== map.map[index - map.width])) {
|
|
@@ -3765,7 +3997,7 @@ function parseTableAlign(element) {
|
|
|
3765
3997
|
if ((marginLeft === "0px" || marginLeft === "0") && marginRight === "auto") return "left";
|
|
3766
3998
|
return null;
|
|
3767
3999
|
}
|
|
3768
|
-
function
|
|
4000
|
+
function renderFixedTableAlignStyle(tableAlign) {
|
|
3769
4001
|
switch (tableAlign) {
|
|
3770
4002
|
case "center":
|
|
3771
4003
|
return "table-layout: fixed; margin-left: auto; margin-right: auto;";
|
|
@@ -3777,28 +4009,94 @@ function renderTableAlignStyle(tableAlign) {
|
|
|
3777
4009
|
return "";
|
|
3778
4010
|
}
|
|
3779
4011
|
}
|
|
3780
|
-
function
|
|
3781
|
-
const
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
if (firstRow) {
|
|
3785
|
-
for (let cellIndex = 0; cellIndex < firstRow.childCount; cellIndex += 1) {
|
|
3786
|
-
const cell = firstRow.child(cellIndex);
|
|
3787
|
-
const colspan = Math.max(1, Number(cell.attrs.colspan) || 1);
|
|
3788
|
-
const colwidth = Array.isArray(cell.attrs.colwidth) ? cell.attrs.colwidth : [];
|
|
3789
|
-
for (let spanIndex = 0; spanIndex < colspan; spanIndex += 1) {
|
|
3790
|
-
const storedWidth = Number(colwidth[spanIndex]);
|
|
3791
|
-
const width = Number.isFinite(storedWidth) && storedWidth > 0 ? Math.max(MIN_RESIZED_TABLE_COLUMN_WIDTH, Math.round(storedWidth)) : DEFAULT_TABLE_COLUMN_WIDTH;
|
|
3792
|
-
totalWidth += width;
|
|
3793
|
-
columns.push(["col", { style: `width: ${width}px; min-width: ${width}px;`, width: String(width) }]);
|
|
3794
|
-
}
|
|
3795
|
-
}
|
|
4012
|
+
function parseTableWidthMode(element) {
|
|
4013
|
+
const storedMode = element.getAttribute("data-table-width-mode");
|
|
4014
|
+
if (storedMode === "responsive" || storedMode === "full" || parsePercentageToBasisPoints(element.style.width) !== null) {
|
|
4015
|
+
return "responsive";
|
|
3796
4016
|
}
|
|
4017
|
+
return "fixed";
|
|
4018
|
+
}
|
|
4019
|
+
function createUEditorColGroup(node, widthMode) {
|
|
4020
|
+
const columnWidths = getLegacyTableColumnWeights(node, DEFAULT_TABLE_COLUMN_WIDTH).map((width) => Math.max(MIN_RESIZED_TABLE_COLUMN_WIDTH, Math.round(width)));
|
|
4021
|
+
const columnRatios = getTableColumnRatios(node);
|
|
4022
|
+
const totalWidth = columnWidths.reduce((sum, width) => sum + width, 0);
|
|
4023
|
+
const columns = columnWidths.map((width, index) => ["col", {
|
|
4024
|
+
style: widthMode === "responsive" ? `width: ${formatBasisPointsAsPercentage(columnRatios[index])};` : `width: ${width}px; min-width: ${width}px;`,
|
|
4025
|
+
width: String(width)
|
|
4026
|
+
}]);
|
|
3797
4027
|
return {
|
|
3798
4028
|
colgroup: ["colgroup", {}, ...columns],
|
|
4029
|
+
columnCount: columns.length,
|
|
3799
4030
|
tableWidth: totalWidth > 0 ? `${totalWidth}px` : ""
|
|
3800
4031
|
};
|
|
3801
4032
|
}
|
|
4033
|
+
function runResponsiveColumnStructureCommand(state, dispatch, command, updateLayout, rewriteFormulas) {
|
|
4034
|
+
const tableInfo = findTableNodeInfoFromState(state);
|
|
4035
|
+
if (!tableInfo) {
|
|
4036
|
+
return command(state, dispatch);
|
|
4037
|
+
}
|
|
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({
|
|
4046
|
+
widthBp: getResponsiveTableWidthBp(tableInfo.node),
|
|
4047
|
+
columnRatios: getTableColumnRatios(tableInfo.node)
|
|
4048
|
+
}, rect) : null;
|
|
4049
|
+
return command(state, dispatch ? (transaction) => {
|
|
4050
|
+
let nextTable = transaction.doc.nodeAt(tableInfo.pos);
|
|
4051
|
+
if (nextTable?.type.name === "table" && nextLayout && nextLayout.columnRatios.length > 0) {
|
|
4052
|
+
const widthBp = clampResponsiveTableWidthBp(nextLayout.widthBp);
|
|
4053
|
+
const tableAlign = normalizeTableAlign(nextTable.attrs.textAlign);
|
|
4054
|
+
const offsetBp = resolveResponsiveTableOffsetBp(
|
|
4055
|
+
widthBp,
|
|
4056
|
+
tableAlign,
|
|
4057
|
+
getResponsiveTableOffsetBp(tableInfo.node)
|
|
4058
|
+
);
|
|
4059
|
+
transaction.setNodeMarkup(tableInfo.pos, void 0, {
|
|
4060
|
+
...nextTable.attrs,
|
|
4061
|
+
widthMode: "responsive",
|
|
4062
|
+
widthBp,
|
|
4063
|
+
offsetBp,
|
|
4064
|
+
columnRatios: normalizeColumnRatios(
|
|
4065
|
+
nextLayout.columnRatios,
|
|
4066
|
+
getLogicalTableColumnCount(nextTable)
|
|
4067
|
+
)
|
|
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
|
+
}
|
|
4096
|
+
}
|
|
4097
|
+
dispatch(transaction);
|
|
4098
|
+
} : void 0);
|
|
4099
|
+
}
|
|
3802
4100
|
var UEditorTable = Table2.extend({
|
|
3803
4101
|
addGlobalAttributes() {
|
|
3804
4102
|
return [
|
|
@@ -3816,10 +4114,64 @@ var UEditorTable = Table2.extend({
|
|
|
3816
4114
|
const tableAlign = normalizeTableAlign(attributes.textAlign);
|
|
3817
4115
|
if (!tableAlign) return {};
|
|
3818
4116
|
return {
|
|
3819
|
-
"data-table-align": tableAlign
|
|
3820
|
-
style: renderTableAlignStyle(tableAlign)
|
|
4117
|
+
"data-table-align": tableAlign
|
|
3821
4118
|
};
|
|
3822
4119
|
}
|
|
4120
|
+
},
|
|
4121
|
+
widthMode: {
|
|
4122
|
+
default: "fixed",
|
|
4123
|
+
parseHTML: (element) => {
|
|
4124
|
+
if (!(element instanceof HTMLElement)) return "fixed";
|
|
4125
|
+
return parseTableWidthMode(element);
|
|
4126
|
+
},
|
|
4127
|
+
renderHTML: (attributes) => {
|
|
4128
|
+
if (normalizeTableWidthMode(attributes.widthMode) !== "responsive") return {};
|
|
4129
|
+
return {
|
|
4130
|
+
"data-table-width-mode": "responsive"
|
|
4131
|
+
};
|
|
4132
|
+
}
|
|
4133
|
+
},
|
|
4134
|
+
widthBp: {
|
|
4135
|
+
default: null,
|
|
4136
|
+
parseHTML: (element) => {
|
|
4137
|
+
if (!(element instanceof HTMLElement) || parseTableWidthMode(element) !== "responsive") return null;
|
|
4138
|
+
const stored = Number(element.getAttribute("data-table-width-bp"));
|
|
4139
|
+
if (Number.isFinite(stored) && stored > 0) return clampResponsiveTableWidthBp(stored);
|
|
4140
|
+
return parsePercentageToBasisPoints(element.getAttribute("data-table-width") ?? element.style.width) ?? DEFAULT_RESPONSIVE_TABLE_WIDTH_BP;
|
|
4141
|
+
},
|
|
4142
|
+
renderHTML: () => ({})
|
|
4143
|
+
},
|
|
4144
|
+
offsetBp: {
|
|
4145
|
+
default: null,
|
|
4146
|
+
parseHTML: (element) => {
|
|
4147
|
+
if (!(element instanceof HTMLElement) || parseTableWidthMode(element) !== "responsive") return null;
|
|
4148
|
+
const storedValue = element.getAttribute("data-table-offset-bp");
|
|
4149
|
+
const stored = Number(storedValue);
|
|
4150
|
+
if (storedValue !== null && Number.isFinite(stored) && stored >= 0) return Math.round(stored);
|
|
4151
|
+
const explicitOffset = parsePercentageToBasisPoints(
|
|
4152
|
+
element.getAttribute("data-table-offset") ?? element.style.marginLeft
|
|
4153
|
+
);
|
|
4154
|
+
if (explicitOffset !== null) return explicitOffset;
|
|
4155
|
+
const widthBp = parsePercentageToBasisPoints(
|
|
4156
|
+
element.getAttribute("data-table-width") ?? element.style.width
|
|
4157
|
+
) ?? DEFAULT_RESPONSIVE_TABLE_WIDTH_BP;
|
|
4158
|
+
const tableAlign = parseTableAlign(element);
|
|
4159
|
+
return resolveResponsiveTableOffsetBp(widthBp, tableAlign);
|
|
4160
|
+
},
|
|
4161
|
+
renderHTML: () => ({})
|
|
4162
|
+
},
|
|
4163
|
+
columnRatios: {
|
|
4164
|
+
default: null,
|
|
4165
|
+
parseHTML: (element) => {
|
|
4166
|
+
if (!(element instanceof HTMLElement)) return null;
|
|
4167
|
+
const storedRatios = parseColumnRatios(
|
|
4168
|
+
element.getAttribute("data-table-column-ratios") ?? element.getAttribute("data-column-ratios")
|
|
4169
|
+
);
|
|
4170
|
+
if (storedRatios) return storedRatios;
|
|
4171
|
+
const columnPercentages = Array.from(element.querySelectorAll("colgroup > col")).map((column) => parsePercentageToBasisPoints(column.style.width));
|
|
4172
|
+
return columnPercentages.length > 0 && columnPercentages.every((ratio) => ratio !== null) ? normalizeColumnRatios(columnPercentages, columnPercentages.length) : null;
|
|
4173
|
+
},
|
|
4174
|
+
renderHTML: () => ({})
|
|
3823
4175
|
}
|
|
3824
4176
|
}
|
|
3825
4177
|
}
|
|
@@ -3828,13 +4180,117 @@ var UEditorTable = Table2.extend({
|
|
|
3828
4180
|
addCommands() {
|
|
3829
4181
|
return {
|
|
3830
4182
|
...this.parent?.(),
|
|
4183
|
+
insertTable: ({ rows = 3, cols = 3, withHeaderRow = true } = {}) => ({ tr, dispatch, editor }) => {
|
|
4184
|
+
const types = tableNodeTypes2(editor.schema);
|
|
4185
|
+
const rowCount = Math.max(1, Math.floor(rows));
|
|
4186
|
+
const columnCount = Math.max(1, Math.floor(cols));
|
|
4187
|
+
const createCells = (type) => Array.from({ length: columnCount }, () => type.createAndFill()).filter((cell) => cell !== null);
|
|
4188
|
+
const bodyCells = createCells(types.cell);
|
|
4189
|
+
const headerCells = withHeaderRow ? createCells(types.header_cell) : bodyCells;
|
|
4190
|
+
const tableRows = Array.from({ length: rowCount }, (_, index) => types.row.createChecked(
|
|
4191
|
+
null,
|
|
4192
|
+
withHeaderRow && index === 0 ? headerCells : bodyCells
|
|
4193
|
+
));
|
|
4194
|
+
const table = types.table.createChecked(
|
|
4195
|
+
{
|
|
4196
|
+
widthMode: "responsive",
|
|
4197
|
+
widthBp: DEFAULT_RESPONSIVE_TABLE_WIDTH_BP,
|
|
4198
|
+
offsetBp: 0,
|
|
4199
|
+
columnRatios: normalizeColumnRatios(null, columnCount)
|
|
4200
|
+
},
|
|
4201
|
+
tableRows
|
|
4202
|
+
);
|
|
4203
|
+
if (dispatch) {
|
|
4204
|
+
const offset = tr.selection.from + 1;
|
|
4205
|
+
tr.replaceSelectionWith(table).scrollIntoView().setSelection(TextSelection.near(tr.doc.resolve(offset)));
|
|
4206
|
+
}
|
|
4207
|
+
return true;
|
|
4208
|
+
},
|
|
4209
|
+
addColumnBefore: () => ({ state, dispatch }) => {
|
|
4210
|
+
return runResponsiveColumnStructureCommand(
|
|
4211
|
+
state,
|
|
4212
|
+
dispatch,
|
|
4213
|
+
addColumnBeforeCommand,
|
|
4214
|
+
(layout, rect) => insertResponsiveColumnLayout(
|
|
4215
|
+
layout.widthBp,
|
|
4216
|
+
layout.columnRatios,
|
|
4217
|
+
rect.left,
|
|
4218
|
+
rect.left
|
|
4219
|
+
),
|
|
4220
|
+
(tableNode, rect) => rewriteTableNodeFormulaReferencesForInsertion(tableNode, "column", rect.left)
|
|
4221
|
+
);
|
|
4222
|
+
},
|
|
4223
|
+
addColumnAfter: () => ({ state, dispatch }) => {
|
|
4224
|
+
return runResponsiveColumnStructureCommand(
|
|
4225
|
+
state,
|
|
4226
|
+
dispatch,
|
|
4227
|
+
addColumnAfterCommand,
|
|
4228
|
+
(layout, rect) => insertResponsiveColumnLayout(
|
|
4229
|
+
layout.widthBp,
|
|
4230
|
+
layout.columnRatios,
|
|
4231
|
+
rect.right,
|
|
4232
|
+
rect.right - 1
|
|
4233
|
+
),
|
|
4234
|
+
(tableNode, rect) => rewriteTableNodeFormulaReferencesForInsertion(tableNode, "column", rect.right)
|
|
4235
|
+
);
|
|
4236
|
+
},
|
|
4237
|
+
deleteColumn: () => ({ state, dispatch }) => {
|
|
4238
|
+
return runResponsiveColumnStructureCommand(
|
|
4239
|
+
state,
|
|
4240
|
+
dispatch,
|
|
4241
|
+
deleteColumnCommand,
|
|
4242
|
+
(layout, rect) => {
|
|
4243
|
+
let nextLayout = layout;
|
|
4244
|
+
for (let index = rect.right - 1; index >= rect.left; index -= 1) {
|
|
4245
|
+
nextLayout = deleteResponsiveColumnLayout(
|
|
4246
|
+
nextLayout.widthBp,
|
|
4247
|
+
nextLayout.columnRatios,
|
|
4248
|
+
index
|
|
4249
|
+
);
|
|
4250
|
+
}
|
|
4251
|
+
return nextLayout;
|
|
4252
|
+
},
|
|
4253
|
+
(tableNode, rect) => rewriteTableNodeFormulaReferencesForDeletion(
|
|
4254
|
+
tableNode,
|
|
4255
|
+
"column",
|
|
4256
|
+
rect.left,
|
|
4257
|
+
rect.right - rect.left
|
|
4258
|
+
)
|
|
4259
|
+
);
|
|
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
|
+
),
|
|
3831
4284
|
setTableAlign: (tableAlign) => ({ state, dispatch }) => {
|
|
3832
4285
|
const tableInfo = findTableNodeInfoFromState(state);
|
|
3833
4286
|
if (!tableInfo) return false;
|
|
4287
|
+
const widthBp = getResponsiveTableWidthBp(tableInfo.node);
|
|
4288
|
+
const offsetBp = resolveResponsiveTableOffsetBp(widthBp, tableAlign);
|
|
3834
4289
|
dispatch?.(
|
|
3835
4290
|
state.tr.setNodeMarkup(tableInfo.pos, tableInfo.node.type, {
|
|
3836
4291
|
...tableInfo.node.attrs,
|
|
3837
|
-
textAlign: tableAlign
|
|
4292
|
+
textAlign: tableAlign,
|
|
4293
|
+
...normalizeTableWidthMode(tableInfo.node.attrs.widthMode) === "responsive" ? { offsetBp } : null
|
|
3838
4294
|
})
|
|
3839
4295
|
);
|
|
3840
4296
|
return true;
|
|
@@ -3853,11 +4309,31 @@ var UEditorTable = Table2.extend({
|
|
|
3853
4309
|
};
|
|
3854
4310
|
},
|
|
3855
4311
|
renderHTML({ node, HTMLAttributes }) {
|
|
3856
|
-
const
|
|
4312
|
+
const widthMode = normalizeTableWidthMode(node.attrs.widthMode);
|
|
4313
|
+
const { colgroup, columnCount, tableWidth } = createUEditorColGroup(node, widthMode);
|
|
4314
|
+
const tableAlign = normalizeTableAlign(node.attrs.textAlign);
|
|
4315
|
+
const widthBp = getResponsiveTableWidthBp(node);
|
|
4316
|
+
const offsetBp = getResponsiveTableOffsetBp(node);
|
|
4317
|
+
const columnRatios = getTableColumnRatios(node);
|
|
4318
|
+
const tableStyle = widthMode === "responsive" ? [
|
|
4319
|
+
`width: ${formatBasisPointsAsPercentage(widthBp)}`,
|
|
4320
|
+
`margin-left: ${formatBasisPointsAsPercentage(offsetBp)}`,
|
|
4321
|
+
"margin-right: auto",
|
|
4322
|
+
`min-width: ${Math.max(1, columnCount) * MIN_RESIZED_TABLE_COLUMN_WIDTH}px`,
|
|
4323
|
+
"table-layout: fixed"
|
|
4324
|
+
].join("; ") + ";" : tableWidth ? `width: ${tableWidth}; ${renderFixedTableAlignStyle(tableAlign)}` : `table-layout: fixed; ${renderFixedTableAlignStyle(tableAlign)}`;
|
|
3857
4325
|
const table = [
|
|
3858
4326
|
"table",
|
|
3859
4327
|
mergeAttributes7(this.options.HTMLAttributes, HTMLAttributes, {
|
|
3860
|
-
|
|
4328
|
+
...widthMode === "responsive" ? {
|
|
4329
|
+
"data-table-width-mode": "responsive",
|
|
4330
|
+
"data-table-width": formatBasisPointsAsPercentage(widthBp),
|
|
4331
|
+
"data-table-width-bp": String(widthBp),
|
|
4332
|
+
"data-table-offset": formatBasisPointsAsPercentage(offsetBp),
|
|
4333
|
+
"data-table-offset-bp": String(offsetBp),
|
|
4334
|
+
"data-table-column-ratios": columnRatios.join(",")
|
|
4335
|
+
} : null,
|
|
4336
|
+
style: tableStyle
|
|
3861
4337
|
}),
|
|
3862
4338
|
colgroup,
|
|
3863
4339
|
["tbody", 0]
|
|
@@ -3910,6 +4386,31 @@ var UEditorTable = Table2.extend({
|
|
|
3910
4386
|
tableEditing({
|
|
3911
4387
|
allowTableNodeSelection: this.options.allowTableNodeSelection
|
|
3912
4388
|
}),
|
|
4389
|
+
new Plugin4({
|
|
4390
|
+
key: new PluginKey5("responsiveTableLayoutNormalizer"),
|
|
4391
|
+
appendTransaction(transactions, _oldState, newState) {
|
|
4392
|
+
if (!transactions.some((transaction) => transaction.docChanged)) return null;
|
|
4393
|
+
const tableInfo = findTableNodeInfoFromState(newState);
|
|
4394
|
+
const node = tableInfo?.node;
|
|
4395
|
+
if (!tableInfo || !node || normalizeTableWidthMode(node.attrs.widthMode) !== "responsive") return null;
|
|
4396
|
+
const columnCount = getLogicalTableColumnCount(node);
|
|
4397
|
+
const columnRatios = getTableColumnRatios(node);
|
|
4398
|
+
const widthBp = getResponsiveTableWidthBp(node);
|
|
4399
|
+
const offsetBp = getResponsiveTableOffsetBp(node);
|
|
4400
|
+
const storedRatios = parseColumnRatios(node.attrs.columnRatios);
|
|
4401
|
+
const ratiosMatch = storedRatios?.length === columnCount && storedRatios.every((ratio, index) => Math.round(ratio) === columnRatios[index]);
|
|
4402
|
+
if (ratiosMatch && node.attrs.widthBp === widthBp && node.attrs.offsetBp === offsetBp && node.attrs.widthMode === "responsive") {
|
|
4403
|
+
return null;
|
|
4404
|
+
}
|
|
4405
|
+
return newState.tr.setNodeMarkup(tableInfo.pos, void 0, {
|
|
4406
|
+
...node.attrs,
|
|
4407
|
+
widthMode: "responsive",
|
|
4408
|
+
widthBp,
|
|
4409
|
+
offsetBp,
|
|
4410
|
+
columnRatios
|
|
4411
|
+
});
|
|
4412
|
+
}
|
|
4413
|
+
}),
|
|
3913
4414
|
new Plugin4({
|
|
3914
4415
|
appendTransaction(_transactions, _oldState, newState) {
|
|
3915
4416
|
const { doc, schema } = newState;
|
|
@@ -3930,7 +4431,7 @@ var UEditorTable = Table2.extend({
|
|
|
3930
4431
|
var table_align_default = UEditorTable;
|
|
3931
4432
|
|
|
3932
4433
|
// src/components/UEditor/CodeBlockView.tsx
|
|
3933
|
-
import
|
|
4434
|
+
import React9, { useState as useState4 } from "react";
|
|
3934
4435
|
import { NodeViewWrapper as NodeViewWrapper7, NodeViewContent as NodeViewContent2 } from "@tiptap/react";
|
|
3935
4436
|
import { Check as Check2, Copy, ChevronDown } from "lucide-react";
|
|
3936
4437
|
import { Fragment, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
@@ -3957,10 +4458,11 @@ var CodeBlockView = ({
|
|
|
3957
4458
|
}) => {
|
|
3958
4459
|
const [copied, setCopied] = useState4(false);
|
|
3959
4460
|
const [isDropdownOpen, setIsDropdownOpen] = useState4(false);
|
|
3960
|
-
const timeoutRef =
|
|
4461
|
+
const timeoutRef = React9.useRef(null);
|
|
4462
|
+
const t = useSmartTranslations("UEditor");
|
|
3961
4463
|
const currentLangValue = node.attrs.language || "text";
|
|
3962
4464
|
const currentLangLabel = LANGUAGES.find((lang) => lang.value === currentLangValue)?.label || "Plain Text";
|
|
3963
|
-
|
|
4465
|
+
React9.useEffect(() => {
|
|
3964
4466
|
return () => {
|
|
3965
4467
|
if (timeoutRef.current) {
|
|
3966
4468
|
clearTimeout(timeoutRef.current);
|
|
@@ -3994,10 +4496,12 @@ var CodeBlockView = ({
|
|
|
3994
4496
|
{
|
|
3995
4497
|
type: "button",
|
|
3996
4498
|
onClick: () => setIsDropdownOpen(!isDropdownOpen),
|
|
3997
|
-
|
|
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",
|
|
3998
4502
|
children: [
|
|
3999
4503
|
currentLangLabel,
|
|
4000
|
-
/* @__PURE__ */ jsx11(ChevronDown, { className: "h-3 w-3" })
|
|
4504
|
+
/* @__PURE__ */ jsx11(ChevronDown, { "aria-hidden": "true", className: "h-3 w-3" })
|
|
4001
4505
|
]
|
|
4002
4506
|
}
|
|
4003
4507
|
),
|
|
@@ -4009,10 +4513,12 @@ var CodeBlockView = ({
|
|
|
4009
4513
|
onClick: () => setIsDropdownOpen(false)
|
|
4010
4514
|
}
|
|
4011
4515
|
),
|
|
4012
|
-
/* @__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(
|
|
4013
4517
|
"button",
|
|
4014
4518
|
{
|
|
4015
4519
|
type: "button",
|
|
4520
|
+
role: "option",
|
|
4521
|
+
"aria-selected": currentLangValue === lang.value,
|
|
4016
4522
|
onClick: () => {
|
|
4017
4523
|
updateAttributes({ language: lang.value });
|
|
4018
4524
|
setIsDropdownOpen(false);
|
|
@@ -4032,9 +4538,10 @@ var CodeBlockView = ({
|
|
|
4032
4538
|
{
|
|
4033
4539
|
type: "button",
|
|
4034
4540
|
onClick: handleCopy,
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
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" })
|
|
4038
4545
|
}
|
|
4039
4546
|
)
|
|
4040
4547
|
]
|
|
@@ -4237,529 +4744,8 @@ import { Extension as Extension10 } from "@tiptap/core";
|
|
|
4237
4744
|
import { Plugin as Plugin6 } from "@tiptap/pm/state";
|
|
4238
4745
|
|
|
4239
4746
|
// src/components/UEditor/table-formula-commands.ts
|
|
4240
|
-
import { TextSelection } from "@tiptap/pm/state";
|
|
4241
|
-
import { selectedRect, setCellAttr, TableMap as TableMap2 } from "@tiptap/pm/tables";
|
|
4242
|
-
|
|
4243
|
-
// src/components/UEditor/table-formula.ts
|
|
4244
|
-
var CELL_ADDRESS_RE = /^([A-Z]+)([1-9]\d*)$/i;
|
|
4245
|
-
var CELL_RANGE_RE = /^([A-Z]+[1-9]\d*):([A-Z]+[1-9]\d*)$/i;
|
|
4246
|
-
var SUPPORTED_FUNCTIONS = /* @__PURE__ */ new Set(["SUM", "AVG", "MIN", "MAX", "COUNT"]);
|
|
4247
|
-
function columnNameToIndex(columnName) {
|
|
4248
|
-
const normalized = columnName.trim().toUpperCase();
|
|
4249
|
-
if (!/^[A-Z]+$/.test(normalized)) {
|
|
4250
|
-
return -1;
|
|
4251
|
-
}
|
|
4252
|
-
let index = 0;
|
|
4253
|
-
for (const char of normalized) {
|
|
4254
|
-
index = index * 26 + char.charCodeAt(0) - 64;
|
|
4255
|
-
}
|
|
4256
|
-
return index - 1;
|
|
4257
|
-
}
|
|
4258
|
-
function indexToColumnName(index) {
|
|
4259
|
-
if (!Number.isInteger(index) || index < 0) {
|
|
4260
|
-
return "";
|
|
4261
|
-
}
|
|
4262
|
-
let value = index + 1;
|
|
4263
|
-
let name = "";
|
|
4264
|
-
while (value > 0) {
|
|
4265
|
-
const remainder = (value - 1) % 26;
|
|
4266
|
-
name = String.fromCharCode(65 + remainder) + name;
|
|
4267
|
-
value = Math.floor((value - 1) / 26);
|
|
4268
|
-
}
|
|
4269
|
-
return name;
|
|
4270
|
-
}
|
|
4271
|
-
function parseTableCellAddress(input) {
|
|
4272
|
-
const match = input.trim().match(CELL_ADDRESS_RE);
|
|
4273
|
-
if (!match) {
|
|
4274
|
-
return null;
|
|
4275
|
-
}
|
|
4276
|
-
const column = columnNameToIndex(match[1] ?? "");
|
|
4277
|
-
const row = Number.parseInt(match[2] ?? "", 10) - 1;
|
|
4278
|
-
if (column < 0 || row < 0) {
|
|
4279
|
-
return null;
|
|
4280
|
-
}
|
|
4281
|
-
return {
|
|
4282
|
-
column,
|
|
4283
|
-
row,
|
|
4284
|
-
label: `${indexToColumnName(column)}${row + 1}`
|
|
4285
|
-
};
|
|
4286
|
-
}
|
|
4287
|
-
function parseTableCellRange(input) {
|
|
4288
|
-
const match = input.trim().match(CELL_RANGE_RE);
|
|
4289
|
-
if (!match) {
|
|
4290
|
-
return null;
|
|
4291
|
-
}
|
|
4292
|
-
const from = parseTableCellAddress(match[1] ?? "");
|
|
4293
|
-
const to = parseTableCellAddress(match[2] ?? "");
|
|
4294
|
-
if (!from || !to) {
|
|
4295
|
-
return null;
|
|
4296
|
-
}
|
|
4297
|
-
return { from, to };
|
|
4298
|
-
}
|
|
4299
|
-
function getTableCellRangeLabels(range) {
|
|
4300
|
-
const startColumn = Math.min(range.from.column, range.to.column);
|
|
4301
|
-
const endColumn = Math.max(range.from.column, range.to.column);
|
|
4302
|
-
const startRow = Math.min(range.from.row, range.to.row);
|
|
4303
|
-
const endRow = Math.max(range.from.row, range.to.row);
|
|
4304
|
-
const labels = [];
|
|
4305
|
-
for (let row = startRow; row <= endRow; row += 1) {
|
|
4306
|
-
for (let column = startColumn; column <= endColumn; column += 1) {
|
|
4307
|
-
labels.push(`${indexToColumnName(column)}${row + 1}`);
|
|
4308
|
-
}
|
|
4309
|
-
}
|
|
4310
|
-
return labels;
|
|
4311
|
-
}
|
|
4312
|
-
function normalizeTableFormula(formula) {
|
|
4313
|
-
return formula.trim().replace(/^=/, "").trim();
|
|
4314
|
-
}
|
|
4315
|
-
function isDraftTableFormula(formula) {
|
|
4316
|
-
const normalized = normalizeTableFormula(formula);
|
|
4317
|
-
if (!normalized) return true;
|
|
4318
|
-
let depth = 0;
|
|
4319
|
-
for (const char of normalized) {
|
|
4320
|
-
if (char === "(") depth += 1;
|
|
4321
|
-
if (char === ")") depth -= 1;
|
|
4322
|
-
if (depth < 0) return false;
|
|
4323
|
-
}
|
|
4324
|
-
if (depth > 0) return true;
|
|
4325
|
-
if (/^[A-Z]+\(\s*\)$/i.test(normalized)) return true;
|
|
4326
|
-
if (/[+\-*/,(]\s*$/.test(normalized)) return true;
|
|
4327
|
-
return false;
|
|
4328
|
-
}
|
|
4329
|
-
function formatFormulaError(error) {
|
|
4330
|
-
return `#${error.toUpperCase()}`;
|
|
4331
|
-
}
|
|
4332
|
-
function normalizeTableNumberFormat(format) {
|
|
4333
|
-
return format === "text" || format === "number" || format === "currency" || format === "percent" || format === "date" ? format : "text";
|
|
4334
|
-
}
|
|
4335
|
-
function formatTableFormulaDisplayValue(value, numberFormat) {
|
|
4336
|
-
const stringValue = String(value);
|
|
4337
|
-
if (stringValue.startsWith("#")) {
|
|
4338
|
-
return stringValue;
|
|
4339
|
-
}
|
|
4340
|
-
const normalizedFormat = normalizeTableNumberFormat(numberFormat);
|
|
4341
|
-
if (normalizedFormat === "text") {
|
|
4342
|
-
return stringValue;
|
|
4343
|
-
}
|
|
4344
|
-
const numericValue = typeof value === "number" ? value : Number.parseFloat(stringValue.replace(/,/g, ""));
|
|
4345
|
-
if (!Number.isFinite(numericValue)) {
|
|
4346
|
-
return stringValue;
|
|
4347
|
-
}
|
|
4348
|
-
if (normalizedFormat === "number") {
|
|
4349
|
-
return new Intl.NumberFormat("en-US", { maximumFractionDigits: 6 }).format(numericValue);
|
|
4350
|
-
}
|
|
4351
|
-
if (normalizedFormat === "currency") {
|
|
4352
|
-
return new Intl.NumberFormat("en-US", {
|
|
4353
|
-
style: "currency",
|
|
4354
|
-
currency: "USD",
|
|
4355
|
-
maximumFractionDigits: 2
|
|
4356
|
-
}).format(numericValue);
|
|
4357
|
-
}
|
|
4358
|
-
if (normalizedFormat === "percent") {
|
|
4359
|
-
return new Intl.NumberFormat("en-US", {
|
|
4360
|
-
style: "percent",
|
|
4361
|
-
maximumFractionDigits: 2
|
|
4362
|
-
}).format(numericValue);
|
|
4363
|
-
}
|
|
4364
|
-
const excelEpochMs = Date.UTC(1899, 11, 30);
|
|
4365
|
-
const date = new Date(excelEpochMs + numericValue * 24 * 60 * 60 * 1e3);
|
|
4366
|
-
if (Number.isNaN(date.getTime())) {
|
|
4367
|
-
return stringValue;
|
|
4368
|
-
}
|
|
4369
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
4370
|
-
year: "numeric",
|
|
4371
|
-
month: "2-digit",
|
|
4372
|
-
day: "2-digit",
|
|
4373
|
-
timeZone: "UTC"
|
|
4374
|
-
}).format(date);
|
|
4375
|
-
}
|
|
4376
|
-
function getTableFormulaReferences(formula) {
|
|
4377
|
-
const normalized = normalizeTableFormula(formula);
|
|
4378
|
-
if (!normalized) return [];
|
|
4379
|
-
const tokens = tokenizeFormula(normalized);
|
|
4380
|
-
if (!tokens) return [];
|
|
4381
|
-
const references = /* @__PURE__ */ new Set();
|
|
4382
|
-
for (const token of tokens) {
|
|
4383
|
-
if (token.type === "cell") {
|
|
4384
|
-
references.add(token.value);
|
|
4385
|
-
} else if (token.type === "range") {
|
|
4386
|
-
const range = parseTableCellRange(token.value);
|
|
4387
|
-
if (!range) continue;
|
|
4388
|
-
for (const label of getTableCellRangeLabels(range)) {
|
|
4389
|
-
references.add(label);
|
|
4390
|
-
}
|
|
4391
|
-
}
|
|
4392
|
-
}
|
|
4393
|
-
return Array.from(references);
|
|
4394
|
-
}
|
|
4395
|
-
function buildTableFormulaDependencyGraph(cells) {
|
|
4396
|
-
const dependencies = /* @__PURE__ */ new Map();
|
|
4397
|
-
const dependents = /* @__PURE__ */ new Map();
|
|
4398
|
-
const formulas = /* @__PURE__ */ new Map();
|
|
4399
|
-
for (const cell of cells) {
|
|
4400
|
-
const label = cell.label.toUpperCase();
|
|
4401
|
-
formulas.set(label, cell.formula);
|
|
4402
|
-
dependencies.set(label, new Set(getTableFormulaReferences(cell.formula)));
|
|
4403
|
-
if (!dependents.has(label)) {
|
|
4404
|
-
dependents.set(label, /* @__PURE__ */ new Set());
|
|
4405
|
-
}
|
|
4406
|
-
}
|
|
4407
|
-
for (const [label, refs] of dependencies) {
|
|
4408
|
-
for (const ref of refs) {
|
|
4409
|
-
if (!dependents.has(ref)) {
|
|
4410
|
-
dependents.set(ref, /* @__PURE__ */ new Set());
|
|
4411
|
-
}
|
|
4412
|
-
dependents.get(ref)?.add(label);
|
|
4413
|
-
}
|
|
4414
|
-
}
|
|
4415
|
-
return { dependencies, dependents, formulas };
|
|
4416
|
-
}
|
|
4417
|
-
function getTableFormulaCircularReferences(graph) {
|
|
4418
|
-
const circular = /* @__PURE__ */ new Set();
|
|
4419
|
-
const visited = /* @__PURE__ */ new Set();
|
|
4420
|
-
const finishOrder = [];
|
|
4421
|
-
for (const startLabel of graph.formulas.keys()) {
|
|
4422
|
-
if (visited.has(startLabel)) continue;
|
|
4423
|
-
visited.add(startLabel);
|
|
4424
|
-
const stack = [
|
|
4425
|
-
{
|
|
4426
|
-
label: startLabel,
|
|
4427
|
-
references: Array.from(graph.dependencies.get(startLabel) ?? []).filter((ref) => graph.formulas.has(ref)),
|
|
4428
|
-
nextIndex: 0
|
|
4429
|
-
}
|
|
4430
|
-
];
|
|
4431
|
-
while (stack.length > 0) {
|
|
4432
|
-
const frame = stack[stack.length - 1];
|
|
4433
|
-
if (!frame) break;
|
|
4434
|
-
const reference = frame.references[frame.nextIndex];
|
|
4435
|
-
if (reference) {
|
|
4436
|
-
frame.nextIndex += 1;
|
|
4437
|
-
if (!visited.has(reference)) {
|
|
4438
|
-
visited.add(reference);
|
|
4439
|
-
stack.push({
|
|
4440
|
-
label: reference,
|
|
4441
|
-
references: Array.from(graph.dependencies.get(reference) ?? []).filter((ref) => graph.formulas.has(ref)),
|
|
4442
|
-
nextIndex: 0
|
|
4443
|
-
});
|
|
4444
|
-
}
|
|
4445
|
-
continue;
|
|
4446
|
-
}
|
|
4447
|
-
stack.pop();
|
|
4448
|
-
finishOrder.push(frame.label);
|
|
4449
|
-
}
|
|
4450
|
-
}
|
|
4451
|
-
const assigned = /* @__PURE__ */ new Set();
|
|
4452
|
-
for (let index = finishOrder.length - 1; index >= 0; index -= 1) {
|
|
4453
|
-
const startLabel = finishOrder[index];
|
|
4454
|
-
if (!startLabel || assigned.has(startLabel)) continue;
|
|
4455
|
-
const component = [];
|
|
4456
|
-
const stack = [startLabel];
|
|
4457
|
-
assigned.add(startLabel);
|
|
4458
|
-
while (stack.length > 0) {
|
|
4459
|
-
const label = stack.pop();
|
|
4460
|
-
if (!label) continue;
|
|
4461
|
-
component.push(label);
|
|
4462
|
-
for (const dependent of graph.dependents.get(label) ?? []) {
|
|
4463
|
-
if (!graph.formulas.has(dependent) || assigned.has(dependent)) continue;
|
|
4464
|
-
assigned.add(dependent);
|
|
4465
|
-
stack.push(dependent);
|
|
4466
|
-
}
|
|
4467
|
-
}
|
|
4468
|
-
if (component.length > 1) {
|
|
4469
|
-
for (const label of component) circular.add(label);
|
|
4470
|
-
} else {
|
|
4471
|
-
const label = component[0];
|
|
4472
|
-
if (label && graph.dependencies.get(label)?.has(label)) circular.add(label);
|
|
4473
|
-
}
|
|
4474
|
-
}
|
|
4475
|
-
return circular;
|
|
4476
|
-
}
|
|
4477
|
-
function getTableFormulaRecalculationOrder(graph) {
|
|
4478
|
-
const circular = getTableFormulaCircularReferences(graph);
|
|
4479
|
-
const visiting = /* @__PURE__ */ new Set();
|
|
4480
|
-
const visited = /* @__PURE__ */ new Set();
|
|
4481
|
-
const order = [];
|
|
4482
|
-
for (const startLabel of graph.formulas.keys()) {
|
|
4483
|
-
if (visited.has(startLabel) || circular.has(startLabel)) continue;
|
|
4484
|
-
const stack = [];
|
|
4485
|
-
const push = (label) => {
|
|
4486
|
-
visiting.add(label);
|
|
4487
|
-
stack.push({
|
|
4488
|
-
label,
|
|
4489
|
-
references: Array.from(graph.dependencies.get(label) ?? []).filter((ref) => graph.formulas.has(ref) && !circular.has(ref)),
|
|
4490
|
-
nextIndex: 0
|
|
4491
|
-
});
|
|
4492
|
-
};
|
|
4493
|
-
push(startLabel);
|
|
4494
|
-
while (stack.length > 0) {
|
|
4495
|
-
const frame = stack[stack.length - 1];
|
|
4496
|
-
if (!frame) break;
|
|
4497
|
-
const reference = frame.references[frame.nextIndex];
|
|
4498
|
-
if (reference) {
|
|
4499
|
-
frame.nextIndex += 1;
|
|
4500
|
-
if (!visited.has(reference) && !visiting.has(reference)) {
|
|
4501
|
-
push(reference);
|
|
4502
|
-
}
|
|
4503
|
-
continue;
|
|
4504
|
-
}
|
|
4505
|
-
stack.pop();
|
|
4506
|
-
visiting.delete(frame.label);
|
|
4507
|
-
visited.add(frame.label);
|
|
4508
|
-
order.push(frame.label);
|
|
4509
|
-
}
|
|
4510
|
-
}
|
|
4511
|
-
return { order, circular };
|
|
4512
|
-
}
|
|
4513
|
-
function getAffectedTableFormulaLabels(graph, changedLabels) {
|
|
4514
|
-
const affected = /* @__PURE__ */ new Set();
|
|
4515
|
-
const queue = Array.from(changedLabels, (label) => label.toUpperCase());
|
|
4516
|
-
for (const label of queue) {
|
|
4517
|
-
if (graph.formulas.has(label)) {
|
|
4518
|
-
affected.add(label);
|
|
4519
|
-
}
|
|
4520
|
-
}
|
|
4521
|
-
for (let index = 0; index < queue.length; index += 1) {
|
|
4522
|
-
const label = queue[index];
|
|
4523
|
-
if (!label) continue;
|
|
4524
|
-
for (const dependent of graph.dependents.get(label) ?? []) {
|
|
4525
|
-
if (affected.has(dependent)) continue;
|
|
4526
|
-
affected.add(dependent);
|
|
4527
|
-
queue.push(dependent);
|
|
4528
|
-
}
|
|
4529
|
-
}
|
|
4530
|
-
return affected;
|
|
4531
|
-
}
|
|
4532
|
-
function evaluateBasicTableFormula(formula, getCellValue) {
|
|
4533
|
-
const normalized = normalizeTableFormula(formula);
|
|
4534
|
-
if (!normalized) {
|
|
4535
|
-
return { value: null, error: "empty" };
|
|
4536
|
-
}
|
|
4537
|
-
const tokens = tokenizeFormula(normalized);
|
|
4538
|
-
if (!tokens) {
|
|
4539
|
-
return { value: null, error: "invalid-formula" };
|
|
4540
|
-
}
|
|
4541
|
-
const parser = new FormulaParser(tokens, getCellValue);
|
|
4542
|
-
const result = parser.parseExpression();
|
|
4543
|
-
if (result.error) {
|
|
4544
|
-
return result;
|
|
4545
|
-
}
|
|
4546
|
-
if (!parser.isComplete()) {
|
|
4547
|
-
return { value: null, error: "invalid-formula" };
|
|
4548
|
-
}
|
|
4549
|
-
return result;
|
|
4550
|
-
}
|
|
4551
|
-
function tokenizeFormula(formula) {
|
|
4552
|
-
const tokens = [];
|
|
4553
|
-
let index = 0;
|
|
4554
|
-
while (index < formula.length) {
|
|
4555
|
-
const char = formula[index];
|
|
4556
|
-
if (!char) break;
|
|
4557
|
-
if (/\s/.test(char)) {
|
|
4558
|
-
index += 1;
|
|
4559
|
-
continue;
|
|
4560
|
-
}
|
|
4561
|
-
if (char === "," || char === "+" || char === "-" || char === "*" || char === "/" || char === "(" || char === ")") {
|
|
4562
|
-
if (char === ",") tokens.push({ type: "comma", value: char });
|
|
4563
|
-
else if (char === "(" || char === ")") tokens.push({ type: "paren", value: char });
|
|
4564
|
-
else tokens.push({ type: "operator", value: char });
|
|
4565
|
-
index += 1;
|
|
4566
|
-
continue;
|
|
4567
|
-
}
|
|
4568
|
-
const numberMatch = formula.slice(index).match(/^(?:\d+(?:\.\d*)?|\.\d+)/);
|
|
4569
|
-
if (numberMatch?.[0]) {
|
|
4570
|
-
const value = Number.parseFloat(numberMatch[0]);
|
|
4571
|
-
if (!Number.isFinite(value)) return null;
|
|
4572
|
-
tokens.push({ type: "number", value });
|
|
4573
|
-
index += numberMatch[0].length;
|
|
4574
|
-
continue;
|
|
4575
|
-
}
|
|
4576
|
-
const identifierMatch = formula.slice(index).match(/^[A-Z]+[1-9]\d*(?::[A-Z]+[1-9]\d*)?|^[A-Z]+/i);
|
|
4577
|
-
if (identifierMatch?.[0]) {
|
|
4578
|
-
const value = identifierMatch[0].toUpperCase();
|
|
4579
|
-
if (CELL_RANGE_RE.test(value)) tokens.push({ type: "range", value });
|
|
4580
|
-
else if (parseTableCellAddress(value)) tokens.push({ type: "cell", value });
|
|
4581
|
-
else if (SUPPORTED_FUNCTIONS.has(value)) tokens.push({ type: "function", value });
|
|
4582
|
-
else return null;
|
|
4583
|
-
index += identifierMatch[0].length;
|
|
4584
|
-
continue;
|
|
4585
|
-
}
|
|
4586
|
-
return null;
|
|
4587
|
-
}
|
|
4588
|
-
return tokens;
|
|
4589
|
-
}
|
|
4590
|
-
function toFiniteFormulaResult(value) {
|
|
4591
|
-
return Number.isFinite(value) ? { value, error: null } : { value: null, error: "invalid-formula" };
|
|
4592
|
-
}
|
|
4593
|
-
function parseTableCellNumericValue(value) {
|
|
4594
|
-
if (typeof value === "number") {
|
|
4595
|
-
return Number.isFinite(value) ? value : null;
|
|
4596
|
-
}
|
|
4597
|
-
let normalized = String(value ?? "").trim();
|
|
4598
|
-
if (!normalized || normalized.startsWith("#")) return null;
|
|
4599
|
-
const isPercent = normalized.endsWith("%");
|
|
4600
|
-
if (isPercent) normalized = normalized.slice(0, -1).trim();
|
|
4601
|
-
const currencyMatch = normalized.match(/^([+-]?)\$(.+)$/);
|
|
4602
|
-
if (currencyMatch) {
|
|
4603
|
-
normalized = `${currencyMatch[1] ?? ""}${currencyMatch[2] ?? ""}`.trim();
|
|
4604
|
-
}
|
|
4605
|
-
const groupedNumber = /^[+-]?\d{1,3}(?:,\d{3})+(?:\.\d*)?(?:[eE][+-]?\d+)?$/;
|
|
4606
|
-
const plainNumber = /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/;
|
|
4607
|
-
if (!groupedNumber.test(normalized) && !plainNumber.test(normalized)) return null;
|
|
4608
|
-
const parsed = Number(normalized.replace(/,/g, ""));
|
|
4609
|
-
if (!Number.isFinite(parsed)) return null;
|
|
4610
|
-
return isPercent ? parsed / 100 : parsed;
|
|
4611
|
-
}
|
|
4612
|
-
var FormulaParser = class {
|
|
4613
|
-
constructor(tokens, getCellValue) {
|
|
4614
|
-
this.tokens = tokens;
|
|
4615
|
-
this.getCellValue = getCellValue;
|
|
4616
|
-
this.index = 0;
|
|
4617
|
-
}
|
|
4618
|
-
isComplete() {
|
|
4619
|
-
return this.index >= this.tokens.length;
|
|
4620
|
-
}
|
|
4621
|
-
parseExpression() {
|
|
4622
|
-
let left = this.parseTerm();
|
|
4623
|
-
while (!left.error) {
|
|
4624
|
-
const operator = this.peekOperator(["+", "-"]);
|
|
4625
|
-
if (!operator) break;
|
|
4626
|
-
this.index += 1;
|
|
4627
|
-
const right = this.parseTerm();
|
|
4628
|
-
if (right.error) return right;
|
|
4629
|
-
left = toFiniteFormulaResult(operator.value === "+" ? left.value + right.value : left.value - right.value);
|
|
4630
|
-
}
|
|
4631
|
-
return left;
|
|
4632
|
-
}
|
|
4633
|
-
parseTerm() {
|
|
4634
|
-
let left = this.parseFactor();
|
|
4635
|
-
while (!left.error) {
|
|
4636
|
-
const operator = this.peekOperator(["*", "/"]);
|
|
4637
|
-
if (!operator) break;
|
|
4638
|
-
this.index += 1;
|
|
4639
|
-
const right = this.parseFactor();
|
|
4640
|
-
if (right.error) return right;
|
|
4641
|
-
if (operator.value === "/" && right.value === 0) {
|
|
4642
|
-
return { value: null, error: "division-by-zero" };
|
|
4643
|
-
}
|
|
4644
|
-
left = toFiniteFormulaResult(operator.value === "*" ? left.value * right.value : left.value / right.value);
|
|
4645
|
-
}
|
|
4646
|
-
return left;
|
|
4647
|
-
}
|
|
4648
|
-
parseFactor() {
|
|
4649
|
-
const token = this.tokens[this.index];
|
|
4650
|
-
if (!token) {
|
|
4651
|
-
return { value: null, error: "invalid-formula" };
|
|
4652
|
-
}
|
|
4653
|
-
if (token.type === "operator" && (token.value === "-" || token.value === "+")) {
|
|
4654
|
-
this.index += 1;
|
|
4655
|
-
const value = this.parseFactor();
|
|
4656
|
-
if (value.error) return value;
|
|
4657
|
-
return toFiniteFormulaResult(token.value === "-" ? -value.value : value.value);
|
|
4658
|
-
}
|
|
4659
|
-
if (token.type === "number") {
|
|
4660
|
-
this.index += 1;
|
|
4661
|
-
return { value: token.value, error: null };
|
|
4662
|
-
}
|
|
4663
|
-
if (token.type === "cell") {
|
|
4664
|
-
this.index += 1;
|
|
4665
|
-
return this.readCellNumber(token.value);
|
|
4666
|
-
}
|
|
4667
|
-
if (token.type === "function") {
|
|
4668
|
-
return this.parseFunction(token.value);
|
|
4669
|
-
}
|
|
4670
|
-
if (token.type === "paren" && token.value === "(") {
|
|
4671
|
-
this.index += 1;
|
|
4672
|
-
const value = this.parseExpression();
|
|
4673
|
-
if (value.error) return value;
|
|
4674
|
-
if (!this.consumeParen(")")) {
|
|
4675
|
-
return { value: null, error: "invalid-formula" };
|
|
4676
|
-
}
|
|
4677
|
-
return value;
|
|
4678
|
-
}
|
|
4679
|
-
return { value: null, error: "invalid-formula" };
|
|
4680
|
-
}
|
|
4681
|
-
parseFunction(name) {
|
|
4682
|
-
this.index += 1;
|
|
4683
|
-
if (!this.consumeParen("(")) {
|
|
4684
|
-
return { value: null, error: "invalid-formula" };
|
|
4685
|
-
}
|
|
4686
|
-
const values = [];
|
|
4687
|
-
while (true) {
|
|
4688
|
-
const token = this.tokens[this.index];
|
|
4689
|
-
if (!token) {
|
|
4690
|
-
return { value: null, error: "invalid-formula" };
|
|
4691
|
-
}
|
|
4692
|
-
if (token.type === "range") {
|
|
4693
|
-
this.index += 1;
|
|
4694
|
-
const range = parseTableCellRange(token.value);
|
|
4695
|
-
if (!range) return { value: null, error: "invalid-reference" };
|
|
4696
|
-
for (const label of getTableCellRangeLabels(range)) {
|
|
4697
|
-
if (name === "COUNT") {
|
|
4698
|
-
const cellValue2 = this.readOptionalCellNumber(label);
|
|
4699
|
-
if (cellValue2 != null) values.push(cellValue2);
|
|
4700
|
-
continue;
|
|
4701
|
-
}
|
|
4702
|
-
const cellValue = this.readOptionalCellNumber(label);
|
|
4703
|
-
if (cellValue != null) values.push(cellValue);
|
|
4704
|
-
}
|
|
4705
|
-
} else if (token.type === "cell") {
|
|
4706
|
-
this.index += 1;
|
|
4707
|
-
const cellValue = this.readOptionalCellNumber(token.value);
|
|
4708
|
-
if (cellValue != null) values.push(cellValue);
|
|
4709
|
-
} else {
|
|
4710
|
-
const value = this.parseExpression();
|
|
4711
|
-
if (value.error) return value;
|
|
4712
|
-
values.push(value.value);
|
|
4713
|
-
}
|
|
4714
|
-
if (this.consumeComma()) {
|
|
4715
|
-
continue;
|
|
4716
|
-
}
|
|
4717
|
-
if (this.consumeParen(")")) {
|
|
4718
|
-
break;
|
|
4719
|
-
}
|
|
4720
|
-
return { value: null, error: "invalid-formula" };
|
|
4721
|
-
}
|
|
4722
|
-
if (name === "SUM") return toFiniteFormulaResult(values.reduce((sum, value) => sum + value, 0));
|
|
4723
|
-
if (name === "AVG") {
|
|
4724
|
-
return values.length > 0 ? toFiniteFormulaResult(values.reduce((sum, value) => sum + value, 0) / values.length) : { value: null, error: "division-by-zero" };
|
|
4725
|
-
}
|
|
4726
|
-
if (name === "MIN") return toFiniteFormulaResult(values.length > 0 ? Math.min(...values) : 0);
|
|
4727
|
-
if (name === "MAX") return toFiniteFormulaResult(values.length > 0 ? Math.max(...values) : 0);
|
|
4728
|
-
if (name === "COUNT") return { value: values.length, error: null };
|
|
4729
|
-
return { value: null, error: "invalid-formula" };
|
|
4730
|
-
}
|
|
4731
|
-
readCellNumber(label) {
|
|
4732
|
-
const parsed = parseTableCellNumericValue(this.getCellValue(label));
|
|
4733
|
-
if (parsed == null) {
|
|
4734
|
-
return { value: null, error: "invalid-reference" };
|
|
4735
|
-
}
|
|
4736
|
-
return { value: parsed, error: null };
|
|
4737
|
-
}
|
|
4738
|
-
readOptionalCellNumber(label) {
|
|
4739
|
-
return parseTableCellNumericValue(this.getCellValue(label));
|
|
4740
|
-
}
|
|
4741
|
-
peekOperator(operators) {
|
|
4742
|
-
const token = this.tokens[this.index];
|
|
4743
|
-
return token?.type === "operator" && operators.includes(token.value) ? token : null;
|
|
4744
|
-
}
|
|
4745
|
-
consumeComma() {
|
|
4746
|
-
if (this.tokens[this.index]?.type !== "comma") {
|
|
4747
|
-
return false;
|
|
4748
|
-
}
|
|
4749
|
-
this.index += 1;
|
|
4750
|
-
return true;
|
|
4751
|
-
}
|
|
4752
|
-
consumeParen(value) {
|
|
4753
|
-
const token = this.tokens[this.index];
|
|
4754
|
-
if (token?.type !== "paren" || token.value !== value) {
|
|
4755
|
-
return false;
|
|
4756
|
-
}
|
|
4757
|
-
this.index += 1;
|
|
4758
|
-
return true;
|
|
4759
|
-
}
|
|
4760
|
-
};
|
|
4761
|
-
|
|
4762
|
-
// src/components/UEditor/table-formula-commands.ts
|
|
4747
|
+
import { TextSelection as TextSelection2 } from "@tiptap/pm/state";
|
|
4748
|
+
import { selectedRect as selectedRect2, setCellAttr, TableMap as TableMap2 } from "@tiptap/pm/tables";
|
|
4763
4749
|
var UEDITOR_TABLE_FORMULA_RECALCULATE_META = "ueditorTableFormulaRecalculate";
|
|
4764
4750
|
var TABLE_FORMULA_PLAN_CACHE_LIMIT = 50;
|
|
4765
4751
|
var tableFormulaPlanCache = /* @__PURE__ */ new Map();
|
|
@@ -4891,7 +4877,7 @@ function restoreSelectionAtTableCell(editor, anchor) {
|
|
|
4891
4877
|
if (!cellNode || cellNode.type.name !== "tableCell" && cellNode.type.name !== "tableHeader") return false;
|
|
4892
4878
|
const selectionPos = Math.min(cellPos + 2, editor.state.doc.content.size);
|
|
4893
4879
|
editor.view.dispatch(
|
|
4894
|
-
editor.state.tr.setSelection(
|
|
4880
|
+
editor.state.tr.setSelection(TextSelection2.near(editor.state.doc.resolve(selectionPos))).setMeta("addToHistory", false)
|
|
4895
4881
|
);
|
|
4896
4882
|
return true;
|
|
4897
4883
|
}
|
|
@@ -5021,7 +5007,7 @@ function removeSelectedTableCellFormula(editor, clearContent) {
|
|
|
5021
5007
|
);
|
|
5022
5008
|
let transaction = editor.state.tr.replaceWith(selectedCell.cellPos, selectedCell.cellPos + selectedCell.node.nodeSize, nextCell2).setMeta(UEDITOR_TABLE_FORMULA_RECALCULATE_META, true);
|
|
5023
5009
|
const selectionPos = Math.min(selectedCell.cellPos + 2, transaction.doc.content.size);
|
|
5024
|
-
transaction = transaction.setSelection(
|
|
5010
|
+
transaction = transaction.setSelection(TextSelection2.near(transaction.doc.resolve(selectionPos)));
|
|
5025
5011
|
editor.view.dispatch(transaction);
|
|
5026
5012
|
recalculateActiveTableFormulas(editor);
|
|
5027
5013
|
restoreSelectionAtTableCell(editor, selectedCell);
|
|
@@ -5221,7 +5207,7 @@ function createActiveTableFormulaRecalculationTransaction(state, options) {
|
|
|
5221
5207
|
return applyTableCellReplacements(state.tr, replacements).setMeta(UEDITOR_TABLE_FORMULA_RECALCULATE_META, true);
|
|
5222
5208
|
}
|
|
5223
5209
|
function recalculateSelectedTable(editor) {
|
|
5224
|
-
const rect =
|
|
5210
|
+
const rect = selectedRect2(editor.state);
|
|
5225
5211
|
const tableNode = rect.table;
|
|
5226
5212
|
return dispatchTableCellReplacements(
|
|
5227
5213
|
editor,
|
|
@@ -5639,6 +5625,7 @@ function buildUEditorExtensions({
|
|
|
5639
5625
|
maxImageFileSize,
|
|
5640
5626
|
allowedImageMimeTypes,
|
|
5641
5627
|
fallbackToDataUrl,
|
|
5628
|
+
onImageUploadError,
|
|
5642
5629
|
editable = true,
|
|
5643
5630
|
fetchMetadata
|
|
5644
5631
|
}) {
|
|
@@ -5706,7 +5693,8 @@ function buildUEditorExtensions({
|
|
|
5706
5693
|
insertMode: imageInsertMode,
|
|
5707
5694
|
...maxImageFileSize !== void 0 ? { maxFileSize: maxImageFileSize } : {},
|
|
5708
5695
|
...allowedImageMimeTypes ? { allowedMimeTypes: allowedImageMimeTypes } : {},
|
|
5709
|
-
...fallbackToDataUrl !== void 0 ? { fallbackToDataUrl } : {}
|
|
5696
|
+
...fallbackToDataUrl !== void 0 ? { fallbackToDataUrl } : {},
|
|
5697
|
+
onError: onImageUploadError
|
|
5710
5698
|
}),
|
|
5711
5699
|
TextStyle,
|
|
5712
5700
|
font_family_default,
|
|
@@ -5819,7 +5807,7 @@ import {
|
|
|
5819
5807
|
} from "lucide-react";
|
|
5820
5808
|
|
|
5821
5809
|
// src/components/UEditor/table-border-commands.ts
|
|
5822
|
-
import { selectedRect as
|
|
5810
|
+
import { selectedRect as selectedRect3 } from "@tiptap/pm/tables";
|
|
5823
5811
|
var SIDES = ["top", "right", "bottom", "left"];
|
|
5824
5812
|
var OPPOSITE_SIDE = {
|
|
5825
5813
|
top: "bottom",
|
|
@@ -5890,7 +5878,7 @@ function getAppliedSides(position, cell, selection) {
|
|
|
5890
5878
|
}
|
|
5891
5879
|
function applyTableCellBorders(editor, position, format, options = {}) {
|
|
5892
5880
|
const { state, view } = editor;
|
|
5893
|
-
const selection =
|
|
5881
|
+
const selection = selectedRect3(state);
|
|
5894
5882
|
const transaction = state.tr;
|
|
5895
5883
|
const cellPositions = new Set(selection.map.cellsInRect(selection));
|
|
5896
5884
|
const sidesByCell = /* @__PURE__ */ new Map();
|
|
@@ -7149,6 +7137,8 @@ var CustomBubbleMenu = ({
|
|
|
7149
7137
|
editor.on("transaction", schedulePositionUpdate);
|
|
7150
7138
|
editor.on("focus", schedulePositionUpdate);
|
|
7151
7139
|
editor.on("blur", handleBlur);
|
|
7140
|
+
editorWindow?.addEventListener("resize", schedulePositionUpdate);
|
|
7141
|
+
editorWindow?.addEventListener("scroll", schedulePositionUpdate, true);
|
|
7152
7142
|
updatePositionRef.current = updatePosition;
|
|
7153
7143
|
schedulePositionUpdate();
|
|
7154
7144
|
return () => {
|
|
@@ -7159,6 +7149,8 @@ var CustomBubbleMenu = ({
|
|
|
7159
7149
|
editor.off("transaction", schedulePositionUpdate);
|
|
7160
7150
|
editor.off("focus", schedulePositionUpdate);
|
|
7161
7151
|
editor.off("blur", handleBlur);
|
|
7152
|
+
editorWindow?.removeEventListener("resize", schedulePositionUpdate);
|
|
7153
|
+
editorWindow?.removeEventListener("scroll", schedulePositionUpdate, true);
|
|
7162
7154
|
};
|
|
7163
7155
|
}, [editor, editorDocument, editorWindow]);
|
|
7164
7156
|
useEffect5(() => {
|
|
@@ -7292,12 +7284,16 @@ var CustomFloatingMenu = ({ editor }) => {
|
|
|
7292
7284
|
editor.on("transaction", schedulePositionUpdate);
|
|
7293
7285
|
editor.on("focus", schedulePositionUpdate);
|
|
7294
7286
|
editor.on("blur", handleBlur);
|
|
7287
|
+
editorWindow?.addEventListener("resize", schedulePositionUpdate);
|
|
7288
|
+
editorWindow?.addEventListener("scroll", schedulePositionUpdate, true);
|
|
7295
7289
|
schedulePositionUpdate();
|
|
7296
7290
|
return () => {
|
|
7297
7291
|
if (animationFrameId !== null) editorWindow?.cancelAnimationFrame(animationFrameId);
|
|
7298
7292
|
editor.off("transaction", schedulePositionUpdate);
|
|
7299
7293
|
editor.off("focus", schedulePositionUpdate);
|
|
7300
7294
|
editor.off("blur", handleBlur);
|
|
7295
|
+
editorWindow?.removeEventListener("resize", schedulePositionUpdate);
|
|
7296
|
+
editorWindow?.removeEventListener("scroll", schedulePositionUpdate, true);
|
|
7301
7297
|
};
|
|
7302
7298
|
}, [editor, editorWindow]);
|
|
7303
7299
|
if (!isVisible || !portalContainer) return null;
|
|
@@ -7356,7 +7352,7 @@ var CharacterCountDisplay = ({ editor, maxCharacters }) => {
|
|
|
7356
7352
|
};
|
|
7357
7353
|
|
|
7358
7354
|
// src/components/UEditor/table-controls.tsx
|
|
7359
|
-
import
|
|
7355
|
+
import React11 from "react";
|
|
7360
7356
|
|
|
7361
7357
|
// node_modules/prosemirror-model/dist/index.js
|
|
7362
7358
|
function findDiffStart(a, b, pos) {
|
|
@@ -10008,7 +10004,7 @@ var Selection = class {
|
|
|
10008
10004
|
found.
|
|
10009
10005
|
*/
|
|
10010
10006
|
static findFrom($pos, dir, textOnly = false) {
|
|
10011
|
-
let inner = $pos.parent.inlineContent ? new
|
|
10007
|
+
let inner = $pos.parent.inlineContent ? new TextSelection3($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly);
|
|
10012
10008
|
if (inner)
|
|
10013
10009
|
return inner;
|
|
10014
10010
|
for (let depth = $pos.depth - 1; depth >= 0; depth--) {
|
|
@@ -10077,7 +10073,7 @@ var Selection = class {
|
|
|
10077
10073
|
returns the bookmark for that.
|
|
10078
10074
|
*/
|
|
10079
10075
|
getBookmark() {
|
|
10080
|
-
return
|
|
10076
|
+
return TextSelection3.between(this.$anchor, this.$head).getBookmark();
|
|
10081
10077
|
}
|
|
10082
10078
|
};
|
|
10083
10079
|
Selection.prototype.visible = true;
|
|
@@ -10097,7 +10093,7 @@ function checkTextSelection($pos) {
|
|
|
10097
10093
|
console["warn"]("TextSelection endpoint not pointing into a node with inline content (" + $pos.parent.type.name + ")");
|
|
10098
10094
|
}
|
|
10099
10095
|
}
|
|
10100
|
-
var
|
|
10096
|
+
var TextSelection3 = class _TextSelection extends Selection {
|
|
10101
10097
|
/**
|
|
10102
10098
|
Construct a text selection between the given points.
|
|
10103
10099
|
*/
|
|
@@ -10183,7 +10179,7 @@ var TextSelection2 = class _TextSelection extends Selection {
|
|
|
10183
10179
|
return new _TextSelection($anchor, $head);
|
|
10184
10180
|
}
|
|
10185
10181
|
};
|
|
10186
|
-
Selection.jsonID("text",
|
|
10182
|
+
Selection.jsonID("text", TextSelection3);
|
|
10187
10183
|
var TextBookmark = class _TextBookmark {
|
|
10188
10184
|
constructor(anchor, head) {
|
|
10189
10185
|
this.anchor = anchor;
|
|
@@ -10193,7 +10189,7 @@ var TextBookmark = class _TextBookmark {
|
|
|
10193
10189
|
return new _TextBookmark(mapping.map(this.anchor), mapping.map(this.head));
|
|
10194
10190
|
}
|
|
10195
10191
|
resolve(doc) {
|
|
10196
|
-
return
|
|
10192
|
+
return TextSelection3.between(doc.resolve(this.anchor), doc.resolve(this.head));
|
|
10197
10193
|
}
|
|
10198
10194
|
};
|
|
10199
10195
|
var NodeSelection = class _NodeSelection extends Selection {
|
|
@@ -10312,7 +10308,7 @@ var AllBookmark = {
|
|
|
10312
10308
|
};
|
|
10313
10309
|
function findSelectionIn(doc, node, pos, index, dir, text = false) {
|
|
10314
10310
|
if (node.inlineContent)
|
|
10315
|
-
return
|
|
10311
|
+
return TextSelection3.create(doc, pos);
|
|
10316
10312
|
for (let i = index - (dir > 0 ? 0 : 1); dir > 0 ? i < node.childCount : i >= 0; i += dir) {
|
|
10317
10313
|
let child = node.child(i);
|
|
10318
10314
|
if (!child.isAtom) {
|
|
@@ -10812,7 +10808,7 @@ function freshColWidth(attrs) {
|
|
|
10812
10808
|
for (let i = 0; i < attrs.colspan; i++) result.push(0);
|
|
10813
10809
|
return result;
|
|
10814
10810
|
}
|
|
10815
|
-
function
|
|
10811
|
+
function tableNodeTypes3(schema) {
|
|
10816
10812
|
let result = schema.cached.tableNodeTypes;
|
|
10817
10813
|
if (!result) {
|
|
10818
10814
|
result = schema.cached.tableNodeTypes = {};
|
|
@@ -10904,7 +10900,7 @@ var CellSelection2 = class CellSelection3 extends Selection {
|
|
|
10904
10900
|
else if (tableChanged && this.isColSelection()) return CellSelection3.colSelection($anchorCell, $headCell);
|
|
10905
10901
|
else return new CellSelection3($anchorCell, $headCell);
|
|
10906
10902
|
}
|
|
10907
|
-
return
|
|
10903
|
+
return TextSelection3.between($anchorCell, $headCell);
|
|
10908
10904
|
}
|
|
10909
10905
|
content() {
|
|
10910
10906
|
const table = this.$anchorCell.node(-1);
|
|
@@ -11329,7 +11325,7 @@ function moveTableRow$1(table, indexesOrigin, indexesTarget, direction) {
|
|
|
11329
11325
|
rows = moveRowInArrayOfRows(rows, indexesOrigin, indexesTarget, direction);
|
|
11330
11326
|
return convertArrayOfRowsToTableNode(table, rows);
|
|
11331
11327
|
}
|
|
11332
|
-
function
|
|
11328
|
+
function selectedRect4(state) {
|
|
11333
11329
|
const sel = state.selection;
|
|
11334
11330
|
const $pos = selectionCell(state);
|
|
11335
11331
|
const table = $pos.node(-1);
|
|
@@ -11346,8 +11342,8 @@ function deprecated_toggleHeader(type) {
|
|
|
11346
11342
|
return function(state, dispatch) {
|
|
11347
11343
|
if (!isInTable2(state)) return false;
|
|
11348
11344
|
if (dispatch) {
|
|
11349
|
-
const types =
|
|
11350
|
-
const rect =
|
|
11345
|
+
const types = tableNodeTypes3(state.schema);
|
|
11346
|
+
const rect = selectedRect4(state), tr = state.tr;
|
|
11351
11347
|
const cells = rect.map.cellsInRect(type == "column" ? {
|
|
11352
11348
|
left: rect.left,
|
|
11353
11349
|
top: 0,
|
|
@@ -11386,8 +11382,8 @@ function toggleHeader(type, options) {
|
|
|
11386
11382
|
return function(state, dispatch) {
|
|
11387
11383
|
if (!isInTable2(state)) return false;
|
|
11388
11384
|
if (dispatch) {
|
|
11389
|
-
const types =
|
|
11390
|
-
const rect =
|
|
11385
|
+
const types = tableNodeTypes3(state.schema);
|
|
11386
|
+
const rect = selectedRect4(state), tr = state.tr;
|
|
11391
11387
|
const isHeaderRowEnabled = isHeaderEnabledByType("row", rect, types);
|
|
11392
11388
|
const isHeaderColumnEnabled = isHeaderEnabledByType("column", rect, types);
|
|
11393
11389
|
const selectionStartsAt = (type === "column" ? isHeaderRowEnabled : type === "row" ? isHeaderColumnEnabled : false) ? 1 : 0;
|
|
@@ -11421,7 +11417,7 @@ function deleteCellSelection(state, dispatch) {
|
|
|
11421
11417
|
if (!(sel instanceof CellSelection2)) return false;
|
|
11422
11418
|
if (dispatch) {
|
|
11423
11419
|
const tr = state.tr;
|
|
11424
|
-
const baseContent =
|
|
11420
|
+
const baseContent = tableNodeTypes3(state.schema).cell.createAndFill().content;
|
|
11425
11421
|
sel.forEachCell((cell, pos) => {
|
|
11426
11422
|
if (!cell.content.eq(baseContent)) tr.replace(tr.mapping.map(pos + 1), tr.mapping.map(pos + cell.nodeSize - 1), new Slice(baseContent, 0, 0));
|
|
11427
11423
|
});
|
|
@@ -11519,7 +11515,7 @@ function shiftArrow(axis, dir) {
|
|
|
11519
11515
|
};
|
|
11520
11516
|
}
|
|
11521
11517
|
function atEndOfCell(view, axis, dir) {
|
|
11522
|
-
if (!(view.state.selection instanceof
|
|
11518
|
+
if (!(view.state.selection instanceof TextSelection3)) return null;
|
|
11523
11519
|
const { $head } = view.state.selection;
|
|
11524
11520
|
for (let d = $head.depth - 1; d >= 0; d--) {
|
|
11525
11521
|
const parent = $head.node(d);
|
|
@@ -11836,7 +11832,8 @@ function buildTableControlLayout(editor, surface, cell) {
|
|
|
11836
11832
|
avgRowHeight,
|
|
11837
11833
|
avgColumnWidth,
|
|
11838
11834
|
rowHandles,
|
|
11839
|
-
columnHandles
|
|
11835
|
+
columnHandles,
|
|
11836
|
+
widthMode: normalizeTableWidthMode(tableInfo.node.attrs.widthMode)
|
|
11840
11837
|
};
|
|
11841
11838
|
}
|
|
11842
11839
|
|
|
@@ -12011,6 +12008,8 @@ function TableAddRails({
|
|
|
12011
12008
|
layout,
|
|
12012
12009
|
onStartAddColumn,
|
|
12013
12010
|
onStartAddRow,
|
|
12011
|
+
onAddColumn,
|
|
12012
|
+
onAddRow,
|
|
12014
12013
|
quickAddColumnLabel,
|
|
12015
12014
|
quickAddRowLabel
|
|
12016
12015
|
}) {
|
|
@@ -12033,17 +12032,16 @@ function TableAddRails({
|
|
|
12033
12032
|
type: "button",
|
|
12034
12033
|
"data-table-control": "add-column",
|
|
12035
12034
|
"aria-label": quickAddColumnLabel,
|
|
12036
|
-
|
|
12037
|
-
|
|
12038
|
-
|
|
12039
|
-
if (
|
|
12040
|
-
onStartAddColumn();
|
|
12035
|
+
tabIndex: showColumnRail ? 0 : -1,
|
|
12036
|
+
onPointerDown: onStartAddColumn,
|
|
12037
|
+
onClick: (event) => {
|
|
12038
|
+
if (event.detail === 0 && canExpandTable) onAddColumn();
|
|
12041
12039
|
},
|
|
12042
12040
|
disabled: !canExpandTable,
|
|
12043
12041
|
className: cn(
|
|
12044
12042
|
"absolute z-30 inline-flex items-center justify-center rounded-md",
|
|
12045
12043
|
"border border-border/70 bg-muted/40 text-muted-foreground shadow-sm backdrop-blur",
|
|
12046
|
-
"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"
|
|
12047
12045
|
),
|
|
12048
12046
|
style: {
|
|
12049
12047
|
top: columnRailTop,
|
|
@@ -12070,17 +12068,16 @@ function TableAddRails({
|
|
|
12070
12068
|
type: "button",
|
|
12071
12069
|
"data-table-control": "add-row",
|
|
12072
12070
|
"aria-label": quickAddRowLabel,
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
if (
|
|
12077
|
-
onStartAddRow();
|
|
12071
|
+
tabIndex: showRowRail ? 0 : -1,
|
|
12072
|
+
onPointerDown: onStartAddRow,
|
|
12073
|
+
onClick: (event) => {
|
|
12074
|
+
if (event.detail === 0 && canExpandTable) onAddRow();
|
|
12078
12075
|
},
|
|
12079
12076
|
disabled: !canExpandTable,
|
|
12080
12077
|
className: cn(
|
|
12081
12078
|
"absolute z-30 inline-flex items-center justify-center rounded-md",
|
|
12082
12079
|
"border border-border/70 bg-muted/40 text-muted-foreground shadow-sm backdrop-blur",
|
|
12083
|
-
"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"
|
|
12084
12081
|
),
|
|
12085
12082
|
style: {
|
|
12086
12083
|
top: rowRailTop,
|
|
@@ -12173,6 +12170,7 @@ function TableRowHandles({
|
|
|
12173
12170
|
getMenuItems,
|
|
12174
12171
|
hoverRowHandleIndex,
|
|
12175
12172
|
onOpenMenuChange,
|
|
12173
|
+
onMove,
|
|
12176
12174
|
onStartDrag,
|
|
12177
12175
|
openMenuKey,
|
|
12178
12176
|
rowDragLabel,
|
|
@@ -12213,13 +12211,16 @@ function TableRowHandles({
|
|
|
12213
12211
|
{
|
|
12214
12212
|
type: "button",
|
|
12215
12213
|
"aria-label": `${rowDragLabel} ${rowHandle.index + 1}`,
|
|
12216
|
-
|
|
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;
|
|
12217
12218
|
event.preventDefault();
|
|
12218
12219
|
event.stopPropagation();
|
|
12219
|
-
|
|
12220
|
+
onMove(rowHandle, event.key === "ArrowUp" ? -1 : 1);
|
|
12220
12221
|
},
|
|
12221
12222
|
className: cn(
|
|
12222
|
-
"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",
|
|
12223
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"
|
|
12224
12225
|
),
|
|
12225
12226
|
style: {
|
|
@@ -12230,7 +12231,7 @@ function TableRowHandles({
|
|
|
12230
12231
|
// selection near the first character of a table cell.
|
|
12231
12232
|
pointerEvents: visible ? "auto" : "none"
|
|
12232
12233
|
},
|
|
12233
|
-
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" })
|
|
12234
12235
|
}
|
|
12235
12236
|
)
|
|
12236
12237
|
}
|
|
@@ -12251,6 +12252,7 @@ function TableColumnHandles({
|
|
|
12251
12252
|
getMenuItems,
|
|
12252
12253
|
hoverColumnHandleIndex,
|
|
12253
12254
|
onOpenMenuChange,
|
|
12255
|
+
onMove,
|
|
12254
12256
|
onStartDrag,
|
|
12255
12257
|
openMenuKey
|
|
12256
12258
|
}) {
|
|
@@ -12288,13 +12290,16 @@ function TableColumnHandles({
|
|
|
12288
12290
|
{
|
|
12289
12291
|
type: "button",
|
|
12290
12292
|
"aria-label": `${columnDragLabel} ${columnHandle.index + 1}`,
|
|
12291
|
-
|
|
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;
|
|
12292
12297
|
event.preventDefault();
|
|
12293
12298
|
event.stopPropagation();
|
|
12294
|
-
|
|
12299
|
+
onMove(columnHandle, event.key === "ArrowLeft" ? -1 : 1);
|
|
12295
12300
|
},
|
|
12296
12301
|
className: cn(
|
|
12297
|
-
"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",
|
|
12298
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"
|
|
12299
12304
|
),
|
|
12300
12305
|
style: {
|
|
@@ -12302,7 +12307,7 @@ function TableColumnHandles({
|
|
|
12302
12307
|
transform: isShown ? "scale(1)" : `scale(${IDLE_HANDLE_SCALE})`,
|
|
12303
12308
|
pointerEvents: visible ? "auto" : "none"
|
|
12304
12309
|
},
|
|
12305
|
-
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" })
|
|
12306
12311
|
}
|
|
12307
12312
|
)
|
|
12308
12313
|
}
|
|
@@ -12317,7 +12322,7 @@ function TableColumnHandles({
|
|
|
12317
12322
|
|
|
12318
12323
|
// src/components/UEditor/table-resize-handles.tsx
|
|
12319
12324
|
import { MoveDiagonal2 } from "lucide-react";
|
|
12320
|
-
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
12325
|
+
import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
12321
12326
|
var HANDLE_BASE_CLASS = cn(
|
|
12322
12327
|
"pointer-events-auto absolute z-10 inline-flex touch-none items-center justify-center rounded-md",
|
|
12323
12328
|
"bg-background/95 text-primary shadow-sm backdrop-blur-sm",
|
|
@@ -12325,11 +12330,30 @@ var HANDLE_BASE_CLASS = cn(
|
|
|
12325
12330
|
"hover:bg-primary hover:text-primary-foreground hover:shadow-md active:scale-95",
|
|
12326
12331
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
12327
12332
|
);
|
|
12333
|
+
var EDGE_HANDLE_CLASS = cn(
|
|
12334
|
+
"pointer-events-auto absolute top-0 z-10 h-full w-2 touch-none cursor-col-resize bg-transparent p-0",
|
|
12335
|
+
"border-transparent transition-colors duration-150 hover:border-primary",
|
|
12336
|
+
"focus-visible:border-primary focus-visible:outline-none"
|
|
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
|
+
}
|
|
12328
12350
|
function TableResizeHandles({
|
|
12329
12351
|
active,
|
|
12330
12352
|
ctrlHint,
|
|
12331
12353
|
frameRef,
|
|
12332
12354
|
layout,
|
|
12355
|
+
onFitWidth,
|
|
12356
|
+
onKeyboardResize,
|
|
12333
12357
|
onStartResize,
|
|
12334
12358
|
resizeBothLabel
|
|
12335
12359
|
}) {
|
|
@@ -12350,6 +12374,38 @@ function TableResizeHandles({
|
|
|
12350
12374
|
height: layout.tableHeight
|
|
12351
12375
|
},
|
|
12352
12376
|
children: [
|
|
12377
|
+
layout.widthMode === "responsive" ? /* @__PURE__ */ jsxs14(Fragment6, { children: [
|
|
12378
|
+
/* @__PURE__ */ jsx17(
|
|
12379
|
+
"button",
|
|
12380
|
+
{
|
|
12381
|
+
type: "button",
|
|
12382
|
+
"aria-label": `${resizeBothLabel} \u2014 \u2190`,
|
|
12383
|
+
title: resizeBothLabel,
|
|
12384
|
+
"data-table-resize-handle": "left",
|
|
12385
|
+
className: cn(
|
|
12386
|
+
EDGE_HANDLE_CLASS,
|
|
12387
|
+
"left-0 border-l-2"
|
|
12388
|
+
),
|
|
12389
|
+
onPointerDown: (event) => onStartResize(event, "left"),
|
|
12390
|
+
onKeyDown: (event) => onKeyboardResize(event, "left")
|
|
12391
|
+
}
|
|
12392
|
+
),
|
|
12393
|
+
/* @__PURE__ */ jsx17(
|
|
12394
|
+
"button",
|
|
12395
|
+
{
|
|
12396
|
+
type: "button",
|
|
12397
|
+
"aria-label": `${resizeBothLabel} \u2014 \u2192`,
|
|
12398
|
+
title: resizeBothLabel,
|
|
12399
|
+
"data-table-resize-handle": "right",
|
|
12400
|
+
className: cn(
|
|
12401
|
+
EDGE_HANDLE_CLASS,
|
|
12402
|
+
"right-0 border-r-2"
|
|
12403
|
+
),
|
|
12404
|
+
onPointerDown: (event) => onStartResize(event, "right"),
|
|
12405
|
+
onKeyDown: (event) => onKeyboardResize(event, "right")
|
|
12406
|
+
}
|
|
12407
|
+
)
|
|
12408
|
+
] }) : null,
|
|
12353
12409
|
/* @__PURE__ */ jsx17(
|
|
12354
12410
|
"button",
|
|
12355
12411
|
{
|
|
@@ -12362,7 +12418,12 @@ function TableResizeHandles({
|
|
|
12362
12418
|
"bottom-[-28px] right-[-30px] h-6 w-6 cursor-nwse-resize",
|
|
12363
12419
|
active && "bg-primary text-primary-foreground shadow-md"
|
|
12364
12420
|
),
|
|
12365
|
-
|
|
12421
|
+
onDoubleClick: onFitWidth,
|
|
12422
|
+
onClick: (event) => {
|
|
12423
|
+
if (event.detail === 0) onFitWidth(event);
|
|
12424
|
+
},
|
|
12425
|
+
onPointerDown: (event) => onStartResize(event, "both"),
|
|
12426
|
+
onKeyDown: (event) => onKeyboardResize(event, "both"),
|
|
12366
12427
|
children: /* @__PURE__ */ jsx17(MoveDiagonal2, { "aria-hidden": "true", className: "h-3.5 w-3.5", strokeWidth: 2.25 })
|
|
12367
12428
|
}
|
|
12368
12429
|
),
|
|
@@ -12373,7 +12434,12 @@ function TableResizeHandles({
|
|
|
12373
12434
|
"aria-live": "polite",
|
|
12374
12435
|
"data-table-resize-dimensions": "",
|
|
12375
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",
|
|
12376
|
-
children:
|
|
12437
|
+
children: formatTableResizeDimensionLabel({
|
|
12438
|
+
width: layout.tableWidth,
|
|
12439
|
+
height: layout.tableHeight,
|
|
12440
|
+
widthMode: layout.widthMode,
|
|
12441
|
+
viewportWidth: layout.viewportWidth
|
|
12442
|
+
})
|
|
12377
12443
|
}
|
|
12378
12444
|
) : null
|
|
12379
12445
|
]
|
|
@@ -12424,7 +12490,7 @@ function getLogicalRowHeights(table, fallback) {
|
|
|
12424
12490
|
});
|
|
12425
12491
|
return heights;
|
|
12426
12492
|
}
|
|
12427
|
-
function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
|
|
12493
|
+
function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight, containerWidth = startWidth) {
|
|
12428
12494
|
const tableInfo = findTableInfo(editor, anchorPos);
|
|
12429
12495
|
if (!tableInfo) return null;
|
|
12430
12496
|
const tableMap = TableMap3.get(tableInfo.node);
|
|
@@ -12433,13 +12499,16 @@ function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
|
|
|
12433
12499
|
const safeHeight = Math.max(tableMap.height * MIN_TABLE_ROW_HEIGHT, Math.round(startHeight));
|
|
12434
12500
|
const fallbackColumnWidth = safeWidth / tableMap.width;
|
|
12435
12501
|
const fallbackRowHeight = safeHeight / tableMap.height;
|
|
12502
|
+
const widthMode = normalizeTableWidthMode(tableInfo.node.attrs.widthMode);
|
|
12503
|
+
const safeContainerWidth = Math.max(1, Math.round(containerWidth));
|
|
12504
|
+
const columnWeights = widthMode === "responsive" ? getTableColumnRatios(tableInfo.node) : getLogicalColumnWidths(tableInfo.node, tableMap, fallbackColumnWidth);
|
|
12436
12505
|
return {
|
|
12437
12506
|
anchorPos,
|
|
12438
12507
|
tablePos: tableInfo.pos,
|
|
12439
12508
|
startWidth: safeWidth,
|
|
12440
12509
|
startHeight: safeHeight,
|
|
12441
12510
|
columnWidths: normalizeWeightsToTotal(
|
|
12442
|
-
|
|
12511
|
+
columnWeights,
|
|
12443
12512
|
safeWidth,
|
|
12444
12513
|
MIN_RESIZED_TABLE_COLUMN_WIDTH
|
|
12445
12514
|
),
|
|
@@ -12449,7 +12518,12 @@ function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
|
|
|
12449
12518
|
MIN_TABLE_ROW_HEIGHT
|
|
12450
12519
|
),
|
|
12451
12520
|
minWidth: tableMap.width * MIN_RESIZED_TABLE_COLUMN_WIDTH,
|
|
12452
|
-
minHeight: tableMap.height * MIN_TABLE_ROW_HEIGHT
|
|
12521
|
+
minHeight: tableMap.height * MIN_TABLE_ROW_HEIGHT,
|
|
12522
|
+
containerWidth: safeContainerWidth,
|
|
12523
|
+
widthMode,
|
|
12524
|
+
widthBp: getResponsiveTableWidthBp(tableInfo.node),
|
|
12525
|
+
offsetBp: getResponsiveTableOffsetBp(tableInfo.node),
|
|
12526
|
+
columnRatios: getTableColumnRatios(tableInfo.node)
|
|
12453
12527
|
};
|
|
12454
12528
|
}
|
|
12455
12529
|
function resolveTableResizeDimensions({
|
|
@@ -12457,12 +12531,14 @@ function resolveTableResizeDimensions({
|
|
|
12457
12531
|
deltaY,
|
|
12458
12532
|
lockAxis,
|
|
12459
12533
|
preserveRatio,
|
|
12534
|
+
edge = "both",
|
|
12460
12535
|
snapshot
|
|
12461
12536
|
}) {
|
|
12462
|
-
|
|
12463
|
-
let
|
|
12537
|
+
const horizontalDelta = edge === "left" ? -deltaX : deltaX;
|
|
12538
|
+
let width = snapshot.startWidth + horizontalDelta;
|
|
12539
|
+
let height = edge === "both" ? snapshot.startHeight + deltaY : snapshot.startHeight;
|
|
12464
12540
|
if (preserveRatio) {
|
|
12465
|
-
const horizontalDrag = Math.abs(deltaX) >= Math.abs(deltaY);
|
|
12541
|
+
const horizontalDrag = edge !== "both" || Math.abs(deltaX) >= Math.abs(deltaY);
|
|
12466
12542
|
const scale = horizontalDrag ? width / snapshot.startWidth : height / snapshot.startHeight;
|
|
12467
12543
|
const minScale = Math.max(
|
|
12468
12544
|
snapshot.minWidth / snapshot.startWidth,
|
|
@@ -12475,22 +12551,56 @@ function resolveTableResizeDimensions({
|
|
|
12475
12551
|
const safeScale = Math.min(Math.max(scale, minScale), maxScale);
|
|
12476
12552
|
width = snapshot.startWidth * safeScale;
|
|
12477
12553
|
height = snapshot.startHeight * safeScale;
|
|
12478
|
-
} else if (lockAxis) {
|
|
12554
|
+
} else if (lockAxis && edge === "both") {
|
|
12479
12555
|
if (Math.abs(deltaX) >= Math.abs(deltaY)) {
|
|
12480
12556
|
height = snapshot.startHeight;
|
|
12481
12557
|
} else {
|
|
12482
12558
|
width = snapshot.startWidth;
|
|
12483
12559
|
}
|
|
12484
12560
|
}
|
|
12561
|
+
let nextWidth = Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minWidth, Math.round(width)));
|
|
12562
|
+
const nextHeight = Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minHeight, Math.round(height)));
|
|
12563
|
+
if (snapshot.widthMode !== "responsive") {
|
|
12564
|
+
return { width: nextWidth, height: nextHeight };
|
|
12565
|
+
}
|
|
12566
|
+
const containerWidth = Math.max(1, snapshot.containerWidth);
|
|
12567
|
+
const startOffset = snapshot.offsetBp / TABLE_WIDTH_BASIS_POINTS * containerWidth;
|
|
12568
|
+
let nextOffset = startOffset;
|
|
12569
|
+
if (edge === "left") {
|
|
12570
|
+
const fixedRightEdge = startOffset + snapshot.startWidth;
|
|
12571
|
+
nextOffset = Math.min(
|
|
12572
|
+
fixedRightEdge - snapshot.minWidth,
|
|
12573
|
+
Math.max(0, startOffset + deltaX)
|
|
12574
|
+
);
|
|
12575
|
+
nextWidth = fixedRightEdge - nextOffset;
|
|
12576
|
+
}
|
|
12577
|
+
const widthBp = clampResponsiveTableWidthBp(
|
|
12578
|
+
nextWidth / containerWidth * TABLE_WIDTH_BASIS_POINTS
|
|
12579
|
+
);
|
|
12580
|
+
const offsetBp = resolveResponsiveTableOffsetBp(
|
|
12581
|
+
widthBp,
|
|
12582
|
+
null,
|
|
12583
|
+
nextOffset / containerWidth * TABLE_WIDTH_BASIS_POINTS
|
|
12584
|
+
);
|
|
12485
12585
|
return {
|
|
12486
|
-
width: Math.
|
|
12487
|
-
height:
|
|
12586
|
+
width: Math.round(widthBp / TABLE_WIDTH_BASIS_POINTS * containerWidth),
|
|
12587
|
+
height: nextHeight,
|
|
12588
|
+
widthBp,
|
|
12589
|
+
offsetBp,
|
|
12590
|
+
leftDelta: nextOffset - startOffset
|
|
12488
12591
|
};
|
|
12489
12592
|
}
|
|
12490
12593
|
function arraysEqual(left, right) {
|
|
12491
12594
|
return Array.isArray(left) && left.length === right.length && left.every((value, index) => value === right[index]);
|
|
12492
12595
|
}
|
|
12493
|
-
function
|
|
12596
|
+
function getResponsiveResizeAlignment(widthBp, offsetBp) {
|
|
12597
|
+
const gap = Math.max(0, TABLE_WIDTH_BASIS_POINTS - widthBp);
|
|
12598
|
+
if (offsetBp === 0) return "left";
|
|
12599
|
+
if (offsetBp === gap) return "right";
|
|
12600
|
+
if (Math.abs(offsetBp * 2 - gap) <= 1) return "center";
|
|
12601
|
+
return null;
|
|
12602
|
+
}
|
|
12603
|
+
function applyTableSize(editor, snapshot, dimensions, options = {}) {
|
|
12494
12604
|
const table = editor.state.doc.nodeAt(snapshot.tablePos);
|
|
12495
12605
|
if (!table || table.type.name !== "table") return false;
|
|
12496
12606
|
const tableMap = TableMap3.get(table);
|
|
@@ -12499,9 +12609,32 @@ function applyTableSize(editor, snapshot, dimensions) {
|
|
|
12499
12609
|
}
|
|
12500
12610
|
const resizeWidth = dimensions.width !== snapshot.startWidth;
|
|
12501
12611
|
const resizeHeight = dimensions.height !== snapshot.startHeight;
|
|
12502
|
-
|
|
12612
|
+
const widthMode = options.widthMode ?? snapshot.widthMode;
|
|
12613
|
+
const widthModeChanged = normalizeTableWidthMode(table.attrs.widthMode) !== widthMode || widthMode === "responsive" && table.attrs.widthMode !== "responsive";
|
|
12614
|
+
const widthBp = dimensions.widthBp ?? clampResponsiveTableWidthBp(
|
|
12615
|
+
dimensions.width / Math.max(1, snapshot.containerWidth) * TABLE_WIDTH_BASIS_POINTS
|
|
12616
|
+
);
|
|
12617
|
+
const offsetBp = resolveResponsiveTableOffsetBp(
|
|
12618
|
+
widthBp,
|
|
12619
|
+
null,
|
|
12620
|
+
dimensions.offsetBp ?? snapshot.offsetBp
|
|
12621
|
+
);
|
|
12622
|
+
const responsiveLayoutChanged = widthMode === "responsive" && (table.attrs.widthBp !== widthBp || table.attrs.offsetBp !== offsetBp);
|
|
12623
|
+
if (!resizeWidth && !resizeHeight && !widthModeChanged && !responsiveLayoutChanged) return false;
|
|
12503
12624
|
const tableStart = snapshot.tablePos + 1;
|
|
12504
12625
|
const transaction = editor.state.tr;
|
|
12626
|
+
if (widthModeChanged || responsiveLayoutChanged) {
|
|
12627
|
+
transaction.setNodeMarkup(snapshot.tablePos, void 0, {
|
|
12628
|
+
...table.attrs,
|
|
12629
|
+
widthMode,
|
|
12630
|
+
...widthMode === "responsive" ? {
|
|
12631
|
+
widthBp,
|
|
12632
|
+
offsetBp,
|
|
12633
|
+
columnRatios: normalizeColumnRatios(snapshot.columnRatios, tableMap.width),
|
|
12634
|
+
textAlign: getResponsiveResizeAlignment(widthBp, offsetBp)
|
|
12635
|
+
} : null
|
|
12636
|
+
});
|
|
12637
|
+
}
|
|
12505
12638
|
if (resizeWidth) {
|
|
12506
12639
|
const nextColumnWidths = normalizeWeightsToTotal(
|
|
12507
12640
|
snapshot.columnWidths,
|
|
@@ -12544,9 +12677,12 @@ function applyTableSize(editor, snapshot, dimensions) {
|
|
|
12544
12677
|
}
|
|
12545
12678
|
|
|
12546
12679
|
// src/components/UEditor/table-controls.tsx
|
|
12547
|
-
import { Fragment as
|
|
12680
|
+
import { Fragment as Fragment7, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
12548
12681
|
var TABLE_MENU_TOP_OFFSET = 10;
|
|
12549
12682
|
var AXIS_HANDLE_RADIUS = 12;
|
|
12683
|
+
function clamp2(value, min, max) {
|
|
12684
|
+
return Math.min(Math.max(value, min), max);
|
|
12685
|
+
}
|
|
12550
12686
|
function nearestIndex(centers, position) {
|
|
12551
12687
|
let bestIndex = 0;
|
|
12552
12688
|
let bestDistance = Number.POSITIVE_INFINITY;
|
|
@@ -12577,21 +12713,21 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12577
12713
|
const t = useSmartTranslations("UEditor");
|
|
12578
12714
|
const editorDocument = editor.view.dom.ownerDocument;
|
|
12579
12715
|
const editorWindow = editorDocument.defaultView;
|
|
12580
|
-
const [layout, setLayout] =
|
|
12581
|
-
const [dragPreview, setDragPreview] =
|
|
12582
|
-
const [tableResizeActive, setTableResizeActive] =
|
|
12583
|
-
const [hoverState, setHoverState] =
|
|
12584
|
-
const [openMenuKey, setOpenMenuKey] =
|
|
12585
|
-
const layoutRef =
|
|
12586
|
-
const dragStateRef =
|
|
12587
|
-
const syncFrameRef =
|
|
12588
|
-
const layoutRefreshFrameRef =
|
|
12589
|
-
const tableResizeFrameRef =
|
|
12590
|
-
const tableResizePreviewFrameRef =
|
|
12591
|
-
|
|
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(() => {
|
|
12592
12728
|
layoutRef.current = layout;
|
|
12593
12729
|
}, [layout]);
|
|
12594
|
-
const syncFromCell =
|
|
12730
|
+
const syncFromCell = React11.useCallback((cell) => {
|
|
12595
12731
|
const surface = containerRef.current;
|
|
12596
12732
|
if (!surface || !cell) {
|
|
12597
12733
|
layoutRef.current = null;
|
|
@@ -12602,10 +12738,10 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12602
12738
|
layoutRef.current = nextLayout;
|
|
12603
12739
|
setLayout(nextLayout);
|
|
12604
12740
|
}, [containerRef, editor]);
|
|
12605
|
-
const syncFromSelection =
|
|
12741
|
+
const syncFromSelection = React11.useCallback(() => {
|
|
12606
12742
|
syncFromCell(getSelectedCell(editor));
|
|
12607
12743
|
}, [editor, syncFromCell]);
|
|
12608
|
-
const scheduleSyncFromSelection =
|
|
12744
|
+
const scheduleSyncFromSelection = React11.useCallback(() => {
|
|
12609
12745
|
if (syncFrameRef.current !== null) return;
|
|
12610
12746
|
if (!editorWindow) return;
|
|
12611
12747
|
syncFrameRef.current = editorWindow.requestAnimationFrame(() => {
|
|
@@ -12613,13 +12749,13 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12613
12749
|
syncFromSelection();
|
|
12614
12750
|
});
|
|
12615
12751
|
}, [editorWindow, syncFromSelection]);
|
|
12616
|
-
|
|
12752
|
+
React11.useEffect(() => () => {
|
|
12617
12753
|
if (syncFrameRef.current !== null) {
|
|
12618
12754
|
editorWindow?.cancelAnimationFrame(syncFrameRef.current);
|
|
12619
12755
|
syncFrameRef.current = null;
|
|
12620
12756
|
}
|
|
12621
12757
|
}, [editorWindow]);
|
|
12622
|
-
const refreshCurrentLayout =
|
|
12758
|
+
const refreshCurrentLayout = React11.useCallback(() => {
|
|
12623
12759
|
const currentLayout = layoutRef.current;
|
|
12624
12760
|
if (!currentLayout) return;
|
|
12625
12761
|
const surface = containerRef.current;
|
|
@@ -12634,7 +12770,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12634
12770
|
layoutRef.current = nextLayout;
|
|
12635
12771
|
setLayout(nextLayout);
|
|
12636
12772
|
}, [containerRef, editor]);
|
|
12637
|
-
const scheduleCurrentLayoutRefresh =
|
|
12773
|
+
const scheduleCurrentLayoutRefresh = React11.useCallback(() => {
|
|
12638
12774
|
if (!layoutRef.current || layoutRefreshFrameRef.current !== null) return;
|
|
12639
12775
|
if (!editorWindow) return;
|
|
12640
12776
|
layoutRefreshFrameRef.current = editorWindow.requestAnimationFrame(() => {
|
|
@@ -12642,31 +12778,42 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12642
12778
|
refreshCurrentLayout();
|
|
12643
12779
|
});
|
|
12644
12780
|
}, [editorWindow, refreshCurrentLayout]);
|
|
12645
|
-
|
|
12781
|
+
React11.useEffect(() => () => {
|
|
12646
12782
|
if (layoutRefreshFrameRef.current !== null) {
|
|
12647
12783
|
editorWindow?.cancelAnimationFrame(layoutRefreshFrameRef.current);
|
|
12648
12784
|
layoutRefreshFrameRef.current = null;
|
|
12649
12785
|
}
|
|
12650
12786
|
}, [editorWindow]);
|
|
12651
|
-
const updateTableResizePreview =
|
|
12787
|
+
const updateTableResizePreview = React11.useCallback((dimensions) => {
|
|
12652
12788
|
const frame = tableResizeFrameRef.current;
|
|
12653
12789
|
if (!frame) return;
|
|
12654
12790
|
frame.style.width = `${dimensions.width}px`;
|
|
12655
12791
|
frame.style.height = `${dimensions.height}px`;
|
|
12792
|
+
const activeLayout = layoutRef.current;
|
|
12793
|
+
if (activeLayout) {
|
|
12794
|
+
frame.style.left = `${activeLayout.tableLeft + (dimensions.leftDelta ?? 0)}px`;
|
|
12795
|
+
}
|
|
12656
12796
|
const dimensionsLabel = frame.querySelector("[data-table-resize-dimensions]");
|
|
12657
|
-
if (dimensionsLabel) {
|
|
12658
|
-
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
|
+
});
|
|
12659
12805
|
}
|
|
12660
12806
|
}, []);
|
|
12661
|
-
const resetTableResizePreview =
|
|
12807
|
+
const resetTableResizePreview = React11.useCallback(() => {
|
|
12662
12808
|
const activeLayout = layoutRef.current;
|
|
12663
12809
|
if (!activeLayout) return;
|
|
12664
12810
|
updateTableResizePreview({
|
|
12665
12811
|
width: Math.round(activeLayout.tableWidth),
|
|
12666
|
-
height: Math.round(activeLayout.tableHeight)
|
|
12812
|
+
height: Math.round(activeLayout.tableHeight),
|
|
12813
|
+
leftDelta: 0
|
|
12667
12814
|
});
|
|
12668
12815
|
}, [updateTableResizePreview]);
|
|
12669
|
-
const clearDrag =
|
|
12816
|
+
const clearDrag = React11.useCallback(() => {
|
|
12670
12817
|
const dragState = dragStateRef.current;
|
|
12671
12818
|
if (dragState?.kind === "resize-table") {
|
|
12672
12819
|
try {
|
|
@@ -12686,7 +12833,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12686
12833
|
resetTableResizePreview();
|
|
12687
12834
|
setDocumentCursor(editorDocument, "");
|
|
12688
12835
|
}, [editorDocument, editorWindow, resetTableResizePreview]);
|
|
12689
|
-
const updateHoverState =
|
|
12836
|
+
const updateHoverState = React11.useCallback((event) => {
|
|
12690
12837
|
const activeLayout = layoutRef.current;
|
|
12691
12838
|
const surface = containerRef.current;
|
|
12692
12839
|
if (!activeLayout || !surface || dragStateRef.current || event.buttons !== 0) {
|
|
@@ -12702,7 +12849,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12702
12849
|
return areTableHoverStatesEqual(prev, nextState) ? prev : nextState;
|
|
12703
12850
|
});
|
|
12704
12851
|
}, [containerRef]);
|
|
12705
|
-
|
|
12852
|
+
React11.useEffect(() => {
|
|
12706
12853
|
const proseMirror = editor.view.dom;
|
|
12707
12854
|
const surface = containerRef.current;
|
|
12708
12855
|
if (!surface) return void 0;
|
|
@@ -12789,37 +12936,37 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12789
12936
|
editor.off("update", scheduleCurrentLayoutRefresh);
|
|
12790
12937
|
};
|
|
12791
12938
|
}, [clearDrag, containerRef, editor, editorWindow, scheduleCurrentLayoutRefresh, scheduleSyncFromSelection, syncFromCell, syncFromSelection, updateHoverState]);
|
|
12792
|
-
const runAtCellPos =
|
|
12939
|
+
const runAtCellPos = React11.useCallback((cellPos, command, options) => {
|
|
12793
12940
|
const result = runTableCommandAtCellPos(editor, cellPos, command);
|
|
12794
12941
|
if (options?.sync !== false) {
|
|
12795
12942
|
scheduleSyncFromSelection();
|
|
12796
12943
|
}
|
|
12797
12944
|
return result;
|
|
12798
12945
|
}, [editor, scheduleSyncFromSelection]);
|
|
12799
|
-
const runAtActiveCell =
|
|
12946
|
+
const runAtActiveCell = React11.useCallback((command, options) => {
|
|
12800
12947
|
return runAtCellPos(layoutRef.current?.cellPos ?? null, command, options);
|
|
12801
12948
|
}, [runAtCellPos]);
|
|
12802
|
-
const duplicateRowAt =
|
|
12949
|
+
const duplicateRowAt = React11.useCallback((rowIndex, cellPos) => {
|
|
12803
12950
|
const result = duplicateTableRowAt(editor, rowIndex, cellPos);
|
|
12804
12951
|
scheduleSyncFromSelection();
|
|
12805
12952
|
return result;
|
|
12806
12953
|
}, [editor, scheduleSyncFromSelection]);
|
|
12807
|
-
const clearRowAt =
|
|
12954
|
+
const clearRowAt = React11.useCallback((rowIndex, cellPos) => {
|
|
12808
12955
|
const result = clearTableRowAt(editor, rowIndex, cellPos);
|
|
12809
12956
|
scheduleSyncFromSelection();
|
|
12810
12957
|
return result;
|
|
12811
12958
|
}, [editor, scheduleSyncFromSelection]);
|
|
12812
|
-
const duplicateColumnAt =
|
|
12959
|
+
const duplicateColumnAt = React11.useCallback((columnIndex, cellPos) => {
|
|
12813
12960
|
const result = duplicateTableColumnAt(editor, columnIndex, cellPos);
|
|
12814
12961
|
scheduleSyncFromSelection();
|
|
12815
12962
|
return result;
|
|
12816
12963
|
}, [editor, scheduleSyncFromSelection]);
|
|
12817
|
-
const clearColumnAt =
|
|
12964
|
+
const clearColumnAt = React11.useCallback((columnIndex, cellPos) => {
|
|
12818
12965
|
const result = clearTableColumnAt(editor, columnIndex, cellPos);
|
|
12819
12966
|
scheduleSyncFromSelection();
|
|
12820
12967
|
return result;
|
|
12821
12968
|
}, [editor, scheduleSyncFromSelection]);
|
|
12822
|
-
const expandTableBy =
|
|
12969
|
+
const expandTableBy = React11.useCallback((rows, cols) => {
|
|
12823
12970
|
const activeCellPos = layoutRef.current?.cellPos ?? editor.state.selection.from;
|
|
12824
12971
|
const result = expandTableFromCell(editor, activeCellPos, rows, cols);
|
|
12825
12972
|
scheduleSyncFromSelection();
|
|
@@ -12828,7 +12975,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12828
12975
|
const canExpandTable = Boolean(layout);
|
|
12829
12976
|
const controlsVisible = false;
|
|
12830
12977
|
const tableMenuOpen = openMenuKey === "table";
|
|
12831
|
-
const startTableResize =
|
|
12978
|
+
const startTableResize = React11.useCallback((event, edge) => {
|
|
12832
12979
|
if (event.button !== 0 || dragStateRef.current) return;
|
|
12833
12980
|
const activeLayout = layoutRef.current;
|
|
12834
12981
|
if (!activeLayout) return;
|
|
@@ -12836,7 +12983,8 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12836
12983
|
editor,
|
|
12837
12984
|
activeLayout.cellPos,
|
|
12838
12985
|
activeLayout.tableWidth,
|
|
12839
|
-
activeLayout.tableHeight
|
|
12986
|
+
activeLayout.tableHeight,
|
|
12987
|
+
activeLayout.viewportWidth
|
|
12840
12988
|
);
|
|
12841
12989
|
if (!snapshot) return;
|
|
12842
12990
|
event.preventDefault();
|
|
@@ -12858,25 +13006,89 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12858
13006
|
pointerTarget: event.currentTarget,
|
|
12859
13007
|
startX: event.clientX,
|
|
12860
13008
|
startY: event.clientY,
|
|
13009
|
+
edge,
|
|
12861
13010
|
snapshot,
|
|
12862
13011
|
pendingDimensions
|
|
12863
13012
|
};
|
|
12864
13013
|
updateTableResizePreview(pendingDimensions);
|
|
12865
|
-
setDocumentCursor(editorDocument, "nwse-resize");
|
|
13014
|
+
setDocumentCursor(editorDocument, edge === "both" ? "nwse-resize" : "ew-resize");
|
|
12866
13015
|
}, [editor, editorDocument, updateTableResizePreview]);
|
|
12867
|
-
const
|
|
13016
|
+
const fitTableToEditorWidth = React11.useCallback((event) => {
|
|
13017
|
+
if (event.button !== 0 || dragStateRef.current) return;
|
|
13018
|
+
const activeLayout = layoutRef.current;
|
|
13019
|
+
if (!activeLayout) return;
|
|
13020
|
+
const snapshot = createTableSizeSnapshot(
|
|
13021
|
+
editor,
|
|
13022
|
+
activeLayout.cellPos,
|
|
13023
|
+
activeLayout.tableWidth,
|
|
13024
|
+
activeLayout.tableHeight,
|
|
13025
|
+
activeLayout.viewportWidth
|
|
13026
|
+
);
|
|
13027
|
+
if (!snapshot) return;
|
|
13028
|
+
event.preventDefault();
|
|
13029
|
+
event.stopPropagation();
|
|
13030
|
+
const didResize = applyTableSize(editor, snapshot, {
|
|
13031
|
+
width: Math.round(activeLayout.viewportWidth),
|
|
13032
|
+
height: snapshot.startHeight,
|
|
13033
|
+
widthBp: TABLE_WIDTH_BASIS_POINTS,
|
|
13034
|
+
offsetBp: 0,
|
|
13035
|
+
leftDelta: -(snapshot.offsetBp / TABLE_WIDTH_BASIS_POINTS * snapshot.containerWidth)
|
|
13036
|
+
}, { widthMode: "responsive" });
|
|
13037
|
+
if (didResize) {
|
|
13038
|
+
scheduleSyncFromSelection();
|
|
13039
|
+
}
|
|
13040
|
+
}, [editor, scheduleSyncFromSelection]);
|
|
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();
|
|
12868
13074
|
setOpenMenuKey(null);
|
|
12869
13075
|
dragStateRef.current = { kind: "add-column", previewCols: 1 };
|
|
12870
13076
|
setDragPreview({ kind: "add-column", previewCols: 1 });
|
|
12871
13077
|
setDocumentCursor(editorDocument, "ew-resize");
|
|
12872
13078
|
}, [editorDocument]);
|
|
12873
|
-
const startAddRowDrag =
|
|
13079
|
+
const startAddRowDrag = React11.useCallback((event) => {
|
|
13080
|
+
if (event.button !== 0 || dragStateRef.current) return;
|
|
13081
|
+
event.preventDefault();
|
|
13082
|
+
event.stopPropagation();
|
|
12874
13083
|
setOpenMenuKey(null);
|
|
12875
13084
|
dragStateRef.current = { kind: "add-row", previewRows: 1 };
|
|
12876
13085
|
setDragPreview({ kind: "add-row", previewRows: 1 });
|
|
12877
13086
|
setDocumentCursor(editorDocument, "ns-resize");
|
|
12878
13087
|
}, [editorDocument]);
|
|
12879
|
-
const startRowDrag =
|
|
13088
|
+
const startRowDrag = React11.useCallback((event, rowHandle) => {
|
|
13089
|
+
if (event.button !== 0 || dragStateRef.current) return;
|
|
13090
|
+
event.preventDefault();
|
|
13091
|
+
event.stopPropagation();
|
|
12880
13092
|
setOpenMenuKey(null);
|
|
12881
13093
|
dragStateRef.current = {
|
|
12882
13094
|
kind: "row",
|
|
@@ -12893,7 +13105,10 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12893
13105
|
});
|
|
12894
13106
|
setDocumentCursor(editorDocument, "grabbing");
|
|
12895
13107
|
}, [editorDocument]);
|
|
12896
|
-
const startColumnDrag =
|
|
13108
|
+
const startColumnDrag = React11.useCallback((event, columnHandle) => {
|
|
13109
|
+
if (event.button !== 0 || dragStateRef.current) return;
|
|
13110
|
+
event.preventDefault();
|
|
13111
|
+
event.stopPropagation();
|
|
12897
13112
|
setOpenMenuKey(null);
|
|
12898
13113
|
dragStateRef.current = {
|
|
12899
13114
|
kind: "column",
|
|
@@ -12910,9 +13125,62 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12910
13125
|
});
|
|
12911
13126
|
setDocumentCursor(editorDocument, "grabbing");
|
|
12912
13127
|
}, [editorDocument]);
|
|
12913
|
-
|
|
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(() => {
|
|
12914
13182
|
if (!editorWindow) return;
|
|
12915
|
-
const
|
|
13183
|
+
const handlePointerMove = (event) => {
|
|
12916
13184
|
const dragState = dragStateRef.current;
|
|
12917
13185
|
const activeLayout = layoutRef.current;
|
|
12918
13186
|
const surface = containerRef.current;
|
|
@@ -12965,25 +13233,70 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12965
13233
|
setDragPreview({ kind: "add-row", previewRows });
|
|
12966
13234
|
setDocumentCursor(editorDocument, "ns-resize");
|
|
12967
13235
|
};
|
|
12968
|
-
const
|
|
13236
|
+
const handlePointerUp = () => {
|
|
12969
13237
|
const dragState = dragStateRef.current;
|
|
12970
13238
|
if (!dragState || dragState.kind === "resize-table") return;
|
|
12971
13239
|
if (dragState.kind === "row" && dragState.originIndex !== dragState.targetIndex) {
|
|
13240
|
+
const tableInfo = findTableInfo(editor, dragState.anchorPos);
|
|
12972
13241
|
moveTableRow({
|
|
12973
13242
|
from: dragState.originIndex,
|
|
12974
13243
|
to: dragState.targetIndex,
|
|
12975
13244
|
pos: dragState.anchorPos,
|
|
12976
13245
|
select: true
|
|
12977
|
-
})(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
|
+
});
|
|
12978
13261
|
scheduleSyncFromSelection();
|
|
12979
13262
|
}
|
|
12980
13263
|
if (dragState.kind === "column" && dragState.originIndex !== dragState.targetIndex) {
|
|
13264
|
+
const tableInfo = findTableInfo(editor, dragState.anchorPos);
|
|
13265
|
+
const responsiveRatios = tableInfo && normalizeTableWidthMode(tableInfo.node.attrs.widthMode) === "responsive" ? moveResponsiveColumnRatio(
|
|
13266
|
+
getTableColumnRatios(tableInfo.node),
|
|
13267
|
+
dragState.originIndex,
|
|
13268
|
+
dragState.targetIndex
|
|
13269
|
+
) : null;
|
|
12981
13270
|
moveTableColumn({
|
|
12982
13271
|
from: dragState.originIndex,
|
|
12983
13272
|
to: dragState.targetIndex,
|
|
12984
13273
|
pos: dragState.anchorPos,
|
|
12985
13274
|
select: true
|
|
12986
|
-
})(editor.state,
|
|
13275
|
+
})(editor.state, (transaction) => {
|
|
13276
|
+
if (tableInfo && responsiveRatios) {
|
|
13277
|
+
const nextTable2 = transaction.doc.nodeAt(tableInfo.pos);
|
|
13278
|
+
if (nextTable2?.type.name === "table") {
|
|
13279
|
+
transaction.setNodeMarkup(tableInfo.pos, void 0, {
|
|
13280
|
+
...nextTable2.attrs,
|
|
13281
|
+
widthMode: "responsive",
|
|
13282
|
+
columnRatios: responsiveRatios
|
|
13283
|
+
});
|
|
13284
|
+
}
|
|
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
|
+
}
|
|
13298
|
+
editor.view.dispatch(transaction);
|
|
13299
|
+
});
|
|
12987
13300
|
scheduleSyncFromSelection();
|
|
12988
13301
|
}
|
|
12989
13302
|
if (dragState.kind === "add-row") {
|
|
@@ -12994,20 +13307,23 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
12994
13307
|
}
|
|
12995
13308
|
clearDrag();
|
|
12996
13309
|
};
|
|
12997
|
-
const
|
|
13310
|
+
const unsubscribePointerMove = subscribeSharedGlobalEvent(
|
|
12998
13311
|
editorWindow,
|
|
12999
|
-
"
|
|
13000
|
-
|
|
13312
|
+
"pointermove",
|
|
13313
|
+
handlePointerMove,
|
|
13314
|
+
{ passive: false }
|
|
13001
13315
|
);
|
|
13002
|
-
const
|
|
13316
|
+
const unsubscribePointerUp = subscribeSharedGlobalEvent(editorWindow, "pointerup", handlePointerUp);
|
|
13317
|
+
const unsubscribePointerCancel = subscribeSharedGlobalEvent(editorWindow, "pointercancel", clearDrag);
|
|
13003
13318
|
const unsubscribeBlur = subscribeSharedGlobalEvent(editorWindow, "blur", clearDrag);
|
|
13004
13319
|
return () => {
|
|
13005
|
-
|
|
13006
|
-
|
|
13320
|
+
unsubscribePointerMove();
|
|
13321
|
+
unsubscribePointerUp();
|
|
13322
|
+
unsubscribePointerCancel();
|
|
13007
13323
|
unsubscribeBlur();
|
|
13008
13324
|
};
|
|
13009
13325
|
}, [clearDrag, containerRef, editor, editorDocument, editorWindow, expandTableBy, scheduleSyncFromSelection]);
|
|
13010
|
-
|
|
13326
|
+
React11.useEffect(() => {
|
|
13011
13327
|
if (!editorWindow) return;
|
|
13012
13328
|
const handlePointerMove = (event) => {
|
|
13013
13329
|
const dragState = dragStateRef.current;
|
|
@@ -13017,6 +13333,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13017
13333
|
deltaY: event.clientY - dragState.startY,
|
|
13018
13334
|
lockAxis: event.ctrlKey && !event.shiftKey,
|
|
13019
13335
|
preserveRatio: event.ctrlKey && event.shiftKey,
|
|
13336
|
+
edge: dragState.edge,
|
|
13020
13337
|
snapshot: dragState.snapshot
|
|
13021
13338
|
});
|
|
13022
13339
|
if (tableResizePreviewFrameRef.current === null) {
|
|
@@ -13028,7 +13345,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13028
13345
|
updateTableResizePreview(currentDragState.pendingDimensions);
|
|
13029
13346
|
});
|
|
13030
13347
|
}
|
|
13031
|
-
setDocumentCursor(editorDocument, "nwse-resize");
|
|
13348
|
+
setDocumentCursor(editorDocument, dragState.edge === "both" ? "nwse-resize" : "ew-resize");
|
|
13032
13349
|
if (event.cancelable) event.preventDefault();
|
|
13033
13350
|
};
|
|
13034
13351
|
const finishTableResize = (event, commit) => {
|
|
@@ -13039,7 +13356,12 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13039
13356
|
tableResizePreviewFrameRef.current = null;
|
|
13040
13357
|
}
|
|
13041
13358
|
updateTableResizePreview(dragState.pendingDimensions);
|
|
13042
|
-
if (commit && applyTableSize(
|
|
13359
|
+
if (commit && applyTableSize(
|
|
13360
|
+
editor,
|
|
13361
|
+
dragState.snapshot,
|
|
13362
|
+
dragState.pendingDimensions,
|
|
13363
|
+
{ widthMode: dragState.snapshot.widthMode }
|
|
13364
|
+
)) {
|
|
13043
13365
|
scheduleSyncFromSelection();
|
|
13044
13366
|
}
|
|
13045
13367
|
clearDrag();
|
|
@@ -13072,7 +13394,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13072
13394
|
}
|
|
13073
13395
|
};
|
|
13074
13396
|
}, [clearDrag, editor, editorDocument, editorWindow, scheduleSyncFromSelection, updateTableResizePreview]);
|
|
13075
|
-
const openCellInspector =
|
|
13397
|
+
const openCellInspector = React11.useCallback(() => {
|
|
13076
13398
|
const cellPos = layoutRef.current?.cellPos;
|
|
13077
13399
|
if (!showCellInspector || cellPos == null) return;
|
|
13078
13400
|
const didSelect = editor.commands.setCellSelection({
|
|
@@ -13084,7 +13406,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13084
13406
|
if (!editor.isDestroyed) editor.view.focus();
|
|
13085
13407
|
});
|
|
13086
13408
|
}, [editor, editorWindow, showCellInspector]);
|
|
13087
|
-
const menuItems =
|
|
13409
|
+
const menuItems = React11.useMemo(() => {
|
|
13088
13410
|
if (!layout) return [];
|
|
13089
13411
|
return [
|
|
13090
13412
|
...showCellInspector ? [{
|
|
@@ -13157,7 +13479,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13157
13479
|
}
|
|
13158
13480
|
];
|
|
13159
13481
|
}, [editor, layout, openCellInspector, runAtActiveCell, showCellInspector, t]);
|
|
13160
|
-
const getRowHandleMenuItems =
|
|
13482
|
+
const getRowHandleMenuItems = React11.useCallback((rowHandle) => [
|
|
13161
13483
|
{
|
|
13162
13484
|
label: t("tableMenu.addRowBefore"),
|
|
13163
13485
|
icon: ArrowUp,
|
|
@@ -13185,7 +13507,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13185
13507
|
destructive: true
|
|
13186
13508
|
}
|
|
13187
13509
|
], [clearRowAt, duplicateRowAt, runAtCellPos, t]);
|
|
13188
|
-
const getColumnHandleMenuItems =
|
|
13510
|
+
const getColumnHandleMenuItems = React11.useCallback((columnHandle) => [
|
|
13189
13511
|
{
|
|
13190
13512
|
label: t("tableMenu.addColumnBefore"),
|
|
13191
13513
|
icon: ArrowLeft,
|
|
@@ -13220,7 +13542,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13220
13542
|
const menuLeft = Math.max(8, layout.tableLeft);
|
|
13221
13543
|
const rowHandleLeft = layout.tableLeft - AXIS_HANDLE_RADIUS;
|
|
13222
13544
|
const columnHandleTop = layout.tableTop - AXIS_HANDLE_RADIUS;
|
|
13223
|
-
return /* @__PURE__ */ jsxs15(
|
|
13545
|
+
return /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
13224
13546
|
/* @__PURE__ */ jsx18(
|
|
13225
13547
|
TableRowHandles,
|
|
13226
13548
|
{
|
|
@@ -13231,6 +13553,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13231
13553
|
onOpenMenuChange: (menuKey, open) => {
|
|
13232
13554
|
setOpenMenuKey((prev) => open ? menuKey : prev === menuKey ? null : prev);
|
|
13233
13555
|
},
|
|
13556
|
+
onMove: moveRowWithKeyboard,
|
|
13234
13557
|
onStartDrag: startRowDrag,
|
|
13235
13558
|
openMenuKey,
|
|
13236
13559
|
rowDragLabel: t("tableMenu.dragRow"),
|
|
@@ -13251,6 +13574,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13251
13574
|
onOpenMenuChange: (menuKey, open) => {
|
|
13252
13575
|
setOpenMenuKey((prev) => open ? menuKey : prev === menuKey ? null : prev);
|
|
13253
13576
|
},
|
|
13577
|
+
onMove: moveColumnWithKeyboard,
|
|
13254
13578
|
onStartDrag: startColumnDrag,
|
|
13255
13579
|
openMenuKey
|
|
13256
13580
|
}
|
|
@@ -13277,6 +13601,8 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13277
13601
|
ctrlHint: t("tableMenu.resizeCtrlHint"),
|
|
13278
13602
|
frameRef: tableResizeFrameRef,
|
|
13279
13603
|
layout,
|
|
13604
|
+
onFitWidth: fitTableToEditorWidth,
|
|
13605
|
+
onKeyboardResize: resizeTableWithKeyboard,
|
|
13280
13606
|
onStartResize: startTableResize,
|
|
13281
13607
|
resizeBothLabel: t("tableMenu.resizeBoth")
|
|
13282
13608
|
}
|
|
@@ -13291,6 +13617,8 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13291
13617
|
layout,
|
|
13292
13618
|
onStartAddColumn: startAddColumnDrag,
|
|
13293
13619
|
onStartAddRow: startAddRowDrag,
|
|
13620
|
+
onAddColumn: () => expandTableBy(0, 1),
|
|
13621
|
+
onAddRow: () => expandTableBy(1, 0),
|
|
13294
13622
|
quickAddColumnLabel: t("tableMenu.quickAddColumnAfter"),
|
|
13295
13623
|
quickAddRowLabel: t("tableMenu.quickAddRowAfter")
|
|
13296
13624
|
}
|
|
@@ -13308,10 +13636,10 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
|
|
|
13308
13636
|
}
|
|
13309
13637
|
|
|
13310
13638
|
// src/components/UEditor/use-table-interactions.ts
|
|
13311
|
-
import
|
|
13639
|
+
import React13, { useEffect as useEffect6, useRef as useRef6 } from "react";
|
|
13312
13640
|
|
|
13313
13641
|
// src/components/UEditor/use-table-row-resize.ts
|
|
13314
|
-
import
|
|
13642
|
+
import React12, { useRef as useRef5 } from "react";
|
|
13315
13643
|
function setRowResizeBodyState(ownerDocument, active) {
|
|
13316
13644
|
ownerDocument.body.style.userSelect = active ? "none" : "";
|
|
13317
13645
|
ownerDocument.body.style.cursor = active ? "row-resize" : "";
|
|
@@ -13325,15 +13653,15 @@ function useTableRowResize({
|
|
|
13325
13653
|
scheduleTableLayoutSync
|
|
13326
13654
|
}) {
|
|
13327
13655
|
const stateRef = useRef5(null);
|
|
13328
|
-
const syncActiveGuide =
|
|
13656
|
+
const syncActiveGuide = React12.useCallback(() => {
|
|
13329
13657
|
const state = stateRef.current;
|
|
13330
13658
|
if (!state) return false;
|
|
13331
13659
|
setHoveredTableCell(state.cellElement);
|
|
13332
13660
|
showRowGuide(state.tableElement, state.rowElement, state.cellElement, state.pendingHeight);
|
|
13333
13661
|
return true;
|
|
13334
13662
|
}, [setHoveredTableCell, showRowGuide]);
|
|
13335
|
-
const isResizing =
|
|
13336
|
-
const beginResize =
|
|
13663
|
+
const isResizing = React12.useCallback(() => stateRef.current !== null, []);
|
|
13664
|
+
const beginResize = React12.useCallback((event, table, row, cell) => {
|
|
13337
13665
|
if (!editor || !isRowResizeHotspot(cell, event.clientX, event.clientY)) {
|
|
13338
13666
|
return false;
|
|
13339
13667
|
}
|
|
@@ -13362,7 +13690,7 @@ function useTableRowResize({
|
|
|
13362
13690
|
event.stopPropagation();
|
|
13363
13691
|
return true;
|
|
13364
13692
|
}, [editor, setHoveredTableCell, showRowGuide]);
|
|
13365
|
-
const handlePointerMove =
|
|
13693
|
+
const handlePointerMove = React12.useCallback((event) => {
|
|
13366
13694
|
const state = stateRef.current;
|
|
13367
13695
|
if (!state) return;
|
|
13368
13696
|
const nextHeight = Math.max(
|
|
@@ -13379,7 +13707,7 @@ function useTableRowResize({
|
|
|
13379
13707
|
setRowResizeBodyState(state.rowElement.ownerDocument, true);
|
|
13380
13708
|
showRowGuide(state.tableElement, state.rowElement, state.cellElement, nextHeight);
|
|
13381
13709
|
}, [showRowGuide]);
|
|
13382
|
-
const handlePointerUp =
|
|
13710
|
+
const handlePointerUp = React12.useCallback((event) => {
|
|
13383
13711
|
if (!editor) return;
|
|
13384
13712
|
const state = stateRef.current;
|
|
13385
13713
|
if (!state) return;
|
|
@@ -13404,7 +13732,7 @@ function useTableRowResize({
|
|
|
13404
13732
|
clearAllTableResizeHover();
|
|
13405
13733
|
scheduleTableLayoutSync();
|
|
13406
13734
|
}, [clearAllTableResizeHover, clearHoveredTableCell, editor, scheduleTableLayoutSync]);
|
|
13407
|
-
const cancelResize =
|
|
13735
|
+
const cancelResize = React12.useCallback(() => {
|
|
13408
13736
|
const state = stateRef.current;
|
|
13409
13737
|
if (!state) return;
|
|
13410
13738
|
stateRef.current = null;
|
|
@@ -13414,7 +13742,7 @@ function useTableRowResize({
|
|
|
13414
13742
|
clearAllTableResizeHover();
|
|
13415
13743
|
scheduleTableLayoutSync();
|
|
13416
13744
|
}, [clearAllTableResizeHover, clearHoveredTableCell, scheduleTableLayoutSync]);
|
|
13417
|
-
const cleanup =
|
|
13745
|
+
const cleanup = React12.useCallback(() => {
|
|
13418
13746
|
const editorDocument = stateRef.current?.rowElement.ownerDocument ?? editor?.view.dom.ownerDocument;
|
|
13419
13747
|
stateRef.current = null;
|
|
13420
13748
|
isRowResizingGlobal.active = false;
|
|
@@ -13443,16 +13771,16 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
13443
13771
|
const activeTableCellRef = useRef6(null);
|
|
13444
13772
|
const suppressActiveCellHighlightRef = useRef6(false);
|
|
13445
13773
|
const tableLayoutSyncFrameRef = useRef6(null);
|
|
13446
|
-
const getProseMirrorElement =
|
|
13774
|
+
const getProseMirrorElement = React13.useCallback(() => {
|
|
13447
13775
|
return editorContentRef.current?.querySelector(".ProseMirror");
|
|
13448
13776
|
}, []);
|
|
13449
|
-
const setEditorResizeCursor =
|
|
13777
|
+
const setEditorResizeCursor = React13.useCallback((cursor) => {
|
|
13450
13778
|
const proseMirror = getProseMirrorElement();
|
|
13451
13779
|
if (proseMirror) {
|
|
13452
13780
|
proseMirror.style.cursor = cursor;
|
|
13453
13781
|
}
|
|
13454
13782
|
}, [getProseMirrorElement]);
|
|
13455
|
-
const hideColumnGuide =
|
|
13783
|
+
const hideColumnGuide = React13.useCallback(() => {
|
|
13456
13784
|
editorContentRef.current?.classList.remove("resize-cursor");
|
|
13457
13785
|
getProseMirrorElement()?.classList.remove("resize-cursor");
|
|
13458
13786
|
const guide = tableColumnGuideRef.current;
|
|
@@ -13460,7 +13788,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
13460
13788
|
guide.style.opacity = "0";
|
|
13461
13789
|
}
|
|
13462
13790
|
}, [getProseMirrorElement]);
|
|
13463
|
-
const hideRowGuide =
|
|
13791
|
+
const hideRowGuide = React13.useCallback(() => {
|
|
13464
13792
|
editorContentRef.current?.classList.remove("resize-row-cursor");
|
|
13465
13793
|
getProseMirrorElement()?.classList.remove("resize-row-cursor");
|
|
13466
13794
|
const guide = tableRowGuideRef.current;
|
|
@@ -13470,21 +13798,21 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
13470
13798
|
}, [getProseMirrorElement]);
|
|
13471
13799
|
const hotspotTimerRef = useRef6(null);
|
|
13472
13800
|
const activeHotspotKeyRef = useRef6(null);
|
|
13473
|
-
const clearHotspotTimer =
|
|
13801
|
+
const clearHotspotTimer = React13.useCallback(() => {
|
|
13474
13802
|
if (hotspotTimerRef.current !== null) {
|
|
13475
13803
|
const realm = editorContentRef.current?.ownerDocument.defaultView;
|
|
13476
13804
|
realm?.clearTimeout(hotspotTimerRef.current);
|
|
13477
13805
|
hotspotTimerRef.current = null;
|
|
13478
13806
|
}
|
|
13479
13807
|
}, []);
|
|
13480
|
-
const clearAllTableResizeHover =
|
|
13808
|
+
const clearAllTableResizeHover = React13.useCallback(() => {
|
|
13481
13809
|
clearHotspotTimer();
|
|
13482
13810
|
activeHotspotKeyRef.current = null;
|
|
13483
13811
|
setEditorResizeCursor("");
|
|
13484
13812
|
hideColumnGuide();
|
|
13485
13813
|
hideRowGuide();
|
|
13486
13814
|
}, [clearHotspotTimer, hideColumnGuide, hideRowGuide, setEditorResizeCursor]);
|
|
13487
|
-
const updateActiveCellHighlight =
|
|
13815
|
+
const updateActiveCellHighlight = React13.useCallback((cell) => {
|
|
13488
13816
|
const surface = editorContentRef.current;
|
|
13489
13817
|
const highlight = activeTableCellHighlightRef.current;
|
|
13490
13818
|
if (!highlight) return;
|
|
@@ -13499,7 +13827,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
13499
13827
|
highlight.style.width = `${metrics.width}px`;
|
|
13500
13828
|
highlight.style.height = `${metrics.height}px`;
|
|
13501
13829
|
}, []);
|
|
13502
|
-
const scheduleTableLayoutSync =
|
|
13830
|
+
const scheduleTableLayoutSync = React13.useCallback(() => {
|
|
13503
13831
|
if (!activeTableCellRef.current || tableLayoutSyncFrameRef.current !== null) return;
|
|
13504
13832
|
const realm = editorContentRef.current?.ownerDocument.defaultView;
|
|
13505
13833
|
if (!realm) return;
|
|
@@ -13511,7 +13839,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
13511
13839
|
editorContentRef.current?.dispatchEvent(new realm.CustomEvent(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT));
|
|
13512
13840
|
});
|
|
13513
13841
|
}, [updateActiveCellHighlight]);
|
|
13514
|
-
const setActiveTableCell =
|
|
13842
|
+
const setActiveTableCell = React13.useCallback((cell) => {
|
|
13515
13843
|
if (activeTableCellRef.current === cell) {
|
|
13516
13844
|
updateActiveCellHighlight(cell);
|
|
13517
13845
|
return;
|
|
@@ -13519,17 +13847,17 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
13519
13847
|
activeTableCellRef.current = cell;
|
|
13520
13848
|
updateActiveCellHighlight(activeTableCellRef.current);
|
|
13521
13849
|
}, [updateActiveCellHighlight]);
|
|
13522
|
-
const clearActiveTableCell =
|
|
13850
|
+
const clearActiveTableCell = React13.useCallback(() => {
|
|
13523
13851
|
activeTableCellRef.current = null;
|
|
13524
13852
|
updateActiveCellHighlight(null);
|
|
13525
13853
|
}, [updateActiveCellHighlight]);
|
|
13526
|
-
const setHoveredTableCell =
|
|
13854
|
+
const setHoveredTableCell = React13.useCallback((cell) => {
|
|
13527
13855
|
hoveredTableCellRef.current = cell;
|
|
13528
13856
|
}, []);
|
|
13529
|
-
const clearHoveredTableCell =
|
|
13857
|
+
const clearHoveredTableCell = React13.useCallback(() => {
|
|
13530
13858
|
hoveredTableCellRef.current = null;
|
|
13531
13859
|
}, []);
|
|
13532
|
-
const showColumnGuide =
|
|
13860
|
+
const showColumnGuide = React13.useCallback((table, row, cell) => {
|
|
13533
13861
|
const surface = editorContentRef.current;
|
|
13534
13862
|
const guide = tableColumnGuideRef.current;
|
|
13535
13863
|
if (!surface || !guide) return;
|
|
@@ -13543,7 +13871,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
13543
13871
|
getProseMirrorElement()?.classList.add("resize-cursor");
|
|
13544
13872
|
setEditorResizeCursor("col-resize");
|
|
13545
13873
|
}, [getProseMirrorElement, setEditorResizeCursor]);
|
|
13546
|
-
const showRowGuide =
|
|
13874
|
+
const showRowGuide = React13.useCallback((table, row, cell, previewHeight) => {
|
|
13547
13875
|
const surface = editorContentRef.current;
|
|
13548
13876
|
const guide = tableRowGuideRef.current;
|
|
13549
13877
|
if (!surface || !guide) return;
|
|
@@ -13575,7 +13903,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
13575
13903
|
clearAllTableResizeHover,
|
|
13576
13904
|
scheduleTableLayoutSync
|
|
13577
13905
|
});
|
|
13578
|
-
const syncActiveTableCellFromSelection =
|
|
13906
|
+
const syncActiveTableCellFromSelection = React13.useCallback(() => {
|
|
13579
13907
|
if (!editor) return;
|
|
13580
13908
|
if (!editor.isFocused) {
|
|
13581
13909
|
clearActiveTableCell();
|
|
@@ -13830,7 +14158,7 @@ import { useEffect as useEffect7, useRef as useRef7 } from "react";
|
|
|
13830
14158
|
import { TableMap as TableMap5 } from "@tiptap/pm/tables";
|
|
13831
14159
|
|
|
13832
14160
|
// src/components/UEditor/table-formula-range-picker.ts
|
|
13833
|
-
import { TextSelection as
|
|
14161
|
+
import { TextSelection as TextSelection4 } from "@tiptap/pm/state";
|
|
13834
14162
|
import { TableMap as TableMap4 } from "@tiptap/pm/tables";
|
|
13835
14163
|
function getCellText2(cellNode) {
|
|
13836
14164
|
return cellNode.textBetween(0, cellNode.content.size, "\n").trim();
|
|
@@ -13908,7 +14236,7 @@ function cancelFormulaEditing(view) {
|
|
|
13908
14236
|
if (!context) return false;
|
|
13909
14237
|
let tr = view.state.tr.delete(context.cellContentStart, context.cellContentEnd);
|
|
13910
14238
|
const selectionPos = Math.min(context.cellContentStart, tr.doc.content.size);
|
|
13911
|
-
tr = tr.setSelection(
|
|
14239
|
+
tr = tr.setSelection(TextSelection4.near(tr.doc.resolve(selectionPos)));
|
|
13912
14240
|
view.dispatch(tr);
|
|
13913
14241
|
view.focus();
|
|
13914
14242
|
return true;
|
|
@@ -13916,7 +14244,7 @@ function cancelFormulaEditing(view) {
|
|
|
13916
14244
|
function getReferenceInsertionPrefix(view, cellContentStart, insertionPos) {
|
|
13917
14245
|
const textBeforeCursor = view.state.doc.textBetween(cellContentStart, insertionPos, "", "");
|
|
13918
14246
|
const isInsideFunctionArguments = /[A-Z]+\([^)]*$/i.test(textBeforeCursor);
|
|
13919
|
-
const followsReference =
|
|
14247
|
+
const followsReference = /\$?[A-Z]+\$?[1-9]\d*(?::\$?[A-Z]+\$?[1-9]\d*)?\s*$/i.test(textBeforeCursor);
|
|
13920
14248
|
return isInsideFunctionArguments && followsReference ? "," : "";
|
|
13921
14249
|
}
|
|
13922
14250
|
function findTableForPos(view, pos) {
|
|
@@ -13985,7 +14313,7 @@ function replacePickedLabel(view, pickState, nextLabel, currentCell) {
|
|
|
13985
14313
|
}
|
|
13986
14314
|
let tr = view.state.tr.insertText(nextLabel, pickState.insertedFrom, pickState.insertedTo);
|
|
13987
14315
|
const nextTo = pickState.insertedFrom + nextLabel.length;
|
|
13988
|
-
tr = tr.setSelection(
|
|
14316
|
+
tr = tr.setSelection(TextSelection4.create(tr.doc, nextTo));
|
|
13989
14317
|
view.dispatch(tr);
|
|
13990
14318
|
return {
|
|
13991
14319
|
...pickState,
|
|
@@ -14022,7 +14350,7 @@ function beginFormulaRangePick(view, event) {
|
|
|
14022
14350
|
const insertedText = `${prefix}${picked.label}`;
|
|
14023
14351
|
const insertedFrom = from + prefix.length;
|
|
14024
14352
|
let tr = view.state.tr.insertText(insertedText, from, to);
|
|
14025
|
-
tr = tr.setSelection(
|
|
14353
|
+
tr = tr.setSelection(TextSelection4.create(tr.doc, from + insertedText.length));
|
|
14026
14354
|
view.dispatch(tr);
|
|
14027
14355
|
view.focus();
|
|
14028
14356
|
event.preventDefault();
|
|
@@ -14467,7 +14795,7 @@ function TableFormulaBar({ editor }) {
|
|
|
14467
14795
|
}
|
|
14468
14796
|
|
|
14469
14797
|
// src/components/UEditor/use-editor-output.ts
|
|
14470
|
-
import * as
|
|
14798
|
+
import * as React15 from "react";
|
|
14471
14799
|
function normalizeDebounceMs(value) {
|
|
14472
14800
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
14473
14801
|
}
|
|
@@ -14477,18 +14805,18 @@ function useUEditorOutput({
|
|
|
14477
14805
|
onJsonChange,
|
|
14478
14806
|
outputDebounceMs
|
|
14479
14807
|
}) {
|
|
14480
|
-
const callbacksRef =
|
|
14808
|
+
const callbacksRef = React15.useRef({
|
|
14481
14809
|
onChange,
|
|
14482
14810
|
onHtmlChange,
|
|
14483
14811
|
onJsonChange
|
|
14484
14812
|
});
|
|
14485
|
-
const pendingEditorRef =
|
|
14486
|
-
const timeoutRef =
|
|
14813
|
+
const pendingEditorRef = React15.useRef(null);
|
|
14814
|
+
const timeoutRef = React15.useRef(null);
|
|
14487
14815
|
const debounceMs = normalizeDebounceMs(outputDebounceMs);
|
|
14488
|
-
|
|
14816
|
+
React15.useLayoutEffect(() => {
|
|
14489
14817
|
callbacksRef.current = { onChange, onHtmlChange, onJsonChange };
|
|
14490
14818
|
}, [onChange, onHtmlChange, onJsonChange]);
|
|
14491
|
-
const flushOutputUpdates =
|
|
14819
|
+
const flushOutputUpdates = React15.useCallback(() => {
|
|
14492
14820
|
if (timeoutRef.current !== null) {
|
|
14493
14821
|
clearTimeout(timeoutRef.current);
|
|
14494
14822
|
timeoutRef.current = null;
|
|
@@ -14506,7 +14834,7 @@ function useUEditorOutput({
|
|
|
14506
14834
|
callbacks.onJsonChange(editor.getJSON());
|
|
14507
14835
|
}
|
|
14508
14836
|
}, []);
|
|
14509
|
-
const scheduleOutputUpdate =
|
|
14837
|
+
const scheduleOutputUpdate = React15.useCallback((editor) => {
|
|
14510
14838
|
const callbacks = callbacksRef.current;
|
|
14511
14839
|
if (!callbacks.onChange && !callbacks.onHtmlChange && !callbacks.onJsonChange) return;
|
|
14512
14840
|
pendingEditorRef.current = editor;
|
|
@@ -14520,32 +14848,98 @@ function useUEditorOutput({
|
|
|
14520
14848
|
}
|
|
14521
14849
|
timeoutRef.current = setTimeout(flushOutputUpdates, debounceMs);
|
|
14522
14850
|
}, [debounceMs, flushOutputUpdates]);
|
|
14523
|
-
|
|
14851
|
+
React15.useEffect(() => {
|
|
14524
14852
|
if (!pendingEditorRef.current || timeoutRef.current === null) return;
|
|
14525
14853
|
clearTimeout(timeoutRef.current);
|
|
14526
14854
|
timeoutRef.current = debounceMs === 0 ? null : setTimeout(flushOutputUpdates, debounceMs);
|
|
14527
14855
|
if (debounceMs === 0) flushOutputUpdates();
|
|
14528
14856
|
}, [debounceMs, flushOutputUpdates]);
|
|
14529
|
-
|
|
14857
|
+
React15.useEffect(() => () => {
|
|
14858
|
+
flushOutputUpdates();
|
|
14530
14859
|
if (timeoutRef.current !== null) {
|
|
14531
14860
|
clearTimeout(timeoutRef.current);
|
|
14532
14861
|
timeoutRef.current = null;
|
|
14533
14862
|
}
|
|
14534
14863
|
pendingEditorRef.current = null;
|
|
14535
|
-
}, []);
|
|
14864
|
+
}, [flushOutputUpdates]);
|
|
14536
14865
|
return {
|
|
14537
14866
|
flushOutputUpdates,
|
|
14538
14867
|
scheduleOutputUpdate
|
|
14539
14868
|
};
|
|
14540
14869
|
}
|
|
14541
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
|
+
|
|
14542
14936
|
// src/components/UEditor/UEditor.tsx
|
|
14543
14937
|
import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
14544
|
-
var LazyMenuBar =
|
|
14545
|
-
const { MenuBar } = await import("./menu-bar-
|
|
14938
|
+
var LazyMenuBar = React17.lazy(async () => {
|
|
14939
|
+
const { MenuBar } = await import("./menu-bar-DPCNNUX5.js");
|
|
14546
14940
|
return { default: MenuBar };
|
|
14547
14941
|
});
|
|
14548
|
-
var UEditor =
|
|
14942
|
+
var UEditor = React17.forwardRef(({
|
|
14549
14943
|
getPortalContainer,
|
|
14550
14944
|
content = "",
|
|
14551
14945
|
onChange,
|
|
@@ -14559,7 +14953,11 @@ var UEditor = React15.forwardRef(({
|
|
|
14559
14953
|
maxImageFileSize,
|
|
14560
14954
|
allowedImageMimeTypes,
|
|
14561
14955
|
fallbackToDataUrl,
|
|
14956
|
+
onImageUploadError,
|
|
14562
14957
|
placeholder,
|
|
14958
|
+
ariaLabel,
|
|
14959
|
+
ariaLabelledBy,
|
|
14960
|
+
ariaDescribedBy,
|
|
14563
14961
|
className,
|
|
14564
14962
|
editable = true,
|
|
14565
14963
|
autofocus = false,
|
|
@@ -14571,6 +14969,7 @@ var UEditor = React15.forwardRef(({
|
|
|
14571
14969
|
maxCharacters,
|
|
14572
14970
|
minHeight = "200px",
|
|
14573
14971
|
maxHeight = "auto",
|
|
14972
|
+
expandWideTables = true,
|
|
14574
14973
|
variant = "default",
|
|
14575
14974
|
rounded = true,
|
|
14576
14975
|
fontFamilies,
|
|
@@ -14598,8 +14997,10 @@ var UEditor = React15.forwardRef(({
|
|
|
14598
14997
|
const editorInstanceRef = useRef10(null);
|
|
14599
14998
|
const formulaRangePickRef = useRef10(null);
|
|
14600
14999
|
const formulaRangeSurfaceRef = useRef10(null);
|
|
14601
|
-
const [formulaRangeHighlight, setFormulaRangeHighlight] =
|
|
14602
|
-
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);
|
|
14603
15004
|
useEffect10(() => {
|
|
14604
15005
|
setIsMenuBarVisible(showMenuBar);
|
|
14605
15006
|
}, [showMenuBar]);
|
|
@@ -14609,7 +15010,7 @@ var UEditor = React15.forwardRef(({
|
|
|
14609
15010
|
onJsonChange,
|
|
14610
15011
|
outputDebounceMs
|
|
14611
15012
|
});
|
|
14612
|
-
const scheduleFormulaRecalculate =
|
|
15013
|
+
const scheduleFormulaRecalculate = React17.useCallback((editor2, options) => {
|
|
14613
15014
|
if (editor2.isDestroyed || scheduledFormulaRecalculateRef.current) return;
|
|
14614
15015
|
if (!options?.force && isEditingTableFormulaText(editor2)) return;
|
|
14615
15016
|
scheduledFormulaRecalculateRef.current = true;
|
|
@@ -14643,14 +15044,15 @@ var UEditor = React15.forwardRef(({
|
|
|
14643
15044
|
maxImageFileSize,
|
|
14644
15045
|
allowedImageMimeTypes,
|
|
14645
15046
|
fallbackToDataUrl,
|
|
15047
|
+
onImageUploadError,
|
|
14646
15048
|
editable,
|
|
14647
15049
|
fetchMetadata
|
|
14648
15050
|
}),
|
|
14649
15051
|
...extraExtensions ?? []
|
|
14650
15052
|
],
|
|
14651
|
-
[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]
|
|
14652
15054
|
);
|
|
14653
|
-
const syncFormulaRangeHighlight =
|
|
15055
|
+
const syncFormulaRangeHighlight = React17.useCallback((pickState) => {
|
|
14654
15056
|
const container = formulaRangeSurfaceRef.current;
|
|
14655
15057
|
setFormulaRangeHighlight(container && pickState ? getFormulaRangePickHighlight(container, pickState) : null);
|
|
14656
15058
|
}, []);
|
|
@@ -14722,9 +15124,6 @@ var UEditor = React15.forwardRef(({
|
|
|
14722
15124
|
clearSelectedTableCellFormula(activeEditor);
|
|
14723
15125
|
return true;
|
|
14724
15126
|
}
|
|
14725
|
-
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
14726
|
-
event.stopPropagation();
|
|
14727
|
-
}
|
|
14728
15127
|
return false;
|
|
14729
15128
|
},
|
|
14730
15129
|
click: (view, event) => {
|
|
@@ -14744,7 +15143,11 @@ var UEditor = React15.forwardRef(({
|
|
|
14744
15143
|
}
|
|
14745
15144
|
},
|
|
14746
15145
|
attributes: {
|
|
14747
|
-
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
|
|
14748
15151
|
}
|
|
14749
15152
|
},
|
|
14750
15153
|
onUpdate: ({ editor: editor2, transaction, appendedTransactions }) => {
|
|
@@ -14790,23 +15193,28 @@ var UEditor = React15.forwardRef(({
|
|
|
14790
15193
|
apply: t("tableMenu.apply"),
|
|
14791
15194
|
cancel: t("imageInput.cancelBtn")
|
|
14792
15195
|
});
|
|
15196
|
+
useWideTableLayout(editor, expandWideTables, widthBoundaryRef, editorShellRef, editorContentRef);
|
|
14793
15197
|
useImperativeHandle4(
|
|
14794
15198
|
ref,
|
|
14795
15199
|
() => ({
|
|
14796
15200
|
editor,
|
|
14797
15201
|
prepareContentForSave: async ({ throwOnError = false } = {}) => {
|
|
14798
|
-
|
|
14799
|
-
|
|
14800
|
-
|
|
15202
|
+
const htmlSnapshot = editor?.getHTML() ?? content ?? "";
|
|
15203
|
+
if (!inFlightPrepareRef.current || inFlightPrepareRef.current.html !== htmlSnapshot) {
|
|
15204
|
+
let trackedPromise;
|
|
15205
|
+
trackedPromise = prepareUEditorContentForSave({
|
|
14801
15206
|
html: htmlSnapshot,
|
|
14802
15207
|
uploadImageForSave,
|
|
14803
15208
|
uploadFileForSave,
|
|
14804
15209
|
uploadConcurrency: uploadImageConcurrency
|
|
14805
15210
|
}).finally(() => {
|
|
14806
|
-
inFlightPrepareRef.current
|
|
15211
|
+
if (inFlightPrepareRef.current?.promise === trackedPromise) {
|
|
15212
|
+
inFlightPrepareRef.current = null;
|
|
15213
|
+
}
|
|
14807
15214
|
});
|
|
15215
|
+
inFlightPrepareRef.current = { html: htmlSnapshot, promise: trackedPromise };
|
|
14808
15216
|
}
|
|
14809
|
-
const result = await inFlightPrepareRef.current;
|
|
15217
|
+
const result = await inFlightPrepareRef.current.promise;
|
|
14810
15218
|
if (throwOnError && result.errors.length > 0) {
|
|
14811
15219
|
throw new UEditorPrepareContentForSaveError(result);
|
|
14812
15220
|
}
|
|
@@ -14845,15 +15253,18 @@ var UEditor = React15.forwardRef(({
|
|
|
14845
15253
|
return /* @__PURE__ */ jsx20(UEditorPortalProvider, { getPortalContainer, children: /* @__PURE__ */ jsx20(
|
|
14846
15254
|
"div",
|
|
14847
15255
|
{
|
|
15256
|
+
role: "status",
|
|
15257
|
+
"aria-live": "polite",
|
|
14848
15258
|
className: cn("w-full border bg-background flex items-center justify-center text-muted-foreground", className),
|
|
14849
15259
|
style: { minHeight },
|
|
14850
15260
|
children: t("loading")
|
|
14851
15261
|
}
|
|
14852
15262
|
) });
|
|
14853
15263
|
}
|
|
14854
|
-
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(
|
|
14855
15265
|
"div",
|
|
14856
15266
|
{
|
|
15267
|
+
ref: editorShellRef,
|
|
14857
15268
|
className: cn(
|
|
14858
15269
|
"group relative flex flex-col text-card-foreground",
|
|
14859
15270
|
editable ? [
|
|
@@ -14868,7 +15279,7 @@ var UEditor = React15.forwardRef(({
|
|
|
14868
15279
|
),
|
|
14869
15280
|
children: [
|
|
14870
15281
|
editable && (showMenuBar || showToolbar || showBubbleMenu) ? /* @__PURE__ */ jsxs17(EditorUiRenderStateProvider, { editor, children: [
|
|
14871
|
-
isMenuBarVisible && /* @__PURE__ */ jsx20(
|
|
15282
|
+
isMenuBarVisible && /* @__PURE__ */ jsx20(React17.Suspense, { fallback: null, children: /* @__PURE__ */ jsx20(
|
|
14872
15283
|
LazyMenuBar,
|
|
14873
15284
|
{
|
|
14874
15285
|
editor,
|
|
@@ -14877,6 +15288,8 @@ var UEditor = React15.forwardRef(({
|
|
|
14877
15288
|
imageInsertMode,
|
|
14878
15289
|
maxImageFileSize,
|
|
14879
15290
|
allowedImageMimeTypes,
|
|
15291
|
+
onImageUploadError,
|
|
15292
|
+
fallbackToDataUrl,
|
|
14880
15293
|
onSave,
|
|
14881
15294
|
onExport,
|
|
14882
15295
|
onSourceCode,
|
|
@@ -14895,6 +15308,8 @@ var UEditor = React15.forwardRef(({
|
|
|
14895
15308
|
imageInsertMode,
|
|
14896
15309
|
maxImageFileSize,
|
|
14897
15310
|
allowedImageMimeTypes,
|
|
15311
|
+
onImageUploadError,
|
|
15312
|
+
fallbackToDataUrl,
|
|
14898
15313
|
fontFamilies,
|
|
14899
15314
|
defaultFontFamily,
|
|
14900
15315
|
fontSizes,
|
|
@@ -14920,7 +15335,10 @@ var UEditor = React15.forwardRef(({
|
|
|
14920
15335
|
editorContentRef.current = node;
|
|
14921
15336
|
formulaRangeSurfaceRef.current = node;
|
|
14922
15337
|
},
|
|
14923
|
-
className:
|
|
15338
|
+
className: cn(
|
|
15339
|
+
"relative flex-1 overflow-y-auto",
|
|
15340
|
+
expandWideTables && "[&_.tableWrapper]:!overflow-visible [&_.tableWrapper]:!pb-0"
|
|
15341
|
+
),
|
|
14924
15342
|
style: {
|
|
14925
15343
|
fontFamily: defaultFontFamily,
|
|
14926
15344
|
minHeight: editable ? minHeight : void 0,
|
|
@@ -14999,7 +15417,7 @@ var UEditor = React15.forwardRef(({
|
|
|
14999
15417
|
showFooter && showCharacterCount && /* @__PURE__ */ jsx20(CharacterCountDisplay, { editor, maxCharacters })
|
|
15000
15418
|
]
|
|
15001
15419
|
}
|
|
15002
|
-
) });
|
|
15420
|
+
) }) });
|
|
15003
15421
|
});
|
|
15004
15422
|
UEditor.displayName = "UEditor";
|
|
15005
15423
|
var UEditor_default = UEditor;
|
|
@@ -15011,4 +15429,4 @@ export {
|
|
|
15011
15429
|
prepareUEditorContentForSave,
|
|
15012
15430
|
UEditor_default
|
|
15013
15431
|
};
|
|
15014
|
-
//# sourceMappingURL=chunk-
|
|
15432
|
+
//# sourceMappingURL=chunk-57BKIC6J.js.map
|