@yurikilian/lex4 1.4.1 → 1.5.1
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/README.md +6 -4
- package/dist/ast/inline-mapper.d.ts.map +1 -1
- package/dist/ast/types.d.ts +1 -1
- package/dist/ast/types.d.ts.map +1 -1
- package/dist/components/CanvasControls.d.ts.map +1 -1
- package/dist/components/HeaderFooterToggle.d.ts +1 -0
- package/dist/components/HeaderFooterToggle.d.ts.map +1 -1
- package/dist/components/Lex4Editor.d.ts.map +1 -1
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/context/document-context.d.ts +1 -0
- package/dist/context/document-context.d.ts.map +1 -1
- package/dist/context/document-provider.d.ts.map +1 -1
- package/dist/context/toolbar-config.d.ts +18 -0
- package/dist/context/toolbar-config.d.ts.map +1 -0
- package/dist/extensions/variables-extension.d.ts.map +1 -1
- package/dist/i18n/defaults.d.ts.map +1 -1
- package/dist/i18n/pt-BR.d.ts.map +1 -1
- package/dist/i18n/types.d.ts +12 -0
- package/dist/i18n/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lex4-editor.cjs +730 -157
- package/dist/lex4-editor.cjs.map +1 -1
- package/dist/lex4-editor.js +714 -141
- package/dist/lex4-editor.js.map +1 -1
- package/dist/lexical/commands/block-commands.d.ts +5 -0
- package/dist/lexical/commands/block-commands.d.ts.map +1 -0
- package/dist/lexical/theme.d.ts.map +1 -1
- package/dist/lexical/utils/import-document-content.d.ts +4 -0
- package/dist/lexical/utils/import-document-content.d.ts.map +1 -0
- package/dist/style.css +51 -23
- package/dist/types/editor-handle.d.ts +2 -0
- package/dist/types/editor-handle.d.ts.map +1 -1
- package/dist/types/editor-props.d.ts +16 -0
- package/dist/types/editor-props.d.ts.map +1 -1
- package/dist/utils/text-style.d.ts +7 -0
- package/dist/utils/text-style.d.ts.map +1 -0
- package/dist/variables/variable-formatting.d.ts +11 -0
- package/dist/variables/variable-formatting.d.ts.map +1 -0
- package/dist/variables/variable-node.d.ts +10 -2
- package/dist/variables/variable-node.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/lex4-editor.cjs
CHANGED
|
@@ -8,13 +8,15 @@ const React = require("react");
|
|
|
8
8
|
const lexical = require("lexical");
|
|
9
9
|
const LexicalComposerContext = require("@lexical/react/LexicalComposerContext");
|
|
10
10
|
const list = require("@lexical/list");
|
|
11
|
+
const selection = require("@lexical/selection");
|
|
12
|
+
const richText = require("@lexical/rich-text");
|
|
13
|
+
const useLexicalNodeSelection = require("@lexical/react/useLexicalNodeSelection");
|
|
11
14
|
const LexicalComposer = require("@lexical/react/LexicalComposer");
|
|
12
15
|
const LexicalRichTextPlugin = require("@lexical/react/LexicalRichTextPlugin");
|
|
13
16
|
const LexicalContentEditable = require("@lexical/react/LexicalContentEditable");
|
|
14
17
|
const LexicalListPlugin = require("@lexical/react/LexicalListPlugin");
|
|
15
18
|
const LexicalErrorBoundary = require("@lexical/react/LexicalErrorBoundary");
|
|
16
19
|
const LexicalOnChangePlugin = require("@lexical/react/LexicalOnChangePlugin");
|
|
17
|
-
const richText = require("@lexical/rich-text");
|
|
18
20
|
function createEmptyPage(id) {
|
|
19
21
|
return {
|
|
20
22
|
id: id ?? crypto.randomUUID(),
|
|
@@ -473,6 +475,15 @@ const DEFAULT_TRANSLATIONS = {
|
|
|
473
475
|
bulletList: "Bullet List",
|
|
474
476
|
indent: "Indent",
|
|
475
477
|
outdent: "Outdent",
|
|
478
|
+
history: "History",
|
|
479
|
+
blockType: "Block type",
|
|
480
|
+
paragraph: "Paragraph",
|
|
481
|
+
heading1: "Heading 1",
|
|
482
|
+
heading2: "Heading 2",
|
|
483
|
+
heading3: "Heading 3",
|
|
484
|
+
heading4: "Heading 4",
|
|
485
|
+
heading5: "Heading 5",
|
|
486
|
+
heading6: "Heading 6",
|
|
476
487
|
openHistory: "Open History",
|
|
477
488
|
closeHistory: "Close History"
|
|
478
489
|
},
|
|
@@ -504,7 +515,9 @@ const DEFAULT_TRANSLATIONS = {
|
|
|
504
515
|
indentedContent: "Indented content",
|
|
505
516
|
outdentedContent: "Outdented content",
|
|
506
517
|
fontChanged: "Font changed to {{value}}",
|
|
507
|
-
fontSizeChanged: "Font size changed to {{value}}pt"
|
|
518
|
+
fontSizeChanged: "Font size changed to {{value}}pt",
|
|
519
|
+
blockTypeChanged: "Block type changed to {{value}}",
|
|
520
|
+
insertedDocumentContent: "Inserted document content"
|
|
508
521
|
}
|
|
509
522
|
},
|
|
510
523
|
variables: {
|
|
@@ -604,6 +617,15 @@ const PT_BR_TRANSLATIONS = {
|
|
|
604
617
|
bulletList: "Lista com Marcadores",
|
|
605
618
|
indent: "Aumentar Recuo",
|
|
606
619
|
outdent: "Diminuir Recuo",
|
|
620
|
+
history: "Histórico",
|
|
621
|
+
blockType: "Tipo de bloco",
|
|
622
|
+
paragraph: "Parágrafo",
|
|
623
|
+
heading1: "Título 1",
|
|
624
|
+
heading2: "Título 2",
|
|
625
|
+
heading3: "Título 3",
|
|
626
|
+
heading4: "Título 4",
|
|
627
|
+
heading5: "Título 5",
|
|
628
|
+
heading6: "Título 6",
|
|
607
629
|
openHistory: "Abrir Histórico",
|
|
608
630
|
closeHistory: "Fechar Histórico"
|
|
609
631
|
},
|
|
@@ -635,7 +657,9 @@ const PT_BR_TRANSLATIONS = {
|
|
|
635
657
|
indentedContent: "Conteúdo recuado",
|
|
636
658
|
outdentedContent: "Recuo reduzido",
|
|
637
659
|
fontChanged: "Fonte alterada para {{value}}",
|
|
638
|
-
fontSizeChanged: "Tamanho da fonte alterado para {{value}}pt"
|
|
660
|
+
fontSizeChanged: "Tamanho da fonte alterado para {{value}}pt",
|
|
661
|
+
blockTypeChanged: "Tipo de bloco alterado para {{value}}",
|
|
662
|
+
insertedDocumentContent: "Conteúdo do documento inserido"
|
|
639
663
|
}
|
|
640
664
|
},
|
|
641
665
|
variables: {
|
|
@@ -797,25 +821,25 @@ function captureCaretSelection(editor) {
|
|
|
797
821
|
};
|
|
798
822
|
let caretSelection = null;
|
|
799
823
|
editor.getEditorState().read(() => {
|
|
800
|
-
const
|
|
801
|
-
if (!lexical.$isRangeSelection(
|
|
824
|
+
const selection2 = lexical.$createRangeSelectionFromDom(window.getSelection(), editor) ?? lexical.$getSelection();
|
|
825
|
+
if (!lexical.$isRangeSelection(selection2)) {
|
|
802
826
|
return;
|
|
803
827
|
}
|
|
804
828
|
caretSelection = {
|
|
805
829
|
anchor: {
|
|
806
|
-
key:
|
|
807
|
-
offset:
|
|
808
|
-
type:
|
|
830
|
+
key: selection2.anchor.key,
|
|
831
|
+
offset: selection2.anchor.offset,
|
|
832
|
+
type: selection2.anchor.type
|
|
809
833
|
},
|
|
810
834
|
focus: {
|
|
811
|
-
key:
|
|
812
|
-
offset:
|
|
813
|
-
type:
|
|
835
|
+
key: selection2.focus.key,
|
|
836
|
+
offset: selection2.focus.offset,
|
|
837
|
+
type: selection2.focus.type
|
|
814
838
|
},
|
|
815
839
|
anchorTextOffset: domSelection && selectionInRoot(domSelection.anchorNode) ? getTextOffset(domSelection.anchorNode, domSelection.anchorOffset) : 0,
|
|
816
840
|
focusTextOffset: domSelection && selectionInRoot(domSelection.focusNode) ? getTextOffset(domSelection.focusNode, domSelection.focusOffset) : 0,
|
|
817
|
-
format:
|
|
818
|
-
style:
|
|
841
|
+
format: selection2.format,
|
|
842
|
+
style: selection2.style
|
|
819
843
|
};
|
|
820
844
|
});
|
|
821
845
|
return caretSelection;
|
|
@@ -1286,6 +1310,7 @@ const DocumentProvider = ({
|
|
|
1286
1310
|
activePageId,
|
|
1287
1311
|
setActivePageId,
|
|
1288
1312
|
activeEditor: activeEditorRef.current,
|
|
1313
|
+
activeCaretPosition: activeCaretPositionRef.current,
|
|
1289
1314
|
consumePendingCaretPosition,
|
|
1290
1315
|
consumePendingFocusAtEnd,
|
|
1291
1316
|
requestFocusAtEnd,
|
|
@@ -1892,6 +1917,36 @@ const HistorySidebar = () => {
|
|
|
1892
1917
|
}
|
|
1893
1918
|
);
|
|
1894
1919
|
};
|
|
1920
|
+
const DEFAULT_TOOLBAR_CONTROL_CONFIG = {
|
|
1921
|
+
visible: true,
|
|
1922
|
+
showLabel: true
|
|
1923
|
+
};
|
|
1924
|
+
const DEFAULT_TOOLBAR_CONFIG = {
|
|
1925
|
+
history: DEFAULT_TOOLBAR_CONTROL_CONFIG,
|
|
1926
|
+
variables: DEFAULT_TOOLBAR_CONTROL_CONFIG,
|
|
1927
|
+
headerFooter: DEFAULT_TOOLBAR_CONTROL_CONFIG
|
|
1928
|
+
};
|
|
1929
|
+
const ToolbarConfigContext = React.createContext(DEFAULT_TOOLBAR_CONFIG);
|
|
1930
|
+
function resolveControlConfig(config) {
|
|
1931
|
+
return {
|
|
1932
|
+
visible: (config == null ? void 0 : config.visible) ?? true,
|
|
1933
|
+
showLabel: (config == null ? void 0 : config.showLabel) ?? true
|
|
1934
|
+
};
|
|
1935
|
+
}
|
|
1936
|
+
function normalizeToolbarConfig(config) {
|
|
1937
|
+
return {
|
|
1938
|
+
history: resolveControlConfig(config == null ? void 0 : config.history),
|
|
1939
|
+
variables: resolveControlConfig(config == null ? void 0 : config.variables),
|
|
1940
|
+
headerFooter: resolveControlConfig(config == null ? void 0 : config.headerFooter)
|
|
1941
|
+
};
|
|
1942
|
+
}
|
|
1943
|
+
const ToolbarConfigProvider = ({ toolbar, children }) => {
|
|
1944
|
+
const resolvedConfig = React.useMemo(() => normalizeToolbarConfig(toolbar), [toolbar]);
|
|
1945
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ToolbarConfigContext.Provider, { value: resolvedConfig, children });
|
|
1946
|
+
};
|
|
1947
|
+
function useToolbarConfig() {
|
|
1948
|
+
return React.useContext(ToolbarConfigContext);
|
|
1949
|
+
}
|
|
1895
1950
|
function resolveExtensions(extensions) {
|
|
1896
1951
|
const resolved = {
|
|
1897
1952
|
nodes: [],
|
|
@@ -1997,9 +2052,9 @@ const SUPPORTED_FONTS = [
|
|
|
1997
2052
|
];
|
|
1998
2053
|
function applyFontFamily(editor, fontFamily) {
|
|
1999
2054
|
editor.update(() => {
|
|
2000
|
-
const
|
|
2001
|
-
if (!lexical.$isRangeSelection(
|
|
2002
|
-
const nodes =
|
|
2055
|
+
const selection2 = lexical.$getSelection();
|
|
2056
|
+
if (!lexical.$isRangeSelection(selection2)) return;
|
|
2057
|
+
const nodes = selection2.getNodes();
|
|
2003
2058
|
for (const node of nodes) {
|
|
2004
2059
|
if (lexical.$isTextNode(node)) {
|
|
2005
2060
|
node.setStyle(`font-family: ${fontFamily}`);
|
|
@@ -2024,11 +2079,12 @@ const SUPPORTED_FONT_SIZES = [
|
|
|
2024
2079
|
48,
|
|
2025
2080
|
72
|
|
2026
2081
|
];
|
|
2082
|
+
const DEFAULT_FONT_SIZE = 12;
|
|
2027
2083
|
function applyFontSize(editor, size) {
|
|
2028
2084
|
editor.update(() => {
|
|
2029
|
-
const
|
|
2030
|
-
if (!lexical.$isRangeSelection(
|
|
2031
|
-
const nodes =
|
|
2085
|
+
const selection2 = lexical.$getSelection();
|
|
2086
|
+
if (!lexical.$isRangeSelection(selection2)) return;
|
|
2087
|
+
const nodes = selection2.getNodes();
|
|
2032
2088
|
for (const node of nodes) {
|
|
2033
2089
|
if (lexical.$isTextNode(node)) {
|
|
2034
2090
|
const existing = node.getStyle();
|
|
@@ -2074,9 +2130,366 @@ function indentContent(editor) {
|
|
|
2074
2130
|
function outdentContent(editor) {
|
|
2075
2131
|
editor.dispatchCommand(lexical.OUTDENT_CONTENT_COMMAND, void 0);
|
|
2076
2132
|
}
|
|
2133
|
+
function setBlockType(editor, blockType) {
|
|
2134
|
+
editor.update(() => {
|
|
2135
|
+
const selection$1 = lexical.$getSelection();
|
|
2136
|
+
if (!lexical.$isRangeSelection(selection$1)) {
|
|
2137
|
+
return;
|
|
2138
|
+
}
|
|
2139
|
+
if (blockType === "paragraph") {
|
|
2140
|
+
selection.$setBlocksType(selection$1, () => lexical.$createParagraphNode());
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
2143
|
+
selection.$setBlocksType(selection$1, () => richText.$createHeadingNode(blockType));
|
|
2144
|
+
});
|
|
2145
|
+
}
|
|
2146
|
+
function getActiveBlockType(editor) {
|
|
2147
|
+
let blockType = "paragraph";
|
|
2148
|
+
editor.getEditorState().read(() => {
|
|
2149
|
+
const selection2 = lexical.$getSelection();
|
|
2150
|
+
if (!lexical.$isRangeSelection(selection2)) {
|
|
2151
|
+
return;
|
|
2152
|
+
}
|
|
2153
|
+
const anchorNode = selection2.anchor.getNode();
|
|
2154
|
+
const topLevelElement = anchorNode.getTopLevelElementOrThrow();
|
|
2155
|
+
if (richText.$isHeadingNode(topLevelElement)) {
|
|
2156
|
+
blockType = topLevelElement.getTag();
|
|
2157
|
+
}
|
|
2158
|
+
});
|
|
2159
|
+
return blockType;
|
|
2160
|
+
}
|
|
2161
|
+
function extractStyleValue(style, property) {
|
|
2162
|
+
const escapedProperty = property.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2163
|
+
const match = style.match(new RegExp(`${escapedProperty}:\\s*([^;]+)`));
|
|
2164
|
+
return match ? match[1].trim().replace(/['"]/g, "") : void 0;
|
|
2165
|
+
}
|
|
2166
|
+
function mergeStyleDeclaration(existingStyle, property, value) {
|
|
2167
|
+
const escapedProperty = property.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2168
|
+
const stripped = existingStyle.replace(
|
|
2169
|
+
new RegExp(`${escapedProperty}:\\s*[^;]+;?\\s*`, "g"),
|
|
2170
|
+
""
|
|
2171
|
+
).trim();
|
|
2172
|
+
const declaration = `${property}: ${value}`;
|
|
2173
|
+
return stripped ? `${stripped}; ${declaration}` : declaration;
|
|
2174
|
+
}
|
|
2175
|
+
function extractFontFamilyFromStyle(style) {
|
|
2176
|
+
return extractStyleValue(style, "font-family");
|
|
2177
|
+
}
|
|
2178
|
+
function extractFontSizePtFromStyle(style) {
|
|
2179
|
+
const value = extractStyleValue(style, "font-size");
|
|
2180
|
+
if (!value) {
|
|
2181
|
+
return void 0;
|
|
2182
|
+
}
|
|
2183
|
+
const match = value.match(/^(\d+(?:\.\d+)?)\s*pt$/);
|
|
2184
|
+
return match ? parseFloat(match[1]) : void 0;
|
|
2185
|
+
}
|
|
2186
|
+
function mergeFontFamilyStyle(existingStyle, fontFamily) {
|
|
2187
|
+
return mergeStyleDeclaration(existingStyle, "font-family", fontFamily);
|
|
2188
|
+
}
|
|
2189
|
+
function mergeFontSizeStyle(existingStyle, size) {
|
|
2190
|
+
return mergeStyleDeclaration(existingStyle, "font-size", `${size}pt`);
|
|
2191
|
+
}
|
|
2192
|
+
const EMPTY_CONTEXT = {
|
|
2193
|
+
definitions: [],
|
|
2194
|
+
refreshDefinitions: () => {
|
|
2195
|
+
},
|
|
2196
|
+
getDefinition: () => void 0
|
|
2197
|
+
};
|
|
2198
|
+
const VariableContext = React.createContext(EMPTY_CONTEXT);
|
|
2199
|
+
const VariableProvider = ({
|
|
2200
|
+
initialDefinitions = [],
|
|
2201
|
+
children
|
|
2202
|
+
}) => {
|
|
2203
|
+
const [definitions, setDefinitions] = React.useState(initialDefinitions);
|
|
2204
|
+
const refresh = React.useCallback((newDefinitions) => {
|
|
2205
|
+
setDefinitions(newDefinitions);
|
|
2206
|
+
}, []);
|
|
2207
|
+
const getDefinition = React.useCallback(
|
|
2208
|
+
(key) => {
|
|
2209
|
+
return definitions.find((d) => d.key === key);
|
|
2210
|
+
},
|
|
2211
|
+
[definitions]
|
|
2212
|
+
);
|
|
2213
|
+
const value = React.useMemo(
|
|
2214
|
+
() => ({ definitions, refreshDefinitions: refresh, getDefinition }),
|
|
2215
|
+
[definitions, refresh, getDefinition]
|
|
2216
|
+
);
|
|
2217
|
+
return /* @__PURE__ */ jsxRuntime.jsx(VariableContext.Provider, { value, children });
|
|
2218
|
+
};
|
|
2219
|
+
function useVariables() {
|
|
2220
|
+
return React.useContext(VariableContext);
|
|
2221
|
+
}
|
|
2222
|
+
class VariableNode extends lexical.DecoratorNode {
|
|
2223
|
+
constructor(variableKey, format = 0, style = "", key) {
|
|
2224
|
+
super(key);
|
|
2225
|
+
__publicField(this, "__variableKey");
|
|
2226
|
+
__publicField(this, "__format");
|
|
2227
|
+
__publicField(this, "__style");
|
|
2228
|
+
this.__variableKey = variableKey;
|
|
2229
|
+
this.__format = format;
|
|
2230
|
+
this.__style = style;
|
|
2231
|
+
}
|
|
2232
|
+
static getType() {
|
|
2233
|
+
return "variable-node";
|
|
2234
|
+
}
|
|
2235
|
+
static clone(node) {
|
|
2236
|
+
return new VariableNode(node.__variableKey, node.__format, node.__style, node.__key);
|
|
2237
|
+
}
|
|
2238
|
+
getVariableKey() {
|
|
2239
|
+
return this.getLatest().__variableKey;
|
|
2240
|
+
}
|
|
2241
|
+
getFormat() {
|
|
2242
|
+
return this.getLatest().__format;
|
|
2243
|
+
}
|
|
2244
|
+
setFormat(format) {
|
|
2245
|
+
const writable = this.getWritable();
|
|
2246
|
+
writable.__format = format;
|
|
2247
|
+
return writable;
|
|
2248
|
+
}
|
|
2249
|
+
getStyle() {
|
|
2250
|
+
return this.getLatest().__style;
|
|
2251
|
+
}
|
|
2252
|
+
setStyle(style) {
|
|
2253
|
+
const writable = this.getWritable();
|
|
2254
|
+
writable.__style = style;
|
|
2255
|
+
return writable;
|
|
2256
|
+
}
|
|
2257
|
+
// -- Serialization --
|
|
2258
|
+
static importJSON(serializedNode) {
|
|
2259
|
+
return $createVariableNode(
|
|
2260
|
+
serializedNode.variableKey,
|
|
2261
|
+
serializedNode.format ?? 0,
|
|
2262
|
+
serializedNode.style ?? ""
|
|
2263
|
+
);
|
|
2264
|
+
}
|
|
2265
|
+
exportJSON() {
|
|
2266
|
+
return {
|
|
2267
|
+
type: "variable-node",
|
|
2268
|
+
version: 1,
|
|
2269
|
+
variableKey: this.__variableKey,
|
|
2270
|
+
format: this.__format,
|
|
2271
|
+
style: this.__style
|
|
2272
|
+
};
|
|
2273
|
+
}
|
|
2274
|
+
// -- DOM --
|
|
2275
|
+
createDOM() {
|
|
2276
|
+
const span = document.createElement("span");
|
|
2277
|
+
span.className = "lex4-variable";
|
|
2278
|
+
span.setAttribute("data-variable-key", this.__variableKey);
|
|
2279
|
+
span.setAttribute("data-testid", `variable-${this.__variableKey}`);
|
|
2280
|
+
span.contentEditable = "false";
|
|
2281
|
+
return span;
|
|
2282
|
+
}
|
|
2283
|
+
updateDOM() {
|
|
2284
|
+
return false;
|
|
2285
|
+
}
|
|
2286
|
+
exportDOM() {
|
|
2287
|
+
const span = document.createElement("span");
|
|
2288
|
+
span.setAttribute("data-variable-key", this.__variableKey);
|
|
2289
|
+
span.textContent = `{{${this.__variableKey}}}`;
|
|
2290
|
+
return { element: span };
|
|
2291
|
+
}
|
|
2292
|
+
static importDOM() {
|
|
2293
|
+
return null;
|
|
2294
|
+
}
|
|
2295
|
+
// -- Behavior --
|
|
2296
|
+
isInline() {
|
|
2297
|
+
return true;
|
|
2298
|
+
}
|
|
2299
|
+
isKeyboardSelectable() {
|
|
2300
|
+
return true;
|
|
2301
|
+
}
|
|
2302
|
+
getTextContent() {
|
|
2303
|
+
return `{{${this.__variableKey}}}`;
|
|
2304
|
+
}
|
|
2305
|
+
// -- Rendering --
|
|
2306
|
+
decorate() {
|
|
2307
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2308
|
+
VariableChip,
|
|
2309
|
+
{
|
|
2310
|
+
nodeKey: this.__key,
|
|
2311
|
+
variableKey: this.__variableKey,
|
|
2312
|
+
format: this.__format,
|
|
2313
|
+
styleValue: this.__style
|
|
2314
|
+
}
|
|
2315
|
+
);
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
function VariableChip({
|
|
2319
|
+
nodeKey,
|
|
2320
|
+
variableKey,
|
|
2321
|
+
format,
|
|
2322
|
+
styleValue
|
|
2323
|
+
}) {
|
|
2324
|
+
const { getDefinition } = useVariables();
|
|
2325
|
+
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
2326
|
+
const [isSelected, setSelected, clearOtherSelections] = useLexicalNodeSelection.useLexicalNodeSelection(nodeKey);
|
|
2327
|
+
const def = getDefinition(variableKey);
|
|
2328
|
+
const label = (def == null ? void 0 : def.label) ?? variableKey;
|
|
2329
|
+
const group = def == null ? void 0 : def.group;
|
|
2330
|
+
const style = React.useMemo(() => {
|
|
2331
|
+
const fontFamily = extractFontFamilyFromStyle(styleValue);
|
|
2332
|
+
const fontSize = extractFontSizePtFromStyle(styleValue);
|
|
2333
|
+
return {
|
|
2334
|
+
...fontFamily ? { fontFamily } : {},
|
|
2335
|
+
...fontSize ? { fontSize: `${fontSize}pt` } : {}
|
|
2336
|
+
};
|
|
2337
|
+
}, [styleValue]);
|
|
2338
|
+
const className = [
|
|
2339
|
+
"lex4-variable-chip",
|
|
2340
|
+
isSelected && "lex4-variable-chip-selected",
|
|
2341
|
+
format & 1 ? "lex4-text-bold" : "",
|
|
2342
|
+
format & 2 ? "lex4-text-italic" : "",
|
|
2343
|
+
format & 8 ? "lex4-text-underline" : "",
|
|
2344
|
+
format & 4 ? "lex4-text-strikethrough" : ""
|
|
2345
|
+
].filter(Boolean).join(" ");
|
|
2346
|
+
const handleClick = React.useCallback((event) => {
|
|
2347
|
+
event.preventDefault();
|
|
2348
|
+
if (!event.shiftKey) {
|
|
2349
|
+
clearOtherSelections();
|
|
2350
|
+
}
|
|
2351
|
+
setSelected(!isSelected);
|
|
2352
|
+
}, [clearOtherSelections, isSelected, setSelected]);
|
|
2353
|
+
React.useEffect(() => {
|
|
2354
|
+
const removeSelectedNodes = () => {
|
|
2355
|
+
editor.update(() => {
|
|
2356
|
+
const selection2 = lexical.$getSelection();
|
|
2357
|
+
if (!lexical.$isNodeSelection(selection2)) {
|
|
2358
|
+
const node = lexical.$getNodeByKey(nodeKey);
|
|
2359
|
+
if ($isVariableNode(node)) {
|
|
2360
|
+
node.remove();
|
|
2361
|
+
}
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
for (const node of selection2.getNodes()) {
|
|
2365
|
+
if ($isVariableNode(node)) {
|
|
2366
|
+
node.remove();
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
});
|
|
2370
|
+
};
|
|
2371
|
+
const unregisterBackspace = editor.registerCommand(
|
|
2372
|
+
lexical.KEY_BACKSPACE_COMMAND,
|
|
2373
|
+
() => {
|
|
2374
|
+
if (!isSelected) {
|
|
2375
|
+
return false;
|
|
2376
|
+
}
|
|
2377
|
+
removeSelectedNodes();
|
|
2378
|
+
return true;
|
|
2379
|
+
},
|
|
2380
|
+
lexical.COMMAND_PRIORITY_LOW
|
|
2381
|
+
);
|
|
2382
|
+
const unregisterDelete = editor.registerCommand(
|
|
2383
|
+
lexical.KEY_DELETE_COMMAND,
|
|
2384
|
+
() => {
|
|
2385
|
+
if (!isSelected) {
|
|
2386
|
+
return false;
|
|
2387
|
+
}
|
|
2388
|
+
removeSelectedNodes();
|
|
2389
|
+
return true;
|
|
2390
|
+
},
|
|
2391
|
+
lexical.COMMAND_PRIORITY_LOW
|
|
2392
|
+
);
|
|
2393
|
+
return () => {
|
|
2394
|
+
unregisterBackspace();
|
|
2395
|
+
unregisterDelete();
|
|
2396
|
+
};
|
|
2397
|
+
}, [editor, isSelected, nodeKey]);
|
|
2398
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2399
|
+
"span",
|
|
2400
|
+
{
|
|
2401
|
+
className,
|
|
2402
|
+
"data-testid": `variable-chip-${variableKey}`,
|
|
2403
|
+
"data-variable-group": group,
|
|
2404
|
+
title: variableKey,
|
|
2405
|
+
style,
|
|
2406
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
2407
|
+
onClick: handleClick,
|
|
2408
|
+
children: label
|
|
2409
|
+
}
|
|
2410
|
+
);
|
|
2411
|
+
}
|
|
2412
|
+
function $createVariableNode(variableKey, format = 0, style = "") {
|
|
2413
|
+
return lexical.$applyNodeReplacement(new VariableNode(variableKey, format, style));
|
|
2414
|
+
}
|
|
2415
|
+
function $isVariableNode(node) {
|
|
2416
|
+
return node instanceof VariableNode;
|
|
2417
|
+
}
|
|
2418
|
+
const FORMAT_MASKS = {
|
|
2419
|
+
bold: 1,
|
|
2420
|
+
italic: 2,
|
|
2421
|
+
strikethrough: 4,
|
|
2422
|
+
underline: 8
|
|
2423
|
+
};
|
|
2424
|
+
function withSelectedVariableNodes(editor, updater) {
|
|
2425
|
+
let updated = false;
|
|
2426
|
+
editor.update(() => {
|
|
2427
|
+
const selection2 = lexical.$getSelection();
|
|
2428
|
+
if (!lexical.$isNodeSelection(selection2)) {
|
|
2429
|
+
return;
|
|
2430
|
+
}
|
|
2431
|
+
const nodes = selection2.getNodes().filter($isVariableNode);
|
|
2432
|
+
if (nodes.length === 0) {
|
|
2433
|
+
return;
|
|
2434
|
+
}
|
|
2435
|
+
updater(nodes);
|
|
2436
|
+
updated = true;
|
|
2437
|
+
});
|
|
2438
|
+
return updated;
|
|
2439
|
+
}
|
|
2440
|
+
function getSelectedVariableNodes(editor) {
|
|
2441
|
+
let nodes = [];
|
|
2442
|
+
editor.getEditorState().read(() => {
|
|
2443
|
+
const selection2 = lexical.$getSelection();
|
|
2444
|
+
if (!lexical.$isNodeSelection(selection2)) {
|
|
2445
|
+
return;
|
|
2446
|
+
}
|
|
2447
|
+
nodes = selection2.getNodes().filter($isVariableNode);
|
|
2448
|
+
});
|
|
2449
|
+
return nodes;
|
|
2450
|
+
}
|
|
2451
|
+
function toggleSelectedVariableFormat(editor, format) {
|
|
2452
|
+
const mask = FORMAT_MASKS[format];
|
|
2453
|
+
if (!mask) {
|
|
2454
|
+
return false;
|
|
2455
|
+
}
|
|
2456
|
+
return withSelectedVariableNodes(editor, (nodes) => {
|
|
2457
|
+
const shouldEnable = nodes.some((node) => (node.getFormat() & mask) === 0);
|
|
2458
|
+
for (const node of nodes) {
|
|
2459
|
+
const nextFormat = shouldEnable ? node.getFormat() | mask : node.getFormat() & ~mask;
|
|
2460
|
+
node.setFormat(nextFormat);
|
|
2461
|
+
}
|
|
2462
|
+
});
|
|
2463
|
+
}
|
|
2464
|
+
function applyFontFamilyToSelectedVariables(editor, fontFamily) {
|
|
2465
|
+
return withSelectedVariableNodes(editor, (nodes) => {
|
|
2466
|
+
for (const node of nodes) {
|
|
2467
|
+
node.setStyle(mergeFontFamilyStyle(node.getStyle(), fontFamily));
|
|
2468
|
+
}
|
|
2469
|
+
});
|
|
2470
|
+
}
|
|
2471
|
+
function applyFontSizeToSelectedVariables(editor, size) {
|
|
2472
|
+
return withSelectedVariableNodes(editor, (nodes) => {
|
|
2473
|
+
for (const node of nodes) {
|
|
2474
|
+
node.setStyle(mergeFontSizeStyle(node.getStyle(), size));
|
|
2475
|
+
}
|
|
2476
|
+
});
|
|
2477
|
+
}
|
|
2478
|
+
function readSelectedVariableFormatting(editor) {
|
|
2479
|
+
const firstNode = getSelectedVariableNodes(editor)[0];
|
|
2480
|
+
if (!firstNode) {
|
|
2481
|
+
return {};
|
|
2482
|
+
}
|
|
2483
|
+
const style = firstNode.getStyle();
|
|
2484
|
+
return {
|
|
2485
|
+
fontFamily: extractFontFamilyFromStyle(style),
|
|
2486
|
+
fontSize: extractFontSizePtFromStyle(style)
|
|
2487
|
+
};
|
|
2488
|
+
}
|
|
2077
2489
|
const HeaderFooterToggle = ({
|
|
2078
2490
|
enabled,
|
|
2079
|
-
onToggle
|
|
2491
|
+
onToggle,
|
|
2492
|
+
showLabel = true
|
|
2080
2493
|
}) => {
|
|
2081
2494
|
const t = useTranslations();
|
|
2082
2495
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -2086,18 +2499,20 @@ const HeaderFooterToggle = ({
|
|
|
2086
2499
|
"data-testid": "header-footer-toggle",
|
|
2087
2500
|
children: [
|
|
2088
2501
|
/* @__PURE__ */ jsxRuntime.jsx(FileText, { size: 14, className: "lex4-hf-toggle-icon" }),
|
|
2089
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-hf-toggle-label", children: t.headerFooter.label }),
|
|
2502
|
+
showLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-hf-toggle-label", children: t.headerFooter.label }),
|
|
2090
2503
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2091
2504
|
"button",
|
|
2092
2505
|
{
|
|
2093
2506
|
type: "button",
|
|
2094
2507
|
role: "switch",
|
|
2095
2508
|
"aria-checked": enabled,
|
|
2509
|
+
"aria-label": t.headerFooter.label,
|
|
2096
2510
|
onMouseDown: (e) => e.preventDefault(),
|
|
2097
2511
|
onClick: () => onToggle(!enabled),
|
|
2098
2512
|
className: "lex4-hf-switch",
|
|
2099
2513
|
style: { backgroundColor: enabled ? "var(--color-primary)" : "var(--color-muted)" },
|
|
2100
2514
|
"data-testid": "header-footer-switch",
|
|
2515
|
+
title: t.headerFooter.label,
|
|
2101
2516
|
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-hf-switch-knob" })
|
|
2102
2517
|
}
|
|
2103
2518
|
)
|
|
@@ -2261,6 +2676,7 @@ const MenuItem = ({ icon, label, onClick, disabled, testId }) => /* @__PURE__ */
|
|
|
2261
2676
|
const MenuDivider = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-settings-divider" });
|
|
2262
2677
|
const CanvasControls = () => {
|
|
2263
2678
|
const { document: document2, dispatch, activePageId, runHistoryAction } = useDocument();
|
|
2679
|
+
const toolbarConfig = useToolbarConfig();
|
|
2264
2680
|
const t = useTranslations();
|
|
2265
2681
|
const runCanvasAction = React.useCallback((label, callback) => {
|
|
2266
2682
|
runHistoryAction(
|
|
@@ -2327,12 +2743,16 @@ const CanvasControls = () => {
|
|
|
2327
2743
|
dispatch({ type: "SET_PAGE_COUNTER_MODE", mode });
|
|
2328
2744
|
});
|
|
2329
2745
|
}, [dispatch, runCanvasAction, t.history.actions.pageCounterSet]);
|
|
2746
|
+
if (!toolbarConfig.headerFooter.visible) {
|
|
2747
|
+
return null;
|
|
2748
|
+
}
|
|
2330
2749
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group lex4-toolbar-group-gap", "data-testid": "header-footer-controls", children: [
|
|
2331
2750
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2332
2751
|
HeaderFooterToggle,
|
|
2333
2752
|
{
|
|
2334
2753
|
enabled: document2.headerFooterEnabled,
|
|
2335
|
-
onToggle: handleToggle
|
|
2754
|
+
onToggle: handleToggle,
|
|
2755
|
+
showLabel: toolbarConfig.headerFooter.showLabel
|
|
2336
2756
|
}
|
|
2337
2757
|
),
|
|
2338
2758
|
document2.headerFooterEnabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2365,7 +2785,17 @@ const Toolbar = () => {
|
|
|
2365
2785
|
undo
|
|
2366
2786
|
} = useDocument();
|
|
2367
2787
|
const { toolbarItems, toolbarEndItems } = useExtensions();
|
|
2788
|
+
const toolbarConfig = useToolbarConfig();
|
|
2368
2789
|
const t = useTranslations();
|
|
2790
|
+
const [activeBlockType, setActiveBlockType] = React.useState("paragraph");
|
|
2791
|
+
const [activeFontFamily, setActiveFontFamily] = React.useState("Calibri");
|
|
2792
|
+
const [activeFontSize, setActiveFontSize] = React.useState(DEFAULT_FONT_SIZE);
|
|
2793
|
+
const normalizeFontFamily = React.useCallback((fontFamily) => {
|
|
2794
|
+
if (fontFamily && SUPPORTED_FONTS.includes(fontFamily)) {
|
|
2795
|
+
return fontFamily;
|
|
2796
|
+
}
|
|
2797
|
+
return "Calibri";
|
|
2798
|
+
}, []);
|
|
2369
2799
|
const withBodySelection = React.useCallback(
|
|
2370
2800
|
(editor, action) => {
|
|
2371
2801
|
editor.update(() => {
|
|
@@ -2401,27 +2831,91 @@ const Toolbar = () => {
|
|
|
2401
2831
|
},
|
|
2402
2832
|
[runHistoryAction]
|
|
2403
2833
|
);
|
|
2834
|
+
React.useEffect(() => {
|
|
2835
|
+
if (!activeEditor) {
|
|
2836
|
+
setActiveBlockType("paragraph");
|
|
2837
|
+
setActiveFontFamily("Calibri");
|
|
2838
|
+
setActiveFontSize(DEFAULT_FONT_SIZE);
|
|
2839
|
+
return;
|
|
2840
|
+
}
|
|
2841
|
+
const updateSelectionState = () => {
|
|
2842
|
+
const selectedVariables = getSelectedVariableNodes(activeEditor);
|
|
2843
|
+
if (selectedVariables.length > 0) {
|
|
2844
|
+
const formatting = readSelectedVariableFormatting(activeEditor);
|
|
2845
|
+
setActiveBlockType("paragraph");
|
|
2846
|
+
setActiveFontFamily(normalizeFontFamily(formatting.fontFamily));
|
|
2847
|
+
setActiveFontSize(formatting.fontSize ?? DEFAULT_FONT_SIZE);
|
|
2848
|
+
return;
|
|
2849
|
+
}
|
|
2850
|
+
setActiveBlockType(getActiveBlockType(activeEditor));
|
|
2851
|
+
let nextFontFamily = "Calibri";
|
|
2852
|
+
let nextFontSize = DEFAULT_FONT_SIZE;
|
|
2853
|
+
activeEditor.getEditorState().read(() => {
|
|
2854
|
+
const selection2 = lexical.$getSelection();
|
|
2855
|
+
if (!lexical.$isRangeSelection(selection2)) {
|
|
2856
|
+
return;
|
|
2857
|
+
}
|
|
2858
|
+
const textNode = selection2.getNodes().find(lexical.$isTextNode);
|
|
2859
|
+
if (!textNode) {
|
|
2860
|
+
return;
|
|
2861
|
+
}
|
|
2862
|
+
const style = textNode.getStyle();
|
|
2863
|
+
nextFontFamily = normalizeFontFamily(extractFontFamilyFromStyle(style));
|
|
2864
|
+
nextFontSize = extractFontSizePtFromStyle(style) ?? DEFAULT_FONT_SIZE;
|
|
2865
|
+
});
|
|
2866
|
+
setActiveFontFamily(nextFontFamily);
|
|
2867
|
+
setActiveFontSize(nextFontSize);
|
|
2868
|
+
};
|
|
2869
|
+
updateSelectionState();
|
|
2870
|
+
const unregisterSelectionChange = activeEditor.registerCommand(
|
|
2871
|
+
lexical.SELECTION_CHANGE_COMMAND,
|
|
2872
|
+
() => {
|
|
2873
|
+
updateSelectionState();
|
|
2874
|
+
return false;
|
|
2875
|
+
},
|
|
2876
|
+
lexical.COMMAND_PRIORITY_LOW
|
|
2877
|
+
);
|
|
2878
|
+
const unregisterUpdateListener = activeEditor.registerUpdateListener(() => {
|
|
2879
|
+
updateSelectionState();
|
|
2880
|
+
});
|
|
2881
|
+
return () => {
|
|
2882
|
+
unregisterSelectionChange();
|
|
2883
|
+
unregisterUpdateListener();
|
|
2884
|
+
};
|
|
2885
|
+
}, [activeEditor, normalizeFontFamily]);
|
|
2404
2886
|
const handleBold = React.useCallback(() => {
|
|
2405
2887
|
debug("toolbar", `bold (globalSelection=${globalSelectionActive}, editors=${editorRegistry.all().length}, hasEditor=${!!activeEditor})`);
|
|
2406
2888
|
runToolbarAction(t.history.actions.boldApplied, () => {
|
|
2889
|
+
if (activeEditor && toggleSelectedVariableFormat(activeEditor, "bold")) {
|
|
2890
|
+
return;
|
|
2891
|
+
}
|
|
2407
2892
|
applyToBodyEditors(toggleBold);
|
|
2408
2893
|
});
|
|
2409
2894
|
}, [activeEditor, applyToBodyEditors, editorRegistry, globalSelectionActive, runToolbarAction, t.history.actions.boldApplied]);
|
|
2410
2895
|
const handleItalic = React.useCallback(() => {
|
|
2411
2896
|
debug("toolbar", `italic (globalSelection=${globalSelectionActive}, hasEditor=${!!activeEditor})`);
|
|
2412
2897
|
runToolbarAction(t.history.actions.italicApplied, () => {
|
|
2898
|
+
if (activeEditor && toggleSelectedVariableFormat(activeEditor, "italic")) {
|
|
2899
|
+
return;
|
|
2900
|
+
}
|
|
2413
2901
|
applyToBodyEditors(toggleItalic);
|
|
2414
2902
|
});
|
|
2415
2903
|
}, [activeEditor, applyToBodyEditors, globalSelectionActive, runToolbarAction, t.history.actions.italicApplied]);
|
|
2416
2904
|
const handleUnderline = React.useCallback(() => {
|
|
2417
2905
|
debug("toolbar", `underline (globalSelection=${globalSelectionActive}, hasEditor=${!!activeEditor})`);
|
|
2418
2906
|
runToolbarAction(t.history.actions.underlineApplied, () => {
|
|
2907
|
+
if (activeEditor && toggleSelectedVariableFormat(activeEditor, "underline")) {
|
|
2908
|
+
return;
|
|
2909
|
+
}
|
|
2419
2910
|
applyToBodyEditors(toggleUnderline);
|
|
2420
2911
|
});
|
|
2421
2912
|
}, [activeEditor, applyToBodyEditors, globalSelectionActive, runToolbarAction, t.history.actions.underlineApplied]);
|
|
2422
2913
|
const handleStrikethrough = React.useCallback(() => {
|
|
2423
2914
|
debug("toolbar", `strikethrough (globalSelection=${globalSelectionActive}, hasEditor=${!!activeEditor})`);
|
|
2424
2915
|
runToolbarAction(t.history.actions.strikethroughApplied, () => {
|
|
2916
|
+
if (activeEditor && toggleSelectedVariableFormat(activeEditor, "strikethrough")) {
|
|
2917
|
+
return;
|
|
2918
|
+
}
|
|
2425
2919
|
applyToBodyEditors(toggleStrikethrough);
|
|
2426
2920
|
});
|
|
2427
2921
|
}, [activeEditor, applyToBodyEditors, globalSelectionActive, runToolbarAction, t.history.actions.strikethroughApplied]);
|
|
@@ -2467,20 +2961,59 @@ const Toolbar = () => {
|
|
|
2467
2961
|
}, [applyToBodyEditors, runToolbarAction, t.history.actions.outdentedContent]);
|
|
2468
2962
|
const handleFontChange = React.useCallback(
|
|
2469
2963
|
(e) => {
|
|
2470
|
-
|
|
2471
|
-
|
|
2964
|
+
const fontFamily = e.target.value;
|
|
2965
|
+
runToolbarAction(interpolate(t.history.actions.fontChanged, { value: fontFamily }), () => {
|
|
2966
|
+
if (activeEditor && applyFontFamilyToSelectedVariables(activeEditor, fontFamily)) {
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2969
|
+
applyToBodyEditors((editor) => applyFontFamily(editor, fontFamily));
|
|
2472
2970
|
});
|
|
2473
2971
|
},
|
|
2474
|
-
[applyToBodyEditors, runToolbarAction, t.history.actions.fontChanged]
|
|
2972
|
+
[activeEditor, applyToBodyEditors, runToolbarAction, t.history.actions.fontChanged]
|
|
2475
2973
|
);
|
|
2476
2974
|
const handleFontSizeChange = React.useCallback(
|
|
2477
2975
|
(e) => {
|
|
2478
2976
|
const size = parseInt(e.target.value, 10);
|
|
2479
2977
|
runToolbarAction(interpolate(t.history.actions.fontSizeChanged, { value: String(size) }), () => {
|
|
2978
|
+
if (activeEditor && applyFontSizeToSelectedVariables(activeEditor, size)) {
|
|
2979
|
+
return;
|
|
2980
|
+
}
|
|
2480
2981
|
applyToBodyEditors((editor) => applyFontSize(editor, size));
|
|
2481
2982
|
});
|
|
2482
2983
|
},
|
|
2483
|
-
[applyToBodyEditors, runToolbarAction, t.history.actions.fontSizeChanged]
|
|
2984
|
+
[activeEditor, applyToBodyEditors, runToolbarAction, t.history.actions.fontSizeChanged]
|
|
2985
|
+
);
|
|
2986
|
+
const handleBlockTypeChange = React.useCallback(
|
|
2987
|
+
(e) => {
|
|
2988
|
+
const blockType = e.target.value;
|
|
2989
|
+
const labelMap = {
|
|
2990
|
+
paragraph: t.toolbar.paragraph,
|
|
2991
|
+
h1: t.toolbar.heading1,
|
|
2992
|
+
h2: t.toolbar.heading2,
|
|
2993
|
+
h3: t.toolbar.heading3,
|
|
2994
|
+
h4: t.toolbar.heading4,
|
|
2995
|
+
h5: t.toolbar.heading5,
|
|
2996
|
+
h6: t.toolbar.heading6
|
|
2997
|
+
};
|
|
2998
|
+
runToolbarAction(
|
|
2999
|
+
interpolate(t.history.actions.blockTypeChanged, { value: labelMap[blockType] }),
|
|
3000
|
+
() => {
|
|
3001
|
+
applyToBodyEditors((editor) => setBlockType(editor, blockType));
|
|
3002
|
+
}
|
|
3003
|
+
);
|
|
3004
|
+
},
|
|
3005
|
+
[
|
|
3006
|
+
applyToBodyEditors,
|
|
3007
|
+
runToolbarAction,
|
|
3008
|
+
t.history.actions.blockTypeChanged,
|
|
3009
|
+
t.toolbar.heading1,
|
|
3010
|
+
t.toolbar.heading2,
|
|
3011
|
+
t.toolbar.heading3,
|
|
3012
|
+
t.toolbar.heading4,
|
|
3013
|
+
t.toolbar.heading5,
|
|
3014
|
+
t.toolbar.heading6,
|
|
3015
|
+
t.toolbar.paragraph
|
|
3016
|
+
]
|
|
2484
3017
|
);
|
|
2485
3018
|
const handleToggleHistory = React.useCallback(() => {
|
|
2486
3019
|
setHistorySidebarOpen(!historySidebarOpen);
|
|
@@ -2514,6 +3047,26 @@ const Toolbar = () => {
|
|
|
2514
3047
|
)
|
|
2515
3048
|
] }),
|
|
2516
3049
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
3050
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-toolbar-group-gap lex4-toolbar-group-block", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3051
|
+
"select",
|
|
3052
|
+
{
|
|
3053
|
+
className: "lex4-toolbar-select lex4-toolbar-select-block",
|
|
3054
|
+
"data-testid": "block-type-selector",
|
|
3055
|
+
"aria-label": t.toolbar.blockType,
|
|
3056
|
+
value: activeBlockType,
|
|
3057
|
+
onChange: handleBlockTypeChange,
|
|
3058
|
+
children: [
|
|
3059
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "paragraph", children: t.toolbar.paragraph }),
|
|
3060
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "h1", children: t.toolbar.heading1 }),
|
|
3061
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "h2", children: t.toolbar.heading2 }),
|
|
3062
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "h3", children: t.toolbar.heading3 }),
|
|
3063
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "h4", children: t.toolbar.heading4 }),
|
|
3064
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "h5", children: t.toolbar.heading5 }),
|
|
3065
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "h6", children: t.toolbar.heading6 })
|
|
3066
|
+
]
|
|
3067
|
+
}
|
|
3068
|
+
) }),
|
|
3069
|
+
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2517
3070
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group-gap", children: [
|
|
2518
3071
|
/* @__PURE__ */ jsxRuntime.jsx(Type, { size: 14, className: "lex4-toolbar-icon" }),
|
|
2519
3072
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2521,7 +3074,7 @@ const Toolbar = () => {
|
|
|
2521
3074
|
{
|
|
2522
3075
|
className: "lex4-toolbar-select",
|
|
2523
3076
|
"data-testid": "font-selector",
|
|
2524
|
-
|
|
3077
|
+
value: activeFontFamily,
|
|
2525
3078
|
onChange: handleFontChange,
|
|
2526
3079
|
children: SUPPORTED_FONTS.map((font) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: font, style: { fontFamily: font }, children: font }, font))
|
|
2527
3080
|
}
|
|
@@ -2534,7 +3087,7 @@ const Toolbar = () => {
|
|
|
2534
3087
|
{
|
|
2535
3088
|
className: "lex4-toolbar-select lex4-toolbar-select-narrow",
|
|
2536
3089
|
"data-testid": "font-size-selector",
|
|
2537
|
-
|
|
3090
|
+
value: String(activeFontSize),
|
|
2538
3091
|
onChange: handleFontSizeChange,
|
|
2539
3092
|
children: SUPPORTED_FONT_SIZES.map((size) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: size, children: size }, size))
|
|
2540
3093
|
}
|
|
@@ -2569,7 +3122,7 @@ const Toolbar = () => {
|
|
|
2569
3122
|
/* @__PURE__ */ jsxRuntime.jsx(CanvasControls, {}),
|
|
2570
3123
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-end", children: [
|
|
2571
3124
|
toolbarEndItems.map((EndItem, idx) => /* @__PURE__ */ jsxRuntime.jsx(EndItem, {}, idx)),
|
|
2572
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3125
|
+
toolbarConfig.history.visible && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2573
3126
|
"button",
|
|
2574
3127
|
{
|
|
2575
3128
|
type: "button",
|
|
@@ -2581,7 +3134,7 @@ const Toolbar = () => {
|
|
|
2581
3134
|
"aria-label": historySidebarOpen ? t.toolbar.closeHistory : t.toolbar.openHistory,
|
|
2582
3135
|
children: [
|
|
2583
3136
|
/* @__PURE__ */ jsxRuntime.jsx(History, { size: 14 }),
|
|
2584
|
-
|
|
3137
|
+
toolbarConfig.history.showLabel && t.toolbar.history
|
|
2585
3138
|
]
|
|
2586
3139
|
}
|
|
2587
3140
|
)
|
|
@@ -2925,7 +3478,8 @@ const lexicalTheme = {
|
|
|
2925
3478
|
h2: "lex4-heading lex4-heading-h2",
|
|
2926
3479
|
h3: "lex4-heading lex4-heading-h3",
|
|
2927
3480
|
h4: "lex4-heading lex4-heading-h4",
|
|
2928
|
-
h5: "lex4-heading lex4-heading-h5"
|
|
3481
|
+
h5: "lex4-heading lex4-heading-h5",
|
|
3482
|
+
h6: "lex4-heading lex4-heading-h6"
|
|
2929
3483
|
},
|
|
2930
3484
|
text: {
|
|
2931
3485
|
bold: "lex4-text-bold",
|
|
@@ -4462,12 +5016,10 @@ function decodeFormatBitmask(format) {
|
|
|
4462
5016
|
return marks;
|
|
4463
5017
|
}
|
|
4464
5018
|
function extractFontFamily(style) {
|
|
4465
|
-
|
|
4466
|
-
return match ? match[1].trim().replace(/['"]/g, "") : void 0;
|
|
5019
|
+
return extractFontFamilyFromStyle(style);
|
|
4467
5020
|
}
|
|
4468
5021
|
function extractFontSizePt(style) {
|
|
4469
|
-
|
|
4470
|
-
return match ? parseFloat(match[1]) : void 0;
|
|
5022
|
+
return extractFontSizePtFromStyle(style);
|
|
4471
5023
|
}
|
|
4472
5024
|
function buildTextMarks(format, style) {
|
|
4473
5025
|
const formatMarks = decodeFormatBitmask(format);
|
|
@@ -4501,9 +5053,11 @@ function mapTextNode(node) {
|
|
|
4501
5053
|
};
|
|
4502
5054
|
}
|
|
4503
5055
|
function mapVariableNode(node) {
|
|
5056
|
+
const marks = buildTextMarks(node.format ?? 0, node.style);
|
|
4504
5057
|
return {
|
|
4505
5058
|
type: "variable",
|
|
4506
|
-
key: node.variableKey
|
|
5059
|
+
key: node.variableKey,
|
|
5060
|
+
...marks ? { marks } : {}
|
|
4507
5061
|
};
|
|
4508
5062
|
}
|
|
4509
5063
|
function mapLineBreak() {
|
|
@@ -4567,7 +5121,7 @@ function mapParagraph(node) {
|
|
|
4567
5121
|
function mapHeading(node) {
|
|
4568
5122
|
var _a;
|
|
4569
5123
|
const alignment = decodeAlignment(node.format);
|
|
4570
|
-
const tagMatch = (_a = node.tag) == null ? void 0 : _a.match(/^h(
|
|
5124
|
+
const tagMatch = (_a = node.tag) == null ? void 0 : _a.match(/^h([1-6])$/);
|
|
4571
5125
|
const level = tagMatch ? parseInt(tagMatch[1], 10) : 1;
|
|
4572
5126
|
return {
|
|
4573
5127
|
type: "heading",
|
|
@@ -4692,6 +5246,105 @@ function buildSavePayload(ast, options) {
|
|
|
4692
5246
|
function serializeDocumentJson(ast) {
|
|
4693
5247
|
return JSON.stringify(ast, null, 2);
|
|
4694
5248
|
}
|
|
5249
|
+
function appendChildren(parent, children = []) {
|
|
5250
|
+
const nodes = children.map(buildLexicalNode).filter((node) => node !== null);
|
|
5251
|
+
if (nodes.length > 0) {
|
|
5252
|
+
parent.append(...nodes);
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5255
|
+
function applyElementFormatting(node, serializedNode) {
|
|
5256
|
+
if (typeof serializedNode.format === "string" && ["left", "center", "right", "justify"].includes(serializedNode.format) && node.setFormat) {
|
|
5257
|
+
node.setFormat(serializedNode.format);
|
|
5258
|
+
}
|
|
5259
|
+
if (typeof serializedNode.indent === "number" && serializedNode.indent > 0 && node.setIndent) {
|
|
5260
|
+
node.setIndent(serializedNode.indent);
|
|
5261
|
+
}
|
|
5262
|
+
}
|
|
5263
|
+
function buildLexicalNode(serializedNode) {
|
|
5264
|
+
switch (serializedNode.type) {
|
|
5265
|
+
case "paragraph": {
|
|
5266
|
+
const node = lexical.$createParagraphNode();
|
|
5267
|
+
applyElementFormatting(node, serializedNode);
|
|
5268
|
+
appendChildren(node, serializedNode.children);
|
|
5269
|
+
return node;
|
|
5270
|
+
}
|
|
5271
|
+
case "heading": {
|
|
5272
|
+
const tag = typeof serializedNode.tag === "string" && /^h[1-6]$/.test(serializedNode.tag) ? serializedNode.tag : "h1";
|
|
5273
|
+
const node = richText.$createHeadingNode(tag);
|
|
5274
|
+
applyElementFormatting(node, serializedNode);
|
|
5275
|
+
appendChildren(node, serializedNode.children);
|
|
5276
|
+
return node;
|
|
5277
|
+
}
|
|
5278
|
+
case "quote": {
|
|
5279
|
+
const node = richText.$createQuoteNode();
|
|
5280
|
+
applyElementFormatting(node, serializedNode);
|
|
5281
|
+
appendChildren(node, serializedNode.children);
|
|
5282
|
+
return node;
|
|
5283
|
+
}
|
|
5284
|
+
case "list": {
|
|
5285
|
+
const listType = serializedNode.listType === "number" ? "number" : "bullet";
|
|
5286
|
+
const node = list.$createListNode(listType, typeof serializedNode.start === "number" ? serializedNode.start : 1);
|
|
5287
|
+
appendChildren(node, serializedNode.children);
|
|
5288
|
+
return node;
|
|
5289
|
+
}
|
|
5290
|
+
case "listitem": {
|
|
5291
|
+
const node = list.$createListItemNode();
|
|
5292
|
+
appendChildren(node, serializedNode.children);
|
|
5293
|
+
return node;
|
|
5294
|
+
}
|
|
5295
|
+
case "text": {
|
|
5296
|
+
const node = lexical.$createTextNode(serializedNode.text ?? "");
|
|
5297
|
+
if (typeof serializedNode.format === "number" && serializedNode.format > 0) {
|
|
5298
|
+
node.setFormat(serializedNode.format);
|
|
5299
|
+
}
|
|
5300
|
+
if (typeof serializedNode.style === "string" && serializedNode.style.trim() !== "") {
|
|
5301
|
+
node.setStyle(serializedNode.style);
|
|
5302
|
+
}
|
|
5303
|
+
return node;
|
|
5304
|
+
}
|
|
5305
|
+
case "linebreak":
|
|
5306
|
+
return lexical.$createLineBreakNode();
|
|
5307
|
+
case "variable-node":
|
|
5308
|
+
return $createVariableNode(
|
|
5309
|
+
serializedNode.variableKey ?? "",
|
|
5310
|
+
typeof serializedNode.format === "number" ? serializedNode.format : 0,
|
|
5311
|
+
typeof serializedNode.style === "string" ? serializedNode.style : ""
|
|
5312
|
+
);
|
|
5313
|
+
default:
|
|
5314
|
+
return null;
|
|
5315
|
+
}
|
|
5316
|
+
}
|
|
5317
|
+
function getBodyChildren(pageState) {
|
|
5318
|
+
const root = pageState == null ? void 0 : pageState.root;
|
|
5319
|
+
return (root == null ? void 0 : root.children) ?? [];
|
|
5320
|
+
}
|
|
5321
|
+
function insertDocumentContent(editor, document2) {
|
|
5322
|
+
let inserted = false;
|
|
5323
|
+
editor.update(() => {
|
|
5324
|
+
const nodes = document2.pages.flatMap((page) => getBodyChildren(page.bodyState)).map(buildLexicalNode).filter((node) => node !== null);
|
|
5325
|
+
if (nodes.length === 0) {
|
|
5326
|
+
return;
|
|
5327
|
+
}
|
|
5328
|
+
const selection2 = lexical.$getSelection();
|
|
5329
|
+
if (lexical.$isRangeSelection(selection2)) {
|
|
5330
|
+
if (selection2.isCollapsed()) {
|
|
5331
|
+
selection2.insertParagraph();
|
|
5332
|
+
}
|
|
5333
|
+
const nextSelection = lexical.$getSelection();
|
|
5334
|
+
if (lexical.$isRangeSelection(nextSelection) || lexical.$isNodeSelection(nextSelection)) {
|
|
5335
|
+
nextSelection.insertNodes(nodes);
|
|
5336
|
+
} else {
|
|
5337
|
+
lexical.$insertNodes(nodes);
|
|
5338
|
+
}
|
|
5339
|
+
} else if (lexical.$isNodeSelection(selection2)) {
|
|
5340
|
+
selection2.insertNodes(nodes);
|
|
5341
|
+
} else {
|
|
5342
|
+
lexical.$insertNodes(nodes);
|
|
5343
|
+
}
|
|
5344
|
+
inserted = true;
|
|
5345
|
+
});
|
|
5346
|
+
return inserted;
|
|
5347
|
+
}
|
|
4695
5348
|
function selectEntireDocument(rootElement, selectionBuffer) {
|
|
4696
5349
|
if (!rootElement || !selectionBuffer) {
|
|
4697
5350
|
return;
|
|
@@ -4898,10 +5551,13 @@ const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, on
|
|
|
4898
5551
|
const {
|
|
4899
5552
|
document: doc,
|
|
4900
5553
|
activeEditor,
|
|
5554
|
+
activeCaretPosition,
|
|
4901
5555
|
historySidebarOpen,
|
|
5556
|
+
runHistoryAction,
|
|
4902
5557
|
setHistorySidebarOpen
|
|
4903
5558
|
} = useDocument();
|
|
4904
5559
|
const { handleFactories } = useExtensions();
|
|
5560
|
+
const t = useTranslations();
|
|
4905
5561
|
const getDocument = React.useCallback(() => doc, [doc]);
|
|
4906
5562
|
const getActiveEditor = React.useCallback(() => activeEditor, [activeEditor]);
|
|
4907
5563
|
const extensionCtx = useExtensionContext(getDocument, getActiveEditor);
|
|
@@ -4912,6 +5568,23 @@ const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, on
|
|
|
4912
5568
|
},
|
|
4913
5569
|
toggleHistorySidebar: () => {
|
|
4914
5570
|
setHistorySidebarOpen(!historySidebarOpen);
|
|
5571
|
+
},
|
|
5572
|
+
insertDocumentContent: (documentToInsert) => {
|
|
5573
|
+
if (!activeEditor || (activeCaretPosition == null ? void 0 : activeCaretPosition.region) !== "body") {
|
|
5574
|
+
return false;
|
|
5575
|
+
}
|
|
5576
|
+
let inserted = false;
|
|
5577
|
+
runHistoryAction(
|
|
5578
|
+
{
|
|
5579
|
+
label: t.history.actions.insertedDocumentContent,
|
|
5580
|
+
source: "toolbar",
|
|
5581
|
+
region: "document"
|
|
5582
|
+
},
|
|
5583
|
+
() => {
|
|
5584
|
+
inserted = insertDocumentContent(activeEditor, documentToInsert);
|
|
5585
|
+
}
|
|
5586
|
+
);
|
|
5587
|
+
return inserted;
|
|
4915
5588
|
}
|
|
4916
5589
|
};
|
|
4917
5590
|
for (const factory of handleFactories) {
|
|
@@ -4919,7 +5592,16 @@ const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, on
|
|
|
4919
5592
|
Object.assign(handle, methods);
|
|
4920
5593
|
}
|
|
4921
5594
|
return handle;
|
|
4922
|
-
}, [
|
|
5595
|
+
}, [
|
|
5596
|
+
activeCaretPosition == null ? void 0 : activeCaretPosition.region,
|
|
5597
|
+
activeEditor,
|
|
5598
|
+
extensionCtx,
|
|
5599
|
+
handleFactories,
|
|
5600
|
+
historySidebarOpen,
|
|
5601
|
+
runHistoryAction,
|
|
5602
|
+
setHistorySidebarOpen,
|
|
5603
|
+
t.history.actions.insertedDocumentContent
|
|
5604
|
+
]);
|
|
4923
5605
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4924
5606
|
EditorChrome,
|
|
4925
5607
|
{
|
|
@@ -4937,9 +5619,10 @@ const Lex4Editor = React.forwardRef(({
|
|
|
4937
5619
|
onSave,
|
|
4938
5620
|
extensions,
|
|
4939
5621
|
translations,
|
|
5622
|
+
toolbar,
|
|
4940
5623
|
className
|
|
4941
5624
|
}, ref) => {
|
|
4942
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TranslationsProvider, { translations, children: /* @__PURE__ */ jsxRuntime.jsx(ExtensionStateProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(ExtensionProvider, { extensions, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5625
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TranslationsProvider, { translations, children: /* @__PURE__ */ jsxRuntime.jsx(ToolbarConfigProvider, { toolbar, children: /* @__PURE__ */ jsxRuntime.jsx(ExtensionStateProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(ExtensionProvider, { extensions, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4943
5626
|
DocumentProvider,
|
|
4944
5627
|
{
|
|
4945
5628
|
initialDocument,
|
|
@@ -4954,7 +5637,7 @@ const Lex4Editor = React.forwardRef(({
|
|
|
4954
5637
|
}
|
|
4955
5638
|
)
|
|
4956
5639
|
}
|
|
4957
|
-
) }) }) });
|
|
5640
|
+
) }) }) }) });
|
|
4958
5641
|
});
|
|
4959
5642
|
Lex4Editor.displayName = "Lex4Editor";
|
|
4960
5643
|
function useOverflowDetection(bodyHeight, onOverflow, debounceMs = 100) {
|
|
@@ -5048,120 +5731,6 @@ function astExtension() {
|
|
|
5048
5731
|
}
|
|
5049
5732
|
};
|
|
5050
5733
|
}
|
|
5051
|
-
const EMPTY_CONTEXT = {
|
|
5052
|
-
definitions: [],
|
|
5053
|
-
refreshDefinitions: () => {
|
|
5054
|
-
},
|
|
5055
|
-
getDefinition: () => void 0
|
|
5056
|
-
};
|
|
5057
|
-
const VariableContext = React.createContext(EMPTY_CONTEXT);
|
|
5058
|
-
const VariableProvider = ({
|
|
5059
|
-
initialDefinitions = [],
|
|
5060
|
-
children
|
|
5061
|
-
}) => {
|
|
5062
|
-
const [definitions, setDefinitions] = React.useState(initialDefinitions);
|
|
5063
|
-
const refresh = React.useCallback((newDefinitions) => {
|
|
5064
|
-
setDefinitions(newDefinitions);
|
|
5065
|
-
}, []);
|
|
5066
|
-
const getDefinition = React.useCallback(
|
|
5067
|
-
(key) => {
|
|
5068
|
-
return definitions.find((d) => d.key === key);
|
|
5069
|
-
},
|
|
5070
|
-
[definitions]
|
|
5071
|
-
);
|
|
5072
|
-
const value = React.useMemo(
|
|
5073
|
-
() => ({ definitions, refreshDefinitions: refresh, getDefinition }),
|
|
5074
|
-
[definitions, refresh, getDefinition]
|
|
5075
|
-
);
|
|
5076
|
-
return /* @__PURE__ */ jsxRuntime.jsx(VariableContext.Provider, { value, children });
|
|
5077
|
-
};
|
|
5078
|
-
function useVariables() {
|
|
5079
|
-
return React.useContext(VariableContext);
|
|
5080
|
-
}
|
|
5081
|
-
class VariableNode extends lexical.DecoratorNode {
|
|
5082
|
-
constructor(variableKey, key) {
|
|
5083
|
-
super(key);
|
|
5084
|
-
__publicField(this, "__variableKey");
|
|
5085
|
-
this.__variableKey = variableKey;
|
|
5086
|
-
}
|
|
5087
|
-
static getType() {
|
|
5088
|
-
return "variable-node";
|
|
5089
|
-
}
|
|
5090
|
-
static clone(node) {
|
|
5091
|
-
return new VariableNode(node.__variableKey, node.__key);
|
|
5092
|
-
}
|
|
5093
|
-
getVariableKey() {
|
|
5094
|
-
return this.__variableKey;
|
|
5095
|
-
}
|
|
5096
|
-
// -- Serialization --
|
|
5097
|
-
static importJSON(serializedNode) {
|
|
5098
|
-
return $createVariableNode(serializedNode.variableKey);
|
|
5099
|
-
}
|
|
5100
|
-
exportJSON() {
|
|
5101
|
-
return {
|
|
5102
|
-
type: "variable-node",
|
|
5103
|
-
version: 1,
|
|
5104
|
-
variableKey: this.__variableKey
|
|
5105
|
-
};
|
|
5106
|
-
}
|
|
5107
|
-
// -- DOM --
|
|
5108
|
-
createDOM() {
|
|
5109
|
-
const span = document.createElement("span");
|
|
5110
|
-
span.className = "lex4-variable";
|
|
5111
|
-
span.setAttribute("data-variable-key", this.__variableKey);
|
|
5112
|
-
span.setAttribute("data-testid", `variable-${this.__variableKey}`);
|
|
5113
|
-
span.contentEditable = "false";
|
|
5114
|
-
return span;
|
|
5115
|
-
}
|
|
5116
|
-
updateDOM() {
|
|
5117
|
-
return false;
|
|
5118
|
-
}
|
|
5119
|
-
exportDOM() {
|
|
5120
|
-
const span = document.createElement("span");
|
|
5121
|
-
span.setAttribute("data-variable-key", this.__variableKey);
|
|
5122
|
-
span.textContent = `{{${this.__variableKey}}}`;
|
|
5123
|
-
return { element: span };
|
|
5124
|
-
}
|
|
5125
|
-
static importDOM() {
|
|
5126
|
-
return null;
|
|
5127
|
-
}
|
|
5128
|
-
// -- Behavior --
|
|
5129
|
-
isInline() {
|
|
5130
|
-
return true;
|
|
5131
|
-
}
|
|
5132
|
-
isKeyboardSelectable() {
|
|
5133
|
-
return true;
|
|
5134
|
-
}
|
|
5135
|
-
getTextContent() {
|
|
5136
|
-
return `{{${this.__variableKey}}}`;
|
|
5137
|
-
}
|
|
5138
|
-
// -- Rendering --
|
|
5139
|
-
decorate() {
|
|
5140
|
-
return /* @__PURE__ */ jsxRuntime.jsx(VariableChip, { variableKey: this.__variableKey });
|
|
5141
|
-
}
|
|
5142
|
-
}
|
|
5143
|
-
function VariableChip({ variableKey }) {
|
|
5144
|
-
const { getDefinition } = useVariables();
|
|
5145
|
-
const def = getDefinition(variableKey);
|
|
5146
|
-
const label = (def == null ? void 0 : def.label) ?? variableKey;
|
|
5147
|
-
const group = def == null ? void 0 : def.group;
|
|
5148
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5149
|
-
"span",
|
|
5150
|
-
{
|
|
5151
|
-
className: "lex4-variable-chip",
|
|
5152
|
-
"data-testid": `variable-chip-${variableKey}`,
|
|
5153
|
-
"data-variable-group": group,
|
|
5154
|
-
title: variableKey,
|
|
5155
|
-
children: label
|
|
5156
|
-
}
|
|
5157
|
-
);
|
|
5158
|
-
}
|
|
5159
|
-
function $createVariableNode(variableKey) {
|
|
5160
|
-
return lexical.$applyNodeReplacement(new VariableNode(variableKey));
|
|
5161
|
-
}
|
|
5162
|
-
function $isVariableNode(node) {
|
|
5163
|
-
return node instanceof VariableNode;
|
|
5164
|
-
}
|
|
5165
5734
|
const INSERT_VARIABLE_COMMAND = lexical.createCommand("INSERT_VARIABLE");
|
|
5166
5735
|
const VariablePlugin = () => {
|
|
5167
5736
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
@@ -5170,8 +5739,8 @@ const VariablePlugin = () => {
|
|
|
5170
5739
|
INSERT_VARIABLE_COMMAND,
|
|
5171
5740
|
(variableKey) => {
|
|
5172
5741
|
editor.update(() => {
|
|
5173
|
-
const
|
|
5174
|
-
if (!lexical.$isRangeSelection(
|
|
5742
|
+
const selection2 = lexical.$getSelection();
|
|
5743
|
+
if (!lexical.$isRangeSelection(selection2)) return;
|
|
5175
5744
|
const variableNode = $createVariableNode(variableKey);
|
|
5176
5745
|
lexical.$insertNodes([variableNode]);
|
|
5177
5746
|
});
|
|
@@ -5422,7 +5991,11 @@ const VariablePanelStateProvider = ({ children }) => {
|
|
|
5422
5991
|
};
|
|
5423
5992
|
const VariableToolbarToggle = () => {
|
|
5424
5993
|
const { panelOpen, setPanelOpen } = useVariablePanelState();
|
|
5994
|
+
const toolbarConfig = useToolbarConfig();
|
|
5425
5995
|
const t = useTranslations();
|
|
5996
|
+
if (!toolbarConfig.variables.visible) {
|
|
5997
|
+
return null;
|
|
5998
|
+
}
|
|
5426
5999
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5427
6000
|
"button",
|
|
5428
6001
|
{
|
|
@@ -5435,7 +6008,7 @@ const VariableToolbarToggle = () => {
|
|
|
5435
6008
|
"aria-label": panelOpen ? t.variables.closePanel : t.variables.openPanel,
|
|
5436
6009
|
children: [
|
|
5437
6010
|
/* @__PURE__ */ jsxRuntime.jsx(Braces, { size: 14 }),
|
|
5438
|
-
t.variables.title
|
|
6011
|
+
toolbarConfig.variables.showLabel && t.variables.title
|
|
5439
6012
|
]
|
|
5440
6013
|
}
|
|
5441
6014
|
);
|