@underverse-ui/underverse 1.0.155 → 1.0.157
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api-reference.json +1 -1
- package/dist/index.cjs +390 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -3
- package/dist/index.d.ts +38 -3
- package/dist/index.js +392 -65
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -869,12 +869,15 @@ var en_default = {
|
|
|
869
869
|
clickToOpenNewTab: "Click to open this link in a new tab.",
|
|
870
870
|
clickToOpenLink: "Click to open link.",
|
|
871
871
|
noDescription: "No description available.",
|
|
872
|
-
failedToLoad: "Failed to load link preview. Click to open link."
|
|
872
|
+
failedToLoad: "Failed to load link preview. Click to open link.",
|
|
873
|
+
previewFailed: "Preview failed to load",
|
|
874
|
+
retryPreview: "Retry preview"
|
|
873
875
|
},
|
|
874
876
|
fileCard: {
|
|
875
877
|
unnamed: "Unnamed file",
|
|
876
878
|
uploading: "(Uploading...)",
|
|
877
|
-
uploadFailed: "Upload failed"
|
|
879
|
+
uploadFailed: "Upload failed",
|
|
880
|
+
retryUpload: "Retry upload"
|
|
878
881
|
},
|
|
879
882
|
menubar: {
|
|
880
883
|
file: "File",
|
|
@@ -1261,12 +1264,15 @@ var vi_default = {
|
|
|
1261
1264
|
clickToOpenNewTab: "B\u1EA5m \u0111\u1EC3 m\u1EDF li\xEAn k\u1EBFt n\xE0y trong tab m\u1EDBi.",
|
|
1262
1265
|
clickToOpenLink: "B\u1EA5m \u0111\u1EC3 m\u1EDF li\xEAn k\u1EBFt.",
|
|
1263
1266
|
noDescription: "Kh\xF4ng c\xF3 m\xF4 t\u1EA3.",
|
|
1264
|
-
failedToLoad: "T\u1EA3i b\u1EA3n xem tr\u01B0\u1EDBc th\u1EA5t b\u1EA1i. B\u1EA5m \u0111\u1EC3 m\u1EDF li\xEAn k\u1EBFt."
|
|
1267
|
+
failedToLoad: "T\u1EA3i b\u1EA3n xem tr\u01B0\u1EDBc th\u1EA5t b\u1EA1i. B\u1EA5m \u0111\u1EC3 m\u1EDF li\xEAn k\u1EBFt.",
|
|
1268
|
+
previewFailed: "Kh\xF4ng t\u1EA3i \u0111\u01B0\u1EE3c b\u1EA3n xem tr\u01B0\u1EDBc",
|
|
1269
|
+
retryPreview: "Th\u1EED l\u1EA1i"
|
|
1265
1270
|
},
|
|
1266
1271
|
fileCard: {
|
|
1267
1272
|
unnamed: "T\u1EC7p kh\xF4ng t\xEAn",
|
|
1268
1273
|
uploading: "(\u0110ang t\u1EA3i l\xEAn...)",
|
|
1269
|
-
uploadFailed: "T\u1EA3i l\xEAn th\u1EA5t b\u1EA1i"
|
|
1274
|
+
uploadFailed: "T\u1EA3i l\xEAn th\u1EA5t b\u1EA1i",
|
|
1275
|
+
retryUpload: "T\u1EA3i l\u1EA1i"
|
|
1270
1276
|
},
|
|
1271
1277
|
menubar: {
|
|
1272
1278
|
file: "T\u1EADp tin",
|
|
@@ -1653,12 +1659,15 @@ var ko_default = {
|
|
|
1653
1659
|
clickToOpenNewTab: "\uD074\uB9AD\uD558\uC5EC \uC774 \uB9C1\uD06C\uB97C \uC0C8 \uD0ED\uC5D0\uC11C \uC5FD\uB2C8\uB2E4.",
|
|
1654
1660
|
clickToOpenLink: "\uD074\uB9AD\uD558\uC5EC \uB9C1\uD06C\uB97C \uC5FD\uB2C8\uB2E4.",
|
|
1655
1661
|
noDescription: "\uC124\uBA85\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
1656
|
-
failedToLoad: "\uB9C1\uD06C \uBBF8\uB9AC\uBCF4\uAE30\uB97C \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uD074\uB9AD\uD558\uC5EC \uB9C1\uD06C\uB97C \uC5FD\uB2C8\uB2E4."
|
|
1662
|
+
failedToLoad: "\uB9C1\uD06C \uBBF8\uB9AC\uBCF4\uAE30\uB97C \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uD074\uB9AD\uD558\uC5EC \uB9C1\uD06C\uB97C \uC5FD\uB2C8\uB2E4.",
|
|
1663
|
+
previewFailed: "\uBBF8\uB9AC\uBCF4\uAE30\uB97C \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4",
|
|
1664
|
+
retryPreview: "\uB2E4\uC2DC \uC2DC\uB3C4"
|
|
1657
1665
|
},
|
|
1658
1666
|
fileCard: {
|
|
1659
1667
|
unnamed: "\uC774\uB984 \uC5C6\uB294 \uD30C\uC77C",
|
|
1660
1668
|
uploading: "(\uC5C5\uB85C\uB4DC \uC911...)",
|
|
1661
|
-
uploadFailed: "\uC5C5\uB85C\uB4DC\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4."
|
|
1669
|
+
uploadFailed: "\uC5C5\uB85C\uB4DC\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.",
|
|
1670
|
+
retryUpload: "\uB2E4\uC2DC \uC5C5\uB85C\uB4DC"
|
|
1662
1671
|
},
|
|
1663
1672
|
menubar: {
|
|
1664
1673
|
file: "\uD30C\uC77C",
|
|
@@ -2045,12 +2054,15 @@ var ja_default = {
|
|
|
2045
2054
|
clickToOpenNewTab: "\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u3053\u306E\u30EA\u30F3\u30AF\u3092\u65B0\u3057\u3044\u30BF\u30D6\u3067\u958B\u304F\u3002",
|
|
2046
2055
|
clickToOpenLink: "\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u30EA\u30F3\u30AF\u3092\u958B\u304F\u3002",
|
|
2047
2056
|
noDescription: "\u8AAC\u660E\u306F\u3042\u308A\u307E\u305B\u3093\u3002",
|
|
2048
|
-
failedToLoad: "\u30D7\u30EC\u30D3\u30E5\u30FC\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u30EA\u30F3\u30AF\u3092\u958B\u304F\u3002"
|
|
2057
|
+
failedToLoad: "\u30D7\u30EC\u30D3\u30E5\u30FC\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u30EA\u30F3\u30AF\u3092\u958B\u304F\u3002",
|
|
2058
|
+
previewFailed: "\u30D7\u30EC\u30D3\u30E5\u30FC\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093\u3067\u3057\u305F",
|
|
2059
|
+
retryPreview: "\u518D\u8A66\u884C"
|
|
2049
2060
|
},
|
|
2050
2061
|
fileCard: {
|
|
2051
2062
|
unnamed: "\u540D\u524D\u306A\u3057\u30D5\u30A1\u30A4\u30EB",
|
|
2052
2063
|
uploading: "(\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u4E2D...)",
|
|
2053
|
-
uploadFailed: "\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u5931\u6557"
|
|
2064
|
+
uploadFailed: "\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u5931\u6557",
|
|
2065
|
+
retryUpload: "\u518D\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9"
|
|
2054
2066
|
},
|
|
2055
2067
|
menubar: {
|
|
2056
2068
|
file: "\u30D5\u30A1\u30A4\u30EB",
|
|
@@ -24855,21 +24867,27 @@ import { Node as Node3, mergeAttributes as mergeAttributes2 } from "@tiptap/core
|
|
|
24855
24867
|
import { ReactNodeViewRenderer as ReactNodeViewRenderer2 } from "@tiptap/react";
|
|
24856
24868
|
|
|
24857
24869
|
// src/components/UEditor/BookmarkView.tsx
|
|
24858
|
-
import { useEffect as useEffect31, useState as useState42 } from "react";
|
|
24870
|
+
import React68, { useEffect as useEffect31, useState as useState42 } from "react";
|
|
24859
24871
|
import { NodeViewWrapper as NodeViewWrapper2 } from "@tiptap/react";
|
|
24860
|
-
import { ExternalLink as ExternalLink2, Globe as Globe2 } from "lucide-react";
|
|
24872
|
+
import { AlertCircle as AlertCircle4, ExternalLink as ExternalLink2, Globe as Globe2, RefreshCw } from "lucide-react";
|
|
24861
24873
|
import { jsx as jsx77, jsxs as jsxs63 } from "react/jsx-runtime";
|
|
24862
24874
|
var BookmarkView = ({ node, updateAttributes, selected, editor }) => {
|
|
24863
24875
|
const t = useSmartTranslations("UEditor");
|
|
24864
24876
|
const { url, title, description, image, publisher } = node.attrs;
|
|
24865
24877
|
const [loading2, setLoading] = useState42(false);
|
|
24866
24878
|
const [error, setError] = useState42(false);
|
|
24879
|
+
const [retryToken, setRetryToken] = useState42(0);
|
|
24880
|
+
const fetchedRetryTokenRef = React68.useRef(-1);
|
|
24881
|
+
const fetchRequestIdRef = React68.useRef(0);
|
|
24867
24882
|
useEffect31(() => {
|
|
24868
|
-
if (title) return;
|
|
24869
|
-
|
|
24883
|
+
if (title && retryToken === 0) return;
|
|
24884
|
+
if (fetchedRetryTokenRef.current === retryToken) return;
|
|
24885
|
+
fetchedRetryTokenRef.current = retryToken;
|
|
24886
|
+
const requestId = fetchRequestIdRef.current + 1;
|
|
24887
|
+
fetchRequestIdRef.current = requestId;
|
|
24870
24888
|
const safeUpdateAttributes = (attrs) => {
|
|
24871
24889
|
Promise.resolve().then(() => {
|
|
24872
|
-
if (
|
|
24890
|
+
if (fetchRequestIdRef.current === requestId && editor && !editor.isDestroyed) {
|
|
24873
24891
|
updateAttributes(attrs);
|
|
24874
24892
|
}
|
|
24875
24893
|
});
|
|
@@ -24896,7 +24914,7 @@ var BookmarkView = ({ node, updateAttributes, selected, editor }) => {
|
|
|
24896
24914
|
setLoading(true);
|
|
24897
24915
|
setError(false);
|
|
24898
24916
|
fetchMetadata(url).then((meta) => {
|
|
24899
|
-
if (
|
|
24917
|
+
if (fetchRequestIdRef.current !== requestId) return;
|
|
24900
24918
|
safeUpdateAttributes({
|
|
24901
24919
|
title: meta.title || new URL(url).hostname || url,
|
|
24902
24920
|
description: meta.description || t("bookmark.noDescription"),
|
|
@@ -24905,33 +24923,22 @@ var BookmarkView = ({ node, updateAttributes, selected, editor }) => {
|
|
|
24905
24923
|
});
|
|
24906
24924
|
setLoading(false);
|
|
24907
24925
|
}).catch(() => {
|
|
24908
|
-
if (
|
|
24926
|
+
if (fetchRequestIdRef.current !== requestId) return;
|
|
24909
24927
|
setError(true);
|
|
24910
24928
|
setLoading(false);
|
|
24911
|
-
try {
|
|
24912
|
-
const hostname = new URL(url).hostname;
|
|
24913
|
-
safeUpdateAttributes({
|
|
24914
|
-
title: hostname || url,
|
|
24915
|
-
description: t("bookmark.failedToLoad"),
|
|
24916
|
-
publisher: hostname
|
|
24917
|
-
});
|
|
24918
|
-
} catch {
|
|
24919
|
-
safeUpdateAttributes({
|
|
24920
|
-
title: url,
|
|
24921
|
-
description: t("bookmark.clickToOpenLink"),
|
|
24922
|
-
publisher: ""
|
|
24923
|
-
});
|
|
24924
|
-
}
|
|
24925
24929
|
});
|
|
24926
|
-
return
|
|
24927
|
-
|
|
24928
|
-
};
|
|
24929
|
-
}, [url, title, editor, updateAttributes, t]);
|
|
24930
|
+
return void 0;
|
|
24931
|
+
}, [url, title, editor, updateAttributes, t, retryToken]);
|
|
24930
24932
|
const handleOpenLink = (e) => {
|
|
24931
24933
|
e.preventDefault();
|
|
24932
24934
|
e.stopPropagation();
|
|
24933
24935
|
window.open(url, "_blank", "noopener,noreferrer");
|
|
24934
24936
|
};
|
|
24937
|
+
const handleRetryPreview = (event) => {
|
|
24938
|
+
event.preventDefault();
|
|
24939
|
+
event.stopPropagation();
|
|
24940
|
+
setRetryToken((value) => value + 1);
|
|
24941
|
+
};
|
|
24935
24942
|
const displayPublisher = publisher || (() => {
|
|
24936
24943
|
try {
|
|
24937
24944
|
return new URL(url).hostname;
|
|
@@ -24967,6 +24974,24 @@ var BookmarkView = ({ node, updateAttributes, selected, editor }) => {
|
|
|
24967
24974
|
/* @__PURE__ */ jsxs63("span", { className: "text-[11px] text-primary/80 font-mono mt-2 truncate flex items-center gap-1", children: [
|
|
24968
24975
|
url,
|
|
24969
24976
|
/* @__PURE__ */ jsx77(ExternalLink2, { className: "h-3 w-3 flex-shrink-0" })
|
|
24977
|
+
] }),
|
|
24978
|
+
error && /* @__PURE__ */ jsxs63("div", { className: "mt-2 flex flex-wrap items-center gap-2 text-xs text-destructive", children: [
|
|
24979
|
+
/* @__PURE__ */ jsxs63("span", { className: "inline-flex items-center gap-1", children: [
|
|
24980
|
+
/* @__PURE__ */ jsx77(AlertCircle4, { className: "h-3.5 w-3.5" }),
|
|
24981
|
+
t("bookmark.previewFailed")
|
|
24982
|
+
] }),
|
|
24983
|
+
/* @__PURE__ */ jsxs63(
|
|
24984
|
+
"button",
|
|
24985
|
+
{
|
|
24986
|
+
type: "button",
|
|
24987
|
+
onClick: handleRetryPreview,
|
|
24988
|
+
className: "inline-flex items-center gap-1 rounded-md border border-destructive/30 px-2 py-0.5 font-medium hover:bg-destructive/10",
|
|
24989
|
+
children: [
|
|
24990
|
+
/* @__PURE__ */ jsx77(RefreshCw, { className: "h-3 w-3" }),
|
|
24991
|
+
t("bookmark.retryPreview")
|
|
24992
|
+
]
|
|
24993
|
+
}
|
|
24994
|
+
)
|
|
24970
24995
|
] })
|
|
24971
24996
|
] }),
|
|
24972
24997
|
image && /* @__PURE__ */ jsx77("div", { className: "relative w-full sm:w-44 h-32 sm:h-auto flex-shrink-0 bg-muted overflow-hidden border-t sm:border-t-0 sm:border-l border-border/50", children: /* @__PURE__ */ jsx77(
|
|
@@ -25104,7 +25129,7 @@ import { ReactNodeViewRenderer as ReactNodeViewRenderer3 } from "@tiptap/react";
|
|
|
25104
25129
|
// src/components/UEditor/FileCardView.tsx
|
|
25105
25130
|
import { useEffect as useEffect32, useState as useState43, useRef as useRef27 } from "react";
|
|
25106
25131
|
import { NodeViewWrapper as NodeViewWrapper3 } from "@tiptap/react";
|
|
25107
|
-
import { Download as Download2, File as LucideFile, FileText as FileText2, Image as Image3, Music, Video } from "lucide-react";
|
|
25132
|
+
import { Download as Download2, File as LucideFile, FileText as FileText2, Image as Image3, Music, RefreshCw as RefreshCw2, Video } from "lucide-react";
|
|
25108
25133
|
import { jsx as jsx78, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
25109
25134
|
function formatBytes(bytes, decimals = 1) {
|
|
25110
25135
|
if (!bytes || bytes <= 0) return "0 Bytes";
|
|
@@ -25151,6 +25176,7 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
25151
25176
|
const { src, fileName, fileSize, fileType } = node.attrs;
|
|
25152
25177
|
const FileIcon = getFileIcon2(fileType);
|
|
25153
25178
|
const [uploadError, setUploadError] = useState43(null);
|
|
25179
|
+
const [retryToken, setRetryToken] = useState43(0);
|
|
25154
25180
|
const uploadAttemptedRef = useRef27(false);
|
|
25155
25181
|
useEffect32(() => {
|
|
25156
25182
|
if (!src || !src.startsWith("data:")) {
|
|
@@ -25182,7 +25208,7 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
25182
25208
|
}
|
|
25183
25209
|
};
|
|
25184
25210
|
void runUpload();
|
|
25185
|
-
}, [src, fileName, fileType, editor, updateAttributes]);
|
|
25211
|
+
}, [src, fileName, fileType, editor, updateAttributes, retryToken]);
|
|
25186
25212
|
const handleDownload = (e) => {
|
|
25187
25213
|
e.preventDefault();
|
|
25188
25214
|
e.stopPropagation();
|
|
@@ -25195,6 +25221,13 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
25195
25221
|
document.body.removeChild(link);
|
|
25196
25222
|
};
|
|
25197
25223
|
const isUploading = (src || "").startsWith("data:");
|
|
25224
|
+
const handleRetryUpload = (event) => {
|
|
25225
|
+
event.preventDefault();
|
|
25226
|
+
event.stopPropagation();
|
|
25227
|
+
uploadAttemptedRef.current = false;
|
|
25228
|
+
setUploadError(null);
|
|
25229
|
+
setRetryToken((value) => value + 1);
|
|
25230
|
+
};
|
|
25198
25231
|
return /* @__PURE__ */ jsxs64(
|
|
25199
25232
|
NodeViewWrapper3,
|
|
25200
25233
|
{
|
|
@@ -25213,7 +25246,19 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
25213
25246
|
isUploading && /* @__PURE__ */ jsx78("span", { className: cn(
|
|
25214
25247
|
"font-medium truncate max-w-[200px]",
|
|
25215
25248
|
uploadError ? "text-destructive" : "text-primary animate-pulse"
|
|
25216
|
-
), children: uploadError ? `${t("fileCard.uploadFailed") || "T\u1EA3i l\xEAn th\u1EA5t b\u1EA1i"}: ${uploadError}` : t("fileCard.uploading") })
|
|
25249
|
+
), children: uploadError ? `${t("fileCard.uploadFailed") || "T\u1EA3i l\xEAn th\u1EA5t b\u1EA1i"}: ${uploadError}` : t("fileCard.uploading") }),
|
|
25250
|
+
isUploading && uploadError && /* @__PURE__ */ jsxs64(
|
|
25251
|
+
"button",
|
|
25252
|
+
{
|
|
25253
|
+
type: "button",
|
|
25254
|
+
onClick: handleRetryUpload,
|
|
25255
|
+
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",
|
|
25256
|
+
children: [
|
|
25257
|
+
/* @__PURE__ */ jsx78(RefreshCw2, { className: "h-3 w-3" }),
|
|
25258
|
+
t("fileCard.retryUpload")
|
|
25259
|
+
]
|
|
25260
|
+
}
|
|
25261
|
+
)
|
|
25217
25262
|
] })
|
|
25218
25263
|
] })
|
|
25219
25264
|
] }),
|
|
@@ -28816,6 +28861,20 @@ function createEmptyCellNode(cellNode) {
|
|
|
28816
28861
|
function createCellCopyForColumnDuplicate(cellNode) {
|
|
28817
28862
|
return cellNode.type.create(cellNode.attrs, cellNode.content);
|
|
28818
28863
|
}
|
|
28864
|
+
function createCellWithDuplicatedLogicalColumn(cellNode, widthIndex) {
|
|
28865
|
+
const colspan = Math.max(1, Number(cellNode.attrs.colspan) || 1);
|
|
28866
|
+
let nextColwidth = null;
|
|
28867
|
+
if (Array.isArray(cellNode.attrs.colwidth)) {
|
|
28868
|
+
nextColwidth = [...cellNode.attrs.colwidth];
|
|
28869
|
+
const duplicateWidth = nextColwidth[widthIndex];
|
|
28870
|
+
nextColwidth.splice(widthIndex + 1, 0, typeof duplicateWidth === "number" ? duplicateWidth : 0);
|
|
28871
|
+
}
|
|
28872
|
+
return cellNode.type.create({
|
|
28873
|
+
...cellNode.attrs,
|
|
28874
|
+
colspan: colspan + 1,
|
|
28875
|
+
...nextColwidth ? { colwidth: nextColwidth } : null
|
|
28876
|
+
}, cellNode.content);
|
|
28877
|
+
}
|
|
28819
28878
|
function getTableRows(tableNode) {
|
|
28820
28879
|
const rows = [];
|
|
28821
28880
|
tableNode.forEach((rowNode, rowOffset) => {
|
|
@@ -28991,6 +29050,11 @@ function duplicateTableColumnAt(editor, columnIndex, cellPos) {
|
|
|
28991
29050
|
return rect && rect.top === rowIndex && rect.left <= columnIndex && columnIndex < rect.right;
|
|
28992
29051
|
});
|
|
28993
29052
|
if (!sourceCell) return rowInfo.node;
|
|
29053
|
+
const sourceRect = safeFindCell(map, sourceCell.relativePos);
|
|
29054
|
+
if (sourceRect && (sourceRect.left < columnIndex || sourceRect.right > columnIndex + 1)) {
|
|
29055
|
+
cells[sourceCell.index] = createCellWithDuplicatedLogicalColumn(sourceCell.node, columnIndex - sourceRect.left);
|
|
29056
|
+
return rowInfo.node.type.create(rowInfo.node.attrs, cells);
|
|
29057
|
+
}
|
|
28994
29058
|
cells.splice(sourceCell.index + 1, 0, createCellCopyForColumnDuplicate(sourceCell.node));
|
|
28995
29059
|
return rowInfo.node.type.create(rowInfo.node.attrs, cells);
|
|
28996
29060
|
});
|
|
@@ -30312,6 +30376,25 @@ function getTableFormulaRecalculationOrder(graph) {
|
|
|
30312
30376
|
}
|
|
30313
30377
|
return { order, circular };
|
|
30314
30378
|
}
|
|
30379
|
+
function getAffectedTableFormulaLabels(graph, changedLabels) {
|
|
30380
|
+
const affected = /* @__PURE__ */ new Set();
|
|
30381
|
+
const queue = Array.from(changedLabels, (label) => label.toUpperCase());
|
|
30382
|
+
for (const label of queue) {
|
|
30383
|
+
if (graph.formulas.has(label)) {
|
|
30384
|
+
affected.add(label);
|
|
30385
|
+
}
|
|
30386
|
+
}
|
|
30387
|
+
for (let index = 0; index < queue.length; index += 1) {
|
|
30388
|
+
const label = queue[index];
|
|
30389
|
+
if (!label) continue;
|
|
30390
|
+
for (const dependent of graph.dependents.get(label) ?? []) {
|
|
30391
|
+
if (affected.has(dependent)) continue;
|
|
30392
|
+
affected.add(dependent);
|
|
30393
|
+
queue.push(dependent);
|
|
30394
|
+
}
|
|
30395
|
+
}
|
|
30396
|
+
return affected;
|
|
30397
|
+
}
|
|
30315
30398
|
function evaluateBasicTableFormula(formula, getCellValue) {
|
|
30316
30399
|
const normalized = normalizeTableFormula(formula);
|
|
30317
30400
|
if (!normalized) {
|
|
@@ -30459,10 +30542,19 @@ var FormulaParser = class {
|
|
|
30459
30542
|
const range = parseTableCellRange(token.value);
|
|
30460
30543
|
if (!range) return { value: null, error: "invalid-reference" };
|
|
30461
30544
|
for (const label of getTableCellRangeLabels(range)) {
|
|
30545
|
+
if (name === "COUNT") {
|
|
30546
|
+
const cellValue2 = this.readOptionalCellNumber(label);
|
|
30547
|
+
if (cellValue2 != null) values.push(cellValue2);
|
|
30548
|
+
continue;
|
|
30549
|
+
}
|
|
30462
30550
|
const cellValue = this.readCellNumber(label);
|
|
30463
30551
|
if (cellValue.error) return cellValue;
|
|
30464
30552
|
values.push(cellValue.value);
|
|
30465
30553
|
}
|
|
30554
|
+
} else if (name === "COUNT" && token.type === "cell") {
|
|
30555
|
+
this.index += 1;
|
|
30556
|
+
const cellValue = this.readOptionalCellNumber(token.value);
|
|
30557
|
+
if (cellValue != null) values.push(cellValue);
|
|
30466
30558
|
} else {
|
|
30467
30559
|
const value = this.parseExpression();
|
|
30468
30560
|
if (value.error) return value;
|
|
@@ -30476,7 +30568,7 @@ var FormulaParser = class {
|
|
|
30476
30568
|
}
|
|
30477
30569
|
return { value: null, error: "invalid-formula" };
|
|
30478
30570
|
}
|
|
30479
|
-
if (values.length === 0) {
|
|
30571
|
+
if (values.length === 0 && name !== "COUNT") {
|
|
30480
30572
|
return { value: null, error: "invalid-formula" };
|
|
30481
30573
|
}
|
|
30482
30574
|
if (name === "SUM") return { value: values.reduce((sum, value) => sum + value, 0), error: null };
|
|
@@ -30494,6 +30586,11 @@ var FormulaParser = class {
|
|
|
30494
30586
|
}
|
|
30495
30587
|
return { value: parsed, error: null };
|
|
30496
30588
|
}
|
|
30589
|
+
readOptionalCellNumber(label) {
|
|
30590
|
+
const value = this.getCellValue(label);
|
|
30591
|
+
const parsed = typeof value === "number" ? value : Number.parseFloat(String(value ?? "").trim());
|
|
30592
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
30593
|
+
}
|
|
30497
30594
|
peekOperator(operators) {
|
|
30498
30595
|
const token = this.tokens[this.index];
|
|
30499
30596
|
return token?.type === "operator" && operators.includes(token.value) ? token : null;
|
|
@@ -30557,6 +30654,41 @@ function getSelectionTableCellNode(editor) {
|
|
|
30557
30654
|
}
|
|
30558
30655
|
return null;
|
|
30559
30656
|
}
|
|
30657
|
+
function getSelectionTableInfo(editor) {
|
|
30658
|
+
const { $from } = editor.state.selection;
|
|
30659
|
+
for (let depth = $from.depth; depth > 0; depth -= 1) {
|
|
30660
|
+
const node = $from.node(depth);
|
|
30661
|
+
if (node.type.name === "table") {
|
|
30662
|
+
return {
|
|
30663
|
+
node,
|
|
30664
|
+
pos: $from.before(depth)
|
|
30665
|
+
};
|
|
30666
|
+
}
|
|
30667
|
+
}
|
|
30668
|
+
return null;
|
|
30669
|
+
}
|
|
30670
|
+
function getSelectionTableCellLabel(editor) {
|
|
30671
|
+
const { $from } = editor.state.selection;
|
|
30672
|
+
let cellDepth = -1;
|
|
30673
|
+
let tableDepth = -1;
|
|
30674
|
+
for (let depth = $from.depth; depth > 0; depth -= 1) {
|
|
30675
|
+
const node = $from.node(depth);
|
|
30676
|
+
if (cellDepth < 0 && (node.type.name === "tableCell" || node.type.name === "tableHeader")) {
|
|
30677
|
+
cellDepth = depth;
|
|
30678
|
+
}
|
|
30679
|
+
if (node.type.name === "table") {
|
|
30680
|
+
tableDepth = depth;
|
|
30681
|
+
break;
|
|
30682
|
+
}
|
|
30683
|
+
}
|
|
30684
|
+
if (cellDepth < 0 || tableDepth < 0) return null;
|
|
30685
|
+
const tableNode = $from.node(tableDepth);
|
|
30686
|
+
const tableStart = $from.start(tableDepth);
|
|
30687
|
+
const relativeCellPos = $from.before(cellDepth) - tableStart;
|
|
30688
|
+
const rect = safeFindCell2(TableMap2.get(tableNode), relativeCellPos);
|
|
30689
|
+
if (!rect) return null;
|
|
30690
|
+
return `${indexToColumnName(rect.left)}${rect.top + 1}`;
|
|
30691
|
+
}
|
|
30560
30692
|
function isEditingTableFormulaText(editor) {
|
|
30561
30693
|
const cellNode = getSelectionTableCellNode(editor);
|
|
30562
30694
|
return Boolean(cellNode && getCellText(cellNode).startsWith("="));
|
|
@@ -30568,20 +30700,6 @@ function createCellDisplayContent(cellNode, displayValue) {
|
|
|
30568
30700
|
}
|
|
30569
30701
|
return [paragraphType.create(null, cellNode.type.schema.text(displayValue))];
|
|
30570
30702
|
}
|
|
30571
|
-
function buildTableValueGetter(tableNode) {
|
|
30572
|
-
const map = TableMap2.get(tableNode);
|
|
30573
|
-
const values = /* @__PURE__ */ new Map();
|
|
30574
|
-
for (const rowInfo of getTableRows2(tableNode)) {
|
|
30575
|
-
for (const entry of rowInfo.cells) {
|
|
30576
|
-
const rect = safeFindCell2(map, entry.relativePos);
|
|
30577
|
-
if (!rect) continue;
|
|
30578
|
-
const label = `${indexToColumnName(rect.left)}${rect.top + 1}`;
|
|
30579
|
-
const computedValue = entry.node.attrs.computedValue;
|
|
30580
|
-
values.set(label, typeof computedValue === "string" && computedValue.trim() ? computedValue : getCellText(entry.node));
|
|
30581
|
-
}
|
|
30582
|
-
}
|
|
30583
|
-
return (label) => values.get(label.toUpperCase());
|
|
30584
|
-
}
|
|
30585
30703
|
function buildTableValueMap(tableNode) {
|
|
30586
30704
|
const map = TableMap2.get(tableNode);
|
|
30587
30705
|
const values = /* @__PURE__ */ new Map();
|
|
@@ -30596,10 +30714,6 @@ function buildTableValueMap(tableNode) {
|
|
|
30596
30714
|
}
|
|
30597
30715
|
return values;
|
|
30598
30716
|
}
|
|
30599
|
-
function getFormulaComputedValue(formula, tableNode) {
|
|
30600
|
-
const result = evaluateBasicTableFormula(formula, buildTableValueGetter(tableNode));
|
|
30601
|
-
return result.error ? `#${result.error.toUpperCase()}` : String(result.value);
|
|
30602
|
-
}
|
|
30603
30717
|
function normalizeFormulaInput(formula) {
|
|
30604
30718
|
const trimmed = formula.trim();
|
|
30605
30719
|
if (!trimmed) return "";
|
|
@@ -30610,19 +30724,19 @@ function setSelectedTableCellFormula(editor, formula) {
|
|
|
30610
30724
|
const { state, view } = editor;
|
|
30611
30725
|
if (!normalized) {
|
|
30612
30726
|
const clearedFormula = setCellAttr("formula", null)(state, view.dispatch.bind(view));
|
|
30613
|
-
const
|
|
30614
|
-
if (clearedFormula ||
|
|
30727
|
+
const clearedValue2 = setCellAttr("computedValue", null)(editor.state, view.dispatch.bind(view));
|
|
30728
|
+
if (clearedFormula || clearedValue2) {
|
|
30729
|
+
recalculateActiveTableFormulas(editor);
|
|
30615
30730
|
view.focus();
|
|
30616
30731
|
dispatchTableLayoutChange(editor);
|
|
30617
30732
|
return true;
|
|
30618
30733
|
}
|
|
30619
30734
|
return false;
|
|
30620
30735
|
}
|
|
30621
|
-
const rect = selectedRect2(state);
|
|
30622
|
-
const computedValue = getFormulaComputedValue(normalized, rect.table);
|
|
30623
30736
|
const appliedFormula = setCellAttr("formula", normalized)(state, view.dispatch.bind(view));
|
|
30624
|
-
const
|
|
30625
|
-
if (appliedFormula ||
|
|
30737
|
+
const clearedValue = setCellAttr("computedValue", null)(editor.state, view.dispatch.bind(view));
|
|
30738
|
+
if (appliedFormula || clearedValue) {
|
|
30739
|
+
recalculateActiveTableFormulas(editor);
|
|
30626
30740
|
view.focus();
|
|
30627
30741
|
dispatchTableLayoutChange(editor);
|
|
30628
30742
|
return true;
|
|
@@ -30704,7 +30818,7 @@ function promoteFormulaTextInTableNode(tableNode) {
|
|
|
30704
30818
|
changed
|
|
30705
30819
|
};
|
|
30706
30820
|
}
|
|
30707
|
-
function recalculateTableNode(tableNode) {
|
|
30821
|
+
function recalculateTableNode(tableNode, options) {
|
|
30708
30822
|
const promoted = promoteFormulaTextInTableNode(tableNode);
|
|
30709
30823
|
tableNode = promoted.tableNode;
|
|
30710
30824
|
const map = TableMap2.get(tableNode);
|
|
@@ -30734,13 +30848,16 @@ function recalculateTableNode(tableNode) {
|
|
|
30734
30848
|
}))
|
|
30735
30849
|
);
|
|
30736
30850
|
const { order, circular } = getTableFormulaRecalculationOrder(graph);
|
|
30851
|
+
const affectedLabels = options?.changedLabels ? getAffectedTableFormulaLabels(graph, options.changedLabels) : null;
|
|
30737
30852
|
const computedValues = /* @__PURE__ */ new Map();
|
|
30738
30853
|
const getCellValue = (label) => values.get(label.toUpperCase());
|
|
30739
30854
|
for (const label of circular) {
|
|
30855
|
+
if (affectedLabels && !affectedLabels.has(label)) continue;
|
|
30740
30856
|
computedValues.set(label, formatFormulaError("circular-reference"));
|
|
30741
30857
|
values.set(label, formatFormulaError("circular-reference"));
|
|
30742
30858
|
}
|
|
30743
30859
|
for (const label of order) {
|
|
30860
|
+
if (affectedLabels && !affectedLabels.has(label)) continue;
|
|
30744
30861
|
const entry = formulaEntries.get(label);
|
|
30745
30862
|
if (!entry) continue;
|
|
30746
30863
|
const result = evaluateBasicTableFormula(entry.formula, getCellValue);
|
|
@@ -30785,6 +30902,22 @@ function recalculateSelectedTable(editor) {
|
|
|
30785
30902
|
dispatchTableLayoutChange(editor);
|
|
30786
30903
|
return true;
|
|
30787
30904
|
}
|
|
30905
|
+
function recalculateActiveTableFormulas(editor) {
|
|
30906
|
+
const tableInfo = getSelectionTableInfo(editor);
|
|
30907
|
+
if (!tableInfo) {
|
|
30908
|
+
return recalculateAllTableFormulas(editor);
|
|
30909
|
+
}
|
|
30910
|
+
const activeCellLabel = getSelectionTableCellLabel(editor);
|
|
30911
|
+
const nextTable = recalculateTableNode(tableInfo.node, {
|
|
30912
|
+
changedLabels: activeCellLabel ? [activeCellLabel] : null
|
|
30913
|
+
});
|
|
30914
|
+
if (!nextTable) return false;
|
|
30915
|
+
editor.view.dispatch(
|
|
30916
|
+
editor.state.tr.replaceWith(tableInfo.pos, tableInfo.pos + tableInfo.node.nodeSize, nextTable).setMeta(UEDITOR_TABLE_FORMULA_RECALCULATE_META, true)
|
|
30917
|
+
);
|
|
30918
|
+
dispatchTableLayoutChange(editor);
|
|
30919
|
+
return true;
|
|
30920
|
+
}
|
|
30788
30921
|
function recalculateAllTableFormulas(editor) {
|
|
30789
30922
|
const replacements = [];
|
|
30790
30923
|
editor.state.doc.descendants((node, pos) => {
|
|
@@ -38820,6 +38953,146 @@ var MenuBar = ({
|
|
|
38820
38953
|
] });
|
|
38821
38954
|
};
|
|
38822
38955
|
|
|
38956
|
+
// src/components/UEditor/table-formula-range-picker.ts
|
|
38957
|
+
import { TextSelection as TextSelection4 } from "@tiptap/pm/state";
|
|
38958
|
+
import { TableMap as TableMap4 } from "@tiptap/pm/tables";
|
|
38959
|
+
function getCellText2(cellNode) {
|
|
38960
|
+
return cellNode.textBetween(0, cellNode.content.size, "\n").trim();
|
|
38961
|
+
}
|
|
38962
|
+
function findSelectionFormulaCell(view) {
|
|
38963
|
+
const { $from } = view.state.selection;
|
|
38964
|
+
for (let depth = $from.depth; depth > 0; depth -= 1) {
|
|
38965
|
+
const node = $from.node(depth);
|
|
38966
|
+
if (node.type.name !== "tableCell" && node.type.name !== "tableHeader") continue;
|
|
38967
|
+
if (!getCellText2(node).startsWith("=")) return null;
|
|
38968
|
+
const cellPos = $from.before(depth);
|
|
38969
|
+
const cellDom = view.nodeDOM(cellPos);
|
|
38970
|
+
const tableDepth = depth - 2;
|
|
38971
|
+
const tableNode = tableDepth > 0 ? $from.node(tableDepth) : null;
|
|
38972
|
+
if (!tableNode || tableNode.type.name !== "table") return null;
|
|
38973
|
+
return {
|
|
38974
|
+
cellDom: cellDom instanceof HTMLTableCellElement ? cellDom : null,
|
|
38975
|
+
tablePos: $from.before(tableDepth)
|
|
38976
|
+
};
|
|
38977
|
+
}
|
|
38978
|
+
return null;
|
|
38979
|
+
}
|
|
38980
|
+
function findTableForPos(view, pos) {
|
|
38981
|
+
const $pos = view.state.doc.resolve(pos);
|
|
38982
|
+
for (let depth = $pos.depth; depth > 0; depth -= 1) {
|
|
38983
|
+
const node = $pos.node(depth);
|
|
38984
|
+
if (node.type.name === "table") {
|
|
38985
|
+
return {
|
|
38986
|
+
node,
|
|
38987
|
+
pos: $pos.before(depth),
|
|
38988
|
+
start: $pos.start(depth)
|
|
38989
|
+
};
|
|
38990
|
+
}
|
|
38991
|
+
}
|
|
38992
|
+
return null;
|
|
38993
|
+
}
|
|
38994
|
+
function getCellRelativePosFromDomPos2(map, tableStart, domPos) {
|
|
38995
|
+
const relativeDomPos = domPos - tableStart;
|
|
38996
|
+
const seen = /* @__PURE__ */ new Set();
|
|
38997
|
+
for (const relativeCellPos of map.map) {
|
|
38998
|
+
if (seen.has(relativeCellPos)) continue;
|
|
38999
|
+
seen.add(relativeCellPos);
|
|
39000
|
+
if (relativeDomPos === relativeCellPos || relativeDomPos === relativeCellPos + 1) {
|
|
39001
|
+
return relativeCellPos;
|
|
39002
|
+
}
|
|
39003
|
+
}
|
|
39004
|
+
return null;
|
|
39005
|
+
}
|
|
39006
|
+
function getPickedCellLabel(view, target, tablePos) {
|
|
39007
|
+
const element = resolveEventElement(target);
|
|
39008
|
+
const cell = element?.closest?.("th,td");
|
|
39009
|
+
if (!(cell instanceof HTMLTableCellElement)) return null;
|
|
39010
|
+
const domPos = view.posAtDOM(cell, 0);
|
|
39011
|
+
const tableInfo = findTableForPos(view, domPos);
|
|
39012
|
+
if (!tableInfo || tableInfo.pos !== tablePos) return null;
|
|
39013
|
+
const map = TableMap4.get(tableInfo.node);
|
|
39014
|
+
const relativeCellPos = getCellRelativePosFromDomPos2(map, tableInfo.start, domPos);
|
|
39015
|
+
if (relativeCellPos == null) return null;
|
|
39016
|
+
const rect = map.findCell(relativeCellPos);
|
|
39017
|
+
return {
|
|
39018
|
+
cell,
|
|
39019
|
+
label: `${indexToColumnName(rect.left)}${rect.top + 1}`
|
|
39020
|
+
};
|
|
39021
|
+
}
|
|
39022
|
+
function normalizeFormulaRangeLabel(fromLabel, toLabel) {
|
|
39023
|
+
return fromLabel === toLabel ? fromLabel : `${fromLabel}:${toLabel}`;
|
|
39024
|
+
}
|
|
39025
|
+
function replacePickedLabel(view, pickState, nextLabel, currentCell) {
|
|
39026
|
+
if (nextLabel === pickState.currentLabel && currentCell === pickState.currentCell) return pickState;
|
|
39027
|
+
if (nextLabel === pickState.currentLabel) {
|
|
39028
|
+
return {
|
|
39029
|
+
...pickState,
|
|
39030
|
+
currentCell
|
|
39031
|
+
};
|
|
39032
|
+
}
|
|
39033
|
+
let tr = view.state.tr.insertText(nextLabel, pickState.insertedFrom, pickState.insertedTo);
|
|
39034
|
+
const nextTo = pickState.insertedFrom + nextLabel.length;
|
|
39035
|
+
tr = tr.setSelection(TextSelection4.create(tr.doc, nextTo));
|
|
39036
|
+
view.dispatch(tr);
|
|
39037
|
+
return {
|
|
39038
|
+
...pickState,
|
|
39039
|
+
insertedTo: nextTo,
|
|
39040
|
+
currentLabel: nextLabel,
|
|
39041
|
+
currentCell
|
|
39042
|
+
};
|
|
39043
|
+
}
|
|
39044
|
+
function beginFormulaRangePick(view, event) {
|
|
39045
|
+
if (event.button !== 0) return null;
|
|
39046
|
+
const formulaCell = findSelectionFormulaCell(view);
|
|
39047
|
+
if (!formulaCell) return null;
|
|
39048
|
+
const picked = getPickedCellLabel(view, event.target, formulaCell.tablePos);
|
|
39049
|
+
if (!picked || picked.cell === formulaCell.cellDom) return null;
|
|
39050
|
+
const { from, to } = view.state.selection;
|
|
39051
|
+
let tr = view.state.tr.insertText(picked.label, from, to);
|
|
39052
|
+
tr = tr.setSelection(TextSelection4.create(tr.doc, from + picked.label.length));
|
|
39053
|
+
view.dispatch(tr);
|
|
39054
|
+
view.focus();
|
|
39055
|
+
event.preventDefault();
|
|
39056
|
+
event.stopPropagation();
|
|
39057
|
+
return {
|
|
39058
|
+
anchorLabel: picked.label,
|
|
39059
|
+
anchorCell: picked.cell,
|
|
39060
|
+
tablePos: formulaCell.tablePos,
|
|
39061
|
+
insertedFrom: from,
|
|
39062
|
+
insertedTo: from + picked.label.length,
|
|
39063
|
+
currentLabel: picked.label,
|
|
39064
|
+
currentCell: picked.cell
|
|
39065
|
+
};
|
|
39066
|
+
}
|
|
39067
|
+
function updateFormulaRangePick(view, pickState, event) {
|
|
39068
|
+
const picked = getPickedCellLabel(view, event.target, pickState.tablePos);
|
|
39069
|
+
if (!picked) return pickState;
|
|
39070
|
+
event.preventDefault();
|
|
39071
|
+
event.stopPropagation();
|
|
39072
|
+
return replacePickedLabel(
|
|
39073
|
+
view,
|
|
39074
|
+
pickState,
|
|
39075
|
+
normalizeFormulaRangeLabel(pickState.anchorLabel, picked.label),
|
|
39076
|
+
picked.cell
|
|
39077
|
+
);
|
|
39078
|
+
}
|
|
39079
|
+
function getFormulaRangePickHighlight(container, pickState) {
|
|
39080
|
+
if (!container.contains(pickState.anchorCell) || !container.contains(pickState.currentCell)) return null;
|
|
39081
|
+
const containerRect = container.getBoundingClientRect();
|
|
39082
|
+
const anchorRect = pickState.anchorCell.getBoundingClientRect();
|
|
39083
|
+
const currentRect = pickState.currentCell.getBoundingClientRect();
|
|
39084
|
+
const left = Math.min(anchorRect.left, currentRect.left) - containerRect.left + container.scrollLeft;
|
|
39085
|
+
const top = Math.min(anchorRect.top, currentRect.top) - containerRect.top + container.scrollTop;
|
|
39086
|
+
const right = Math.max(anchorRect.right, currentRect.right) - containerRect.left + container.scrollLeft;
|
|
39087
|
+
const bottom = Math.max(anchorRect.bottom, currentRect.bottom) - containerRect.top + container.scrollTop;
|
|
39088
|
+
return {
|
|
39089
|
+
left,
|
|
39090
|
+
top,
|
|
39091
|
+
width: Math.max(0, right - left),
|
|
39092
|
+
height: Math.max(0, bottom - top)
|
|
39093
|
+
};
|
|
39094
|
+
}
|
|
39095
|
+
|
|
38823
39096
|
// src/components/UEditor/UEditor.tsx
|
|
38824
39097
|
import { jsx as jsx94, jsxs as jsxs79 } from "react/jsx-runtime";
|
|
38825
39098
|
var UEditor = React83.forwardRef(({
|
|
@@ -38852,7 +39125,6 @@ var UEditor = React83.forwardRef(({
|
|
|
38852
39125
|
fetchMetadata,
|
|
38853
39126
|
uploadFile,
|
|
38854
39127
|
uploadFileForSave,
|
|
38855
|
-
collaborationOptions,
|
|
38856
39128
|
extraExtensions,
|
|
38857
39129
|
showMenuBar = false,
|
|
38858
39130
|
onSave,
|
|
@@ -38865,6 +39137,9 @@ var UEditor = React83.forwardRef(({
|
|
|
38865
39137
|
const inFlightPrepareRef = useRef37(null);
|
|
38866
39138
|
const lastAppliedContentRef = useRef37(content ?? "");
|
|
38867
39139
|
const scheduledFormulaRecalculateRef = useRef37(false);
|
|
39140
|
+
const formulaRangePickRef = useRef37(null);
|
|
39141
|
+
const formulaRangeSurfaceRef = useRef37(null);
|
|
39142
|
+
const [formulaRangeHighlight, setFormulaRangeHighlight] = React83.useState(null);
|
|
38868
39143
|
const scheduleFormulaRecalculate = React83.useCallback((editor2, options) => {
|
|
38869
39144
|
if (editor2.isDestroyed || scheduledFormulaRecalculateRef.current) return;
|
|
38870
39145
|
if (!options?.force && isEditingTableFormulaText(editor2)) return;
|
|
@@ -38872,7 +39147,7 @@ var UEditor = React83.forwardRef(({
|
|
|
38872
39147
|
queueMicrotask(() => {
|
|
38873
39148
|
scheduledFormulaRecalculateRef.current = false;
|
|
38874
39149
|
if (!editor2.isDestroyed && (options?.force || !isEditingTableFormulaText(editor2))) {
|
|
38875
|
-
|
|
39150
|
+
recalculateActiveTableFormulas(editor2);
|
|
38876
39151
|
}
|
|
38877
39152
|
});
|
|
38878
39153
|
}, []);
|
|
@@ -38905,6 +39180,10 @@ var UEditor = React83.forwardRef(({
|
|
|
38905
39180
|
],
|
|
38906
39181
|
[effectivePlaceholder, t, maxCharacters, uploadImage, resolvedUploadFile, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable, fetchMetadata, extraExtensions]
|
|
38907
39182
|
);
|
|
39183
|
+
const syncFormulaRangeHighlight = React83.useCallback((pickState) => {
|
|
39184
|
+
const container = formulaRangeSurfaceRef.current;
|
|
39185
|
+
setFormulaRangeHighlight(container && pickState ? getFormulaRangePickHighlight(container, pickState) : null);
|
|
39186
|
+
}, []);
|
|
38908
39187
|
const editor = useEditor({
|
|
38909
39188
|
immediatelyRender: false,
|
|
38910
39189
|
extensions,
|
|
@@ -38913,6 +39192,37 @@ var UEditor = React83.forwardRef(({
|
|
|
38913
39192
|
autofocus,
|
|
38914
39193
|
editorProps: {
|
|
38915
39194
|
handleDOMEvents: {
|
|
39195
|
+
mousedown: (view, event) => {
|
|
39196
|
+
if (!(event instanceof MouseEvent)) return false;
|
|
39197
|
+
const pickState = beginFormulaRangePick(view, event);
|
|
39198
|
+
if (!pickState) return false;
|
|
39199
|
+
formulaRangePickRef.current = pickState;
|
|
39200
|
+
syncFormulaRangeHighlight(pickState);
|
|
39201
|
+
return true;
|
|
39202
|
+
},
|
|
39203
|
+
mousemove: (view, event) => {
|
|
39204
|
+
if (!(event instanceof MouseEvent)) return false;
|
|
39205
|
+
const pickState = formulaRangePickRef.current;
|
|
39206
|
+
if (!pickState) return false;
|
|
39207
|
+
if (event.buttons === 0) {
|
|
39208
|
+
formulaRangePickRef.current = null;
|
|
39209
|
+
syncFormulaRangeHighlight(null);
|
|
39210
|
+
return false;
|
|
39211
|
+
}
|
|
39212
|
+
const nextPickState = updateFormulaRangePick(view, pickState, event);
|
|
39213
|
+
formulaRangePickRef.current = nextPickState;
|
|
39214
|
+
syncFormulaRangeHighlight(nextPickState);
|
|
39215
|
+
return true;
|
|
39216
|
+
},
|
|
39217
|
+
mouseup: (_view, event) => {
|
|
39218
|
+
if (!(event instanceof MouseEvent)) return false;
|
|
39219
|
+
if (!formulaRangePickRef.current) return false;
|
|
39220
|
+
formulaRangePickRef.current = null;
|
|
39221
|
+
syncFormulaRangeHighlight(null);
|
|
39222
|
+
event.preventDefault();
|
|
39223
|
+
event.stopPropagation();
|
|
39224
|
+
return true;
|
|
39225
|
+
},
|
|
38916
39226
|
keydown: (_view, event) => {
|
|
38917
39227
|
if (!(event instanceof KeyboardEvent)) return false;
|
|
38918
39228
|
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
@@ -39078,7 +39388,10 @@ var UEditor = React83.forwardRef(({
|
|
|
39078
39388
|
/* @__PURE__ */ jsxs79(
|
|
39079
39389
|
"div",
|
|
39080
39390
|
{
|
|
39081
|
-
ref:
|
|
39391
|
+
ref: (node) => {
|
|
39392
|
+
editorContentRef.current = node;
|
|
39393
|
+
formulaRangeSurfaceRef.current = node;
|
|
39394
|
+
},
|
|
39082
39395
|
className: "relative flex-1 overflow-y-auto",
|
|
39083
39396
|
style: {
|
|
39084
39397
|
minHeight: editable ? minHeight : void 0,
|
|
@@ -39110,6 +39423,20 @@ var UEditor = React83.forwardRef(({
|
|
|
39110
39423
|
className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10"
|
|
39111
39424
|
}
|
|
39112
39425
|
),
|
|
39426
|
+
formulaRangeHighlight && /* @__PURE__ */ jsx94(
|
|
39427
|
+
"span",
|
|
39428
|
+
{
|
|
39429
|
+
"aria-hidden": "true",
|
|
39430
|
+
"data-ueditor-formula-range-highlight": "",
|
|
39431
|
+
className: "pointer-events-none absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10",
|
|
39432
|
+
style: {
|
|
39433
|
+
left: formulaRangeHighlight.left,
|
|
39434
|
+
top: formulaRangeHighlight.top,
|
|
39435
|
+
width: formulaRangeHighlight.width,
|
|
39436
|
+
height: formulaRangeHighlight.height
|
|
39437
|
+
}
|
|
39438
|
+
}
|
|
39439
|
+
),
|
|
39113
39440
|
editable && /* @__PURE__ */ jsx94(TableControls, { editor, containerRef: editorContentRef }),
|
|
39114
39441
|
/* @__PURE__ */ jsx94(
|
|
39115
39442
|
EditorContent,
|