@tarviks/lexical-rich-editor 1.0.11 → 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 +738 -537
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +740 -539
- 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(
|
|
@@ -3488,310 +3758,112 @@ function $onDragStart2(event) {
|
|
|
3488
3758
|
if (!node) return false;
|
|
3489
3759
|
const dataTransfer = event.dataTransfer;
|
|
3490
3760
|
if (!dataTransfer) return false;
|
|
3491
|
-
dataTransfer.setData("text/plain", "_");
|
|
3492
|
-
dataTransfer.setDragImage(img2, 0, 0);
|
|
3493
|
-
dataTransfer.setData(
|
|
3494
|
-
"application/x-lexical-drag",
|
|
3495
|
-
JSON.stringify({
|
|
3496
|
-
data: {
|
|
3497
|
-
altText: node.__altText,
|
|
3498
|
-
caption: node.__caption,
|
|
3499
|
-
height: node.__height,
|
|
3500
|
-
key: node.getKey(),
|
|
3501
|
-
showCaption: node.__showCaption,
|
|
3502
|
-
src: node.__src,
|
|
3503
|
-
width: node.__width
|
|
3504
|
-
},
|
|
3505
|
-
type: "image"
|
|
3506
|
-
})
|
|
3507
|
-
);
|
|
3508
|
-
return true;
|
|
3509
|
-
}
|
|
3510
|
-
var $onDragover2 = (event) => {
|
|
3511
|
-
const node = $getImageNodeInSelection2();
|
|
3512
|
-
if (!node) return false;
|
|
3513
|
-
if (!canDropImage2(event)) {
|
|
3514
|
-
event.preventDefault();
|
|
3515
|
-
}
|
|
3516
|
-
return true;
|
|
3517
|
-
};
|
|
3518
|
-
var $onDrop2 = (event, editor) => {
|
|
3519
|
-
const node = $getImageNodeInSelection2();
|
|
3520
|
-
if (!node) return false;
|
|
3521
|
-
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);
|
|
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);
|
|
3761
|
+
dataTransfer.setData("text/plain", "_");
|
|
3762
|
+
dataTransfer.setDragImage(img2, 0, 0);
|
|
3763
|
+
dataTransfer.setData(
|
|
3764
|
+
"application/x-lexical-drag",
|
|
3765
|
+
JSON.stringify({
|
|
3766
|
+
data: {
|
|
3767
|
+
altText: node.__altText,
|
|
3768
|
+
caption: node.__caption,
|
|
3769
|
+
height: node.__height,
|
|
3770
|
+
key: node.getKey(),
|
|
3771
|
+
showCaption: node.__showCaption,
|
|
3772
|
+
src: node.__src,
|
|
3773
|
+
width: node.__width
|
|
3774
|
+
},
|
|
3775
|
+
type: "image"
|
|
3776
|
+
})
|
|
3777
|
+
);
|
|
3778
|
+
return true;
|
|
3779
|
+
}
|
|
3780
|
+
var $onDragover2 = (event) => {
|
|
3781
|
+
const node = $getImageNodeInSelection2();
|
|
3782
|
+
if (!node) return false;
|
|
3783
|
+
if (!canDropImage2(event)) {
|
|
3784
|
+
event.preventDefault();
|
|
3785
|
+
}
|
|
3786
|
+
return true;
|
|
3787
|
+
};
|
|
3788
|
+
var $onDrop2 = (event, editor) => {
|
|
3789
|
+
const node = $getImageNodeInSelection2();
|
|
3790
|
+
if (!node) return false;
|
|
3791
|
+
const data = getDragImageData2(event);
|
|
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);
|
|
3788
3800
|
}
|
|
3801
|
+
lexical.$setSelection(rangeSelection);
|
|
3802
|
+
editor.dispatchCommand(INSERT_INLINE_IMAGE_COMMAND, data);
|
|
3789
3803
|
}
|
|
3790
|
-
|
|
3791
|
-
|
|
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");
|
|
3834
|
+
}
|
|
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
|
+
);
|
|
3845
|
+
}
|
|
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) {
|
|
@@ -5112,40 +5187,6 @@ var hsvToRgb = (h, s, v) => {
|
|
|
5112
5187
|
b: Math.round((bb + m) * 255)
|
|
5113
5188
|
};
|
|
5114
5189
|
};
|
|
5115
|
-
function useDrag(onMove, onEnd, interactingRef) {
|
|
5116
|
-
const draggingRef = React9__namespace.useRef(false);
|
|
5117
|
-
const start = React9__namespace.useCallback(
|
|
5118
|
-
(e) => {
|
|
5119
|
-
draggingRef.current = true;
|
|
5120
|
-
if (interactingRef) interactingRef.current = true;
|
|
5121
|
-
onMove(e.clientX, e.clientY);
|
|
5122
|
-
const move = (ev) => {
|
|
5123
|
-
if (!draggingRef.current) return;
|
|
5124
|
-
onMove(ev.clientX, ev.clientY);
|
|
5125
|
-
};
|
|
5126
|
-
const up = () => {
|
|
5127
|
-
draggingRef.current = false;
|
|
5128
|
-
window.removeEventListener("mousemove", move);
|
|
5129
|
-
window.removeEventListener("mouseup", up);
|
|
5130
|
-
if (interactingRef) {
|
|
5131
|
-
const clearFlag = () => {
|
|
5132
|
-
interactingRef.current = false;
|
|
5133
|
-
};
|
|
5134
|
-
window.addEventListener("click", clearFlag, { once: true });
|
|
5135
|
-
setTimeout(() => {
|
|
5136
|
-
window.removeEventListener("click", clearFlag);
|
|
5137
|
-
interactingRef.current = false;
|
|
5138
|
-
}, 0);
|
|
5139
|
-
}
|
|
5140
|
-
onEnd?.();
|
|
5141
|
-
};
|
|
5142
|
-
window.addEventListener("mousemove", move);
|
|
5143
|
-
window.addEventListener("mouseup", up);
|
|
5144
|
-
},
|
|
5145
|
-
[onMove, onEnd, interactingRef]
|
|
5146
|
-
);
|
|
5147
|
-
return start;
|
|
5148
|
-
}
|
|
5149
5190
|
var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange }) => {
|
|
5150
5191
|
const [open, setOpen] = React9__namespace.useState(false);
|
|
5151
5192
|
const btnRef = React9__namespace.useRef(null);
|
|
@@ -5156,13 +5197,9 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5156
5197
|
},
|
|
5157
5198
|
[onOpenChange]
|
|
5158
5199
|
);
|
|
5159
|
-
const interactingRef = React9__namespace.useRef(false);
|
|
5160
5200
|
const handleDismiss = React9__namespace.useCallback(() => setOpenAndNotify(false), [setOpenAndNotify]);
|
|
5161
5201
|
const preventDismissOnEvent = React9__namespace.useCallback(
|
|
5162
|
-
(ev) =>
|
|
5163
|
-
if (interactingRef.current) return true;
|
|
5164
|
-
return ev.type !== "click";
|
|
5165
|
-
},
|
|
5202
|
+
(ev) => ev.type !== "click",
|
|
5166
5203
|
[]
|
|
5167
5204
|
);
|
|
5168
5205
|
const [, forceReposition] = React9__namespace.useState(0);
|
|
@@ -5184,100 +5221,119 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5184
5221
|
window.removeEventListener("resize", reposition);
|
|
5185
5222
|
};
|
|
5186
5223
|
}, [open]);
|
|
5187
|
-
const
|
|
5224
|
+
const appliedHex = React9__namespace.useMemo(() => normalizeHex(value || "#000000"), [value]);
|
|
5225
|
+
const [hex, setHexState] = React9__namespace.useState(appliedHex);
|
|
5226
|
+
const [hexText, setHexText] = React9__namespace.useState(appliedHex);
|
|
5188
5227
|
const { r, g, b } = React9__namespace.useMemo(() => hexToRgb(hex), [hex]);
|
|
5189
5228
|
const hsv = React9__namespace.useMemo(() => rgbToHsv(r, g, b), [r, g, b]);
|
|
5190
5229
|
const [h, setH] = React9__namespace.useState(hsv.h);
|
|
5191
5230
|
const [s, setS] = React9__namespace.useState(hsv.s);
|
|
5192
5231
|
const [v, setV] = React9__namespace.useState(hsv.v);
|
|
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
|
+
);
|
|
5193
5258
|
const wasOpenRef = React9__namespace.useRef(open);
|
|
5194
|
-
console.log("[AO-ColorPicker]", title, "render with incoming value prop:", JSON.stringify(value));
|
|
5195
5259
|
React9__namespace.useEffect(() => {
|
|
5196
5260
|
const justOpened = open && !wasOpenRef.current;
|
|
5197
5261
|
wasOpenRef.current = open;
|
|
5198
|
-
console.log("[AO-ColorPicker]", title, "open-seed effect", {
|
|
5199
|
-
open,
|
|
5200
|
-
justOpened,
|
|
5201
|
-
incomingValue: value
|
|
5202
|
-
});
|
|
5203
5262
|
if (!justOpened) return;
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
normalized: n
|
|
5208
|
-
});
|
|
5209
|
-
setHex(n);
|
|
5210
|
-
const rgb = hexToRgb(n);
|
|
5263
|
+
setHexState(appliedHex);
|
|
5264
|
+
setHexText(appliedHex);
|
|
5265
|
+
const rgb = hexToRgb(appliedHex);
|
|
5211
5266
|
const next = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
5212
5267
|
setH(next.h);
|
|
5213
5268
|
setS(next.s);
|
|
5214
5269
|
setV(next.v);
|
|
5215
|
-
}, [
|
|
5216
|
-
const
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5270
|
+
}, [appliedHex, open]);
|
|
5271
|
+
const svRef = React9__namespace.useRef(null);
|
|
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 };
|
|
5221
5280
|
}, []);
|
|
5222
|
-
const
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
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);
|
|
5228
5288
|
},
|
|
5229
|
-
[
|
|
5289
|
+
[svPointFromEvent, commitFromHsv]
|
|
5230
5290
|
);
|
|
5231
|
-
const
|
|
5291
|
+
const handleSVPointerMove = React9__namespace.useCallback(
|
|
5292
|
+
(e) => {
|
|
5293
|
+
if (e.buttons !== 1) return;
|
|
5294
|
+
const pt = svPointFromEvent(e.clientX, e.clientY);
|
|
5295
|
+
if (pt) commitFromHsv(hRef.current, pt.ss, pt.vv);
|
|
5296
|
+
},
|
|
5297
|
+
[svPointFromEvent, commitFromHsv]
|
|
5298
|
+
);
|
|
5299
|
+
const hueRef = React9__namespace.useRef(null);
|
|
5232
5300
|
const sRef = React9__namespace.useRef(s);
|
|
5301
|
+
sRef.current = s;
|
|
5233
5302
|
const vRef = React9__namespace.useRef(v);
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
if (!svRef.current) return;
|
|
5247
|
-
const rect = svRef.current.getBoundingClientRect();
|
|
5248
|
-
const x = clamp3(clientX - rect.left, 0, rect.width);
|
|
5249
|
-
const y = clamp3(clientY - rect.top, 0, rect.height);
|
|
5250
|
-
const ss = rect.width === 0 ? 0 : x / rect.width;
|
|
5251
|
-
const vv = rect.height === 0 ? 0 : 1 - y / rect.height;
|
|
5252
|
-
setS(ss);
|
|
5253
|
-
setV(vv);
|
|
5254
|
-
sRef.current = ss;
|
|
5255
|
-
vRef.current = vv;
|
|
5256
|
-
updateHexFromHsv(hRef.current, ss, vv);
|
|
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);
|
|
5257
5315
|
},
|
|
5258
|
-
[
|
|
5316
|
+
[huePointFromEvent, commitFromHsv]
|
|
5259
5317
|
);
|
|
5260
|
-
const
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
const
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
updateHexFromHsv(hh, sRef.current, vRef.current);
|
|
5318
|
+
const handleHuePointerMove = React9__namespace.useCallback(
|
|
5319
|
+
(e) => {
|
|
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));
|
|
5274
5331
|
},
|
|
5275
|
-
[
|
|
5332
|
+
[commit]
|
|
5276
5333
|
);
|
|
5277
|
-
const
|
|
5278
|
-
|
|
5279
|
-
}, [
|
|
5280
|
-
const startHue = useDrag((x) => onHueMove(x), commitHue, interactingRef);
|
|
5334
|
+
const handleHexBlur = React9__namespace.useCallback(() => {
|
|
5335
|
+
commit(normalizeHex(hexText));
|
|
5336
|
+
}, [hexText, commit]);
|
|
5281
5337
|
const svThumb = React9__namespace.useMemo(() => ({ left: `${s * 100}%`, top: `${(1 - v) * 100}%` }), [s, v]);
|
|
5282
5338
|
const hueThumb = React9__namespace.useMemo(() => ({ left: `${h / 360 * 100}%` }), [h]);
|
|
5283
5339
|
const hueColor = React9__namespace.useMemo(() => {
|
|
@@ -5302,10 +5358,6 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5302
5358
|
},
|
|
5303
5359
|
onClick: () => {
|
|
5304
5360
|
if (disabled) return;
|
|
5305
|
-
console.log("[AO-ColorPicker]", title, "trigger button clicked", {
|
|
5306
|
-
wasOpen: open,
|
|
5307
|
-
activeElementBeforeToggle: document.activeElement?.tagName
|
|
5308
|
-
});
|
|
5309
5361
|
setOpenAndNotify(!open);
|
|
5310
5362
|
}
|
|
5311
5363
|
}
|
|
@@ -5320,7 +5372,7 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5320
5372
|
transform: "translateX(-50%)",
|
|
5321
5373
|
width: 14,
|
|
5322
5374
|
height: 3,
|
|
5323
|
-
background:
|
|
5375
|
+
background: appliedHex,
|
|
5324
5376
|
borderRadius: 1,
|
|
5325
5377
|
border: "0.5px solid rgba(0,0,0,0.18)",
|
|
5326
5378
|
pointerEvents: "none"
|
|
@@ -5336,72 +5388,192 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5336
5388
|
directionalHint: 4,
|
|
5337
5389
|
className: "aoColorCallout",
|
|
5338
5390
|
preventDismissOnEvent,
|
|
5339
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap:
|
|
5340
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
5341
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
5342
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "aoLexTitle", children: title })
|
|
5343
|
-
] }),
|
|
5344
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aoLexRow", children: [
|
|
5345
|
-
/* @__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 }),
|
|
5346
5394
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5347
|
-
|
|
5395
|
+
"button",
|
|
5348
5396
|
{
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
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, {})
|
|
5362
5416
|
}
|
|
5363
5417
|
)
|
|
5364
5418
|
] }),
|
|
5365
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5366
|
-
"
|
|
5419
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5420
|
+
"div",
|
|
5367
5421
|
{
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
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)"
|
|
5380
5434
|
},
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
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: [
|
|
5394
5513
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5395
|
-
|
|
5514
|
+
"div",
|
|
5396
5515
|
{
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
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)"
|
|
5401
5523
|
}
|
|
5402
5524
|
}
|
|
5403
5525
|
),
|
|
5404
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
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
|
+
)
|
|
5538
|
+
] }),
|
|
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
|
+
)
|
|
5405
5577
|
] })
|
|
5406
5578
|
] })
|
|
5407
5579
|
}
|
|
@@ -5414,20 +5586,10 @@ var ColorPickerPlugin = ({ disabled }) => {
|
|
|
5414
5586
|
const lastRangeSelectionRef = React9__namespace.default.useRef(null);
|
|
5415
5587
|
const updateToolbar = () => {
|
|
5416
5588
|
const selection$1 = lexical.$getSelection();
|
|
5417
|
-
|
|
5418
|
-
console.log("[AO-ColorPicker] updateToolbar", {
|
|
5419
|
-
isRangeSelection: isRange,
|
|
5420
|
-
isCollapsed: isRange ? selection$1.isCollapsed() : null
|
|
5421
|
-
});
|
|
5422
|
-
if (isRange) {
|
|
5589
|
+
if (lexical.$isRangeSelection(selection$1)) {
|
|
5423
5590
|
lastRangeSelectionRef.current = selection$1.clone();
|
|
5424
5591
|
const c = selection.$getSelectionStyleValueForProperty(selection$1, "color", "#000000");
|
|
5425
|
-
const bg = selection.$getSelectionStyleValueForProperty(
|
|
5426
|
-
selection$1,
|
|
5427
|
-
"background-color",
|
|
5428
|
-
"#ffffff"
|
|
5429
|
-
);
|
|
5430
|
-
console.log("[AO-ColorPicker] updateToolbar readback", { color: c, bgColor: bg });
|
|
5592
|
+
const bg = selection.$getSelectionStyleValueForProperty(selection$1, "background-color", "#ffffff");
|
|
5431
5593
|
setColors({ color: c, bgColor: bg });
|
|
5432
5594
|
}
|
|
5433
5595
|
};
|
|
@@ -5457,15 +5619,6 @@ var ColorPickerPlugin = ({ disabled }) => {
|
|
|
5457
5619
|
};
|
|
5458
5620
|
const applyStyle = (args) => {
|
|
5459
5621
|
if (disabled) return;
|
|
5460
|
-
console.log("[AO-ColorPicker] applyStyle called", {
|
|
5461
|
-
property: args.property,
|
|
5462
|
-
color: args.color,
|
|
5463
|
-
hasSavedSelection: !!lastRangeSelectionRef.current,
|
|
5464
|
-
savedSelectionIsCollapsed: lastRangeSelectionRef.current?.isCollapsed() ?? null,
|
|
5465
|
-
wasEditorActiveAtOpen: wasEditorActiveRef.current,
|
|
5466
|
-
activeElementTag: document.activeElement?.tagName,
|
|
5467
|
-
activeElementClass: document.activeElement?.className
|
|
5468
|
-
});
|
|
5469
5622
|
editor.update(
|
|
5470
5623
|
() => {
|
|
5471
5624
|
const saved = lastRangeSelectionRef.current;
|
|
@@ -5473,39 +5626,17 @@ var ColorPickerPlugin = ({ disabled }) => {
|
|
|
5473
5626
|
lexical.$setSelection(saved.clone());
|
|
5474
5627
|
}
|
|
5475
5628
|
const selection$1 = lexical.$getSelection();
|
|
5476
|
-
|
|
5477
|
-
console.log("[AO-ColorPicker] applyStyle inside editor.update", {
|
|
5478
|
-
hadSavedSelection: !!saved,
|
|
5479
|
-
selectionAfterRestoreIsRange: isRange,
|
|
5480
|
-
selectionAfterRestoreIsCollapsed: isRange ? selection$1.isCollapsed() : null
|
|
5481
|
-
});
|
|
5482
|
-
if (isRange) {
|
|
5629
|
+
if (lexical.$isRangeSelection(selection$1)) {
|
|
5483
5630
|
selection.$patchStyleText(selection$1, { [args.property]: args.color });
|
|
5484
|
-
const verify = selection.$getSelectionStyleValueForProperty(
|
|
5485
|
-
selection$1,
|
|
5486
|
-
args.property,
|
|
5487
|
-
"<none>"
|
|
5488
|
-
);
|
|
5489
|
-
console.log("[AO-ColorPicker] applyStyle after patchStyleText, readback in same update", {
|
|
5490
|
-
property: args.property,
|
|
5491
|
-
appliedColor: args.color,
|
|
5492
|
-
readBack: verify
|
|
5493
|
-
});
|
|
5494
|
-
} else {
|
|
5495
|
-
console.warn(
|
|
5496
|
-
"[AO-ColorPicker] applyStyle: no range selection available \u2014 style was NOT applied",
|
|
5497
|
-
{ property: args.property, color: args.color }
|
|
5498
|
-
);
|
|
5499
5631
|
}
|
|
5500
5632
|
},
|
|
5501
5633
|
// Without this tag, Lexical's reconciler force-focuses the editor root
|
|
5502
5634
|
// whenever this update's selection diff finds the root isn't already
|
|
5503
|
-
// focused
|
|
5504
|
-
//
|
|
5505
|
-
//
|
|
5506
|
-
//
|
|
5507
|
-
//
|
|
5508
|
-
// popover until the drag's tracked color desynced from the cursor.
|
|
5635
|
+
// focused — which it isn't while the color picker's Callout holds
|
|
5636
|
+
// focus. The picker now only calls applyStyle once, on Apply, so this
|
|
5637
|
+
// is no longer fighting for focus on every drag pixel, but there's no
|
|
5638
|
+
// reason to force a focus change here at all — handleOpenChange above
|
|
5639
|
+
// already does that deliberately, once, on close.
|
|
5509
5640
|
{ tag: lexical.SKIP_SELECTION_FOCUS_TAG }
|
|
5510
5641
|
);
|
|
5511
5642
|
};
|
|
@@ -5874,6 +6005,60 @@ var InsertLinkPlugin = ({ disabled }) => {
|
|
|
5874
6005
|
}
|
|
5875
6006
|
);
|
|
5876
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
|
+
}
|
|
5877
6062
|
var TableItemPlugin = ({ disabled }) => {
|
|
5878
6063
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
5879
6064
|
const [columns, setColumns] = React9.useState("");
|
|
@@ -6091,7 +6276,8 @@ var ALLOWED_TOKENS = {
|
|
|
6091
6276
|
FontSize: true,
|
|
6092
6277
|
Decorators: true,
|
|
6093
6278
|
CodeBlock: true,
|
|
6094
|
-
Align: true
|
|
6279
|
+
Align: true,
|
|
6280
|
+
PageSetup: true
|
|
6095
6281
|
};
|
|
6096
6282
|
function sanitizePluginGroups(groups) {
|
|
6097
6283
|
if (!groups || groups.length === 0) return [];
|
|
@@ -6630,6 +6816,16 @@ var ToolBarPlugins = (props) => {
|
|
|
6630
6816
|
key
|
|
6631
6817
|
);
|
|
6632
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
|
+
);
|
|
6633
6829
|
default:
|
|
6634
6830
|
return null;
|
|
6635
6831
|
}
|
|
@@ -6851,12 +7047,6 @@ function FocusEventsPlugin({
|
|
|
6851
7047
|
const next = e.relatedTarget;
|
|
6852
7048
|
const container = containerRef.current;
|
|
6853
7049
|
const stillInside = !!next && (container ? container.contains(next) : root.contains(next));
|
|
6854
|
-
console.log("[AO-ColorPicker] FocusEventsPlugin focusout", {
|
|
6855
|
-
relatedTargetTag: next ? next.tagName : null,
|
|
6856
|
-
relatedTargetClass: next ? next.className : null,
|
|
6857
|
-
stillInside,
|
|
6858
|
-
willClearSelection: !stillInside
|
|
6859
|
-
});
|
|
6860
7050
|
if (stillInside) return;
|
|
6861
7051
|
editor.update(() => {
|
|
6862
7052
|
lexical.$setSelection(null);
|
|
@@ -6987,6 +7177,8 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
6987
7177
|
const [charCount, setCharCount] = React9.useState(0);
|
|
6988
7178
|
const handleCharCount = React9.useCallback((count) => setCharCount(count), []);
|
|
6989
7179
|
const [refErrors, setRefErrors] = React9.useState([]);
|
|
7180
|
+
const [pageSetup, setPageSetup] = React9.useState(DEFAULT_PAGE_SETUP);
|
|
7181
|
+
const pageCanvas = resolvePageCanvasMetrics(pageSetup);
|
|
6990
7182
|
const contentEditableDomRef = React9.useRef(null);
|
|
6991
7183
|
const previousOverLimitRef = React9.useRef(false);
|
|
6992
7184
|
const focusedRef = React9.useRef(false);
|
|
@@ -7028,8 +7220,8 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
7028
7220
|
color: "var(--colorNeutralForeground3, grey)",
|
|
7029
7221
|
position: "absolute",
|
|
7030
7222
|
top: props.level !== "none" /* None */ ? "17px" : "27px",
|
|
7031
|
-
left:
|
|
7032
|
-
right:
|
|
7223
|
+
left: pageCanvas.paddingPx,
|
|
7224
|
+
right: pageCanvas.paddingPx,
|
|
7033
7225
|
fontSize: "14px",
|
|
7034
7226
|
pointerEvents: "none",
|
|
7035
7227
|
userSelect: "none"
|
|
@@ -7040,8 +7232,6 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
7040
7232
|
outline: "none",
|
|
7041
7233
|
overflow: "auto",
|
|
7042
7234
|
marginTop: "0px",
|
|
7043
|
-
paddingLeft: "20px",
|
|
7044
|
-
paddingRight: "20px",
|
|
7045
7235
|
position: "relative",
|
|
7046
7236
|
background: "var(--colorNeutralBackground1, #ffffff)",
|
|
7047
7237
|
justifyContent: "center",
|
|
@@ -7141,7 +7331,9 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
7141
7331
|
ToolBarPlugins,
|
|
7142
7332
|
{
|
|
7143
7333
|
level: props.level ?? "basic" /* Basic */,
|
|
7144
|
-
readOnly: props.readOnly
|
|
7334
|
+
readOnly: props.readOnly,
|
|
7335
|
+
pageSetup,
|
|
7336
|
+
onPageSetupChange: setPageSetup
|
|
7145
7337
|
}
|
|
7146
7338
|
)
|
|
7147
7339
|
}
|
|
@@ -7155,7 +7347,8 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
7155
7347
|
padding: "15px 0px",
|
|
7156
7348
|
overflowY: "scroll",
|
|
7157
7349
|
overflowX: "auto",
|
|
7158
|
-
minWidth: 0
|
|
7350
|
+
minWidth: 0,
|
|
7351
|
+
background: pageCanvas.widthPx !== void 0 ? "#eef0f2" : void 0
|
|
7159
7352
|
},
|
|
7160
7353
|
onClickCapture: handleReadOnlyClickCapture,
|
|
7161
7354
|
children: [
|
|
@@ -7174,7 +7367,15 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
7174
7367
|
{
|
|
7175
7368
|
ref: contentEditableDomRef,
|
|
7176
7369
|
className: react.css(EditorStyles.contentEditor),
|
|
7177
|
-
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
|
+
},
|
|
7178
7379
|
spellCheck: !resolvedSpellCheck,
|
|
7179
7380
|
autoCorrect: resolvedSpellCheck ? "off" : void 0,
|
|
7180
7381
|
autoCapitalize: resolvedSpellCheck ? "off" : void 0
|