@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.js
CHANGED
|
@@ -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,
|
|
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: "
|
|
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
|
|
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
|
|
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
|
-
|
|
2486
|
-
|
|
2512
|
+
event.stopPropagation();
|
|
2513
|
+
if (!isSelected || event.shiftKey) {
|
|
2514
|
+
selectNode(event.shiftKey);
|
|
2487
2515
|
}
|
|
2488
|
-
|
|
2489
|
-
|
|
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:
|
|
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 =
|
|
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
|
|
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 "
|
|
3282
|
+
return "Inter";
|
|
3183
3283
|
}
|
|
3184
3284
|
function normalizeAlignment(alignment) {
|
|
3185
3285
|
if (alignment === "center" || alignment === "right" || alignment === "justify") {
|