@yurikilian/lex4 1.7.0 → 1.8.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/lex4-editor.cjs +160 -60
- package/dist/lex4-editor.cjs.map +1 -1
- package/dist/lex4-editor.js +161 -61
- package/dist/lex4-editor.js.map +1 -1
- package/dist/lexical/commands/block-commands.d.ts.map +1 -1
- package/dist/style.css +30 -26
- package/dist/variables/variable-formatting.d.ts +1 -0
- package/dist/variables/variable-formatting.d.ts.map +1 -1
- package/dist/variables/variable-node.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/lex4-editor.cjs
CHANGED
|
@@ -850,7 +850,7 @@ function mergeFontSize(existingStyle, size) {
|
|
|
850
850
|
}
|
|
851
851
|
const DEFAULT_TOOLBAR_STYLE_SNAPSHOT = {
|
|
852
852
|
blockType: "paragraph",
|
|
853
|
-
fontFamily: "
|
|
853
|
+
fontFamily: "Inter",
|
|
854
854
|
fontSize: DEFAULT_FONT_SIZE,
|
|
855
855
|
alignment: "left",
|
|
856
856
|
isBold: false,
|
|
@@ -2413,6 +2413,7 @@ class VariableNode extends lexical.DecoratorNode {
|
|
|
2413
2413
|
const span = document.createElement("span");
|
|
2414
2414
|
span.className = "lex4-variable";
|
|
2415
2415
|
span.setAttribute("data-variable-key", this.__variableKey);
|
|
2416
|
+
span.setAttribute("data-node-key", this.__key);
|
|
2416
2417
|
span.setAttribute("data-testid", `variable-${this.__variableKey}`);
|
|
2417
2418
|
span.contentEditable = "false";
|
|
2418
2419
|
return span;
|
|
@@ -2460,7 +2461,7 @@ function VariableChip({
|
|
|
2460
2461
|
}) {
|
|
2461
2462
|
const { getDefinition } = useVariables();
|
|
2462
2463
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
2463
|
-
const [isSelected
|
|
2464
|
+
const [isSelected] = useLexicalNodeSelection.useLexicalNodeSelection(nodeKey);
|
|
2464
2465
|
const def = getDefinition(variableKey);
|
|
2465
2466
|
const label = (def == null ? void 0 : def.label) ?? variableKey;
|
|
2466
2467
|
const group = def == null ? void 0 : def.group;
|
|
@@ -2482,13 +2483,48 @@ function VariableChip({
|
|
|
2482
2483
|
format & 8 ? "lex4-text-underline" : "",
|
|
2483
2484
|
format & 4 ? "lex4-text-strikethrough" : ""
|
|
2484
2485
|
].filter(Boolean).join(" ");
|
|
2485
|
-
const
|
|
2486
|
+
const clearDomSelection = React.useCallback(() => {
|
|
2487
|
+
var _a;
|
|
2488
|
+
if (typeof window === "undefined") {
|
|
2489
|
+
return;
|
|
2490
|
+
}
|
|
2491
|
+
(_a = window.getSelection()) == null ? void 0 : _a.removeAllRanges();
|
|
2492
|
+
}, []);
|
|
2493
|
+
const selectNode = React.useCallback((extendSelection) => {
|
|
2494
|
+
editor.focus();
|
|
2495
|
+
editor.update(() => {
|
|
2496
|
+
const nextSelection = lexical.$createNodeSelection();
|
|
2497
|
+
if (extendSelection) {
|
|
2498
|
+
const currentSelection = lexical.$getSelection();
|
|
2499
|
+
if (lexical.$isNodeSelection(currentSelection)) {
|
|
2500
|
+
for (const node of currentSelection.getNodes()) {
|
|
2501
|
+
if ($isVariableNode(node)) {
|
|
2502
|
+
nextSelection.add(node.getKey());
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
nextSelection.add(nodeKey);
|
|
2508
|
+
lexical.$setSelection(nextSelection);
|
|
2509
|
+
});
|
|
2510
|
+
clearDomSelection();
|
|
2511
|
+
}, [clearDomSelection, editor, nodeKey]);
|
|
2512
|
+
const handleMouseDown = React.useCallback((event) => {
|
|
2486
2513
|
event.preventDefault();
|
|
2487
|
-
|
|
2488
|
-
|
|
2514
|
+
event.stopPropagation();
|
|
2515
|
+
if (!isSelected || event.shiftKey) {
|
|
2516
|
+
selectNode(event.shiftKey);
|
|
2489
2517
|
}
|
|
2490
|
-
|
|
2491
|
-
|
|
2518
|
+
}, [isSelected, selectNode]);
|
|
2519
|
+
const handleClick = React.useCallback((event) => {
|
|
2520
|
+
event.preventDefault();
|
|
2521
|
+
event.stopPropagation();
|
|
2522
|
+
}, []);
|
|
2523
|
+
const handleMouseUp = React.useCallback((event) => {
|
|
2524
|
+
event.preventDefault();
|
|
2525
|
+
event.stopPropagation();
|
|
2526
|
+
clearDomSelection();
|
|
2527
|
+
}, [clearDomSelection]);
|
|
2492
2528
|
React.useEffect(() => {
|
|
2493
2529
|
const removeSelectedNodes = () => {
|
|
2494
2530
|
editor.update(() => {
|
|
@@ -2576,7 +2612,8 @@ function VariableChip({
|
|
|
2576
2612
|
"data-variable-group": group,
|
|
2577
2613
|
title: variableKey,
|
|
2578
2614
|
style,
|
|
2579
|
-
onMouseDown:
|
|
2615
|
+
onMouseDown: handleMouseDown,
|
|
2616
|
+
onMouseUp: handleMouseUp,
|
|
2580
2617
|
onClick: handleClick,
|
|
2581
2618
|
children: label
|
|
2582
2619
|
}
|
|
@@ -2588,6 +2625,83 @@ function $createVariableNode(variableKey, format = 0, style = "") {
|
|
|
2588
2625
|
function $isVariableNode(node) {
|
|
2589
2626
|
return node instanceof VariableNode;
|
|
2590
2627
|
}
|
|
2628
|
+
const FORMAT_MASKS$1 = {
|
|
2629
|
+
bold: 1,
|
|
2630
|
+
italic: 2,
|
|
2631
|
+
strikethrough: 4,
|
|
2632
|
+
underline: 8
|
|
2633
|
+
};
|
|
2634
|
+
function dedupeVariableNodes(nodes) {
|
|
2635
|
+
return Array.from(new Map(nodes.map((node) => [node.getKey(), node])).values());
|
|
2636
|
+
}
|
|
2637
|
+
function getSelectedVariableNodesFromSelection(selection2) {
|
|
2638
|
+
if (!selection2 || typeof selection2 !== "object" || !("getNodes" in selection2) || typeof selection2.getNodes !== "function") {
|
|
2639
|
+
return [];
|
|
2640
|
+
}
|
|
2641
|
+
return dedupeVariableNodes(selection2.getNodes().filter($isVariableNode));
|
|
2642
|
+
}
|
|
2643
|
+
function getVisuallySelectedVariableNodes(editor) {
|
|
2644
|
+
const rootElement = editor.getRootElement();
|
|
2645
|
+
if (!rootElement) {
|
|
2646
|
+
return [];
|
|
2647
|
+
}
|
|
2648
|
+
const nodes = [];
|
|
2649
|
+
rootElement.querySelectorAll(".lex4-variable-chip-selected").forEach((chip) => {
|
|
2650
|
+
const variableElement = chip.closest("[data-node-key]");
|
|
2651
|
+
const nodeKey = variableElement == null ? void 0 : variableElement.dataset.nodeKey;
|
|
2652
|
+
if (!nodeKey) {
|
|
2653
|
+
return;
|
|
2654
|
+
}
|
|
2655
|
+
const node = lexical.$getNodeByKey(nodeKey);
|
|
2656
|
+
if ($isVariableNode(node)) {
|
|
2657
|
+
nodes.push(node);
|
|
2658
|
+
}
|
|
2659
|
+
});
|
|
2660
|
+
return dedupeVariableNodes(nodes);
|
|
2661
|
+
}
|
|
2662
|
+
function withSelectedVariableNodes(editor, updater) {
|
|
2663
|
+
let updated = false;
|
|
2664
|
+
editor.update(() => {
|
|
2665
|
+
const nodes = [
|
|
2666
|
+
...getSelectedVariableNodesFromSelection(lexical.$getSelection()),
|
|
2667
|
+
...getVisuallySelectedVariableNodes(editor)
|
|
2668
|
+
];
|
|
2669
|
+
const uniqueNodes = dedupeVariableNodes(nodes);
|
|
2670
|
+
if (uniqueNodes.length === 0) {
|
|
2671
|
+
return;
|
|
2672
|
+
}
|
|
2673
|
+
updater(uniqueNodes);
|
|
2674
|
+
updated = true;
|
|
2675
|
+
});
|
|
2676
|
+
return updated;
|
|
2677
|
+
}
|
|
2678
|
+
function toggleSelectedVariableFormat(editor, format) {
|
|
2679
|
+
const mask = FORMAT_MASKS$1[format];
|
|
2680
|
+
if (!mask) {
|
|
2681
|
+
return false;
|
|
2682
|
+
}
|
|
2683
|
+
return withSelectedVariableNodes(editor, (nodes) => {
|
|
2684
|
+
const shouldEnable = nodes.some((node) => (node.getFormat() & mask) === 0);
|
|
2685
|
+
for (const node of nodes) {
|
|
2686
|
+
const nextFormat = shouldEnable ? node.getFormat() | mask : node.getFormat() & ~mask;
|
|
2687
|
+
node.setFormat(nextFormat);
|
|
2688
|
+
}
|
|
2689
|
+
});
|
|
2690
|
+
}
|
|
2691
|
+
function applyFontFamilyToSelectedVariables(editor, fontFamily) {
|
|
2692
|
+
return withSelectedVariableNodes(editor, (nodes) => {
|
|
2693
|
+
for (const node of nodes) {
|
|
2694
|
+
node.setStyle(mergeFontFamilyStyle(node.getStyle(), fontFamily));
|
|
2695
|
+
}
|
|
2696
|
+
});
|
|
2697
|
+
}
|
|
2698
|
+
function applyFontSizeToSelectedVariables(editor, size) {
|
|
2699
|
+
return withSelectedVariableNodes(editor, (nodes) => {
|
|
2700
|
+
for (const node of nodes) {
|
|
2701
|
+
node.setStyle(mergeFontSizeStyle(node.getStyle(), size));
|
|
2702
|
+
}
|
|
2703
|
+
});
|
|
2704
|
+
}
|
|
2591
2705
|
function getElementBlockType$1(element) {
|
|
2592
2706
|
if (richText.$isHeadingNode(element)) {
|
|
2593
2707
|
return element.getTag();
|
|
@@ -2653,15 +2767,38 @@ function getStandaloneVariableChildren(topLevelElement) {
|
|
|
2653
2767
|
}
|
|
2654
2768
|
return meaningfulChildren;
|
|
2655
2769
|
}
|
|
2770
|
+
function getSelectedVariableNodesFromRangeSelection(editor, selection2) {
|
|
2771
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2772
|
+
const variables = [];
|
|
2773
|
+
for (const node of [
|
|
2774
|
+
selection2.anchor.getNode(),
|
|
2775
|
+
selection2.focus.getNode(),
|
|
2776
|
+
...selection2.getNodes(),
|
|
2777
|
+
...getVisuallySelectedVariableNodes(editor)
|
|
2778
|
+
]) {
|
|
2779
|
+
if (!$isVariableNode(node) || seen.has(node.getKey())) {
|
|
2780
|
+
continue;
|
|
2781
|
+
}
|
|
2782
|
+
seen.add(node.getKey());
|
|
2783
|
+
variables.push(node);
|
|
2784
|
+
}
|
|
2785
|
+
return variables;
|
|
2786
|
+
}
|
|
2656
2787
|
function setBlockType(editor, blockType) {
|
|
2657
2788
|
editor.update(() => {
|
|
2789
|
+
const visuallySelectedVariables = getVisuallySelectedVariableNodes(editor);
|
|
2658
2790
|
const currentSelection = lexical.$getSelection();
|
|
2659
2791
|
const selection$1 = lexical.$isNodeSelection(currentSelection) ? currentSelection : lexical.$createRangeSelectionFromDom(window.getSelection(), editor) ?? currentSelection;
|
|
2660
2792
|
if (lexical.$isRangeSelection(selection$1)) {
|
|
2661
2793
|
lexical.$setSelection(selection$1);
|
|
2662
2794
|
}
|
|
2663
2795
|
if (lexical.$isNodeSelection(selection$1)) {
|
|
2664
|
-
const variables =
|
|
2796
|
+
const variables = Array.from(new Map(
|
|
2797
|
+
[
|
|
2798
|
+
...selection$1.getNodes().filter($isVariableNode),
|
|
2799
|
+
...visuallySelectedVariables
|
|
2800
|
+
].map((variable) => [variable.getKey(), variable])
|
|
2801
|
+
).values());
|
|
2665
2802
|
if (variables.length === 0) {
|
|
2666
2803
|
return;
|
|
2667
2804
|
}
|
|
@@ -2693,69 +2830,32 @@ function setBlockType(editor, blockType) {
|
|
|
2693
2830
|
return;
|
|
2694
2831
|
}
|
|
2695
2832
|
if (!lexical.$isRangeSelection(selection$1)) {
|
|
2833
|
+
if (visuallySelectedVariables.length === 0) {
|
|
2834
|
+
return;
|
|
2835
|
+
}
|
|
2836
|
+
for (const variable of visuallySelectedVariables) {
|
|
2837
|
+
variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
|
|
2838
|
+
}
|
|
2696
2839
|
return;
|
|
2697
2840
|
}
|
|
2698
2841
|
const anchorTopLevel = selection$1.anchor.getNode().getTopLevelElementOrThrow();
|
|
2699
2842
|
const standaloneVariables = lexical.$isElementNode(anchorTopLevel) ? getStandaloneVariableChildren(anchorTopLevel) : null;
|
|
2843
|
+
const selectedVariables = getSelectedVariableNodesFromRangeSelection(editor, selection$1);
|
|
2700
2844
|
if (isPartialSingleBlockSelection(selection$1)) {
|
|
2701
2845
|
selection.$patchStyleText(selection$1, createInlineBlockTypeStylePatch(blockType));
|
|
2846
|
+
for (const variable of selectedVariables) {
|
|
2847
|
+
variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
|
|
2848
|
+
}
|
|
2702
2849
|
return;
|
|
2703
2850
|
}
|
|
2704
|
-
for (const variable of
|
|
2851
|
+
for (const variable of new Map(
|
|
2852
|
+
[...standaloneVariables ?? [], ...selectedVariables].map((variable2) => [variable2.getKey(), variable2])
|
|
2853
|
+
).values()) {
|
|
2705
2854
|
variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
|
|
2706
2855
|
}
|
|
2707
2856
|
applySemanticBlockType(selection$1, blockType);
|
|
2708
2857
|
});
|
|
2709
2858
|
}
|
|
2710
|
-
const FORMAT_MASKS$1 = {
|
|
2711
|
-
bold: 1,
|
|
2712
|
-
italic: 2,
|
|
2713
|
-
strikethrough: 4,
|
|
2714
|
-
underline: 8
|
|
2715
|
-
};
|
|
2716
|
-
function withSelectedVariableNodes(editor, updater) {
|
|
2717
|
-
let updated = false;
|
|
2718
|
-
editor.update(() => {
|
|
2719
|
-
const selection2 = lexical.$getSelection();
|
|
2720
|
-
if (!lexical.$isNodeSelection(selection2)) {
|
|
2721
|
-
return;
|
|
2722
|
-
}
|
|
2723
|
-
const nodes = selection2.getNodes().filter($isVariableNode);
|
|
2724
|
-
if (nodes.length === 0) {
|
|
2725
|
-
return;
|
|
2726
|
-
}
|
|
2727
|
-
updater(nodes);
|
|
2728
|
-
updated = true;
|
|
2729
|
-
});
|
|
2730
|
-
return updated;
|
|
2731
|
-
}
|
|
2732
|
-
function toggleSelectedVariableFormat(editor, format) {
|
|
2733
|
-
const mask = FORMAT_MASKS$1[format];
|
|
2734
|
-
if (!mask) {
|
|
2735
|
-
return false;
|
|
2736
|
-
}
|
|
2737
|
-
return withSelectedVariableNodes(editor, (nodes) => {
|
|
2738
|
-
const shouldEnable = nodes.some((node) => (node.getFormat() & mask) === 0);
|
|
2739
|
-
for (const node of nodes) {
|
|
2740
|
-
const nextFormat = shouldEnable ? node.getFormat() | mask : node.getFormat() & ~mask;
|
|
2741
|
-
node.setFormat(nextFormat);
|
|
2742
|
-
}
|
|
2743
|
-
});
|
|
2744
|
-
}
|
|
2745
|
-
function applyFontFamilyToSelectedVariables(editor, fontFamily) {
|
|
2746
|
-
return withSelectedVariableNodes(editor, (nodes) => {
|
|
2747
|
-
for (const node of nodes) {
|
|
2748
|
-
node.setStyle(mergeFontFamilyStyle(node.getStyle(), fontFamily));
|
|
2749
|
-
}
|
|
2750
|
-
});
|
|
2751
|
-
}
|
|
2752
|
-
function applyFontSizeToSelectedVariables(editor, size) {
|
|
2753
|
-
return withSelectedVariableNodes(editor, (nodes) => {
|
|
2754
|
-
for (const node of nodes) {
|
|
2755
|
-
node.setStyle(mergeFontSizeStyle(node.getStyle(), size));
|
|
2756
|
-
}
|
|
2757
|
-
});
|
|
2758
|
-
}
|
|
2759
2859
|
const BLOCK_TYPE_OPTIONS = [
|
|
2760
2860
|
{ value: "paragraph", shortLabel: "P" },
|
|
2761
2861
|
{ value: "h1", shortLabel: "H1" },
|
|
@@ -3181,7 +3281,7 @@ function normalizeFontFamily(fontFamily) {
|
|
|
3181
3281
|
if (fontFamily && SUPPORTED_FONTS.includes(fontFamily)) {
|
|
3182
3282
|
return fontFamily;
|
|
3183
3283
|
}
|
|
3184
|
-
return "
|
|
3284
|
+
return "Inter";
|
|
3185
3285
|
}
|
|
3186
3286
|
function normalizeAlignment(alignment) {
|
|
3187
3287
|
if (alignment === "center" || alignment === "right" || alignment === "justify") {
|