@underverse-ui/underverse 1.0.184 → 1.0.185
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 +684 -196
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +678 -190
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/index.cjs
CHANGED
|
@@ -1086,6 +1086,11 @@ var en_default = {
|
|
|
1086
1086
|
borderColor: "Border Color",
|
|
1087
1087
|
clearBorder: "Clear Border",
|
|
1088
1088
|
formula: "Formula",
|
|
1089
|
+
formulaBar: "Formula bar",
|
|
1090
|
+
formulaError: "Formula error",
|
|
1091
|
+
editFormula: "Edit formula",
|
|
1092
|
+
clearCell: "Clear cell",
|
|
1093
|
+
convertToValue: "Convert to value",
|
|
1089
1094
|
numberFormat: "Number Format",
|
|
1090
1095
|
formatText: "Text",
|
|
1091
1096
|
formatDate: "Date",
|
|
@@ -1508,6 +1513,11 @@ var vi_default = {
|
|
|
1508
1513
|
borderColor: "M\xE0u vi\u1EC1n",
|
|
1509
1514
|
clearBorder: "X\xF3a vi\u1EC1n",
|
|
1510
1515
|
formula: "C\xF4ng th\u1EE9c",
|
|
1516
|
+
formulaBar: "Thanh c\xF4ng th\u1EE9c",
|
|
1517
|
+
formulaError: "L\u1ED7i c\xF4ng th\u1EE9c",
|
|
1518
|
+
editFormula: "S\u1EEDa c\xF4ng th\u1EE9c",
|
|
1519
|
+
clearCell: "X\xF3a n\u1ED9i dung \xF4",
|
|
1520
|
+
convertToValue: "Chuy\u1EC3n th\xE0nh gi\xE1 tr\u1ECB",
|
|
1511
1521
|
numberFormat: "\u0110\u1ECBnh d\u1EA1ng s\u1ED1",
|
|
1512
1522
|
formatText: "Ch\u1EEF",
|
|
1513
1523
|
formatDate: "Ng\xE0y",
|
|
@@ -1930,6 +1940,11 @@ var ko_default = {
|
|
|
1930
1940
|
borderColor: "\uD14C\uB450\uB9AC \uC0C9\uC0C1",
|
|
1931
1941
|
clearBorder: "\uD14C\uB450\uB9AC \uC9C0\uC6B0\uAE30",
|
|
1932
1942
|
formula: "\uC218\uC2DD",
|
|
1943
|
+
formulaBar: "\uC218\uC2DD \uC785\uB825\uC904",
|
|
1944
|
+
formulaError: "\uC218\uC2DD \uC624\uB958",
|
|
1945
|
+
editFormula: "\uC218\uC2DD \uD3B8\uC9D1",
|
|
1946
|
+
clearCell: "\uC140 \uB0B4\uC6A9 \uC0AD\uC81C",
|
|
1947
|
+
convertToValue: "\uAC12\uC73C\uB85C \uBCC0\uD658",
|
|
1933
1948
|
numberFormat: "\uD45C\uC2DC \uD615\uC2DD",
|
|
1934
1949
|
formatText: "\uD14D\uC2A4\uD2B8",
|
|
1935
1950
|
formatDate: "\uB0A0\uC9DC",
|
|
@@ -2352,6 +2367,11 @@ var ja_default = {
|
|
|
2352
2367
|
borderColor: "\u67A0\u7DDA\u306E\u8272",
|
|
2353
2368
|
clearBorder: "\u67A0\u7DDA\u3092\u30AF\u30EA\u30A2",
|
|
2354
2369
|
formula: "\u6570\u5F0F",
|
|
2370
|
+
formulaBar: "\u6570\u5F0F\u30D0\u30FC",
|
|
2371
|
+
formulaError: "\u6570\u5F0F\u30A8\u30E9\u30FC",
|
|
2372
|
+
editFormula: "\u6570\u5F0F\u3092\u7DE8\u96C6",
|
|
2373
|
+
clearCell: "\u30BB\u30EB\u3092\u30AF\u30EA\u30A2",
|
|
2374
|
+
convertToValue: "\u5024\u306B\u5909\u63DB",
|
|
2355
2375
|
numberFormat: "\u8868\u793A\u5F62\u5F0F",
|
|
2356
2376
|
formatText: "\u30C6\u30AD\u30B9\u30C8",
|
|
2357
2377
|
formatDate: "\u65E5\u4ED8",
|
|
@@ -27548,8 +27568,8 @@ function useLocale2() {
|
|
|
27548
27568
|
}
|
|
27549
27569
|
|
|
27550
27570
|
// src/components/UEditor/UEditor.tsx
|
|
27551
|
-
var
|
|
27552
|
-
var
|
|
27571
|
+
var import_react82 = __toESM(require("react"), 1);
|
|
27572
|
+
var import_react83 = require("@tiptap/react");
|
|
27553
27573
|
|
|
27554
27574
|
// src/components/UEditor/extensions.ts
|
|
27555
27575
|
var import_core16 = require("@tiptap/core");
|
|
@@ -27711,6 +27731,54 @@ var import_react49 = require("@tiptap/react");
|
|
|
27711
27731
|
var import_react47 = __toESM(require("react"), 1);
|
|
27712
27732
|
var import_react48 = require("@tiptap/react");
|
|
27713
27733
|
var import_lucide_react43 = require("lucide-react");
|
|
27734
|
+
|
|
27735
|
+
// src/components/UEditor/url-safety.ts
|
|
27736
|
+
var LINK_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]);
|
|
27737
|
+
var IMAGE_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
27738
|
+
var FILE_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "blob:"]);
|
|
27739
|
+
function normalizeUrlInput(raw) {
|
|
27740
|
+
return raw.trim().replace(/[\u0000-\u001F\u007F\s]+/g, "");
|
|
27741
|
+
}
|
|
27742
|
+
function isProtocolRelativeUrl(value) {
|
|
27743
|
+
return value.startsWith("//");
|
|
27744
|
+
}
|
|
27745
|
+
function isRelativeUrl(value) {
|
|
27746
|
+
return value.startsWith("/") || value.startsWith("./") || value.startsWith("../") || value.startsWith("#");
|
|
27747
|
+
}
|
|
27748
|
+
function isDataImageUrl(value) {
|
|
27749
|
+
return /^data:image\/(?:png|jpe?g|gif|webp|svg\+xml|bmp|x-icon|avif);base64,/i.test(value);
|
|
27750
|
+
}
|
|
27751
|
+
function isDataFileUrl(value) {
|
|
27752
|
+
return /^data:[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*(?:;[a-z0-9!#$&^_.+-]+=[^;,]*)*;base64,[a-z0-9+/]*={0,2}$/i.test(value);
|
|
27753
|
+
}
|
|
27754
|
+
function isSafeUEditorUrl(raw, kind) {
|
|
27755
|
+
const value = normalizeUrlInput(raw);
|
|
27756
|
+
if (!value) return false;
|
|
27757
|
+
if (kind === "image" && isDataImageUrl(value)) return true;
|
|
27758
|
+
if (kind === "file" && isDataFileUrl(value)) return true;
|
|
27759
|
+
if (isProtocolRelativeUrl(value)) return false;
|
|
27760
|
+
if (isRelativeUrl(value)) return true;
|
|
27761
|
+
try {
|
|
27762
|
+
const parsed = new URL(value);
|
|
27763
|
+
if (kind === "image") return IMAGE_PROTOCOLS.has(parsed.protocol);
|
|
27764
|
+
if (kind === "file") return FILE_PROTOCOLS.has(parsed.protocol);
|
|
27765
|
+
return LINK_PROTOCOLS.has(parsed.protocol);
|
|
27766
|
+
} catch {
|
|
27767
|
+
return false;
|
|
27768
|
+
}
|
|
27769
|
+
}
|
|
27770
|
+
function sanitizeUEditorUrl(raw, kind) {
|
|
27771
|
+
const value = raw.trim();
|
|
27772
|
+
if (!value) return "";
|
|
27773
|
+
if (isSafeUEditorUrl(value, kind)) return normalizeUrlInput(value);
|
|
27774
|
+
if (kind === "link" && !isProtocolRelativeUrl(value) && !/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(value)) {
|
|
27775
|
+
const withProtocol = `https://${value}`;
|
|
27776
|
+
return isSafeUEditorUrl(withProtocol, kind) ? withProtocol : "";
|
|
27777
|
+
}
|
|
27778
|
+
return "";
|
|
27779
|
+
}
|
|
27780
|
+
|
|
27781
|
+
// src/components/UEditor/BookmarkView.tsx
|
|
27714
27782
|
var import_jsx_runtime80 = require("react/jsx-runtime");
|
|
27715
27783
|
var BookmarkView = ({ node, updateAttributes, selected, editor }) => {
|
|
27716
27784
|
const t = useSmartTranslations("UEditor");
|
|
@@ -27718,17 +27786,25 @@ var BookmarkView = ({ node, updateAttributes, selected, editor }) => {
|
|
|
27718
27786
|
const [loading2, setLoading] = (0, import_react47.useState)(false);
|
|
27719
27787
|
const [error, setError] = (0, import_react47.useState)(false);
|
|
27720
27788
|
const [retryToken, setRetryToken] = (0, import_react47.useState)(0);
|
|
27721
|
-
const
|
|
27789
|
+
const lastFetchKeyRef = import_react47.default.useRef("");
|
|
27722
27790
|
const fetchRequestIdRef = import_react47.default.useRef(0);
|
|
27791
|
+
const safeUrl = sanitizeUEditorUrl(String(url ?? ""), "link");
|
|
27792
|
+
const safeImage = sanitizeUEditorUrl(String(image ?? ""), "image");
|
|
27793
|
+
const clickToOpenNewTabMessage = t("bookmark.clickToOpenNewTab");
|
|
27794
|
+
const clickToOpenLinkMessage = t("bookmark.clickToOpenLink");
|
|
27795
|
+
const noDescriptionMessage = t("bookmark.noDescription");
|
|
27723
27796
|
(0, import_react47.useEffect)(() => {
|
|
27724
27797
|
if (title && retryToken === 0) return;
|
|
27725
|
-
if (
|
|
27726
|
-
|
|
27798
|
+
if (!safeUrl) return;
|
|
27799
|
+
const fetchKey = `${safeUrl}\0${retryToken}`;
|
|
27800
|
+
if (lastFetchKeyRef.current === fetchKey) return;
|
|
27801
|
+
lastFetchKeyRef.current = fetchKey;
|
|
27727
27802
|
const requestId = fetchRequestIdRef.current + 1;
|
|
27728
27803
|
fetchRequestIdRef.current = requestId;
|
|
27804
|
+
let active = true;
|
|
27729
27805
|
const safeUpdateAttributes = (attrs) => {
|
|
27730
27806
|
Promise.resolve().then(() => {
|
|
27731
|
-
if (fetchRequestIdRef.current === requestId && editor && !editor.isDestroyed) {
|
|
27807
|
+
if (active && fetchRequestIdRef.current === requestId && editor && !editor.isDestroyed) {
|
|
27732
27808
|
updateAttributes(attrs);
|
|
27733
27809
|
}
|
|
27734
27810
|
});
|
|
@@ -27737,43 +27813,75 @@ var BookmarkView = ({ node, updateAttributes, selected, editor }) => {
|
|
|
27737
27813
|
const fetchMetadata = extension?.options?.fetchMetadata;
|
|
27738
27814
|
if (!fetchMetadata) {
|
|
27739
27815
|
try {
|
|
27740
|
-
const hostname = new URL(
|
|
27816
|
+
const hostname = new URL(safeUrl).hostname;
|
|
27741
27817
|
safeUpdateAttributes({
|
|
27742
|
-
title: hostname ||
|
|
27743
|
-
description:
|
|
27818
|
+
title: hostname || safeUrl,
|
|
27819
|
+
description: clickToOpenNewTabMessage,
|
|
27744
27820
|
publisher: hostname
|
|
27745
27821
|
});
|
|
27746
27822
|
} catch {
|
|
27747
27823
|
safeUpdateAttributes({
|
|
27748
|
-
title:
|
|
27749
|
-
description:
|
|
27824
|
+
title: safeUrl,
|
|
27825
|
+
description: clickToOpenLinkMessage,
|
|
27750
27826
|
publisher: ""
|
|
27751
27827
|
});
|
|
27752
27828
|
}
|
|
27753
|
-
return
|
|
27829
|
+
return () => {
|
|
27830
|
+
active = false;
|
|
27831
|
+
};
|
|
27754
27832
|
}
|
|
27755
|
-
|
|
27756
|
-
|
|
27757
|
-
|
|
27758
|
-
|
|
27833
|
+
queueMicrotask(() => {
|
|
27834
|
+
if (!active) return;
|
|
27835
|
+
setLoading(true);
|
|
27836
|
+
setError(false);
|
|
27837
|
+
});
|
|
27838
|
+
fetchMetadata(safeUrl).then((meta) => {
|
|
27839
|
+
if (!active || fetchRequestIdRef.current !== requestId) return;
|
|
27840
|
+
const hostname = (() => {
|
|
27841
|
+
try {
|
|
27842
|
+
return new URL(safeUrl).hostname;
|
|
27843
|
+
} catch {
|
|
27844
|
+
return "";
|
|
27845
|
+
}
|
|
27846
|
+
})();
|
|
27759
27847
|
safeUpdateAttributes({
|
|
27760
|
-
title: meta.title ||
|
|
27761
|
-
description: meta.description ||
|
|
27762
|
-
image: meta.image
|
|
27763
|
-
publisher: meta.publisher ||
|
|
27848
|
+
title: meta.title || hostname || safeUrl,
|
|
27849
|
+
description: meta.description || noDescriptionMessage,
|
|
27850
|
+
image: meta.image ? sanitizeUEditorUrl(meta.image, "image") : "",
|
|
27851
|
+
publisher: meta.publisher || hostname
|
|
27764
27852
|
});
|
|
27765
27853
|
setLoading(false);
|
|
27766
27854
|
}).catch(() => {
|
|
27767
|
-
if (fetchRequestIdRef.current !== requestId) return;
|
|
27855
|
+
if (!active || fetchRequestIdRef.current !== requestId) return;
|
|
27768
27856
|
setError(true);
|
|
27769
27857
|
setLoading(false);
|
|
27770
27858
|
});
|
|
27771
|
-
return
|
|
27772
|
-
|
|
27773
|
-
|
|
27774
|
-
|
|
27775
|
-
|
|
27776
|
-
|
|
27859
|
+
return () => {
|
|
27860
|
+
active = false;
|
|
27861
|
+
};
|
|
27862
|
+
}, [
|
|
27863
|
+
safeUrl,
|
|
27864
|
+
title,
|
|
27865
|
+
editor,
|
|
27866
|
+
updateAttributes,
|
|
27867
|
+
retryToken,
|
|
27868
|
+
clickToOpenNewTabMessage,
|
|
27869
|
+
clickToOpenLinkMessage,
|
|
27870
|
+
noDescriptionMessage
|
|
27871
|
+
]);
|
|
27872
|
+
const openLink = () => {
|
|
27873
|
+
if (safeUrl) window.open(safeUrl, "_blank", "noopener,noreferrer");
|
|
27874
|
+
};
|
|
27875
|
+
const handleOpenLink = (event) => {
|
|
27876
|
+
event.preventDefault();
|
|
27877
|
+
event.stopPropagation();
|
|
27878
|
+
openLink();
|
|
27879
|
+
};
|
|
27880
|
+
const handleKeyDown2 = (event) => {
|
|
27881
|
+
if (event.key !== "Enter") return;
|
|
27882
|
+
event.preventDefault();
|
|
27883
|
+
event.stopPropagation();
|
|
27884
|
+
openLink();
|
|
27777
27885
|
};
|
|
27778
27886
|
const handleRetryPreview = (event) => {
|
|
27779
27887
|
event.preventDefault();
|
|
@@ -27782,7 +27890,7 @@ var BookmarkView = ({ node, updateAttributes, selected, editor }) => {
|
|
|
27782
27890
|
};
|
|
27783
27891
|
const displayPublisher = publisher || (() => {
|
|
27784
27892
|
try {
|
|
27785
|
-
return new URL(
|
|
27893
|
+
return safeUrl ? new URL(safeUrl).hostname : "";
|
|
27786
27894
|
} catch {
|
|
27787
27895
|
return "";
|
|
27788
27896
|
}
|
|
@@ -27795,6 +27903,10 @@ var BookmarkView = ({ node, updateAttributes, selected, editor }) => {
|
|
|
27795
27903
|
selected && "ring-2 ring-primary/45 border-primary/20 shadow-sm"
|
|
27796
27904
|
),
|
|
27797
27905
|
onClick: handleOpenLink,
|
|
27906
|
+
onKeyDown: handleKeyDown2,
|
|
27907
|
+
role: "link",
|
|
27908
|
+
tabIndex: safeUrl ? 0 : -1,
|
|
27909
|
+
"aria-disabled": !safeUrl,
|
|
27798
27910
|
children: loading2 ? /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "flex items-center justify-between p-4 gap-4 animate-pulse", children: [
|
|
27799
27911
|
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "flex-1 flex flex-col gap-2", children: [
|
|
27800
27912
|
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "h-4 w-1/3 bg-muted-foreground/20 rounded" }),
|
|
@@ -27809,11 +27921,11 @@ var BookmarkView = ({ node, updateAttributes, selected, editor }) => {
|
|
|
27809
27921
|
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react43.Globe, { className: "h-3 w-3 flex-shrink-0" }),
|
|
27810
27922
|
displayPublisher
|
|
27811
27923
|
] }),
|
|
27812
|
-
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("h4", { className: "text-sm font-semibold text-foreground line-clamp-1 break-all", children: title || url }),
|
|
27924
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("h4", { className: "text-sm font-semibold text-foreground line-clamp-1 break-all", children: title || safeUrl || String(url ?? "") }),
|
|
27813
27925
|
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "text-xs text-muted-foreground line-clamp-2 leading-relaxed", children: description })
|
|
27814
27926
|
] }),
|
|
27815
27927
|
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "text-[11px] text-primary/80 font-mono mt-2 truncate flex items-center gap-1", children: [
|
|
27816
|
-
url,
|
|
27928
|
+
safeUrl || String(url ?? ""),
|
|
27817
27929
|
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_lucide_react43.ExternalLink, { className: "h-3 w-3 flex-shrink-0" })
|
|
27818
27930
|
] }),
|
|
27819
27931
|
error && /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "mt-2 flex flex-wrap items-center gap-2 text-xs text-destructive", children: [
|
|
@@ -27835,10 +27947,10 @@ var BookmarkView = ({ node, updateAttributes, selected, editor }) => {
|
|
|
27835
27947
|
)
|
|
27836
27948
|
] })
|
|
27837
27949
|
] }),
|
|
27838
|
-
|
|
27950
|
+
safeImage && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("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__ */ (0, import_jsx_runtime80.jsx)(
|
|
27839
27951
|
"img",
|
|
27840
27952
|
{
|
|
27841
|
-
src:
|
|
27953
|
+
src: safeImage,
|
|
27842
27954
|
alt: title || "Link preview image",
|
|
27843
27955
|
className: "absolute inset-0 w-full h-full object-cover transition-opacity duration-300",
|
|
27844
27956
|
onError: (e) => {
|
|
@@ -27868,11 +27980,11 @@ var Bookmark = import_core2.Node.create({
|
|
|
27868
27980
|
return {
|
|
27869
27981
|
url: {
|
|
27870
27982
|
default: "",
|
|
27871
|
-
parseHTML: (element) => element.getAttribute("href") || element.getAttribute("data-url") || "",
|
|
27872
|
-
renderHTML: (attributes) =>
|
|
27873
|
-
|
|
27874
|
-
"data-url":
|
|
27875
|
-
}
|
|
27983
|
+
parseHTML: (element) => sanitizeUEditorUrl(element.getAttribute("href") || element.getAttribute("data-url") || "", "link"),
|
|
27984
|
+
renderHTML: (attributes) => {
|
|
27985
|
+
const url = sanitizeUEditorUrl(String(attributes.url ?? ""), "link");
|
|
27986
|
+
return url ? { href: url, "data-url": url } : {};
|
|
27987
|
+
}
|
|
27876
27988
|
},
|
|
27877
27989
|
title: {
|
|
27878
27990
|
default: "",
|
|
@@ -27890,10 +28002,11 @@ var Bookmark = import_core2.Node.create({
|
|
|
27890
28002
|
},
|
|
27891
28003
|
image: {
|
|
27892
28004
|
default: "",
|
|
27893
|
-
parseHTML: (element) => element.getAttribute("data-image") || "",
|
|
27894
|
-
renderHTML: (attributes) =>
|
|
27895
|
-
|
|
27896
|
-
|
|
28005
|
+
parseHTML: (element) => sanitizeUEditorUrl(element.getAttribute("data-image") || "", "image"),
|
|
28006
|
+
renderHTML: (attributes) => {
|
|
28007
|
+
const image = sanitizeUEditorUrl(String(attributes.image ?? ""), "image");
|
|
28008
|
+
return image ? { "data-image": image } : {};
|
|
28009
|
+
}
|
|
27897
28010
|
},
|
|
27898
28011
|
publisher: {
|
|
27899
28012
|
default: "",
|
|
@@ -27926,9 +28039,12 @@ var Bookmark = import_core2.Node.create({
|
|
|
27926
28039
|
addCommands() {
|
|
27927
28040
|
return {
|
|
27928
28041
|
setBookmark: (attributes) => ({ commands }) => {
|
|
28042
|
+
const url = sanitizeUEditorUrl(attributes.url, "link");
|
|
28043
|
+
if (!url) return false;
|
|
28044
|
+
const image = attributes.image ? sanitizeUEditorUrl(attributes.image, "image") : "";
|
|
27929
28045
|
return commands.insertContent({
|
|
27930
28046
|
type: this.name,
|
|
27931
|
-
attrs: attributes
|
|
28047
|
+
attrs: { ...attributes, url, image }
|
|
27932
28048
|
});
|
|
27933
28049
|
}
|
|
27934
28050
|
};
|
|
@@ -27945,7 +28061,6 @@ var Bookmark = import_core2.Node.create({
|
|
|
27945
28061
|
if (!text || !URL_REGEX.test(text)) return false;
|
|
27946
28062
|
const { selection } = view.state;
|
|
27947
28063
|
const parent = selection.$from.parent;
|
|
27948
|
-
console.log("DEBUG handlePaste name:", parent.type.name, "size:", parent.content.size);
|
|
27949
28064
|
const isEmptyParagraph = parent.type.name === "paragraph" && parent.content.size === 0;
|
|
27950
28065
|
if (isEmptyParagraph) {
|
|
27951
28066
|
event.preventDefault();
|
|
@@ -27973,15 +28088,15 @@ var import_react51 = require("@tiptap/react");
|
|
|
27973
28088
|
var import_lucide_react44 = require("lucide-react");
|
|
27974
28089
|
var import_jsx_runtime81 = require("react/jsx-runtime");
|
|
27975
28090
|
function formatBytes(bytes, decimals = 1) {
|
|
27976
|
-
if (!bytes || bytes <= 0) return "0 Bytes";
|
|
28091
|
+
if (!Number.isFinite(bytes) || bytes <= 0) return "0 Bytes";
|
|
27977
28092
|
const k = 1024;
|
|
27978
28093
|
const dm = decimals < 0 ? 0 : decimals;
|
|
27979
|
-
const sizes = ["Bytes", "KB", "MB", "GB"];
|
|
27980
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
28094
|
+
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB"];
|
|
28095
|
+
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1);
|
|
27981
28096
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
|
|
27982
28097
|
}
|
|
27983
28098
|
function getFileIcon2(type) {
|
|
27984
|
-
const mime = (type || "").toLowerCase();
|
|
28099
|
+
const mime = String(type || "").toLowerCase();
|
|
27985
28100
|
if (mime.includes("pdf")) return import_lucide_react44.FileText;
|
|
27986
28101
|
if (mime.startsWith("image/")) return import_lucide_react44.Image;
|
|
27987
28102
|
if (mime.startsWith("audio/")) return import_lucide_react44.Music;
|
|
@@ -28007,11 +28122,13 @@ function dataURLtoFile(dataurl, filename, mimeType) {
|
|
|
28007
28122
|
}
|
|
28008
28123
|
}
|
|
28009
28124
|
return new File([bytes], filename, { type: mime });
|
|
28010
|
-
} catch
|
|
28011
|
-
console.error("Error converting data URI to file:", e);
|
|
28125
|
+
} catch {
|
|
28012
28126
|
return null;
|
|
28013
28127
|
}
|
|
28014
28128
|
}
|
|
28129
|
+
function getErrorMessage(error) {
|
|
28130
|
+
return error instanceof Error && error.message ? error.message : "Upload failed";
|
|
28131
|
+
}
|
|
28015
28132
|
var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
28016
28133
|
const t = useSmartTranslations("UEditor");
|
|
28017
28134
|
const { src, fileName, fileSize, fileType } = node.attrs;
|
|
@@ -28019,49 +28136,64 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
28019
28136
|
const [uploadError, setUploadError] = (0, import_react50.useState)(null);
|
|
28020
28137
|
const [retryToken, setRetryToken] = (0, import_react50.useState)(0);
|
|
28021
28138
|
const uploadAttemptedRef = (0, import_react50.useRef)(false);
|
|
28139
|
+
const lastUploadSrcRef = (0, import_react50.useRef)("");
|
|
28140
|
+
const uploadRequestIdRef = (0, import_react50.useRef)(0);
|
|
28141
|
+
const safeSrc = sanitizeUEditorUrl(String(src ?? ""), "file");
|
|
28142
|
+
const extension = editor?.extensionManager?.extensions?.find((item) => item.name === "fileCard");
|
|
28143
|
+
const uploadFn = extension?.options?.upload;
|
|
28022
28144
|
(0, import_react50.useEffect)(() => {
|
|
28023
|
-
if (
|
|
28145
|
+
if (lastUploadSrcRef.current !== safeSrc) {
|
|
28146
|
+
lastUploadSrcRef.current = safeSrc;
|
|
28147
|
+
uploadAttemptedRef.current = false;
|
|
28148
|
+
}
|
|
28149
|
+
if (!safeSrc || !safeSrc.startsWith("data:") || !uploadFn) {
|
|
28024
28150
|
return;
|
|
28025
28151
|
}
|
|
28026
|
-
|
|
28027
|
-
const uploadFn = extension?.options?.upload;
|
|
28028
|
-
if (!uploadFn || uploadAttemptedRef.current || !updateAttributes) {
|
|
28152
|
+
if (uploadAttemptedRef.current || !updateAttributes) {
|
|
28029
28153
|
return;
|
|
28030
28154
|
}
|
|
28031
28155
|
uploadAttemptedRef.current = true;
|
|
28032
28156
|
setUploadError(null);
|
|
28157
|
+
const requestId = uploadRequestIdRef.current + 1;
|
|
28158
|
+
uploadRequestIdRef.current = requestId;
|
|
28159
|
+
let active = true;
|
|
28033
28160
|
const runUpload = async () => {
|
|
28034
28161
|
try {
|
|
28035
|
-
const file = dataURLtoFile(
|
|
28162
|
+
const file = dataURLtoFile(safeSrc, fileName || "file", fileType);
|
|
28036
28163
|
if (!file) {
|
|
28037
28164
|
throw new Error("Failed to parse file data");
|
|
28038
28165
|
}
|
|
28039
28166
|
const resolvedUrl = await uploadFn(file);
|
|
28167
|
+
const nextSrc = sanitizeUEditorUrl(String(resolvedUrl ?? ""), "file");
|
|
28168
|
+
if (!nextSrc) throw new Error("Upload handler returned an unsafe URL");
|
|
28040
28169
|
Promise.resolve().then(() => {
|
|
28041
|
-
if (editor && !editor.isDestroyed) {
|
|
28042
|
-
updateAttributes({ src:
|
|
28170
|
+
if (active && uploadRequestIdRef.current === requestId && editor && !editor.isDestroyed) {
|
|
28171
|
+
updateAttributes({ src: nextSrc });
|
|
28043
28172
|
}
|
|
28044
28173
|
});
|
|
28045
|
-
} catch (
|
|
28046
|
-
|
|
28047
|
-
setUploadError(
|
|
28174
|
+
} catch (error) {
|
|
28175
|
+
if (!active || uploadRequestIdRef.current !== requestId) return;
|
|
28176
|
+
setUploadError(getErrorMessage(error));
|
|
28048
28177
|
uploadAttemptedRef.current = false;
|
|
28049
28178
|
}
|
|
28050
28179
|
};
|
|
28051
28180
|
void runUpload();
|
|
28052
|
-
|
|
28181
|
+
return () => {
|
|
28182
|
+
active = false;
|
|
28183
|
+
};
|
|
28184
|
+
}, [safeSrc, fileName, fileType, editor, updateAttributes, uploadFn, retryToken]);
|
|
28053
28185
|
const handleDownload = (e) => {
|
|
28054
28186
|
e.preventDefault();
|
|
28055
28187
|
e.stopPropagation();
|
|
28056
|
-
if (!
|
|
28188
|
+
if (!safeSrc) return;
|
|
28057
28189
|
const link = document.createElement("a");
|
|
28058
|
-
link.href =
|
|
28190
|
+
link.href = safeSrc;
|
|
28059
28191
|
link.download = fileName || "download";
|
|
28060
28192
|
document.body.appendChild(link);
|
|
28061
28193
|
link.click();
|
|
28062
28194
|
document.body.removeChild(link);
|
|
28063
28195
|
};
|
|
28064
|
-
const
|
|
28196
|
+
const hasInlineUpload = safeSrc.startsWith("data:") && Boolean(uploadFn);
|
|
28065
28197
|
const handleRetryUpload = (event) => {
|
|
28066
28198
|
event.preventDefault();
|
|
28067
28199
|
event.stopPropagation();
|
|
@@ -28084,11 +28216,11 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
28084
28216
|
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "text-sm font-semibold text-foreground truncate break-all", children: fileName || t("fileCard.unnamed") }),
|
|
28085
28217
|
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "text-xs text-muted-foreground flex items-center gap-2 mt-0.5", children: [
|
|
28086
28218
|
fileSize ? /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { children: formatBytes(fileSize) }) : null,
|
|
28087
|
-
|
|
28219
|
+
hasInlineUpload && /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: cn(
|
|
28088
28220
|
"font-medium truncate max-w-50",
|
|
28089
28221
|
uploadError ? "text-destructive" : "text-primary animate-pulse"
|
|
28090
28222
|
), children: uploadError ? `${t("fileCard.uploadFailed") || "T\u1EA3i l\xEAn th\u1EA5t b\u1EA1i"}: ${uploadError}` : t("fileCard.uploading") }),
|
|
28091
|
-
|
|
28223
|
+
hasInlineUpload && uploadError && /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
|
|
28092
28224
|
"button",
|
|
28093
28225
|
{
|
|
28094
28226
|
type: "button",
|
|
@@ -28103,7 +28235,7 @@ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
|
|
|
28103
28235
|
] })
|
|
28104
28236
|
] })
|
|
28105
28237
|
] }),
|
|
28106
|
-
|
|
28238
|
+
safeSrc && /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
28107
28239
|
"button",
|
|
28108
28240
|
{
|
|
28109
28241
|
type: "button",
|
|
@@ -28132,11 +28264,11 @@ var FileCard = import_core3.Node.create({
|
|
|
28132
28264
|
return {
|
|
28133
28265
|
src: {
|
|
28134
28266
|
default: "",
|
|
28135
|
-
parseHTML: (element) => element.getAttribute("href") || element.getAttribute("data-src") || "",
|
|
28136
|
-
renderHTML: (attributes) =>
|
|
28137
|
-
|
|
28138
|
-
"data-src":
|
|
28139
|
-
}
|
|
28267
|
+
parseHTML: (element) => sanitizeUEditorUrl(element.getAttribute("href") || element.getAttribute("data-src") || "", "file"),
|
|
28268
|
+
renderHTML: (attributes) => {
|
|
28269
|
+
const src = sanitizeUEditorUrl(String(attributes.src ?? ""), "file");
|
|
28270
|
+
return src ? { href: src, "data-src": src } : {};
|
|
28271
|
+
}
|
|
28140
28272
|
},
|
|
28141
28273
|
fileName: {
|
|
28142
28274
|
default: "",
|
|
@@ -28148,13 +28280,15 @@ var FileCard = import_core3.Node.create({
|
|
|
28148
28280
|
fileSize: {
|
|
28149
28281
|
default: null,
|
|
28150
28282
|
parseHTML: (element) => {
|
|
28151
|
-
const
|
|
28152
|
-
|
|
28283
|
+
const rawValue = element.getAttribute("data-file-size");
|
|
28284
|
+
const value = rawValue ? Number(rawValue) : Number.NaN;
|
|
28285
|
+
return Number.isFinite(value) && value >= 0 ? value : null;
|
|
28153
28286
|
},
|
|
28154
28287
|
renderHTML: (attributes) => {
|
|
28155
|
-
|
|
28288
|
+
const fileSize = Number(attributes.fileSize);
|
|
28289
|
+
if (!Number.isFinite(fileSize) || fileSize < 0) return {};
|
|
28156
28290
|
return {
|
|
28157
|
-
"data-file-size":
|
|
28291
|
+
"data-file-size": fileSize
|
|
28158
28292
|
};
|
|
28159
28293
|
}
|
|
28160
28294
|
},
|
|
@@ -28189,9 +28323,16 @@ var FileCard = import_core3.Node.create({
|
|
|
28189
28323
|
addCommands() {
|
|
28190
28324
|
return {
|
|
28191
28325
|
setFileCard: (attributes) => ({ commands }) => {
|
|
28326
|
+
const src = sanitizeUEditorUrl(attributes.src, "file");
|
|
28327
|
+
if (!src) return false;
|
|
28328
|
+
const fileSize = Number(attributes.fileSize);
|
|
28192
28329
|
return commands.insertContent({
|
|
28193
28330
|
type: this.name,
|
|
28194
|
-
attrs:
|
|
28331
|
+
attrs: {
|
|
28332
|
+
...attributes,
|
|
28333
|
+
src,
|
|
28334
|
+
fileSize: Number.isFinite(fileSize) && fileSize >= 0 ? fileSize : null
|
|
28335
|
+
}
|
|
28195
28336
|
});
|
|
28196
28337
|
}
|
|
28197
28338
|
};
|
|
@@ -28605,6 +28746,10 @@ function destroyTippyInstance(instance) {
|
|
|
28605
28746
|
if (!instance || instance.state.isDestroyed) return;
|
|
28606
28747
|
instance.destroy();
|
|
28607
28748
|
}
|
|
28749
|
+
function setTippyReferenceClientRect(instance, clientRect) {
|
|
28750
|
+
if (!instance || instance.state.isDestroyed) return;
|
|
28751
|
+
instance.setProps({ getReferenceClientRect: clientRect });
|
|
28752
|
+
}
|
|
28608
28753
|
|
|
28609
28754
|
// src/components/UEditor/slash-command.tsx
|
|
28610
28755
|
var import_jsx_runtime84 = require("react/jsx-runtime");
|
|
@@ -28977,9 +29122,7 @@ var SlashCommand = import_core6.Extension.create({
|
|
|
28977
29122
|
if (!props.clientRect) {
|
|
28978
29123
|
return;
|
|
28979
29124
|
}
|
|
28980
|
-
popup
|
|
28981
|
-
getReferenceClientRect: props.clientRect
|
|
28982
|
-
});
|
|
29125
|
+
setTippyReferenceClientRect(getFirstTippyInstance(popup), props.clientRect);
|
|
28983
29126
|
},
|
|
28984
29127
|
onKeyDown(props) {
|
|
28985
29128
|
if (!props || !props.event) return false;
|
|
@@ -29716,45 +29859,6 @@ function getClipboardTsvTableContent(dataTransfer) {
|
|
|
29716
29859
|
);
|
|
29717
29860
|
}
|
|
29718
29861
|
|
|
29719
|
-
// src/components/UEditor/url-safety.ts
|
|
29720
|
-
var LINK_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]);
|
|
29721
|
-
var IMAGE_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
29722
|
-
function normalizeUrlInput(raw) {
|
|
29723
|
-
return raw.trim().replace(/[\u0000-\u001F\u007F\s]+/g, "");
|
|
29724
|
-
}
|
|
29725
|
-
function isProtocolRelativeUrl(value) {
|
|
29726
|
-
return value.startsWith("//");
|
|
29727
|
-
}
|
|
29728
|
-
function isRelativeUrl(value) {
|
|
29729
|
-
return value.startsWith("/") || value.startsWith("./") || value.startsWith("../") || value.startsWith("#");
|
|
29730
|
-
}
|
|
29731
|
-
function isDataImageUrl(value) {
|
|
29732
|
-
return /^data:image\/(?:png|jpe?g|gif|webp|svg\+xml|bmp|x-icon|avif);base64,/i.test(value);
|
|
29733
|
-
}
|
|
29734
|
-
function isSafeUEditorUrl(raw, kind) {
|
|
29735
|
-
const value = normalizeUrlInput(raw);
|
|
29736
|
-
if (!value) return false;
|
|
29737
|
-
if (kind === "image" && isDataImageUrl(value)) return true;
|
|
29738
|
-
if (isRelativeUrl(value)) return true;
|
|
29739
|
-
if (isProtocolRelativeUrl(value)) return false;
|
|
29740
|
-
try {
|
|
29741
|
-
const parsed = new URL(value);
|
|
29742
|
-
return kind === "image" ? IMAGE_PROTOCOLS.has(parsed.protocol) : LINK_PROTOCOLS.has(parsed.protocol);
|
|
29743
|
-
} catch {
|
|
29744
|
-
return false;
|
|
29745
|
-
}
|
|
29746
|
-
}
|
|
29747
|
-
function sanitizeUEditorUrl(raw, kind) {
|
|
29748
|
-
const value = raw.trim();
|
|
29749
|
-
if (!value) return "";
|
|
29750
|
-
if (isSafeUEditorUrl(value, kind)) return normalizeUrlInput(value);
|
|
29751
|
-
if (kind === "link" && !isProtocolRelativeUrl(value) && !/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(value)) {
|
|
29752
|
-
const withProtocol = `https://${value}`;
|
|
29753
|
-
return isSafeUEditorUrl(withProtocol, kind) ? withProtocol : "";
|
|
29754
|
-
}
|
|
29755
|
-
return "";
|
|
29756
|
-
}
|
|
29757
|
-
|
|
29758
29862
|
// src/components/UEditor/clipboard-images.ts
|
|
29759
29863
|
var DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
29760
29864
|
var DEFAULT_UEDITOR_IMAGE_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif", "image/svg+xml"];
|
|
@@ -29996,9 +30100,7 @@ var EmojiSuggestion = import_core8.Extension.create({
|
|
|
29996
30100
|
if (!props.clientRect) {
|
|
29997
30101
|
return;
|
|
29998
30102
|
}
|
|
29999
|
-
popup
|
|
30000
|
-
getReferenceClientRect: props.clientRect
|
|
30001
|
-
});
|
|
30103
|
+
setTippyReferenceClientRect(getFirstTippyInstance(popup), props.clientRect);
|
|
30002
30104
|
},
|
|
30003
30105
|
onKeyDown(props) {
|
|
30004
30106
|
if (!props || !props.event) return false;
|
|
@@ -30095,7 +30197,7 @@ var FormulaSuggestionList = (0, import_react62.forwardRef)((props, ref) => {
|
|
|
30095
30197
|
setSelectedIndex((prev) => (prev + 1) % props.items.length);
|
|
30096
30198
|
return true;
|
|
30097
30199
|
}
|
|
30098
|
-
if (event.key === "
|
|
30200
|
+
if (event.key === "Tab") {
|
|
30099
30201
|
const item = props.items[selectedIndex];
|
|
30100
30202
|
if (item) {
|
|
30101
30203
|
props.command(item);
|
|
@@ -30185,9 +30287,7 @@ var FormulaSuggestion = import_core9.Extension.create({
|
|
|
30185
30287
|
if (!props.clientRect) {
|
|
30186
30288
|
return;
|
|
30187
30289
|
}
|
|
30188
|
-
popup
|
|
30189
|
-
getReferenceClientRect: props.clientRect
|
|
30190
|
-
});
|
|
30290
|
+
setTippyReferenceClientRect(getFirstTippyInstance(popup), props.clientRect);
|
|
30191
30291
|
},
|
|
30192
30292
|
onKeyDown(props) {
|
|
30193
30293
|
const popupInstance = getFirstTippyInstance(popup);
|
|
@@ -31929,7 +32029,6 @@ function buildUEditorExtensions({
|
|
|
31929
32029
|
import_extension_gapcursor.default,
|
|
31930
32030
|
import_extension_link.default.configure({
|
|
31931
32031
|
openOnClick: false,
|
|
31932
|
-
protocols: ["http", "https", "mailto", "tel"],
|
|
31933
32032
|
isAllowedUri: (url) => isSafeUEditorUrl(url ?? "", "link"),
|
|
31934
32033
|
HTMLAttributes: {
|
|
31935
32034
|
class: "text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer"
|
|
@@ -32981,7 +33080,7 @@ var EditorToolbar = ({
|
|
|
32981
33080
|
const [showImageInput, setShowImageInput] = (0, import_react70.useState)(false);
|
|
32982
33081
|
const [showLinkInput, setShowLinkInput] = (0, import_react70.useState)(false);
|
|
32983
33082
|
const [isTableMenuOpen, setIsTableMenuOpen] = (0, import_react70.useState)(false);
|
|
32984
|
-
const
|
|
33083
|
+
const [preservedTableAnchorPos, setPreservedTableAnchorPos] = (0, import_react70.useState)(null);
|
|
32985
33084
|
const fileInputRef = (0, import_react70.useRef)(null);
|
|
32986
33085
|
const [isUploadingImage, setIsUploadingImage] = (0, import_react70.useState)(false);
|
|
32987
33086
|
const [imageUploadError, setImageUploadError] = (0, import_react70.useState)(null);
|
|
@@ -32996,7 +33095,7 @@ var EditorToolbar = ({
|
|
|
32996
33095
|
const tableAlignAttr = tableAttrs.tableAlign ?? tableAttrs.textAlign;
|
|
32997
33096
|
const currentTableAlign = tableAlignAttr === "center" || tableAlignAttr === "right" ? tableAlignAttr : "left";
|
|
32998
33097
|
const isTableSelected = tableInfo !== null;
|
|
32999
|
-
const hasTableContext = isTableSelected ||
|
|
33098
|
+
const hasTableContext = isTableSelected || preservedTableAnchorPos !== null;
|
|
33000
33099
|
const canMergeCells = hasTableContext && editor.can().mergeCells();
|
|
33001
33100
|
const canSplitCell = hasTableContext && editor.can().splitCell();
|
|
33002
33101
|
const currentCellVerticalAlign = normalizeStyleValue(editor.getAttributes("tableCell").verticalAlign || editor.getAttributes("tableHeader").verticalAlign) || "";
|
|
@@ -33021,7 +33120,7 @@ var EditorToolbar = ({
|
|
|
33021
33120
|
const displayedFontFamilyValue = currentFontFamily || defaultFontFamilyValue;
|
|
33022
33121
|
const displayedFontSizeLabel = currentFontSize ? currentFontSizeLabel : "13";
|
|
33023
33122
|
const activeFontSize = currentFontSize || "13px";
|
|
33024
|
-
const tableCommandAnchorPos =
|
|
33123
|
+
const tableCommandAnchorPos = preservedTableAnchorPos ?? tableAnchorPos ?? void 0;
|
|
33025
33124
|
const isMedium = variant === "medium";
|
|
33026
33125
|
const isMediumFull = variant === "medium-full";
|
|
33027
33126
|
const isFull = variant === "default" || variant === "full" || variant === "notion" || !variant;
|
|
@@ -33697,7 +33796,7 @@ var EditorToolbar = ({
|
|
|
33697
33796
|
isOpen: isTableMenuOpen,
|
|
33698
33797
|
onOpenChange: (open) => {
|
|
33699
33798
|
setIsTableMenuOpen(open);
|
|
33700
|
-
|
|
33799
|
+
setPreservedTableAnchorPos(open ? getTableAnchorPos(editor) : null);
|
|
33701
33800
|
},
|
|
33702
33801
|
trigger: /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(ToolbarButton, { onClick: () => {
|
|
33703
33802
|
}, title: t("toolbar.table"), children: [
|
|
@@ -33714,6 +33813,7 @@ var EditorToolbar = ({
|
|
|
33714
33813
|
onInsert: (rows, cols) => {
|
|
33715
33814
|
editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();
|
|
33716
33815
|
setIsTableMenuOpen(false);
|
|
33816
|
+
setPreservedTableAnchorPos(null);
|
|
33717
33817
|
}
|
|
33718
33818
|
}
|
|
33719
33819
|
),
|
|
@@ -33904,6 +34004,7 @@ var import_react_dom8 = require("react-dom");
|
|
|
33904
34004
|
var import_lucide_react54 = require("lucide-react");
|
|
33905
34005
|
|
|
33906
34006
|
// src/components/UEditor/table-formula-commands.ts
|
|
34007
|
+
var import_state10 = require("@tiptap/pm/state");
|
|
33907
34008
|
var import_tables5 = require("@tiptap/pm/tables");
|
|
33908
34009
|
|
|
33909
34010
|
// src/components/UEditor/table-formula.ts
|
|
@@ -34467,6 +34568,75 @@ function getSelectionTableCellNode(editor) {
|
|
|
34467
34568
|
}
|
|
34468
34569
|
return null;
|
|
34469
34570
|
}
|
|
34571
|
+
function getSelectionTableCellPos(editor) {
|
|
34572
|
+
const cellSelection = editor.state.selection;
|
|
34573
|
+
const anchorCellPos = cellSelection.$anchorCell?.pos;
|
|
34574
|
+
if (typeof anchorCellPos === "number") {
|
|
34575
|
+
const node = editor.state.doc.nodeAt(anchorCellPos);
|
|
34576
|
+
if (node?.type.name === "tableCell" || node?.type.name === "tableHeader") {
|
|
34577
|
+
return anchorCellPos;
|
|
34578
|
+
}
|
|
34579
|
+
}
|
|
34580
|
+
const { $from } = editor.state.selection;
|
|
34581
|
+
for (let depth = $from.depth; depth > 0; depth -= 1) {
|
|
34582
|
+
const node = $from.node(depth);
|
|
34583
|
+
if (node.type.name === "tableCell" || node.type.name === "tableHeader") {
|
|
34584
|
+
return $from.before(depth);
|
|
34585
|
+
}
|
|
34586
|
+
}
|
|
34587
|
+
return null;
|
|
34588
|
+
}
|
|
34589
|
+
function getSelectionTableCellAnchor(editor) {
|
|
34590
|
+
const cellPos = getSelectionTableCellPos(editor);
|
|
34591
|
+
if (cellPos == null) return null;
|
|
34592
|
+
const node = editor.state.doc.nodeAt(cellPos);
|
|
34593
|
+
if (!node || node.type.name !== "tableCell" && node.type.name !== "tableHeader") return null;
|
|
34594
|
+
const $cell = editor.state.doc.resolve(Math.min(cellPos + 1, editor.state.doc.content.size));
|
|
34595
|
+
for (let depth = $cell.depth; depth > 0; depth -= 1) {
|
|
34596
|
+
const tableNode = $cell.node(depth);
|
|
34597
|
+
if (tableNode.type.name !== "table") continue;
|
|
34598
|
+
const tableStart = $cell.start(depth);
|
|
34599
|
+
const rect = safeFindCell2(import_tables5.TableMap.get(tableNode), cellPos - tableStart);
|
|
34600
|
+
if (!rect) return null;
|
|
34601
|
+
return {
|
|
34602
|
+
cellPos,
|
|
34603
|
+
column: rect.left,
|
|
34604
|
+
label: `${indexToColumnName(rect.left)}${rect.top + 1}`,
|
|
34605
|
+
node,
|
|
34606
|
+
row: rect.top,
|
|
34607
|
+
tablePos: tableStart - 1
|
|
34608
|
+
};
|
|
34609
|
+
}
|
|
34610
|
+
return null;
|
|
34611
|
+
}
|
|
34612
|
+
function restoreSelectionAtTableCell(editor, anchor) {
|
|
34613
|
+
const tableNode = editor.state.doc.nodeAt(anchor.tablePos);
|
|
34614
|
+
if (!tableNode || tableNode.type.name !== "table") return false;
|
|
34615
|
+
const map = import_tables5.TableMap.get(tableNode);
|
|
34616
|
+
if (anchor.row >= map.height || anchor.column >= map.width) return false;
|
|
34617
|
+
const relativeCellPos = map.positionAt(anchor.row, anchor.column, tableNode);
|
|
34618
|
+
const cellPos = anchor.tablePos + 1 + relativeCellPos;
|
|
34619
|
+
const cellNode = editor.state.doc.nodeAt(cellPos);
|
|
34620
|
+
if (!cellNode || cellNode.type.name !== "tableCell" && cellNode.type.name !== "tableHeader") return false;
|
|
34621
|
+
const selectionPos = Math.min(cellPos + 2, editor.state.doc.content.size);
|
|
34622
|
+
editor.view.dispatch(
|
|
34623
|
+
editor.state.tr.setSelection(import_state10.TextSelection.near(editor.state.doc.resolve(selectionPos))).setMeta("addToHistory", false)
|
|
34624
|
+
);
|
|
34625
|
+
return true;
|
|
34626
|
+
}
|
|
34627
|
+
function getSelectedTableFormulaCell(editor) {
|
|
34628
|
+
const selectedCell = getSelectionTableCellAnchor(editor);
|
|
34629
|
+
if (!selectedCell) return null;
|
|
34630
|
+
const formula = typeof selectedCell.node.attrs.formula === "string" ? selectedCell.node.attrs.formula.trim() : "";
|
|
34631
|
+
if (!formula) return null;
|
|
34632
|
+
const computedValue = typeof selectedCell.node.attrs.computedValue === "string" ? selectedCell.node.attrs.computedValue : "";
|
|
34633
|
+
return {
|
|
34634
|
+
...selectedCell,
|
|
34635
|
+
computedValue,
|
|
34636
|
+
formula,
|
|
34637
|
+
formulaState: computedValue.startsWith("#") ? "error" : "computed"
|
|
34638
|
+
};
|
|
34639
|
+
}
|
|
34470
34640
|
function getSelectionTableInfo(editor) {
|
|
34471
34641
|
const { $from } = editor.state.selection;
|
|
34472
34642
|
for (let depth = $from.depth; depth > 0; depth -= 1) {
|
|
@@ -34513,6 +34683,28 @@ function createCellDisplayContent(cellNode, displayValue) {
|
|
|
34513
34683
|
}
|
|
34514
34684
|
return [paragraphType.create(null, cellNode.type.schema.text(displayValue))];
|
|
34515
34685
|
}
|
|
34686
|
+
function removeSelectedTableCellFormula(editor, clearContent) {
|
|
34687
|
+
const selectedCell = getSelectedTableFormulaCell(editor);
|
|
34688
|
+
if (!selectedCell) return false;
|
|
34689
|
+
const nextCell2 = selectedCell.node.type.create(
|
|
34690
|
+
{
|
|
34691
|
+
...selectedCell.node.attrs,
|
|
34692
|
+
formula: null,
|
|
34693
|
+
computedValue: null
|
|
34694
|
+
},
|
|
34695
|
+
clearContent ? createCellDisplayContent(selectedCell.node, "") : selectedCell.node.content,
|
|
34696
|
+
selectedCell.node.marks
|
|
34697
|
+
);
|
|
34698
|
+
let transaction = editor.state.tr.replaceWith(selectedCell.cellPos, selectedCell.cellPos + selectedCell.node.nodeSize, nextCell2).setMeta(UEDITOR_TABLE_FORMULA_RECALCULATE_META, true);
|
|
34699
|
+
const selectionPos = Math.min(selectedCell.cellPos + 2, transaction.doc.content.size);
|
|
34700
|
+
transaction = transaction.setSelection(import_state10.TextSelection.near(transaction.doc.resolve(selectionPos)));
|
|
34701
|
+
editor.view.dispatch(transaction);
|
|
34702
|
+
recalculateActiveTableFormulas(editor);
|
|
34703
|
+
restoreSelectionAtTableCell(editor, selectedCell);
|
|
34704
|
+
editor.view.focus();
|
|
34705
|
+
dispatchTableLayoutChange(editor);
|
|
34706
|
+
return true;
|
|
34707
|
+
}
|
|
34516
34708
|
function buildTableValueMap(tableNode) {
|
|
34517
34709
|
const map = import_tables5.TableMap.get(tableNode);
|
|
34518
34710
|
const values = /* @__PURE__ */ new Map();
|
|
@@ -34535,21 +34727,15 @@ function normalizeFormulaInput(formula) {
|
|
|
34535
34727
|
function setSelectedTableCellFormula(editor, formula) {
|
|
34536
34728
|
const normalized = normalizeFormulaInput(formula);
|
|
34537
34729
|
const { state, view } = editor;
|
|
34730
|
+
const selectionAnchor = getSelectionTableCellAnchor(editor);
|
|
34538
34731
|
if (!normalized) {
|
|
34539
|
-
|
|
34540
|
-
const clearedValue2 = (0, import_tables5.setCellAttr)("computedValue", null)(editor.state, view.dispatch.bind(view));
|
|
34541
|
-
if (clearedFormula || clearedValue2) {
|
|
34542
|
-
recalculateActiveTableFormulas(editor);
|
|
34543
|
-
view.focus();
|
|
34544
|
-
dispatchTableLayoutChange(editor);
|
|
34545
|
-
return true;
|
|
34546
|
-
}
|
|
34547
|
-
return false;
|
|
34732
|
+
return clearSelectedTableCellFormula(editor);
|
|
34548
34733
|
}
|
|
34549
34734
|
const appliedFormula = (0, import_tables5.setCellAttr)("formula", normalized)(state, view.dispatch.bind(view));
|
|
34550
34735
|
const clearedValue = (0, import_tables5.setCellAttr)("computedValue", null)(editor.state, view.dispatch.bind(view));
|
|
34551
34736
|
if (appliedFormula || clearedValue) {
|
|
34552
34737
|
recalculateActiveTableFormulas(editor);
|
|
34738
|
+
if (selectionAnchor) restoreSelectionAtTableCell(editor, selectionAnchor);
|
|
34553
34739
|
view.focus();
|
|
34554
34740
|
dispatchTableLayoutChange(editor);
|
|
34555
34741
|
return true;
|
|
@@ -34557,7 +34743,10 @@ function setSelectedTableCellFormula(editor, formula) {
|
|
|
34557
34743
|
return false;
|
|
34558
34744
|
}
|
|
34559
34745
|
function clearSelectedTableCellFormula(editor) {
|
|
34560
|
-
return
|
|
34746
|
+
return removeSelectedTableCellFormula(editor, true);
|
|
34747
|
+
}
|
|
34748
|
+
function convertSelectedTableCellFormulaToValue(editor) {
|
|
34749
|
+
return removeSelectedTableCellFormula(editor, false);
|
|
34561
34750
|
}
|
|
34562
34751
|
function setSelectedTableCellNumberFormat(editor, numberFormat) {
|
|
34563
34752
|
const value = numberFormat && numberFormat !== "text" ? numberFormat : null;
|
|
@@ -34757,6 +34946,58 @@ function recalculateAllTableFormulas(editor) {
|
|
|
34757
34946
|
|
|
34758
34947
|
// src/components/UEditor/menus.tsx
|
|
34759
34948
|
var import_jsx_runtime92 = require("react/jsx-runtime");
|
|
34949
|
+
var FloatingSlashCommandMenu = ({ editor, onClose }) => {
|
|
34950
|
+
const t = useSmartTranslations("UEditor");
|
|
34951
|
+
const messages = (0, import_react72.useMemo)(() => buildSlashCommandMessages(t), [t]);
|
|
34952
|
+
const items = (0, import_react72.useMemo)(() => buildSlashCommandItems({ query: "", messages }), [messages]);
|
|
34953
|
+
const listRef = (0, import_react72.useRef)(null);
|
|
34954
|
+
(0, import_react72.useEffect)(() => {
|
|
34955
|
+
const handleKeyDown2 = (event) => {
|
|
34956
|
+
if (event.key === "Escape") {
|
|
34957
|
+
event.preventDefault();
|
|
34958
|
+
onClose();
|
|
34959
|
+
return;
|
|
34960
|
+
}
|
|
34961
|
+
const handled = listRef.current?.onKeyDown({ event }) ?? false;
|
|
34962
|
+
if (handled) {
|
|
34963
|
+
event.preventDefault();
|
|
34964
|
+
}
|
|
34965
|
+
};
|
|
34966
|
+
document.addEventListener("keydown", handleKeyDown2);
|
|
34967
|
+
return () => document.removeEventListener("keydown", handleKeyDown2);
|
|
34968
|
+
}, [onClose]);
|
|
34969
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(
|
|
34970
|
+
SlashCommandList,
|
|
34971
|
+
{
|
|
34972
|
+
ref: listRef,
|
|
34973
|
+
items,
|
|
34974
|
+
messages,
|
|
34975
|
+
command: (item) => {
|
|
34976
|
+
item.command({ editor });
|
|
34977
|
+
onClose();
|
|
34978
|
+
}
|
|
34979
|
+
}
|
|
34980
|
+
);
|
|
34981
|
+
};
|
|
34982
|
+
var FloatingMenuContent = ({ editor }) => {
|
|
34983
|
+
const t = useSmartTranslations("UEditor");
|
|
34984
|
+
const [showCommands, setShowCommands] = (0, import_react72.useState)(false);
|
|
34985
|
+
if (showCommands) {
|
|
34986
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(FloatingSlashCommandMenu, { editor, onClose: () => setShowCommands(false) });
|
|
34987
|
+
}
|
|
34988
|
+
return /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(
|
|
34989
|
+
"button",
|
|
34990
|
+
{
|
|
34991
|
+
type: "button",
|
|
34992
|
+
onClick: () => setShowCommands(true),
|
|
34993
|
+
className: "flex items-center gap-1 px-2 py-1.5 rounded-lg hover:bg-accent transition-all group",
|
|
34994
|
+
children: [
|
|
34995
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)(import_lucide_react54.Plus, { className: "w-4 h-4 text-muted-foreground group-hover:text-foreground" }),
|
|
34996
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "text-sm text-muted-foreground group-hover:text-foreground", children: t("floatingMenu.addBlock") })
|
|
34997
|
+
]
|
|
34998
|
+
}
|
|
34999
|
+
);
|
|
35000
|
+
};
|
|
34760
35001
|
function applyTableCellBackground(editor, color) {
|
|
34761
35002
|
const value = color || null;
|
|
34762
35003
|
const { state, view } = editor;
|
|
@@ -35495,7 +35736,8 @@ var LinkPreviewContent = ({ editor, onEdit }) => {
|
|
|
35495
35736
|
const url = editor.getAttributes("link").href || "";
|
|
35496
35737
|
const t = useSmartTranslations("UEditor");
|
|
35497
35738
|
const handleOpen = () => {
|
|
35498
|
-
|
|
35739
|
+
const safeUrl = sanitizeUEditorUrl(url, "link");
|
|
35740
|
+
if (safeUrl) window.open(safeUrl, "_blank", "noopener,noreferrer");
|
|
35499
35741
|
};
|
|
35500
35742
|
const handleUnlink = () => {
|
|
35501
35743
|
editor.chain().focus().unsetLink().run();
|
|
@@ -35525,16 +35767,19 @@ var CustomBubbleMenu = ({
|
|
|
35525
35767
|
});
|
|
35526
35768
|
const menuRef = (0, import_react72.useRef)(null);
|
|
35527
35769
|
const keepOpenRef = (0, import_react72.useRef)(false);
|
|
35770
|
+
const [keepOpen, setKeepOpenState] = (0, import_react72.useState)(false);
|
|
35528
35771
|
const showTimeoutRef = (0, import_react72.useRef)(null);
|
|
35529
35772
|
const suppressShowUntilRef = (0, import_react72.useRef)(0);
|
|
35530
35773
|
const setKeepOpen = (0, import_react72.useCallback)((next) => {
|
|
35531
35774
|
keepOpenRef.current = next;
|
|
35775
|
+
setKeepOpenState(next);
|
|
35532
35776
|
if (!next) setLinkInputOpen(false);
|
|
35533
35777
|
if (next) setIsVisible(true);
|
|
35534
35778
|
}, []);
|
|
35535
35779
|
const closeBubbleMenu = (0, import_react72.useCallback)(() => {
|
|
35536
35780
|
suppressShowUntilRef.current = Date.now() + 1e3;
|
|
35537
35781
|
keepOpenRef.current = false;
|
|
35782
|
+
setKeepOpenState(false);
|
|
35538
35783
|
setLinkInputOpen(false);
|
|
35539
35784
|
setIsVisible(false);
|
|
35540
35785
|
if (showTimeoutRef.current) {
|
|
@@ -35640,13 +35885,13 @@ var CustomBubbleMenu = ({
|
|
|
35640
35885
|
onMouseDown: (e) => {
|
|
35641
35886
|
const target = e.target;
|
|
35642
35887
|
if (target?.closest?.("[data-ueditor-close-on-select]")) {
|
|
35643
|
-
|
|
35888
|
+
setKeepOpen(false);
|
|
35644
35889
|
} else if (target?.closest?.("[data-ueditor-keep-open]")) {
|
|
35645
|
-
|
|
35890
|
+
setKeepOpen(true);
|
|
35646
35891
|
}
|
|
35647
35892
|
e.preventDefault();
|
|
35648
35893
|
},
|
|
35649
|
-
children: editor.isActive("link") && !
|
|
35894
|
+
children: editor.isActive("link") && !keepOpen && !linkInputOpen ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(
|
|
35650
35895
|
LinkPreviewContent,
|
|
35651
35896
|
{
|
|
35652
35897
|
editor,
|
|
@@ -35672,6 +35917,54 @@ var CustomBubbleMenu = ({
|
|
|
35672
35917
|
document.body
|
|
35673
35918
|
);
|
|
35674
35919
|
};
|
|
35920
|
+
var CustomFloatingMenu = ({ editor }) => {
|
|
35921
|
+
const FLOATING_MENU_OFFSET = 16;
|
|
35922
|
+
const [isVisible, setIsVisible] = (0, import_react72.useState)(false);
|
|
35923
|
+
const [position, setPosition2] = (0, import_react72.useState)({ top: 0, left: 0 });
|
|
35924
|
+
(0, import_react72.useEffect)(() => {
|
|
35925
|
+
const updatePosition = () => {
|
|
35926
|
+
const { state, view } = editor;
|
|
35927
|
+
const { $from, empty } = state.selection;
|
|
35928
|
+
const isEmptyTextBlock = $from.parent.isTextblock && $from.parent.type.name === "paragraph" && $from.parent.textContent === "" && empty;
|
|
35929
|
+
if (!isEmptyTextBlock || !view.hasFocus()) {
|
|
35930
|
+
setIsVisible(false);
|
|
35931
|
+
return;
|
|
35932
|
+
}
|
|
35933
|
+
const coords = view.coordsAtPos($from.pos);
|
|
35934
|
+
setPosition2({ top: coords.top - FLOATING_MENU_OFFSET, left: coords.left });
|
|
35935
|
+
setIsVisible(true);
|
|
35936
|
+
};
|
|
35937
|
+
const handleBlur = () => setIsVisible(false);
|
|
35938
|
+
editor.on("selectionUpdate", updatePosition);
|
|
35939
|
+
editor.on("focus", updatePosition);
|
|
35940
|
+
editor.on("blur", handleBlur);
|
|
35941
|
+
editor.on("update", updatePosition);
|
|
35942
|
+
return () => {
|
|
35943
|
+
editor.off("selectionUpdate", updatePosition);
|
|
35944
|
+
editor.off("focus", updatePosition);
|
|
35945
|
+
editor.off("blur", handleBlur);
|
|
35946
|
+
editor.off("update", updatePosition);
|
|
35947
|
+
};
|
|
35948
|
+
}, [editor]);
|
|
35949
|
+
if (!isVisible) return null;
|
|
35950
|
+
return (0, import_react_dom8.createPortal)(
|
|
35951
|
+
/* @__PURE__ */ (0, import_jsx_runtime92.jsx)(
|
|
35952
|
+
"div",
|
|
35953
|
+
{
|
|
35954
|
+
"data-popover": true,
|
|
35955
|
+
className: "fixed z-99999 rounded-2xl border border-border/50 bg-card text-card-foreground shadow-lg backdrop-blur-sm overflow-hidden animate-in fade-in-0 slide-in-from-bottom-2",
|
|
35956
|
+
style: {
|
|
35957
|
+
top: `${position.top}px`,
|
|
35958
|
+
left: `${position.left}px`,
|
|
35959
|
+
transform: "translate(-50%, -100%)"
|
|
35960
|
+
},
|
|
35961
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
35962
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(FloatingMenuContent, { editor })
|
|
35963
|
+
}
|
|
35964
|
+
),
|
|
35965
|
+
document.body
|
|
35966
|
+
);
|
|
35967
|
+
};
|
|
35675
35968
|
|
|
35676
35969
|
// src/components/UEditor/CharacterCount.tsx
|
|
35677
35970
|
var import_jsx_runtime93 = require("react/jsx-runtime");
|
|
@@ -38747,7 +39040,7 @@ var Selection = class {
|
|
|
38747
39040
|
found.
|
|
38748
39041
|
*/
|
|
38749
39042
|
static findFrom($pos, dir, textOnly = false) {
|
|
38750
|
-
let inner = $pos.parent.inlineContent ? new
|
|
39043
|
+
let inner = $pos.parent.inlineContent ? new TextSelection4($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly);
|
|
38751
39044
|
if (inner)
|
|
38752
39045
|
return inner;
|
|
38753
39046
|
for (let depth = $pos.depth - 1; depth >= 0; depth--) {
|
|
@@ -38816,7 +39109,7 @@ var Selection = class {
|
|
|
38816
39109
|
returns the bookmark for that.
|
|
38817
39110
|
*/
|
|
38818
39111
|
getBookmark() {
|
|
38819
|
-
return
|
|
39112
|
+
return TextSelection4.between(this.$anchor, this.$head).getBookmark();
|
|
38820
39113
|
}
|
|
38821
39114
|
};
|
|
38822
39115
|
Selection.prototype.visible = true;
|
|
@@ -38836,7 +39129,7 @@ function checkTextSelection($pos) {
|
|
|
38836
39129
|
console["warn"]("TextSelection endpoint not pointing into a node with inline content (" + $pos.parent.type.name + ")");
|
|
38837
39130
|
}
|
|
38838
39131
|
}
|
|
38839
|
-
var
|
|
39132
|
+
var TextSelection4 = class _TextSelection extends Selection {
|
|
38840
39133
|
/**
|
|
38841
39134
|
Construct a text selection between the given points.
|
|
38842
39135
|
*/
|
|
@@ -38922,7 +39215,7 @@ var TextSelection3 = class _TextSelection extends Selection {
|
|
|
38922
39215
|
return new _TextSelection($anchor, $head);
|
|
38923
39216
|
}
|
|
38924
39217
|
};
|
|
38925
|
-
Selection.jsonID("text",
|
|
39218
|
+
Selection.jsonID("text", TextSelection4);
|
|
38926
39219
|
var TextBookmark = class _TextBookmark {
|
|
38927
39220
|
constructor(anchor, head) {
|
|
38928
39221
|
this.anchor = anchor;
|
|
@@ -38932,7 +39225,7 @@ var TextBookmark = class _TextBookmark {
|
|
|
38932
39225
|
return new _TextBookmark(mapping.map(this.anchor), mapping.map(this.head));
|
|
38933
39226
|
}
|
|
38934
39227
|
resolve(doc) {
|
|
38935
|
-
return
|
|
39228
|
+
return TextSelection4.between(doc.resolve(this.anchor), doc.resolve(this.head));
|
|
38936
39229
|
}
|
|
38937
39230
|
};
|
|
38938
39231
|
var NodeSelection2 = class _NodeSelection extends Selection {
|
|
@@ -39051,7 +39344,7 @@ var AllBookmark = {
|
|
|
39051
39344
|
};
|
|
39052
39345
|
function findSelectionIn(doc, node, pos, index, dir, text = false) {
|
|
39053
39346
|
if (node.inlineContent)
|
|
39054
|
-
return
|
|
39347
|
+
return TextSelection4.create(doc, pos);
|
|
39055
39348
|
for (let i = index - (dir > 0 ? 0 : 1); dir > 0 ? i < node.childCount : i >= 0; i += dir) {
|
|
39056
39349
|
let child = node.child(i);
|
|
39057
39350
|
if (!child.isAtom) {
|
|
@@ -39643,7 +39936,7 @@ var CellSelection = class CellSelection2 extends Selection {
|
|
|
39643
39936
|
else if (tableChanged && this.isColSelection()) return CellSelection2.colSelection($anchorCell, $headCell);
|
|
39644
39937
|
else return new CellSelection2($anchorCell, $headCell);
|
|
39645
39938
|
}
|
|
39646
|
-
return
|
|
39939
|
+
return TextSelection4.between($anchorCell, $headCell);
|
|
39647
39940
|
}
|
|
39648
39941
|
content() {
|
|
39649
39942
|
const table = this.$anchorCell.node(-1);
|
|
@@ -40258,7 +40551,7 @@ function shiftArrow(axis, dir) {
|
|
|
40258
40551
|
};
|
|
40259
40552
|
}
|
|
40260
40553
|
function atEndOfCell(view, axis, dir) {
|
|
40261
|
-
if (!(view.state.selection instanceof
|
|
40554
|
+
if (!(view.state.selection instanceof TextSelection4)) return null;
|
|
40262
40555
|
const { $head } = view.state.selection;
|
|
40263
40556
|
for (let d = $head.depth - 1; d >= 0; d--) {
|
|
40264
40557
|
const parent = $head.node(d);
|
|
@@ -41378,7 +41671,7 @@ function TableControls({ editor, containerRef }) {
|
|
|
41378
41671
|
destructive: true
|
|
41379
41672
|
}
|
|
41380
41673
|
];
|
|
41381
|
-
}, [layout, runAtActiveCell, t]);
|
|
41674
|
+
}, [editor, layout, runAtActiveCell, t]);
|
|
41382
41675
|
const getRowHandleMenuItems = import_react74.default.useCallback((rowHandle) => [
|
|
41383
41676
|
{
|
|
41384
41677
|
label: t("tableMenu.addRowBefore"),
|
|
@@ -41594,6 +41887,42 @@ var UEDITOR_PROSEMIRROR_CLASS_NAME = cn(
|
|
|
41594
41887
|
"[&_th]:px-2",
|
|
41595
41888
|
"[&_th]:py-0",
|
|
41596
41889
|
"[&_th_p]:my-0",
|
|
41890
|
+
"[&_td[data-formula]]:pr-7",
|
|
41891
|
+
"[&_th[data-formula]]:pr-7",
|
|
41892
|
+
"[&_td[data-formula]]:before:pointer-events-none",
|
|
41893
|
+
"[&_th[data-formula]]:before:pointer-events-none",
|
|
41894
|
+
"[&_td[data-formula]]:before:absolute",
|
|
41895
|
+
"[&_th[data-formula]]:before:absolute",
|
|
41896
|
+
"[&_td[data-formula]]:before:right-1",
|
|
41897
|
+
"[&_th[data-formula]]:before:right-1",
|
|
41898
|
+
"[&_td[data-formula]]:before:top-1",
|
|
41899
|
+
"[&_th[data-formula]]:before:top-1",
|
|
41900
|
+
"[&_td[data-formula]]:before:z-[1]",
|
|
41901
|
+
"[&_th[data-formula]]:before:z-[1]",
|
|
41902
|
+
"[&_td[data-formula]]:before:rounded-sm",
|
|
41903
|
+
"[&_th[data-formula]]:before:rounded-sm",
|
|
41904
|
+
"[&_td[data-formula]]:before:bg-primary/10",
|
|
41905
|
+
"[&_th[data-formula]]:before:bg-primary/10",
|
|
41906
|
+
"[&_td[data-formula]]:before:px-1",
|
|
41907
|
+
"[&_th[data-formula]]:before:px-1",
|
|
41908
|
+
"[&_td[data-formula]]:before:font-mono",
|
|
41909
|
+
"[&_th[data-formula]]:before:font-mono",
|
|
41910
|
+
"[&_td[data-formula]]:before:text-[9px]",
|
|
41911
|
+
"[&_th[data-formula]]:before:text-[9px]",
|
|
41912
|
+
"[&_td[data-formula]]:before:font-semibold",
|
|
41913
|
+
"[&_th[data-formula]]:before:font-semibold",
|
|
41914
|
+
"[&_td[data-formula]]:before:leading-4",
|
|
41915
|
+
"[&_th[data-formula]]:before:leading-4",
|
|
41916
|
+
"[&_td[data-formula]]:before:text-primary",
|
|
41917
|
+
"[&_th[data-formula]]:before:text-primary",
|
|
41918
|
+
"[&_td[data-formula]]:before:content-['fx']",
|
|
41919
|
+
"[&_th[data-formula]]:before:content-['fx']",
|
|
41920
|
+
"[&_td[data-formula-state='error']]:bg-destructive/5",
|
|
41921
|
+
"[&_th[data-formula-state='error']]:bg-destructive/5",
|
|
41922
|
+
"[&_td[data-formula-state='error']]:before:bg-destructive/10",
|
|
41923
|
+
"[&_th[data-formula-state='error']]:before:bg-destructive/10",
|
|
41924
|
+
"[&_td[data-formula-state='error']]:before:text-destructive",
|
|
41925
|
+
"[&_th[data-formula-state='error']]:before:text-destructive",
|
|
41597
41926
|
"[&_td[colwidth]]:min-w-0",
|
|
41598
41927
|
"[&_th[colwidth]]:min-w-0",
|
|
41599
41928
|
"[&_td[data-colwidth]]:min-w-0",
|
|
@@ -42099,7 +42428,7 @@ function useUEditorTableInteractions(editor, editable = true) {
|
|
|
42099
42428
|
clearHoveredTableCell();
|
|
42100
42429
|
clearAllTableResizeHover();
|
|
42101
42430
|
};
|
|
42102
|
-
}, [beginResize, cancelResize, cleanupRowResize, clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, editable, editor, handleRowResizePointerMove, handleRowResizePointerUp, hideColumnGuide, hideRowGuide, isRowResizing, scheduleTableLayoutSync, showColumnGuide, showRowGuide, syncActiveRowResizeGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
|
|
42431
|
+
}, [beginResize, cancelResize, cleanupRowResize, clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, editable, editor, handleRowResizePointerMove, handleRowResizePointerUp, hideColumnGuide, hideRowGuide, isRowResizing, scheduleTableLayoutSync, setActiveTableCell, setHoveredTableCell, showColumnGuide, showRowGuide, syncActiveRowResizeGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
|
|
42103
42432
|
return {
|
|
42104
42433
|
editorContentRef,
|
|
42105
42434
|
tableColumnGuideRef,
|
|
@@ -42113,7 +42442,7 @@ var import_react77 = require("react");
|
|
|
42113
42442
|
var import_tables8 = require("@tiptap/pm/tables");
|
|
42114
42443
|
|
|
42115
42444
|
// src/components/UEditor/table-formula-range-picker.ts
|
|
42116
|
-
var
|
|
42445
|
+
var import_state11 = require("@tiptap/pm/state");
|
|
42117
42446
|
var import_tables7 = require("@tiptap/pm/tables");
|
|
42118
42447
|
function getCellText2(cellNode) {
|
|
42119
42448
|
return cellNode.textBetween(0, cellNode.content.size, "\n").trim();
|
|
@@ -42149,7 +42478,7 @@ function cancelFormulaEditing(view) {
|
|
|
42149
42478
|
if (!context) return false;
|
|
42150
42479
|
let tr = view.state.tr.delete(context.cellContentStart, context.cellContentEnd);
|
|
42151
42480
|
const selectionPos = Math.min(context.cellContentStart, tr.doc.content.size);
|
|
42152
|
-
tr = tr.setSelection(
|
|
42481
|
+
tr = tr.setSelection(import_state11.TextSelection.near(tr.doc.resolve(selectionPos)));
|
|
42153
42482
|
view.dispatch(tr);
|
|
42154
42483
|
view.focus();
|
|
42155
42484
|
return true;
|
|
@@ -42216,7 +42545,7 @@ function replacePickedLabel(view, pickState, nextLabel, currentCell) {
|
|
|
42216
42545
|
}
|
|
42217
42546
|
let tr = view.state.tr.insertText(nextLabel, pickState.insertedFrom, pickState.insertedTo);
|
|
42218
42547
|
const nextTo = pickState.insertedFrom + nextLabel.length;
|
|
42219
|
-
tr = tr.setSelection(
|
|
42548
|
+
tr = tr.setSelection(import_state11.TextSelection.create(tr.doc, nextTo));
|
|
42220
42549
|
view.dispatch(tr);
|
|
42221
42550
|
return {
|
|
42222
42551
|
...pickState,
|
|
@@ -42236,7 +42565,7 @@ function beginFormulaRangePick(view, event) {
|
|
|
42236
42565
|
const insertedText = `${prefix}${picked.label}`;
|
|
42237
42566
|
const insertedFrom = from + prefix.length;
|
|
42238
42567
|
let tr = view.state.tr.insertText(insertedText, from, to);
|
|
42239
|
-
tr = tr.setSelection(
|
|
42568
|
+
tr = tr.setSelection(import_state11.TextSelection.create(tr.doc, from + insertedText.length));
|
|
42240
42569
|
view.dispatch(tr);
|
|
42241
42570
|
view.focus();
|
|
42242
42571
|
event.preventDefault();
|
|
@@ -43385,9 +43714,156 @@ var MenuBar = ({
|
|
|
43385
43714
|
] });
|
|
43386
43715
|
};
|
|
43387
43716
|
|
|
43388
|
-
// src/components/UEditor/
|
|
43717
|
+
// src/components/UEditor/table-formula-bar.tsx
|
|
43718
|
+
var import_react80 = require("react");
|
|
43719
|
+
var import_react81 = require("@tiptap/react");
|
|
43720
|
+
var import_lucide_react59 = require("lucide-react");
|
|
43389
43721
|
var import_jsx_runtime100 = require("react/jsx-runtime");
|
|
43390
|
-
|
|
43722
|
+
function TableFormulaBar({ editor }) {
|
|
43723
|
+
const t = useSmartTranslations("UEditor");
|
|
43724
|
+
const inputRef = (0, import_react80.useRef)(null);
|
|
43725
|
+
const [draftState, setDraftState] = (0, import_react80.useState)(null);
|
|
43726
|
+
(0, import_react81.useEditorState)({
|
|
43727
|
+
editor,
|
|
43728
|
+
selector: ({ transactionNumber }) => transactionNumber
|
|
43729
|
+
});
|
|
43730
|
+
const selectedCell = getSelectedTableFormulaCell(editor);
|
|
43731
|
+
(0, import_react80.useEffect)(() => {
|
|
43732
|
+
const focusFormulaInput = () => {
|
|
43733
|
+
inputRef.current?.focus();
|
|
43734
|
+
};
|
|
43735
|
+
const handleDoubleClick = (event) => {
|
|
43736
|
+
const target = resolveEventElement(event.target);
|
|
43737
|
+
if (!target?.closest?.("td[data-formula],th[data-formula]")) return;
|
|
43738
|
+
event.preventDefault();
|
|
43739
|
+
focusFormulaInput();
|
|
43740
|
+
};
|
|
43741
|
+
editor.view.dom.addEventListener("dblclick", handleDoubleClick);
|
|
43742
|
+
return () => {
|
|
43743
|
+
editor.view.dom.removeEventListener("dblclick", handleDoubleClick);
|
|
43744
|
+
};
|
|
43745
|
+
}, [editor]);
|
|
43746
|
+
if (!selectedCell) return null;
|
|
43747
|
+
const selectedCellKey = `${selectedCell.tablePos}:${selectedCell.row}:${selectedCell.column}`;
|
|
43748
|
+
const draft = draftState?.cellKey === selectedCellKey && draftState.sourceFormula === selectedCell.formula ? draftState.value : selectedCell.formula;
|
|
43749
|
+
const setDraft = (value) => {
|
|
43750
|
+
setDraftState({
|
|
43751
|
+
cellKey: selectedCellKey,
|
|
43752
|
+
sourceFormula: selectedCell.formula,
|
|
43753
|
+
value
|
|
43754
|
+
});
|
|
43755
|
+
};
|
|
43756
|
+
const applyDraft = () => {
|
|
43757
|
+
const normalized = normalizeFormulaInput(draft);
|
|
43758
|
+
if (normalized) {
|
|
43759
|
+
setSelectedTableCellFormula(editor, normalized);
|
|
43760
|
+
} else {
|
|
43761
|
+
clearSelectedTableCellFormula(editor);
|
|
43762
|
+
}
|
|
43763
|
+
setDraftState(null);
|
|
43764
|
+
};
|
|
43765
|
+
const cancelDraft = () => {
|
|
43766
|
+
setDraftState(null);
|
|
43767
|
+
window.setTimeout(() => {
|
|
43768
|
+
if (!editor.isDestroyed) editor.commands.focus();
|
|
43769
|
+
}, 0);
|
|
43770
|
+
};
|
|
43771
|
+
return /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)(
|
|
43772
|
+
"div",
|
|
43773
|
+
{
|
|
43774
|
+
"data-ueditor-formula-bar": "",
|
|
43775
|
+
role: "toolbar",
|
|
43776
|
+
"aria-label": t("tableMenu.formulaBar"),
|
|
43777
|
+
className: "flex min-h-10 items-center gap-2 border-b border-border/60 bg-muted/25 px-2 py-1.5",
|
|
43778
|
+
children: [
|
|
43779
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43780
|
+
"span",
|
|
43781
|
+
{
|
|
43782
|
+
"data-ueditor-formula-cell-label": "",
|
|
43783
|
+
className: "flex h-7 min-w-12 items-center justify-center rounded-md border border-border/60 bg-background px-2 font-mono text-xs font-semibold text-foreground",
|
|
43784
|
+
children: selectedCell.label
|
|
43785
|
+
}
|
|
43786
|
+
),
|
|
43787
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(import_lucide_react59.Sigma, { "aria-hidden": "true", className: "h-4 w-4 shrink-0 text-primary" }),
|
|
43788
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43789
|
+
"input",
|
|
43790
|
+
{
|
|
43791
|
+
ref: inputRef,
|
|
43792
|
+
"data-ueditor-formula-input": "",
|
|
43793
|
+
value: draft,
|
|
43794
|
+
onChange: (event) => setDraft(event.target.value),
|
|
43795
|
+
onKeyDown: (event) => {
|
|
43796
|
+
event.stopPropagation();
|
|
43797
|
+
if (event.key === "Enter") {
|
|
43798
|
+
event.preventDefault();
|
|
43799
|
+
applyDraft();
|
|
43800
|
+
} else if (event.key === "Escape") {
|
|
43801
|
+
event.preventDefault();
|
|
43802
|
+
cancelDraft();
|
|
43803
|
+
}
|
|
43804
|
+
},
|
|
43805
|
+
"aria-label": t("tableMenu.editFormula"),
|
|
43806
|
+
className: "h-7 min-w-0 flex-1 rounded-md border border-border/60 bg-background px-2 font-mono text-sm text-foreground outline-none focus:border-primary/40 focus:ring-2 focus:ring-primary/15"
|
|
43807
|
+
}
|
|
43808
|
+
),
|
|
43809
|
+
selectedCell.formulaState === "error" && /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)(
|
|
43810
|
+
"span",
|
|
43811
|
+
{
|
|
43812
|
+
role: "status",
|
|
43813
|
+
className: "hidden shrink-0 items-center gap-1 text-xs font-medium text-destructive sm:inline-flex",
|
|
43814
|
+
children: [
|
|
43815
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(import_lucide_react59.AlertCircle, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
43816
|
+
t("tableMenu.formulaError")
|
|
43817
|
+
]
|
|
43818
|
+
}
|
|
43819
|
+
),
|
|
43820
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43821
|
+
"button",
|
|
43822
|
+
{
|
|
43823
|
+
type: "button",
|
|
43824
|
+
onClick: applyDraft,
|
|
43825
|
+
"aria-label": t("tableMenu.apply"),
|
|
43826
|
+
title: t("tableMenu.apply"),
|
|
43827
|
+
className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-primary text-primary-foreground transition-colors hover:bg-primary/90",
|
|
43828
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(import_lucide_react59.Check, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
43829
|
+
}
|
|
43830
|
+
),
|
|
43831
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43832
|
+
"button",
|
|
43833
|
+
{
|
|
43834
|
+
type: "button",
|
|
43835
|
+
onClick: () => {
|
|
43836
|
+
convertSelectedTableCellFormulaToValue(editor);
|
|
43837
|
+
setDraftState(null);
|
|
43838
|
+
},
|
|
43839
|
+
"aria-label": t("tableMenu.convertToValue"),
|
|
43840
|
+
title: t("tableMenu.convertToValue"),
|
|
43841
|
+
className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md border border-border/60 bg-background text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
43842
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(import_lucide_react59.Hash, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
43843
|
+
}
|
|
43844
|
+
),
|
|
43845
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43846
|
+
"button",
|
|
43847
|
+
{
|
|
43848
|
+
type: "button",
|
|
43849
|
+
onClick: () => {
|
|
43850
|
+
clearSelectedTableCellFormula(editor);
|
|
43851
|
+
setDraftState(null);
|
|
43852
|
+
},
|
|
43853
|
+
"aria-label": t("tableMenu.clearCell"),
|
|
43854
|
+
title: t("tableMenu.clearCell"),
|
|
43855
|
+
className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md border border-destructive/30 bg-background text-destructive transition-colors hover:bg-destructive/10",
|
|
43856
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(import_lucide_react59.Trash2, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
43857
|
+
}
|
|
43858
|
+
)
|
|
43859
|
+
]
|
|
43860
|
+
}
|
|
43861
|
+
);
|
|
43862
|
+
}
|
|
43863
|
+
|
|
43864
|
+
// src/components/UEditor/UEditor.tsx
|
|
43865
|
+
var import_jsx_runtime101 = require("react/jsx-runtime");
|
|
43866
|
+
var UEditor = import_react82.default.forwardRef(({
|
|
43391
43867
|
content = "",
|
|
43392
43868
|
onChange,
|
|
43393
43869
|
onHtmlChange,
|
|
@@ -43405,6 +43881,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43405
43881
|
autofocus = false,
|
|
43406
43882
|
showToolbar = true,
|
|
43407
43883
|
showBubbleMenu = true,
|
|
43884
|
+
showFloatingMenu = false,
|
|
43408
43885
|
showCharacterCount = true,
|
|
43409
43886
|
showFooter = true,
|
|
43410
43887
|
maxCharacters,
|
|
@@ -43428,14 +43905,14 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43428
43905
|
}, ref) => {
|
|
43429
43906
|
const t = useSmartTranslations("UEditor");
|
|
43430
43907
|
const effectivePlaceholder = placeholder ?? t("placeholder");
|
|
43431
|
-
const inFlightPrepareRef = (0,
|
|
43432
|
-
const lastAppliedContentRef = (0,
|
|
43433
|
-
const scheduledFormulaRecalculateRef = (0,
|
|
43434
|
-
const editorInstanceRef = (0,
|
|
43435
|
-
const formulaRangePickRef = (0,
|
|
43436
|
-
const formulaRangeSurfaceRef = (0,
|
|
43437
|
-
const [formulaRangeHighlight, setFormulaRangeHighlight] =
|
|
43438
|
-
const scheduleFormulaRecalculate =
|
|
43908
|
+
const inFlightPrepareRef = (0, import_react82.useRef)(null);
|
|
43909
|
+
const lastAppliedContentRef = (0, import_react82.useRef)(content ?? "");
|
|
43910
|
+
const scheduledFormulaRecalculateRef = (0, import_react82.useRef)(false);
|
|
43911
|
+
const editorInstanceRef = (0, import_react82.useRef)(null);
|
|
43912
|
+
const formulaRangePickRef = (0, import_react82.useRef)(null);
|
|
43913
|
+
const formulaRangeSurfaceRef = (0, import_react82.useRef)(null);
|
|
43914
|
+
const [formulaRangeHighlight, setFormulaRangeHighlight] = import_react82.default.useState(null);
|
|
43915
|
+
const scheduleFormulaRecalculate = import_react82.default.useCallback((editor2, options) => {
|
|
43439
43916
|
if (editor2.isDestroyed || scheduledFormulaRecalculateRef.current) return;
|
|
43440
43917
|
if (!options?.force && isEditingTableFormulaText(editor2)) return;
|
|
43441
43918
|
scheduledFormulaRecalculateRef.current = true;
|
|
@@ -43446,7 +43923,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43446
43923
|
}
|
|
43447
43924
|
});
|
|
43448
43925
|
}, []);
|
|
43449
|
-
const resolvedUploadFile = (0,
|
|
43926
|
+
const resolvedUploadFile = (0, import_react82.useMemo)(() => {
|
|
43450
43927
|
if (uploadFile) return uploadFile;
|
|
43451
43928
|
if (uploadFileForSave) {
|
|
43452
43929
|
return async (file) => {
|
|
@@ -43456,7 +43933,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43456
43933
|
}
|
|
43457
43934
|
return uploadImage;
|
|
43458
43935
|
}, [uploadFile, uploadFileForSave, uploadImage]);
|
|
43459
|
-
const extensions = (0,
|
|
43936
|
+
const extensions = (0, import_react82.useMemo)(
|
|
43460
43937
|
() => [
|
|
43461
43938
|
...buildUEditorExtensions({
|
|
43462
43939
|
placeholder: effectivePlaceholder,
|
|
@@ -43475,11 +43952,11 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43475
43952
|
],
|
|
43476
43953
|
[effectivePlaceholder, t, maxCharacters, uploadImage, resolvedUploadFile, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable, fetchMetadata, extraExtensions]
|
|
43477
43954
|
);
|
|
43478
|
-
const syncFormulaRangeHighlight =
|
|
43955
|
+
const syncFormulaRangeHighlight = import_react82.default.useCallback((pickState) => {
|
|
43479
43956
|
const container = formulaRangeSurfaceRef.current;
|
|
43480
43957
|
setFormulaRangeHighlight(container && pickState ? getFormulaRangePickHighlight(container, pickState) : null);
|
|
43481
43958
|
}, []);
|
|
43482
|
-
const editor = (0,
|
|
43959
|
+
const editor = (0, import_react83.useEditor)({
|
|
43483
43960
|
immediatelyRender: false,
|
|
43484
43961
|
extensions,
|
|
43485
43962
|
content,
|
|
@@ -43524,9 +44001,9 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43524
44001
|
if (formulaContext && event.key === "Enter") {
|
|
43525
44002
|
event.preventDefault();
|
|
43526
44003
|
event.stopPropagation();
|
|
43527
|
-
const
|
|
43528
|
-
if (
|
|
43529
|
-
recalculateActiveTableFormulas(
|
|
44004
|
+
const activeEditor2 = editorInstanceRef.current;
|
|
44005
|
+
if (activeEditor2 && !isDraftTableFormula(formulaContext.formula)) {
|
|
44006
|
+
recalculateActiveTableFormulas(activeEditor2);
|
|
43530
44007
|
}
|
|
43531
44008
|
return true;
|
|
43532
44009
|
}
|
|
@@ -43536,6 +44013,13 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43536
44013
|
cancelFormulaEditing(_view);
|
|
43537
44014
|
return true;
|
|
43538
44015
|
}
|
|
44016
|
+
const activeEditor = editorInstanceRef.current;
|
|
44017
|
+
if (activeEditor && (event.key === "Backspace" || event.key === "Delete") && getSelectedTableFormulaCell(activeEditor)) {
|
|
44018
|
+
event.preventDefault();
|
|
44019
|
+
event.stopPropagation();
|
|
44020
|
+
clearSelectedTableCellFormula(activeEditor);
|
|
44021
|
+
return true;
|
|
44022
|
+
}
|
|
43539
44023
|
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
43540
44024
|
event.stopPropagation();
|
|
43541
44025
|
}
|
|
@@ -43546,7 +44030,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43546
44030
|
if (event.button !== 0) return false;
|
|
43547
44031
|
const target = resolveEventElement(event.target);
|
|
43548
44032
|
const anchor = target?.closest?.("a[href]");
|
|
43549
|
-
const href = anchor?.getAttribute("href") ?? "";
|
|
44033
|
+
const href = sanitizeUEditorUrl(anchor?.getAttribute("href") ?? "", "link");
|
|
43550
44034
|
if (!href) return false;
|
|
43551
44035
|
if (editable) return false;
|
|
43552
44036
|
if (!view.state.selection.empty) return false;
|
|
@@ -43572,11 +44056,13 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43572
44056
|
onSelectionUpdate: ({ editor: editor2 }) => {
|
|
43573
44057
|
scheduleFormulaRecalculate(editor2);
|
|
43574
44058
|
},
|
|
43575
|
-
onBlur: ({ editor: editor2 }) => {
|
|
44059
|
+
onBlur: ({ editor: editor2, event }) => {
|
|
44060
|
+
const nextTarget = event.relatedTarget;
|
|
44061
|
+
if (nextTarget instanceof Element && nextTarget.closest("[data-ueditor-formula-bar]")) return;
|
|
43576
44062
|
scheduleFormulaRecalculate(editor2, { force: true });
|
|
43577
44063
|
}
|
|
43578
44064
|
});
|
|
43579
|
-
(0,
|
|
44065
|
+
(0, import_react82.useEffect)(() => {
|
|
43580
44066
|
editorInstanceRef.current = editor;
|
|
43581
44067
|
return () => {
|
|
43582
44068
|
if (editorInstanceRef.current === editor) editorInstanceRef.current = null;
|
|
@@ -43592,7 +44078,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43592
44078
|
apply: t("tableMenu.apply"),
|
|
43593
44079
|
cancel: t("imageInput.cancelBtn")
|
|
43594
44080
|
});
|
|
43595
|
-
(0,
|
|
44081
|
+
(0, import_react82.useImperativeHandle)(
|
|
43596
44082
|
ref,
|
|
43597
44083
|
() => ({
|
|
43598
44084
|
editor,
|
|
@@ -43617,7 +44103,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43617
44103
|
}),
|
|
43618
44104
|
[content, editor, uploadImageForSave, uploadFileForSave, uploadImageConcurrency]
|
|
43619
44105
|
);
|
|
43620
|
-
(0,
|
|
44106
|
+
(0, import_react82.useEffect)(() => {
|
|
43621
44107
|
if (!editor) return;
|
|
43622
44108
|
queueMicrotask(() => {
|
|
43623
44109
|
if (!editor.isDestroyed) {
|
|
@@ -43625,7 +44111,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43625
44111
|
}
|
|
43626
44112
|
});
|
|
43627
44113
|
}, [editor]);
|
|
43628
|
-
(0,
|
|
44114
|
+
(0, import_react82.useEffect)(() => {
|
|
43629
44115
|
if (!editor) return;
|
|
43630
44116
|
const nextContent = content ?? "";
|
|
43631
44117
|
if (lastAppliedContentRef.current === nextContent) return;
|
|
@@ -43644,7 +44130,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43644
44130
|
}
|
|
43645
44131
|
}, [content, editor]);
|
|
43646
44132
|
if (!editor) {
|
|
43647
|
-
return /* @__PURE__ */ (0,
|
|
44133
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43648
44134
|
"div",
|
|
43649
44135
|
{
|
|
43650
44136
|
className: cn("w-full border bg-background flex items-center justify-center text-muted-foreground", className),
|
|
@@ -43653,7 +44139,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43653
44139
|
}
|
|
43654
44140
|
);
|
|
43655
44141
|
}
|
|
43656
|
-
return /* @__PURE__ */ (0,
|
|
44142
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)(
|
|
43657
44143
|
"div",
|
|
43658
44144
|
{
|
|
43659
44145
|
className: cn(
|
|
@@ -43669,7 +44155,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43669
44155
|
className
|
|
43670
44156
|
),
|
|
43671
44157
|
children: [
|
|
43672
|
-
editable && showMenuBar && /* @__PURE__ */ (0,
|
|
44158
|
+
editable && showMenuBar && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43673
44159
|
MenuBar,
|
|
43674
44160
|
{
|
|
43675
44161
|
editor,
|
|
@@ -43684,7 +44170,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43684
44170
|
onPreview
|
|
43685
44171
|
}
|
|
43686
44172
|
),
|
|
43687
|
-
editable && showToolbar && /* @__PURE__ */ (0,
|
|
44173
|
+
editable && showToolbar && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43688
44174
|
EditorToolbar,
|
|
43689
44175
|
{
|
|
43690
44176
|
editor,
|
|
@@ -43699,7 +44185,8 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43699
44185
|
letterSpacings
|
|
43700
44186
|
}
|
|
43701
44187
|
),
|
|
43702
|
-
editable &&
|
|
44188
|
+
editable && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(TableFormulaBar, { editor }),
|
|
44189
|
+
editable && showBubbleMenu && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43703
44190
|
CustomBubbleMenu,
|
|
43704
44191
|
{
|
|
43705
44192
|
editor,
|
|
@@ -43707,7 +44194,8 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43707
44194
|
lineHeights
|
|
43708
44195
|
}
|
|
43709
44196
|
),
|
|
43710
|
-
/* @__PURE__ */ (0,
|
|
44197
|
+
editable && showFloatingMenu && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(CustomFloatingMenu, { editor }),
|
|
44198
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)(
|
|
43711
44199
|
"div",
|
|
43712
44200
|
{
|
|
43713
44201
|
ref: (node) => {
|
|
@@ -43720,7 +44208,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43720
44208
|
maxHeight
|
|
43721
44209
|
},
|
|
43722
44210
|
children: [
|
|
43723
|
-
/* @__PURE__ */ (0,
|
|
44211
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43724
44212
|
"span",
|
|
43725
44213
|
{
|
|
43726
44214
|
ref: tableColumnGuideRef,
|
|
@@ -43728,7 +44216,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43728
44216
|
className: "pointer-events-none absolute z-20 bg-primary opacity-0 transition-opacity duration-100"
|
|
43729
44217
|
}
|
|
43730
44218
|
),
|
|
43731
|
-
/* @__PURE__ */ (0,
|
|
44219
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43732
44220
|
"span",
|
|
43733
44221
|
{
|
|
43734
44222
|
ref: tableRowGuideRef,
|
|
@@ -43736,7 +44224,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43736
44224
|
className: "pointer-events-none absolute z-20 bg-primary opacity-0 transition-opacity duration-100"
|
|
43737
44225
|
}
|
|
43738
44226
|
),
|
|
43739
|
-
/* @__PURE__ */ (0,
|
|
44227
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43740
44228
|
"span",
|
|
43741
44229
|
{
|
|
43742
44230
|
ref: activeTableCellHighlightRef,
|
|
@@ -43745,7 +44233,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43745
44233
|
className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10"
|
|
43746
44234
|
}
|
|
43747
44235
|
),
|
|
43748
|
-
/* @__PURE__ */ (0,
|
|
44236
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43749
44237
|
"div",
|
|
43750
44238
|
{
|
|
43751
44239
|
ref: formulaCoordinateOverlayRef,
|
|
@@ -43753,7 +44241,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43753
44241
|
className: "pointer-events-none absolute inset-0 z-[21] hidden overflow-visible"
|
|
43754
44242
|
}
|
|
43755
44243
|
),
|
|
43756
|
-
formulaRangeHighlight && /* @__PURE__ */ (0,
|
|
44244
|
+
formulaRangeHighlight && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43757
44245
|
"span",
|
|
43758
44246
|
{
|
|
43759
44247
|
"aria-hidden": "true",
|
|
@@ -43767,9 +44255,9 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43767
44255
|
}
|
|
43768
44256
|
}
|
|
43769
44257
|
),
|
|
43770
|
-
editable && /* @__PURE__ */ (0,
|
|
43771
|
-
/* @__PURE__ */ (0,
|
|
43772
|
-
|
|
44258
|
+
editable && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(TableControls, { editor, containerRef: editorContentRef }),
|
|
44259
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
44260
|
+
import_react83.EditorContent,
|
|
43773
44261
|
{
|
|
43774
44262
|
editor,
|
|
43775
44263
|
className: "min-h-full"
|
|
@@ -43778,7 +44266,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43778
44266
|
]
|
|
43779
44267
|
}
|
|
43780
44268
|
),
|
|
43781
|
-
showFooter && showCharacterCount && /* @__PURE__ */ (0,
|
|
44269
|
+
showFooter && showCharacterCount && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(CharacterCountDisplay, { editor, maxCharacters })
|
|
43782
44270
|
]
|
|
43783
44271
|
}
|
|
43784
44272
|
);
|