@underverse-ui/underverse 1.0.184 → 1.0.186
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 +782 -205
- 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 +776 -199
- 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();
|
|
@@ -42132,6 +42461,9 @@ function getFormulaEditingTableContext(view) {
|
|
|
42132
42461
|
if (!tableNode || tableNode.type.name !== "table") return null;
|
|
42133
42462
|
const tableDom = cellDom.closest("table");
|
|
42134
42463
|
if (!(tableDom instanceof HTMLTableElement)) return null;
|
|
42464
|
+
const tableMap = import_tables7.TableMap.get(tableNode);
|
|
42465
|
+
const tableStart = $from.start(tableDepth);
|
|
42466
|
+
const formulaCellRect = tableMap.findCell(cellPos - tableStart);
|
|
42135
42467
|
return {
|
|
42136
42468
|
cellContentEnd: $from.end(depth),
|
|
42137
42469
|
cellContentStart: $from.start(depth),
|
|
@@ -42139,17 +42471,56 @@ function getFormulaEditingTableContext(view) {
|
|
|
42139
42471
|
formula: getCellText2(node),
|
|
42140
42472
|
tableDom,
|
|
42141
42473
|
tableNode,
|
|
42142
|
-
tablePos: $from.before(tableDepth)
|
|
42474
|
+
tablePos: $from.before(tableDepth),
|
|
42475
|
+
formulaCellLabel: `${indexToColumnName(formulaCellRect.left)}${formulaCellRect.top + 1}`
|
|
42143
42476
|
};
|
|
42144
42477
|
}
|
|
42145
42478
|
return null;
|
|
42146
42479
|
}
|
|
42480
|
+
function collectTableFormulaCells(tableNode) {
|
|
42481
|
+
const tableMap = import_tables7.TableMap.get(tableNode);
|
|
42482
|
+
const formulas = [];
|
|
42483
|
+
tableNode.forEach((rowNode, rowOffset) => {
|
|
42484
|
+
rowNode.forEach((cellNode, cellOffset) => {
|
|
42485
|
+
const formula = typeof cellNode.attrs.formula === "string" ? cellNode.attrs.formula.trim() : "";
|
|
42486
|
+
if (!formula) return;
|
|
42487
|
+
const rect = tableMap.findCell(rowOffset + 1 + cellOffset);
|
|
42488
|
+
formulas.push({
|
|
42489
|
+
label: `${indexToColumnName(rect.left)}${rect.top + 1}`,
|
|
42490
|
+
formula
|
|
42491
|
+
});
|
|
42492
|
+
});
|
|
42493
|
+
});
|
|
42494
|
+
return formulas;
|
|
42495
|
+
}
|
|
42496
|
+
function getFormulaCycleBlockedLabels(tableNode, formulaCellLabel) {
|
|
42497
|
+
const graph = buildTableFormulaDependencyGraph(collectTableFormulaCells(tableNode));
|
|
42498
|
+
const blocked = /* @__PURE__ */ new Set();
|
|
42499
|
+
const queue = [formulaCellLabel.toUpperCase()];
|
|
42500
|
+
for (let index = 0; index < queue.length; index += 1) {
|
|
42501
|
+
const label = queue[index];
|
|
42502
|
+
if (!label || blocked.has(label)) continue;
|
|
42503
|
+
blocked.add(label);
|
|
42504
|
+
for (const dependent of graph.dependents.get(label) ?? []) {
|
|
42505
|
+
if (!blocked.has(dependent)) queue.push(dependent);
|
|
42506
|
+
}
|
|
42507
|
+
}
|
|
42508
|
+
return blocked;
|
|
42509
|
+
}
|
|
42510
|
+
function getReferenceLabels(reference) {
|
|
42511
|
+
const range = parseTableCellRange(reference);
|
|
42512
|
+
return range ? getTableCellRangeLabels(range) : [reference.toUpperCase()];
|
|
42513
|
+
}
|
|
42514
|
+
function isBlockedFormulaReference(tableNode, formulaCellLabel, reference) {
|
|
42515
|
+
const blockedLabels = getFormulaCycleBlockedLabels(tableNode, formulaCellLabel);
|
|
42516
|
+
return getReferenceLabels(reference).some((label) => blockedLabels.has(label));
|
|
42517
|
+
}
|
|
42147
42518
|
function cancelFormulaEditing(view) {
|
|
42148
42519
|
const context = getFormulaEditingTableContext(view);
|
|
42149
42520
|
if (!context) return false;
|
|
42150
42521
|
let tr = view.state.tr.delete(context.cellContentStart, context.cellContentEnd);
|
|
42151
42522
|
const selectionPos = Math.min(context.cellContentStart, tr.doc.content.size);
|
|
42152
|
-
tr = tr.setSelection(
|
|
42523
|
+
tr = tr.setSelection(import_state11.TextSelection.near(tr.doc.resolve(selectionPos)));
|
|
42153
42524
|
view.dispatch(tr);
|
|
42154
42525
|
view.focus();
|
|
42155
42526
|
return true;
|
|
@@ -42207,19 +42578,30 @@ function normalizeFormulaRangeLabel(fromLabel, toLabel) {
|
|
|
42207
42578
|
return fromLabel === toLabel ? fromLabel : `${fromLabel}:${toLabel}`;
|
|
42208
42579
|
}
|
|
42209
42580
|
function replacePickedLabel(view, pickState, nextLabel, currentCell) {
|
|
42210
|
-
|
|
42581
|
+
const formulaContext = getFormulaEditingTableContext(view);
|
|
42582
|
+
const blocked = formulaContext ? isBlockedFormulaReference(formulaContext.tableNode, pickState.formulaCellLabel, nextLabel) : false;
|
|
42583
|
+
if (blocked) {
|
|
42584
|
+
return {
|
|
42585
|
+
...pickState,
|
|
42586
|
+
blocked: true,
|
|
42587
|
+
currentCell
|
|
42588
|
+
};
|
|
42589
|
+
}
|
|
42590
|
+
if (nextLabel === pickState.currentLabel && currentCell === pickState.currentCell && !pickState.blocked) return pickState;
|
|
42211
42591
|
if (nextLabel === pickState.currentLabel) {
|
|
42212
42592
|
return {
|
|
42213
42593
|
...pickState,
|
|
42594
|
+
blocked: false,
|
|
42214
42595
|
currentCell
|
|
42215
42596
|
};
|
|
42216
42597
|
}
|
|
42217
42598
|
let tr = view.state.tr.insertText(nextLabel, pickState.insertedFrom, pickState.insertedTo);
|
|
42218
42599
|
const nextTo = pickState.insertedFrom + nextLabel.length;
|
|
42219
|
-
tr = tr.setSelection(
|
|
42600
|
+
tr = tr.setSelection(import_state11.TextSelection.create(tr.doc, nextTo));
|
|
42220
42601
|
view.dispatch(tr);
|
|
42221
42602
|
return {
|
|
42222
42603
|
...pickState,
|
|
42604
|
+
blocked: false,
|
|
42223
42605
|
insertedTo: nextTo,
|
|
42224
42606
|
currentLabel: nextLabel,
|
|
42225
42607
|
currentCell
|
|
@@ -42231,12 +42613,28 @@ function beginFormulaRangePick(view, event) {
|
|
|
42231
42613
|
if (!formulaCell) return null;
|
|
42232
42614
|
const picked = getFormulaTableCellInfo(view, event.target, formulaCell.tablePos);
|
|
42233
42615
|
if (!picked || picked.cell === formulaCell.cellDom) return null;
|
|
42616
|
+
const blocked = isBlockedFormulaReference(formulaCell.tableNode, formulaCell.formulaCellLabel, picked.label);
|
|
42617
|
+
if (blocked) {
|
|
42618
|
+
event.preventDefault();
|
|
42619
|
+
event.stopPropagation();
|
|
42620
|
+
return {
|
|
42621
|
+
anchorLabel: picked.label,
|
|
42622
|
+
anchorCell: picked.cell,
|
|
42623
|
+
tablePos: formulaCell.tablePos,
|
|
42624
|
+
insertedFrom: view.state.selection.from,
|
|
42625
|
+
insertedTo: view.state.selection.from,
|
|
42626
|
+
currentLabel: "",
|
|
42627
|
+
currentCell: picked.cell,
|
|
42628
|
+
blocked: true,
|
|
42629
|
+
formulaCellLabel: formulaCell.formulaCellLabel
|
|
42630
|
+
};
|
|
42631
|
+
}
|
|
42234
42632
|
const { from, to } = view.state.selection;
|
|
42235
42633
|
const prefix = from === to ? getReferenceInsertionPrefix(view, formulaCell.cellContentStart, from) : "";
|
|
42236
42634
|
const insertedText = `${prefix}${picked.label}`;
|
|
42237
42635
|
const insertedFrom = from + prefix.length;
|
|
42238
42636
|
let tr = view.state.tr.insertText(insertedText, from, to);
|
|
42239
|
-
tr = tr.setSelection(
|
|
42637
|
+
tr = tr.setSelection(import_state11.TextSelection.create(tr.doc, from + insertedText.length));
|
|
42240
42638
|
view.dispatch(tr);
|
|
42241
42639
|
view.focus();
|
|
42242
42640
|
event.preventDefault();
|
|
@@ -42248,7 +42646,9 @@ function beginFormulaRangePick(view, event) {
|
|
|
42248
42646
|
insertedFrom,
|
|
42249
42647
|
insertedTo: insertedFrom + picked.label.length,
|
|
42250
42648
|
currentLabel: picked.label,
|
|
42251
|
-
currentCell: picked.cell
|
|
42649
|
+
currentCell: picked.cell,
|
|
42650
|
+
blocked: false,
|
|
42651
|
+
formulaCellLabel: formulaCell.formulaCellLabel
|
|
42252
42652
|
};
|
|
42253
42653
|
}
|
|
42254
42654
|
function updateFormulaRangePick(view, pickState, event) {
|
|
@@ -42276,7 +42676,8 @@ function getFormulaRangePickHighlight(container, pickState) {
|
|
|
42276
42676
|
left,
|
|
42277
42677
|
top,
|
|
42278
42678
|
width: Math.max(0, right - left),
|
|
42279
|
-
height: Math.max(0, bottom - top)
|
|
42679
|
+
height: Math.max(0, bottom - top),
|
|
42680
|
+
blocked: pickState.blocked
|
|
42280
42681
|
};
|
|
42281
42682
|
}
|
|
42282
42683
|
|
|
@@ -42300,6 +42701,12 @@ function createReferenceHighlight(label) {
|
|
|
42300
42701
|
element.className = "pointer-events-none absolute z-[21] rounded-[2px] border-2 border-emerald-500 bg-emerald-500/15";
|
|
42301
42702
|
return element;
|
|
42302
42703
|
}
|
|
42704
|
+
function createBlockedReferenceHighlight(label) {
|
|
42705
|
+
const element = document.createElement("span");
|
|
42706
|
+
element.dataset.ueditorFormulaBlockedReference = label;
|
|
42707
|
+
element.className = "pointer-events-none absolute z-[22] rounded-[2px] border-2 border-destructive/80 bg-destructive/10";
|
|
42708
|
+
return element;
|
|
42709
|
+
}
|
|
42303
42710
|
function useFormulaCoordinateOverlay(editor, containerRef, labels) {
|
|
42304
42711
|
const overlayRef = (0, import_react77.useRef)(null);
|
|
42305
42712
|
(0, import_react77.useEffect)(() => {
|
|
@@ -42311,6 +42718,7 @@ function useFormulaCoordinateOverlay(editor, containerRef, labels) {
|
|
|
42311
42718
|
let activeTable = null;
|
|
42312
42719
|
let activeTablePos = null;
|
|
42313
42720
|
let hoverLabel = null;
|
|
42721
|
+
const scrollListenerOptions = { passive: true, capture: true };
|
|
42314
42722
|
const clearOverlay = () => {
|
|
42315
42723
|
activeTable = null;
|
|
42316
42724
|
activeTablePos = null;
|
|
@@ -42370,10 +42778,12 @@ function useFormulaCoordinateOverlay(editor, containerRef, labels) {
|
|
|
42370
42778
|
actions.dataset.ueditorFormulaActions = "";
|
|
42371
42779
|
actions.className = "pointer-events-auto absolute z-50 flex items-center gap-1 rounded-md border border-border bg-background p-1 shadow-md";
|
|
42372
42780
|
const formulaCellRect = context.cellDom.getBoundingClientRect();
|
|
42781
|
+
const formulaActionsHeight = 34;
|
|
42782
|
+
const formulaActionsTop = formulaCellRect.bottom + 4 + formulaActionsHeight > tableRect.bottom ? Math.max(containerRect.top + 4, formulaCellRect.top - formulaActionsHeight - 4) : formulaCellRect.bottom + 4;
|
|
42373
42783
|
setPosition(
|
|
42374
42784
|
actions,
|
|
42375
42785
|
formulaCellRect.left - containerRect.left + container.scrollLeft,
|
|
42376
|
-
|
|
42786
|
+
formulaActionsTop - containerRect.top + container.scrollTop
|
|
42377
42787
|
);
|
|
42378
42788
|
const applyButton = document.createElement("button");
|
|
42379
42789
|
applyButton.type = "button";
|
|
@@ -42425,10 +42835,12 @@ function useFormulaCoordinateOverlay(editor, containerRef, labels) {
|
|
|
42425
42835
|
children.push(label);
|
|
42426
42836
|
}
|
|
42427
42837
|
const references = new Set(getTableFormulaReferences(context.formula));
|
|
42838
|
+
const blockedReferences = getFormulaCycleBlockedLabels(context.tableNode, context.formulaCellLabel);
|
|
42428
42839
|
for (const info of cellInfos) {
|
|
42429
|
-
if (!info
|
|
42840
|
+
if (!info) continue;
|
|
42430
42841
|
const cellRect = info.cell.getBoundingClientRect();
|
|
42431
|
-
const highlight = createReferenceHighlight(info.label);
|
|
42842
|
+
const highlight = info.label !== context.formulaCellLabel && blockedReferences.has(info.label) ? createBlockedReferenceHighlight(info.label) : references.has(info.label) ? createReferenceHighlight(info.label) : null;
|
|
42843
|
+
if (!highlight) continue;
|
|
42432
42844
|
setPosition(
|
|
42433
42845
|
highlight,
|
|
42434
42846
|
cellRect.left - containerRect.left + container.scrollLeft + 2,
|
|
@@ -42483,6 +42895,7 @@ function useFormulaCoordinateOverlay(editor, containerRef, labels) {
|
|
|
42483
42895
|
editor.view.dom.addEventListener("mousemove", handleMouseMove2);
|
|
42484
42896
|
editor.view.dom.addEventListener("mouseleave", handleMouseLeave2);
|
|
42485
42897
|
container.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleSync);
|
|
42898
|
+
container.addEventListener("scroll", scheduleSync, scrollListenerOptions);
|
|
42486
42899
|
window.addEventListener("resize", scheduleSync);
|
|
42487
42900
|
scheduleSync();
|
|
42488
42901
|
return () => {
|
|
@@ -42493,6 +42906,7 @@ function useFormulaCoordinateOverlay(editor, containerRef, labels) {
|
|
|
42493
42906
|
editor.view.dom.removeEventListener("mousemove", handleMouseMove2);
|
|
42494
42907
|
editor.view.dom.removeEventListener("mouseleave", handleMouseLeave2);
|
|
42495
42908
|
container.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleSync);
|
|
42909
|
+
container.removeEventListener("scroll", scheduleSync, scrollListenerOptions);
|
|
42496
42910
|
window.removeEventListener("resize", scheduleSync);
|
|
42497
42911
|
if (animationFrame != null) window.cancelAnimationFrame(animationFrame);
|
|
42498
42912
|
clearOverlay();
|
|
@@ -43385,9 +43799,156 @@ var MenuBar = ({
|
|
|
43385
43799
|
] });
|
|
43386
43800
|
};
|
|
43387
43801
|
|
|
43388
|
-
// src/components/UEditor/
|
|
43802
|
+
// src/components/UEditor/table-formula-bar.tsx
|
|
43803
|
+
var import_react80 = require("react");
|
|
43804
|
+
var import_react81 = require("@tiptap/react");
|
|
43805
|
+
var import_lucide_react59 = require("lucide-react");
|
|
43389
43806
|
var import_jsx_runtime100 = require("react/jsx-runtime");
|
|
43390
|
-
|
|
43807
|
+
function TableFormulaBar({ editor }) {
|
|
43808
|
+
const t = useSmartTranslations("UEditor");
|
|
43809
|
+
const inputRef = (0, import_react80.useRef)(null);
|
|
43810
|
+
const [draftState, setDraftState] = (0, import_react80.useState)(null);
|
|
43811
|
+
(0, import_react81.useEditorState)({
|
|
43812
|
+
editor,
|
|
43813
|
+
selector: ({ transactionNumber }) => transactionNumber
|
|
43814
|
+
});
|
|
43815
|
+
const selectedCell = getSelectedTableFormulaCell(editor);
|
|
43816
|
+
(0, import_react80.useEffect)(() => {
|
|
43817
|
+
const focusFormulaInput = () => {
|
|
43818
|
+
inputRef.current?.focus();
|
|
43819
|
+
};
|
|
43820
|
+
const handleDoubleClick = (event) => {
|
|
43821
|
+
const target = resolveEventElement(event.target);
|
|
43822
|
+
if (!target?.closest?.("td[data-formula],th[data-formula]")) return;
|
|
43823
|
+
event.preventDefault();
|
|
43824
|
+
focusFormulaInput();
|
|
43825
|
+
};
|
|
43826
|
+
editor.view.dom.addEventListener("dblclick", handleDoubleClick);
|
|
43827
|
+
return () => {
|
|
43828
|
+
editor.view.dom.removeEventListener("dblclick", handleDoubleClick);
|
|
43829
|
+
};
|
|
43830
|
+
}, [editor]);
|
|
43831
|
+
if (!selectedCell) return null;
|
|
43832
|
+
const selectedCellKey = `${selectedCell.tablePos}:${selectedCell.row}:${selectedCell.column}`;
|
|
43833
|
+
const draft = draftState?.cellKey === selectedCellKey && draftState.sourceFormula === selectedCell.formula ? draftState.value : selectedCell.formula;
|
|
43834
|
+
const setDraft = (value) => {
|
|
43835
|
+
setDraftState({
|
|
43836
|
+
cellKey: selectedCellKey,
|
|
43837
|
+
sourceFormula: selectedCell.formula,
|
|
43838
|
+
value
|
|
43839
|
+
});
|
|
43840
|
+
};
|
|
43841
|
+
const applyDraft = () => {
|
|
43842
|
+
const normalized = normalizeFormulaInput(draft);
|
|
43843
|
+
if (normalized) {
|
|
43844
|
+
setSelectedTableCellFormula(editor, normalized);
|
|
43845
|
+
} else {
|
|
43846
|
+
clearSelectedTableCellFormula(editor);
|
|
43847
|
+
}
|
|
43848
|
+
setDraftState(null);
|
|
43849
|
+
};
|
|
43850
|
+
const cancelDraft = () => {
|
|
43851
|
+
setDraftState(null);
|
|
43852
|
+
window.setTimeout(() => {
|
|
43853
|
+
if (!editor.isDestroyed) editor.commands.focus();
|
|
43854
|
+
}, 0);
|
|
43855
|
+
};
|
|
43856
|
+
return /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)(
|
|
43857
|
+
"div",
|
|
43858
|
+
{
|
|
43859
|
+
"data-ueditor-formula-bar": "",
|
|
43860
|
+
role: "toolbar",
|
|
43861
|
+
"aria-label": t("tableMenu.formulaBar"),
|
|
43862
|
+
className: "flex min-h-10 items-center gap-2 border-b border-border/60 bg-muted/25 px-2 py-1.5",
|
|
43863
|
+
children: [
|
|
43864
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43865
|
+
"span",
|
|
43866
|
+
{
|
|
43867
|
+
"data-ueditor-formula-cell-label": "",
|
|
43868
|
+
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",
|
|
43869
|
+
children: selectedCell.label
|
|
43870
|
+
}
|
|
43871
|
+
),
|
|
43872
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(import_lucide_react59.Sigma, { "aria-hidden": "true", className: "h-4 w-4 shrink-0 text-primary" }),
|
|
43873
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43874
|
+
"input",
|
|
43875
|
+
{
|
|
43876
|
+
ref: inputRef,
|
|
43877
|
+
"data-ueditor-formula-input": "",
|
|
43878
|
+
value: draft,
|
|
43879
|
+
onChange: (event) => setDraft(event.target.value),
|
|
43880
|
+
onKeyDown: (event) => {
|
|
43881
|
+
event.stopPropagation();
|
|
43882
|
+
if (event.key === "Enter") {
|
|
43883
|
+
event.preventDefault();
|
|
43884
|
+
applyDraft();
|
|
43885
|
+
} else if (event.key === "Escape") {
|
|
43886
|
+
event.preventDefault();
|
|
43887
|
+
cancelDraft();
|
|
43888
|
+
}
|
|
43889
|
+
},
|
|
43890
|
+
"aria-label": t("tableMenu.editFormula"),
|
|
43891
|
+
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"
|
|
43892
|
+
}
|
|
43893
|
+
),
|
|
43894
|
+
selectedCell.formulaState === "error" && /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)(
|
|
43895
|
+
"span",
|
|
43896
|
+
{
|
|
43897
|
+
role: "status",
|
|
43898
|
+
className: "hidden shrink-0 items-center gap-1 text-xs font-medium text-destructive sm:inline-flex",
|
|
43899
|
+
children: [
|
|
43900
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(import_lucide_react59.AlertCircle, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
43901
|
+
t("tableMenu.formulaError")
|
|
43902
|
+
]
|
|
43903
|
+
}
|
|
43904
|
+
),
|
|
43905
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43906
|
+
"button",
|
|
43907
|
+
{
|
|
43908
|
+
type: "button",
|
|
43909
|
+
onClick: applyDraft,
|
|
43910
|
+
"aria-label": t("tableMenu.apply"),
|
|
43911
|
+
title: t("tableMenu.apply"),
|
|
43912
|
+
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",
|
|
43913
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(import_lucide_react59.Check, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
43914
|
+
}
|
|
43915
|
+
),
|
|
43916
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43917
|
+
"button",
|
|
43918
|
+
{
|
|
43919
|
+
type: "button",
|
|
43920
|
+
onClick: () => {
|
|
43921
|
+
convertSelectedTableCellFormulaToValue(editor);
|
|
43922
|
+
setDraftState(null);
|
|
43923
|
+
},
|
|
43924
|
+
"aria-label": t("tableMenu.convertToValue"),
|
|
43925
|
+
title: t("tableMenu.convertToValue"),
|
|
43926
|
+
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",
|
|
43927
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(import_lucide_react59.Hash, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
43928
|
+
}
|
|
43929
|
+
),
|
|
43930
|
+
/* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
|
|
43931
|
+
"button",
|
|
43932
|
+
{
|
|
43933
|
+
type: "button",
|
|
43934
|
+
onClick: () => {
|
|
43935
|
+
clearSelectedTableCellFormula(editor);
|
|
43936
|
+
setDraftState(null);
|
|
43937
|
+
},
|
|
43938
|
+
"aria-label": t("tableMenu.clearCell"),
|
|
43939
|
+
title: t("tableMenu.clearCell"),
|
|
43940
|
+
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",
|
|
43941
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(import_lucide_react59.Trash2, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
43942
|
+
}
|
|
43943
|
+
)
|
|
43944
|
+
]
|
|
43945
|
+
}
|
|
43946
|
+
);
|
|
43947
|
+
}
|
|
43948
|
+
|
|
43949
|
+
// src/components/UEditor/UEditor.tsx
|
|
43950
|
+
var import_jsx_runtime101 = require("react/jsx-runtime");
|
|
43951
|
+
var UEditor = import_react82.default.forwardRef(({
|
|
43391
43952
|
content = "",
|
|
43392
43953
|
onChange,
|
|
43393
43954
|
onHtmlChange,
|
|
@@ -43405,6 +43966,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43405
43966
|
autofocus = false,
|
|
43406
43967
|
showToolbar = true,
|
|
43407
43968
|
showBubbleMenu = true,
|
|
43969
|
+
showFloatingMenu = false,
|
|
43408
43970
|
showCharacterCount = true,
|
|
43409
43971
|
showFooter = true,
|
|
43410
43972
|
maxCharacters,
|
|
@@ -43428,14 +43990,14 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43428
43990
|
}, ref) => {
|
|
43429
43991
|
const t = useSmartTranslations("UEditor");
|
|
43430
43992
|
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 =
|
|
43993
|
+
const inFlightPrepareRef = (0, import_react82.useRef)(null);
|
|
43994
|
+
const lastAppliedContentRef = (0, import_react82.useRef)(content ?? "");
|
|
43995
|
+
const scheduledFormulaRecalculateRef = (0, import_react82.useRef)(false);
|
|
43996
|
+
const editorInstanceRef = (0, import_react82.useRef)(null);
|
|
43997
|
+
const formulaRangePickRef = (0, import_react82.useRef)(null);
|
|
43998
|
+
const formulaRangeSurfaceRef = (0, import_react82.useRef)(null);
|
|
43999
|
+
const [formulaRangeHighlight, setFormulaRangeHighlight] = import_react82.default.useState(null);
|
|
44000
|
+
const scheduleFormulaRecalculate = import_react82.default.useCallback((editor2, options) => {
|
|
43439
44001
|
if (editor2.isDestroyed || scheduledFormulaRecalculateRef.current) return;
|
|
43440
44002
|
if (!options?.force && isEditingTableFormulaText(editor2)) return;
|
|
43441
44003
|
scheduledFormulaRecalculateRef.current = true;
|
|
@@ -43446,7 +44008,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43446
44008
|
}
|
|
43447
44009
|
});
|
|
43448
44010
|
}, []);
|
|
43449
|
-
const resolvedUploadFile = (0,
|
|
44011
|
+
const resolvedUploadFile = (0, import_react82.useMemo)(() => {
|
|
43450
44012
|
if (uploadFile) return uploadFile;
|
|
43451
44013
|
if (uploadFileForSave) {
|
|
43452
44014
|
return async (file) => {
|
|
@@ -43456,7 +44018,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43456
44018
|
}
|
|
43457
44019
|
return uploadImage;
|
|
43458
44020
|
}, [uploadFile, uploadFileForSave, uploadImage]);
|
|
43459
|
-
const extensions = (0,
|
|
44021
|
+
const extensions = (0, import_react82.useMemo)(
|
|
43460
44022
|
() => [
|
|
43461
44023
|
...buildUEditorExtensions({
|
|
43462
44024
|
placeholder: effectivePlaceholder,
|
|
@@ -43475,11 +44037,11 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43475
44037
|
],
|
|
43476
44038
|
[effectivePlaceholder, t, maxCharacters, uploadImage, resolvedUploadFile, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable, fetchMetadata, extraExtensions]
|
|
43477
44039
|
);
|
|
43478
|
-
const syncFormulaRangeHighlight =
|
|
44040
|
+
const syncFormulaRangeHighlight = import_react82.default.useCallback((pickState) => {
|
|
43479
44041
|
const container = formulaRangeSurfaceRef.current;
|
|
43480
44042
|
setFormulaRangeHighlight(container && pickState ? getFormulaRangePickHighlight(container, pickState) : null);
|
|
43481
44043
|
}, []);
|
|
43482
|
-
const editor = (0,
|
|
44044
|
+
const editor = (0, import_react83.useEditor)({
|
|
43483
44045
|
immediatelyRender: false,
|
|
43484
44046
|
extensions,
|
|
43485
44047
|
content,
|
|
@@ -43524,9 +44086,9 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43524
44086
|
if (formulaContext && event.key === "Enter") {
|
|
43525
44087
|
event.preventDefault();
|
|
43526
44088
|
event.stopPropagation();
|
|
43527
|
-
const
|
|
43528
|
-
if (
|
|
43529
|
-
recalculateActiveTableFormulas(
|
|
44089
|
+
const activeEditor2 = editorInstanceRef.current;
|
|
44090
|
+
if (activeEditor2 && !isDraftTableFormula(formulaContext.formula)) {
|
|
44091
|
+
recalculateActiveTableFormulas(activeEditor2);
|
|
43530
44092
|
}
|
|
43531
44093
|
return true;
|
|
43532
44094
|
}
|
|
@@ -43536,6 +44098,13 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43536
44098
|
cancelFormulaEditing(_view);
|
|
43537
44099
|
return true;
|
|
43538
44100
|
}
|
|
44101
|
+
const activeEditor = editorInstanceRef.current;
|
|
44102
|
+
if (activeEditor && (event.key === "Backspace" || event.key === "Delete") && getSelectedTableFormulaCell(activeEditor)) {
|
|
44103
|
+
event.preventDefault();
|
|
44104
|
+
event.stopPropagation();
|
|
44105
|
+
clearSelectedTableCellFormula(activeEditor);
|
|
44106
|
+
return true;
|
|
44107
|
+
}
|
|
43539
44108
|
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
43540
44109
|
event.stopPropagation();
|
|
43541
44110
|
}
|
|
@@ -43546,7 +44115,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43546
44115
|
if (event.button !== 0) return false;
|
|
43547
44116
|
const target = resolveEventElement(event.target);
|
|
43548
44117
|
const anchor = target?.closest?.("a[href]");
|
|
43549
|
-
const href = anchor?.getAttribute("href") ?? "";
|
|
44118
|
+
const href = sanitizeUEditorUrl(anchor?.getAttribute("href") ?? "", "link");
|
|
43550
44119
|
if (!href) return false;
|
|
43551
44120
|
if (editable) return false;
|
|
43552
44121
|
if (!view.state.selection.empty) return false;
|
|
@@ -43572,11 +44141,13 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43572
44141
|
onSelectionUpdate: ({ editor: editor2 }) => {
|
|
43573
44142
|
scheduleFormulaRecalculate(editor2);
|
|
43574
44143
|
},
|
|
43575
|
-
onBlur: ({ editor: editor2 }) => {
|
|
44144
|
+
onBlur: ({ editor: editor2, event }) => {
|
|
44145
|
+
const nextTarget = event.relatedTarget;
|
|
44146
|
+
if (nextTarget instanceof Element && nextTarget.closest("[data-ueditor-formula-bar]")) return;
|
|
43576
44147
|
scheduleFormulaRecalculate(editor2, { force: true });
|
|
43577
44148
|
}
|
|
43578
44149
|
});
|
|
43579
|
-
(0,
|
|
44150
|
+
(0, import_react82.useEffect)(() => {
|
|
43580
44151
|
editorInstanceRef.current = editor;
|
|
43581
44152
|
return () => {
|
|
43582
44153
|
if (editorInstanceRef.current === editor) editorInstanceRef.current = null;
|
|
@@ -43592,7 +44163,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43592
44163
|
apply: t("tableMenu.apply"),
|
|
43593
44164
|
cancel: t("imageInput.cancelBtn")
|
|
43594
44165
|
});
|
|
43595
|
-
(0,
|
|
44166
|
+
(0, import_react82.useImperativeHandle)(
|
|
43596
44167
|
ref,
|
|
43597
44168
|
() => ({
|
|
43598
44169
|
editor,
|
|
@@ -43617,7 +44188,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43617
44188
|
}),
|
|
43618
44189
|
[content, editor, uploadImageForSave, uploadFileForSave, uploadImageConcurrency]
|
|
43619
44190
|
);
|
|
43620
|
-
(0,
|
|
44191
|
+
(0, import_react82.useEffect)(() => {
|
|
43621
44192
|
if (!editor) return;
|
|
43622
44193
|
queueMicrotask(() => {
|
|
43623
44194
|
if (!editor.isDestroyed) {
|
|
@@ -43625,7 +44196,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43625
44196
|
}
|
|
43626
44197
|
});
|
|
43627
44198
|
}, [editor]);
|
|
43628
|
-
(0,
|
|
44199
|
+
(0, import_react82.useEffect)(() => {
|
|
43629
44200
|
if (!editor) return;
|
|
43630
44201
|
const nextContent = content ?? "";
|
|
43631
44202
|
if (lastAppliedContentRef.current === nextContent) return;
|
|
@@ -43644,7 +44215,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43644
44215
|
}
|
|
43645
44216
|
}, [content, editor]);
|
|
43646
44217
|
if (!editor) {
|
|
43647
|
-
return /* @__PURE__ */ (0,
|
|
44218
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43648
44219
|
"div",
|
|
43649
44220
|
{
|
|
43650
44221
|
className: cn("w-full border bg-background flex items-center justify-center text-muted-foreground", className),
|
|
@@ -43653,7 +44224,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43653
44224
|
}
|
|
43654
44225
|
);
|
|
43655
44226
|
}
|
|
43656
|
-
return /* @__PURE__ */ (0,
|
|
44227
|
+
return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)(
|
|
43657
44228
|
"div",
|
|
43658
44229
|
{
|
|
43659
44230
|
className: cn(
|
|
@@ -43669,7 +44240,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43669
44240
|
className
|
|
43670
44241
|
),
|
|
43671
44242
|
children: [
|
|
43672
|
-
editable && showMenuBar && /* @__PURE__ */ (0,
|
|
44243
|
+
editable && showMenuBar && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43673
44244
|
MenuBar,
|
|
43674
44245
|
{
|
|
43675
44246
|
editor,
|
|
@@ -43684,7 +44255,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43684
44255
|
onPreview
|
|
43685
44256
|
}
|
|
43686
44257
|
),
|
|
43687
|
-
editable && showToolbar && /* @__PURE__ */ (0,
|
|
44258
|
+
editable && showToolbar && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43688
44259
|
EditorToolbar,
|
|
43689
44260
|
{
|
|
43690
44261
|
editor,
|
|
@@ -43699,7 +44270,8 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43699
44270
|
letterSpacings
|
|
43700
44271
|
}
|
|
43701
44272
|
),
|
|
43702
|
-
editable &&
|
|
44273
|
+
editable && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(TableFormulaBar, { editor }),
|
|
44274
|
+
editable && showBubbleMenu && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43703
44275
|
CustomBubbleMenu,
|
|
43704
44276
|
{
|
|
43705
44277
|
editor,
|
|
@@ -43707,7 +44279,8 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43707
44279
|
lineHeights
|
|
43708
44280
|
}
|
|
43709
44281
|
),
|
|
43710
|
-
/* @__PURE__ */ (0,
|
|
44282
|
+
editable && showFloatingMenu && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(CustomFloatingMenu, { editor }),
|
|
44283
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsxs)(
|
|
43711
44284
|
"div",
|
|
43712
44285
|
{
|
|
43713
44286
|
ref: (node) => {
|
|
@@ -43720,7 +44293,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43720
44293
|
maxHeight
|
|
43721
44294
|
},
|
|
43722
44295
|
children: [
|
|
43723
|
-
/* @__PURE__ */ (0,
|
|
44296
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43724
44297
|
"span",
|
|
43725
44298
|
{
|
|
43726
44299
|
ref: tableColumnGuideRef,
|
|
@@ -43728,7 +44301,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43728
44301
|
className: "pointer-events-none absolute z-20 bg-primary opacity-0 transition-opacity duration-100"
|
|
43729
44302
|
}
|
|
43730
44303
|
),
|
|
43731
|
-
/* @__PURE__ */ (0,
|
|
44304
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43732
44305
|
"span",
|
|
43733
44306
|
{
|
|
43734
44307
|
ref: tableRowGuideRef,
|
|
@@ -43736,7 +44309,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43736
44309
|
className: "pointer-events-none absolute z-20 bg-primary opacity-0 transition-opacity duration-100"
|
|
43737
44310
|
}
|
|
43738
44311
|
),
|
|
43739
|
-
/* @__PURE__ */ (0,
|
|
44312
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43740
44313
|
"span",
|
|
43741
44314
|
{
|
|
43742
44315
|
ref: activeTableCellHighlightRef,
|
|
@@ -43745,20 +44318,24 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43745
44318
|
className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10"
|
|
43746
44319
|
}
|
|
43747
44320
|
),
|
|
43748
|
-
/* @__PURE__ */ (0,
|
|
44321
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43749
44322
|
"div",
|
|
43750
44323
|
{
|
|
43751
44324
|
ref: formulaCoordinateOverlayRef,
|
|
43752
44325
|
"data-ueditor-formula-coordinate-overlay": "",
|
|
43753
|
-
className: "pointer-events-none absolute inset-0 z-[
|
|
44326
|
+
className: "pointer-events-none absolute inset-0 z-[35] hidden overflow-visible"
|
|
43754
44327
|
}
|
|
43755
44328
|
),
|
|
43756
|
-
formulaRangeHighlight && /* @__PURE__ */ (0,
|
|
44329
|
+
formulaRangeHighlight && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
43757
44330
|
"span",
|
|
43758
44331
|
{
|
|
43759
44332
|
"aria-hidden": "true",
|
|
43760
44333
|
"data-ueditor-formula-range-highlight": "",
|
|
43761
|
-
|
|
44334
|
+
"data-ueditor-formula-range-blocked": formulaRangeHighlight.blocked ? "true" : void 0,
|
|
44335
|
+
className: cn(
|
|
44336
|
+
"pointer-events-none absolute z-20 rounded-[2px] border-2",
|
|
44337
|
+
formulaRangeHighlight.blocked ? "border-destructive bg-destructive/15" : "border-primary bg-primary/10"
|
|
44338
|
+
),
|
|
43762
44339
|
style: {
|
|
43763
44340
|
left: formulaRangeHighlight.left,
|
|
43764
44341
|
top: formulaRangeHighlight.top,
|
|
@@ -43767,9 +44344,9 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43767
44344
|
}
|
|
43768
44345
|
}
|
|
43769
44346
|
),
|
|
43770
|
-
editable && /* @__PURE__ */ (0,
|
|
43771
|
-
/* @__PURE__ */ (0,
|
|
43772
|
-
|
|
44347
|
+
editable && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(TableControls, { editor, containerRef: editorContentRef }),
|
|
44348
|
+
/* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
|
|
44349
|
+
import_react83.EditorContent,
|
|
43773
44350
|
{
|
|
43774
44351
|
editor,
|
|
43775
44352
|
className: "min-h-full"
|
|
@@ -43778,7 +44355,7 @@ var UEditor = import_react80.default.forwardRef(({
|
|
|
43778
44355
|
]
|
|
43779
44356
|
}
|
|
43780
44357
|
),
|
|
43781
|
-
showFooter && showCharacterCount && /* @__PURE__ */ (0,
|
|
44358
|
+
showFooter && showCharacterCount && /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(CharacterCountDisplay, { editor, maxCharacters })
|
|
43782
44359
|
]
|
|
43783
44360
|
}
|
|
43784
44361
|
);
|