@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.
@@ -3,7 +3,7 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
5
5
  import React, { createContext, useContext, useMemo, useRef, useReducer, useState, useCallback, useEffect, forwardRef, createElement, useImperativeHandle } from "react";
6
- import { $getSelection, $isRangeSelection, $isTextNode, $getRoot, $createRangeSelectionFromDom, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, OUTDENT_CONTENT_COMMAND, INDENT_CONTENT_COMMAND, $applyNodeReplacement, DecoratorNode, KEY_BACKSPACE_COMMAND, COMMAND_PRIORITY_LOW, KEY_DELETE_COMMAND, KEY_DOWN_COMMAND, $isNodeSelection, $getNodeByKey, $setSelection, $createNodeSelection, $isElementNode, $createParagraphNode, $selectAll, SELECTION_CHANGE_COMMAND, KEY_TAB_COMMAND, $isParagraphNode, FOCUS_COMMAND, $splitNode, $getNearestNodeFromDOMNode, CONTROLLED_TEXT_INSERTION_COMMAND, PASTE_COMMAND, KEY_ENTER_COMMAND, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_CRITICAL, $insertNodes, $createLineBreakNode, $createTextNode, createCommand, COMMAND_PRIORITY_EDITOR } from "lexical";
6
+ import { $getSelection, $isRangeSelection, $isTextNode, $getRoot, $createRangeSelectionFromDom, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, OUTDENT_CONTENT_COMMAND, INDENT_CONTENT_COMMAND, $applyNodeReplacement, DecoratorNode, $createNodeSelection, $isNodeSelection, $setSelection, KEY_BACKSPACE_COMMAND, COMMAND_PRIORITY_LOW, KEY_DELETE_COMMAND, KEY_DOWN_COMMAND, $getNodeByKey, $isElementNode, $createParagraphNode, $selectAll, SELECTION_CHANGE_COMMAND, KEY_TAB_COMMAND, $isParagraphNode, FOCUS_COMMAND, $splitNode, $getNearestNodeFromDOMNode, CONTROLLED_TEXT_INSERTION_COMMAND, PASTE_COMMAND, KEY_ENTER_COMMAND, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_CRITICAL, $insertNodes, $createLineBreakNode, $createTextNode, createCommand, COMMAND_PRIORITY_EDITOR } from "lexical";
7
7
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
8
8
  import { INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, ListNode, ListItemNode, $isListNode, $createListItemNode, $createListNode } from "@lexical/list";
9
9
  import { $patchStyleText, $setBlocksType } from "@lexical/selection";
@@ -848,7 +848,7 @@ function mergeFontSize(existingStyle, size) {
848
848
  }
849
849
  const DEFAULT_TOOLBAR_STYLE_SNAPSHOT = {
850
850
  blockType: "paragraph",
851
- fontFamily: "Calibri",
851
+ fontFamily: "Inter",
852
852
  fontSize: DEFAULT_FONT_SIZE,
853
853
  alignment: "left",
854
854
  isBold: false,
@@ -2411,6 +2411,7 @@ class VariableNode extends DecoratorNode {
2411
2411
  const span = document.createElement("span");
2412
2412
  span.className = "lex4-variable";
2413
2413
  span.setAttribute("data-variable-key", this.__variableKey);
2414
+ span.setAttribute("data-node-key", this.__key);
2414
2415
  span.setAttribute("data-testid", `variable-${this.__variableKey}`);
2415
2416
  span.contentEditable = "false";
2416
2417
  return span;
@@ -2458,7 +2459,7 @@ function VariableChip({
2458
2459
  }) {
2459
2460
  const { getDefinition } = useVariables();
2460
2461
  const [editor] = useLexicalComposerContext();
2461
- const [isSelected, setSelected, clearOtherSelections] = useLexicalNodeSelection(nodeKey);
2462
+ const [isSelected] = useLexicalNodeSelection(nodeKey);
2462
2463
  const def = getDefinition(variableKey);
2463
2464
  const label = (def == null ? void 0 : def.label) ?? variableKey;
2464
2465
  const group = def == null ? void 0 : def.group;
@@ -2480,13 +2481,48 @@ function VariableChip({
2480
2481
  format & 8 ? "lex4-text-underline" : "",
2481
2482
  format & 4 ? "lex4-text-strikethrough" : ""
2482
2483
  ].filter(Boolean).join(" ");
2483
- const handleClick = useCallback((event) => {
2484
+ const clearDomSelection = useCallback(() => {
2485
+ var _a;
2486
+ if (typeof window === "undefined") {
2487
+ return;
2488
+ }
2489
+ (_a = window.getSelection()) == null ? void 0 : _a.removeAllRanges();
2490
+ }, []);
2491
+ const selectNode = useCallback((extendSelection) => {
2492
+ editor.focus();
2493
+ editor.update(() => {
2494
+ const nextSelection = $createNodeSelection();
2495
+ if (extendSelection) {
2496
+ const currentSelection = $getSelection();
2497
+ if ($isNodeSelection(currentSelection)) {
2498
+ for (const node of currentSelection.getNodes()) {
2499
+ if ($isVariableNode(node)) {
2500
+ nextSelection.add(node.getKey());
2501
+ }
2502
+ }
2503
+ }
2504
+ }
2505
+ nextSelection.add(nodeKey);
2506
+ $setSelection(nextSelection);
2507
+ });
2508
+ clearDomSelection();
2509
+ }, [clearDomSelection, editor, nodeKey]);
2510
+ const handleMouseDown = useCallback((event) => {
2484
2511
  event.preventDefault();
2485
- if (!event.shiftKey) {
2486
- clearOtherSelections();
2512
+ event.stopPropagation();
2513
+ if (!isSelected || event.shiftKey) {
2514
+ selectNode(event.shiftKey);
2487
2515
  }
2488
- setSelected(!isSelected);
2489
- }, [clearOtherSelections, isSelected, setSelected]);
2516
+ }, [isSelected, selectNode]);
2517
+ const handleClick = useCallback((event) => {
2518
+ event.preventDefault();
2519
+ event.stopPropagation();
2520
+ }, []);
2521
+ const handleMouseUp = useCallback((event) => {
2522
+ event.preventDefault();
2523
+ event.stopPropagation();
2524
+ clearDomSelection();
2525
+ }, [clearDomSelection]);
2490
2526
  useEffect(() => {
2491
2527
  const removeSelectedNodes = () => {
2492
2528
  editor.update(() => {
@@ -2574,7 +2610,8 @@ function VariableChip({
2574
2610
  "data-variable-group": group,
2575
2611
  title: variableKey,
2576
2612
  style,
2577
- onMouseDown: (event) => event.preventDefault(),
2613
+ onMouseDown: handleMouseDown,
2614
+ onMouseUp: handleMouseUp,
2578
2615
  onClick: handleClick,
2579
2616
  children: label
2580
2617
  }
@@ -2586,6 +2623,83 @@ function $createVariableNode(variableKey, format = 0, style = "") {
2586
2623
  function $isVariableNode(node) {
2587
2624
  return node instanceof VariableNode;
2588
2625
  }
2626
+ const FORMAT_MASKS$1 = {
2627
+ bold: 1,
2628
+ italic: 2,
2629
+ strikethrough: 4,
2630
+ underline: 8
2631
+ };
2632
+ function dedupeVariableNodes(nodes) {
2633
+ return Array.from(new Map(nodes.map((node) => [node.getKey(), node])).values());
2634
+ }
2635
+ function getSelectedVariableNodesFromSelection(selection) {
2636
+ if (!selection || typeof selection !== "object" || !("getNodes" in selection) || typeof selection.getNodes !== "function") {
2637
+ return [];
2638
+ }
2639
+ return dedupeVariableNodes(selection.getNodes().filter($isVariableNode));
2640
+ }
2641
+ function getVisuallySelectedVariableNodes(editor) {
2642
+ const rootElement = editor.getRootElement();
2643
+ if (!rootElement) {
2644
+ return [];
2645
+ }
2646
+ const nodes = [];
2647
+ rootElement.querySelectorAll(".lex4-variable-chip-selected").forEach((chip) => {
2648
+ const variableElement = chip.closest("[data-node-key]");
2649
+ const nodeKey = variableElement == null ? void 0 : variableElement.dataset.nodeKey;
2650
+ if (!nodeKey) {
2651
+ return;
2652
+ }
2653
+ const node = $getNodeByKey(nodeKey);
2654
+ if ($isVariableNode(node)) {
2655
+ nodes.push(node);
2656
+ }
2657
+ });
2658
+ return dedupeVariableNodes(nodes);
2659
+ }
2660
+ function withSelectedVariableNodes(editor, updater) {
2661
+ let updated = false;
2662
+ editor.update(() => {
2663
+ const nodes = [
2664
+ ...getSelectedVariableNodesFromSelection($getSelection()),
2665
+ ...getVisuallySelectedVariableNodes(editor)
2666
+ ];
2667
+ const uniqueNodes = dedupeVariableNodes(nodes);
2668
+ if (uniqueNodes.length === 0) {
2669
+ return;
2670
+ }
2671
+ updater(uniqueNodes);
2672
+ updated = true;
2673
+ });
2674
+ return updated;
2675
+ }
2676
+ function toggleSelectedVariableFormat(editor, format) {
2677
+ const mask = FORMAT_MASKS$1[format];
2678
+ if (!mask) {
2679
+ return false;
2680
+ }
2681
+ return withSelectedVariableNodes(editor, (nodes) => {
2682
+ const shouldEnable = nodes.some((node) => (node.getFormat() & mask) === 0);
2683
+ for (const node of nodes) {
2684
+ const nextFormat = shouldEnable ? node.getFormat() | mask : node.getFormat() & ~mask;
2685
+ node.setFormat(nextFormat);
2686
+ }
2687
+ });
2688
+ }
2689
+ function applyFontFamilyToSelectedVariables(editor, fontFamily) {
2690
+ return withSelectedVariableNodes(editor, (nodes) => {
2691
+ for (const node of nodes) {
2692
+ node.setStyle(mergeFontFamilyStyle(node.getStyle(), fontFamily));
2693
+ }
2694
+ });
2695
+ }
2696
+ function applyFontSizeToSelectedVariables(editor, size) {
2697
+ return withSelectedVariableNodes(editor, (nodes) => {
2698
+ for (const node of nodes) {
2699
+ node.setStyle(mergeFontSizeStyle(node.getStyle(), size));
2700
+ }
2701
+ });
2702
+ }
2589
2703
  function getElementBlockType$1(element) {
2590
2704
  if ($isHeadingNode(element)) {
2591
2705
  return element.getTag();
@@ -2651,15 +2765,38 @@ function getStandaloneVariableChildren(topLevelElement) {
2651
2765
  }
2652
2766
  return meaningfulChildren;
2653
2767
  }
2768
+ function getSelectedVariableNodesFromRangeSelection(editor, selection) {
2769
+ const seen = /* @__PURE__ */ new Set();
2770
+ const variables = [];
2771
+ for (const node of [
2772
+ selection.anchor.getNode(),
2773
+ selection.focus.getNode(),
2774
+ ...selection.getNodes(),
2775
+ ...getVisuallySelectedVariableNodes(editor)
2776
+ ]) {
2777
+ if (!$isVariableNode(node) || seen.has(node.getKey())) {
2778
+ continue;
2779
+ }
2780
+ seen.add(node.getKey());
2781
+ variables.push(node);
2782
+ }
2783
+ return variables;
2784
+ }
2654
2785
  function setBlockType(editor, blockType) {
2655
2786
  editor.update(() => {
2787
+ const visuallySelectedVariables = getVisuallySelectedVariableNodes(editor);
2656
2788
  const currentSelection = $getSelection();
2657
2789
  const selection = $isNodeSelection(currentSelection) ? currentSelection : $createRangeSelectionFromDom(window.getSelection(), editor) ?? currentSelection;
2658
2790
  if ($isRangeSelection(selection)) {
2659
2791
  $setSelection(selection);
2660
2792
  }
2661
2793
  if ($isNodeSelection(selection)) {
2662
- const variables = selection.getNodes().filter($isVariableNode);
2794
+ const variables = Array.from(new Map(
2795
+ [
2796
+ ...selection.getNodes().filter($isVariableNode),
2797
+ ...visuallySelectedVariables
2798
+ ].map((variable) => [variable.getKey(), variable])
2799
+ ).values());
2663
2800
  if (variables.length === 0) {
2664
2801
  return;
2665
2802
  }
@@ -2691,69 +2828,32 @@ function setBlockType(editor, blockType) {
2691
2828
  return;
2692
2829
  }
2693
2830
  if (!$isRangeSelection(selection)) {
2831
+ if (visuallySelectedVariables.length === 0) {
2832
+ return;
2833
+ }
2834
+ for (const variable of visuallySelectedVariables) {
2835
+ variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
2836
+ }
2694
2837
  return;
2695
2838
  }
2696
2839
  const anchorTopLevel = selection.anchor.getNode().getTopLevelElementOrThrow();
2697
2840
  const standaloneVariables = $isElementNode(anchorTopLevel) ? getStandaloneVariableChildren(anchorTopLevel) : null;
2841
+ const selectedVariables = getSelectedVariableNodesFromRangeSelection(editor, selection);
2698
2842
  if (isPartialSingleBlockSelection(selection)) {
2699
2843
  $patchStyleText(selection, createInlineBlockTypeStylePatch(blockType));
2844
+ for (const variable of selectedVariables) {
2845
+ variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
2846
+ }
2700
2847
  return;
2701
2848
  }
2702
- for (const variable of standaloneVariables ?? []) {
2849
+ for (const variable of new Map(
2850
+ [...standaloneVariables ?? [], ...selectedVariables].map((variable2) => [variable2.getKey(), variable2])
2851
+ ).values()) {
2703
2852
  variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
2704
2853
  }
2705
2854
  applySemanticBlockType(selection, blockType);
2706
2855
  });
2707
2856
  }
2708
- const FORMAT_MASKS$1 = {
2709
- bold: 1,
2710
- italic: 2,
2711
- strikethrough: 4,
2712
- underline: 8
2713
- };
2714
- function withSelectedVariableNodes(editor, updater) {
2715
- let updated = false;
2716
- editor.update(() => {
2717
- const selection = $getSelection();
2718
- if (!$isNodeSelection(selection)) {
2719
- return;
2720
- }
2721
- const nodes = selection.getNodes().filter($isVariableNode);
2722
- if (nodes.length === 0) {
2723
- return;
2724
- }
2725
- updater(nodes);
2726
- updated = true;
2727
- });
2728
- return updated;
2729
- }
2730
- function toggleSelectedVariableFormat(editor, format) {
2731
- const mask = FORMAT_MASKS$1[format];
2732
- if (!mask) {
2733
- return false;
2734
- }
2735
- return withSelectedVariableNodes(editor, (nodes) => {
2736
- const shouldEnable = nodes.some((node) => (node.getFormat() & mask) === 0);
2737
- for (const node of nodes) {
2738
- const nextFormat = shouldEnable ? node.getFormat() | mask : node.getFormat() & ~mask;
2739
- node.setFormat(nextFormat);
2740
- }
2741
- });
2742
- }
2743
- function applyFontFamilyToSelectedVariables(editor, fontFamily) {
2744
- return withSelectedVariableNodes(editor, (nodes) => {
2745
- for (const node of nodes) {
2746
- node.setStyle(mergeFontFamilyStyle(node.getStyle(), fontFamily));
2747
- }
2748
- });
2749
- }
2750
- function applyFontSizeToSelectedVariables(editor, size) {
2751
- return withSelectedVariableNodes(editor, (nodes) => {
2752
- for (const node of nodes) {
2753
- node.setStyle(mergeFontSizeStyle(node.getStyle(), size));
2754
- }
2755
- });
2756
- }
2757
2857
  const BLOCK_TYPE_OPTIONS = [
2758
2858
  { value: "paragraph", shortLabel: "P" },
2759
2859
  { value: "h1", shortLabel: "H1" },
@@ -3179,7 +3279,7 @@ function normalizeFontFamily(fontFamily) {
3179
3279
  if (fontFamily && SUPPORTED_FONTS.includes(fontFamily)) {
3180
3280
  return fontFamily;
3181
3281
  }
3182
- return "Calibri";
3282
+ return "Inter";
3183
3283
  }
3184
3284
  function normalizeAlignment(alignment) {
3185
3285
  if (alignment === "center" || alignment === "right" || alignment === "justify") {