@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.mjs
CHANGED
|
@@ -6,9 +6,9 @@ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext
|
|
|
6
6
|
import { useLexicalEditable } from '@lexical/react/useLexicalEditable';
|
|
7
7
|
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';
|
|
8
8
|
import { createCommand, DecoratorNode, COMMAND_PRIORITY_HIGH, TextNode, ElementNode, $setSelection, $getSelection, $isRangeSelection, SELECTION_CHANGE_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, $findMatchingParent, COMMAND_PRIORITY_LOW, KEY_DOWN_COMMAND, $insertNodes, $isRootOrShadowRoot, $createParagraphNode, COMMAND_PRIORITY_EDITOR, PASTE_COMMAND, DRAGSTART_COMMAND, DRAGOVER_COMMAND, DROP_COMMAND, $getNodeByKey, $getRoot, $createTextNode, $isTextNode, $createRangeSelection, $isElementNode, $isNodeSelection, CLICK_COMMAND, $applyNodeReplacement, FORMAT_TEXT_COMMAND, $isDecoratorNode, $getNearestNodeFromDOMNode, COMMAND_PRIORITY_CRITICAL, REDO_COMMAND, UNDO_COMMAND, getDOMSelection, KEY_ESCAPE_COMMAND, isHTMLElement, getDOMSelectionFromTarget, SKIP_SELECTION_FOCUS_TAG, createEditor, KEY_ENTER_COMMAND } from 'lexical';
|
|
9
|
-
import { mergeStyleSets, Stack, css, useTheme, Callout, TextField
|
|
10
|
-
import { makeStyles, FluentProvider, webLightTheme, Menu, MenuTrigger, MenuPopover, MenuList, MenuGroup, MenuGroupHeader, MenuItem, MenuDivider, Dropdown, Option, ToolbarDivider, Button, Popover, PopoverTrigger, PopoverSurface, Field, Input } from '@fluentui/react-components';
|
|
11
|
-
import { ErrorCircleRegular, ChevronDown12Regular, ArrowUpRegular, RowTripleRegular, ArrowDownRegular, ArrowLeftRegular, ColumnTripleRegular, ArrowRightRegular, DeleteRegular, TextCaseUppercaseFilled, TextCaseLowercaseFilled, TextCaseTitleFilled, TextStrikethroughFilled, TextSubscriptFilled, TextSuperscriptFilled, HighlightAccentFilled, TextBulletListLtrFilled, TextNumberListLtrFilled, DocumentPageBreakRegular, CommentQuoteRegular, TextUnderlineFilled, TextItalicFilled, TextBold24Regular, TextAlignLeftFilled, TextAlignCenterFilled, TextAlignRightFilled, TextAlignJustifyFilled, VideoClipRegular, ImageEditRegular, AttachFilled, ImageAddRegular, TableAddRegular, LinkAddRegular, TextColorRegular, PaintBucket16Filled, CodeFilled, LinkFilled } from '@fluentui/react-icons';
|
|
9
|
+
import { mergeStyleSets, Stack, css, useTheme, Callout, TextField } from '@fluentui/react';
|
|
10
|
+
import { makeStyles, FluentProvider, webLightTheme, Menu, MenuTrigger, MenuPopover, MenuList, MenuGroup, MenuGroupHeader, MenuItem, MenuDivider, Dropdown, Option, ToolbarDivider, Button, MenuItemRadio, Popover, PopoverTrigger, PopoverSurface, Field, Input } from '@fluentui/react-components';
|
|
11
|
+
import { ErrorCircleRegular, ChevronDown12Regular, ArrowUpRegular, RowTripleRegular, ArrowDownRegular, ArrowLeftRegular, ColumnTripleRegular, ArrowRightRegular, DeleteRegular, TextCaseUppercaseFilled, TextCaseLowercaseFilled, TextCaseTitleFilled, TextStrikethroughFilled, TextSubscriptFilled, TextSuperscriptFilled, HighlightAccentFilled, TextBulletListLtrFilled, TextNumberListLtrFilled, DocumentPageBreakRegular, CommentQuoteRegular, TextUnderlineFilled, TextItalicFilled, TextBold24Regular, DocumentRegular, TextAlignLeftFilled, TextAlignCenterFilled, TextAlignRightFilled, TextAlignJustifyFilled, VideoClipRegular, ImageEditRegular, AttachFilled, ImageAddRegular, TableAddRegular, LinkAddRegular, TextColorRegular, PaintBucket16Filled, CodeFilled, LinkFilled, Dismiss16Regular } from '@fluentui/react-icons';
|
|
12
12
|
import { CodeHighlightNode, CodeNode, $isCodeHighlightNode } from '@lexical/code';
|
|
13
13
|
import { LinkNode, AutoLinkNode, $isLinkNode, $isAutoLinkNode, TOGGLE_LINK_COMMAND, $createLinkNode } from '@lexical/link';
|
|
14
14
|
import { ListNode, ListItemNode, $isListNode, REMOVE_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND } from '@lexical/list';
|
|
@@ -1228,6 +1228,46 @@ var ContentEditorLevel = /* @__PURE__ */ ((ContentEditorLevel2) => {
|
|
|
1228
1228
|
ContentEditorLevel2["Pro"] = "pro";
|
|
1229
1229
|
return ContentEditorLevel2;
|
|
1230
1230
|
})(ContentEditorLevel || {});
|
|
1231
|
+
|
|
1232
|
+
// src/Types/PageSetup.ts
|
|
1233
|
+
var DEFAULT_PAGE_SETUP = {
|
|
1234
|
+
size: "pageless",
|
|
1235
|
+
orientation: "portrait",
|
|
1236
|
+
margin: "normal"
|
|
1237
|
+
};
|
|
1238
|
+
var PAGE_SIZE_OPTIONS = [
|
|
1239
|
+
{ key: "a4", label: 'A4 (8.27" x 11.69")', widthIn: 8.27, heightIn: 11.69 },
|
|
1240
|
+
{ key: "letter", label: 'Letter (8.5" x 11")', widthIn: 8.5, heightIn: 11 },
|
|
1241
|
+
{ key: "legal", label: 'Legal (8.5" x 14")', widthIn: 8.5, heightIn: 14 },
|
|
1242
|
+
{ key: "tabloid", label: 'Tabloid (11" x 17")', widthIn: 11, heightIn: 17 },
|
|
1243
|
+
{ key: "a3", label: 'A3 (11.69" x 16.54")', widthIn: 11.69, heightIn: 16.54 },
|
|
1244
|
+
{ key: "a5", label: 'A5 (5.83" x 8.27")', widthIn: 5.83, heightIn: 8.27 },
|
|
1245
|
+
{ key: "b4", label: 'B4 (9.84" x 13.90")', widthIn: 9.84, heightIn: 13.9 },
|
|
1246
|
+
{ key: "b5", label: 'B5 (6.93" x 9.84")', widthIn: 6.93, heightIn: 9.84 },
|
|
1247
|
+
{ key: "statement", label: 'Statement (5.5" x 8.5")', widthIn: 5.5, heightIn: 8.5 },
|
|
1248
|
+
{ key: "executive", label: 'Executive (7.25" x 10.5")', widthIn: 7.25, heightIn: 10.5 },
|
|
1249
|
+
{ key: "folio", label: 'Folio (8.5" x 13")', widthIn: 8.5, heightIn: 13 }
|
|
1250
|
+
];
|
|
1251
|
+
var MARGIN_OPTIONS = [
|
|
1252
|
+
{ key: "narrow", label: 'Narrow (0.25")', valueIn: 0.25 },
|
|
1253
|
+
{ key: "normal", label: 'Normal (0.4")', valueIn: 0.4 },
|
|
1254
|
+
{ key: "moderate", label: 'Moderate (0.75")', valueIn: 0.75 },
|
|
1255
|
+
{ key: "wide", label: 'Wide (1")', valueIn: 1 }
|
|
1256
|
+
];
|
|
1257
|
+
var CSS_PX_PER_INCH = 96;
|
|
1258
|
+
function resolvePageCanvasMetrics(value) {
|
|
1259
|
+
const margin = MARGIN_OPTIONS.find((o) => o.key === value.margin) ?? MARGIN_OPTIONS[1];
|
|
1260
|
+
if (value.size === "pageless") {
|
|
1261
|
+
return { widthPx: void 0, paddingPx: 20 };
|
|
1262
|
+
}
|
|
1263
|
+
const size = PAGE_SIZE_OPTIONS.find((o) => o.key === value.size);
|
|
1264
|
+
if (!size) return { widthPx: void 0, paddingPx: 20 };
|
|
1265
|
+
const widthIn = value.orientation === "landscape" ? size.heightIn : size.widthIn;
|
|
1266
|
+
return {
|
|
1267
|
+
widthPx: Math.round(widthIn * CSS_PX_PER_INCH),
|
|
1268
|
+
paddingPx: Math.round(margin.valueIn * CSS_PX_PER_INCH)
|
|
1269
|
+
};
|
|
1270
|
+
}
|
|
1231
1271
|
var AutocompleteNode = class _AutocompleteNode extends TextNode {
|
|
1232
1272
|
static getType() {
|
|
1233
1273
|
return "autocomplete";
|
|
@@ -2466,6 +2506,236 @@ function CharacterStylesPopupPlugin(props) {
|
|
|
2466
2506
|
const [editor] = useLexicalComposerContext();
|
|
2467
2507
|
return useCharacterStylesPopup(editor, props);
|
|
2468
2508
|
}
|
|
2509
|
+
|
|
2510
|
+
// src/Utils/Sanitize.ts
|
|
2511
|
+
var DROP_ENTIRELY = /* @__PURE__ */ new Set([
|
|
2512
|
+
"script",
|
|
2513
|
+
"noscript",
|
|
2514
|
+
"style",
|
|
2515
|
+
"object",
|
|
2516
|
+
"embed",
|
|
2517
|
+
"form",
|
|
2518
|
+
"input",
|
|
2519
|
+
"button",
|
|
2520
|
+
"select",
|
|
2521
|
+
"textarea",
|
|
2522
|
+
"meta",
|
|
2523
|
+
"link",
|
|
2524
|
+
"base"
|
|
2525
|
+
]);
|
|
2526
|
+
var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
2527
|
+
// Block
|
|
2528
|
+
"p",
|
|
2529
|
+
"h1",
|
|
2530
|
+
"h2",
|
|
2531
|
+
"h3",
|
|
2532
|
+
"h4",
|
|
2533
|
+
"h5",
|
|
2534
|
+
"h6",
|
|
2535
|
+
"ul",
|
|
2536
|
+
"ol",
|
|
2537
|
+
"li",
|
|
2538
|
+
"blockquote",
|
|
2539
|
+
"pre",
|
|
2540
|
+
"div",
|
|
2541
|
+
"table",
|
|
2542
|
+
"thead",
|
|
2543
|
+
"tbody",
|
|
2544
|
+
"tfoot",
|
|
2545
|
+
"tr",
|
|
2546
|
+
"td",
|
|
2547
|
+
"th",
|
|
2548
|
+
// Inline
|
|
2549
|
+
"span",
|
|
2550
|
+
"a",
|
|
2551
|
+
"strong",
|
|
2552
|
+
"b",
|
|
2553
|
+
"em",
|
|
2554
|
+
"i",
|
|
2555
|
+
"u",
|
|
2556
|
+
"s",
|
|
2557
|
+
"del",
|
|
2558
|
+
"strike",
|
|
2559
|
+
"sub",
|
|
2560
|
+
"sup",
|
|
2561
|
+
"mark",
|
|
2562
|
+
"code",
|
|
2563
|
+
"br",
|
|
2564
|
+
"hr",
|
|
2565
|
+
// Media / embeds
|
|
2566
|
+
"img",
|
|
2567
|
+
"iframe"
|
|
2568
|
+
]);
|
|
2569
|
+
var ALLOWED_ATTRS = /* @__PURE__ */ new Set([
|
|
2570
|
+
// Presentation
|
|
2571
|
+
"class",
|
|
2572
|
+
"style",
|
|
2573
|
+
"dir",
|
|
2574
|
+
"lang",
|
|
2575
|
+
// Anchors
|
|
2576
|
+
"href",
|
|
2577
|
+
"target",
|
|
2578
|
+
"rel",
|
|
2579
|
+
// Images
|
|
2580
|
+
"src",
|
|
2581
|
+
"alt",
|
|
2582
|
+
"width",
|
|
2583
|
+
"height",
|
|
2584
|
+
// Tables
|
|
2585
|
+
"colspan",
|
|
2586
|
+
"rowspan",
|
|
2587
|
+
// Lists — <ol type="a"> and <ol start="2">
|
|
2588
|
+
"start",
|
|
2589
|
+
"type",
|
|
2590
|
+
// Lexical-internal data markers
|
|
2591
|
+
"data-lex-block",
|
|
2592
|
+
"data-kind",
|
|
2593
|
+
"data-lexical-decorator",
|
|
2594
|
+
// Misc
|
|
2595
|
+
"title",
|
|
2596
|
+
"allowfullscreen"
|
|
2597
|
+
]);
|
|
2598
|
+
var DANGEROUS_URL = /^\s*(javascript|data\s*:|vbscript)/i;
|
|
2599
|
+
function sanitizeElement(el) {
|
|
2600
|
+
for (const child of Array.from(el.children)) {
|
|
2601
|
+
sanitizeElement(child);
|
|
2602
|
+
}
|
|
2603
|
+
const tag = el.tagName.toLowerCase();
|
|
2604
|
+
if (DROP_ENTIRELY.has(tag)) {
|
|
2605
|
+
el.parentNode?.removeChild(el);
|
|
2606
|
+
return;
|
|
2607
|
+
}
|
|
2608
|
+
if (tag === "iframe") {
|
|
2609
|
+
const src = el.getAttribute("src") ?? "";
|
|
2610
|
+
const isYouTube = /^\s*https:\/\/(www\.)?(youtube\.com|youtube-nocookie\.com)\/embed\/[^?&/]+/i.test(src);
|
|
2611
|
+
if (!isYouTube) {
|
|
2612
|
+
el.parentNode?.removeChild(el);
|
|
2613
|
+
return;
|
|
2614
|
+
}
|
|
2615
|
+
}
|
|
2616
|
+
if (!ALLOWED_TAGS.has(tag)) {
|
|
2617
|
+
while (el.firstChild) {
|
|
2618
|
+
el.parentNode?.insertBefore(el.firstChild, el);
|
|
2619
|
+
}
|
|
2620
|
+
el.parentNode?.removeChild(el);
|
|
2621
|
+
return;
|
|
2622
|
+
}
|
|
2623
|
+
for (const { name, value } of Array.from(el.attributes)) {
|
|
2624
|
+
const lname = name.toLowerCase();
|
|
2625
|
+
if (!ALLOWED_ATTRS.has(lname)) {
|
|
2626
|
+
el.removeAttribute(name);
|
|
2627
|
+
continue;
|
|
2628
|
+
}
|
|
2629
|
+
if (lname === "href" || lname === "src") {
|
|
2630
|
+
if (DANGEROUS_URL.test(value)) {
|
|
2631
|
+
el.removeAttribute(name);
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
if (lname === "style") {
|
|
2635
|
+
const safe = value.replace(/expression\s*\(/gi, "(").replace(/url\s*\(\s*['"]?\s*javascript:/gi, "url(");
|
|
2636
|
+
el.setAttribute("style", safe);
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
if (tag === "a" && (el.getAttribute("target") || "").toLowerCase() === "_blank") {
|
|
2640
|
+
const rel = (el.getAttribute("rel") || "").trim();
|
|
2641
|
+
const tokens = new Set(
|
|
2642
|
+
rel.split(/\s+/).filter(Boolean).map((t) => t.toLowerCase())
|
|
2643
|
+
);
|
|
2644
|
+
tokens.add("noopener");
|
|
2645
|
+
tokens.add("noreferrer");
|
|
2646
|
+
el.setAttribute("rel", Array.from(tokens).join(" "));
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
function sanitizeHtml(html) {
|
|
2650
|
+
if (!html || typeof html !== "string") return "";
|
|
2651
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
2652
|
+
for (const child of Array.from(doc.body.children)) {
|
|
2653
|
+
sanitizeElement(child);
|
|
2654
|
+
}
|
|
2655
|
+
return doc.body.innerHTML;
|
|
2656
|
+
}
|
|
2657
|
+
function postProcessOutput(html) {
|
|
2658
|
+
if (!html) return html;
|
|
2659
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
2660
|
+
for (const inner of Array.from(doc.querySelectorAll("b > strong"))) {
|
|
2661
|
+
const outer = inner.parentElement;
|
|
2662
|
+
_mergeAttributes(inner, outer);
|
|
2663
|
+
while (inner.firstChild) outer.insertBefore(inner.firstChild, inner);
|
|
2664
|
+
outer.removeChild(inner);
|
|
2665
|
+
}
|
|
2666
|
+
for (const inner of Array.from(doc.querySelectorAll("i > em"))) {
|
|
2667
|
+
const outer = inner.parentElement;
|
|
2668
|
+
_mergeAttributes(inner, outer);
|
|
2669
|
+
while (inner.firstChild) outer.insertBefore(inner.firstChild, inner);
|
|
2670
|
+
outer.removeChild(inner);
|
|
2671
|
+
}
|
|
2672
|
+
for (const p of Array.from(doc.querySelectorAll("p"))) {
|
|
2673
|
+
const style = p.style;
|
|
2674
|
+
const hasMargin = !!(style.margin || style.marginTop || style.marginRight || style.marginBottom || style.marginLeft);
|
|
2675
|
+
if (!hasMargin) style.margin = "0";
|
|
2676
|
+
if (!style.lineHeight) style.lineHeight = "1.25";
|
|
2677
|
+
}
|
|
2678
|
+
return doc.body.innerHTML;
|
|
2679
|
+
}
|
|
2680
|
+
function _mergeAttributes(src, dst) {
|
|
2681
|
+
for (const { name, value } of Array.from(src.attributes)) {
|
|
2682
|
+
if (name === "style") {
|
|
2683
|
+
const prev = dst.getAttribute("style") || "";
|
|
2684
|
+
dst.setAttribute("style", prev ? `${prev}; ${value}` : value);
|
|
2685
|
+
} else if (name === "class") {
|
|
2686
|
+
const prev = dst.getAttribute("class") || "";
|
|
2687
|
+
dst.setAttribute("class", prev ? `${prev} ${value}` : value);
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
var BLOCK_TAGS = /* @__PURE__ */ new Set([
|
|
2692
|
+
"p",
|
|
2693
|
+
"h1",
|
|
2694
|
+
"h2",
|
|
2695
|
+
"h3",
|
|
2696
|
+
"h4",
|
|
2697
|
+
"h5",
|
|
2698
|
+
"h6",
|
|
2699
|
+
"div",
|
|
2700
|
+
"ul",
|
|
2701
|
+
"ol",
|
|
2702
|
+
"li",
|
|
2703
|
+
"table",
|
|
2704
|
+
"blockquote",
|
|
2705
|
+
"pre",
|
|
2706
|
+
"hr"
|
|
2707
|
+
]);
|
|
2708
|
+
function normalizeToBlockHtml(html) {
|
|
2709
|
+
if (!html) return "";
|
|
2710
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
2711
|
+
const body = doc.body;
|
|
2712
|
+
const childNodes = Array.from(body.childNodes);
|
|
2713
|
+
const needsWrap = childNodes.some((node) => {
|
|
2714
|
+
if (node.nodeType === Node.TEXT_NODE) return !!node.nodeValue?.trim();
|
|
2715
|
+
if (node.nodeType === Node.ELEMENT_NODE)
|
|
2716
|
+
return !BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
2717
|
+
return false;
|
|
2718
|
+
});
|
|
2719
|
+
if (!needsWrap) return html;
|
|
2720
|
+
while (body.firstChild) body.removeChild(body.firstChild);
|
|
2721
|
+
let pendingP = null;
|
|
2722
|
+
for (const node of childNodes) {
|
|
2723
|
+
const isBlock = node.nodeType === Node.ELEMENT_NODE && BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
2724
|
+
const isWhitespace = node.nodeType === Node.TEXT_NODE && !node.nodeValue?.trim();
|
|
2725
|
+
if (isBlock) {
|
|
2726
|
+
if (pendingP) {
|
|
2727
|
+
body.appendChild(pendingP);
|
|
2728
|
+
pendingP = null;
|
|
2729
|
+
}
|
|
2730
|
+
body.appendChild(node);
|
|
2731
|
+
} else if (!isWhitespace) {
|
|
2732
|
+
if (!pendingP) pendingP = doc.createElement("p");
|
|
2733
|
+
pendingP.appendChild(node);
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
if (pendingP) body.appendChild(pendingP);
|
|
2737
|
+
return body.innerHTML;
|
|
2738
|
+
}
|
|
2469
2739
|
var CustomOnChangePlugin = ({ value, onChange }) => {
|
|
2470
2740
|
const [editor] = useLexicalComposerContext();
|
|
2471
2741
|
const initializedRef = useRef(false);
|
|
@@ -2486,7 +2756,7 @@ var CustomOnChangePlugin = ({ value, onChange }) => {
|
|
|
2486
2756
|
}, [editor, value]);
|
|
2487
2757
|
const handleChange = useCallback((editorState) => {
|
|
2488
2758
|
editorState.read(() => {
|
|
2489
|
-
onChangeRef.current($generateHtmlFromNodes(editor));
|
|
2759
|
+
onChangeRef.current(postProcessOutput($generateHtmlFromNodes(editor)));
|
|
2490
2760
|
});
|
|
2491
2761
|
}, [editor]);
|
|
2492
2762
|
return /* @__PURE__ */ jsx(
|
|
@@ -3468,309 +3738,111 @@ function $onDragStart2(event) {
|
|
|
3468
3738
|
const dataTransfer = event.dataTransfer;
|
|
3469
3739
|
if (!dataTransfer) return false;
|
|
3470
3740
|
dataTransfer.setData("text/plain", "_");
|
|
3471
|
-
dataTransfer.setDragImage(img2, 0, 0);
|
|
3472
|
-
dataTransfer.setData(
|
|
3473
|
-
"application/x-lexical-drag",
|
|
3474
|
-
JSON.stringify({
|
|
3475
|
-
data: {
|
|
3476
|
-
altText: node.__altText,
|
|
3477
|
-
caption: node.__caption,
|
|
3478
|
-
height: node.__height,
|
|
3479
|
-
key: node.getKey(),
|
|
3480
|
-
showCaption: node.__showCaption,
|
|
3481
|
-
src: node.__src,
|
|
3482
|
-
width: node.__width
|
|
3483
|
-
},
|
|
3484
|
-
type: "image"
|
|
3485
|
-
})
|
|
3486
|
-
);
|
|
3487
|
-
return true;
|
|
3488
|
-
}
|
|
3489
|
-
var $onDragover2 = (event) => {
|
|
3490
|
-
const node = $getImageNodeInSelection2();
|
|
3491
|
-
if (!node) return false;
|
|
3492
|
-
if (!canDropImage2(event)) {
|
|
3493
|
-
event.preventDefault();
|
|
3494
|
-
}
|
|
3495
|
-
return true;
|
|
3496
|
-
};
|
|
3497
|
-
var $onDrop2 = (event, editor) => {
|
|
3498
|
-
const node = $getImageNodeInSelection2();
|
|
3499
|
-
if (!node) return false;
|
|
3500
|
-
const data = getDragImageData2(event);
|
|
3501
|
-
if (!data) return false;
|
|
3502
|
-
event.preventDefault();
|
|
3503
|
-
if (canDropImage2(event)) {
|
|
3504
|
-
const range = getDragSelection2(event);
|
|
3505
|
-
node.remove();
|
|
3506
|
-
const rangeSelection = $createRangeSelection();
|
|
3507
|
-
if (range !== null && range !== void 0) {
|
|
3508
|
-
rangeSelection.applyDOMRange(range);
|
|
3509
|
-
}
|
|
3510
|
-
$setSelection(rangeSelection);
|
|
3511
|
-
editor.dispatchCommand(INSERT_INLINE_IMAGE_COMMAND, data);
|
|
3512
|
-
}
|
|
3513
|
-
return true;
|
|
3514
|
-
};
|
|
3515
|
-
var $getImageNodeInSelection2 = () => {
|
|
3516
|
-
const selection = $getSelection();
|
|
3517
|
-
if (!$isNodeSelection(selection)) return null;
|
|
3518
|
-
const nodes = selection.getNodes();
|
|
3519
|
-
const node = nodes[0];
|
|
3520
|
-
return $isInlineImageNode(node) ? node : null;
|
|
3521
|
-
};
|
|
3522
|
-
var getDragImageData2 = (event) => {
|
|
3523
|
-
const dragData = event.dataTransfer?.getData("application/x-lexical-drag");
|
|
3524
|
-
if (!dragData) return null;
|
|
3525
|
-
const { type, data } = JSON.parse(dragData);
|
|
3526
|
-
if (type !== "image") return null;
|
|
3527
|
-
return data;
|
|
3528
|
-
};
|
|
3529
|
-
var canDropImage2 = (event) => {
|
|
3530
|
-
const target = event.target;
|
|
3531
|
-
return !!(isHTMLElement(target) && !target.closest("code, span.editor-image") && isHTMLElement(target.parentElement) && target.parentElement.closest("div.ContentEditable__root"));
|
|
3532
|
-
};
|
|
3533
|
-
var getDragSelection2 = (event) => {
|
|
3534
|
-
let range;
|
|
3535
|
-
const domSelection = getDOMSelectionFromTarget(event.target);
|
|
3536
|
-
if (document.caretRangeFromPoint) {
|
|
3537
|
-
range = document.caretRangeFromPoint(event.clientX, event.clientY);
|
|
3538
|
-
} else if (event.rangeParent && domSelection !== null) {
|
|
3539
|
-
domSelection.collapse(event.rangeParent, event.rangeOffset || 0);
|
|
3540
|
-
range = domSelection.getRangeAt(0);
|
|
3541
|
-
} else {
|
|
3542
|
-
throw Error("Cannot get the selection when dragging");
|
|
3543
|
-
}
|
|
3544
|
-
return range;
|
|
3545
|
-
};
|
|
3546
|
-
var INSERT_PAGE_BREAK = createCommand();
|
|
3547
|
-
function PageBreakPlugin() {
|
|
3548
|
-
const [editor] = useLexicalComposerContext();
|
|
3549
|
-
useEffect(() => {
|
|
3550
|
-
if (!editor.hasNodes([PageBreakNode])) {
|
|
3551
|
-
throw new Error(
|
|
3552
|
-
"PageBreakPlugin: PageBreakNode is not registered on editor"
|
|
3553
|
-
);
|
|
3554
|
-
}
|
|
3555
|
-
return mergeRegister(
|
|
3556
|
-
editor.registerCommand(
|
|
3557
|
-
INSERT_PAGE_BREAK,
|
|
3558
|
-
() => {
|
|
3559
|
-
const selection = $getSelection();
|
|
3560
|
-
if (!$isRangeSelection(selection)) {
|
|
3561
|
-
return false;
|
|
3562
|
-
}
|
|
3563
|
-
const focusNode = selection.focus.getNode();
|
|
3564
|
-
if (focusNode !== null) {
|
|
3565
|
-
const pgBreak = $createPageBreakNode();
|
|
3566
|
-
$insertNodeToNearestRoot(pgBreak);
|
|
3567
|
-
}
|
|
3568
|
-
return true;
|
|
3569
|
-
},
|
|
3570
|
-
COMMAND_PRIORITY_EDITOR
|
|
3571
|
-
)
|
|
3572
|
-
);
|
|
3573
|
-
}, [editor]);
|
|
3574
|
-
return null;
|
|
3575
|
-
}
|
|
3576
|
-
|
|
3577
|
-
// src/Utils/Sanitize.ts
|
|
3578
|
-
var DROP_ENTIRELY = /* @__PURE__ */ new Set([
|
|
3579
|
-
"script",
|
|
3580
|
-
"noscript",
|
|
3581
|
-
"style",
|
|
3582
|
-
"object",
|
|
3583
|
-
"embed",
|
|
3584
|
-
"form",
|
|
3585
|
-
"input",
|
|
3586
|
-
"button",
|
|
3587
|
-
"select",
|
|
3588
|
-
"textarea",
|
|
3589
|
-
"meta",
|
|
3590
|
-
"link",
|
|
3591
|
-
"base"
|
|
3592
|
-
]);
|
|
3593
|
-
var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
3594
|
-
// Block
|
|
3595
|
-
"p",
|
|
3596
|
-
"h1",
|
|
3597
|
-
"h2",
|
|
3598
|
-
"h3",
|
|
3599
|
-
"h4",
|
|
3600
|
-
"h5",
|
|
3601
|
-
"h6",
|
|
3602
|
-
"ul",
|
|
3603
|
-
"ol",
|
|
3604
|
-
"li",
|
|
3605
|
-
"blockquote",
|
|
3606
|
-
"pre",
|
|
3607
|
-
"div",
|
|
3608
|
-
"table",
|
|
3609
|
-
"thead",
|
|
3610
|
-
"tbody",
|
|
3611
|
-
"tfoot",
|
|
3612
|
-
"tr",
|
|
3613
|
-
"td",
|
|
3614
|
-
"th",
|
|
3615
|
-
// Inline
|
|
3616
|
-
"span",
|
|
3617
|
-
"a",
|
|
3618
|
-
"strong",
|
|
3619
|
-
"b",
|
|
3620
|
-
"em",
|
|
3621
|
-
"i",
|
|
3622
|
-
"u",
|
|
3623
|
-
"s",
|
|
3624
|
-
"del",
|
|
3625
|
-
"strike",
|
|
3626
|
-
"sub",
|
|
3627
|
-
"sup",
|
|
3628
|
-
"mark",
|
|
3629
|
-
"code",
|
|
3630
|
-
"br",
|
|
3631
|
-
"hr",
|
|
3632
|
-
// Media / embeds
|
|
3633
|
-
"img",
|
|
3634
|
-
"iframe"
|
|
3635
|
-
]);
|
|
3636
|
-
var ALLOWED_ATTRS = /* @__PURE__ */ new Set([
|
|
3637
|
-
// Presentation
|
|
3638
|
-
"class",
|
|
3639
|
-
"style",
|
|
3640
|
-
"dir",
|
|
3641
|
-
"lang",
|
|
3642
|
-
// Anchors
|
|
3643
|
-
"href",
|
|
3644
|
-
"target",
|
|
3645
|
-
"rel",
|
|
3646
|
-
// Images
|
|
3647
|
-
"src",
|
|
3648
|
-
"alt",
|
|
3649
|
-
"width",
|
|
3650
|
-
"height",
|
|
3651
|
-
// Tables
|
|
3652
|
-
"colspan",
|
|
3653
|
-
"rowspan",
|
|
3654
|
-
// Lists — <ol type="a"> and <ol start="2">
|
|
3655
|
-
"start",
|
|
3656
|
-
"type",
|
|
3657
|
-
// Lexical-internal data markers
|
|
3658
|
-
"data-lex-block",
|
|
3659
|
-
"data-kind",
|
|
3660
|
-
"data-lexical-decorator",
|
|
3661
|
-
// Misc
|
|
3662
|
-
"title",
|
|
3663
|
-
"allowfullscreen"
|
|
3664
|
-
]);
|
|
3665
|
-
var DANGEROUS_URL = /^\s*(javascript|data\s*:|vbscript)/i;
|
|
3666
|
-
function sanitizeElement(el) {
|
|
3667
|
-
for (const child of Array.from(el.children)) {
|
|
3668
|
-
sanitizeElement(child);
|
|
3669
|
-
}
|
|
3670
|
-
const tag = el.tagName.toLowerCase();
|
|
3671
|
-
if (DROP_ENTIRELY.has(tag)) {
|
|
3672
|
-
el.parentNode?.removeChild(el);
|
|
3673
|
-
return;
|
|
3674
|
-
}
|
|
3675
|
-
if (tag === "iframe") {
|
|
3676
|
-
const src = el.getAttribute("src") ?? "";
|
|
3677
|
-
const isYouTube = /^\s*https:\/\/(www\.)?(youtube\.com|youtube-nocookie\.com)\/embed\/[^?&/]+/i.test(src);
|
|
3678
|
-
if (!isYouTube) {
|
|
3679
|
-
el.parentNode?.removeChild(el);
|
|
3680
|
-
return;
|
|
3681
|
-
}
|
|
3682
|
-
}
|
|
3683
|
-
if (!ALLOWED_TAGS.has(tag)) {
|
|
3684
|
-
while (el.firstChild) {
|
|
3685
|
-
el.parentNode?.insertBefore(el.firstChild, el);
|
|
3686
|
-
}
|
|
3687
|
-
el.parentNode?.removeChild(el);
|
|
3688
|
-
return;
|
|
3689
|
-
}
|
|
3690
|
-
for (const { name, value } of Array.from(el.attributes)) {
|
|
3691
|
-
const lname = name.toLowerCase();
|
|
3692
|
-
if (!ALLOWED_ATTRS.has(lname)) {
|
|
3693
|
-
el.removeAttribute(name);
|
|
3694
|
-
continue;
|
|
3695
|
-
}
|
|
3696
|
-
if (lname === "href" || lname === "src") {
|
|
3697
|
-
if (DANGEROUS_URL.test(value)) {
|
|
3698
|
-
el.removeAttribute(name);
|
|
3699
|
-
}
|
|
3700
|
-
}
|
|
3701
|
-
if (lname === "style") {
|
|
3702
|
-
const safe = value.replace(/expression\s*\(/gi, "(").replace(/url\s*\(\s*['"]?\s*javascript:/gi, "url(");
|
|
3703
|
-
el.setAttribute("style", safe);
|
|
3704
|
-
}
|
|
3705
|
-
}
|
|
3706
|
-
if (tag === "a" && (el.getAttribute("target") || "").toLowerCase() === "_blank") {
|
|
3707
|
-
const rel = (el.getAttribute("rel") || "").trim();
|
|
3708
|
-
const tokens = new Set(
|
|
3709
|
-
rel.split(/\s+/).filter(Boolean).map((t) => t.toLowerCase())
|
|
3710
|
-
);
|
|
3711
|
-
tokens.add("noopener");
|
|
3712
|
-
tokens.add("noreferrer");
|
|
3713
|
-
el.setAttribute("rel", Array.from(tokens).join(" "));
|
|
3714
|
-
}
|
|
3715
|
-
}
|
|
3716
|
-
function sanitizeHtml(html) {
|
|
3717
|
-
if (!html || typeof html !== "string") return "";
|
|
3718
|
-
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
3719
|
-
for (const child of Array.from(doc.body.children)) {
|
|
3720
|
-
sanitizeElement(child);
|
|
3721
|
-
}
|
|
3722
|
-
return doc.body.innerHTML;
|
|
3723
|
-
}
|
|
3724
|
-
var BLOCK_TAGS = /* @__PURE__ */ new Set([
|
|
3725
|
-
"p",
|
|
3726
|
-
"h1",
|
|
3727
|
-
"h2",
|
|
3728
|
-
"h3",
|
|
3729
|
-
"h4",
|
|
3730
|
-
"h5",
|
|
3731
|
-
"h6",
|
|
3732
|
-
"div",
|
|
3733
|
-
"ul",
|
|
3734
|
-
"ol",
|
|
3735
|
-
"li",
|
|
3736
|
-
"table",
|
|
3737
|
-
"blockquote",
|
|
3738
|
-
"pre",
|
|
3739
|
-
"hr"
|
|
3740
|
-
]);
|
|
3741
|
-
function normalizeToBlockHtml(html) {
|
|
3742
|
-
if (!html) return "";
|
|
3743
|
-
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
3744
|
-
const body = doc.body;
|
|
3745
|
-
const childNodes = Array.from(body.childNodes);
|
|
3746
|
-
const needsWrap = childNodes.some((node) => {
|
|
3747
|
-
if (node.nodeType === Node.TEXT_NODE) return !!node.nodeValue?.trim();
|
|
3748
|
-
if (node.nodeType === Node.ELEMENT_NODE)
|
|
3749
|
-
return !BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
3750
|
-
return false;
|
|
3751
|
-
});
|
|
3752
|
-
if (!needsWrap) return html;
|
|
3753
|
-
while (body.firstChild) body.removeChild(body.firstChild);
|
|
3754
|
-
let pendingP = null;
|
|
3755
|
-
for (const node of childNodes) {
|
|
3756
|
-
const isBlock = node.nodeType === Node.ELEMENT_NODE && BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
3757
|
-
const isWhitespace = node.nodeType === Node.TEXT_NODE && !node.nodeValue?.trim();
|
|
3758
|
-
if (isBlock) {
|
|
3759
|
-
if (pendingP) {
|
|
3760
|
-
body.appendChild(pendingP);
|
|
3761
|
-
pendingP = null;
|
|
3762
|
-
}
|
|
3763
|
-
body.appendChild(node);
|
|
3764
|
-
} else if (!isWhitespace) {
|
|
3765
|
-
if (!pendingP) pendingP = doc.createElement("p");
|
|
3766
|
-
pendingP.appendChild(node);
|
|
3741
|
+
dataTransfer.setDragImage(img2, 0, 0);
|
|
3742
|
+
dataTransfer.setData(
|
|
3743
|
+
"application/x-lexical-drag",
|
|
3744
|
+
JSON.stringify({
|
|
3745
|
+
data: {
|
|
3746
|
+
altText: node.__altText,
|
|
3747
|
+
caption: node.__caption,
|
|
3748
|
+
height: node.__height,
|
|
3749
|
+
key: node.getKey(),
|
|
3750
|
+
showCaption: node.__showCaption,
|
|
3751
|
+
src: node.__src,
|
|
3752
|
+
width: node.__width
|
|
3753
|
+
},
|
|
3754
|
+
type: "image"
|
|
3755
|
+
})
|
|
3756
|
+
);
|
|
3757
|
+
return true;
|
|
3758
|
+
}
|
|
3759
|
+
var $onDragover2 = (event) => {
|
|
3760
|
+
const node = $getImageNodeInSelection2();
|
|
3761
|
+
if (!node) return false;
|
|
3762
|
+
if (!canDropImage2(event)) {
|
|
3763
|
+
event.preventDefault();
|
|
3764
|
+
}
|
|
3765
|
+
return true;
|
|
3766
|
+
};
|
|
3767
|
+
var $onDrop2 = (event, editor) => {
|
|
3768
|
+
const node = $getImageNodeInSelection2();
|
|
3769
|
+
if (!node) return false;
|
|
3770
|
+
const data = getDragImageData2(event);
|
|
3771
|
+
if (!data) return false;
|
|
3772
|
+
event.preventDefault();
|
|
3773
|
+
if (canDropImage2(event)) {
|
|
3774
|
+
const range = getDragSelection2(event);
|
|
3775
|
+
node.remove();
|
|
3776
|
+
const rangeSelection = $createRangeSelection();
|
|
3777
|
+
if (range !== null && range !== void 0) {
|
|
3778
|
+
rangeSelection.applyDOMRange(range);
|
|
3767
3779
|
}
|
|
3780
|
+
$setSelection(rangeSelection);
|
|
3781
|
+
editor.dispatchCommand(INSERT_INLINE_IMAGE_COMMAND, data);
|
|
3768
3782
|
}
|
|
3769
|
-
|
|
3770
|
-
|
|
3783
|
+
return true;
|
|
3784
|
+
};
|
|
3785
|
+
var $getImageNodeInSelection2 = () => {
|
|
3786
|
+
const selection = $getSelection();
|
|
3787
|
+
if (!$isNodeSelection(selection)) return null;
|
|
3788
|
+
const nodes = selection.getNodes();
|
|
3789
|
+
const node = nodes[0];
|
|
3790
|
+
return $isInlineImageNode(node) ? node : null;
|
|
3791
|
+
};
|
|
3792
|
+
var getDragImageData2 = (event) => {
|
|
3793
|
+
const dragData = event.dataTransfer?.getData("application/x-lexical-drag");
|
|
3794
|
+
if (!dragData) return null;
|
|
3795
|
+
const { type, data } = JSON.parse(dragData);
|
|
3796
|
+
if (type !== "image") return null;
|
|
3797
|
+
return data;
|
|
3798
|
+
};
|
|
3799
|
+
var canDropImage2 = (event) => {
|
|
3800
|
+
const target = event.target;
|
|
3801
|
+
return !!(isHTMLElement(target) && !target.closest("code, span.editor-image") && isHTMLElement(target.parentElement) && target.parentElement.closest("div.ContentEditable__root"));
|
|
3802
|
+
};
|
|
3803
|
+
var getDragSelection2 = (event) => {
|
|
3804
|
+
let range;
|
|
3805
|
+
const domSelection = getDOMSelectionFromTarget(event.target);
|
|
3806
|
+
if (document.caretRangeFromPoint) {
|
|
3807
|
+
range = document.caretRangeFromPoint(event.clientX, event.clientY);
|
|
3808
|
+
} else if (event.rangeParent && domSelection !== null) {
|
|
3809
|
+
domSelection.collapse(event.rangeParent, event.rangeOffset || 0);
|
|
3810
|
+
range = domSelection.getRangeAt(0);
|
|
3811
|
+
} else {
|
|
3812
|
+
throw Error("Cannot get the selection when dragging");
|
|
3813
|
+
}
|
|
3814
|
+
return range;
|
|
3815
|
+
};
|
|
3816
|
+
var INSERT_PAGE_BREAK = createCommand();
|
|
3817
|
+
function PageBreakPlugin() {
|
|
3818
|
+
const [editor] = useLexicalComposerContext();
|
|
3819
|
+
useEffect(() => {
|
|
3820
|
+
if (!editor.hasNodes([PageBreakNode])) {
|
|
3821
|
+
throw new Error(
|
|
3822
|
+
"PageBreakPlugin: PageBreakNode is not registered on editor"
|
|
3823
|
+
);
|
|
3824
|
+
}
|
|
3825
|
+
return mergeRegister(
|
|
3826
|
+
editor.registerCommand(
|
|
3827
|
+
INSERT_PAGE_BREAK,
|
|
3828
|
+
() => {
|
|
3829
|
+
const selection = $getSelection();
|
|
3830
|
+
if (!$isRangeSelection(selection)) {
|
|
3831
|
+
return false;
|
|
3832
|
+
}
|
|
3833
|
+
const focusNode = selection.focus.getNode();
|
|
3834
|
+
if (focusNode !== null) {
|
|
3835
|
+
const pgBreak = $createPageBreakNode();
|
|
3836
|
+
$insertNodeToNearestRoot(pgBreak);
|
|
3837
|
+
}
|
|
3838
|
+
return true;
|
|
3839
|
+
},
|
|
3840
|
+
COMMAND_PRIORITY_EDITOR
|
|
3841
|
+
)
|
|
3842
|
+
);
|
|
3843
|
+
}, [editor]);
|
|
3844
|
+
return null;
|
|
3771
3845
|
}
|
|
3772
|
-
|
|
3773
|
-
// src/Utils/Helper.ts
|
|
3774
3846
|
function findBlockByKind(kind) {
|
|
3775
3847
|
const root = $getRoot();
|
|
3776
3848
|
for (const child of root.getChildren()) {
|
|
@@ -3842,7 +3914,7 @@ function RefApiPlugin({
|
|
|
3842
3914
|
editor.getEditorState().read(() => {
|
|
3843
3915
|
html = $generateHtmlFromNodes(editor, null);
|
|
3844
3916
|
});
|
|
3845
|
-
return html;
|
|
3917
|
+
return postProcessOutput(html);
|
|
3846
3918
|
},
|
|
3847
3919
|
clear: () => {
|
|
3848
3920
|
editor.update(() => {
|
|
@@ -4991,7 +5063,8 @@ function getToolbarGroupsByLevel(level) {
|
|
|
4991
5063
|
["FontFamily", "|"],
|
|
4992
5064
|
["FontSize", "|"],
|
|
4993
5065
|
["Decorators", "|"],
|
|
4994
|
-
["Align"]
|
|
5066
|
+
["Align", "|"],
|
|
5067
|
+
["PageSetup"]
|
|
4995
5068
|
];
|
|
4996
5069
|
case "pro" /* Pro */:
|
|
4997
5070
|
default:
|
|
@@ -5006,7 +5079,8 @@ function getToolbarGroupsByLevel(level) {
|
|
|
5006
5079
|
["FontFamily", "|"],
|
|
5007
5080
|
["FontSize", "|"],
|
|
5008
5081
|
["Decorators", "|"],
|
|
5009
|
-
["Align"]
|
|
5082
|
+
["Align", "|"],
|
|
5083
|
+
["PageSetup"]
|
|
5010
5084
|
];
|
|
5011
5085
|
}
|
|
5012
5086
|
}
|
|
@@ -5044,6 +5118,7 @@ var normalizeHex = (v) => {
|
|
|
5044
5118
|
if (hex.length === 4 || hex.length === 7) return hex.toLowerCase();
|
|
5045
5119
|
return "#000000";
|
|
5046
5120
|
};
|
|
5121
|
+
var isCompleteHex = (v) => /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test((v ?? "").trim());
|
|
5047
5122
|
var hexToRgb = (hex) => {
|
|
5048
5123
|
const h = normalizeHex(hex).replace("#", "");
|
|
5049
5124
|
if (h.length === 3) {
|
|
@@ -5091,40 +5166,6 @@ var hsvToRgb = (h, s, v) => {
|
|
|
5091
5166
|
b: Math.round((bb + m) * 255)
|
|
5092
5167
|
};
|
|
5093
5168
|
};
|
|
5094
|
-
function useDrag(onMove, onEnd, interactingRef) {
|
|
5095
|
-
const draggingRef = React9.useRef(false);
|
|
5096
|
-
const start = React9.useCallback(
|
|
5097
|
-
(e) => {
|
|
5098
|
-
draggingRef.current = true;
|
|
5099
|
-
if (interactingRef) interactingRef.current = true;
|
|
5100
|
-
onMove(e.clientX, e.clientY);
|
|
5101
|
-
const move = (ev) => {
|
|
5102
|
-
if (!draggingRef.current) return;
|
|
5103
|
-
onMove(ev.clientX, ev.clientY);
|
|
5104
|
-
};
|
|
5105
|
-
const up = () => {
|
|
5106
|
-
draggingRef.current = false;
|
|
5107
|
-
window.removeEventListener("mousemove", move);
|
|
5108
|
-
window.removeEventListener("mouseup", up);
|
|
5109
|
-
if (interactingRef) {
|
|
5110
|
-
const clearFlag = () => {
|
|
5111
|
-
interactingRef.current = false;
|
|
5112
|
-
};
|
|
5113
|
-
window.addEventListener("click", clearFlag, { once: true });
|
|
5114
|
-
setTimeout(() => {
|
|
5115
|
-
window.removeEventListener("click", clearFlag);
|
|
5116
|
-
interactingRef.current = false;
|
|
5117
|
-
}, 0);
|
|
5118
|
-
}
|
|
5119
|
-
onEnd?.();
|
|
5120
|
-
};
|
|
5121
|
-
window.addEventListener("mousemove", move);
|
|
5122
|
-
window.addEventListener("mouseup", up);
|
|
5123
|
-
},
|
|
5124
|
-
[onMove, onEnd, interactingRef]
|
|
5125
|
-
);
|
|
5126
|
-
return start;
|
|
5127
|
-
}
|
|
5128
5169
|
var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange }) => {
|
|
5129
5170
|
const [open, setOpen] = React9.useState(false);
|
|
5130
5171
|
const btnRef = React9.useRef(null);
|
|
@@ -5135,13 +5176,9 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5135
5176
|
},
|
|
5136
5177
|
[onOpenChange]
|
|
5137
5178
|
);
|
|
5138
|
-
const interactingRef = React9.useRef(false);
|
|
5139
5179
|
const handleDismiss = React9.useCallback(() => setOpenAndNotify(false), [setOpenAndNotify]);
|
|
5140
5180
|
const preventDismissOnEvent = React9.useCallback(
|
|
5141
|
-
(ev) =>
|
|
5142
|
-
if (interactingRef.current) return true;
|
|
5143
|
-
return ev.type !== "click";
|
|
5144
|
-
},
|
|
5181
|
+
(ev) => ev.type !== "click",
|
|
5145
5182
|
[]
|
|
5146
5183
|
);
|
|
5147
5184
|
const [, forceReposition] = React9.useState(0);
|
|
@@ -5163,100 +5200,119 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5163
5200
|
window.removeEventListener("resize", reposition);
|
|
5164
5201
|
};
|
|
5165
5202
|
}, [open]);
|
|
5166
|
-
const
|
|
5203
|
+
const appliedHex = React9.useMemo(() => normalizeHex(value || "#000000"), [value]);
|
|
5204
|
+
const [hex, setHexState] = React9.useState(appliedHex);
|
|
5205
|
+
const [hexText, setHexText] = React9.useState(appliedHex);
|
|
5167
5206
|
const { r, g, b } = React9.useMemo(() => hexToRgb(hex), [hex]);
|
|
5168
5207
|
const hsv = React9.useMemo(() => rgbToHsv(r, g, b), [r, g, b]);
|
|
5169
5208
|
const [h, setH] = React9.useState(hsv.h);
|
|
5170
5209
|
const [s, setS] = React9.useState(hsv.s);
|
|
5171
5210
|
const [v, setV] = React9.useState(hsv.v);
|
|
5211
|
+
const commit = React9.useCallback(
|
|
5212
|
+
(nextHex) => {
|
|
5213
|
+
const rgb = hexToRgb(nextHex);
|
|
5214
|
+
const next = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
5215
|
+
setHexState(nextHex);
|
|
5216
|
+
setHexText(nextHex);
|
|
5217
|
+
setH(next.h);
|
|
5218
|
+
setS(next.s);
|
|
5219
|
+
setV(next.v);
|
|
5220
|
+
onChange(nextHex);
|
|
5221
|
+
},
|
|
5222
|
+
[onChange]
|
|
5223
|
+
);
|
|
5224
|
+
const commitFromHsv = React9.useCallback(
|
|
5225
|
+
(hh, ss, vv) => {
|
|
5226
|
+
const rgb = hsvToRgb(hh, ss, vv);
|
|
5227
|
+
const nextHex = rgbToHex(rgb.r, rgb.g, rgb.b);
|
|
5228
|
+
setHexState(nextHex);
|
|
5229
|
+
setHexText(nextHex);
|
|
5230
|
+
setH(hh);
|
|
5231
|
+
setS(ss);
|
|
5232
|
+
setV(vv);
|
|
5233
|
+
onChange(nextHex);
|
|
5234
|
+
},
|
|
5235
|
+
[onChange]
|
|
5236
|
+
);
|
|
5172
5237
|
const wasOpenRef = React9.useRef(open);
|
|
5173
|
-
console.log("[AO-ColorPicker]", title, "render with incoming value prop:", JSON.stringify(value));
|
|
5174
5238
|
React9.useEffect(() => {
|
|
5175
5239
|
const justOpened = open && !wasOpenRef.current;
|
|
5176
5240
|
wasOpenRef.current = open;
|
|
5177
|
-
console.log("[AO-ColorPicker]", title, "open-seed effect", {
|
|
5178
|
-
open,
|
|
5179
|
-
justOpened,
|
|
5180
|
-
incomingValue: value
|
|
5181
|
-
});
|
|
5182
5241
|
if (!justOpened) return;
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
normalized: n
|
|
5187
|
-
});
|
|
5188
|
-
setHex(n);
|
|
5189
|
-
const rgb = hexToRgb(n);
|
|
5242
|
+
setHexState(appliedHex);
|
|
5243
|
+
setHexText(appliedHex);
|
|
5244
|
+
const rgb = hexToRgb(appliedHex);
|
|
5190
5245
|
const next = rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
5191
5246
|
setH(next.h);
|
|
5192
5247
|
setS(next.s);
|
|
5193
5248
|
setV(next.v);
|
|
5194
|
-
}, [
|
|
5195
|
-
const
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5249
|
+
}, [appliedHex, open]);
|
|
5250
|
+
const svRef = React9.useRef(null);
|
|
5251
|
+
const svPointFromEvent = React9.useCallback((clientX, clientY) => {
|
|
5252
|
+
if (!svRef.current) return null;
|
|
5253
|
+
const rect = svRef.current.getBoundingClientRect();
|
|
5254
|
+
const x = clamp3(clientX - rect.left, 0, rect.width);
|
|
5255
|
+
const y = clamp3(clientY - rect.top, 0, rect.height);
|
|
5256
|
+
const ss = rect.width === 0 ? 0 : x / rect.width;
|
|
5257
|
+
const vv = rect.height === 0 ? 0 : 1 - y / rect.height;
|
|
5258
|
+
return { ss, vv };
|
|
5200
5259
|
}, []);
|
|
5201
|
-
const
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5260
|
+
const hRef = React9.useRef(h);
|
|
5261
|
+
hRef.current = h;
|
|
5262
|
+
const handleSVPointerDown = React9.useCallback(
|
|
5263
|
+
(e) => {
|
|
5264
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
5265
|
+
const pt = svPointFromEvent(e.clientX, e.clientY);
|
|
5266
|
+
if (pt) commitFromHsv(hRef.current, pt.ss, pt.vv);
|
|
5207
5267
|
},
|
|
5208
|
-
[
|
|
5268
|
+
[svPointFromEvent, commitFromHsv]
|
|
5209
5269
|
);
|
|
5210
|
-
const
|
|
5270
|
+
const handleSVPointerMove = React9.useCallback(
|
|
5271
|
+
(e) => {
|
|
5272
|
+
if (e.buttons !== 1) return;
|
|
5273
|
+
const pt = svPointFromEvent(e.clientX, e.clientY);
|
|
5274
|
+
if (pt) commitFromHsv(hRef.current, pt.ss, pt.vv);
|
|
5275
|
+
},
|
|
5276
|
+
[svPointFromEvent, commitFromHsv]
|
|
5277
|
+
);
|
|
5278
|
+
const hueRef = React9.useRef(null);
|
|
5211
5279
|
const sRef = React9.useRef(s);
|
|
5280
|
+
sRef.current = s;
|
|
5212
5281
|
const vRef = React9.useRef(v);
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
if (!svRef.current) return;
|
|
5226
|
-
const rect = svRef.current.getBoundingClientRect();
|
|
5227
|
-
const x = clamp3(clientX - rect.left, 0, rect.width);
|
|
5228
|
-
const y = clamp3(clientY - rect.top, 0, rect.height);
|
|
5229
|
-
const ss = rect.width === 0 ? 0 : x / rect.width;
|
|
5230
|
-
const vv = rect.height === 0 ? 0 : 1 - y / rect.height;
|
|
5231
|
-
setS(ss);
|
|
5232
|
-
setV(vv);
|
|
5233
|
-
sRef.current = ss;
|
|
5234
|
-
vRef.current = vv;
|
|
5235
|
-
updateHexFromHsv(hRef.current, ss, vv);
|
|
5282
|
+
vRef.current = v;
|
|
5283
|
+
const huePointFromEvent = React9.useCallback((clientX) => {
|
|
5284
|
+
if (!hueRef.current) return null;
|
|
5285
|
+
const rect = hueRef.current.getBoundingClientRect();
|
|
5286
|
+
const x = clamp3(clientX - rect.left, 0, rect.width);
|
|
5287
|
+
return rect.width === 0 ? 0 : x / rect.width * 360;
|
|
5288
|
+
}, []);
|
|
5289
|
+
const handleHuePointerDown = React9.useCallback(
|
|
5290
|
+
(e) => {
|
|
5291
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
5292
|
+
const hh = huePointFromEvent(e.clientX);
|
|
5293
|
+
if (hh != null) commitFromHsv(hh, sRef.current, vRef.current);
|
|
5236
5294
|
},
|
|
5237
|
-
[
|
|
5295
|
+
[huePointFromEvent, commitFromHsv]
|
|
5238
5296
|
);
|
|
5239
|
-
const
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
const onHueMove = React9.useCallback(
|
|
5245
|
-
(clientX) => {
|
|
5246
|
-
if (!hueRef.current) return;
|
|
5247
|
-
const rect = hueRef.current.getBoundingClientRect();
|
|
5248
|
-
const x = clamp3(clientX - rect.left, 0, rect.width);
|
|
5249
|
-
const hh = rect.width === 0 ? 0 : x / rect.width * 360;
|
|
5250
|
-
setH(hh);
|
|
5251
|
-
hRef.current = hh;
|
|
5252
|
-
updateHexFromHsv(hh, sRef.current, vRef.current);
|
|
5297
|
+
const handleHuePointerMove = React9.useCallback(
|
|
5298
|
+
(e) => {
|
|
5299
|
+
if (e.buttons !== 1) return;
|
|
5300
|
+
const hh = huePointFromEvent(e.clientX);
|
|
5301
|
+
if (hh != null) commitFromHsv(hh, sRef.current, vRef.current);
|
|
5253
5302
|
},
|
|
5254
|
-
[
|
|
5303
|
+
[huePointFromEvent, commitFromHsv]
|
|
5255
5304
|
);
|
|
5256
|
-
const
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5305
|
+
const handleHexChange = React9.useCallback(
|
|
5306
|
+
(_, val) => {
|
|
5307
|
+
const next = val ?? "";
|
|
5308
|
+
setHexText(next);
|
|
5309
|
+
if (isCompleteHex(next.trim())) commit(normalizeHex(next));
|
|
5310
|
+
},
|
|
5311
|
+
[commit]
|
|
5312
|
+
);
|
|
5313
|
+
const handleHexBlur = React9.useCallback(() => {
|
|
5314
|
+
commit(normalizeHex(hexText));
|
|
5315
|
+
}, [hexText, commit]);
|
|
5260
5316
|
const svThumb = React9.useMemo(() => ({ left: `${s * 100}%`, top: `${(1 - v) * 100}%` }), [s, v]);
|
|
5261
5317
|
const hueThumb = React9.useMemo(() => ({ left: `${h / 360 * 100}%` }), [h]);
|
|
5262
5318
|
const hueColor = React9.useMemo(() => {
|
|
@@ -5281,10 +5337,6 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5281
5337
|
},
|
|
5282
5338
|
onClick: () => {
|
|
5283
5339
|
if (disabled) return;
|
|
5284
|
-
console.log("[AO-ColorPicker]", title, "trigger button clicked", {
|
|
5285
|
-
wasOpen: open,
|
|
5286
|
-
activeElementBeforeToggle: document.activeElement?.tagName
|
|
5287
|
-
});
|
|
5288
5340
|
setOpenAndNotify(!open);
|
|
5289
5341
|
}
|
|
5290
5342
|
}
|
|
@@ -5299,7 +5351,7 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5299
5351
|
transform: "translateX(-50%)",
|
|
5300
5352
|
width: 14,
|
|
5301
5353
|
height: 3,
|
|
5302
|
-
background:
|
|
5354
|
+
background: appliedHex,
|
|
5303
5355
|
borderRadius: 1,
|
|
5304
5356
|
border: "0.5px solid rgba(0,0,0,0.18)",
|
|
5305
5357
|
pointerEvents: "none"
|
|
@@ -5315,72 +5367,192 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5315
5367
|
directionalHint: 4,
|
|
5316
5368
|
className: "aoColorCallout",
|
|
5317
5369
|
preventDismissOnEvent,
|
|
5318
|
-
children: /* @__PURE__ */ jsxs(Stack, { tokens: { childrenGap:
|
|
5319
|
-
/* @__PURE__ */ jsxs("div", {
|
|
5320
|
-
/* @__PURE__ */ jsx("div", {
|
|
5321
|
-
/* @__PURE__ */ jsx("div", { className: "aoLexTitle", children: title })
|
|
5322
|
-
] }),
|
|
5323
|
-
/* @__PURE__ */ jsxs("div", { className: "aoLexRow", children: [
|
|
5324
|
-
/* @__PURE__ */ jsx("div", { className: "aoLexLabel", children: "Hex" }),
|
|
5370
|
+
children: /* @__PURE__ */ jsxs(Stack, { tokens: { childrenGap: 14 }, styles: { root: { padding: "14px 16px 16px", width: 288 } }, children: [
|
|
5371
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
5372
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 13, fontWeight: 600, color: "#242424", letterSpacing: 0.1 }, children: title }),
|
|
5325
5373
|
/* @__PURE__ */ jsx(
|
|
5326
|
-
|
|
5374
|
+
"button",
|
|
5327
5375
|
{
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5376
|
+
type: "button",
|
|
5377
|
+
"aria-label": "Close",
|
|
5378
|
+
onClick: () => setOpenAndNotify(false),
|
|
5379
|
+
style: {
|
|
5380
|
+
display: "flex",
|
|
5381
|
+
alignItems: "center",
|
|
5382
|
+
justifyContent: "center",
|
|
5383
|
+
width: 24,
|
|
5384
|
+
height: 24,
|
|
5385
|
+
padding: 0,
|
|
5386
|
+
border: "none",
|
|
5387
|
+
borderRadius: 4,
|
|
5388
|
+
background: "transparent",
|
|
5389
|
+
color: "#616161",
|
|
5390
|
+
cursor: "pointer"
|
|
5391
|
+
},
|
|
5392
|
+
onMouseEnter: (e) => e.currentTarget.style.background = "#f0f0f0",
|
|
5393
|
+
onMouseLeave: (e) => e.currentTarget.style.background = "transparent",
|
|
5394
|
+
children: /* @__PURE__ */ jsx(Dismiss16Regular, {})
|
|
5341
5395
|
}
|
|
5342
5396
|
)
|
|
5343
5397
|
] }),
|
|
5344
|
-
/* @__PURE__ */
|
|
5345
|
-
"
|
|
5398
|
+
/* @__PURE__ */ jsxs(
|
|
5399
|
+
"div",
|
|
5346
5400
|
{
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5401
|
+
ref: svRef,
|
|
5402
|
+
onPointerDown: handleSVPointerDown,
|
|
5403
|
+
onPointerMove: handleSVPointerMove,
|
|
5404
|
+
style: {
|
|
5405
|
+
position: "relative",
|
|
5406
|
+
width: "100%",
|
|
5407
|
+
height: 150,
|
|
5408
|
+
borderRadius: 8,
|
|
5409
|
+
overflow: "hidden",
|
|
5410
|
+
cursor: "crosshair",
|
|
5411
|
+
touchAction: "none",
|
|
5412
|
+
boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.08)"
|
|
5359
5413
|
},
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5414
|
+
children: [
|
|
5415
|
+
/* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: hueColor } }),
|
|
5416
|
+
/* @__PURE__ */ jsx(
|
|
5417
|
+
"div",
|
|
5418
|
+
{
|
|
5419
|
+
style: {
|
|
5420
|
+
position: "absolute",
|
|
5421
|
+
inset: 0,
|
|
5422
|
+
background: "linear-gradient(to right, #fff, rgba(255,255,255,0))"
|
|
5423
|
+
}
|
|
5424
|
+
}
|
|
5425
|
+
),
|
|
5426
|
+
/* @__PURE__ */ jsx(
|
|
5427
|
+
"div",
|
|
5428
|
+
{
|
|
5429
|
+
style: {
|
|
5430
|
+
position: "absolute",
|
|
5431
|
+
inset: 0,
|
|
5432
|
+
background: "linear-gradient(to top, #000, rgba(0,0,0,0))"
|
|
5433
|
+
}
|
|
5434
|
+
}
|
|
5435
|
+
),
|
|
5436
|
+
/* @__PURE__ */ jsx(
|
|
5437
|
+
"div",
|
|
5438
|
+
{
|
|
5439
|
+
style: {
|
|
5440
|
+
position: "absolute",
|
|
5441
|
+
width: 16,
|
|
5442
|
+
height: 16,
|
|
5443
|
+
borderRadius: "50%",
|
|
5444
|
+
border: "2px solid #fff",
|
|
5445
|
+
boxShadow: "0 0 0 1px rgba(0,0,0,0.35), 0 1px 3px rgba(0,0,0,0.4)",
|
|
5446
|
+
transform: "translate(-50%, -50%)",
|
|
5447
|
+
pointerEvents: "none",
|
|
5448
|
+
...svThumb
|
|
5449
|
+
}
|
|
5450
|
+
}
|
|
5451
|
+
)
|
|
5452
|
+
]
|
|
5453
|
+
}
|
|
5454
|
+
),
|
|
5455
|
+
/* @__PURE__ */ jsx(
|
|
5456
|
+
"div",
|
|
5457
|
+
{
|
|
5458
|
+
ref: hueRef,
|
|
5459
|
+
onPointerDown: handleHuePointerDown,
|
|
5460
|
+
onPointerMove: handleHuePointerMove,
|
|
5461
|
+
style: {
|
|
5462
|
+
position: "relative",
|
|
5463
|
+
width: "100%",
|
|
5464
|
+
height: 12,
|
|
5465
|
+
borderRadius: 999,
|
|
5466
|
+
cursor: "pointer",
|
|
5467
|
+
touchAction: "none",
|
|
5468
|
+
background: "linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)",
|
|
5469
|
+
boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.08)"
|
|
5470
|
+
},
|
|
5471
|
+
children: /* @__PURE__ */ jsx(
|
|
5472
|
+
"div",
|
|
5473
|
+
{
|
|
5474
|
+
style: {
|
|
5475
|
+
position: "absolute",
|
|
5476
|
+
top: "50%",
|
|
5477
|
+
width: 16,
|
|
5478
|
+
height: 16,
|
|
5479
|
+
borderRadius: "50%",
|
|
5480
|
+
background: hueColor,
|
|
5481
|
+
border: "2px solid #fff",
|
|
5482
|
+
boxShadow: "0 0 0 1px rgba(0,0,0,0.35), 0 1px 3px rgba(0,0,0,0.4)",
|
|
5483
|
+
transform: "translate(-50%, -50%)",
|
|
5484
|
+
pointerEvents: "none",
|
|
5485
|
+
...hueThumb
|
|
5486
|
+
}
|
|
5487
|
+
}
|
|
5488
|
+
)
|
|
5489
|
+
}
|
|
5490
|
+
),
|
|
5491
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
5373
5492
|
/* @__PURE__ */ jsx(
|
|
5374
|
-
|
|
5493
|
+
"div",
|
|
5375
5494
|
{
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5495
|
+
style: {
|
|
5496
|
+
width: 32,
|
|
5497
|
+
height: 32,
|
|
5498
|
+
borderRadius: 6,
|
|
5499
|
+
flexShrink: 0,
|
|
5500
|
+
background: hex,
|
|
5501
|
+
boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.12)"
|
|
5380
5502
|
}
|
|
5381
5503
|
}
|
|
5382
5504
|
),
|
|
5383
|
-
/* @__PURE__ */ jsx(
|
|
5505
|
+
/* @__PURE__ */ jsx(
|
|
5506
|
+
TextField,
|
|
5507
|
+
{
|
|
5508
|
+
value: hexText,
|
|
5509
|
+
onChange: handleHexChange,
|
|
5510
|
+
onBlur: handleHexBlur,
|
|
5511
|
+
onKeyDown: (e) => {
|
|
5512
|
+
if (e.key === "Enter") commit(normalizeHex(hexText));
|
|
5513
|
+
},
|
|
5514
|
+
styles: { root: { flex: 1 }, fieldGroup: { borderRadius: 6 } }
|
|
5515
|
+
}
|
|
5516
|
+
)
|
|
5517
|
+
] }),
|
|
5518
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
5519
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 11, fontWeight: 600, color: "#8a8a8a", marginBottom: 6, letterSpacing: 0.3 }, children: "STANDARD COLORS" }),
|
|
5520
|
+
/* @__PURE__ */ jsx(
|
|
5521
|
+
"div",
|
|
5522
|
+
{
|
|
5523
|
+
style: {
|
|
5524
|
+
display: "grid",
|
|
5525
|
+
gridTemplateColumns: "repeat(9, 1fr)",
|
|
5526
|
+
gap: 6
|
|
5527
|
+
},
|
|
5528
|
+
children: PRESET.map((c) => {
|
|
5529
|
+
const isSelected = c.toLowerCase() === hex.toLowerCase();
|
|
5530
|
+
return /* @__PURE__ */ jsx(
|
|
5531
|
+
"button",
|
|
5532
|
+
{
|
|
5533
|
+
type: "button",
|
|
5534
|
+
onClick: () => commit(c),
|
|
5535
|
+
title: c,
|
|
5536
|
+
"aria-label": c,
|
|
5537
|
+
style: {
|
|
5538
|
+
width: 22,
|
|
5539
|
+
height: 22,
|
|
5540
|
+
padding: 0,
|
|
5541
|
+
borderRadius: 5,
|
|
5542
|
+
background: c,
|
|
5543
|
+
cursor: "pointer",
|
|
5544
|
+
boxShadow: isSelected ? "0 0 0 2px #fff, 0 0 0 3px #4a86e8" : "inset 0 0 0 1px rgba(0,0,0,0.15)",
|
|
5545
|
+
border: "none",
|
|
5546
|
+
transition: "transform 80ms ease"
|
|
5547
|
+
},
|
|
5548
|
+
onMouseEnter: (e) => e.currentTarget.style.transform = "scale(1.12)",
|
|
5549
|
+
onMouseLeave: (e) => e.currentTarget.style.transform = "scale(1)"
|
|
5550
|
+
},
|
|
5551
|
+
c
|
|
5552
|
+
);
|
|
5553
|
+
})
|
|
5554
|
+
}
|
|
5555
|
+
)
|
|
5384
5556
|
] })
|
|
5385
5557
|
] })
|
|
5386
5558
|
}
|
|
@@ -5393,20 +5565,10 @@ var ColorPickerPlugin = ({ disabled }) => {
|
|
|
5393
5565
|
const lastRangeSelectionRef = React9__default.useRef(null);
|
|
5394
5566
|
const updateToolbar = () => {
|
|
5395
5567
|
const selection = $getSelection();
|
|
5396
|
-
|
|
5397
|
-
console.log("[AO-ColorPicker] updateToolbar", {
|
|
5398
|
-
isRangeSelection: isRange,
|
|
5399
|
-
isCollapsed: isRange ? selection.isCollapsed() : null
|
|
5400
|
-
});
|
|
5401
|
-
if (isRange) {
|
|
5568
|
+
if ($isRangeSelection(selection)) {
|
|
5402
5569
|
lastRangeSelectionRef.current = selection.clone();
|
|
5403
5570
|
const c = $getSelectionStyleValueForProperty(selection, "color", "#000000");
|
|
5404
|
-
const bg = $getSelectionStyleValueForProperty(
|
|
5405
|
-
selection,
|
|
5406
|
-
"background-color",
|
|
5407
|
-
"#ffffff"
|
|
5408
|
-
);
|
|
5409
|
-
console.log("[AO-ColorPicker] updateToolbar readback", { color: c, bgColor: bg });
|
|
5571
|
+
const bg = $getSelectionStyleValueForProperty(selection, "background-color", "#ffffff");
|
|
5410
5572
|
setColors({ color: c, bgColor: bg });
|
|
5411
5573
|
}
|
|
5412
5574
|
};
|
|
@@ -5436,15 +5598,6 @@ var ColorPickerPlugin = ({ disabled }) => {
|
|
|
5436
5598
|
};
|
|
5437
5599
|
const applyStyle = (args) => {
|
|
5438
5600
|
if (disabled) return;
|
|
5439
|
-
console.log("[AO-ColorPicker] applyStyle called", {
|
|
5440
|
-
property: args.property,
|
|
5441
|
-
color: args.color,
|
|
5442
|
-
hasSavedSelection: !!lastRangeSelectionRef.current,
|
|
5443
|
-
savedSelectionIsCollapsed: lastRangeSelectionRef.current?.isCollapsed() ?? null,
|
|
5444
|
-
wasEditorActiveAtOpen: wasEditorActiveRef.current,
|
|
5445
|
-
activeElementTag: document.activeElement?.tagName,
|
|
5446
|
-
activeElementClass: document.activeElement?.className
|
|
5447
|
-
});
|
|
5448
5601
|
editor.update(
|
|
5449
5602
|
() => {
|
|
5450
5603
|
const saved = lastRangeSelectionRef.current;
|
|
@@ -5452,39 +5605,17 @@ var ColorPickerPlugin = ({ disabled }) => {
|
|
|
5452
5605
|
$setSelection(saved.clone());
|
|
5453
5606
|
}
|
|
5454
5607
|
const selection = $getSelection();
|
|
5455
|
-
|
|
5456
|
-
console.log("[AO-ColorPicker] applyStyle inside editor.update", {
|
|
5457
|
-
hadSavedSelection: !!saved,
|
|
5458
|
-
selectionAfterRestoreIsRange: isRange,
|
|
5459
|
-
selectionAfterRestoreIsCollapsed: isRange ? selection.isCollapsed() : null
|
|
5460
|
-
});
|
|
5461
|
-
if (isRange) {
|
|
5608
|
+
if ($isRangeSelection(selection)) {
|
|
5462
5609
|
$patchStyleText(selection, { [args.property]: args.color });
|
|
5463
|
-
const verify = $getSelectionStyleValueForProperty(
|
|
5464
|
-
selection,
|
|
5465
|
-
args.property,
|
|
5466
|
-
"<none>"
|
|
5467
|
-
);
|
|
5468
|
-
console.log("[AO-ColorPicker] applyStyle after patchStyleText, readback in same update", {
|
|
5469
|
-
property: args.property,
|
|
5470
|
-
appliedColor: args.color,
|
|
5471
|
-
readBack: verify
|
|
5472
|
-
});
|
|
5473
|
-
} else {
|
|
5474
|
-
console.warn(
|
|
5475
|
-
"[AO-ColorPicker] applyStyle: no range selection available \u2014 style was NOT applied",
|
|
5476
|
-
{ property: args.property, color: args.color }
|
|
5477
|
-
);
|
|
5478
5610
|
}
|
|
5479
5611
|
},
|
|
5480
5612
|
// Without this tag, Lexical's reconciler force-focuses the editor root
|
|
5481
5613
|
// whenever this update's selection diff finds the root isn't already
|
|
5482
|
-
// focused
|
|
5483
|
-
//
|
|
5484
|
-
//
|
|
5485
|
-
//
|
|
5486
|
-
//
|
|
5487
|
-
// popover until the drag's tracked color desynced from the cursor.
|
|
5614
|
+
// focused — which it isn't while the color picker's Callout holds
|
|
5615
|
+
// focus. The picker now only calls applyStyle once, on Apply, so this
|
|
5616
|
+
// is no longer fighting for focus on every drag pixel, but there's no
|
|
5617
|
+
// reason to force a focus change here at all — handleOpenChange above
|
|
5618
|
+
// already does that deliberately, once, on close.
|
|
5488
5619
|
{ tag: SKIP_SELECTION_FOCUS_TAG }
|
|
5489
5620
|
);
|
|
5490
5621
|
};
|
|
@@ -5853,6 +5984,60 @@ var InsertLinkPlugin = ({ disabled }) => {
|
|
|
5853
5984
|
}
|
|
5854
5985
|
);
|
|
5855
5986
|
};
|
|
5987
|
+
function PageSetupPlugin({ disabled, value, onChange }) {
|
|
5988
|
+
const sizeLabel = value.size === "pageless" ? "Pageless" : PAGE_SIZE_OPTIONS.find((o) => o.key === value.size)?.label ?? "Pageless";
|
|
5989
|
+
const isPaged = value.size !== "pageless";
|
|
5990
|
+
return /* @__PURE__ */ jsxs(
|
|
5991
|
+
Menu,
|
|
5992
|
+
{
|
|
5993
|
+
checkedValues: {
|
|
5994
|
+
size: [value.size],
|
|
5995
|
+
orientation: [value.orientation],
|
|
5996
|
+
margin: [value.margin]
|
|
5997
|
+
},
|
|
5998
|
+
onCheckedValueChange: (_, data) => {
|
|
5999
|
+
const selected = data.checkedItems[0];
|
|
6000
|
+
if (!selected) return;
|
|
6001
|
+
if (data.name === "size") onChange({ ...value, size: selected });
|
|
6002
|
+
else if (data.name === "orientation")
|
|
6003
|
+
onChange({ ...value, orientation: selected });
|
|
6004
|
+
else if (data.name === "margin") onChange({ ...value, margin: selected });
|
|
6005
|
+
},
|
|
6006
|
+
children: [
|
|
6007
|
+
/* @__PURE__ */ jsx(MenuTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsx(
|
|
6008
|
+
Button,
|
|
6009
|
+
{
|
|
6010
|
+
appearance: "subtle",
|
|
6011
|
+
size: "small",
|
|
6012
|
+
disabled,
|
|
6013
|
+
icon: /* @__PURE__ */ jsx(DocumentRegular, {}),
|
|
6014
|
+
title: "Page setup",
|
|
6015
|
+
style: { minWidth: "auto" },
|
|
6016
|
+
children: sizeLabel
|
|
6017
|
+
}
|
|
6018
|
+
) }),
|
|
6019
|
+
/* @__PURE__ */ jsx(MenuPopover, { style: { minWidth: 220 }, children: /* @__PURE__ */ jsxs(MenuList, { children: [
|
|
6020
|
+
/* @__PURE__ */ jsxs(MenuGroup, { children: [
|
|
6021
|
+
/* @__PURE__ */ jsx(MenuGroupHeader, { children: "Page size" }),
|
|
6022
|
+
/* @__PURE__ */ jsx(MenuItemRadio, { name: "size", value: "pageless", children: "Pageless" }),
|
|
6023
|
+
PAGE_SIZE_OPTIONS.map((opt) => /* @__PURE__ */ jsx(MenuItemRadio, { name: "size", value: opt.key, children: opt.label }, opt.key))
|
|
6024
|
+
] }),
|
|
6025
|
+
/* @__PURE__ */ jsx(MenuDivider, {}),
|
|
6026
|
+
/* @__PURE__ */ jsxs(MenuGroup, { children: [
|
|
6027
|
+
/* @__PURE__ */ jsx(MenuGroupHeader, { children: "Orientation" }),
|
|
6028
|
+
/* @__PURE__ */ jsx(MenuItemRadio, { name: "orientation", value: "portrait", disabled: !isPaged, children: "Portrait" }),
|
|
6029
|
+
/* @__PURE__ */ jsx(MenuItemRadio, { name: "orientation", value: "landscape", disabled: !isPaged, children: "Landscape" })
|
|
6030
|
+
] }),
|
|
6031
|
+
/* @__PURE__ */ jsx(MenuDivider, {}),
|
|
6032
|
+
/* @__PURE__ */ jsxs(MenuGroup, { children: [
|
|
6033
|
+
/* @__PURE__ */ jsx(MenuGroupHeader, { children: "Margins" }),
|
|
6034
|
+
MARGIN_OPTIONS.map((opt) => /* @__PURE__ */ jsx(MenuItemRadio, { name: "margin", value: opt.key, disabled: !isPaged, children: opt.label }, opt.key))
|
|
6035
|
+
] })
|
|
6036
|
+
] }) })
|
|
6037
|
+
]
|
|
6038
|
+
}
|
|
6039
|
+
);
|
|
6040
|
+
}
|
|
5856
6041
|
var TableItemPlugin = ({ disabled }) => {
|
|
5857
6042
|
const [editor] = useLexicalComposerContext();
|
|
5858
6043
|
const [columns, setColumns] = useState("");
|
|
@@ -6070,7 +6255,8 @@ var ALLOWED_TOKENS = {
|
|
|
6070
6255
|
FontSize: true,
|
|
6071
6256
|
Decorators: true,
|
|
6072
6257
|
CodeBlock: true,
|
|
6073
|
-
Align: true
|
|
6258
|
+
Align: true,
|
|
6259
|
+
PageSetup: true
|
|
6074
6260
|
};
|
|
6075
6261
|
function sanitizePluginGroups(groups) {
|
|
6076
6262
|
if (!groups || groups.length === 0) return [];
|
|
@@ -6609,6 +6795,16 @@ var ToolBarPlugins = (props) => {
|
|
|
6609
6795
|
key
|
|
6610
6796
|
);
|
|
6611
6797
|
}
|
|
6798
|
+
case "PageSetup":
|
|
6799
|
+
return /* @__PURE__ */ jsx(
|
|
6800
|
+
PageSetupPlugin,
|
|
6801
|
+
{
|
|
6802
|
+
disabled: !isEditable || props.readOnly,
|
|
6803
|
+
value: props.pageSetup,
|
|
6804
|
+
onChange: props.onPageSetupChange
|
|
6805
|
+
},
|
|
6806
|
+
key
|
|
6807
|
+
);
|
|
6612
6808
|
default:
|
|
6613
6809
|
return null;
|
|
6614
6810
|
}
|
|
@@ -6830,12 +7026,6 @@ function FocusEventsPlugin({
|
|
|
6830
7026
|
const next = e.relatedTarget;
|
|
6831
7027
|
const container = containerRef.current;
|
|
6832
7028
|
const stillInside = !!next && (container ? container.contains(next) : root.contains(next));
|
|
6833
|
-
console.log("[AO-ColorPicker] FocusEventsPlugin focusout", {
|
|
6834
|
-
relatedTargetTag: next ? next.tagName : null,
|
|
6835
|
-
relatedTargetClass: next ? next.className : null,
|
|
6836
|
-
stillInside,
|
|
6837
|
-
willClearSelection: !stillInside
|
|
6838
|
-
});
|
|
6839
7029
|
if (stillInside) return;
|
|
6840
7030
|
editor.update(() => {
|
|
6841
7031
|
$setSelection(null);
|
|
@@ -6966,6 +7156,8 @@ var ContentEditorComponent = forwardRef(
|
|
|
6966
7156
|
const [charCount, setCharCount] = useState(0);
|
|
6967
7157
|
const handleCharCount = useCallback((count) => setCharCount(count), []);
|
|
6968
7158
|
const [refErrors, setRefErrors] = useState([]);
|
|
7159
|
+
const [pageSetup, setPageSetup] = useState(DEFAULT_PAGE_SETUP);
|
|
7160
|
+
const pageCanvas = resolvePageCanvasMetrics(pageSetup);
|
|
6969
7161
|
const contentEditableDomRef = useRef(null);
|
|
6970
7162
|
const previousOverLimitRef = useRef(false);
|
|
6971
7163
|
const focusedRef = useRef(false);
|
|
@@ -7007,8 +7199,8 @@ var ContentEditorComponent = forwardRef(
|
|
|
7007
7199
|
color: "var(--colorNeutralForeground3, grey)",
|
|
7008
7200
|
position: "absolute",
|
|
7009
7201
|
top: props.level !== "none" /* None */ ? "17px" : "27px",
|
|
7010
|
-
left:
|
|
7011
|
-
right:
|
|
7202
|
+
left: pageCanvas.paddingPx,
|
|
7203
|
+
right: pageCanvas.paddingPx,
|
|
7012
7204
|
fontSize: "14px",
|
|
7013
7205
|
pointerEvents: "none",
|
|
7014
7206
|
userSelect: "none"
|
|
@@ -7019,8 +7211,6 @@ var ContentEditorComponent = forwardRef(
|
|
|
7019
7211
|
outline: "none",
|
|
7020
7212
|
overflow: "auto",
|
|
7021
7213
|
marginTop: "0px",
|
|
7022
|
-
paddingLeft: "20px",
|
|
7023
|
-
paddingRight: "20px",
|
|
7024
7214
|
position: "relative",
|
|
7025
7215
|
background: "var(--colorNeutralBackground1, #ffffff)",
|
|
7026
7216
|
justifyContent: "center",
|
|
@@ -7120,7 +7310,9 @@ var ContentEditorComponent = forwardRef(
|
|
|
7120
7310
|
ToolBarPlugins,
|
|
7121
7311
|
{
|
|
7122
7312
|
level: props.level ?? "basic" /* Basic */,
|
|
7123
|
-
readOnly: props.readOnly
|
|
7313
|
+
readOnly: props.readOnly,
|
|
7314
|
+
pageSetup,
|
|
7315
|
+
onPageSetupChange: setPageSetup
|
|
7124
7316
|
}
|
|
7125
7317
|
)
|
|
7126
7318
|
}
|
|
@@ -7134,7 +7326,8 @@ var ContentEditorComponent = forwardRef(
|
|
|
7134
7326
|
padding: "15px 0px",
|
|
7135
7327
|
overflowY: "scroll",
|
|
7136
7328
|
overflowX: "auto",
|
|
7137
|
-
minWidth: 0
|
|
7329
|
+
minWidth: 0,
|
|
7330
|
+
background: pageCanvas.widthPx !== void 0 ? "#eef0f2" : void 0
|
|
7138
7331
|
},
|
|
7139
7332
|
onClickCapture: handleReadOnlyClickCapture,
|
|
7140
7333
|
children: [
|
|
@@ -7153,7 +7346,15 @@ var ContentEditorComponent = forwardRef(
|
|
|
7153
7346
|
{
|
|
7154
7347
|
ref: contentEditableDomRef,
|
|
7155
7348
|
className: css(EditorStyles.contentEditor),
|
|
7156
|
-
style: {
|
|
7349
|
+
style: {
|
|
7350
|
+
paddingTop: props.level !== "none" /* None */ ? 0 : 10,
|
|
7351
|
+
paddingLeft: pageCanvas.paddingPx,
|
|
7352
|
+
paddingRight: pageCanvas.paddingPx,
|
|
7353
|
+
maxWidth: pageCanvas.widthPx,
|
|
7354
|
+
marginLeft: pageCanvas.widthPx !== void 0 ? "auto" : void 0,
|
|
7355
|
+
marginRight: pageCanvas.widthPx !== void 0 ? "auto" : void 0,
|
|
7356
|
+
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
|
|
7357
|
+
},
|
|
7157
7358
|
spellCheck: !resolvedSpellCheck,
|
|
7158
7359
|
autoCorrect: resolvedSpellCheck ? "off" : void 0,
|
|
7159
7360
|
autoCapitalize: resolvedSpellCheck ? "off" : void 0
|