@tarviks/lexical-rich-editor 1.1.0 → 1.2.1
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/dist/index.css +80 -34
- package/dist/index.css.map +1 -1
- package/dist/index.js +1889 -1297
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1892 -1300
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -636,7 +636,6 @@ var init_ImageComponent = __esm({
|
|
|
636
636
|
editor,
|
|
637
637
|
buttonRef,
|
|
638
638
|
imageRef,
|
|
639
|
-
maxWidth,
|
|
640
639
|
onResizeStart,
|
|
641
640
|
onResizeEnd,
|
|
642
641
|
captionsEnabled: !isLoadError && captionsEnabled
|
|
@@ -787,6 +786,9 @@ var init_ImageNode = __esm({
|
|
|
787
786
|
const writable = this.getWritable();
|
|
788
787
|
writable.__width = width;
|
|
789
788
|
writable.__height = height;
|
|
789
|
+
if (typeof width === "number" && width > writable.__maxWidth) {
|
|
790
|
+
writable.__maxWidth = width;
|
|
791
|
+
}
|
|
790
792
|
}
|
|
791
793
|
setShowCaption(showCaption) {
|
|
792
794
|
const writable = this.getWritable();
|
|
@@ -876,6 +878,7 @@ __export(InlineImageComponent_exports, {
|
|
|
876
878
|
var imageCache2, useSuspenseImage2, LazyImage2, InlineImageComponent, InlineImageComponent_default;
|
|
877
879
|
var init_InlineImageComponent = __esm({
|
|
878
880
|
"src/Nodes/InlineImageComponent.tsx"() {
|
|
881
|
+
init_ImageResizer();
|
|
879
882
|
init_InlineImage();
|
|
880
883
|
init_InlineImageNode();
|
|
881
884
|
imageCache2 = /* @__PURE__ */ new Set();
|
|
@@ -918,6 +921,29 @@ var init_InlineImageComponent = __esm({
|
|
|
918
921
|
const buttonRef = React9.useRef(null);
|
|
919
922
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
920
923
|
const isEditable = useLexicalEditable.useLexicalEditable();
|
|
924
|
+
const [isResizing, setIsResizing] = React9.useState(false);
|
|
925
|
+
const onResizeEnd = (nextWidth, nextHeight) => {
|
|
926
|
+
setTimeout(() => {
|
|
927
|
+
setIsResizing(false);
|
|
928
|
+
}, 200);
|
|
929
|
+
editor.update(() => {
|
|
930
|
+
const node = lexical.$getNodeByKey(nodeKey);
|
|
931
|
+
if ($isInlineImageNode(node)) {
|
|
932
|
+
node.setWidthAndHeight(nextWidth, nextHeight);
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
};
|
|
936
|
+
const onResizeStart = () => {
|
|
937
|
+
setIsResizing(true);
|
|
938
|
+
};
|
|
939
|
+
const setShowCaption = (show) => {
|
|
940
|
+
editor.update(() => {
|
|
941
|
+
const node = lexical.$getNodeByKey(nodeKey);
|
|
942
|
+
if ($isInlineImageNode(node)) {
|
|
943
|
+
node.setShowCaption(show);
|
|
944
|
+
}
|
|
945
|
+
});
|
|
946
|
+
};
|
|
921
947
|
const $onDelete = React9.useCallback(
|
|
922
948
|
(payload) => {
|
|
923
949
|
const deleteSelection = lexical.$getSelection();
|
|
@@ -993,6 +1019,9 @@ var init_InlineImageComponent = __esm({
|
|
|
993
1019
|
lexical.CLICK_COMMAND,
|
|
994
1020
|
(payload) => {
|
|
995
1021
|
const event = payload;
|
|
1022
|
+
if (isResizing) {
|
|
1023
|
+
return true;
|
|
1024
|
+
}
|
|
996
1025
|
if (event.target === imageRef.current) {
|
|
997
1026
|
if (event.shiftKey) {
|
|
998
1027
|
setSelected(!isSelected);
|
|
@@ -1041,6 +1070,7 @@ var init_InlineImageComponent = __esm({
|
|
|
1041
1070
|
}, [
|
|
1042
1071
|
clearSelection,
|
|
1043
1072
|
editor,
|
|
1073
|
+
isResizing,
|
|
1044
1074
|
isSelected,
|
|
1045
1075
|
nodeKey,
|
|
1046
1076
|
$onDelete,
|
|
@@ -1048,20 +1078,35 @@ var init_InlineImageComponent = __esm({
|
|
|
1048
1078
|
$onEscape,
|
|
1049
1079
|
setSelected
|
|
1050
1080
|
]);
|
|
1051
|
-
const draggable = isSelected && lexical.$isNodeSelection(selection);
|
|
1052
|
-
const isFocused = isSelected && isEditable;
|
|
1053
|
-
return /* @__PURE__ */ jsxRuntime.jsx(React9.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1081
|
+
const draggable = isSelected && lexical.$isNodeSelection(selection) && !isResizing;
|
|
1082
|
+
const isFocused = (isSelected || isResizing) && isEditable;
|
|
1083
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React9.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1084
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { draggable, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1085
|
+
LazyImage2,
|
|
1086
|
+
{
|
|
1087
|
+
className: isFocused ? `focused ${lexical.$isNodeSelection(selection) ? "draggable" : ""}` : null,
|
|
1088
|
+
src,
|
|
1089
|
+
altText,
|
|
1090
|
+
imageRef,
|
|
1091
|
+
width,
|
|
1092
|
+
height,
|
|
1093
|
+
position
|
|
1094
|
+
}
|
|
1095
|
+
) }),
|
|
1096
|
+
isFocused && lexical.$isNodeSelection(selection) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1097
|
+
ImageResizer_default,
|
|
1098
|
+
{
|
|
1099
|
+
showCaption,
|
|
1100
|
+
setShowCaption,
|
|
1101
|
+
editor,
|
|
1102
|
+
buttonRef,
|
|
1103
|
+
imageRef,
|
|
1104
|
+
onResizeStart,
|
|
1105
|
+
onResizeEnd,
|
|
1106
|
+
captionsEnabled: false
|
|
1107
|
+
}
|
|
1108
|
+
)
|
|
1109
|
+
] }) });
|
|
1065
1110
|
};
|
|
1066
1111
|
InlineImageComponent_default = InlineImageComponent;
|
|
1067
1112
|
}
|
|
@@ -1249,6 +1294,46 @@ var ContentEditorLevel = /* @__PURE__ */ ((ContentEditorLevel2) => {
|
|
|
1249
1294
|
ContentEditorLevel2["Pro"] = "pro";
|
|
1250
1295
|
return ContentEditorLevel2;
|
|
1251
1296
|
})(ContentEditorLevel || {});
|
|
1297
|
+
|
|
1298
|
+
// src/Types/PageSetup.ts
|
|
1299
|
+
var DEFAULT_PAGE_SETUP = {
|
|
1300
|
+
size: "pageless",
|
|
1301
|
+
orientation: "portrait",
|
|
1302
|
+
margin: "normal"
|
|
1303
|
+
};
|
|
1304
|
+
var PAGE_SIZE_OPTIONS = [
|
|
1305
|
+
{ key: "a4", label: 'A4 (8.27" x 11.69")', widthIn: 8.27, heightIn: 11.69 },
|
|
1306
|
+
{ key: "letter", label: 'Letter (8.5" x 11")', widthIn: 8.5, heightIn: 11 },
|
|
1307
|
+
{ key: "legal", label: 'Legal (8.5" x 14")', widthIn: 8.5, heightIn: 14 },
|
|
1308
|
+
{ key: "tabloid", label: 'Tabloid (11" x 17")', widthIn: 11, heightIn: 17 },
|
|
1309
|
+
{ key: "a3", label: 'A3 (11.69" x 16.54")', widthIn: 11.69, heightIn: 16.54 },
|
|
1310
|
+
{ key: "a5", label: 'A5 (5.83" x 8.27")', widthIn: 5.83, heightIn: 8.27 },
|
|
1311
|
+
{ key: "b4", label: 'B4 (9.84" x 13.90")', widthIn: 9.84, heightIn: 13.9 },
|
|
1312
|
+
{ key: "b5", label: 'B5 (6.93" x 9.84")', widthIn: 6.93, heightIn: 9.84 },
|
|
1313
|
+
{ key: "statement", label: 'Statement (5.5" x 8.5")', widthIn: 5.5, heightIn: 8.5 },
|
|
1314
|
+
{ key: "executive", label: 'Executive (7.25" x 10.5")', widthIn: 7.25, heightIn: 10.5 },
|
|
1315
|
+
{ key: "folio", label: 'Folio (8.5" x 13")', widthIn: 8.5, heightIn: 13 }
|
|
1316
|
+
];
|
|
1317
|
+
var MARGIN_OPTIONS = [
|
|
1318
|
+
{ key: "narrow", label: 'Narrow (0.25")', valueIn: 0.25 },
|
|
1319
|
+
{ key: "normal", label: 'Normal (0.4")', valueIn: 0.4 },
|
|
1320
|
+
{ key: "moderate", label: 'Moderate (0.75")', valueIn: 0.75 },
|
|
1321
|
+
{ key: "wide", label: 'Wide (1")', valueIn: 1 }
|
|
1322
|
+
];
|
|
1323
|
+
var CSS_PX_PER_INCH = 96;
|
|
1324
|
+
function resolvePageCanvasMetrics(value) {
|
|
1325
|
+
const margin = MARGIN_OPTIONS.find((o) => o.key === value.margin) ?? MARGIN_OPTIONS[1];
|
|
1326
|
+
if (value.size === "pageless") {
|
|
1327
|
+
return { widthPx: void 0, paddingPx: 20 };
|
|
1328
|
+
}
|
|
1329
|
+
const size = PAGE_SIZE_OPTIONS.find((o) => o.key === value.size);
|
|
1330
|
+
if (!size) return { widthPx: void 0, paddingPx: 20 };
|
|
1331
|
+
const widthIn = value.orientation === "landscape" ? size.heightIn : size.widthIn;
|
|
1332
|
+
return {
|
|
1333
|
+
widthPx: Math.round(widthIn * CSS_PX_PER_INCH),
|
|
1334
|
+
paddingPx: Math.round(margin.valueIn * CSS_PX_PER_INCH)
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1252
1337
|
var AutocompleteNode = class _AutocompleteNode extends lexical.TextNode {
|
|
1253
1338
|
static getType() {
|
|
1254
1339
|
return "autocomplete";
|
|
@@ -2487,99 +2572,329 @@ function CharacterStylesPopupPlugin(props) {
|
|
|
2487
2572
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
2488
2573
|
return useCharacterStylesPopup(editor, props);
|
|
2489
2574
|
}
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2575
|
+
|
|
2576
|
+
// src/Utils/Sanitize.ts
|
|
2577
|
+
var DROP_ENTIRELY = /* @__PURE__ */ new Set([
|
|
2578
|
+
"script",
|
|
2579
|
+
"noscript",
|
|
2580
|
+
"style",
|
|
2581
|
+
"object",
|
|
2582
|
+
"embed",
|
|
2583
|
+
"form",
|
|
2584
|
+
"input",
|
|
2585
|
+
"button",
|
|
2586
|
+
"select",
|
|
2587
|
+
"textarea",
|
|
2588
|
+
"meta",
|
|
2589
|
+
"link",
|
|
2590
|
+
"base"
|
|
2591
|
+
]);
|
|
2592
|
+
var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
2593
|
+
// Block
|
|
2594
|
+
"p",
|
|
2595
|
+
"h1",
|
|
2596
|
+
"h2",
|
|
2597
|
+
"h3",
|
|
2598
|
+
"h4",
|
|
2599
|
+
"h5",
|
|
2600
|
+
"h6",
|
|
2601
|
+
"ul",
|
|
2602
|
+
"ol",
|
|
2603
|
+
"li",
|
|
2604
|
+
"blockquote",
|
|
2605
|
+
"pre",
|
|
2606
|
+
"div",
|
|
2607
|
+
"table",
|
|
2608
|
+
"thead",
|
|
2609
|
+
"tbody",
|
|
2610
|
+
"tfoot",
|
|
2611
|
+
"tr",
|
|
2612
|
+
"td",
|
|
2613
|
+
"th",
|
|
2614
|
+
// Inline
|
|
2615
|
+
"span",
|
|
2616
|
+
"a",
|
|
2617
|
+
"strong",
|
|
2618
|
+
"b",
|
|
2619
|
+
"em",
|
|
2620
|
+
"i",
|
|
2621
|
+
"u",
|
|
2622
|
+
"s",
|
|
2623
|
+
"del",
|
|
2624
|
+
"strike",
|
|
2625
|
+
"sub",
|
|
2626
|
+
"sup",
|
|
2627
|
+
"mark",
|
|
2628
|
+
"code",
|
|
2629
|
+
"br",
|
|
2630
|
+
"hr",
|
|
2631
|
+
// Media / embeds
|
|
2632
|
+
"img",
|
|
2633
|
+
"iframe"
|
|
2634
|
+
]);
|
|
2635
|
+
var ALLOWED_ATTRS = /* @__PURE__ */ new Set([
|
|
2636
|
+
// Presentation
|
|
2637
|
+
"class",
|
|
2638
|
+
"style",
|
|
2639
|
+
"dir",
|
|
2640
|
+
"lang",
|
|
2641
|
+
// Anchors
|
|
2642
|
+
"href",
|
|
2643
|
+
"target",
|
|
2644
|
+
"rel",
|
|
2645
|
+
// Images
|
|
2646
|
+
"src",
|
|
2647
|
+
"alt",
|
|
2648
|
+
"width",
|
|
2649
|
+
"height",
|
|
2650
|
+
// Tables
|
|
2651
|
+
"colspan",
|
|
2652
|
+
"rowspan",
|
|
2653
|
+
// Lists — <ol type="a"> and <ol start="2">
|
|
2654
|
+
"start",
|
|
2655
|
+
"type",
|
|
2656
|
+
// Lexical-internal data markers
|
|
2657
|
+
"data-lex-block",
|
|
2658
|
+
"data-kind",
|
|
2659
|
+
"data-lexical-decorator",
|
|
2660
|
+
// Misc
|
|
2661
|
+
"title",
|
|
2662
|
+
"allowfullscreen"
|
|
2663
|
+
]);
|
|
2664
|
+
var DANGEROUS_URL = /^\s*(javascript|data\s*:|vbscript)/i;
|
|
2665
|
+
function sanitizeElement(el) {
|
|
2666
|
+
for (const child of Array.from(el.children)) {
|
|
2667
|
+
sanitizeElement(child);
|
|
2534
2668
|
}
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
var setFloatingElemPositionForLinkEditor = (targetRect, floatingElem, anchorElem, verticalGap = VERTICAL_GAP, horizontalOffset = HORIZONTAL_OFFSET) => {
|
|
2539
|
-
const scrollerElem = anchorElem.parentElement;
|
|
2540
|
-
if (targetRect === null || !scrollerElem) {
|
|
2541
|
-
floatingElem.style.opacity = "0";
|
|
2542
|
-
floatingElem.style.transform = "translate(-10000px, -10000px)";
|
|
2669
|
+
const tag = el.tagName.toLowerCase();
|
|
2670
|
+
if (DROP_ENTIRELY.has(tag)) {
|
|
2671
|
+
el.parentNode?.removeChild(el);
|
|
2543
2672
|
return;
|
|
2544
2673
|
}
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
}
|
|
2553
|
-
if (left + floatingElemRect.width > editorScrollerRect.right) {
|
|
2554
|
-
left = editorScrollerRect.right - floatingElemRect.width - horizontalOffset;
|
|
2674
|
+
if (tag === "iframe") {
|
|
2675
|
+
const src = el.getAttribute("src") ?? "";
|
|
2676
|
+
const isYouTube = /^\s*https:\/\/(www\.)?(youtube\.com|youtube-nocookie\.com)\/embed\/[^?&/]+/i.test(src);
|
|
2677
|
+
if (!isYouTube) {
|
|
2678
|
+
el.parentNode?.removeChild(el);
|
|
2679
|
+
return;
|
|
2680
|
+
}
|
|
2555
2681
|
}
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
floatingElem.style.transform = `translate(${left}px, ${top}px)`;
|
|
2560
|
-
};
|
|
2561
|
-
var SUPPORTED_URL_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
2562
|
-
"http:",
|
|
2563
|
-
"https:",
|
|
2564
|
-
"mailto:",
|
|
2565
|
-
"sms:",
|
|
2566
|
-
"tel:"
|
|
2567
|
-
]);
|
|
2568
|
-
var sanitizeUrl = (url) => {
|
|
2569
|
-
try {
|
|
2570
|
-
const parsedUrl = new URL(url);
|
|
2571
|
-
if (!SUPPORTED_URL_PROTOCOLS.has(parsedUrl.protocol)) {
|
|
2572
|
-
return "about:blank";
|
|
2682
|
+
if (!ALLOWED_TAGS.has(tag)) {
|
|
2683
|
+
while (el.firstChild) {
|
|
2684
|
+
el.parentNode?.insertBefore(el.firstChild, el);
|
|
2573
2685
|
}
|
|
2574
|
-
|
|
2575
|
-
return
|
|
2686
|
+
el.parentNode?.removeChild(el);
|
|
2687
|
+
return;
|
|
2576
2688
|
}
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2689
|
+
for (const { name, value } of Array.from(el.attributes)) {
|
|
2690
|
+
const lname = name.toLowerCase();
|
|
2691
|
+
if (!ALLOWED_ATTRS.has(lname)) {
|
|
2692
|
+
el.removeAttribute(name);
|
|
2693
|
+
continue;
|
|
2694
|
+
}
|
|
2695
|
+
if (lname === "href" || lname === "src") {
|
|
2696
|
+
if (DANGEROUS_URL.test(value)) {
|
|
2697
|
+
el.removeAttribute(name);
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
if (lname === "style") {
|
|
2701
|
+
const safe = value.replace(/expression\s*\(/gi, "(").replace(/url\s*\(\s*['"]?\s*javascript:/gi, "url(");
|
|
2702
|
+
el.setAttribute("style", safe);
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
if (tag === "a" && (el.getAttribute("target") || "").toLowerCase() === "_blank") {
|
|
2706
|
+
const rel = (el.getAttribute("rel") || "").trim();
|
|
2707
|
+
const tokens = new Set(
|
|
2708
|
+
rel.split(/\s+/).filter(Boolean).map((t) => t.toLowerCase())
|
|
2709
|
+
);
|
|
2710
|
+
tokens.add("noopener");
|
|
2711
|
+
tokens.add("noreferrer");
|
|
2712
|
+
el.setAttribute("rel", Array.from(tokens).join(" "));
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
function sanitizeHtml(html) {
|
|
2716
|
+
if (!html || typeof html !== "string") return "";
|
|
2717
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
2718
|
+
for (const child of Array.from(doc.body.children)) {
|
|
2719
|
+
sanitizeElement(child);
|
|
2720
|
+
}
|
|
2721
|
+
return doc.body.innerHTML;
|
|
2722
|
+
}
|
|
2723
|
+
function postProcessOutput(html) {
|
|
2724
|
+
if (!html) return html;
|
|
2725
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
2726
|
+
for (const inner of Array.from(doc.querySelectorAll("b > strong"))) {
|
|
2727
|
+
const outer = inner.parentElement;
|
|
2728
|
+
_mergeAttributes(inner, outer);
|
|
2729
|
+
while (inner.firstChild) outer.insertBefore(inner.firstChild, inner);
|
|
2730
|
+
outer.removeChild(inner);
|
|
2731
|
+
}
|
|
2732
|
+
for (const inner of Array.from(doc.querySelectorAll("i > em"))) {
|
|
2733
|
+
const outer = inner.parentElement;
|
|
2734
|
+
_mergeAttributes(inner, outer);
|
|
2735
|
+
while (inner.firstChild) outer.insertBefore(inner.firstChild, inner);
|
|
2736
|
+
outer.removeChild(inner);
|
|
2737
|
+
}
|
|
2738
|
+
for (const p of Array.from(doc.querySelectorAll("p"))) {
|
|
2739
|
+
const style = p.style;
|
|
2740
|
+
const hasMargin = !!(style.margin || style.marginTop || style.marginRight || style.marginBottom || style.marginLeft);
|
|
2741
|
+
if (!hasMargin) style.margin = "0";
|
|
2742
|
+
if (!style.lineHeight) style.lineHeight = "1.25";
|
|
2743
|
+
}
|
|
2744
|
+
return doc.body.innerHTML;
|
|
2745
|
+
}
|
|
2746
|
+
function _mergeAttributes(src, dst) {
|
|
2747
|
+
for (const { name, value } of Array.from(src.attributes)) {
|
|
2748
|
+
if (name === "style") {
|
|
2749
|
+
const prev = dst.getAttribute("style") || "";
|
|
2750
|
+
dst.setAttribute("style", prev ? `${prev}; ${value}` : value);
|
|
2751
|
+
} else if (name === "class") {
|
|
2752
|
+
const prev = dst.getAttribute("class") || "";
|
|
2753
|
+
dst.setAttribute("class", prev ? `${prev} ${value}` : value);
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
var BLOCK_TAGS = /* @__PURE__ */ new Set([
|
|
2758
|
+
"p",
|
|
2759
|
+
"h1",
|
|
2760
|
+
"h2",
|
|
2761
|
+
"h3",
|
|
2762
|
+
"h4",
|
|
2763
|
+
"h5",
|
|
2764
|
+
"h6",
|
|
2765
|
+
"div",
|
|
2766
|
+
"ul",
|
|
2767
|
+
"ol",
|
|
2768
|
+
"li",
|
|
2769
|
+
"table",
|
|
2770
|
+
"blockquote",
|
|
2771
|
+
"pre",
|
|
2772
|
+
"hr"
|
|
2773
|
+
]);
|
|
2774
|
+
function normalizeToBlockHtml(html) {
|
|
2775
|
+
if (!html) return "";
|
|
2776
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
2777
|
+
const body = doc.body;
|
|
2778
|
+
const childNodes = Array.from(body.childNodes);
|
|
2779
|
+
const needsWrap = childNodes.some((node) => {
|
|
2780
|
+
if (node.nodeType === Node.TEXT_NODE) return !!node.nodeValue?.trim();
|
|
2781
|
+
if (node.nodeType === Node.ELEMENT_NODE)
|
|
2782
|
+
return !BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
2783
|
+
return false;
|
|
2784
|
+
});
|
|
2785
|
+
if (!needsWrap) return html;
|
|
2786
|
+
while (body.firstChild) body.removeChild(body.firstChild);
|
|
2787
|
+
let pendingP = null;
|
|
2788
|
+
for (const node of childNodes) {
|
|
2789
|
+
const isBlock = node.nodeType === Node.ELEMENT_NODE && BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
2790
|
+
const isWhitespace = node.nodeType === Node.TEXT_NODE && !node.nodeValue?.trim();
|
|
2791
|
+
if (isBlock) {
|
|
2792
|
+
if (pendingP) {
|
|
2793
|
+
body.appendChild(pendingP);
|
|
2794
|
+
pendingP = null;
|
|
2795
|
+
}
|
|
2796
|
+
body.appendChild(node);
|
|
2797
|
+
} else if (!isWhitespace) {
|
|
2798
|
+
if (!pendingP) pendingP = doc.createElement("p");
|
|
2799
|
+
pendingP.appendChild(node);
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
if (pendingP) body.appendChild(pendingP);
|
|
2803
|
+
return body.innerHTML;
|
|
2804
|
+
}
|
|
2805
|
+
var CustomOnChangePlugin = ({ value, onChange }) => {
|
|
2806
|
+
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
2807
|
+
const initializedRef = React9.useRef(false);
|
|
2808
|
+
const onChangeRef = React9.useRef(onChange);
|
|
2809
|
+
onChangeRef.current = onChange;
|
|
2810
|
+
React9.useEffect(() => {
|
|
2811
|
+
if (!value || initializedRef.current) return;
|
|
2812
|
+
initializedRef.current = true;
|
|
2813
|
+
editor.update(() => {
|
|
2814
|
+
const root = lexical.$getRoot();
|
|
2815
|
+
root.clear();
|
|
2816
|
+
const parser = new DOMParser();
|
|
2817
|
+
const dom = parser.parseFromString(value, "text/html");
|
|
2818
|
+
const nodes = html.$generateNodesFromDOM(editor, dom);
|
|
2819
|
+
root.append(...nodes);
|
|
2820
|
+
lexical.$setSelection(null);
|
|
2821
|
+
});
|
|
2822
|
+
}, [editor, value]);
|
|
2823
|
+
const handleChange = React9.useCallback((editorState) => {
|
|
2824
|
+
editorState.read(() => {
|
|
2825
|
+
onChangeRef.current(postProcessOutput(html.$generateHtmlFromNodes(editor)));
|
|
2826
|
+
});
|
|
2827
|
+
}, [editor]);
|
|
2828
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2829
|
+
LexicalOnChangePlugin.OnChangePlugin,
|
|
2830
|
+
{
|
|
2831
|
+
onChange: handleChange,
|
|
2832
|
+
ignoreSelectionChange: true
|
|
2833
|
+
}
|
|
2834
|
+
);
|
|
2835
|
+
};
|
|
2836
|
+
var getSelectedNode2 = (selection$1) => {
|
|
2837
|
+
const anchor = selection$1.anchor;
|
|
2838
|
+
const anchorNode = selection$1.anchor.getNode();
|
|
2839
|
+
const focus = selection$1.focus;
|
|
2840
|
+
const focusNode = selection$1.focus.getNode();
|
|
2841
|
+
if (anchorNode === focusNode) {
|
|
2842
|
+
return anchorNode;
|
|
2843
|
+
}
|
|
2844
|
+
const isBackward = selection$1.isBackward();
|
|
2845
|
+
if (isBackward) {
|
|
2846
|
+
return selection.$isAtNodeEnd(focus) ? anchorNode : focusNode;
|
|
2847
|
+
} else {
|
|
2848
|
+
return selection.$isAtNodeEnd(anchor) ? anchorNode : focusNode;
|
|
2849
|
+
}
|
|
2850
|
+
};
|
|
2851
|
+
var VERTICAL_GAP = 10;
|
|
2852
|
+
var HORIZONTAL_OFFSET = 5;
|
|
2853
|
+
var setFloatingElemPositionForLinkEditor = (targetRect, floatingElem, anchorElem, verticalGap = VERTICAL_GAP, horizontalOffset = HORIZONTAL_OFFSET) => {
|
|
2854
|
+
const scrollerElem = anchorElem.parentElement;
|
|
2855
|
+
if (targetRect === null || !scrollerElem) {
|
|
2856
|
+
floatingElem.style.opacity = "0";
|
|
2857
|
+
floatingElem.style.transform = "translate(-10000px, -10000px)";
|
|
2858
|
+
return;
|
|
2859
|
+
}
|
|
2860
|
+
const floatingElemRect = floatingElem.getBoundingClientRect();
|
|
2861
|
+
const anchorElementRect = anchorElem.getBoundingClientRect();
|
|
2862
|
+
const editorScrollerRect = scrollerElem.getBoundingClientRect();
|
|
2863
|
+
let top = targetRect.top - verticalGap;
|
|
2864
|
+
let left = targetRect.left - horizontalOffset;
|
|
2865
|
+
if (top < editorScrollerRect.top) {
|
|
2866
|
+
top += floatingElemRect.height + targetRect.height + verticalGap * 2;
|
|
2867
|
+
}
|
|
2868
|
+
if (left + floatingElemRect.width > editorScrollerRect.right) {
|
|
2869
|
+
left = editorScrollerRect.right - floatingElemRect.width - horizontalOffset;
|
|
2870
|
+
}
|
|
2871
|
+
top -= anchorElementRect.top;
|
|
2872
|
+
left -= anchorElementRect.left;
|
|
2873
|
+
floatingElem.style.opacity = "1";
|
|
2874
|
+
floatingElem.style.transform = `translate(${left}px, ${top}px)`;
|
|
2875
|
+
};
|
|
2876
|
+
var SUPPORTED_URL_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
2877
|
+
"http:",
|
|
2878
|
+
"https:",
|
|
2879
|
+
"mailto:",
|
|
2880
|
+
"sms:",
|
|
2881
|
+
"tel:"
|
|
2882
|
+
]);
|
|
2883
|
+
var sanitizeUrl = (url) => {
|
|
2884
|
+
try {
|
|
2885
|
+
const parsedUrl = new URL(url);
|
|
2886
|
+
if (!SUPPORTED_URL_PROTOCOLS.has(parsedUrl.protocol)) {
|
|
2887
|
+
return "about:blank";
|
|
2888
|
+
}
|
|
2889
|
+
} catch {
|
|
2890
|
+
return url;
|
|
2891
|
+
}
|
|
2892
|
+
return url;
|
|
2893
|
+
};
|
|
2894
|
+
var preventDefault = (event) => {
|
|
2895
|
+
event.preventDefault();
|
|
2896
|
+
};
|
|
2897
|
+
var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMode, setIsLinkEditMode }) => {
|
|
2583
2898
|
const [editedLinkUrl, setEditedLinkUrl] = React9.useState("https://");
|
|
2584
2899
|
const [lastSelection, setLastSelection] = React9.useState(null);
|
|
2585
2900
|
const [linkUrl, setLinkUrl] = React9.useState("");
|
|
@@ -2608,7 +2923,7 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
2608
2923
|
return;
|
|
2609
2924
|
}
|
|
2610
2925
|
const rootElement = editor.getRootElement();
|
|
2611
|
-
if (selection !== null && nativeSelection !== null && rootElement !== null && rootElement.contains(nativeSelection.anchorNode) && editor.isEditable()) {
|
|
2926
|
+
if (isLink && selection !== null && nativeSelection !== null && rootElement !== null && rootElement.contains(nativeSelection.anchorNode) && editor.isEditable()) {
|
|
2612
2927
|
const domRect = nativeSelection.focusNode?.parentElement?.getBoundingClientRect();
|
|
2613
2928
|
if (domRect) {
|
|
2614
2929
|
domRect.y += 40;
|
|
@@ -2624,7 +2939,7 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
2624
2939
|
setLinkUrl("");
|
|
2625
2940
|
}
|
|
2626
2941
|
return true;
|
|
2627
|
-
}, [anchorElem, editor, setIsLinkEditMode, isLinkEditMode, linkUrl]);
|
|
2942
|
+
}, [anchorElem, editor, isLink, setIsLinkEditMode, isLinkEditMode, linkUrl]);
|
|
2628
2943
|
React9.useEffect(() => {
|
|
2629
2944
|
const scrollerElem = anchorElem.parentElement;
|
|
2630
2945
|
const update = () => {
|
|
@@ -2722,6 +3037,7 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
2722
3037
|
{
|
|
2723
3038
|
ref: inputRef,
|
|
2724
3039
|
className: "link-input",
|
|
3040
|
+
placeholder: "https://",
|
|
2725
3041
|
value: editedLinkUrl,
|
|
2726
3042
|
onChange: (event) => {
|
|
2727
3043
|
setEditedLinkUrl(event.target.value);
|
|
@@ -2731,27 +3047,31 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
2731
3047
|
}
|
|
2732
3048
|
}
|
|
2733
3049
|
),
|
|
2734
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3050
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "link-actions", children: [
|
|
2735
3051
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2736
|
-
"
|
|
3052
|
+
"button",
|
|
2737
3053
|
{
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
3054
|
+
type: "button",
|
|
3055
|
+
className: "link-icon-btn link-cancel",
|
|
3056
|
+
title: "Cancel",
|
|
3057
|
+
"aria-label": "Cancel",
|
|
2741
3058
|
onMouseDown: preventDefault,
|
|
2742
3059
|
onClick: () => {
|
|
2743
3060
|
setIsLinkEditMode(false);
|
|
2744
|
-
}
|
|
3061
|
+
},
|
|
3062
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.Dismiss16Regular, {})
|
|
2745
3063
|
}
|
|
2746
3064
|
),
|
|
2747
3065
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2748
|
-
"
|
|
3066
|
+
"button",
|
|
2749
3067
|
{
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
3068
|
+
type: "button",
|
|
3069
|
+
className: "link-icon-btn link-confirm",
|
|
3070
|
+
title: "Confirm",
|
|
3071
|
+
"aria-label": "Confirm",
|
|
2753
3072
|
onMouseDown: preventDefault,
|
|
2754
|
-
onClick: handleLinkSubmission
|
|
3073
|
+
onClick: handleLinkSubmission,
|
|
3074
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.Checkmark16Regular, {})
|
|
2755
3075
|
}
|
|
2756
3076
|
)
|
|
2757
3077
|
] })
|
|
@@ -2765,32 +3085,38 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
2765
3085
|
children: linkUrl
|
|
2766
3086
|
}
|
|
2767
3087
|
),
|
|
2768
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
3088
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "link-actions", children: [
|
|
3089
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3090
|
+
"button",
|
|
3091
|
+
{
|
|
3092
|
+
type: "button",
|
|
3093
|
+
className: "link-icon-btn link-edit",
|
|
3094
|
+
title: "Edit link",
|
|
3095
|
+
"aria-label": "Edit link",
|
|
3096
|
+
onMouseDown: preventDefault,
|
|
3097
|
+
onClick: (event) => {
|
|
3098
|
+
event.preventDefault();
|
|
3099
|
+
setEditedLinkUrl(linkUrl);
|
|
3100
|
+
setIsLinkEditMode(true);
|
|
3101
|
+
},
|
|
3102
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.Edit16Regular, {})
|
|
2779
3103
|
}
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
3104
|
+
),
|
|
3105
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3106
|
+
"button",
|
|
3107
|
+
{
|
|
3108
|
+
type: "button",
|
|
3109
|
+
className: "link-icon-btn link-trash",
|
|
3110
|
+
title: "Remove link",
|
|
3111
|
+
"aria-label": "Remove link",
|
|
3112
|
+
onMouseDown: preventDefault,
|
|
3113
|
+
onClick: () => {
|
|
3114
|
+
editor.dispatchCommand(link.TOGGLE_LINK_COMMAND, null);
|
|
3115
|
+
},
|
|
3116
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.Delete16Regular, {})
|
|
2791
3117
|
}
|
|
2792
|
-
|
|
2793
|
-
)
|
|
3118
|
+
)
|
|
3119
|
+
] })
|
|
2794
3120
|
] }) });
|
|
2795
3121
|
};
|
|
2796
3122
|
var useFloatingLinkEditorToolbar = (editor, anchorElem, isLinkEditMode, setIsLinkEditMode) => {
|
|
@@ -2891,74 +3217,28 @@ var readClipboardImageAsDataURL = async (event) => {
|
|
|
2891
3217
|
}
|
|
2892
3218
|
return null;
|
|
2893
3219
|
};
|
|
2894
|
-
var InsertImageByURL = ({
|
|
2895
|
-
setIsOpen,
|
|
2896
|
-
onClick,
|
|
2897
|
-
disabled
|
|
2898
|
-
}) => {
|
|
2899
|
-
const [altText, setAltText] = React9.useState("");
|
|
2900
|
-
const [src, setSrc] = React9.useState("");
|
|
2901
|
-
const isDisabled = disabled || src === "";
|
|
2902
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 6, padding: "10px 0px 0px 0px" }, children: [
|
|
2903
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Enter URL", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2904
|
-
reactComponents.Input,
|
|
2905
|
-
{
|
|
2906
|
-
autoFocus: !disabled,
|
|
2907
|
-
appearance: "underline",
|
|
2908
|
-
placeholder: "Add URL",
|
|
2909
|
-
disabled,
|
|
2910
|
-
onChange: (_, v) => setSrc(v.value),
|
|
2911
|
-
value: src
|
|
2912
|
-
}
|
|
2913
|
-
) }),
|
|
2914
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Alt Text", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2915
|
-
reactComponents.Input,
|
|
2916
|
-
{
|
|
2917
|
-
placeholder: "Alt text",
|
|
2918
|
-
disabled,
|
|
2919
|
-
onChange: (_, v) => setAltText(v.value),
|
|
2920
|
-
value: altText
|
|
2921
|
-
},
|
|
2922
|
-
"alt-text-url"
|
|
2923
|
-
) }),
|
|
2924
|
-
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { horizontal: true, horizontalAlign: "end", tokens: { childrenGap: 6 }, children: [
|
|
2925
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2926
|
-
reactComponents.Button,
|
|
2927
|
-
{
|
|
2928
|
-
style: { width: "150px" },
|
|
2929
|
-
onClick: () => !disabled && onClick({ altText, src }),
|
|
2930
|
-
disabled: isDisabled,
|
|
2931
|
-
size: "small",
|
|
2932
|
-
children: "Confirm"
|
|
2933
|
-
},
|
|
2934
|
-
"url-confirm-btn"
|
|
2935
|
-
),
|
|
2936
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2937
|
-
reactComponents.Button,
|
|
2938
|
-
{
|
|
2939
|
-
style: { width: "150px" },
|
|
2940
|
-
onClick: () => setIsOpen(false),
|
|
2941
|
-
disabled,
|
|
2942
|
-
size: "small",
|
|
2943
|
-
children: "Cancel"
|
|
2944
|
-
},
|
|
2945
|
-
"file-url-cancel"
|
|
2946
|
-
)
|
|
2947
|
-
] })
|
|
2948
|
-
] });
|
|
2949
|
-
};
|
|
2950
3220
|
var InsertImageDialog = ({
|
|
2951
3221
|
activeEditor,
|
|
2952
|
-
disabled
|
|
3222
|
+
disabled,
|
|
3223
|
+
open: externalOpen,
|
|
3224
|
+
onClose
|
|
2953
3225
|
}) => {
|
|
2954
3226
|
const [src, setSrc] = React9.useState("");
|
|
2955
3227
|
const [altText, setAltText] = React9.useState("");
|
|
2956
|
-
const [
|
|
2957
|
-
const [selectedValue, setSelectedValue] = React9.useState("Upload");
|
|
3228
|
+
const [internalOpen, setInternalOpen] = React9.useState(false);
|
|
2958
3229
|
const [fileName, setFileName] = React9.useState("");
|
|
2959
3230
|
const hasModifier = React9.useRef(false);
|
|
2960
3231
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#333333";
|
|
2961
|
-
const
|
|
3232
|
+
const isControlled = externalOpen !== void 0;
|
|
3233
|
+
const isOpen = isControlled ? !!externalOpen && !disabled : internalOpen && !disabled;
|
|
3234
|
+
const isAddDisabled = disabled || src === "";
|
|
3235
|
+
const handleClose = () => {
|
|
3236
|
+
setSrc("");
|
|
3237
|
+
setAltText("");
|
|
3238
|
+
setFileName("");
|
|
3239
|
+
if (isControlled) onClose?.();
|
|
3240
|
+
else setInternalOpen(false);
|
|
3241
|
+
};
|
|
2962
3242
|
React9.useEffect(() => {
|
|
2963
3243
|
hasModifier.current = false;
|
|
2964
3244
|
const handler = (e) => {
|
|
@@ -2970,10 +3250,7 @@ var InsertImageDialog = ({
|
|
|
2970
3250
|
const onClick = (payload) => {
|
|
2971
3251
|
if (disabled) return;
|
|
2972
3252
|
activeEditor.dispatchCommand(INSERT_IMAGE_COMMAND, payload);
|
|
2973
|
-
|
|
2974
|
-
setAltText("");
|
|
2975
|
-
setSrc("");
|
|
2976
|
-
setFileName("");
|
|
3253
|
+
handleClose();
|
|
2977
3254
|
};
|
|
2978
3255
|
const loadImage = (event) => {
|
|
2979
3256
|
if (disabled) return;
|
|
@@ -2988,118 +3265,108 @@ var InsertImageDialog = ({
|
|
|
2988
3265
|
};
|
|
2989
3266
|
reader.readAsDataURL(files[0]);
|
|
2990
3267
|
};
|
|
2991
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
3268
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3269
|
+
!isControlled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3270
|
+
reactComponents.Button,
|
|
3271
|
+
{
|
|
3272
|
+
size: "small",
|
|
3273
|
+
title: "Add Image",
|
|
3274
|
+
disabled,
|
|
3275
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ImageAddRegular, { style: { color: iconColor } }),
|
|
3276
|
+
style: {
|
|
3277
|
+
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
3278
|
+
border: "none",
|
|
3279
|
+
margin: 2,
|
|
3280
|
+
opacity: disabled ? 0.55 : 1,
|
|
3281
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
3282
|
+
},
|
|
3283
|
+
onClick: () => {
|
|
3284
|
+
if (disabled) return;
|
|
3285
|
+
setSrc("");
|
|
3286
|
+
setAltText("");
|
|
3287
|
+
setFileName("");
|
|
3288
|
+
setInternalOpen(true);
|
|
3289
|
+
}
|
|
2999
3290
|
},
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
pointerEvents: disabled ? "none" : "auto"
|
|
3032
|
-
},
|
|
3033
|
-
children: [
|
|
3034
|
-
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 6 }, children: [
|
|
3035
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Upload", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3036
|
-
"label",
|
|
3037
|
-
{
|
|
3038
|
-
style: {
|
|
3039
|
-
cursor: disabled ? "not-allowed" : "pointer",
|
|
3040
|
-
display: "flex",
|
|
3041
|
-
alignItems: "center",
|
|
3042
|
-
gap: 8,
|
|
3043
|
-
opacity: disabled ? 0.75 : 1
|
|
3291
|
+
"upload-image"
|
|
3292
|
+
),
|
|
3293
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3294
|
+
reactComponents.Dialog,
|
|
3295
|
+
{
|
|
3296
|
+
open: isOpen,
|
|
3297
|
+
onOpenChange: (_, data) => {
|
|
3298
|
+
if (!data.open) handleClose();
|
|
3299
|
+
},
|
|
3300
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogSurface, { style: { maxWidth: "400px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogBody, { children: [
|
|
3301
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTitle, { children: "Insert Image" }),
|
|
3302
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogContent, { children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 10 }, style: { paddingTop: 8 }, children: [
|
|
3303
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Upload", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3304
|
+
"label",
|
|
3305
|
+
{
|
|
3306
|
+
style: {
|
|
3307
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
3308
|
+
display: "flex",
|
|
3309
|
+
alignItems: "center",
|
|
3310
|
+
gap: 8,
|
|
3311
|
+
opacity: disabled ? 0.75 : 1
|
|
3312
|
+
},
|
|
3313
|
+
children: [
|
|
3314
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3315
|
+
"input",
|
|
3316
|
+
{
|
|
3317
|
+
type: "file",
|
|
3318
|
+
accept: "image/*",
|
|
3319
|
+
style: { display: "none" },
|
|
3320
|
+
disabled,
|
|
3321
|
+
onChange: loadImage
|
|
3044
3322
|
},
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
disabled,
|
|
3093
|
-
setIsOpen: (open) => setIsOpen(open),
|
|
3094
|
-
onClick: (payload) => onClick(payload)
|
|
3095
|
-
}
|
|
3096
|
-
)
|
|
3097
|
-
]
|
|
3098
|
-
}
|
|
3099
|
-
)
|
|
3100
|
-
]
|
|
3101
|
-
}
|
|
3102
|
-
);
|
|
3323
|
+
"inline-image-upload"
|
|
3324
|
+
),
|
|
3325
|
+
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { horizontal: true, children: [
|
|
3326
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3327
|
+
reactIcons.AttachFilled,
|
|
3328
|
+
{
|
|
3329
|
+
style: {
|
|
3330
|
+
fontSize: "16px",
|
|
3331
|
+
color: disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#808080",
|
|
3332
|
+
marginTop: 2
|
|
3333
|
+
}
|
|
3334
|
+
}
|
|
3335
|
+
),
|
|
3336
|
+
!fileName && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#808080" }, children: "Upload File" })
|
|
3337
|
+
] }),
|
|
3338
|
+
fileName && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#808080" }, children: fileName })
|
|
3339
|
+
]
|
|
3340
|
+
}
|
|
3341
|
+
) }),
|
|
3342
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Alt Text", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3343
|
+
reactComponents.Input,
|
|
3344
|
+
{
|
|
3345
|
+
placeholder: "Alt text",
|
|
3346
|
+
appearance: "underline",
|
|
3347
|
+
disabled,
|
|
3348
|
+
onChange: (_, d) => setAltText(d.value),
|
|
3349
|
+
value: altText
|
|
3350
|
+
}
|
|
3351
|
+
) })
|
|
3352
|
+
] }) }),
|
|
3353
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogActions, { children: [
|
|
3354
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3355
|
+
reactComponents.Button,
|
|
3356
|
+
{
|
|
3357
|
+
appearance: "primary",
|
|
3358
|
+
size: "small",
|
|
3359
|
+
disabled: isAddDisabled,
|
|
3360
|
+
onClick: () => onClick({ altText, src }),
|
|
3361
|
+
children: "Add"
|
|
3362
|
+
}
|
|
3363
|
+
),
|
|
3364
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: handleClose, children: "Cancel" })
|
|
3365
|
+
] })
|
|
3366
|
+
] }) })
|
|
3367
|
+
}
|
|
3368
|
+
)
|
|
3369
|
+
] });
|
|
3103
3370
|
};
|
|
3104
3371
|
var ImagesPlugin = ({ captionsEnabled }) => {
|
|
3105
3372
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
@@ -3265,17 +3532,28 @@ var useStyles = reactComponents.makeStyles({
|
|
|
3265
3532
|
});
|
|
3266
3533
|
var InsertInlineImageDialog = ({
|
|
3267
3534
|
disabled,
|
|
3268
|
-
activeEditor
|
|
3535
|
+
activeEditor,
|
|
3536
|
+
open: externalOpen,
|
|
3537
|
+
onClose
|
|
3269
3538
|
}) => {
|
|
3270
3539
|
const hasModifier = React9.useRef(false);
|
|
3271
3540
|
const [src, setSrc] = React9.useState("");
|
|
3272
|
-
const [
|
|
3541
|
+
const [internalOpen, setInternalOpen] = React9.useState(false);
|
|
3273
3542
|
const [altText, setAltText] = React9.useState("");
|
|
3274
3543
|
const [fileName, setFileName] = React9.useState("");
|
|
3275
3544
|
const [position, setPosition] = React9.useState("left");
|
|
3276
3545
|
const styles = useStyles();
|
|
3277
3546
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#333333";
|
|
3278
|
-
const
|
|
3547
|
+
const isControlled = externalOpen !== void 0;
|
|
3548
|
+
const isOpen = isControlled ? !!externalOpen && !disabled : internalOpen && !disabled;
|
|
3549
|
+
const isAddDisabled = disabled || src === "";
|
|
3550
|
+
const handleClose = () => {
|
|
3551
|
+
setSrc("");
|
|
3552
|
+
setAltText("");
|
|
3553
|
+
setFileName("");
|
|
3554
|
+
if (isControlled) onClose?.();
|
|
3555
|
+
else setInternalOpen(false);
|
|
3556
|
+
};
|
|
3279
3557
|
const loadImage = (event) => {
|
|
3280
3558
|
if (disabled) return;
|
|
3281
3559
|
const files = event.target.files;
|
|
@@ -3300,146 +3578,135 @@ var InsertInlineImageDialog = ({
|
|
|
3300
3578
|
if (disabled) return;
|
|
3301
3579
|
const payload = { altText, position, src };
|
|
3302
3580
|
activeEditor.dispatchCommand(INSERT_INLINE_IMAGE_COMMAND, payload);
|
|
3303
|
-
|
|
3304
|
-
setAltText("");
|
|
3305
|
-
setSrc("");
|
|
3306
|
-
setFileName("");
|
|
3581
|
+
handleClose();
|
|
3307
3582
|
};
|
|
3308
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3583
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3584
|
+
!isControlled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3585
|
+
reactComponents.Button,
|
|
3586
|
+
{
|
|
3587
|
+
size: "small",
|
|
3588
|
+
title: "Add Inline Image",
|
|
3589
|
+
disabled,
|
|
3590
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ImageEditRegular, { style: { color: iconColor } }),
|
|
3591
|
+
style: {
|
|
3592
|
+
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
3593
|
+
border: "none",
|
|
3594
|
+
margin: 2,
|
|
3595
|
+
opacity: disabled ? 0.55 : 1,
|
|
3596
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
3597
|
+
},
|
|
3598
|
+
onClick: () => {
|
|
3599
|
+
if (disabled) return;
|
|
3600
|
+
setSrc("");
|
|
3601
|
+
setAltText("");
|
|
3602
|
+
setFileName("");
|
|
3603
|
+
setInternalOpen(true);
|
|
3604
|
+
}
|
|
3316
3605
|
},
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
"label",
|
|
3353
|
-
{
|
|
3354
|
-
style: {
|
|
3355
|
-
cursor: disabled ? "not-allowed" : "pointer",
|
|
3356
|
-
display: "flex",
|
|
3357
|
-
alignItems: "center",
|
|
3358
|
-
gap: 8,
|
|
3359
|
-
opacity: disabled ? 0.75 : 1
|
|
3360
|
-
},
|
|
3361
|
-
children: [
|
|
3606
|
+
"upload-inline-image"
|
|
3607
|
+
),
|
|
3608
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3609
|
+
reactComponents.Dialog,
|
|
3610
|
+
{
|
|
3611
|
+
open: isOpen,
|
|
3612
|
+
onOpenChange: (_, data) => {
|
|
3613
|
+
if (!data.open) handleClose();
|
|
3614
|
+
},
|
|
3615
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogSurface, { style: { maxWidth: "440px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogBody, { children: [
|
|
3616
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTitle, { children: "Insert Inline Image" }),
|
|
3617
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogContent, { children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 10 }, style: { paddingTop: 8 }, children: [
|
|
3618
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Upload", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3619
|
+
"label",
|
|
3620
|
+
{
|
|
3621
|
+
style: {
|
|
3622
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
3623
|
+
display: "flex",
|
|
3624
|
+
alignItems: "center",
|
|
3625
|
+
gap: 8,
|
|
3626
|
+
opacity: disabled ? 0.75 : 1
|
|
3627
|
+
},
|
|
3628
|
+
children: [
|
|
3629
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3630
|
+
"input",
|
|
3631
|
+
{
|
|
3632
|
+
type: "file",
|
|
3633
|
+
accept: "image/*",
|
|
3634
|
+
style: { display: "none" },
|
|
3635
|
+
disabled,
|
|
3636
|
+
onChange: loadImage
|
|
3637
|
+
},
|
|
3638
|
+
"inline-image-upload"
|
|
3639
|
+
),
|
|
3640
|
+
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { horizontal: true, children: [
|
|
3362
3641
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3363
|
-
|
|
3642
|
+
reactIcons.AttachFilled,
|
|
3364
3643
|
{
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
}
|
|
3371
|
-
|
|
3372
|
-
)
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
onClick: () => setIsOpen(false),
|
|
3432
|
-
children: "Cancel"
|
|
3433
|
-
},
|
|
3434
|
-
"file-inline-upload-cancel"
|
|
3435
|
-
)
|
|
3436
|
-
] })
|
|
3437
|
-
] })
|
|
3438
|
-
}
|
|
3439
|
-
)
|
|
3440
|
-
]
|
|
3441
|
-
}
|
|
3442
|
-
);
|
|
3644
|
+
style: {
|
|
3645
|
+
fontSize: "16px",
|
|
3646
|
+
color: disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#808080",
|
|
3647
|
+
marginTop: 2
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
),
|
|
3651
|
+
!fileName && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#808080" }, children: "Upload File" })
|
|
3652
|
+
] }),
|
|
3653
|
+
fileName && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#808080" }, children: fileName })
|
|
3654
|
+
]
|
|
3655
|
+
}
|
|
3656
|
+
) }),
|
|
3657
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Position", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3658
|
+
reactComponents.Dropdown,
|
|
3659
|
+
{
|
|
3660
|
+
placeholder: "Left Align",
|
|
3661
|
+
className: styles.alignDropdown,
|
|
3662
|
+
disabled,
|
|
3663
|
+
listbox: { style: { width: "120px" } },
|
|
3664
|
+
root: { style: { borderBottom: "1px solid black" } },
|
|
3665
|
+
children: [
|
|
3666
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Option, { text: "full", onClick: () => setPosition("full"), children: "Full" }, "full"),
|
|
3667
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Option, { text: "left", onClick: () => setPosition("left"), children: "Left" }, "left"),
|
|
3668
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Option, { text: "right", onClick: () => setPosition("right"), children: "Right" }, "right")
|
|
3669
|
+
]
|
|
3670
|
+
}
|
|
3671
|
+
) }),
|
|
3672
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Alt Text", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3673
|
+
reactComponents.Input,
|
|
3674
|
+
{
|
|
3675
|
+
placeholder: "Alt text",
|
|
3676
|
+
appearance: "underline",
|
|
3677
|
+
disabled,
|
|
3678
|
+
value: altText,
|
|
3679
|
+
onChange: (_, d) => setAltText(d.value)
|
|
3680
|
+
}
|
|
3681
|
+
) })
|
|
3682
|
+
] }) }),
|
|
3683
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogActions, { children: [
|
|
3684
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3685
|
+
reactComponents.Button,
|
|
3686
|
+
{
|
|
3687
|
+
appearance: "primary",
|
|
3688
|
+
size: "small",
|
|
3689
|
+
disabled: isAddDisabled,
|
|
3690
|
+
onClick: handleOnClick,
|
|
3691
|
+
children: "Add"
|
|
3692
|
+
},
|
|
3693
|
+
"file-inline-upload-btn"
|
|
3694
|
+
),
|
|
3695
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3696
|
+
reactComponents.Button,
|
|
3697
|
+
{
|
|
3698
|
+
size: "small",
|
|
3699
|
+
disabled,
|
|
3700
|
+
onClick: handleClose,
|
|
3701
|
+
children: "Cancel"
|
|
3702
|
+
},
|
|
3703
|
+
"file-inline-upload-cancel"
|
|
3704
|
+
)
|
|
3705
|
+
] })
|
|
3706
|
+
] }) })
|
|
3707
|
+
}
|
|
3708
|
+
)
|
|
3709
|
+
] });
|
|
3443
3710
|
};
|
|
3444
3711
|
var InlineImagePlugin = () => {
|
|
3445
3712
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
@@ -3594,204 +3861,6 @@ function PageBreakPlugin() {
|
|
|
3594
3861
|
}, [editor]);
|
|
3595
3862
|
return null;
|
|
3596
3863
|
}
|
|
3597
|
-
|
|
3598
|
-
// src/Utils/Sanitize.ts
|
|
3599
|
-
var DROP_ENTIRELY = /* @__PURE__ */ new Set([
|
|
3600
|
-
"script",
|
|
3601
|
-
"noscript",
|
|
3602
|
-
"style",
|
|
3603
|
-
"object",
|
|
3604
|
-
"embed",
|
|
3605
|
-
"form",
|
|
3606
|
-
"input",
|
|
3607
|
-
"button",
|
|
3608
|
-
"select",
|
|
3609
|
-
"textarea",
|
|
3610
|
-
"meta",
|
|
3611
|
-
"link",
|
|
3612
|
-
"base"
|
|
3613
|
-
]);
|
|
3614
|
-
var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
3615
|
-
// Block
|
|
3616
|
-
"p",
|
|
3617
|
-
"h1",
|
|
3618
|
-
"h2",
|
|
3619
|
-
"h3",
|
|
3620
|
-
"h4",
|
|
3621
|
-
"h5",
|
|
3622
|
-
"h6",
|
|
3623
|
-
"ul",
|
|
3624
|
-
"ol",
|
|
3625
|
-
"li",
|
|
3626
|
-
"blockquote",
|
|
3627
|
-
"pre",
|
|
3628
|
-
"div",
|
|
3629
|
-
"table",
|
|
3630
|
-
"thead",
|
|
3631
|
-
"tbody",
|
|
3632
|
-
"tfoot",
|
|
3633
|
-
"tr",
|
|
3634
|
-
"td",
|
|
3635
|
-
"th",
|
|
3636
|
-
// Inline
|
|
3637
|
-
"span",
|
|
3638
|
-
"a",
|
|
3639
|
-
"strong",
|
|
3640
|
-
"b",
|
|
3641
|
-
"em",
|
|
3642
|
-
"i",
|
|
3643
|
-
"u",
|
|
3644
|
-
"s",
|
|
3645
|
-
"del",
|
|
3646
|
-
"strike",
|
|
3647
|
-
"sub",
|
|
3648
|
-
"sup",
|
|
3649
|
-
"mark",
|
|
3650
|
-
"code",
|
|
3651
|
-
"br",
|
|
3652
|
-
"hr",
|
|
3653
|
-
// Media / embeds
|
|
3654
|
-
"img",
|
|
3655
|
-
"iframe"
|
|
3656
|
-
]);
|
|
3657
|
-
var ALLOWED_ATTRS = /* @__PURE__ */ new Set([
|
|
3658
|
-
// Presentation
|
|
3659
|
-
"class",
|
|
3660
|
-
"style",
|
|
3661
|
-
"dir",
|
|
3662
|
-
"lang",
|
|
3663
|
-
// Anchors
|
|
3664
|
-
"href",
|
|
3665
|
-
"target",
|
|
3666
|
-
"rel",
|
|
3667
|
-
// Images
|
|
3668
|
-
"src",
|
|
3669
|
-
"alt",
|
|
3670
|
-
"width",
|
|
3671
|
-
"height",
|
|
3672
|
-
// Tables
|
|
3673
|
-
"colspan",
|
|
3674
|
-
"rowspan",
|
|
3675
|
-
// Lists — <ol type="a"> and <ol start="2">
|
|
3676
|
-
"start",
|
|
3677
|
-
"type",
|
|
3678
|
-
// Lexical-internal data markers
|
|
3679
|
-
"data-lex-block",
|
|
3680
|
-
"data-kind",
|
|
3681
|
-
"data-lexical-decorator",
|
|
3682
|
-
// Misc
|
|
3683
|
-
"title",
|
|
3684
|
-
"allowfullscreen"
|
|
3685
|
-
]);
|
|
3686
|
-
var DANGEROUS_URL = /^\s*(javascript|data\s*:|vbscript)/i;
|
|
3687
|
-
function sanitizeElement(el) {
|
|
3688
|
-
for (const child of Array.from(el.children)) {
|
|
3689
|
-
sanitizeElement(child);
|
|
3690
|
-
}
|
|
3691
|
-
const tag = el.tagName.toLowerCase();
|
|
3692
|
-
if (DROP_ENTIRELY.has(tag)) {
|
|
3693
|
-
el.parentNode?.removeChild(el);
|
|
3694
|
-
return;
|
|
3695
|
-
}
|
|
3696
|
-
if (tag === "iframe") {
|
|
3697
|
-
const src = el.getAttribute("src") ?? "";
|
|
3698
|
-
const isYouTube = /^\s*https:\/\/(www\.)?(youtube\.com|youtube-nocookie\.com)\/embed\/[^?&/]+/i.test(src);
|
|
3699
|
-
if (!isYouTube) {
|
|
3700
|
-
el.parentNode?.removeChild(el);
|
|
3701
|
-
return;
|
|
3702
|
-
}
|
|
3703
|
-
}
|
|
3704
|
-
if (!ALLOWED_TAGS.has(tag)) {
|
|
3705
|
-
while (el.firstChild) {
|
|
3706
|
-
el.parentNode?.insertBefore(el.firstChild, el);
|
|
3707
|
-
}
|
|
3708
|
-
el.parentNode?.removeChild(el);
|
|
3709
|
-
return;
|
|
3710
|
-
}
|
|
3711
|
-
for (const { name, value } of Array.from(el.attributes)) {
|
|
3712
|
-
const lname = name.toLowerCase();
|
|
3713
|
-
if (!ALLOWED_ATTRS.has(lname)) {
|
|
3714
|
-
el.removeAttribute(name);
|
|
3715
|
-
continue;
|
|
3716
|
-
}
|
|
3717
|
-
if (lname === "href" || lname === "src") {
|
|
3718
|
-
if (DANGEROUS_URL.test(value)) {
|
|
3719
|
-
el.removeAttribute(name);
|
|
3720
|
-
}
|
|
3721
|
-
}
|
|
3722
|
-
if (lname === "style") {
|
|
3723
|
-
const safe = value.replace(/expression\s*\(/gi, "(").replace(/url\s*\(\s*['"]?\s*javascript:/gi, "url(");
|
|
3724
|
-
el.setAttribute("style", safe);
|
|
3725
|
-
}
|
|
3726
|
-
}
|
|
3727
|
-
if (tag === "a" && (el.getAttribute("target") || "").toLowerCase() === "_blank") {
|
|
3728
|
-
const rel = (el.getAttribute("rel") || "").trim();
|
|
3729
|
-
const tokens = new Set(
|
|
3730
|
-
rel.split(/\s+/).filter(Boolean).map((t) => t.toLowerCase())
|
|
3731
|
-
);
|
|
3732
|
-
tokens.add("noopener");
|
|
3733
|
-
tokens.add("noreferrer");
|
|
3734
|
-
el.setAttribute("rel", Array.from(tokens).join(" "));
|
|
3735
|
-
}
|
|
3736
|
-
}
|
|
3737
|
-
function sanitizeHtml(html) {
|
|
3738
|
-
if (!html || typeof html !== "string") return "";
|
|
3739
|
-
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
3740
|
-
for (const child of Array.from(doc.body.children)) {
|
|
3741
|
-
sanitizeElement(child);
|
|
3742
|
-
}
|
|
3743
|
-
return doc.body.innerHTML;
|
|
3744
|
-
}
|
|
3745
|
-
var BLOCK_TAGS = /* @__PURE__ */ new Set([
|
|
3746
|
-
"p",
|
|
3747
|
-
"h1",
|
|
3748
|
-
"h2",
|
|
3749
|
-
"h3",
|
|
3750
|
-
"h4",
|
|
3751
|
-
"h5",
|
|
3752
|
-
"h6",
|
|
3753
|
-
"div",
|
|
3754
|
-
"ul",
|
|
3755
|
-
"ol",
|
|
3756
|
-
"li",
|
|
3757
|
-
"table",
|
|
3758
|
-
"blockquote",
|
|
3759
|
-
"pre",
|
|
3760
|
-
"hr"
|
|
3761
|
-
]);
|
|
3762
|
-
function normalizeToBlockHtml(html) {
|
|
3763
|
-
if (!html) return "";
|
|
3764
|
-
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
3765
|
-
const body = doc.body;
|
|
3766
|
-
const childNodes = Array.from(body.childNodes);
|
|
3767
|
-
const needsWrap = childNodes.some((node) => {
|
|
3768
|
-
if (node.nodeType === Node.TEXT_NODE) return !!node.nodeValue?.trim();
|
|
3769
|
-
if (node.nodeType === Node.ELEMENT_NODE)
|
|
3770
|
-
return !BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
3771
|
-
return false;
|
|
3772
|
-
});
|
|
3773
|
-
if (!needsWrap) return html;
|
|
3774
|
-
while (body.firstChild) body.removeChild(body.firstChild);
|
|
3775
|
-
let pendingP = null;
|
|
3776
|
-
for (const node of childNodes) {
|
|
3777
|
-
const isBlock = node.nodeType === Node.ELEMENT_NODE && BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
3778
|
-
const isWhitespace = node.nodeType === Node.TEXT_NODE && !node.nodeValue?.trim();
|
|
3779
|
-
if (isBlock) {
|
|
3780
|
-
if (pendingP) {
|
|
3781
|
-
body.appendChild(pendingP);
|
|
3782
|
-
pendingP = null;
|
|
3783
|
-
}
|
|
3784
|
-
body.appendChild(node);
|
|
3785
|
-
} else if (!isWhitespace) {
|
|
3786
|
-
if (!pendingP) pendingP = doc.createElement("p");
|
|
3787
|
-
pendingP.appendChild(node);
|
|
3788
|
-
}
|
|
3789
|
-
}
|
|
3790
|
-
if (pendingP) body.appendChild(pendingP);
|
|
3791
|
-
return body.innerHTML;
|
|
3792
|
-
}
|
|
3793
|
-
|
|
3794
|
-
// src/Utils/Helper.ts
|
|
3795
3864
|
function findBlockByKind(kind) {
|
|
3796
3865
|
const root = lexical.$getRoot();
|
|
3797
3866
|
for (const child of root.getChildren()) {
|
|
@@ -3863,7 +3932,7 @@ function RefApiPlugin({
|
|
|
3863
3932
|
editor.getEditorState().read(() => {
|
|
3864
3933
|
html$1 = html.$generateHtmlFromNodes(editor, null);
|
|
3865
3934
|
});
|
|
3866
|
-
return html$1;
|
|
3935
|
+
return postProcessOutput(html$1);
|
|
3867
3936
|
},
|
|
3868
3937
|
clear: () => {
|
|
3869
3938
|
editor.update(() => {
|
|
@@ -5006,13 +5075,14 @@ function getToolbarGroupsByLevel(level) {
|
|
|
5006
5075
|
// ['undo', 'redo', '|'],
|
|
5007
5076
|
["Bold", "Italic", "Underline", "|"],
|
|
5008
5077
|
["ColorPicker", "|"],
|
|
5009
|
-
["Link", "
|
|
5010
|
-
|
|
5078
|
+
["Link", "|"],
|
|
5079
|
+
["Insert", "|"],
|
|
5011
5080
|
["Heading", "|"],
|
|
5012
5081
|
["FontFamily", "|"],
|
|
5013
5082
|
["FontSize", "|"],
|
|
5014
5083
|
["Decorators", "|"],
|
|
5015
|
-
["Align"]
|
|
5084
|
+
["Align", "|"],
|
|
5085
|
+
["PageSetup"]
|
|
5016
5086
|
];
|
|
5017
5087
|
case "pro" /* Pro */:
|
|
5018
5088
|
default:
|
|
@@ -5020,14 +5090,14 @@ function getToolbarGroupsByLevel(level) {
|
|
|
5020
5090
|
// ['undo', 'redo', '|'],
|
|
5021
5091
|
["Bold", "Italic", "Underline", "|"],
|
|
5022
5092
|
["ColorPicker", "|"],
|
|
5023
|
-
["Link", "
|
|
5024
|
-
|
|
5025
|
-
["Image", "Youtube", "InlineImage", "|"],
|
|
5093
|
+
["Link", "|"],
|
|
5094
|
+
["Insert", "|"],
|
|
5026
5095
|
["Heading", "|"],
|
|
5027
5096
|
["FontFamily", "|"],
|
|
5028
5097
|
["FontSize", "|"],
|
|
5029
5098
|
["Decorators", "|"],
|
|
5030
|
-
["Align"]
|
|
5099
|
+
["Align", "|"],
|
|
5100
|
+
["PageSetup"]
|
|
5031
5101
|
];
|
|
5032
5102
|
}
|
|
5033
5103
|
}
|
|
@@ -5065,6 +5135,7 @@ var normalizeHex = (v) => {
|
|
|
5065
5135
|
if (hex.length === 4 || hex.length === 7) return hex.toLowerCase();
|
|
5066
5136
|
return "#000000";
|
|
5067
5137
|
};
|
|
5138
|
+
var isCompleteHex = (v) => /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test((v ?? "").trim());
|
|
5068
5139
|
var hexToRgb = (hex) => {
|
|
5069
5140
|
const h = normalizeHex(hex).replace("#", "");
|
|
5070
5141
|
if (h.length === 3) {
|
|
@@ -5147,62 +5218,118 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5147
5218
|
};
|
|
5148
5219
|
}, [open]);
|
|
5149
5220
|
const appliedHex = React9__namespace.useMemo(() => normalizeHex(value || "#000000"), [value]);
|
|
5150
|
-
const [hex,
|
|
5221
|
+
const [hex, setHexState] = React9__namespace.useState(appliedHex);
|
|
5222
|
+
const [hexText, setHexText] = React9__namespace.useState(appliedHex);
|
|
5151
5223
|
const { r, g, b } = React9__namespace.useMemo(() => hexToRgb(hex), [hex]);
|
|
5152
5224
|
const hsv = React9__namespace.useMemo(() => rgbToHsv(r, g, b), [r, g, b]);
|
|
5153
5225
|
const [h, setH] = React9__namespace.useState(hsv.h);
|
|
5154
5226
|
const [s, setS] = React9__namespace.useState(hsv.s);
|
|
5155
5227
|
const [v, setV] = React9__namespace.useState(hsv.v);
|
|
5156
|
-
const
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5228
|
+
const commit = React9__namespace.useCallback(
|
|
5229
|
+
(nextHex) => {
|
|
5230
|
+
const rgb = hexToRgb(nextHex);
|
|
5231
|
+
const next = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
5232
|
+
setHexState(nextHex);
|
|
5233
|
+
setHexText(nextHex);
|
|
5234
|
+
setH(next.h);
|
|
5235
|
+
setS(next.s);
|
|
5236
|
+
setV(next.v);
|
|
5237
|
+
onChange(nextHex);
|
|
5238
|
+
},
|
|
5239
|
+
[onChange]
|
|
5240
|
+
);
|
|
5241
|
+
const commitFromHsv = React9__namespace.useCallback(
|
|
5242
|
+
(hh, ss, vv) => {
|
|
5243
|
+
const rgb = hsvToRgb(hh, ss, vv);
|
|
5244
|
+
const nextHex = rgbToHex(rgb.r, rgb.g, rgb.b);
|
|
5245
|
+
setHexState(nextHex);
|
|
5246
|
+
setHexText(nextHex);
|
|
5247
|
+
setH(hh);
|
|
5248
|
+
setS(ss);
|
|
5249
|
+
setV(vv);
|
|
5250
|
+
onChange(nextHex);
|
|
5251
|
+
},
|
|
5252
|
+
[onChange]
|
|
5253
|
+
);
|
|
5171
5254
|
const wasOpenRef = React9__namespace.useRef(open);
|
|
5172
5255
|
React9__namespace.useEffect(() => {
|
|
5173
5256
|
const justOpened = open && !wasOpenRef.current;
|
|
5174
5257
|
wasOpenRef.current = open;
|
|
5175
5258
|
if (!justOpened) return;
|
|
5176
|
-
|
|
5177
|
-
|
|
5259
|
+
setHexState(appliedHex);
|
|
5260
|
+
setHexText(appliedHex);
|
|
5261
|
+
const rgb = hexToRgb(appliedHex);
|
|
5262
|
+
const next = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
5263
|
+
setH(next.h);
|
|
5264
|
+
setS(next.s);
|
|
5265
|
+
setV(next.v);
|
|
5266
|
+
}, [appliedHex, open]);
|
|
5178
5267
|
const svRef = React9__namespace.useRef(null);
|
|
5179
|
-
const
|
|
5268
|
+
const svPointFromEvent = React9__namespace.useCallback((clientX, clientY) => {
|
|
5269
|
+
if (!svRef.current) return null;
|
|
5270
|
+
const rect = svRef.current.getBoundingClientRect();
|
|
5271
|
+
const x = clamp3(clientX - rect.left, 0, rect.width);
|
|
5272
|
+
const y = clamp3(clientY - rect.top, 0, rect.height);
|
|
5273
|
+
const ss = rect.width === 0 ? 0 : x / rect.width;
|
|
5274
|
+
const vv = rect.height === 0 ? 0 : 1 - y / rect.height;
|
|
5275
|
+
return { ss, vv };
|
|
5276
|
+
}, []);
|
|
5277
|
+
const hRef = React9__namespace.useRef(h);
|
|
5278
|
+
hRef.current = h;
|
|
5279
|
+
const handleSVPointerDown = React9__namespace.useCallback(
|
|
5280
|
+
(e) => {
|
|
5281
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
5282
|
+
const pt = svPointFromEvent(e.clientX, e.clientY);
|
|
5283
|
+
if (pt) commitFromHsv(hRef.current, pt.ss, pt.vv);
|
|
5284
|
+
},
|
|
5285
|
+
[svPointFromEvent, commitFromHsv]
|
|
5286
|
+
);
|
|
5287
|
+
const handleSVPointerMove = React9__namespace.useCallback(
|
|
5180
5288
|
(e) => {
|
|
5181
|
-
if (
|
|
5182
|
-
const
|
|
5183
|
-
|
|
5184
|
-
const y = clamp3(e.clientY - rect.top, 0, rect.height);
|
|
5185
|
-
const ss = rect.width === 0 ? 0 : x / rect.width;
|
|
5186
|
-
const vv = rect.height === 0 ? 0 : 1 - y / rect.height;
|
|
5187
|
-
setDraftFromHsv(h, ss, vv);
|
|
5289
|
+
if (e.buttons !== 1) return;
|
|
5290
|
+
const pt = svPointFromEvent(e.clientX, e.clientY);
|
|
5291
|
+
if (pt) commitFromHsv(hRef.current, pt.ss, pt.vv);
|
|
5188
5292
|
},
|
|
5189
|
-
[
|
|
5293
|
+
[svPointFromEvent, commitFromHsv]
|
|
5190
5294
|
);
|
|
5191
5295
|
const hueRef = React9__namespace.useRef(null);
|
|
5192
|
-
const
|
|
5296
|
+
const sRef = React9__namespace.useRef(s);
|
|
5297
|
+
sRef.current = s;
|
|
5298
|
+
const vRef = React9__namespace.useRef(v);
|
|
5299
|
+
vRef.current = v;
|
|
5300
|
+
const huePointFromEvent = React9__namespace.useCallback((clientX) => {
|
|
5301
|
+
if (!hueRef.current) return null;
|
|
5302
|
+
const rect = hueRef.current.getBoundingClientRect();
|
|
5303
|
+
const x = clamp3(clientX - rect.left, 0, rect.width);
|
|
5304
|
+
return rect.width === 0 ? 0 : x / rect.width * 360;
|
|
5305
|
+
}, []);
|
|
5306
|
+
const handleHuePointerDown = React9__namespace.useCallback(
|
|
5307
|
+
(e) => {
|
|
5308
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
5309
|
+
const hh = huePointFromEvent(e.clientX);
|
|
5310
|
+
if (hh != null) commitFromHsv(hh, sRef.current, vRef.current);
|
|
5311
|
+
},
|
|
5312
|
+
[huePointFromEvent, commitFromHsv]
|
|
5313
|
+
);
|
|
5314
|
+
const handleHuePointerMove = React9__namespace.useCallback(
|
|
5193
5315
|
(e) => {
|
|
5194
|
-
if (
|
|
5195
|
-
const
|
|
5196
|
-
|
|
5197
|
-
const hh = rect.width === 0 ? 0 : x / rect.width * 360;
|
|
5198
|
-
setDraftFromHsv(hh, s, v);
|
|
5316
|
+
if (e.buttons !== 1) return;
|
|
5317
|
+
const hh = huePointFromEvent(e.clientX);
|
|
5318
|
+
if (hh != null) commitFromHsv(hh, sRef.current, vRef.current);
|
|
5199
5319
|
},
|
|
5200
|
-
[
|
|
5320
|
+
[huePointFromEvent, commitFromHsv]
|
|
5201
5321
|
);
|
|
5202
|
-
const
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5322
|
+
const handleHexChange = React9__namespace.useCallback(
|
|
5323
|
+
(_, val) => {
|
|
5324
|
+
const next = val ?? "";
|
|
5325
|
+
setHexText(next);
|
|
5326
|
+
if (isCompleteHex(next.trim())) commit(normalizeHex(next));
|
|
5327
|
+
},
|
|
5328
|
+
[commit]
|
|
5329
|
+
);
|
|
5330
|
+
const handleHexBlur = React9__namespace.useCallback(() => {
|
|
5331
|
+
commit(normalizeHex(hexText));
|
|
5332
|
+
}, [hexText, commit]);
|
|
5206
5333
|
const svThumb = React9__namespace.useMemo(() => ({ left: `${s * 100}%`, top: `${(1 - v) * 100}%` }), [s, v]);
|
|
5207
5334
|
const hueThumb = React9__namespace.useMemo(() => ({ left: `${h / 360 * 100}%` }), [h]);
|
|
5208
5335
|
const hueColor = React9__namespace.useMemo(() => {
|
|
@@ -5257,44 +5384,192 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5257
5384
|
directionalHint: 4,
|
|
5258
5385
|
className: "aoColorCallout",
|
|
5259
5386
|
preventDismissOnEvent,
|
|
5260
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap:
|
|
5261
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
5262
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
5263
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5387
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 14 }, styles: { root: { padding: "14px 16px 16px", width: 288 } }, children: [
|
|
5388
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
5389
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, fontWeight: 600, color: "#242424", letterSpacing: 0.1 }, children: title }),
|
|
5390
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5391
|
+
"button",
|
|
5392
|
+
{
|
|
5393
|
+
type: "button",
|
|
5394
|
+
"aria-label": "Close",
|
|
5395
|
+
onClick: () => setOpenAndNotify(false),
|
|
5396
|
+
style: {
|
|
5397
|
+
display: "flex",
|
|
5398
|
+
alignItems: "center",
|
|
5399
|
+
justifyContent: "center",
|
|
5400
|
+
width: 24,
|
|
5401
|
+
height: 24,
|
|
5402
|
+
padding: 0,
|
|
5403
|
+
border: "none",
|
|
5404
|
+
borderRadius: 4,
|
|
5405
|
+
background: "transparent",
|
|
5406
|
+
color: "#616161",
|
|
5407
|
+
cursor: "pointer"
|
|
5408
|
+
},
|
|
5409
|
+
onMouseEnter: (e) => e.currentTarget.style.background = "#f0f0f0",
|
|
5410
|
+
onMouseLeave: (e) => e.currentTarget.style.background = "transparent",
|
|
5411
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.Dismiss16Regular, {})
|
|
5412
|
+
}
|
|
5413
|
+
)
|
|
5264
5414
|
] }),
|
|
5265
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5266
|
-
|
|
5415
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5416
|
+
"div",
|
|
5417
|
+
{
|
|
5418
|
+
ref: svRef,
|
|
5419
|
+
onPointerDown: handleSVPointerDown,
|
|
5420
|
+
onPointerMove: handleSVPointerMove,
|
|
5421
|
+
style: {
|
|
5422
|
+
position: "relative",
|
|
5423
|
+
width: "100%",
|
|
5424
|
+
height: 150,
|
|
5425
|
+
borderRadius: 8,
|
|
5426
|
+
overflow: "hidden",
|
|
5427
|
+
cursor: "crosshair",
|
|
5428
|
+
touchAction: "none",
|
|
5429
|
+
boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.08)"
|
|
5430
|
+
},
|
|
5431
|
+
children: [
|
|
5432
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, background: hueColor } }),
|
|
5433
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5434
|
+
"div",
|
|
5435
|
+
{
|
|
5436
|
+
style: {
|
|
5437
|
+
position: "absolute",
|
|
5438
|
+
inset: 0,
|
|
5439
|
+
background: "linear-gradient(to right, #fff, rgba(255,255,255,0))"
|
|
5440
|
+
}
|
|
5441
|
+
}
|
|
5442
|
+
),
|
|
5443
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5444
|
+
"div",
|
|
5445
|
+
{
|
|
5446
|
+
style: {
|
|
5447
|
+
position: "absolute",
|
|
5448
|
+
inset: 0,
|
|
5449
|
+
background: "linear-gradient(to top, #000, rgba(0,0,0,0))"
|
|
5450
|
+
}
|
|
5451
|
+
}
|
|
5452
|
+
),
|
|
5453
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5454
|
+
"div",
|
|
5455
|
+
{
|
|
5456
|
+
style: {
|
|
5457
|
+
position: "absolute",
|
|
5458
|
+
width: 16,
|
|
5459
|
+
height: 16,
|
|
5460
|
+
borderRadius: "50%",
|
|
5461
|
+
border: "2px solid #fff",
|
|
5462
|
+
boxShadow: "0 0 0 1px rgba(0,0,0,0.35), 0 1px 3px rgba(0,0,0,0.4)",
|
|
5463
|
+
transform: "translate(-50%, -50%)",
|
|
5464
|
+
pointerEvents: "none",
|
|
5465
|
+
...svThumb
|
|
5466
|
+
}
|
|
5467
|
+
}
|
|
5468
|
+
)
|
|
5469
|
+
]
|
|
5470
|
+
}
|
|
5471
|
+
),
|
|
5472
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5473
|
+
"div",
|
|
5474
|
+
{
|
|
5475
|
+
ref: hueRef,
|
|
5476
|
+
onPointerDown: handleHuePointerDown,
|
|
5477
|
+
onPointerMove: handleHuePointerMove,
|
|
5478
|
+
style: {
|
|
5479
|
+
position: "relative",
|
|
5480
|
+
width: "100%",
|
|
5481
|
+
height: 12,
|
|
5482
|
+
borderRadius: 999,
|
|
5483
|
+
cursor: "pointer",
|
|
5484
|
+
touchAction: "none",
|
|
5485
|
+
background: "linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)",
|
|
5486
|
+
boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.08)"
|
|
5487
|
+
},
|
|
5488
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5489
|
+
"div",
|
|
5490
|
+
{
|
|
5491
|
+
style: {
|
|
5492
|
+
position: "absolute",
|
|
5493
|
+
top: "50%",
|
|
5494
|
+
width: 16,
|
|
5495
|
+
height: 16,
|
|
5496
|
+
borderRadius: "50%",
|
|
5497
|
+
background: hueColor,
|
|
5498
|
+
border: "2px solid #fff",
|
|
5499
|
+
boxShadow: "0 0 0 1px rgba(0,0,0,0.35), 0 1px 3px rgba(0,0,0,0.4)",
|
|
5500
|
+
transform: "translate(-50%, -50%)",
|
|
5501
|
+
pointerEvents: "none",
|
|
5502
|
+
...hueThumb
|
|
5503
|
+
}
|
|
5504
|
+
}
|
|
5505
|
+
)
|
|
5506
|
+
}
|
|
5507
|
+
),
|
|
5508
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
5509
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5510
|
+
"div",
|
|
5511
|
+
{
|
|
5512
|
+
style: {
|
|
5513
|
+
width: 32,
|
|
5514
|
+
height: 32,
|
|
5515
|
+
borderRadius: 6,
|
|
5516
|
+
flexShrink: 0,
|
|
5517
|
+
background: hex,
|
|
5518
|
+
boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.12)"
|
|
5519
|
+
}
|
|
5520
|
+
}
|
|
5521
|
+
),
|
|
5267
5522
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5268
5523
|
react.TextField,
|
|
5269
5524
|
{
|
|
5270
|
-
value:
|
|
5271
|
-
onChange:
|
|
5272
|
-
onBlur:
|
|
5525
|
+
value: hexText,
|
|
5526
|
+
onChange: handleHexChange,
|
|
5527
|
+
onBlur: handleHexBlur,
|
|
5528
|
+
onKeyDown: (e) => {
|
|
5529
|
+
if (e.key === "Enter") commit(normalizeHex(hexText));
|
|
5530
|
+
},
|
|
5531
|
+
styles: { root: { flex: 1 }, fieldGroup: { borderRadius: 6 } }
|
|
5273
5532
|
}
|
|
5274
5533
|
)
|
|
5275
5534
|
] }),
|
|
5276
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5277
|
-
"
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5535
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5536
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, fontWeight: 600, color: "#8a8a8a", marginBottom: 6, letterSpacing: 0.3 }, children: "STANDARD COLORS" }),
|
|
5537
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5538
|
+
"div",
|
|
5539
|
+
{
|
|
5540
|
+
style: {
|
|
5541
|
+
display: "grid",
|
|
5542
|
+
gridTemplateColumns: "repeat(9, 1fr)",
|
|
5543
|
+
gap: 6
|
|
5544
|
+
},
|
|
5545
|
+
children: PRESET.map((c) => {
|
|
5546
|
+
const isSelected = c.toLowerCase() === hex.toLowerCase();
|
|
5547
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5548
|
+
"button",
|
|
5549
|
+
{
|
|
5550
|
+
type: "button",
|
|
5551
|
+
onClick: () => commit(c),
|
|
5552
|
+
title: c,
|
|
5553
|
+
"aria-label": c,
|
|
5554
|
+
style: {
|
|
5555
|
+
width: 22,
|
|
5556
|
+
height: 22,
|
|
5557
|
+
padding: 0,
|
|
5558
|
+
borderRadius: 5,
|
|
5559
|
+
background: c,
|
|
5560
|
+
cursor: "pointer",
|
|
5561
|
+
boxShadow: isSelected ? "0 0 0 2px #fff, 0 0 0 3px #4a86e8" : "inset 0 0 0 1px rgba(0,0,0,0.15)",
|
|
5562
|
+
border: "none",
|
|
5563
|
+
transition: "transform 80ms ease"
|
|
5564
|
+
},
|
|
5565
|
+
onMouseEnter: (e) => e.currentTarget.style.transform = "scale(1.12)",
|
|
5566
|
+
onMouseLeave: (e) => e.currentTarget.style.transform = "scale(1)"
|
|
5567
|
+
},
|
|
5568
|
+
c
|
|
5569
|
+
);
|
|
5570
|
+
})
|
|
5571
|
+
}
|
|
5572
|
+
)
|
|
5298
5573
|
] })
|
|
5299
5574
|
] })
|
|
5300
5575
|
}
|
|
@@ -5626,294 +5901,464 @@ var FontSizePlugin = ({ disabled }) => {
|
|
|
5626
5901
|
"fontsize"
|
|
5627
5902
|
) });
|
|
5628
5903
|
};
|
|
5629
|
-
var
|
|
5904
|
+
var VERBATIM_LINK_RE = /^https?:\/\/|^mailto:|^tel:|^#|^\//i;
|
|
5905
|
+
function getLinkValidationMessage(raw) {
|
|
5906
|
+
const trimmed = raw.trim();
|
|
5907
|
+
if (!trimmed) return void 0;
|
|
5908
|
+
if (/\s/.test(trimmed)) return "URL cannot contain spaces";
|
|
5909
|
+
if (!VERBATIM_LINK_RE.test(trimmed) && !trimmed.includes(".")) {
|
|
5910
|
+
return "Enter a valid URL (e.g. example.com)";
|
|
5911
|
+
}
|
|
5912
|
+
return void 0;
|
|
5913
|
+
}
|
|
5914
|
+
var InsertLinkPlugin = ({
|
|
5915
|
+
disabled,
|
|
5916
|
+
open: externalOpen,
|
|
5917
|
+
onClose
|
|
5918
|
+
}) => {
|
|
5630
5919
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
5631
|
-
const [
|
|
5920
|
+
const [internalOpen, setInternalOpen] = React9.useState(false);
|
|
5632
5921
|
const [text, setText] = React9.useState("");
|
|
5633
5922
|
const [link$1, setLink] = React9.useState("");
|
|
5634
5923
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#333333";
|
|
5924
|
+
const isControlled = externalOpen !== void 0;
|
|
5925
|
+
const isOpen = isControlled ? !!externalOpen && !disabled : internalOpen && !disabled;
|
|
5926
|
+
const linkError = getLinkValidationMessage(link$1);
|
|
5927
|
+
const handleClose = () => {
|
|
5928
|
+
setText("");
|
|
5929
|
+
setLink("");
|
|
5930
|
+
if (isControlled) onClose?.();
|
|
5931
|
+
else setInternalOpen(false);
|
|
5932
|
+
};
|
|
5635
5933
|
const insertLink = (text2, link2) => {
|
|
5636
5934
|
if (disabled) return;
|
|
5935
|
+
if (getLinkValidationMessage(link2)) return;
|
|
5936
|
+
const trimmedLink = link2.trim();
|
|
5937
|
+
const href = VERBATIM_LINK_RE.test(trimmedLink) ? trimmedLink : `https://${trimmedLink}`;
|
|
5637
5938
|
editor.update(() => {
|
|
5638
|
-
setText("");
|
|
5639
|
-
setLink("");
|
|
5640
5939
|
const selection = lexical.$getSelection();
|
|
5641
5940
|
if (lexical.$isRangeSelection(selection)) {
|
|
5642
5941
|
const textNode = new lexical.TextNode(text2);
|
|
5643
|
-
const linkNode = link.$createLinkNode(
|
|
5942
|
+
const linkNode = link.$createLinkNode(href);
|
|
5644
5943
|
linkNode.append(textNode);
|
|
5645
5944
|
selection.insertNodes([linkNode]);
|
|
5646
5945
|
}
|
|
5647
|
-
setIsOpen(false);
|
|
5648
5946
|
});
|
|
5947
|
+
handleClose();
|
|
5649
5948
|
};
|
|
5949
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5950
|
+
!isControlled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5951
|
+
reactComponents.Button,
|
|
5952
|
+
{
|
|
5953
|
+
size: "small",
|
|
5954
|
+
title: "Add link",
|
|
5955
|
+
disabled,
|
|
5956
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.LinkAddRegular, { style: { color: iconColor } }),
|
|
5957
|
+
style: {
|
|
5958
|
+
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
5959
|
+
border: "none",
|
|
5960
|
+
margin: 2,
|
|
5961
|
+
opacity: disabled ? 0.55 : 1,
|
|
5962
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
5963
|
+
},
|
|
5964
|
+
onClick: () => {
|
|
5965
|
+
if (disabled) return;
|
|
5966
|
+
setInternalOpen((prev) => !prev);
|
|
5967
|
+
}
|
|
5968
|
+
},
|
|
5969
|
+
"upload-link"
|
|
5970
|
+
),
|
|
5971
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5972
|
+
reactComponents.Dialog,
|
|
5973
|
+
{
|
|
5974
|
+
open: isOpen,
|
|
5975
|
+
onOpenChange: (_, data) => {
|
|
5976
|
+
if (!data.open) handleClose();
|
|
5977
|
+
},
|
|
5978
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogSurface, { style: { maxWidth: "380px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogBody, { children: [
|
|
5979
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTitle, { children: "Insert Link" }),
|
|
5980
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogContent, { children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 10 }, style: { paddingTop: 8 }, children: [
|
|
5981
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Text", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5982
|
+
reactComponents.Input,
|
|
5983
|
+
{
|
|
5984
|
+
autoFocus: !disabled,
|
|
5985
|
+
value: text,
|
|
5986
|
+
appearance: "underline",
|
|
5987
|
+
placeholder: "Text",
|
|
5988
|
+
disabled,
|
|
5989
|
+
onChange: (_, v) => setText(v.value)
|
|
5990
|
+
}
|
|
5991
|
+
) }),
|
|
5992
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5993
|
+
reactComponents.Field,
|
|
5994
|
+
{
|
|
5995
|
+
label: "Link",
|
|
5996
|
+
orientation: "horizontal",
|
|
5997
|
+
size: "small",
|
|
5998
|
+
validationState: linkError ? "error" : "none",
|
|
5999
|
+
validationMessage: linkError,
|
|
6000
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6001
|
+
reactComponents.Input,
|
|
6002
|
+
{
|
|
6003
|
+
value: link$1,
|
|
6004
|
+
appearance: "underline",
|
|
6005
|
+
placeholder: "Link",
|
|
6006
|
+
disabled,
|
|
6007
|
+
onChange: (_, v) => setLink(v.value),
|
|
6008
|
+
onKeyDown: (e) => {
|
|
6009
|
+
if (e.key === "Enter" && text && link$1 && !linkError) insertLink(text, link$1);
|
|
6010
|
+
}
|
|
6011
|
+
}
|
|
6012
|
+
)
|
|
6013
|
+
}
|
|
6014
|
+
)
|
|
6015
|
+
] }) }),
|
|
6016
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogActions, { children: [
|
|
6017
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6018
|
+
reactComponents.Button,
|
|
6019
|
+
{
|
|
6020
|
+
appearance: "primary",
|
|
6021
|
+
size: "small",
|
|
6022
|
+
disabled: disabled || !text || !link$1 || !!linkError,
|
|
6023
|
+
onClick: () => insertLink(text, link$1),
|
|
6024
|
+
children: "Add"
|
|
6025
|
+
}
|
|
6026
|
+
),
|
|
6027
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: handleClose, children: "Cancel" })
|
|
6028
|
+
] })
|
|
6029
|
+
] }) })
|
|
6030
|
+
}
|
|
6031
|
+
)
|
|
6032
|
+
] });
|
|
6033
|
+
};
|
|
6034
|
+
function PageSetupPlugin({ disabled, value, onChange }) {
|
|
6035
|
+
const sizeLabel = value.size === "pageless" ? "Pageless" : PAGE_SIZE_OPTIONS.find((o) => o.key === value.size)?.label ?? "Pageless";
|
|
6036
|
+
const isPaged = value.size !== "pageless";
|
|
5650
6037
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5651
|
-
reactComponents.
|
|
6038
|
+
reactComponents.Menu,
|
|
5652
6039
|
{
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
6040
|
+
checkedValues: {
|
|
6041
|
+
size: [value.size],
|
|
6042
|
+
orientation: [value.orientation],
|
|
6043
|
+
margin: [value.margin]
|
|
6044
|
+
},
|
|
6045
|
+
onCheckedValueChange: (_, data) => {
|
|
6046
|
+
const selected = data.checkedItems[0];
|
|
6047
|
+
if (!selected) return;
|
|
6048
|
+
if (data.name === "size") onChange({ ...value, size: selected });
|
|
6049
|
+
else if (data.name === "orientation")
|
|
6050
|
+
onChange({ ...value, orientation: selected });
|
|
6051
|
+
else if (data.name === "margin") onChange({ ...value, margin: selected });
|
|
5658
6052
|
},
|
|
5659
6053
|
children: [
|
|
5660
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.
|
|
6054
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5661
6055
|
reactComponents.Button,
|
|
5662
6056
|
{
|
|
6057
|
+
appearance: "subtle",
|
|
5663
6058
|
size: "small",
|
|
5664
|
-
title: "Add link",
|
|
5665
6059
|
disabled,
|
|
5666
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
margin: 2,
|
|
5671
|
-
opacity: disabled ? 0.55 : 1,
|
|
5672
|
-
cursor: disabled ? "not-allowed" : "pointer"
|
|
5673
|
-
},
|
|
5674
|
-
onClick: () => {
|
|
5675
|
-
if (!disabled) setIsOpen((prev) => !prev);
|
|
5676
|
-
}
|
|
5677
|
-
},
|
|
5678
|
-
"upload-link"
|
|
5679
|
-
) }),
|
|
5680
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5681
|
-
reactComponents.PopoverSurface,
|
|
5682
|
-
{
|
|
5683
|
-
style: {
|
|
5684
|
-
width: "270px",
|
|
5685
|
-
opacity: disabled ? 0.6 : 1,
|
|
5686
|
-
pointerEvents: disabled ? "none" : "auto"
|
|
5687
|
-
},
|
|
5688
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 10 }, children: [
|
|
5689
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Text", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5690
|
-
reactComponents.Input,
|
|
5691
|
-
{
|
|
5692
|
-
autoFocus: !disabled,
|
|
5693
|
-
value: text,
|
|
5694
|
-
appearance: "underline",
|
|
5695
|
-
placeholder: "Text",
|
|
5696
|
-
disabled,
|
|
5697
|
-
onChange: (_, v) => setText(v.value)
|
|
5698
|
-
}
|
|
5699
|
-
) }),
|
|
5700
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Link", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5701
|
-
reactComponents.Input,
|
|
5702
|
-
{
|
|
5703
|
-
value: link$1,
|
|
5704
|
-
appearance: "underline",
|
|
5705
|
-
placeholder: "Link",
|
|
5706
|
-
disabled,
|
|
5707
|
-
onChange: (_, v) => setLink(v.value)
|
|
5708
|
-
}
|
|
5709
|
-
) }),
|
|
5710
|
-
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { horizontal: true, horizontalAlign: "end", tokens: { childrenGap: 6 }, children: [
|
|
5711
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5712
|
-
reactComponents.Button,
|
|
5713
|
-
{
|
|
5714
|
-
size: "small",
|
|
5715
|
-
disabled: disabled || !text || !link$1,
|
|
5716
|
-
onClick: () => insertLink(text, link$1),
|
|
5717
|
-
children: "Add"
|
|
5718
|
-
}
|
|
5719
|
-
),
|
|
5720
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: () => setIsOpen(false), children: "Cancel" })
|
|
5721
|
-
] })
|
|
5722
|
-
] })
|
|
6060
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DocumentRegular, {}),
|
|
6061
|
+
title: "Page setup",
|
|
6062
|
+
style: { minWidth: "auto" },
|
|
6063
|
+
children: sizeLabel
|
|
5723
6064
|
}
|
|
5724
|
-
)
|
|
6065
|
+
) }),
|
|
6066
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuPopover, { style: { minWidth: 220 }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuList, { children: [
|
|
6067
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuGroup, { children: [
|
|
6068
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuGroupHeader, { children: "Page size" }),
|
|
6069
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItemRadio, { name: "size", value: "pageless", children: "Pageless" }),
|
|
6070
|
+
PAGE_SIZE_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItemRadio, { name: "size", value: opt.key, children: opt.label }, opt.key))
|
|
6071
|
+
] }),
|
|
6072
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuDivider, {}),
|
|
6073
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuGroup, { children: [
|
|
6074
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuGroupHeader, { children: "Orientation" }),
|
|
6075
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItemRadio, { name: "orientation", value: "portrait", disabled: !isPaged, children: "Portrait" }),
|
|
6076
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItemRadio, { name: "orientation", value: "landscape", disabled: !isPaged, children: "Landscape" })
|
|
6077
|
+
] }),
|
|
6078
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuDivider, {}),
|
|
6079
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuGroup, { children: [
|
|
6080
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuGroupHeader, { children: "Margins" }),
|
|
6081
|
+
MARGIN_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItemRadio, { name: "margin", value: opt.key, disabled: !isPaged, children: opt.label }, opt.key))
|
|
6082
|
+
] })
|
|
6083
|
+
] }) })
|
|
5725
6084
|
]
|
|
5726
6085
|
}
|
|
5727
6086
|
);
|
|
5728
|
-
}
|
|
5729
|
-
var
|
|
6087
|
+
}
|
|
6088
|
+
var MAX_ROWS = 50;
|
|
6089
|
+
var MAX_COLS = 50;
|
|
6090
|
+
var TableItemPlugin = ({
|
|
6091
|
+
disabled,
|
|
6092
|
+
open: externalOpen,
|
|
6093
|
+
onClose
|
|
6094
|
+
}) => {
|
|
5730
6095
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
5731
6096
|
const [columns, setColumns] = React9.useState("");
|
|
5732
6097
|
const [rows, setRows] = React9.useState("");
|
|
5733
|
-
const [
|
|
6098
|
+
const [internalOpen, setInternalOpen] = React9.useState(false);
|
|
6099
|
+
const [rowError, setRowError] = React9.useState("");
|
|
6100
|
+
const [colError, setColError] = React9.useState("");
|
|
6101
|
+
const isControlled = externalOpen !== void 0;
|
|
6102
|
+
const isOpen = isControlled ? !!externalOpen && !disabled : internalOpen && !disabled;
|
|
5734
6103
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#333333";
|
|
6104
|
+
const handleClose = () => {
|
|
6105
|
+
setRows("");
|
|
6106
|
+
setColumns("");
|
|
6107
|
+
setRowError("");
|
|
6108
|
+
setColError("");
|
|
6109
|
+
if (isControlled) onClose?.();
|
|
6110
|
+
else setInternalOpen(false);
|
|
6111
|
+
};
|
|
6112
|
+
const onRowsChange = (val) => {
|
|
6113
|
+
const clean = val.replace(/\D/g, "");
|
|
6114
|
+
setRows(clean);
|
|
6115
|
+
const n = Number(clean);
|
|
6116
|
+
if (clean && n > MAX_ROWS) setRowError(`Maximum ${MAX_ROWS} rows allowed`);
|
|
6117
|
+
else setRowError("");
|
|
6118
|
+
};
|
|
6119
|
+
const onColsChange = (val) => {
|
|
6120
|
+
const clean = val.replace(/\D/g, "");
|
|
6121
|
+
setColumns(clean);
|
|
6122
|
+
const n = Number(clean);
|
|
6123
|
+
if (clean && n > MAX_COLS) setColError(`Maximum ${MAX_COLS} columns allowed`);
|
|
6124
|
+
else setColError("");
|
|
6125
|
+
};
|
|
5735
6126
|
const onAddTable = () => {
|
|
5736
6127
|
if (disabled) return;
|
|
5737
6128
|
const row = Number(rows);
|
|
5738
6129
|
const col = Number(columns);
|
|
5739
6130
|
if (!row || !col) return;
|
|
6131
|
+
if (row > MAX_ROWS || col > MAX_COLS) return;
|
|
5740
6132
|
editor.update(() => {
|
|
5741
6133
|
const tableNode = table.$createTableNodeWithDimensions(row, col, true);
|
|
5742
6134
|
utils.$insertNodeToNearestRoot(tableNode);
|
|
5743
6135
|
});
|
|
5744
|
-
|
|
5745
|
-
setColumns("");
|
|
5746
|
-
setIsOpen(false);
|
|
6136
|
+
handleClose();
|
|
5747
6137
|
};
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
6138
|
+
const isAddDisabled = disabled || !rows || !columns || !!rowError || !!colError;
|
|
6139
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6140
|
+
!isControlled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6141
|
+
reactComponents.Button,
|
|
6142
|
+
{
|
|
6143
|
+
size: "small",
|
|
6144
|
+
title: "Add table",
|
|
6145
|
+
disabled,
|
|
6146
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TableAddRegular, { style: { color: iconColor } }),
|
|
6147
|
+
style: {
|
|
6148
|
+
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
6149
|
+
border: "none",
|
|
6150
|
+
margin: 2,
|
|
6151
|
+
opacity: disabled ? 0.55 : 1,
|
|
6152
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
6153
|
+
},
|
|
6154
|
+
onClick: () => {
|
|
6155
|
+
if (disabled) return;
|
|
6156
|
+
setRows("");
|
|
6157
|
+
setColumns("");
|
|
6158
|
+
setRowError("");
|
|
6159
|
+
setColError("");
|
|
6160
|
+
setInternalOpen(true);
|
|
6161
|
+
}
|
|
5756
6162
|
},
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
"insert-table-nodes"
|
|
5780
|
-
) }),
|
|
5781
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5782
|
-
reactComponents.PopoverSurface,
|
|
5783
|
-
{
|
|
5784
|
-
style: {
|
|
5785
|
-
width: "270px",
|
|
5786
|
-
opacity: disabled ? 0.6 : 1,
|
|
5787
|
-
pointerEvents: disabled ? "none" : "auto"
|
|
5788
|
-
},
|
|
5789
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 10 }, children: [
|
|
5790
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Rows", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5791
|
-
reactComponents.Input,
|
|
5792
|
-
{
|
|
5793
|
-
autoFocus: !disabled,
|
|
5794
|
-
type: "number",
|
|
5795
|
-
min: 1,
|
|
5796
|
-
value: rows,
|
|
5797
|
-
placeholder: "Rows",
|
|
5798
|
-
appearance: "underline",
|
|
5799
|
-
disabled,
|
|
5800
|
-
input: { style: { textAlign: "left" } },
|
|
5801
|
-
onChange: (_, v) => setRows(v.value.replace(/\D/g, ""))
|
|
5802
|
-
}
|
|
5803
|
-
) }),
|
|
5804
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Columns", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5805
|
-
reactComponents.Input,
|
|
5806
|
-
{
|
|
5807
|
-
type: "number",
|
|
5808
|
-
min: 1,
|
|
5809
|
-
value: columns,
|
|
5810
|
-
placeholder: "Columns",
|
|
5811
|
-
appearance: "underline",
|
|
5812
|
-
disabled,
|
|
5813
|
-
input: { style: { textAlign: "left" } },
|
|
5814
|
-
onChange: (_, v) => setColumns(v.value.replace(/\D/g, ""))
|
|
5815
|
-
}
|
|
5816
|
-
) }),
|
|
5817
|
-
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { horizontal: true, horizontalAlign: "end", tokens: { childrenGap: 6 }, children: [
|
|
5818
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5819
|
-
reactComponents.Button,
|
|
6163
|
+
"insert-table-nodes"
|
|
6164
|
+
),
|
|
6165
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6166
|
+
reactComponents.Dialog,
|
|
6167
|
+
{
|
|
6168
|
+
open: isOpen,
|
|
6169
|
+
onOpenChange: (_, data) => {
|
|
6170
|
+
if (!data.open) handleClose();
|
|
6171
|
+
},
|
|
6172
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogSurface, { style: { maxWidth: "380px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogBody, { children: [
|
|
6173
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTitle, { children: "Insert Table" }),
|
|
6174
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogContent, { children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 10 }, style: { paddingTop: 8 }, children: [
|
|
6175
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6176
|
+
reactComponents.Field,
|
|
6177
|
+
{
|
|
6178
|
+
label: "Rows",
|
|
6179
|
+
orientation: "horizontal",
|
|
6180
|
+
size: "small",
|
|
6181
|
+
validationMessage: rowError || void 0,
|
|
6182
|
+
validationState: rowError ? "error" : "none",
|
|
6183
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6184
|
+
reactComponents.Input,
|
|
5820
6185
|
{
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
6186
|
+
autoFocus: !disabled,
|
|
6187
|
+
type: "number",
|
|
6188
|
+
min: 1,
|
|
6189
|
+
max: MAX_ROWS,
|
|
6190
|
+
value: rows,
|
|
6191
|
+
placeholder: "Rows",
|
|
6192
|
+
appearance: "underline",
|
|
6193
|
+
disabled,
|
|
6194
|
+
input: { style: { textAlign: "left" } },
|
|
6195
|
+
onChange: (_, v) => onRowsChange(v.value)
|
|
5826
6196
|
}
|
|
5827
|
-
)
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
6197
|
+
)
|
|
6198
|
+
}
|
|
6199
|
+
),
|
|
6200
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6201
|
+
reactComponents.Field,
|
|
6202
|
+
{
|
|
6203
|
+
label: "Columns",
|
|
6204
|
+
orientation: "horizontal",
|
|
6205
|
+
size: "small",
|
|
6206
|
+
validationMessage: colError || void 0,
|
|
6207
|
+
validationState: colError ? "error" : "none",
|
|
6208
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6209
|
+
reactComponents.Input,
|
|
6210
|
+
{
|
|
6211
|
+
type: "number",
|
|
6212
|
+
min: 1,
|
|
6213
|
+
max: MAX_COLS,
|
|
6214
|
+
value: columns,
|
|
6215
|
+
placeholder: "Columns",
|
|
6216
|
+
appearance: "underline",
|
|
6217
|
+
disabled,
|
|
6218
|
+
input: { style: { textAlign: "left" } },
|
|
6219
|
+
onChange: (_, v) => onColsChange(v.value)
|
|
6220
|
+
}
|
|
6221
|
+
)
|
|
6222
|
+
}
|
|
6223
|
+
)
|
|
6224
|
+
] }) }),
|
|
6225
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogActions, { children: [
|
|
6226
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6227
|
+
reactComponents.Button,
|
|
6228
|
+
{
|
|
6229
|
+
appearance: "primary",
|
|
6230
|
+
size: "small",
|
|
6231
|
+
disabled: isAddDisabled,
|
|
6232
|
+
onClick: onAddTable,
|
|
6233
|
+
children: "Add"
|
|
6234
|
+
}
|
|
6235
|
+
),
|
|
6236
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: handleClose, children: "Cancel" })
|
|
6237
|
+
] })
|
|
6238
|
+
] }) })
|
|
6239
|
+
}
|
|
6240
|
+
)
|
|
6241
|
+
] });
|
|
5836
6242
|
};
|
|
5837
|
-
|
|
6243
|
+
function extractYouTubeId(url) {
|
|
6244
|
+
const trimmed = url.trim();
|
|
6245
|
+
if (/^[\w-]{11}$/.test(trimmed)) return trimmed;
|
|
6246
|
+
const match = /(?:youtu\.be\/|youtube\.com\/(?:watch\?v=|embed\/|v\/|shorts\/|live\/|u\/\w\/))([^#&?]{11})/.exec(trimmed);
|
|
6247
|
+
return match ? match[1] : null;
|
|
6248
|
+
}
|
|
6249
|
+
var YoutubeUploadPlugin = ({
|
|
6250
|
+
disabled,
|
|
6251
|
+
open: externalOpen,
|
|
6252
|
+
onClose
|
|
6253
|
+
}) => {
|
|
5838
6254
|
const [url, setURL] = React9.useState("");
|
|
5839
|
-
const [
|
|
6255
|
+
const [urlError, setUrlError] = React9.useState("");
|
|
6256
|
+
const [internalOpen, setInternalOpen] = React9.useState(false);
|
|
5840
6257
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
5841
6258
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#424242";
|
|
6259
|
+
const isControlled = externalOpen !== void 0;
|
|
6260
|
+
const isOpen = isControlled ? !!externalOpen && !disabled : internalOpen && !disabled;
|
|
6261
|
+
const handleClose = () => {
|
|
6262
|
+
setURL("");
|
|
6263
|
+
setUrlError("");
|
|
6264
|
+
if (isControlled) onClose?.();
|
|
6265
|
+
else setInternalOpen(false);
|
|
6266
|
+
};
|
|
5842
6267
|
const onHandleEmbeded = () => {
|
|
5843
6268
|
if (disabled) return;
|
|
5844
6269
|
if (!url) return;
|
|
5845
|
-
const
|
|
5846
|
-
|
|
5847
|
-
|
|
6270
|
+
const id = extractYouTubeId(url);
|
|
6271
|
+
if (!id) {
|
|
6272
|
+
setUrlError("Invalid YouTube URL. Supported: watch?v=, youtu.be/, /shorts/, /live/");
|
|
6273
|
+
return;
|
|
6274
|
+
}
|
|
6275
|
+
setUrlError("");
|
|
5848
6276
|
editor.update(() => {
|
|
5849
6277
|
const node = $createYouTubeNode(id);
|
|
5850
6278
|
lexical.$insertNodes([node]);
|
|
5851
6279
|
});
|
|
5852
|
-
|
|
5853
|
-
setIsOpen(false);
|
|
6280
|
+
handleClose();
|
|
5854
6281
|
};
|
|
5855
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
reactComponents.
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
6282
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6283
|
+
!isControlled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6284
|
+
reactComponents.Button,
|
|
6285
|
+
{
|
|
6286
|
+
title: "Add youtube URL",
|
|
6287
|
+
size: "small",
|
|
6288
|
+
disabled,
|
|
6289
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.VideoClipRegular, { style: { color: iconColor } }),
|
|
6290
|
+
style: {
|
|
6291
|
+
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
6292
|
+
border: "none",
|
|
6293
|
+
margin: 2,
|
|
6294
|
+
opacity: disabled ? 0.55 : 1,
|
|
6295
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
6296
|
+
},
|
|
6297
|
+
onClick: () => {
|
|
6298
|
+
if (disabled) return;
|
|
6299
|
+
setURL("");
|
|
6300
|
+
setUrlError("");
|
|
6301
|
+
setInternalOpen(true);
|
|
6302
|
+
}
|
|
6303
|
+
},
|
|
6304
|
+
"upload-video"
|
|
6305
|
+
),
|
|
6306
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6307
|
+
reactComponents.Dialog,
|
|
6308
|
+
{
|
|
6309
|
+
open: isOpen,
|
|
6310
|
+
onOpenChange: (_, data) => {
|
|
6311
|
+
if (!data.open) handleClose();
|
|
6312
|
+
},
|
|
6313
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogSurface, { style: { maxWidth: "420px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogBody, { children: [
|
|
6314
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTitle, { children: "Insert YouTube Video" }),
|
|
6315
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogContent, { children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 10 }, style: { paddingTop: 8 }, children: [
|
|
6316
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6317
|
+
reactComponents.Field,
|
|
6318
|
+
{
|
|
6319
|
+
label: "URL",
|
|
6320
|
+
orientation: "horizontal",
|
|
6321
|
+
size: "small",
|
|
6322
|
+
validationState: urlError ? "error" : "none",
|
|
6323
|
+
validationMessage: urlError || void 0,
|
|
6324
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6325
|
+
reactComponents.Input,
|
|
6326
|
+
{
|
|
6327
|
+
autoFocus: !disabled,
|
|
6328
|
+
disabled,
|
|
6329
|
+
value: url,
|
|
6330
|
+
appearance: "underline",
|
|
6331
|
+
placeholder: "Paste YouTube URL or video ID\u2026",
|
|
6332
|
+
onChange: (_, v) => {
|
|
6333
|
+
setURL(v.value);
|
|
6334
|
+
if (urlError) setUrlError("");
|
|
6335
|
+
},
|
|
6336
|
+
onKeyDown: (e) => {
|
|
6337
|
+
if (e.key === "Enter") onHandleEmbeded();
|
|
6338
|
+
}
|
|
6339
|
+
}
|
|
6340
|
+
)
|
|
6341
|
+
}
|
|
6342
|
+
),
|
|
6343
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: "#94a3b8", lineHeight: 1.5 }, children: "Supports: youtube.com/watch?v=\u2026, youtu.be/\u2026, /shorts/\u2026, /live/\u2026" })
|
|
6344
|
+
] }) }),
|
|
6345
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogActions, { children: [
|
|
6346
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6347
|
+
reactComponents.Button,
|
|
6348
|
+
{
|
|
6349
|
+
appearance: "primary",
|
|
6350
|
+
size: "small",
|
|
6351
|
+
disabled: disabled || !url,
|
|
6352
|
+
onClick: onHandleEmbeded,
|
|
6353
|
+
children: "Add"
|
|
6354
|
+
}
|
|
6355
|
+
),
|
|
6356
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: handleClose, children: "Cancel" })
|
|
6357
|
+
] })
|
|
6358
|
+
] }) })
|
|
6359
|
+
}
|
|
6360
|
+
)
|
|
6361
|
+
] });
|
|
5917
6362
|
};
|
|
5918
6363
|
var useStyles4 = reactComponents.makeStyles({
|
|
5919
6364
|
dropdown: {
|
|
@@ -5938,12 +6383,14 @@ var ALLOWED_TOKENS = {
|
|
|
5938
6383
|
Image: true,
|
|
5939
6384
|
InlineImage: true,
|
|
5940
6385
|
Youtube: true,
|
|
6386
|
+
Insert: true,
|
|
5941
6387
|
Heading: true,
|
|
5942
6388
|
FontFamily: true,
|
|
5943
6389
|
FontSize: true,
|
|
5944
6390
|
Decorators: true,
|
|
5945
6391
|
CodeBlock: true,
|
|
5946
|
-
Align: true
|
|
6392
|
+
Align: true,
|
|
6393
|
+
PageSetup: true
|
|
5947
6394
|
};
|
|
5948
6395
|
function sanitizePluginGroups(groups) {
|
|
5949
6396
|
if (!groups || groups.length === 0) return [];
|
|
@@ -5968,6 +6415,7 @@ var ToolBarPlugins = (props) => {
|
|
|
5968
6415
|
const [isLowercase, setIsLowercase] = React9.useState(false);
|
|
5969
6416
|
const [isCapitalize, setIsCapitalize] = React9.useState(false);
|
|
5970
6417
|
const [alignment, setAlignment] = React9.useState("left");
|
|
6418
|
+
const [activeInsertDialog, setActiveInsertDialog] = React9.useState(null);
|
|
5971
6419
|
const lastSelectionRef = React9__namespace.default.useRef(null);
|
|
5972
6420
|
const presetGroups = getToolbarGroupsByLevel(props.level);
|
|
5973
6421
|
const pluginGroups = React9.useMemo(() => sanitizePluginGroups(presetGroups), [presetGroups]);
|
|
@@ -6213,6 +6661,7 @@ var ToolBarPlugins = (props) => {
|
|
|
6213
6661
|
marginRight: 8,
|
|
6214
6662
|
verticalAlign: "middle"
|
|
6215
6663
|
};
|
|
6664
|
+
const isDisabled = !isEditable || !!props.readOnly;
|
|
6216
6665
|
switch (token) {
|
|
6217
6666
|
case "Bold":
|
|
6218
6667
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -6276,6 +6725,95 @@ var ToolBarPlugins = (props) => {
|
|
|
6276
6725
|
);
|
|
6277
6726
|
case "Youtube":
|
|
6278
6727
|
return /* @__PURE__ */ jsxRuntime.jsx(YoutubeUploadPlugin, { disabled: !isEditable || props.readOnly }, key);
|
|
6728
|
+
case "Insert": {
|
|
6729
|
+
const menuIconColor = isDisabled ? fgDisabled : fg;
|
|
6730
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React9__namespace.default.Fragment, { children: [
|
|
6731
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Menu, { children: [
|
|
6732
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6733
|
+
reactComponents.Button,
|
|
6734
|
+
{
|
|
6735
|
+
size: "small",
|
|
6736
|
+
disabled: isDisabled,
|
|
6737
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.AddRegular, { style: { color: menuIconColor } }),
|
|
6738
|
+
style: {
|
|
6739
|
+
...getButtonStyle(false),
|
|
6740
|
+
gap: 4,
|
|
6741
|
+
paddingInline: 8
|
|
6742
|
+
},
|
|
6743
|
+
children: "Insert"
|
|
6744
|
+
}
|
|
6745
|
+
) }),
|
|
6746
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuPopover, { children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuList, { children: [
|
|
6747
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6748
|
+
reactComponents.MenuItem,
|
|
6749
|
+
{
|
|
6750
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TableAddRegular, { style: { color: menuIconColor } }),
|
|
6751
|
+
onClick: () => !isDisabled && setActiveInsertDialog("table"),
|
|
6752
|
+
children: "Table"
|
|
6753
|
+
}
|
|
6754
|
+
),
|
|
6755
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6756
|
+
reactComponents.MenuItem,
|
|
6757
|
+
{
|
|
6758
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ImageAddRegular, { style: { color: menuIconColor } }),
|
|
6759
|
+
onClick: () => !isDisabled && setActiveInsertDialog("image"),
|
|
6760
|
+
children: "Image"
|
|
6761
|
+
}
|
|
6762
|
+
),
|
|
6763
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6764
|
+
reactComponents.MenuItem,
|
|
6765
|
+
{
|
|
6766
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ImageEditRegular, { style: { color: menuIconColor } }),
|
|
6767
|
+
onClick: () => !isDisabled && setActiveInsertDialog("inlineImage"),
|
|
6768
|
+
children: "Inline Image"
|
|
6769
|
+
}
|
|
6770
|
+
),
|
|
6771
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6772
|
+
reactComponents.MenuItem,
|
|
6773
|
+
{
|
|
6774
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.VideoClipRegular, { style: { color: menuIconColor } }),
|
|
6775
|
+
onClick: () => !isDisabled && setActiveInsertDialog("youtube"),
|
|
6776
|
+
children: "YouTube"
|
|
6777
|
+
}
|
|
6778
|
+
)
|
|
6779
|
+
] }) })
|
|
6780
|
+
] }),
|
|
6781
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6782
|
+
TableItemPlugin,
|
|
6783
|
+
{
|
|
6784
|
+
disabled: isDisabled,
|
|
6785
|
+
open: activeInsertDialog === "table",
|
|
6786
|
+
onClose: () => setActiveInsertDialog(null)
|
|
6787
|
+
}
|
|
6788
|
+
),
|
|
6789
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6790
|
+
InsertImageDialog,
|
|
6791
|
+
{
|
|
6792
|
+
activeEditor: editor,
|
|
6793
|
+
disabled: isDisabled,
|
|
6794
|
+
open: activeInsertDialog === "image",
|
|
6795
|
+
onClose: () => setActiveInsertDialog(null)
|
|
6796
|
+
}
|
|
6797
|
+
),
|
|
6798
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6799
|
+
InsertInlineImageDialog,
|
|
6800
|
+
{
|
|
6801
|
+
activeEditor: editor,
|
|
6802
|
+
disabled: isDisabled,
|
|
6803
|
+
open: activeInsertDialog === "inlineImage",
|
|
6804
|
+
onClose: () => setActiveInsertDialog(null)
|
|
6805
|
+
}
|
|
6806
|
+
),
|
|
6807
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6808
|
+
YoutubeUploadPlugin,
|
|
6809
|
+
{
|
|
6810
|
+
disabled: isDisabled,
|
|
6811
|
+
open: activeInsertDialog === "youtube",
|
|
6812
|
+
onClose: () => setActiveInsertDialog(null)
|
|
6813
|
+
}
|
|
6814
|
+
)
|
|
6815
|
+
] }, key);
|
|
6816
|
+
}
|
|
6279
6817
|
case "Heading": {
|
|
6280
6818
|
const headingLabel = selectNodeType === "paragraph" ? "Normal" : HEADING_OPTION.find((h) => h.key === selectNodeType)?.text ?? selectNodeType;
|
|
6281
6819
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -6482,6 +7020,16 @@ var ToolBarPlugins = (props) => {
|
|
|
6482
7020
|
key
|
|
6483
7021
|
);
|
|
6484
7022
|
}
|
|
7023
|
+
case "PageSetup":
|
|
7024
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7025
|
+
PageSetupPlugin,
|
|
7026
|
+
{
|
|
7027
|
+
disabled: !isEditable || props.readOnly,
|
|
7028
|
+
value: props.pageSetup,
|
|
7029
|
+
onChange: props.onPageSetupChange
|
|
7030
|
+
},
|
|
7031
|
+
key
|
|
7032
|
+
);
|
|
6485
7033
|
default:
|
|
6486
7034
|
return null;
|
|
6487
7035
|
}
|
|
@@ -6661,7 +7209,9 @@ function BrowserSpellCheckPlugin({ enabled }) {
|
|
|
6661
7209
|
}, [editor, enabled]);
|
|
6662
7210
|
return null;
|
|
6663
7211
|
}
|
|
6664
|
-
function WordCountPlugin({
|
|
7212
|
+
function WordCountPlugin({
|
|
7213
|
+
onCountChange
|
|
7214
|
+
}) {
|
|
6665
7215
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
6666
7216
|
React9.useEffect(() => {
|
|
6667
7217
|
return editor.registerUpdateListener(({ editorState }) => {
|
|
@@ -6674,7 +7224,9 @@ function WordCountPlugin({ onCountChange }) {
|
|
|
6674
7224
|
}, [editor, onCountChange]);
|
|
6675
7225
|
return null;
|
|
6676
7226
|
}
|
|
6677
|
-
function CharCountPlugin({
|
|
7227
|
+
function CharCountPlugin({
|
|
7228
|
+
onCountChange
|
|
7229
|
+
}) {
|
|
6678
7230
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
6679
7231
|
React9.useEffect(() => {
|
|
6680
7232
|
return editor.registerUpdateListener(({ editorState }) => {
|
|
@@ -6758,7 +7310,10 @@ function _adaptRawSpell(data, text) {
|
|
|
6758
7310
|
}
|
|
6759
7311
|
const rawGrammar = data.grammar_correction ?? data.improved_text;
|
|
6760
7312
|
const grammarCorrection = rawGrammar && rawGrammar.trim() !== text.trim() ? rawGrammar.trim() : void 0;
|
|
6761
|
-
return {
|
|
7313
|
+
return {
|
|
7314
|
+
issues: issues.sort((a, b) => a.offset - b.offset),
|
|
7315
|
+
grammarCorrection
|
|
7316
|
+
};
|
|
6762
7317
|
}
|
|
6763
7318
|
function _adaptRawSuggest(data) {
|
|
6764
7319
|
if (!data) return null;
|
|
@@ -6813,348 +7368,385 @@ function _makeQueryFn(fn) {
|
|
|
6813
7368
|
};
|
|
6814
7369
|
};
|
|
6815
7370
|
}
|
|
6816
|
-
var ContentEditorComponent = React9.forwardRef(
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
);
|
|
6905
|
-
const validateUrl = (url) => url === "https://" || urlRegExp.test(url);
|
|
6906
|
-
const handleReadOnlyClickCapture = (e) => {
|
|
6907
|
-
if (!isReadOnly) return;
|
|
6908
|
-
const target = e.target;
|
|
6909
|
-
const anchor = target?.closest?.("a");
|
|
6910
|
-
if (anchor) {
|
|
6911
|
-
e.preventDefault();
|
|
6912
|
-
e.stopPropagation();
|
|
7371
|
+
var ContentEditorComponent = React9.forwardRef((props, ref) => {
|
|
7372
|
+
const isReadOnly = !!props.readOnly;
|
|
7373
|
+
const resolvedSpellCheck = React9__namespace.default.useMemo(
|
|
7374
|
+
() => props.spellCheckFn ? _makeSpellCheckFn(props.spellCheckFn) : props.useSpellCheck,
|
|
7375
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
7376
|
+
[props.spellCheckFn, props.useSpellCheck]
|
|
7377
|
+
);
|
|
7378
|
+
const resolvedQuery = React9__namespace.default.useMemo(
|
|
7379
|
+
() => props.suggestFn ? _makeQueryFn(props.suggestFn) : props.useQuery,
|
|
7380
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
7381
|
+
[props.suggestFn, props.useQuery]
|
|
7382
|
+
);
|
|
7383
|
+
const [floatingAnchorElem, setFloatingAnchorElem] = React9.useState(null);
|
|
7384
|
+
const [isLinkEditMode, setIsLinkEditMode] = React9.useState(false);
|
|
7385
|
+
const [wordCount, setWordCount] = React9.useState(0);
|
|
7386
|
+
const handleWordCount = React9.useCallback(
|
|
7387
|
+
(count) => setWordCount(count),
|
|
7388
|
+
[]
|
|
7389
|
+
);
|
|
7390
|
+
const [charCount, setCharCount] = React9.useState(0);
|
|
7391
|
+
const handleCharCount = React9.useCallback(
|
|
7392
|
+
(count) => setCharCount(count),
|
|
7393
|
+
[]
|
|
7394
|
+
);
|
|
7395
|
+
const [refErrors, setRefErrors] = React9.useState([]);
|
|
7396
|
+
const [pageSetup, setPageSetup] = React9.useState(DEFAULT_PAGE_SETUP);
|
|
7397
|
+
const pageCanvas = resolvePageCanvasMetrics(pageSetup);
|
|
7398
|
+
const contentEditableDomRef = React9.useRef(null);
|
|
7399
|
+
const previousOverLimitRef = React9.useRef(false);
|
|
7400
|
+
const focusedRef = React9.useRef(false);
|
|
7401
|
+
const setFocused = (focused) => {
|
|
7402
|
+
focusedRef.current = focused;
|
|
7403
|
+
};
|
|
7404
|
+
const containerRef = React9.useRef(null);
|
|
7405
|
+
const onAnchorRef = (elem) => {
|
|
7406
|
+
if (elem) setFloatingAnchorElem(elem);
|
|
7407
|
+
};
|
|
7408
|
+
const initialConfig = {
|
|
7409
|
+
namespace: props.namespace,
|
|
7410
|
+
theme,
|
|
7411
|
+
onError: () => {
|
|
7412
|
+
},
|
|
7413
|
+
nodes: [
|
|
7414
|
+
richText.HeadingNode,
|
|
7415
|
+
richText.QuoteNode,
|
|
7416
|
+
code.CodeHighlightNode,
|
|
7417
|
+
code.CodeNode,
|
|
7418
|
+
list.ListNode,
|
|
7419
|
+
list.ListItemNode,
|
|
7420
|
+
link.LinkNode,
|
|
7421
|
+
link.AutoLinkNode,
|
|
7422
|
+
table.TableNode,
|
|
7423
|
+
table.TableRowNode,
|
|
7424
|
+
table.TableCellNode,
|
|
7425
|
+
ImageNode,
|
|
7426
|
+
InlineImageNode,
|
|
7427
|
+
YouTubeNode,
|
|
7428
|
+
PageBreakNode,
|
|
7429
|
+
AutocompleteNode,
|
|
7430
|
+
SpellErrorNode,
|
|
7431
|
+
HtmlBlockNode
|
|
7432
|
+
]
|
|
7433
|
+
};
|
|
7434
|
+
const EditorStyles = react.mergeStyleSets({
|
|
7435
|
+
editorPlaceholder: {
|
|
7436
|
+
color: "var(--colorNeutralForeground3, grey)",
|
|
7437
|
+
position: "absolute",
|
|
7438
|
+
top: props.level !== "none" /* None */ ? "17px" : "27px",
|
|
7439
|
+
left: pageCanvas.paddingPx,
|
|
7440
|
+
right: pageCanvas.paddingPx,
|
|
7441
|
+
fontSize: "14px",
|
|
7442
|
+
pointerEvents: "none",
|
|
7443
|
+
userSelect: "none"
|
|
7444
|
+
},
|
|
7445
|
+
contentEditor: {
|
|
7446
|
+
zIndex: 0,
|
|
7447
|
+
flex: "auto",
|
|
7448
|
+
outline: "none",
|
|
7449
|
+
overflow: "auto",
|
|
7450
|
+
marginTop: "0px",
|
|
7451
|
+
position: "relative",
|
|
7452
|
+
background: "var(--colorNeutralBackground1, #ffffff)",
|
|
7453
|
+
justifyContent: "center",
|
|
7454
|
+
height: props.contentHeight ?? "100%",
|
|
7455
|
+
...isReadOnly && {
|
|
7456
|
+
cursor: "not-allowed",
|
|
7457
|
+
opacity: 0.75,
|
|
7458
|
+
userSelect: "text"
|
|
6913
7459
|
}
|
|
6914
|
-
};
|
|
6915
|
-
const [touched, setTouched] = React9.useState(false);
|
|
6916
|
-
const isOverLimit = props.wordLimit !== void 0 && wordCount > props.wordLimit;
|
|
6917
|
-
const internalErrors = [];
|
|
6918
|
-
if (isOverLimit) {
|
|
6919
|
-
const m = props.errorMessages?.wordLimitExceeded;
|
|
6920
|
-
internalErrors.push(
|
|
6921
|
-
typeof m === "function" ? m(wordCount, props.wordLimit) : m ?? `Word limit exceeded (${wordCount} / ${props.wordLimit} words used)`
|
|
6922
|
-
);
|
|
6923
|
-
}
|
|
6924
|
-
if (props.required && touched && wordCount === 0) {
|
|
6925
|
-
internalErrors.push(
|
|
6926
|
-
props.errorMessages?.required ?? "This field is required"
|
|
6927
|
-
);
|
|
6928
7460
|
}
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
if (
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
);
|
|
7461
|
+
});
|
|
7462
|
+
const urlRegExp = new RegExp(
|
|
7463
|
+
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/
|
|
7464
|
+
);
|
|
7465
|
+
const validateUrl = (url) => url === "https://" || urlRegExp.test(url);
|
|
7466
|
+
const handleReadOnlyClickCapture = (e) => {
|
|
7467
|
+
if (!isReadOnly) return;
|
|
7468
|
+
const target = e.target;
|
|
7469
|
+
const anchor = target?.closest?.("a");
|
|
7470
|
+
if (anchor) {
|
|
7471
|
+
e.preventDefault();
|
|
7472
|
+
e.stopPropagation();
|
|
6940
7473
|
}
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
7474
|
+
};
|
|
7475
|
+
const [touched, setTouched] = React9.useState(false);
|
|
7476
|
+
const isOverLimit = props.wordLimit !== void 0 && wordCount > props.wordLimit;
|
|
7477
|
+
const internalErrors = [];
|
|
7478
|
+
if (isOverLimit) {
|
|
7479
|
+
const m = props.errorMessages?.wordLimitExceeded;
|
|
7480
|
+
internalErrors.push(
|
|
7481
|
+
typeof m === "function" ? m(wordCount, props.wordLimit) : m ?? `Word limit exceeded (${wordCount} / ${props.wordLimit} words used)`
|
|
7482
|
+
);
|
|
7483
|
+
}
|
|
7484
|
+
if (props.required && touched && wordCount === 0) {
|
|
7485
|
+
internalErrors.push(
|
|
7486
|
+
props.errorMessages?.required ?? "This field is required"
|
|
7487
|
+
);
|
|
7488
|
+
}
|
|
7489
|
+
if (props.minWords !== void 0 && touched && wordCount < props.minWords) {
|
|
7490
|
+
const m = props.errorMessages?.minWords;
|
|
7491
|
+
internalErrors.push(
|
|
7492
|
+
typeof m === "function" ? m(wordCount, props.minWords) : m ?? `Minimum ${props.minWords} words required (${wordCount} entered)`
|
|
7493
|
+
);
|
|
7494
|
+
}
|
|
7495
|
+
if (props.maxChars !== void 0 && charCount > props.maxChars) {
|
|
7496
|
+
const m = props.errorMessages?.maxCharsExceeded;
|
|
7497
|
+
internalErrors.push(
|
|
7498
|
+
typeof m === "function" ? m(charCount, props.maxChars) : m ?? `Character limit exceeded (${charCount} / ${props.maxChars} characters used)`
|
|
7499
|
+
);
|
|
7500
|
+
}
|
|
7501
|
+
if (props.minChars !== void 0 && touched && charCount < props.minChars && charCount > 0) {
|
|
7502
|
+
const m = props.errorMessages?.minCharsRequired;
|
|
7503
|
+
internalErrors.push(
|
|
7504
|
+
typeof m === "function" ? m(charCount, props.minChars) : m ?? `Minimum ${props.minChars} characters required (${charCount} entered)`
|
|
7505
|
+
);
|
|
7506
|
+
}
|
|
7507
|
+
const allErrors = [
|
|
7508
|
+
...internalErrors,
|
|
7509
|
+
...props.errors ?? [],
|
|
7510
|
+
...refErrors
|
|
7511
|
+
];
|
|
7512
|
+
const hasErrors = allErrors.length > 0;
|
|
7513
|
+
const hasRedBorder = hasErrors;
|
|
7514
|
+
React9.useEffect(() => {
|
|
7515
|
+
if (props.wordLimit === void 0 || !props.onWordLimitExceeded) return;
|
|
7516
|
+
const wasOverLimit = previousOverLimitRef.current;
|
|
7517
|
+
if (isOverLimit !== wasOverLimit) {
|
|
7518
|
+
props.onWordLimitExceeded({
|
|
7519
|
+
wordCount,
|
|
7520
|
+
wordLimit: props.wordLimit,
|
|
7521
|
+
exceeded: isOverLimit
|
|
7522
|
+
});
|
|
7523
|
+
previousOverLimitRef.current = isOverLimit;
|
|
6946
7524
|
}
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
}
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6965
|
-
|
|
6966
|
-
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
7525
|
+
}, [isOverLimit, wordCount, props.wordLimit, props.onWordLimitExceeded]);
|
|
7526
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactComponents.FluentProvider, { theme: reactComponents.webLightTheme, style: { height: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsx(LexicalComposer.LexicalComposer, { initialConfig, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, style: { height: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7527
|
+
react.Stack,
|
|
7528
|
+
{
|
|
7529
|
+
style: {
|
|
7530
|
+
zIndex: 1e3,
|
|
7531
|
+
background: "#fff",
|
|
7532
|
+
borderRadius: "2px",
|
|
7533
|
+
width: props.width ?? "100%",
|
|
7534
|
+
height: props.height ?? "100%",
|
|
7535
|
+
margin: props.margin ?? "5px auto",
|
|
7536
|
+
border: `1px solid ${hasRedBorder ? "#c4272c" : "var(--colorNeutralStroke1, #ccced1)"}`,
|
|
7537
|
+
transition: "border-color 0.2s",
|
|
7538
|
+
display: "flex",
|
|
7539
|
+
flexDirection: "column"
|
|
7540
|
+
},
|
|
7541
|
+
children: [
|
|
7542
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7543
|
+
"div",
|
|
7544
|
+
{
|
|
7545
|
+
style: {
|
|
7546
|
+
pointerEvents: isReadOnly ? "none" : "auto",
|
|
7547
|
+
position: "sticky",
|
|
7548
|
+
opacity: isReadOnly ? 0.85 : 1
|
|
7549
|
+
},
|
|
7550
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7551
|
+
ToolBarPlugins,
|
|
7552
|
+
{
|
|
7553
|
+
level: props.level ?? "basic" /* Basic */,
|
|
7554
|
+
readOnly: props.readOnly,
|
|
7555
|
+
pageSetup,
|
|
7556
|
+
onPageSetupChange: setPageSetup
|
|
7557
|
+
}
|
|
7558
|
+
)
|
|
7559
|
+
}
|
|
7560
|
+
),
|
|
7561
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7562
|
+
"div",
|
|
7563
|
+
{
|
|
7564
|
+
style: {
|
|
7565
|
+
position: "relative",
|
|
7566
|
+
flexGrow: 1,
|
|
7567
|
+
padding: "15px 0px",
|
|
7568
|
+
overflowY: "scroll",
|
|
7569
|
+
overflowX: "auto",
|
|
7570
|
+
minWidth: 0,
|
|
7571
|
+
background: pageCanvas.widthPx !== void 0 ? "#eef0f2" : void 0
|
|
7572
|
+
},
|
|
7573
|
+
onClickCapture: handleReadOnlyClickCapture,
|
|
7574
|
+
children: [
|
|
7575
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7576
|
+
LexicalRichTextPlugin.RichTextPlugin,
|
|
7577
|
+
{
|
|
7578
|
+
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary,
|
|
7579
|
+
contentEditable: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7580
|
+
"div",
|
|
7581
|
+
{
|
|
7582
|
+
className: "editor",
|
|
7583
|
+
style: { height: "100%", position: "relative" },
|
|
7584
|
+
ref: onAnchorRef,
|
|
7585
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7586
|
+
LexicalContentEditable.ContentEditable,
|
|
7587
|
+
{
|
|
7588
|
+
ref: contentEditableDomRef,
|
|
7589
|
+
className: react.css(EditorStyles.contentEditor),
|
|
7590
|
+
style: {
|
|
7591
|
+
paddingTop: props.level !== "none" /* None */ ? 0 : 10,
|
|
7592
|
+
paddingLeft: pageCanvas.paddingPx,
|
|
7593
|
+
paddingRight: pageCanvas.paddingPx,
|
|
7594
|
+
maxWidth: pageCanvas.widthPx,
|
|
7595
|
+
marginLeft: pageCanvas.widthPx !== void 0 ? "auto" : void 0,
|
|
7596
|
+
marginRight: pageCanvas.widthPx !== void 0 ? "auto" : void 0,
|
|
7597
|
+
boxShadow: pageCanvas.widthPx !== void 0 ? "0 0 0 1px rgba(0,0,0,0.08), 0 2px 8px rgba(0,0,0,0.08)" : void 0
|
|
7598
|
+
},
|
|
7599
|
+
spellCheck: !resolvedSpellCheck,
|
|
7600
|
+
autoCorrect: resolvedSpellCheck ? "off" : void 0,
|
|
7601
|
+
autoCapitalize: resolvedSpellCheck ? "off" : void 0
|
|
7602
|
+
}
|
|
7603
|
+
)
|
|
7604
|
+
}
|
|
7605
|
+
),
|
|
7606
|
+
placeholder: /* @__PURE__ */ jsxRuntime.jsx(react.Stack, { className: react.css(EditorStyles.editorPlaceholder), children: props.placeholder })
|
|
7607
|
+
}
|
|
7608
|
+
),
|
|
7609
|
+
props.wordLimit !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7610
|
+
"div",
|
|
6988
7611
|
{
|
|
6989
|
-
|
|
6990
|
-
|
|
7612
|
+
style: {
|
|
7613
|
+
position: "sticky",
|
|
7614
|
+
bottom: 0,
|
|
7615
|
+
display: "flex",
|
|
7616
|
+
justifyContent: "flex-end",
|
|
7617
|
+
paddingRight: 14,
|
|
7618
|
+
pointerEvents: "none",
|
|
7619
|
+
userSelect: "none"
|
|
7620
|
+
},
|
|
7621
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7622
|
+
"span",
|
|
7623
|
+
{
|
|
7624
|
+
style: {
|
|
7625
|
+
fontSize: "11px",
|
|
7626
|
+
color: isOverLimit ? "#c4272c" : "var(--colorNeutralForeground3, #aaa)",
|
|
7627
|
+
fontWeight: isOverLimit ? 600 : 400,
|
|
7628
|
+
transition: "color 0.2s, font-weight 0.2s"
|
|
7629
|
+
},
|
|
7630
|
+
children: [
|
|
7631
|
+
wordCount,
|
|
7632
|
+
" / ",
|
|
7633
|
+
props.wordLimit,
|
|
7634
|
+
" words"
|
|
7635
|
+
]
|
|
7636
|
+
}
|
|
7637
|
+
)
|
|
6991
7638
|
}
|
|
6992
7639
|
)
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
{
|
|
7021
|
-
ref: contentEditableDomRef,
|
|
7022
|
-
className: react.css(EditorStyles.contentEditor),
|
|
7023
|
-
style: { paddingTop: props.level !== "none" /* None */ ? 0 : 10 },
|
|
7024
|
-
spellCheck: !resolvedSpellCheck,
|
|
7025
|
-
autoCorrect: resolvedSpellCheck ? "off" : void 0,
|
|
7026
|
-
autoCapitalize: resolvedSpellCheck ? "off" : void 0
|
|
7027
|
-
}
|
|
7028
|
-
)
|
|
7029
|
-
}
|
|
7030
|
-
),
|
|
7031
|
-
placeholder: /* @__PURE__ */ jsxRuntime.jsx(react.Stack, { className: react.css(EditorStyles.editorPlaceholder), children: props.placeholder })
|
|
7032
|
-
}
|
|
7033
|
-
),
|
|
7034
|
-
props.wordLimit !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7035
|
-
"div",
|
|
7036
|
-
{
|
|
7037
|
-
style: {
|
|
7038
|
-
position: "sticky",
|
|
7039
|
-
bottom: 0,
|
|
7040
|
-
display: "flex",
|
|
7041
|
-
justifyContent: "flex-end",
|
|
7042
|
-
paddingRight: 14,
|
|
7043
|
-
pointerEvents: "none",
|
|
7044
|
-
userSelect: "none"
|
|
7045
|
-
},
|
|
7046
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7047
|
-
"span",
|
|
7048
|
-
{
|
|
7049
|
-
style: {
|
|
7050
|
-
fontSize: "11px",
|
|
7051
|
-
color: isOverLimit ? "#c4272c" : "var(--colorNeutralForeground3, #aaa)",
|
|
7052
|
-
fontWeight: isOverLimit ? 600 : 400,
|
|
7053
|
-
transition: "color 0.2s, font-weight 0.2s"
|
|
7054
|
-
},
|
|
7055
|
-
children: [
|
|
7056
|
-
wordCount,
|
|
7057
|
-
" / ",
|
|
7058
|
-
props.wordLimit,
|
|
7059
|
-
" words"
|
|
7060
|
-
]
|
|
7061
|
-
}
|
|
7062
|
-
)
|
|
7063
|
-
}
|
|
7064
|
-
)
|
|
7065
|
-
]
|
|
7066
|
-
}
|
|
7067
|
-
),
|
|
7068
|
-
hasErrors && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7069
|
-
"div",
|
|
7070
|
-
{
|
|
7071
|
-
style: {
|
|
7072
|
-
borderTop: "1px solid #fbd5d5",
|
|
7073
|
-
background: "#fff8f8",
|
|
7074
|
-
padding: "6px 12px 8px",
|
|
7075
|
-
display: "flex",
|
|
7076
|
-
flexDirection: "column",
|
|
7077
|
-
gap: 4
|
|
7078
|
-
},
|
|
7079
|
-
children: allErrors.map((err, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
7080
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.ErrorCircleRegular, { style: { fontSize: 14, color: "#c4272c", flexShrink: 0 } }),
|
|
7081
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#c4272c" }, children: err })
|
|
7082
|
-
] }, i))
|
|
7083
|
-
}
|
|
7084
|
-
),
|
|
7085
|
-
/* @__PURE__ */ jsxRuntime.jsx(ReadOnlyPlugin, { readonly: isReadOnly }),
|
|
7086
|
-
/* @__PURE__ */ jsxRuntime.jsx(BrowserSpellCheckPlugin, { enabled: !resolvedSpellCheck }),
|
|
7087
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7088
|
-
FocusEventsPlugin,
|
|
7089
|
-
{
|
|
7090
|
-
onFocus: props.onFocus,
|
|
7091
|
-
onBlur: () => {
|
|
7092
|
-
setTouched(true);
|
|
7093
|
-
props.onBlur?.();
|
|
7640
|
+
]
|
|
7641
|
+
}
|
|
7642
|
+
),
|
|
7643
|
+
hasErrors && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7644
|
+
"div",
|
|
7645
|
+
{
|
|
7646
|
+
style: {
|
|
7647
|
+
borderTop: "1px solid #fbd5d5",
|
|
7648
|
+
background: "#fff8f8",
|
|
7649
|
+
padding: "6px 12px 8px",
|
|
7650
|
+
display: "flex",
|
|
7651
|
+
flexDirection: "column",
|
|
7652
|
+
gap: 4
|
|
7653
|
+
},
|
|
7654
|
+
children: allErrors.map((err, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7655
|
+
"div",
|
|
7656
|
+
{
|
|
7657
|
+
style: { display: "flex", alignItems: "center", gap: 6 },
|
|
7658
|
+
children: [
|
|
7659
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7660
|
+
reactIcons.ErrorCircleRegular,
|
|
7661
|
+
{
|
|
7662
|
+
style: { fontSize: 14, color: "#c4272c", flexShrink: 0 }
|
|
7663
|
+
}
|
|
7664
|
+
),
|
|
7665
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#c4272c" }, children: err })
|
|
7666
|
+
]
|
|
7094
7667
|
},
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7668
|
+
i
|
|
7669
|
+
))
|
|
7670
|
+
}
|
|
7671
|
+
),
|
|
7672
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReadOnlyPlugin, { readonly: isReadOnly }),
|
|
7673
|
+
/* @__PURE__ */ jsxRuntime.jsx(BrowserSpellCheckPlugin, { enabled: !resolvedSpellCheck }),
|
|
7674
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7675
|
+
FocusEventsPlugin,
|
|
7676
|
+
{
|
|
7677
|
+
onFocus: props.onFocus,
|
|
7678
|
+
onBlur: () => {
|
|
7679
|
+
setTouched(true);
|
|
7680
|
+
props.onBlur?.();
|
|
7681
|
+
},
|
|
7682
|
+
setFocused,
|
|
7683
|
+
containerRef
|
|
7684
|
+
}
|
|
7685
|
+
),
|
|
7686
|
+
props.autoFocus && !isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(LexicalAutoFocusPlugin.AutoFocusPlugin, {}),
|
|
7687
|
+
/* @__PURE__ */ jsxRuntime.jsx(LexicalHistoryPlugin.HistoryPlugin, {}),
|
|
7688
|
+
/* @__PURE__ */ jsxRuntime.jsx(LexicalListPlugin.ListPlugin, {}),
|
|
7689
|
+
/* @__PURE__ */ jsxRuntime.jsx(LexicalLinkPlugin.LinkPlugin, { validateUrl }),
|
|
7690
|
+
/* @__PURE__ */ jsxRuntime.jsx(LexicalAutoLinkPlugin.AutoLinkPlugin, { matchers: MATCHERS }),
|
|
7691
|
+
/* @__PURE__ */ jsxRuntime.jsx(LexicalTablePlugin.TablePlugin, { hasCellMerge: true, hasCellBackgroundColor: true }),
|
|
7692
|
+
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(YoutubeDeletePlugin, {}),
|
|
7693
|
+
!isReadOnly && floatingAnchorElem && /* @__PURE__ */ jsxRuntime.jsx(TableActionMenuPlugin, {}),
|
|
7694
|
+
!isReadOnly && floatingAnchorElem && /* @__PURE__ */ jsxRuntime.jsx(TableCellResizerPlugin, { anchorElem: floatingAnchorElem }),
|
|
7695
|
+
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7696
|
+
FloatingLinkEditorPlugin,
|
|
7697
|
+
{
|
|
7698
|
+
anchorElem: floatingAnchorElem,
|
|
7699
|
+
isLinkEditMode,
|
|
7700
|
+
setIsLinkEditMode
|
|
7701
|
+
}
|
|
7702
|
+
),
|
|
7703
|
+
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(ImagePlugin_default, {}),
|
|
7704
|
+
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(InlineImage_default, {}),
|
|
7705
|
+
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(PageBreakPlugin, {}),
|
|
7706
|
+
!!resolvedQuery && !isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7707
|
+
AutocompletePlugin,
|
|
7708
|
+
{
|
|
7709
|
+
useQuery: resolvedQuery,
|
|
7710
|
+
isReadOnly,
|
|
7711
|
+
onSuggestionShown: props.onSuggestionShown,
|
|
7712
|
+
onSuggestionAccept: props.onSuggestionAccept,
|
|
7713
|
+
idleMs: props.suggestIdleMs ?? 300,
|
|
7714
|
+
minWords: 4,
|
|
7715
|
+
prefixWindow: 300
|
|
7716
|
+
}
|
|
7717
|
+
),
|
|
7718
|
+
!!resolvedSpellCheck && !isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7719
|
+
SpellCheckPlugin,
|
|
7720
|
+
{
|
|
7721
|
+
useSpellCheck: resolvedSpellCheck,
|
|
7722
|
+
onSpellCheckAccept: props.onSpellCheckAccept,
|
|
7723
|
+
idleMs: props.spellCheckIdleMs ?? 1200,
|
|
7724
|
+
enabled: props.spellCheckEnabled !== false
|
|
7725
|
+
}
|
|
7726
|
+
),
|
|
7727
|
+
!isReadOnly && props.showFloatingToolbar && /* @__PURE__ */ jsxRuntime.jsx(CharacterStylesPopupPlugin, {}),
|
|
7728
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7729
|
+
CustomOnChangePlugin,
|
|
7730
|
+
{
|
|
7731
|
+
value: props.value,
|
|
7732
|
+
onChange: props.onChange
|
|
7733
|
+
}
|
|
7734
|
+
),
|
|
7735
|
+
(props.wordLimit !== void 0 || props.required || props.minWords !== void 0) && /* @__PURE__ */ jsxRuntime.jsx(WordCountPlugin, { onCountChange: handleWordCount }),
|
|
7736
|
+
(props.maxChars !== void 0 || props.minChars !== void 0) && /* @__PURE__ */ jsxRuntime.jsx(CharCountPlugin, { onCountChange: handleCharCount }),
|
|
7737
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7738
|
+
RefApiPlugin,
|
|
7739
|
+
{
|
|
7740
|
+
forwardedRef: ref,
|
|
7741
|
+
contentEditableDomRef,
|
|
7742
|
+
focusedRef,
|
|
7743
|
+
setRefErrors
|
|
7744
|
+
}
|
|
7745
|
+
)
|
|
7746
|
+
]
|
|
7747
|
+
}
|
|
7748
|
+
) }) }) });
|
|
7749
|
+
});
|
|
7158
7750
|
|
|
7159
7751
|
exports.ContentEditorComponent = ContentEditorComponent;
|
|
7160
7752
|
exports.ContentEditorLevel = ContentEditorLevel;
|