@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.
@@ -850,7 +850,7 @@ function mergeFontSize(existingStyle, size) {
850
850
  }
851
851
  const DEFAULT_TOOLBAR_STYLE_SNAPSHOT = {
852
852
  blockType: "paragraph",
853
- fontFamily: "Calibri",
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, setSelected, clearOtherSelections] = useLexicalNodeSelection.useLexicalNodeSelection(nodeKey);
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 handleClick = React.useCallback((event) => {
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
- if (!event.shiftKey) {
2488
- clearOtherSelections();
2514
+ event.stopPropagation();
2515
+ if (!isSelected || event.shiftKey) {
2516
+ selectNode(event.shiftKey);
2489
2517
  }
2490
- setSelected(!isSelected);
2491
- }, [clearOtherSelections, isSelected, setSelected]);
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: (event) => event.preventDefault(),
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 = selection$1.getNodes().filter($isVariableNode);
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 standaloneVariables ?? []) {
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 "Calibri";
3284
+ return "Inter";
3185
3285
  }
3186
3286
  function normalizeAlignment(alignment) {
3187
3287
  if (alignment === "center" || alignment === "right" || alignment === "justify") {