@tarviks/lexical-rich-editor 1.1.0 → 1.2.0
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.js +704 -349
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +707 -352
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1249,6 +1249,46 @@ var ContentEditorLevel = /* @__PURE__ */ ((ContentEditorLevel2) => {
|
|
|
1249
1249
|
ContentEditorLevel2["Pro"] = "pro";
|
|
1250
1250
|
return ContentEditorLevel2;
|
|
1251
1251
|
})(ContentEditorLevel || {});
|
|
1252
|
+
|
|
1253
|
+
// src/Types/PageSetup.ts
|
|
1254
|
+
var DEFAULT_PAGE_SETUP = {
|
|
1255
|
+
size: "pageless",
|
|
1256
|
+
orientation: "portrait",
|
|
1257
|
+
margin: "normal"
|
|
1258
|
+
};
|
|
1259
|
+
var PAGE_SIZE_OPTIONS = [
|
|
1260
|
+
{ key: "a4", label: 'A4 (8.27" x 11.69")', widthIn: 8.27, heightIn: 11.69 },
|
|
1261
|
+
{ key: "letter", label: 'Letter (8.5" x 11")', widthIn: 8.5, heightIn: 11 },
|
|
1262
|
+
{ key: "legal", label: 'Legal (8.5" x 14")', widthIn: 8.5, heightIn: 14 },
|
|
1263
|
+
{ key: "tabloid", label: 'Tabloid (11" x 17")', widthIn: 11, heightIn: 17 },
|
|
1264
|
+
{ key: "a3", label: 'A3 (11.69" x 16.54")', widthIn: 11.69, heightIn: 16.54 },
|
|
1265
|
+
{ key: "a5", label: 'A5 (5.83" x 8.27")', widthIn: 5.83, heightIn: 8.27 },
|
|
1266
|
+
{ key: "b4", label: 'B4 (9.84" x 13.90")', widthIn: 9.84, heightIn: 13.9 },
|
|
1267
|
+
{ key: "b5", label: 'B5 (6.93" x 9.84")', widthIn: 6.93, heightIn: 9.84 },
|
|
1268
|
+
{ key: "statement", label: 'Statement (5.5" x 8.5")', widthIn: 5.5, heightIn: 8.5 },
|
|
1269
|
+
{ key: "executive", label: 'Executive (7.25" x 10.5")', widthIn: 7.25, heightIn: 10.5 },
|
|
1270
|
+
{ key: "folio", label: 'Folio (8.5" x 13")', widthIn: 8.5, heightIn: 13 }
|
|
1271
|
+
];
|
|
1272
|
+
var MARGIN_OPTIONS = [
|
|
1273
|
+
{ key: "narrow", label: 'Narrow (0.25")', valueIn: 0.25 },
|
|
1274
|
+
{ key: "normal", label: 'Normal (0.4")', valueIn: 0.4 },
|
|
1275
|
+
{ key: "moderate", label: 'Moderate (0.75")', valueIn: 0.75 },
|
|
1276
|
+
{ key: "wide", label: 'Wide (1")', valueIn: 1 }
|
|
1277
|
+
];
|
|
1278
|
+
var CSS_PX_PER_INCH = 96;
|
|
1279
|
+
function resolvePageCanvasMetrics(value) {
|
|
1280
|
+
const margin = MARGIN_OPTIONS.find((o) => o.key === value.margin) ?? MARGIN_OPTIONS[1];
|
|
1281
|
+
if (value.size === "pageless") {
|
|
1282
|
+
return { widthPx: void 0, paddingPx: 20 };
|
|
1283
|
+
}
|
|
1284
|
+
const size = PAGE_SIZE_OPTIONS.find((o) => o.key === value.size);
|
|
1285
|
+
if (!size) return { widthPx: void 0, paddingPx: 20 };
|
|
1286
|
+
const widthIn = value.orientation === "landscape" ? size.heightIn : size.widthIn;
|
|
1287
|
+
return {
|
|
1288
|
+
widthPx: Math.round(widthIn * CSS_PX_PER_INCH),
|
|
1289
|
+
paddingPx: Math.round(margin.valueIn * CSS_PX_PER_INCH)
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1252
1292
|
var AutocompleteNode = class _AutocompleteNode extends lexical.TextNode {
|
|
1253
1293
|
static getType() {
|
|
1254
1294
|
return "autocomplete";
|
|
@@ -2487,6 +2527,236 @@ function CharacterStylesPopupPlugin(props) {
|
|
|
2487
2527
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
2488
2528
|
return useCharacterStylesPopup(editor, props);
|
|
2489
2529
|
}
|
|
2530
|
+
|
|
2531
|
+
// src/Utils/Sanitize.ts
|
|
2532
|
+
var DROP_ENTIRELY = /* @__PURE__ */ new Set([
|
|
2533
|
+
"script",
|
|
2534
|
+
"noscript",
|
|
2535
|
+
"style",
|
|
2536
|
+
"object",
|
|
2537
|
+
"embed",
|
|
2538
|
+
"form",
|
|
2539
|
+
"input",
|
|
2540
|
+
"button",
|
|
2541
|
+
"select",
|
|
2542
|
+
"textarea",
|
|
2543
|
+
"meta",
|
|
2544
|
+
"link",
|
|
2545
|
+
"base"
|
|
2546
|
+
]);
|
|
2547
|
+
var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
2548
|
+
// Block
|
|
2549
|
+
"p",
|
|
2550
|
+
"h1",
|
|
2551
|
+
"h2",
|
|
2552
|
+
"h3",
|
|
2553
|
+
"h4",
|
|
2554
|
+
"h5",
|
|
2555
|
+
"h6",
|
|
2556
|
+
"ul",
|
|
2557
|
+
"ol",
|
|
2558
|
+
"li",
|
|
2559
|
+
"blockquote",
|
|
2560
|
+
"pre",
|
|
2561
|
+
"div",
|
|
2562
|
+
"table",
|
|
2563
|
+
"thead",
|
|
2564
|
+
"tbody",
|
|
2565
|
+
"tfoot",
|
|
2566
|
+
"tr",
|
|
2567
|
+
"td",
|
|
2568
|
+
"th",
|
|
2569
|
+
// Inline
|
|
2570
|
+
"span",
|
|
2571
|
+
"a",
|
|
2572
|
+
"strong",
|
|
2573
|
+
"b",
|
|
2574
|
+
"em",
|
|
2575
|
+
"i",
|
|
2576
|
+
"u",
|
|
2577
|
+
"s",
|
|
2578
|
+
"del",
|
|
2579
|
+
"strike",
|
|
2580
|
+
"sub",
|
|
2581
|
+
"sup",
|
|
2582
|
+
"mark",
|
|
2583
|
+
"code",
|
|
2584
|
+
"br",
|
|
2585
|
+
"hr",
|
|
2586
|
+
// Media / embeds
|
|
2587
|
+
"img",
|
|
2588
|
+
"iframe"
|
|
2589
|
+
]);
|
|
2590
|
+
var ALLOWED_ATTRS = /* @__PURE__ */ new Set([
|
|
2591
|
+
// Presentation
|
|
2592
|
+
"class",
|
|
2593
|
+
"style",
|
|
2594
|
+
"dir",
|
|
2595
|
+
"lang",
|
|
2596
|
+
// Anchors
|
|
2597
|
+
"href",
|
|
2598
|
+
"target",
|
|
2599
|
+
"rel",
|
|
2600
|
+
// Images
|
|
2601
|
+
"src",
|
|
2602
|
+
"alt",
|
|
2603
|
+
"width",
|
|
2604
|
+
"height",
|
|
2605
|
+
// Tables
|
|
2606
|
+
"colspan",
|
|
2607
|
+
"rowspan",
|
|
2608
|
+
// Lists — <ol type="a"> and <ol start="2">
|
|
2609
|
+
"start",
|
|
2610
|
+
"type",
|
|
2611
|
+
// Lexical-internal data markers
|
|
2612
|
+
"data-lex-block",
|
|
2613
|
+
"data-kind",
|
|
2614
|
+
"data-lexical-decorator",
|
|
2615
|
+
// Misc
|
|
2616
|
+
"title",
|
|
2617
|
+
"allowfullscreen"
|
|
2618
|
+
]);
|
|
2619
|
+
var DANGEROUS_URL = /^\s*(javascript|data\s*:|vbscript)/i;
|
|
2620
|
+
function sanitizeElement(el) {
|
|
2621
|
+
for (const child of Array.from(el.children)) {
|
|
2622
|
+
sanitizeElement(child);
|
|
2623
|
+
}
|
|
2624
|
+
const tag = el.tagName.toLowerCase();
|
|
2625
|
+
if (DROP_ENTIRELY.has(tag)) {
|
|
2626
|
+
el.parentNode?.removeChild(el);
|
|
2627
|
+
return;
|
|
2628
|
+
}
|
|
2629
|
+
if (tag === "iframe") {
|
|
2630
|
+
const src = el.getAttribute("src") ?? "";
|
|
2631
|
+
const isYouTube = /^\s*https:\/\/(www\.)?(youtube\.com|youtube-nocookie\.com)\/embed\/[^?&/]+/i.test(src);
|
|
2632
|
+
if (!isYouTube) {
|
|
2633
|
+
el.parentNode?.removeChild(el);
|
|
2634
|
+
return;
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
if (!ALLOWED_TAGS.has(tag)) {
|
|
2638
|
+
while (el.firstChild) {
|
|
2639
|
+
el.parentNode?.insertBefore(el.firstChild, el);
|
|
2640
|
+
}
|
|
2641
|
+
el.parentNode?.removeChild(el);
|
|
2642
|
+
return;
|
|
2643
|
+
}
|
|
2644
|
+
for (const { name, value } of Array.from(el.attributes)) {
|
|
2645
|
+
const lname = name.toLowerCase();
|
|
2646
|
+
if (!ALLOWED_ATTRS.has(lname)) {
|
|
2647
|
+
el.removeAttribute(name);
|
|
2648
|
+
continue;
|
|
2649
|
+
}
|
|
2650
|
+
if (lname === "href" || lname === "src") {
|
|
2651
|
+
if (DANGEROUS_URL.test(value)) {
|
|
2652
|
+
el.removeAttribute(name);
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
if (lname === "style") {
|
|
2656
|
+
const safe = value.replace(/expression\s*\(/gi, "(").replace(/url\s*\(\s*['"]?\s*javascript:/gi, "url(");
|
|
2657
|
+
el.setAttribute("style", safe);
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
if (tag === "a" && (el.getAttribute("target") || "").toLowerCase() === "_blank") {
|
|
2661
|
+
const rel = (el.getAttribute("rel") || "").trim();
|
|
2662
|
+
const tokens = new Set(
|
|
2663
|
+
rel.split(/\s+/).filter(Boolean).map((t) => t.toLowerCase())
|
|
2664
|
+
);
|
|
2665
|
+
tokens.add("noopener");
|
|
2666
|
+
tokens.add("noreferrer");
|
|
2667
|
+
el.setAttribute("rel", Array.from(tokens).join(" "));
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
function sanitizeHtml(html) {
|
|
2671
|
+
if (!html || typeof html !== "string") return "";
|
|
2672
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
2673
|
+
for (const child of Array.from(doc.body.children)) {
|
|
2674
|
+
sanitizeElement(child);
|
|
2675
|
+
}
|
|
2676
|
+
return doc.body.innerHTML;
|
|
2677
|
+
}
|
|
2678
|
+
function postProcessOutput(html) {
|
|
2679
|
+
if (!html) return html;
|
|
2680
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
2681
|
+
for (const inner of Array.from(doc.querySelectorAll("b > strong"))) {
|
|
2682
|
+
const outer = inner.parentElement;
|
|
2683
|
+
_mergeAttributes(inner, outer);
|
|
2684
|
+
while (inner.firstChild) outer.insertBefore(inner.firstChild, inner);
|
|
2685
|
+
outer.removeChild(inner);
|
|
2686
|
+
}
|
|
2687
|
+
for (const inner of Array.from(doc.querySelectorAll("i > em"))) {
|
|
2688
|
+
const outer = inner.parentElement;
|
|
2689
|
+
_mergeAttributes(inner, outer);
|
|
2690
|
+
while (inner.firstChild) outer.insertBefore(inner.firstChild, inner);
|
|
2691
|
+
outer.removeChild(inner);
|
|
2692
|
+
}
|
|
2693
|
+
for (const p of Array.from(doc.querySelectorAll("p"))) {
|
|
2694
|
+
const style = p.style;
|
|
2695
|
+
const hasMargin = !!(style.margin || style.marginTop || style.marginRight || style.marginBottom || style.marginLeft);
|
|
2696
|
+
if (!hasMargin) style.margin = "0";
|
|
2697
|
+
if (!style.lineHeight) style.lineHeight = "1.25";
|
|
2698
|
+
}
|
|
2699
|
+
return doc.body.innerHTML;
|
|
2700
|
+
}
|
|
2701
|
+
function _mergeAttributes(src, dst) {
|
|
2702
|
+
for (const { name, value } of Array.from(src.attributes)) {
|
|
2703
|
+
if (name === "style") {
|
|
2704
|
+
const prev = dst.getAttribute("style") || "";
|
|
2705
|
+
dst.setAttribute("style", prev ? `${prev}; ${value}` : value);
|
|
2706
|
+
} else if (name === "class") {
|
|
2707
|
+
const prev = dst.getAttribute("class") || "";
|
|
2708
|
+
dst.setAttribute("class", prev ? `${prev} ${value}` : value);
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
var BLOCK_TAGS = /* @__PURE__ */ new Set([
|
|
2713
|
+
"p",
|
|
2714
|
+
"h1",
|
|
2715
|
+
"h2",
|
|
2716
|
+
"h3",
|
|
2717
|
+
"h4",
|
|
2718
|
+
"h5",
|
|
2719
|
+
"h6",
|
|
2720
|
+
"div",
|
|
2721
|
+
"ul",
|
|
2722
|
+
"ol",
|
|
2723
|
+
"li",
|
|
2724
|
+
"table",
|
|
2725
|
+
"blockquote",
|
|
2726
|
+
"pre",
|
|
2727
|
+
"hr"
|
|
2728
|
+
]);
|
|
2729
|
+
function normalizeToBlockHtml(html) {
|
|
2730
|
+
if (!html) return "";
|
|
2731
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
2732
|
+
const body = doc.body;
|
|
2733
|
+
const childNodes = Array.from(body.childNodes);
|
|
2734
|
+
const needsWrap = childNodes.some((node) => {
|
|
2735
|
+
if (node.nodeType === Node.TEXT_NODE) return !!node.nodeValue?.trim();
|
|
2736
|
+
if (node.nodeType === Node.ELEMENT_NODE)
|
|
2737
|
+
return !BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
2738
|
+
return false;
|
|
2739
|
+
});
|
|
2740
|
+
if (!needsWrap) return html;
|
|
2741
|
+
while (body.firstChild) body.removeChild(body.firstChild);
|
|
2742
|
+
let pendingP = null;
|
|
2743
|
+
for (const node of childNodes) {
|
|
2744
|
+
const isBlock = node.nodeType === Node.ELEMENT_NODE && BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
2745
|
+
const isWhitespace = node.nodeType === Node.TEXT_NODE && !node.nodeValue?.trim();
|
|
2746
|
+
if (isBlock) {
|
|
2747
|
+
if (pendingP) {
|
|
2748
|
+
body.appendChild(pendingP);
|
|
2749
|
+
pendingP = null;
|
|
2750
|
+
}
|
|
2751
|
+
body.appendChild(node);
|
|
2752
|
+
} else if (!isWhitespace) {
|
|
2753
|
+
if (!pendingP) pendingP = doc.createElement("p");
|
|
2754
|
+
pendingP.appendChild(node);
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
if (pendingP) body.appendChild(pendingP);
|
|
2758
|
+
return body.innerHTML;
|
|
2759
|
+
}
|
|
2490
2760
|
var CustomOnChangePlugin = ({ value, onChange }) => {
|
|
2491
2761
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
2492
2762
|
const initializedRef = React9.useRef(false);
|
|
@@ -2507,7 +2777,7 @@ var CustomOnChangePlugin = ({ value, onChange }) => {
|
|
|
2507
2777
|
}, [editor, value]);
|
|
2508
2778
|
const handleChange = React9.useCallback((editorState) => {
|
|
2509
2779
|
editorState.read(() => {
|
|
2510
|
-
onChangeRef.current(html.$generateHtmlFromNodes(editor));
|
|
2780
|
+
onChangeRef.current(postProcessOutput(html.$generateHtmlFromNodes(editor)));
|
|
2511
2781
|
});
|
|
2512
2782
|
}, [editor]);
|
|
2513
2783
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3519,279 +3789,81 @@ var $onDrop2 = (event, editor) => {
|
|
|
3519
3789
|
const node = $getImageNodeInSelection2();
|
|
3520
3790
|
if (!node) return false;
|
|
3521
3791
|
const data = getDragImageData2(event);
|
|
3522
|
-
if (!data) return false;
|
|
3523
|
-
event.preventDefault();
|
|
3524
|
-
if (canDropImage2(event)) {
|
|
3525
|
-
const range = getDragSelection2(event);
|
|
3526
|
-
node.remove();
|
|
3527
|
-
const rangeSelection = lexical.$createRangeSelection();
|
|
3528
|
-
if (range !== null && range !== void 0) {
|
|
3529
|
-
rangeSelection.applyDOMRange(range);
|
|
3530
|
-
}
|
|
3531
|
-
lexical.$setSelection(rangeSelection);
|
|
3532
|
-
editor.dispatchCommand(INSERT_INLINE_IMAGE_COMMAND, data);
|
|
3533
|
-
}
|
|
3534
|
-
return true;
|
|
3535
|
-
};
|
|
3536
|
-
var $getImageNodeInSelection2 = () => {
|
|
3537
|
-
const selection = lexical.$getSelection();
|
|
3538
|
-
if (!lexical.$isNodeSelection(selection)) return null;
|
|
3539
|
-
const nodes = selection.getNodes();
|
|
3540
|
-
const node = nodes[0];
|
|
3541
|
-
return $isInlineImageNode(node) ? node : null;
|
|
3542
|
-
};
|
|
3543
|
-
var getDragImageData2 = (event) => {
|
|
3544
|
-
const dragData = event.dataTransfer?.getData("application/x-lexical-drag");
|
|
3545
|
-
if (!dragData) return null;
|
|
3546
|
-
const { type, data } = JSON.parse(dragData);
|
|
3547
|
-
if (type !== "image") return null;
|
|
3548
|
-
return data;
|
|
3549
|
-
};
|
|
3550
|
-
var canDropImage2 = (event) => {
|
|
3551
|
-
const target = event.target;
|
|
3552
|
-
return !!(lexical.isHTMLElement(target) && !target.closest("code, span.editor-image") && lexical.isHTMLElement(target.parentElement) && target.parentElement.closest("div.ContentEditable__root"));
|
|
3553
|
-
};
|
|
3554
|
-
var getDragSelection2 = (event) => {
|
|
3555
|
-
let range;
|
|
3556
|
-
const domSelection = lexical.getDOMSelectionFromTarget(event.target);
|
|
3557
|
-
if (document.caretRangeFromPoint) {
|
|
3558
|
-
range = document.caretRangeFromPoint(event.clientX, event.clientY);
|
|
3559
|
-
} else if (event.rangeParent && domSelection !== null) {
|
|
3560
|
-
domSelection.collapse(event.rangeParent, event.rangeOffset || 0);
|
|
3561
|
-
range = domSelection.getRangeAt(0);
|
|
3562
|
-
} else {
|
|
3563
|
-
throw Error("Cannot get the selection when dragging");
|
|
3564
|
-
}
|
|
3565
|
-
return range;
|
|
3566
|
-
};
|
|
3567
|
-
var INSERT_PAGE_BREAK = lexical.createCommand();
|
|
3568
|
-
function PageBreakPlugin() {
|
|
3569
|
-
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
3570
|
-
React9.useEffect(() => {
|
|
3571
|
-
if (!editor.hasNodes([PageBreakNode])) {
|
|
3572
|
-
throw new Error(
|
|
3573
|
-
"PageBreakPlugin: PageBreakNode is not registered on editor"
|
|
3574
|
-
);
|
|
3575
|
-
}
|
|
3576
|
-
return utils.mergeRegister(
|
|
3577
|
-
editor.registerCommand(
|
|
3578
|
-
INSERT_PAGE_BREAK,
|
|
3579
|
-
() => {
|
|
3580
|
-
const selection = lexical.$getSelection();
|
|
3581
|
-
if (!lexical.$isRangeSelection(selection)) {
|
|
3582
|
-
return false;
|
|
3583
|
-
}
|
|
3584
|
-
const focusNode = selection.focus.getNode();
|
|
3585
|
-
if (focusNode !== null) {
|
|
3586
|
-
const pgBreak = $createPageBreakNode();
|
|
3587
|
-
utils.$insertNodeToNearestRoot(pgBreak);
|
|
3588
|
-
}
|
|
3589
|
-
return true;
|
|
3590
|
-
},
|
|
3591
|
-
lexical.COMMAND_PRIORITY_EDITOR
|
|
3592
|
-
)
|
|
3593
|
-
);
|
|
3594
|
-
}, [editor]);
|
|
3595
|
-
return null;
|
|
3596
|
-
}
|
|
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);
|
|
3792
|
+
if (!data) return false;
|
|
3793
|
+
event.preventDefault();
|
|
3794
|
+
if (canDropImage2(event)) {
|
|
3795
|
+
const range = getDragSelection2(event);
|
|
3796
|
+
node.remove();
|
|
3797
|
+
const rangeSelection = lexical.$createRangeSelection();
|
|
3798
|
+
if (range !== null && range !== void 0) {
|
|
3799
|
+
rangeSelection.applyDOMRange(range);
|
|
3725
3800
|
}
|
|
3801
|
+
lexical.$setSelection(rangeSelection);
|
|
3802
|
+
editor.dispatchCommand(INSERT_INLINE_IMAGE_COMMAND, data);
|
|
3726
3803
|
}
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
if (!
|
|
3739
|
-
const
|
|
3740
|
-
|
|
3741
|
-
|
|
3804
|
+
return true;
|
|
3805
|
+
};
|
|
3806
|
+
var $getImageNodeInSelection2 = () => {
|
|
3807
|
+
const selection = lexical.$getSelection();
|
|
3808
|
+
if (!lexical.$isNodeSelection(selection)) return null;
|
|
3809
|
+
const nodes = selection.getNodes();
|
|
3810
|
+
const node = nodes[0];
|
|
3811
|
+
return $isInlineImageNode(node) ? node : null;
|
|
3812
|
+
};
|
|
3813
|
+
var getDragImageData2 = (event) => {
|
|
3814
|
+
const dragData = event.dataTransfer?.getData("application/x-lexical-drag");
|
|
3815
|
+
if (!dragData) return null;
|
|
3816
|
+
const { type, data } = JSON.parse(dragData);
|
|
3817
|
+
if (type !== "image") return null;
|
|
3818
|
+
return data;
|
|
3819
|
+
};
|
|
3820
|
+
var canDropImage2 = (event) => {
|
|
3821
|
+
const target = event.target;
|
|
3822
|
+
return !!(lexical.isHTMLElement(target) && !target.closest("code, span.editor-image") && lexical.isHTMLElement(target.parentElement) && target.parentElement.closest("div.ContentEditable__root"));
|
|
3823
|
+
};
|
|
3824
|
+
var getDragSelection2 = (event) => {
|
|
3825
|
+
let range;
|
|
3826
|
+
const domSelection = lexical.getDOMSelectionFromTarget(event.target);
|
|
3827
|
+
if (document.caretRangeFromPoint) {
|
|
3828
|
+
range = document.caretRangeFromPoint(event.clientX, event.clientY);
|
|
3829
|
+
} else if (event.rangeParent && domSelection !== null) {
|
|
3830
|
+
domSelection.collapse(event.rangeParent, event.rangeOffset || 0);
|
|
3831
|
+
range = domSelection.getRangeAt(0);
|
|
3832
|
+
} else {
|
|
3833
|
+
throw Error("Cannot get the selection when dragging");
|
|
3742
3834
|
}
|
|
3743
|
-
return
|
|
3744
|
-
}
|
|
3745
|
-
var
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
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);
|
|
3835
|
+
return range;
|
|
3836
|
+
};
|
|
3837
|
+
var INSERT_PAGE_BREAK = lexical.createCommand();
|
|
3838
|
+
function PageBreakPlugin() {
|
|
3839
|
+
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
3840
|
+
React9.useEffect(() => {
|
|
3841
|
+
if (!editor.hasNodes([PageBreakNode])) {
|
|
3842
|
+
throw new Error(
|
|
3843
|
+
"PageBreakPlugin: PageBreakNode is not registered on editor"
|
|
3844
|
+
);
|
|
3788
3845
|
}
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3846
|
+
return utils.mergeRegister(
|
|
3847
|
+
editor.registerCommand(
|
|
3848
|
+
INSERT_PAGE_BREAK,
|
|
3849
|
+
() => {
|
|
3850
|
+
const selection = lexical.$getSelection();
|
|
3851
|
+
if (!lexical.$isRangeSelection(selection)) {
|
|
3852
|
+
return false;
|
|
3853
|
+
}
|
|
3854
|
+
const focusNode = selection.focus.getNode();
|
|
3855
|
+
if (focusNode !== null) {
|
|
3856
|
+
const pgBreak = $createPageBreakNode();
|
|
3857
|
+
utils.$insertNodeToNearestRoot(pgBreak);
|
|
3858
|
+
}
|
|
3859
|
+
return true;
|
|
3860
|
+
},
|
|
3861
|
+
lexical.COMMAND_PRIORITY_EDITOR
|
|
3862
|
+
)
|
|
3863
|
+
);
|
|
3864
|
+
}, [editor]);
|
|
3865
|
+
return null;
|
|
3792
3866
|
}
|
|
3793
|
-
|
|
3794
|
-
// src/Utils/Helper.ts
|
|
3795
3867
|
function findBlockByKind(kind) {
|
|
3796
3868
|
const root = lexical.$getRoot();
|
|
3797
3869
|
for (const child of root.getChildren()) {
|
|
@@ -3863,7 +3935,7 @@ function RefApiPlugin({
|
|
|
3863
3935
|
editor.getEditorState().read(() => {
|
|
3864
3936
|
html$1 = html.$generateHtmlFromNodes(editor, null);
|
|
3865
3937
|
});
|
|
3866
|
-
return html$1;
|
|
3938
|
+
return postProcessOutput(html$1);
|
|
3867
3939
|
},
|
|
3868
3940
|
clear: () => {
|
|
3869
3941
|
editor.update(() => {
|
|
@@ -5012,7 +5084,8 @@ function getToolbarGroupsByLevel(level) {
|
|
|
5012
5084
|
["FontFamily", "|"],
|
|
5013
5085
|
["FontSize", "|"],
|
|
5014
5086
|
["Decorators", "|"],
|
|
5015
|
-
["Align"]
|
|
5087
|
+
["Align", "|"],
|
|
5088
|
+
["PageSetup"]
|
|
5016
5089
|
];
|
|
5017
5090
|
case "pro" /* Pro */:
|
|
5018
5091
|
default:
|
|
@@ -5027,7 +5100,8 @@ function getToolbarGroupsByLevel(level) {
|
|
|
5027
5100
|
["FontFamily", "|"],
|
|
5028
5101
|
["FontSize", "|"],
|
|
5029
5102
|
["Decorators", "|"],
|
|
5030
|
-
["Align"]
|
|
5103
|
+
["Align", "|"],
|
|
5104
|
+
["PageSetup"]
|
|
5031
5105
|
];
|
|
5032
5106
|
}
|
|
5033
5107
|
}
|
|
@@ -5065,6 +5139,7 @@ var normalizeHex = (v) => {
|
|
|
5065
5139
|
if (hex.length === 4 || hex.length === 7) return hex.toLowerCase();
|
|
5066
5140
|
return "#000000";
|
|
5067
5141
|
};
|
|
5142
|
+
var isCompleteHex = (v) => /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test((v ?? "").trim());
|
|
5068
5143
|
var hexToRgb = (hex) => {
|
|
5069
5144
|
const h = normalizeHex(hex).replace("#", "");
|
|
5070
5145
|
if (h.length === 3) {
|
|
@@ -5147,62 +5222,118 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5147
5222
|
};
|
|
5148
5223
|
}, [open]);
|
|
5149
5224
|
const appliedHex = React9__namespace.useMemo(() => normalizeHex(value || "#000000"), [value]);
|
|
5150
|
-
const [hex,
|
|
5225
|
+
const [hex, setHexState] = React9__namespace.useState(appliedHex);
|
|
5226
|
+
const [hexText, setHexText] = React9__namespace.useState(appliedHex);
|
|
5151
5227
|
const { r, g, b } = React9__namespace.useMemo(() => hexToRgb(hex), [hex]);
|
|
5152
5228
|
const hsv = React9__namespace.useMemo(() => rgbToHsv(r, g, b), [r, g, b]);
|
|
5153
5229
|
const [h, setH] = React9__namespace.useState(hsv.h);
|
|
5154
5230
|
const [s, setS] = React9__namespace.useState(hsv.s);
|
|
5155
5231
|
const [v, setV] = React9__namespace.useState(hsv.v);
|
|
5156
|
-
const
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5232
|
+
const commit = React9__namespace.useCallback(
|
|
5233
|
+
(nextHex) => {
|
|
5234
|
+
const rgb = hexToRgb(nextHex);
|
|
5235
|
+
const next = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
5236
|
+
setHexState(nextHex);
|
|
5237
|
+
setHexText(nextHex);
|
|
5238
|
+
setH(next.h);
|
|
5239
|
+
setS(next.s);
|
|
5240
|
+
setV(next.v);
|
|
5241
|
+
onChange(nextHex);
|
|
5242
|
+
},
|
|
5243
|
+
[onChange]
|
|
5244
|
+
);
|
|
5245
|
+
const commitFromHsv = React9__namespace.useCallback(
|
|
5246
|
+
(hh, ss, vv) => {
|
|
5247
|
+
const rgb = hsvToRgb(hh, ss, vv);
|
|
5248
|
+
const nextHex = rgbToHex(rgb.r, rgb.g, rgb.b);
|
|
5249
|
+
setHexState(nextHex);
|
|
5250
|
+
setHexText(nextHex);
|
|
5251
|
+
setH(hh);
|
|
5252
|
+
setS(ss);
|
|
5253
|
+
setV(vv);
|
|
5254
|
+
onChange(nextHex);
|
|
5255
|
+
},
|
|
5256
|
+
[onChange]
|
|
5257
|
+
);
|
|
5171
5258
|
const wasOpenRef = React9__namespace.useRef(open);
|
|
5172
5259
|
React9__namespace.useEffect(() => {
|
|
5173
5260
|
const justOpened = open && !wasOpenRef.current;
|
|
5174
5261
|
wasOpenRef.current = open;
|
|
5175
5262
|
if (!justOpened) return;
|
|
5176
|
-
|
|
5177
|
-
|
|
5263
|
+
setHexState(appliedHex);
|
|
5264
|
+
setHexText(appliedHex);
|
|
5265
|
+
const rgb = hexToRgb(appliedHex);
|
|
5266
|
+
const next = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
5267
|
+
setH(next.h);
|
|
5268
|
+
setS(next.s);
|
|
5269
|
+
setV(next.v);
|
|
5270
|
+
}, [appliedHex, open]);
|
|
5178
5271
|
const svRef = React9__namespace.useRef(null);
|
|
5179
|
-
const
|
|
5272
|
+
const svPointFromEvent = React9__namespace.useCallback((clientX, clientY) => {
|
|
5273
|
+
if (!svRef.current) return null;
|
|
5274
|
+
const rect = svRef.current.getBoundingClientRect();
|
|
5275
|
+
const x = clamp3(clientX - rect.left, 0, rect.width);
|
|
5276
|
+
const y = clamp3(clientY - rect.top, 0, rect.height);
|
|
5277
|
+
const ss = rect.width === 0 ? 0 : x / rect.width;
|
|
5278
|
+
const vv = rect.height === 0 ? 0 : 1 - y / rect.height;
|
|
5279
|
+
return { ss, vv };
|
|
5280
|
+
}, []);
|
|
5281
|
+
const hRef = React9__namespace.useRef(h);
|
|
5282
|
+
hRef.current = h;
|
|
5283
|
+
const handleSVPointerDown = React9__namespace.useCallback(
|
|
5284
|
+
(e) => {
|
|
5285
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
5286
|
+
const pt = svPointFromEvent(e.clientX, e.clientY);
|
|
5287
|
+
if (pt) commitFromHsv(hRef.current, pt.ss, pt.vv);
|
|
5288
|
+
},
|
|
5289
|
+
[svPointFromEvent, commitFromHsv]
|
|
5290
|
+
);
|
|
5291
|
+
const handleSVPointerMove = React9__namespace.useCallback(
|
|
5180
5292
|
(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);
|
|
5293
|
+
if (e.buttons !== 1) return;
|
|
5294
|
+
const pt = svPointFromEvent(e.clientX, e.clientY);
|
|
5295
|
+
if (pt) commitFromHsv(hRef.current, pt.ss, pt.vv);
|
|
5188
5296
|
},
|
|
5189
|
-
[
|
|
5297
|
+
[svPointFromEvent, commitFromHsv]
|
|
5190
5298
|
);
|
|
5191
5299
|
const hueRef = React9__namespace.useRef(null);
|
|
5192
|
-
const
|
|
5300
|
+
const sRef = React9__namespace.useRef(s);
|
|
5301
|
+
sRef.current = s;
|
|
5302
|
+
const vRef = React9__namespace.useRef(v);
|
|
5303
|
+
vRef.current = v;
|
|
5304
|
+
const huePointFromEvent = React9__namespace.useCallback((clientX) => {
|
|
5305
|
+
if (!hueRef.current) return null;
|
|
5306
|
+
const rect = hueRef.current.getBoundingClientRect();
|
|
5307
|
+
const x = clamp3(clientX - rect.left, 0, rect.width);
|
|
5308
|
+
return rect.width === 0 ? 0 : x / rect.width * 360;
|
|
5309
|
+
}, []);
|
|
5310
|
+
const handleHuePointerDown = React9__namespace.useCallback(
|
|
5311
|
+
(e) => {
|
|
5312
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
5313
|
+
const hh = huePointFromEvent(e.clientX);
|
|
5314
|
+
if (hh != null) commitFromHsv(hh, sRef.current, vRef.current);
|
|
5315
|
+
},
|
|
5316
|
+
[huePointFromEvent, commitFromHsv]
|
|
5317
|
+
);
|
|
5318
|
+
const handleHuePointerMove = React9__namespace.useCallback(
|
|
5193
5319
|
(e) => {
|
|
5194
|
-
if (
|
|
5195
|
-
const
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5320
|
+
if (e.buttons !== 1) return;
|
|
5321
|
+
const hh = huePointFromEvent(e.clientX);
|
|
5322
|
+
if (hh != null) commitFromHsv(hh, sRef.current, vRef.current);
|
|
5323
|
+
},
|
|
5324
|
+
[huePointFromEvent, commitFromHsv]
|
|
5325
|
+
);
|
|
5326
|
+
const handleHexChange = React9__namespace.useCallback(
|
|
5327
|
+
(_, val) => {
|
|
5328
|
+
const next = val ?? "";
|
|
5329
|
+
setHexText(next);
|
|
5330
|
+
if (isCompleteHex(next.trim())) commit(normalizeHex(next));
|
|
5199
5331
|
},
|
|
5200
|
-
[
|
|
5332
|
+
[commit]
|
|
5201
5333
|
);
|
|
5202
|
-
const
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
}, [onChange, hex, setOpenAndNotify]);
|
|
5334
|
+
const handleHexBlur = React9__namespace.useCallback(() => {
|
|
5335
|
+
commit(normalizeHex(hexText));
|
|
5336
|
+
}, [hexText, commit]);
|
|
5206
5337
|
const svThumb = React9__namespace.useMemo(() => ({ left: `${s * 100}%`, top: `${(1 - v) * 100}%` }), [s, v]);
|
|
5207
5338
|
const hueThumb = React9__namespace.useMemo(() => ({ left: `${h / 360 * 100}%` }), [h]);
|
|
5208
5339
|
const hueColor = React9__namespace.useMemo(() => {
|
|
@@ -5257,44 +5388,192 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5257
5388
|
directionalHint: 4,
|
|
5258
5389
|
className: "aoColorCallout",
|
|
5259
5390
|
preventDismissOnEvent,
|
|
5260
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap:
|
|
5261
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
5262
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
5263
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "aoLexTitle", children: title })
|
|
5264
|
-
] }),
|
|
5265
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aoLexRow", children: [
|
|
5266
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "aoLexLabel", children: "Hex" }),
|
|
5391
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 14 }, styles: { root: { padding: "14px 16px 16px", width: 288 } }, children: [
|
|
5392
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
5393
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, fontWeight: 600, color: "#242424", letterSpacing: 0.1 }, children: title }),
|
|
5267
5394
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5268
|
-
|
|
5395
|
+
"button",
|
|
5269
5396
|
{
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5397
|
+
type: "button",
|
|
5398
|
+
"aria-label": "Close",
|
|
5399
|
+
onClick: () => setOpenAndNotify(false),
|
|
5400
|
+
style: {
|
|
5401
|
+
display: "flex",
|
|
5402
|
+
alignItems: "center",
|
|
5403
|
+
justifyContent: "center",
|
|
5404
|
+
width: 24,
|
|
5405
|
+
height: 24,
|
|
5406
|
+
padding: 0,
|
|
5407
|
+
border: "none",
|
|
5408
|
+
borderRadius: 4,
|
|
5409
|
+
background: "transparent",
|
|
5410
|
+
color: "#616161",
|
|
5411
|
+
cursor: "pointer"
|
|
5412
|
+
},
|
|
5413
|
+
onMouseEnter: (e) => e.currentTarget.style.background = "#f0f0f0",
|
|
5414
|
+
onMouseLeave: (e) => e.currentTarget.style.background = "transparent",
|
|
5415
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.Dismiss16Regular, {})
|
|
5273
5416
|
}
|
|
5274
5417
|
)
|
|
5275
5418
|
] }),
|
|
5276
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5277
|
-
"
|
|
5419
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5420
|
+
"div",
|
|
5278
5421
|
{
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5422
|
+
ref: svRef,
|
|
5423
|
+
onPointerDown: handleSVPointerDown,
|
|
5424
|
+
onPointerMove: handleSVPointerMove,
|
|
5425
|
+
style: {
|
|
5426
|
+
position: "relative",
|
|
5427
|
+
width: "100%",
|
|
5428
|
+
height: 150,
|
|
5429
|
+
borderRadius: 8,
|
|
5430
|
+
overflow: "hidden",
|
|
5431
|
+
cursor: "crosshair",
|
|
5432
|
+
touchAction: "none",
|
|
5433
|
+
boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.08)"
|
|
5434
|
+
},
|
|
5435
|
+
children: [
|
|
5436
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, background: hueColor } }),
|
|
5437
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5438
|
+
"div",
|
|
5439
|
+
{
|
|
5440
|
+
style: {
|
|
5441
|
+
position: "absolute",
|
|
5442
|
+
inset: 0,
|
|
5443
|
+
background: "linear-gradient(to right, #fff, rgba(255,255,255,0))"
|
|
5444
|
+
}
|
|
5445
|
+
}
|
|
5446
|
+
),
|
|
5447
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5448
|
+
"div",
|
|
5449
|
+
{
|
|
5450
|
+
style: {
|
|
5451
|
+
position: "absolute",
|
|
5452
|
+
inset: 0,
|
|
5453
|
+
background: "linear-gradient(to top, #000, rgba(0,0,0,0))"
|
|
5454
|
+
}
|
|
5455
|
+
}
|
|
5456
|
+
),
|
|
5457
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5458
|
+
"div",
|
|
5459
|
+
{
|
|
5460
|
+
style: {
|
|
5461
|
+
position: "absolute",
|
|
5462
|
+
width: 16,
|
|
5463
|
+
height: 16,
|
|
5464
|
+
borderRadius: "50%",
|
|
5465
|
+
border: "2px solid #fff",
|
|
5466
|
+
boxShadow: "0 0 0 1px rgba(0,0,0,0.35), 0 1px 3px rgba(0,0,0,0.4)",
|
|
5467
|
+
transform: "translate(-50%, -50%)",
|
|
5468
|
+
pointerEvents: "none",
|
|
5469
|
+
...svThumb
|
|
5470
|
+
}
|
|
5471
|
+
}
|
|
5472
|
+
)
|
|
5473
|
+
]
|
|
5474
|
+
}
|
|
5475
|
+
),
|
|
5476
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5477
|
+
"div",
|
|
5478
|
+
{
|
|
5479
|
+
ref: hueRef,
|
|
5480
|
+
onPointerDown: handleHuePointerDown,
|
|
5481
|
+
onPointerMove: handleHuePointerMove,
|
|
5482
|
+
style: {
|
|
5483
|
+
position: "relative",
|
|
5484
|
+
width: "100%",
|
|
5485
|
+
height: 12,
|
|
5486
|
+
borderRadius: 999,
|
|
5487
|
+
cursor: "pointer",
|
|
5488
|
+
touchAction: "none",
|
|
5489
|
+
background: "linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)",
|
|
5490
|
+
boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.08)"
|
|
5491
|
+
},
|
|
5492
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5493
|
+
"div",
|
|
5494
|
+
{
|
|
5495
|
+
style: {
|
|
5496
|
+
position: "absolute",
|
|
5497
|
+
top: "50%",
|
|
5498
|
+
width: 16,
|
|
5499
|
+
height: 16,
|
|
5500
|
+
borderRadius: "50%",
|
|
5501
|
+
background: hueColor,
|
|
5502
|
+
border: "2px solid #fff",
|
|
5503
|
+
boxShadow: "0 0 0 1px rgba(0,0,0,0.35), 0 1px 3px rgba(0,0,0,0.4)",
|
|
5504
|
+
transform: "translate(-50%, -50%)",
|
|
5505
|
+
pointerEvents: "none",
|
|
5506
|
+
...hueThumb
|
|
5507
|
+
}
|
|
5508
|
+
}
|
|
5509
|
+
)
|
|
5510
|
+
}
|
|
5511
|
+
),
|
|
5512
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
5513
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5514
|
+
"div",
|
|
5515
|
+
{
|
|
5516
|
+
style: {
|
|
5517
|
+
width: 32,
|
|
5518
|
+
height: 32,
|
|
5519
|
+
borderRadius: 6,
|
|
5520
|
+
flexShrink: 0,
|
|
5521
|
+
background: hex,
|
|
5522
|
+
boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.12)"
|
|
5523
|
+
}
|
|
5524
|
+
}
|
|
5525
|
+
),
|
|
5526
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5527
|
+
react.TextField,
|
|
5528
|
+
{
|
|
5529
|
+
value: hexText,
|
|
5530
|
+
onChange: handleHexChange,
|
|
5531
|
+
onBlur: handleHexBlur,
|
|
5532
|
+
onKeyDown: (e) => {
|
|
5533
|
+
if (e.key === "Enter") commit(normalizeHex(hexText));
|
|
5534
|
+
},
|
|
5535
|
+
styles: { root: { flex: 1 }, fieldGroup: { borderRadius: 6 } }
|
|
5536
|
+
}
|
|
5537
|
+
)
|
|
5292
5538
|
] }),
|
|
5293
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5539
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5540
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, fontWeight: 600, color: "#8a8a8a", marginBottom: 6, letterSpacing: 0.3 }, children: "STANDARD COLORS" }),
|
|
5541
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5542
|
+
"div",
|
|
5543
|
+
{
|
|
5544
|
+
style: {
|
|
5545
|
+
display: "grid",
|
|
5546
|
+
gridTemplateColumns: "repeat(9, 1fr)",
|
|
5547
|
+
gap: 6
|
|
5548
|
+
},
|
|
5549
|
+
children: PRESET.map((c) => {
|
|
5550
|
+
const isSelected = c.toLowerCase() === hex.toLowerCase();
|
|
5551
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5552
|
+
"button",
|
|
5553
|
+
{
|
|
5554
|
+
type: "button",
|
|
5555
|
+
onClick: () => commit(c),
|
|
5556
|
+
title: c,
|
|
5557
|
+
"aria-label": c,
|
|
5558
|
+
style: {
|
|
5559
|
+
width: 22,
|
|
5560
|
+
height: 22,
|
|
5561
|
+
padding: 0,
|
|
5562
|
+
borderRadius: 5,
|
|
5563
|
+
background: c,
|
|
5564
|
+
cursor: "pointer",
|
|
5565
|
+
boxShadow: isSelected ? "0 0 0 2px #fff, 0 0 0 3px #4a86e8" : "inset 0 0 0 1px rgba(0,0,0,0.15)",
|
|
5566
|
+
border: "none",
|
|
5567
|
+
transition: "transform 80ms ease"
|
|
5568
|
+
},
|
|
5569
|
+
onMouseEnter: (e) => e.currentTarget.style.transform = "scale(1.12)",
|
|
5570
|
+
onMouseLeave: (e) => e.currentTarget.style.transform = "scale(1)"
|
|
5571
|
+
},
|
|
5572
|
+
c
|
|
5573
|
+
);
|
|
5574
|
+
})
|
|
5575
|
+
}
|
|
5576
|
+
)
|
|
5298
5577
|
] })
|
|
5299
5578
|
] })
|
|
5300
5579
|
}
|
|
@@ -5726,6 +6005,60 @@ var InsertLinkPlugin = ({ disabled }) => {
|
|
|
5726
6005
|
}
|
|
5727
6006
|
);
|
|
5728
6007
|
};
|
|
6008
|
+
function PageSetupPlugin({ disabled, value, onChange }) {
|
|
6009
|
+
const sizeLabel = value.size === "pageless" ? "Pageless" : PAGE_SIZE_OPTIONS.find((o) => o.key === value.size)?.label ?? "Pageless";
|
|
6010
|
+
const isPaged = value.size !== "pageless";
|
|
6011
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6012
|
+
reactComponents.Menu,
|
|
6013
|
+
{
|
|
6014
|
+
checkedValues: {
|
|
6015
|
+
size: [value.size],
|
|
6016
|
+
orientation: [value.orientation],
|
|
6017
|
+
margin: [value.margin]
|
|
6018
|
+
},
|
|
6019
|
+
onCheckedValueChange: (_, data) => {
|
|
6020
|
+
const selected = data.checkedItems[0];
|
|
6021
|
+
if (!selected) return;
|
|
6022
|
+
if (data.name === "size") onChange({ ...value, size: selected });
|
|
6023
|
+
else if (data.name === "orientation")
|
|
6024
|
+
onChange({ ...value, orientation: selected });
|
|
6025
|
+
else if (data.name === "margin") onChange({ ...value, margin: selected });
|
|
6026
|
+
},
|
|
6027
|
+
children: [
|
|
6028
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6029
|
+
reactComponents.Button,
|
|
6030
|
+
{
|
|
6031
|
+
appearance: "subtle",
|
|
6032
|
+
size: "small",
|
|
6033
|
+
disabled,
|
|
6034
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DocumentRegular, {}),
|
|
6035
|
+
title: "Page setup",
|
|
6036
|
+
style: { minWidth: "auto" },
|
|
6037
|
+
children: sizeLabel
|
|
6038
|
+
}
|
|
6039
|
+
) }),
|
|
6040
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuPopover, { style: { minWidth: 220 }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuList, { children: [
|
|
6041
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuGroup, { children: [
|
|
6042
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuGroupHeader, { children: "Page size" }),
|
|
6043
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItemRadio, { name: "size", value: "pageless", children: "Pageless" }),
|
|
6044
|
+
PAGE_SIZE_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItemRadio, { name: "size", value: opt.key, children: opt.label }, opt.key))
|
|
6045
|
+
] }),
|
|
6046
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuDivider, {}),
|
|
6047
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuGroup, { children: [
|
|
6048
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuGroupHeader, { children: "Orientation" }),
|
|
6049
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItemRadio, { name: "orientation", value: "portrait", disabled: !isPaged, children: "Portrait" }),
|
|
6050
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItemRadio, { name: "orientation", value: "landscape", disabled: !isPaged, children: "Landscape" })
|
|
6051
|
+
] }),
|
|
6052
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuDivider, {}),
|
|
6053
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuGroup, { children: [
|
|
6054
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuGroupHeader, { children: "Margins" }),
|
|
6055
|
+
MARGIN_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItemRadio, { name: "margin", value: opt.key, disabled: !isPaged, children: opt.label }, opt.key))
|
|
6056
|
+
] })
|
|
6057
|
+
] }) })
|
|
6058
|
+
]
|
|
6059
|
+
}
|
|
6060
|
+
);
|
|
6061
|
+
}
|
|
5729
6062
|
var TableItemPlugin = ({ disabled }) => {
|
|
5730
6063
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
5731
6064
|
const [columns, setColumns] = React9.useState("");
|
|
@@ -5943,7 +6276,8 @@ var ALLOWED_TOKENS = {
|
|
|
5943
6276
|
FontSize: true,
|
|
5944
6277
|
Decorators: true,
|
|
5945
6278
|
CodeBlock: true,
|
|
5946
|
-
Align: true
|
|
6279
|
+
Align: true,
|
|
6280
|
+
PageSetup: true
|
|
5947
6281
|
};
|
|
5948
6282
|
function sanitizePluginGroups(groups) {
|
|
5949
6283
|
if (!groups || groups.length === 0) return [];
|
|
@@ -6482,6 +6816,16 @@ var ToolBarPlugins = (props) => {
|
|
|
6482
6816
|
key
|
|
6483
6817
|
);
|
|
6484
6818
|
}
|
|
6819
|
+
case "PageSetup":
|
|
6820
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6821
|
+
PageSetupPlugin,
|
|
6822
|
+
{
|
|
6823
|
+
disabled: !isEditable || props.readOnly,
|
|
6824
|
+
value: props.pageSetup,
|
|
6825
|
+
onChange: props.onPageSetupChange
|
|
6826
|
+
},
|
|
6827
|
+
key
|
|
6828
|
+
);
|
|
6485
6829
|
default:
|
|
6486
6830
|
return null;
|
|
6487
6831
|
}
|
|
@@ -6833,6 +7177,8 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
6833
7177
|
const [charCount, setCharCount] = React9.useState(0);
|
|
6834
7178
|
const handleCharCount = React9.useCallback((count) => setCharCount(count), []);
|
|
6835
7179
|
const [refErrors, setRefErrors] = React9.useState([]);
|
|
7180
|
+
const [pageSetup, setPageSetup] = React9.useState(DEFAULT_PAGE_SETUP);
|
|
7181
|
+
const pageCanvas = resolvePageCanvasMetrics(pageSetup);
|
|
6836
7182
|
const contentEditableDomRef = React9.useRef(null);
|
|
6837
7183
|
const previousOverLimitRef = React9.useRef(false);
|
|
6838
7184
|
const focusedRef = React9.useRef(false);
|
|
@@ -6874,8 +7220,8 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
6874
7220
|
color: "var(--colorNeutralForeground3, grey)",
|
|
6875
7221
|
position: "absolute",
|
|
6876
7222
|
top: props.level !== "none" /* None */ ? "17px" : "27px",
|
|
6877
|
-
left:
|
|
6878
|
-
right:
|
|
7223
|
+
left: pageCanvas.paddingPx,
|
|
7224
|
+
right: pageCanvas.paddingPx,
|
|
6879
7225
|
fontSize: "14px",
|
|
6880
7226
|
pointerEvents: "none",
|
|
6881
7227
|
userSelect: "none"
|
|
@@ -6886,8 +7232,6 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
6886
7232
|
outline: "none",
|
|
6887
7233
|
overflow: "auto",
|
|
6888
7234
|
marginTop: "0px",
|
|
6889
|
-
paddingLeft: "20px",
|
|
6890
|
-
paddingRight: "20px",
|
|
6891
7235
|
position: "relative",
|
|
6892
7236
|
background: "var(--colorNeutralBackground1, #ffffff)",
|
|
6893
7237
|
justifyContent: "center",
|
|
@@ -6987,7 +7331,9 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
6987
7331
|
ToolBarPlugins,
|
|
6988
7332
|
{
|
|
6989
7333
|
level: props.level ?? "basic" /* Basic */,
|
|
6990
|
-
readOnly: props.readOnly
|
|
7334
|
+
readOnly: props.readOnly,
|
|
7335
|
+
pageSetup,
|
|
7336
|
+
onPageSetupChange: setPageSetup
|
|
6991
7337
|
}
|
|
6992
7338
|
)
|
|
6993
7339
|
}
|
|
@@ -7001,7 +7347,8 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
7001
7347
|
padding: "15px 0px",
|
|
7002
7348
|
overflowY: "scroll",
|
|
7003
7349
|
overflowX: "auto",
|
|
7004
|
-
minWidth: 0
|
|
7350
|
+
minWidth: 0,
|
|
7351
|
+
background: pageCanvas.widthPx !== void 0 ? "#eef0f2" : void 0
|
|
7005
7352
|
},
|
|
7006
7353
|
onClickCapture: handleReadOnlyClickCapture,
|
|
7007
7354
|
children: [
|
|
@@ -7020,7 +7367,15 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
7020
7367
|
{
|
|
7021
7368
|
ref: contentEditableDomRef,
|
|
7022
7369
|
className: react.css(EditorStyles.contentEditor),
|
|
7023
|
-
style: {
|
|
7370
|
+
style: {
|
|
7371
|
+
paddingTop: props.level !== "none" /* None */ ? 0 : 10,
|
|
7372
|
+
paddingLeft: pageCanvas.paddingPx,
|
|
7373
|
+
paddingRight: pageCanvas.paddingPx,
|
|
7374
|
+
maxWidth: pageCanvas.widthPx,
|
|
7375
|
+
marginLeft: pageCanvas.widthPx !== void 0 ? "auto" : void 0,
|
|
7376
|
+
marginRight: pageCanvas.widthPx !== void 0 ? "auto" : void 0,
|
|
7377
|
+
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
|
|
7378
|
+
},
|
|
7024
7379
|
spellCheck: !resolvedSpellCheck,
|
|
7025
7380
|
autoCorrect: resolvedSpellCheck ? "off" : void 0,
|
|
7026
7381
|
autoCapitalize: resolvedSpellCheck ? "off" : void 0
|