@yurikilian/lex4 1.6.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/README.md +4 -2
- package/dist/components/BlockTypePicker.d.ts +1 -1
- package/dist/components/BlockTypePicker.d.ts.map +1 -1
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/context/document-provider.d.ts.map +1 -1
- package/dist/context/toolbar-style-snapshot.d.ts +4 -0
- package/dist/context/toolbar-style-snapshot.d.ts.map +1 -0
- package/dist/context/toolbar-style-store.d.ts +28 -0
- package/dist/context/toolbar-style-store.d.ts.map +1 -0
- package/dist/lex4-editor.cjs +544 -161
- package/dist/lex4-editor.cjs.map +1 -1
- package/dist/lex4-editor.js +547 -164
- package/dist/lex4-editor.js.map +1 -1
- package/dist/lexical/commands/block-commands.d.ts +1 -1
- package/dist/lexical/commands/block-commands.d.ts.map +1 -1
- package/dist/lexical/commands/block-types.d.ts +2 -0
- package/dist/lexical/commands/block-types.d.ts.map +1 -0
- package/dist/style.css +31 -27
- package/dist/utils/text-style.d.ts +6 -0
- package/dist/utils/text-style.d.ts.map +1 -1
- 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 +3 -2
package/dist/lex4-editor.cjs
CHANGED
|
@@ -779,6 +779,115 @@ const TranslationsProvider = ({
|
|
|
779
779
|
);
|
|
780
780
|
return /* @__PURE__ */ jsxRuntime.jsx(TranslationsContext.Provider, { value: merged, children });
|
|
781
781
|
};
|
|
782
|
+
const createStoreImpl = (createState) => {
|
|
783
|
+
let state;
|
|
784
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
785
|
+
const setState = (partial, replace) => {
|
|
786
|
+
const nextState = typeof partial === "function" ? partial(state) : partial;
|
|
787
|
+
if (!Object.is(nextState, state)) {
|
|
788
|
+
const previousState = state;
|
|
789
|
+
state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
|
|
790
|
+
listeners.forEach((listener) => listener(state, previousState));
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
const getState = () => state;
|
|
794
|
+
const getInitialState = () => initialState;
|
|
795
|
+
const subscribe = (listener) => {
|
|
796
|
+
listeners.add(listener);
|
|
797
|
+
return () => listeners.delete(listener);
|
|
798
|
+
};
|
|
799
|
+
const api = { setState, getState, getInitialState, subscribe };
|
|
800
|
+
const initialState = state = createState(setState, getState, api);
|
|
801
|
+
return api;
|
|
802
|
+
};
|
|
803
|
+
const createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
|
|
804
|
+
const identity = (arg) => arg;
|
|
805
|
+
function useStore(api, selector = identity) {
|
|
806
|
+
const slice = React.useSyncExternalStore(
|
|
807
|
+
api.subscribe,
|
|
808
|
+
React.useCallback(() => selector(api.getState()), [api, selector]),
|
|
809
|
+
React.useCallback(() => selector(api.getInitialState()), [api, selector])
|
|
810
|
+
);
|
|
811
|
+
React.useDebugValue(slice);
|
|
812
|
+
return slice;
|
|
813
|
+
}
|
|
814
|
+
const SUPPORTED_FONT_SIZES = [
|
|
815
|
+
8,
|
|
816
|
+
9,
|
|
817
|
+
10,
|
|
818
|
+
11,
|
|
819
|
+
12,
|
|
820
|
+
14,
|
|
821
|
+
16,
|
|
822
|
+
18,
|
|
823
|
+
20,
|
|
824
|
+
24,
|
|
825
|
+
28,
|
|
826
|
+
32,
|
|
827
|
+
36,
|
|
828
|
+
48,
|
|
829
|
+
72
|
|
830
|
+
];
|
|
831
|
+
const DEFAULT_FONT_SIZE = 12;
|
|
832
|
+
function applyFontSize(editor, size) {
|
|
833
|
+
editor.update(() => {
|
|
834
|
+
const selection2 = lexical.$getSelection();
|
|
835
|
+
if (!lexical.$isRangeSelection(selection2)) return;
|
|
836
|
+
const nodes = selection2.getNodes();
|
|
837
|
+
for (const node of nodes) {
|
|
838
|
+
if (lexical.$isTextNode(node)) {
|
|
839
|
+
const existing = node.getStyle();
|
|
840
|
+
const updated = mergeFontSize(existing, size);
|
|
841
|
+
node.setStyle(updated);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
function mergeFontSize(existingStyle, size) {
|
|
847
|
+
const stripped = existingStyle.replace(/font-size:\s*[^;]+;?\s*/g, "").trim();
|
|
848
|
+
const sizeDecl = `font-size: ${size}pt`;
|
|
849
|
+
return stripped ? `${stripped}; ${sizeDecl}` : sizeDecl;
|
|
850
|
+
}
|
|
851
|
+
const DEFAULT_TOOLBAR_STYLE_SNAPSHOT = {
|
|
852
|
+
blockType: "paragraph",
|
|
853
|
+
fontFamily: "Inter",
|
|
854
|
+
fontSize: DEFAULT_FONT_SIZE,
|
|
855
|
+
alignment: "left",
|
|
856
|
+
isBold: false,
|
|
857
|
+
isItalic: false,
|
|
858
|
+
isUnderline: false,
|
|
859
|
+
isStrikethrough: false,
|
|
860
|
+
hasSelectedVariable: false
|
|
861
|
+
};
|
|
862
|
+
function createToolbarStyleStore(initialSnapshot = DEFAULT_TOOLBAR_STYLE_SNAPSHOT) {
|
|
863
|
+
return createStore((set) => ({
|
|
864
|
+
...initialSnapshot,
|
|
865
|
+
setSnapshot: (snapshot) => set(snapshot),
|
|
866
|
+
reset: () => set(DEFAULT_TOOLBAR_STYLE_SNAPSHOT)
|
|
867
|
+
}));
|
|
868
|
+
}
|
|
869
|
+
const ToolbarStyleStoreContext = React.createContext(null);
|
|
870
|
+
const ToolbarStyleStoreProvider = ({ children }) => {
|
|
871
|
+
const storeRef = React.useRef(null);
|
|
872
|
+
if (!storeRef.current) {
|
|
873
|
+
storeRef.current = createToolbarStyleStore();
|
|
874
|
+
}
|
|
875
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ToolbarStyleStoreContext.Provider, { value: storeRef.current, children });
|
|
876
|
+
};
|
|
877
|
+
function useToolbarStyleStore(selector) {
|
|
878
|
+
const store = React.useContext(ToolbarStyleStoreContext);
|
|
879
|
+
if (!store) {
|
|
880
|
+
throw new Error("useToolbarStyleStore must be used within a ToolbarStyleStoreProvider");
|
|
881
|
+
}
|
|
882
|
+
return useStore(store, selector);
|
|
883
|
+
}
|
|
884
|
+
function useToolbarStyleStoreApi() {
|
|
885
|
+
const store = React.useContext(ToolbarStyleStoreContext);
|
|
886
|
+
if (!store) {
|
|
887
|
+
throw new Error("useToolbarStyleStoreApi must be used within a ToolbarStyleStoreProvider");
|
|
888
|
+
}
|
|
889
|
+
return store;
|
|
890
|
+
}
|
|
782
891
|
const HISTORY_RESTORE_SUPPRESSION_MS = 100;
|
|
783
892
|
const HISTORY_BATCH_FLUSH_MS = 16;
|
|
784
893
|
function cloneDocumentSnapshot(document2) {
|
|
@@ -1335,7 +1444,7 @@ const DocumentProvider = ({
|
|
|
1335
1444
|
undo,
|
|
1336
1445
|
redo,
|
|
1337
1446
|
editorRegistry
|
|
1338
|
-
}, children });
|
|
1447
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsx(ToolbarStyleStoreProvider, { children }) });
|
|
1339
1448
|
};
|
|
1340
1449
|
/**
|
|
1341
1450
|
* @license lucide-react v1.8.0 - ISC
|
|
@@ -2083,43 +2192,6 @@ function applyFontFamily(editor, fontFamily) {
|
|
|
2083
2192
|
}
|
|
2084
2193
|
});
|
|
2085
2194
|
}
|
|
2086
|
-
const SUPPORTED_FONT_SIZES = [
|
|
2087
|
-
8,
|
|
2088
|
-
9,
|
|
2089
|
-
10,
|
|
2090
|
-
11,
|
|
2091
|
-
12,
|
|
2092
|
-
14,
|
|
2093
|
-
16,
|
|
2094
|
-
18,
|
|
2095
|
-
20,
|
|
2096
|
-
24,
|
|
2097
|
-
28,
|
|
2098
|
-
32,
|
|
2099
|
-
36,
|
|
2100
|
-
48,
|
|
2101
|
-
72
|
|
2102
|
-
];
|
|
2103
|
-
const DEFAULT_FONT_SIZE = 12;
|
|
2104
|
-
function applyFontSize(editor, size) {
|
|
2105
|
-
editor.update(() => {
|
|
2106
|
-
const selection2 = lexical.$getSelection();
|
|
2107
|
-
if (!lexical.$isRangeSelection(selection2)) return;
|
|
2108
|
-
const nodes = selection2.getNodes();
|
|
2109
|
-
for (const node of nodes) {
|
|
2110
|
-
if (lexical.$isTextNode(node)) {
|
|
2111
|
-
const existing = node.getStyle();
|
|
2112
|
-
const updated = mergeFontSize(existing, size);
|
|
2113
|
-
node.setStyle(updated);
|
|
2114
|
-
}
|
|
2115
|
-
}
|
|
2116
|
-
});
|
|
2117
|
-
}
|
|
2118
|
-
function mergeFontSize(existingStyle, size) {
|
|
2119
|
-
const stripped = existingStyle.replace(/font-size:\s*[^;]+;?\s*/g, "").trim();
|
|
2120
|
-
const sizeDecl = `font-size: ${size}pt`;
|
|
2121
|
-
return stripped ? `${stripped}; ${sizeDecl}` : sizeDecl;
|
|
2122
|
-
}
|
|
2123
2195
|
function toggleFormat(editor, format) {
|
|
2124
2196
|
editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, format);
|
|
2125
2197
|
}
|
|
@@ -2151,48 +2223,77 @@ function indentContent(editor) {
|
|
|
2151
2223
|
function outdentContent(editor) {
|
|
2152
2224
|
editor.dispatchCommand(lexical.OUTDENT_CONTENT_COMMAND, void 0);
|
|
2153
2225
|
}
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
}
|
|
2226
|
+
const INLINE_BLOCK_STYLE_PROPERTY = "--lex4-block-type";
|
|
2227
|
+
const INLINE_BLOCK_STYLE_PRESETS = {
|
|
2228
|
+
paragraph: {
|
|
2229
|
+
[INLINE_BLOCK_STYLE_PROPERTY]: "paragraph",
|
|
2230
|
+
"font-size": "12pt",
|
|
2231
|
+
"font-weight": "400"
|
|
2232
|
+
},
|
|
2233
|
+
h1: {
|
|
2234
|
+
[INLINE_BLOCK_STYLE_PROPERTY]: "h1",
|
|
2235
|
+
"font-size": "22.5pt",
|
|
2236
|
+
"font-weight": "700"
|
|
2237
|
+
},
|
|
2238
|
+
h2: {
|
|
2239
|
+
[INLINE_BLOCK_STYLE_PROPERTY]: "h2",
|
|
2240
|
+
"font-size": "18pt",
|
|
2241
|
+
"font-weight": "700"
|
|
2242
|
+
},
|
|
2243
|
+
h3: {
|
|
2244
|
+
[INLINE_BLOCK_STYLE_PROPERTY]: "h3",
|
|
2245
|
+
"font-size": "15pt",
|
|
2246
|
+
"font-weight": "600"
|
|
2247
|
+
},
|
|
2248
|
+
h4: {
|
|
2249
|
+
[INLINE_BLOCK_STYLE_PROPERTY]: "h4",
|
|
2250
|
+
"font-size": "13.5pt",
|
|
2251
|
+
"font-weight": "600"
|
|
2252
|
+
},
|
|
2253
|
+
h5: {
|
|
2254
|
+
[INLINE_BLOCK_STYLE_PROPERTY]: "h5",
|
|
2255
|
+
"font-size": "12pt",
|
|
2256
|
+
"font-weight": "500"
|
|
2257
|
+
},
|
|
2258
|
+
h6: {
|
|
2259
|
+
[INLINE_BLOCK_STYLE_PROPERTY]: "h6",
|
|
2260
|
+
"font-size": "11.25pt",
|
|
2261
|
+
"font-weight": "500"
|
|
2262
|
+
}
|
|
2263
|
+
};
|
|
2264
|
+
function escapeStyleProperty(property) {
|
|
2265
|
+
const escapedProperty = property.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2266
|
+
return escapedProperty;
|
|
2166
2267
|
}
|
|
2167
|
-
function
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
if (richText.$isHeadingNode(topLevelElement)) {
|
|
2177
|
-
blockType = topLevelElement.getTag();
|
|
2178
|
-
}
|
|
2179
|
-
});
|
|
2180
|
-
return blockType;
|
|
2268
|
+
function stripStyleDeclaration(existingStyle, property) {
|
|
2269
|
+
const escapedProperty = escapeStyleProperty(property);
|
|
2270
|
+
return existingStyle.replace(
|
|
2271
|
+
new RegExp(`${escapedProperty}:\\s*[^;]+;?\\s*`, "g"),
|
|
2272
|
+
""
|
|
2273
|
+
).trim();
|
|
2274
|
+
}
|
|
2275
|
+
function isSupportedInlineBlockType(value) {
|
|
2276
|
+
return value === "paragraph" || value === "h1" || value === "h2" || value === "h3" || value === "h4" || value === "h5" || value === "h6";
|
|
2181
2277
|
}
|
|
2182
2278
|
function extractStyleValue(style, property) {
|
|
2183
|
-
const escapedProperty = property
|
|
2279
|
+
const escapedProperty = escapeStyleProperty(property);
|
|
2184
2280
|
const match = style.match(new RegExp(`${escapedProperty}:\\s*([^;]+)`));
|
|
2185
2281
|
return match ? match[1].trim().replace(/['"]/g, "") : void 0;
|
|
2186
2282
|
}
|
|
2283
|
+
function removeStyleDeclaration(existingStyle, property) {
|
|
2284
|
+
return stripStyleDeclaration(existingStyle, property);
|
|
2285
|
+
}
|
|
2187
2286
|
function mergeStyleDeclaration(existingStyle, property, value) {
|
|
2188
|
-
const
|
|
2189
|
-
const stripped = existingStyle.replace(
|
|
2190
|
-
new RegExp(`${escapedProperty}:\\s*[^;]+;?\\s*`, "g"),
|
|
2191
|
-
""
|
|
2192
|
-
).trim();
|
|
2287
|
+
const stripped = stripStyleDeclaration(existingStyle, property);
|
|
2193
2288
|
const declaration = `${property}: ${value}`;
|
|
2194
2289
|
return stripped ? `${stripped}; ${declaration}` : declaration;
|
|
2195
2290
|
}
|
|
2291
|
+
function mergeStyleDeclarations(existingStyle, declarations) {
|
|
2292
|
+
return Object.entries(declarations).reduce(
|
|
2293
|
+
(style, [property, value]) => mergeStyleDeclaration(style, property, value),
|
|
2294
|
+
existingStyle
|
|
2295
|
+
);
|
|
2296
|
+
}
|
|
2196
2297
|
function extractFontFamilyFromStyle(style) {
|
|
2197
2298
|
return extractStyleValue(style, "font-family");
|
|
2198
2299
|
}
|
|
@@ -2210,6 +2311,21 @@ function mergeFontFamilyStyle(existingStyle, fontFamily) {
|
|
|
2210
2311
|
function mergeFontSizeStyle(existingStyle, size) {
|
|
2211
2312
|
return mergeStyleDeclaration(existingStyle, "font-size", `${size}pt`);
|
|
2212
2313
|
}
|
|
2314
|
+
function extractInlineBlockTypeFromStyle(style) {
|
|
2315
|
+
const value = extractStyleValue(style, INLINE_BLOCK_STYLE_PROPERTY);
|
|
2316
|
+
return isSupportedInlineBlockType(value) ? value : void 0;
|
|
2317
|
+
}
|
|
2318
|
+
function createInlineBlockTypeStylePatch(blockType) {
|
|
2319
|
+
return INLINE_BLOCK_STYLE_PRESETS[blockType];
|
|
2320
|
+
}
|
|
2321
|
+
function mergeInlineBlockTypeStyle(existingStyle, blockType) {
|
|
2322
|
+
const baseStyle = [
|
|
2323
|
+
INLINE_BLOCK_STYLE_PROPERTY,
|
|
2324
|
+
"font-size",
|
|
2325
|
+
"font-weight"
|
|
2326
|
+
].reduce((style, property) => removeStyleDeclaration(style, property), existingStyle);
|
|
2327
|
+
return mergeStyleDeclarations(baseStyle, createInlineBlockTypeStylePatch(blockType));
|
|
2328
|
+
}
|
|
2213
2329
|
const EMPTY_CONTEXT = {
|
|
2214
2330
|
definitions: [],
|
|
2215
2331
|
refreshDefinitions: () => {
|
|
@@ -2297,6 +2413,7 @@ class VariableNode extends lexical.DecoratorNode {
|
|
|
2297
2413
|
const span = document.createElement("span");
|
|
2298
2414
|
span.className = "lex4-variable";
|
|
2299
2415
|
span.setAttribute("data-variable-key", this.__variableKey);
|
|
2416
|
+
span.setAttribute("data-node-key", this.__key);
|
|
2300
2417
|
span.setAttribute("data-testid", `variable-${this.__variableKey}`);
|
|
2301
2418
|
span.contentEditable = "false";
|
|
2302
2419
|
return span;
|
|
@@ -2344,16 +2461,18 @@ function VariableChip({
|
|
|
2344
2461
|
}) {
|
|
2345
2462
|
const { getDefinition } = useVariables();
|
|
2346
2463
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
2347
|
-
const [isSelected
|
|
2464
|
+
const [isSelected] = useLexicalNodeSelection.useLexicalNodeSelection(nodeKey);
|
|
2348
2465
|
const def = getDefinition(variableKey);
|
|
2349
2466
|
const label = (def == null ? void 0 : def.label) ?? variableKey;
|
|
2350
2467
|
const group = def == null ? void 0 : def.group;
|
|
2351
2468
|
const style = React.useMemo(() => {
|
|
2352
2469
|
const fontFamily = extractFontFamilyFromStyle(styleValue);
|
|
2353
2470
|
const fontSize = extractFontSizePtFromStyle(styleValue);
|
|
2471
|
+
const fontWeight = extractStyleValue(styleValue, "font-weight");
|
|
2354
2472
|
return {
|
|
2355
2473
|
...fontFamily ? { fontFamily } : {},
|
|
2356
|
-
...fontSize ? { fontSize: `${fontSize}pt` } : {}
|
|
2474
|
+
...fontSize ? { fontSize: `${fontSize}pt` } : {},
|
|
2475
|
+
...fontWeight ? { fontWeight } : {}
|
|
2357
2476
|
};
|
|
2358
2477
|
}, [styleValue]);
|
|
2359
2478
|
const className = [
|
|
@@ -2364,13 +2483,48 @@ function VariableChip({
|
|
|
2364
2483
|
format & 8 ? "lex4-text-underline" : "",
|
|
2365
2484
|
format & 4 ? "lex4-text-strikethrough" : ""
|
|
2366
2485
|
].filter(Boolean).join(" ");
|
|
2367
|
-
const
|
|
2486
|
+
const clearDomSelection = React.useCallback(() => {
|
|
2487
|
+
var _a;
|
|
2488
|
+
if (typeof window === "undefined") {
|
|
2489
|
+
return;
|
|
2490
|
+
}
|
|
2491
|
+
(_a = window.getSelection()) == null ? void 0 : _a.removeAllRanges();
|
|
2492
|
+
}, []);
|
|
2493
|
+
const selectNode = React.useCallback((extendSelection) => {
|
|
2494
|
+
editor.focus();
|
|
2495
|
+
editor.update(() => {
|
|
2496
|
+
const nextSelection = lexical.$createNodeSelection();
|
|
2497
|
+
if (extendSelection) {
|
|
2498
|
+
const currentSelection = lexical.$getSelection();
|
|
2499
|
+
if (lexical.$isNodeSelection(currentSelection)) {
|
|
2500
|
+
for (const node of currentSelection.getNodes()) {
|
|
2501
|
+
if ($isVariableNode(node)) {
|
|
2502
|
+
nextSelection.add(node.getKey());
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
nextSelection.add(nodeKey);
|
|
2508
|
+
lexical.$setSelection(nextSelection);
|
|
2509
|
+
});
|
|
2510
|
+
clearDomSelection();
|
|
2511
|
+
}, [clearDomSelection, editor, nodeKey]);
|
|
2512
|
+
const handleMouseDown = React.useCallback((event) => {
|
|
2368
2513
|
event.preventDefault();
|
|
2369
|
-
|
|
2370
|
-
|
|
2514
|
+
event.stopPropagation();
|
|
2515
|
+
if (!isSelected || event.shiftKey) {
|
|
2516
|
+
selectNode(event.shiftKey);
|
|
2371
2517
|
}
|
|
2372
|
-
|
|
2373
|
-
|
|
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]);
|
|
2374
2528
|
React.useEffect(() => {
|
|
2375
2529
|
const removeSelectedNodes = () => {
|
|
2376
2530
|
editor.update(() => {
|
|
@@ -2458,7 +2612,8 @@ function VariableChip({
|
|
|
2458
2612
|
"data-variable-group": group,
|
|
2459
2613
|
title: variableKey,
|
|
2460
2614
|
style,
|
|
2461
|
-
onMouseDown:
|
|
2615
|
+
onMouseDown: handleMouseDown,
|
|
2616
|
+
onMouseUp: handleMouseUp,
|
|
2462
2617
|
onClick: handleClick,
|
|
2463
2618
|
children: label
|
|
2464
2619
|
}
|
|
@@ -2470,41 +2625,58 @@ function $createVariableNode(variableKey, format = 0, style = "") {
|
|
|
2470
2625
|
function $isVariableNode(node) {
|
|
2471
2626
|
return node instanceof VariableNode;
|
|
2472
2627
|
}
|
|
2473
|
-
const FORMAT_MASKS = {
|
|
2628
|
+
const FORMAT_MASKS$1 = {
|
|
2474
2629
|
bold: 1,
|
|
2475
2630
|
italic: 2,
|
|
2476
2631
|
strikethrough: 4,
|
|
2477
2632
|
underline: 8
|
|
2478
2633
|
};
|
|
2479
|
-
function
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
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) {
|
|
2484
2653
|
return;
|
|
2485
2654
|
}
|
|
2486
|
-
const
|
|
2487
|
-
if (
|
|
2488
|
-
|
|
2655
|
+
const node = lexical.$getNodeByKey(nodeKey);
|
|
2656
|
+
if ($isVariableNode(node)) {
|
|
2657
|
+
nodes.push(node);
|
|
2489
2658
|
}
|
|
2490
|
-
updater(nodes);
|
|
2491
|
-
updated = true;
|
|
2492
2659
|
});
|
|
2493
|
-
return
|
|
2660
|
+
return dedupeVariableNodes(nodes);
|
|
2494
2661
|
}
|
|
2495
|
-
function
|
|
2496
|
-
let
|
|
2497
|
-
editor.
|
|
2498
|
-
const
|
|
2499
|
-
|
|
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) {
|
|
2500
2671
|
return;
|
|
2501
2672
|
}
|
|
2502
|
-
|
|
2673
|
+
updater(uniqueNodes);
|
|
2674
|
+
updated = true;
|
|
2503
2675
|
});
|
|
2504
|
-
return
|
|
2676
|
+
return updated;
|
|
2505
2677
|
}
|
|
2506
2678
|
function toggleSelectedVariableFormat(editor, format) {
|
|
2507
|
-
const mask = FORMAT_MASKS[format];
|
|
2679
|
+
const mask = FORMAT_MASKS$1[format];
|
|
2508
2680
|
if (!mask) {
|
|
2509
2681
|
return false;
|
|
2510
2682
|
}
|
|
@@ -2530,24 +2702,159 @@ function applyFontSizeToSelectedVariables(editor, size) {
|
|
|
2530
2702
|
}
|
|
2531
2703
|
});
|
|
2532
2704
|
}
|
|
2533
|
-
function
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2705
|
+
function getElementBlockType$1(element) {
|
|
2706
|
+
if (richText.$isHeadingNode(element)) {
|
|
2707
|
+
return element.getTag();
|
|
2708
|
+
}
|
|
2709
|
+
return "paragraph";
|
|
2710
|
+
}
|
|
2711
|
+
function getVariableTopLevelElement(variable) {
|
|
2712
|
+
const topLevelElement = variable.getTopLevelElementOrThrow();
|
|
2713
|
+
return lexical.$isElementNode(topLevelElement) ? topLevelElement : null;
|
|
2714
|
+
}
|
|
2715
|
+
function replaceTopLevelBlockType(element, blockType) {
|
|
2716
|
+
const currentType = getElementBlockType$1(element);
|
|
2717
|
+
if (currentType === blockType) {
|
|
2718
|
+
return;
|
|
2719
|
+
}
|
|
2720
|
+
const nextElement = blockType === "paragraph" ? lexical.$createParagraphNode() : richText.$createHeadingNode(blockType);
|
|
2721
|
+
nextElement.setFormat(element.getFormatType());
|
|
2722
|
+
nextElement.setIndent(element.getIndent());
|
|
2723
|
+
const children = element.getChildren();
|
|
2724
|
+
for (const child of children) {
|
|
2725
|
+
nextElement.append(child);
|
|
2726
|
+
}
|
|
2727
|
+
element.replace(nextElement);
|
|
2728
|
+
}
|
|
2729
|
+
function isPartialSingleBlockSelection(selection2) {
|
|
2730
|
+
if (selection2.isCollapsed()) {
|
|
2731
|
+
return false;
|
|
2732
|
+
}
|
|
2733
|
+
const anchorTopLevel = selection2.anchor.getNode().getTopLevelElementOrThrow();
|
|
2734
|
+
const focusTopLevel = selection2.focus.getNode().getTopLevelElementOrThrow();
|
|
2735
|
+
if (!anchorTopLevel.is(focusTopLevel)) {
|
|
2736
|
+
return false;
|
|
2737
|
+
}
|
|
2738
|
+
const selectedText = selection2.getTextContent().trim();
|
|
2739
|
+
const blockText = anchorTopLevel.getTextContent().trim();
|
|
2740
|
+
return selectedText.length > 0 && selectedText.length < blockText.length;
|
|
2741
|
+
}
|
|
2742
|
+
function applySemanticBlockType(selection$1, blockType) {
|
|
2743
|
+
if (blockType === "paragraph") {
|
|
2744
|
+
selection.$setBlocksType(selection$1, () => lexical.$createParagraphNode());
|
|
2745
|
+
return;
|
|
2746
|
+
}
|
|
2747
|
+
selection.$setBlocksType(selection$1, () => richText.$createHeadingNode(blockType));
|
|
2748
|
+
}
|
|
2749
|
+
function selectedVariablesOccupyEntireBlock(variables, topLevelElement) {
|
|
2750
|
+
const selectedKeys = new Set(variables.map((variable) => variable.getKey()));
|
|
2751
|
+
const meaningfulChildren = topLevelElement.getChildren().filter(
|
|
2752
|
+
(child) => !(lexical.$isTextNode(child) && child.getTextContent().trim() === "")
|
|
2753
|
+
);
|
|
2754
|
+
if (meaningfulChildren.length === 0) {
|
|
2755
|
+
return false;
|
|
2756
|
+
}
|
|
2757
|
+
return meaningfulChildren.every(
|
|
2758
|
+
(child) => $isVariableNode(child) && selectedKeys.has(child.getKey())
|
|
2759
|
+
);
|
|
2760
|
+
}
|
|
2761
|
+
function getStandaloneVariableChildren(topLevelElement) {
|
|
2762
|
+
const meaningfulChildren = topLevelElement.getChildren().filter(
|
|
2763
|
+
(child) => !(lexical.$isTextNode(child) && child.getTextContent().trim() === "")
|
|
2764
|
+
);
|
|
2765
|
+
if (meaningfulChildren.length === 0 || !meaningfulChildren.every($isVariableNode)) {
|
|
2766
|
+
return null;
|
|
2767
|
+
}
|
|
2768
|
+
return meaningfulChildren;
|
|
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
|
+
}
|
|
2787
|
+
function setBlockType(editor, blockType) {
|
|
2788
|
+
editor.update(() => {
|
|
2789
|
+
const visuallySelectedVariables = getVisuallySelectedVariableNodes(editor);
|
|
2790
|
+
const currentSelection = lexical.$getSelection();
|
|
2791
|
+
const selection$1 = lexical.$isNodeSelection(currentSelection) ? currentSelection : lexical.$createRangeSelectionFromDom(window.getSelection(), editor) ?? currentSelection;
|
|
2792
|
+
if (lexical.$isRangeSelection(selection$1)) {
|
|
2793
|
+
lexical.$setSelection(selection$1);
|
|
2794
|
+
}
|
|
2795
|
+
if (lexical.$isNodeSelection(selection$1)) {
|
|
2796
|
+
const variables = Array.from(new Map(
|
|
2797
|
+
[
|
|
2798
|
+
...selection$1.getNodes().filter($isVariableNode),
|
|
2799
|
+
...visuallySelectedVariables
|
|
2800
|
+
].map((variable) => [variable.getKey(), variable])
|
|
2801
|
+
).values());
|
|
2802
|
+
if (variables.length === 0) {
|
|
2803
|
+
return;
|
|
2804
|
+
}
|
|
2805
|
+
const firstTopLevelElement = getVariableTopLevelElement(variables[0]);
|
|
2806
|
+
if (!firstTopLevelElement) {
|
|
2807
|
+
return;
|
|
2808
|
+
}
|
|
2809
|
+
const sameTopLevelElement = variables.every(
|
|
2810
|
+
(variable) => {
|
|
2811
|
+
var _a;
|
|
2812
|
+
return ((_a = getVariableTopLevelElement(variable)) == null ? void 0 : _a.is(firstTopLevelElement)) ?? false;
|
|
2813
|
+
}
|
|
2814
|
+
);
|
|
2815
|
+
if (sameTopLevelElement && selectedVariablesOccupyEntireBlock(variables, firstTopLevelElement)) {
|
|
2816
|
+
for (const variable of variables) {
|
|
2817
|
+
variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
|
|
2818
|
+
}
|
|
2819
|
+
replaceTopLevelBlockType(firstTopLevelElement, blockType);
|
|
2820
|
+
const nextSelection = lexical.$createNodeSelection();
|
|
2821
|
+
for (const variable of variables) {
|
|
2822
|
+
nextSelection.add(variable.getKey());
|
|
2823
|
+
}
|
|
2824
|
+
lexical.$setSelection(nextSelection);
|
|
2825
|
+
return;
|
|
2826
|
+
}
|
|
2827
|
+
for (const variable of variables) {
|
|
2828
|
+
variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
|
|
2829
|
+
}
|
|
2538
2830
|
return;
|
|
2539
2831
|
}
|
|
2540
|
-
|
|
2541
|
-
|
|
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
|
+
}
|
|
2542
2839
|
return;
|
|
2543
2840
|
}
|
|
2544
|
-
const
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2841
|
+
const anchorTopLevel = selection$1.anchor.getNode().getTopLevelElementOrThrow();
|
|
2842
|
+
const standaloneVariables = lexical.$isElementNode(anchorTopLevel) ? getStandaloneVariableChildren(anchorTopLevel) : null;
|
|
2843
|
+
const selectedVariables = getSelectedVariableNodesFromRangeSelection(editor, selection$1);
|
|
2844
|
+
if (isPartialSingleBlockSelection(selection$1)) {
|
|
2845
|
+
selection.$patchStyleText(selection$1, createInlineBlockTypeStylePatch(blockType));
|
|
2846
|
+
for (const variable of selectedVariables) {
|
|
2847
|
+
variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
|
|
2848
|
+
}
|
|
2849
|
+
return;
|
|
2850
|
+
}
|
|
2851
|
+
for (const variable of new Map(
|
|
2852
|
+
[...standaloneVariables ?? [], ...selectedVariables].map((variable2) => [variable2.getKey(), variable2])
|
|
2853
|
+
).values()) {
|
|
2854
|
+
variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
|
|
2855
|
+
}
|
|
2856
|
+
applySemanticBlockType(selection$1, blockType);
|
|
2549
2857
|
});
|
|
2550
|
-
return formatting;
|
|
2551
2858
|
}
|
|
2552
2859
|
const BLOCK_TYPE_OPTIONS = [
|
|
2553
2860
|
{ value: "paragraph", shortLabel: "P" },
|
|
@@ -2964,6 +3271,108 @@ const CanvasControls = () => {
|
|
|
2964
3271
|
)
|
|
2965
3272
|
] });
|
|
2966
3273
|
};
|
|
3274
|
+
const FORMAT_MASKS = {
|
|
3275
|
+
bold: 1,
|
|
3276
|
+
italic: 2,
|
|
3277
|
+
strikethrough: 4,
|
|
3278
|
+
underline: 8
|
|
3279
|
+
};
|
|
3280
|
+
function normalizeFontFamily(fontFamily) {
|
|
3281
|
+
if (fontFamily && SUPPORTED_FONTS.includes(fontFamily)) {
|
|
3282
|
+
return fontFamily;
|
|
3283
|
+
}
|
|
3284
|
+
return "Inter";
|
|
3285
|
+
}
|
|
3286
|
+
function normalizeAlignment(alignment) {
|
|
3287
|
+
if (alignment === "center" || alignment === "right" || alignment === "justify") {
|
|
3288
|
+
return alignment;
|
|
3289
|
+
}
|
|
3290
|
+
return "left";
|
|
3291
|
+
}
|
|
3292
|
+
function getElementBlockType(node) {
|
|
3293
|
+
const topLevelElement = node.getTopLevelElementOrThrow();
|
|
3294
|
+
if (richText.$isHeadingNode(topLevelElement)) {
|
|
3295
|
+
return topLevelElement.getTag();
|
|
3296
|
+
}
|
|
3297
|
+
return "paragraph";
|
|
3298
|
+
}
|
|
3299
|
+
function getElementAlignment(node) {
|
|
3300
|
+
const topLevelElement = node.getTopLevelElementOrThrow();
|
|
3301
|
+
if (lexical.$isElementNode(topLevelElement)) {
|
|
3302
|
+
return normalizeAlignment(topLevelElement.getFormatType());
|
|
3303
|
+
}
|
|
3304
|
+
return "left";
|
|
3305
|
+
}
|
|
3306
|
+
function getInlineStyleTarget(nodes, anchorNode) {
|
|
3307
|
+
if (lexical.$isTextNode(anchorNode) || $isVariableNode(anchorNode)) {
|
|
3308
|
+
return anchorNode;
|
|
3309
|
+
}
|
|
3310
|
+
return nodes.find((node) => lexical.$isTextNode(node) || $isVariableNode(node)) ?? null;
|
|
3311
|
+
}
|
|
3312
|
+
function getInlineStyleFromNode(node) {
|
|
3313
|
+
if (lexical.$isTextNode(node) || $isVariableNode(node)) {
|
|
3314
|
+
return node.getStyle();
|
|
3315
|
+
}
|
|
3316
|
+
return "";
|
|
3317
|
+
}
|
|
3318
|
+
function hasInlineFormat(node, format) {
|
|
3319
|
+
if ($isVariableNode(node)) {
|
|
3320
|
+
return (node.getFormat() & FORMAT_MASKS[format]) !== 0;
|
|
3321
|
+
}
|
|
3322
|
+
if (lexical.$isTextNode(node) && "hasFormat" in node && typeof node.hasFormat === "function") {
|
|
3323
|
+
return node.hasFormat(format);
|
|
3324
|
+
}
|
|
3325
|
+
if (lexical.$isTextNode(node) && "getFormat" in node && typeof node.getFormat === "function") {
|
|
3326
|
+
return (node.getFormat() & FORMAT_MASKS[format]) !== 0;
|
|
3327
|
+
}
|
|
3328
|
+
return false;
|
|
3329
|
+
}
|
|
3330
|
+
function readToolbarStyleSnapshot(editor, editorState = editor.getEditorState()) {
|
|
3331
|
+
let snapshot = DEFAULT_TOOLBAR_STYLE_SNAPSHOT;
|
|
3332
|
+
editorState.read(() => {
|
|
3333
|
+
const currentSelection = lexical.$getSelection();
|
|
3334
|
+
const selection2 = lexical.$isNodeSelection(currentSelection) ? currentSelection : lexical.$createRangeSelectionFromDom(window.getSelection(), editor) ?? currentSelection;
|
|
3335
|
+
if (lexical.$isNodeSelection(selection2)) {
|
|
3336
|
+
const variableNodes = selection2.getNodes().filter($isVariableNode);
|
|
3337
|
+
if (variableNodes.length === 0) {
|
|
3338
|
+
return;
|
|
3339
|
+
}
|
|
3340
|
+
const firstVariableNode = variableNodes[0];
|
|
3341
|
+
const style2 = firstVariableNode.getStyle();
|
|
3342
|
+
snapshot = {
|
|
3343
|
+
blockType: extractInlineBlockTypeFromStyle(style2) ?? getElementBlockType(firstVariableNode),
|
|
3344
|
+
fontFamily: normalizeFontFamily(extractFontFamilyFromStyle(style2)),
|
|
3345
|
+
fontSize: extractFontSizePtFromStyle(style2) ?? DEFAULT_FONT_SIZE,
|
|
3346
|
+
alignment: getElementAlignment(firstVariableNode),
|
|
3347
|
+
isBold: variableNodes.every((node) => (node.getFormat() & FORMAT_MASKS.bold) !== 0),
|
|
3348
|
+
isItalic: variableNodes.every((node) => (node.getFormat() & FORMAT_MASKS.italic) !== 0),
|
|
3349
|
+
isUnderline: variableNodes.every((node) => (node.getFormat() & FORMAT_MASKS.underline) !== 0),
|
|
3350
|
+
isStrikethrough: variableNodes.every((node) => (node.getFormat() & FORMAT_MASKS.strikethrough) !== 0),
|
|
3351
|
+
hasSelectedVariable: true
|
|
3352
|
+
};
|
|
3353
|
+
return;
|
|
3354
|
+
}
|
|
3355
|
+
if (!lexical.$isRangeSelection(selection2)) {
|
|
3356
|
+
return;
|
|
3357
|
+
}
|
|
3358
|
+
const anchorNode = selection2.anchor.getNode();
|
|
3359
|
+
const inlineStyleTarget = getInlineStyleTarget(selection2.getNodes(), anchorNode);
|
|
3360
|
+
const style = selection2.style || getInlineStyleFromNode(inlineStyleTarget);
|
|
3361
|
+
const isCollapsed = selection2.isCollapsed();
|
|
3362
|
+
snapshot = {
|
|
3363
|
+
blockType: extractInlineBlockTypeFromStyle(style) ?? getElementBlockType(anchorNode),
|
|
3364
|
+
fontFamily: normalizeFontFamily(extractFontFamilyFromStyle(style)),
|
|
3365
|
+
fontSize: extractFontSizePtFromStyle(style) ?? DEFAULT_FONT_SIZE,
|
|
3366
|
+
alignment: getElementAlignment(anchorNode),
|
|
3367
|
+
isBold: selection2.hasFormat("bold") || isCollapsed && hasInlineFormat(inlineStyleTarget, "bold"),
|
|
3368
|
+
isItalic: selection2.hasFormat("italic") || isCollapsed && hasInlineFormat(inlineStyleTarget, "italic"),
|
|
3369
|
+
isUnderline: selection2.hasFormat("underline") || isCollapsed && hasInlineFormat(inlineStyleTarget, "underline"),
|
|
3370
|
+
isStrikethrough: selection2.hasFormat("strikethrough") || isCollapsed && hasInlineFormat(inlineStyleTarget, "strikethrough"),
|
|
3371
|
+
hasSelectedVariable: false
|
|
3372
|
+
};
|
|
3373
|
+
});
|
|
3374
|
+
return snapshot;
|
|
3375
|
+
}
|
|
2967
3376
|
const Toolbar = () => {
|
|
2968
3377
|
const {
|
|
2969
3378
|
activeEditor,
|
|
@@ -2980,15 +3389,15 @@ const Toolbar = () => {
|
|
|
2980
3389
|
const { toolbarItems, toolbarEndItems } = useExtensions();
|
|
2981
3390
|
const toolbarConfig = useToolbarConfig();
|
|
2982
3391
|
const t = useTranslations();
|
|
2983
|
-
const
|
|
2984
|
-
const
|
|
2985
|
-
const
|
|
2986
|
-
const
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
3392
|
+
const toolbarStyleStore = useToolbarStyleStoreApi();
|
|
3393
|
+
const activeBlockType = useToolbarStyleStore((state) => state.blockType);
|
|
3394
|
+
const activeFontFamily = useToolbarStyleStore((state) => state.fontFamily);
|
|
3395
|
+
const activeFontSize = useToolbarStyleStore((state) => state.fontSize);
|
|
3396
|
+
const activeAlignment = useToolbarStyleStore((state) => state.alignment);
|
|
3397
|
+
const isBoldActive = useToolbarStyleStore((state) => state.isBold);
|
|
3398
|
+
const isItalicActive = useToolbarStyleStore((state) => state.isItalic);
|
|
3399
|
+
const isUnderlineActive = useToolbarStyleStore((state) => state.isUnderline);
|
|
3400
|
+
const isStrikethroughActive = useToolbarStyleStore((state) => state.isStrikethrough);
|
|
2992
3401
|
const withBodySelection = React.useCallback(
|
|
2993
3402
|
(editor, action) => {
|
|
2994
3403
|
editor.update(() => {
|
|
@@ -3026,38 +3435,11 @@ const Toolbar = () => {
|
|
|
3026
3435
|
);
|
|
3027
3436
|
React.useEffect(() => {
|
|
3028
3437
|
if (!activeEditor) {
|
|
3029
|
-
|
|
3030
|
-
setActiveFontFamily("Calibri");
|
|
3031
|
-
setActiveFontSize(DEFAULT_FONT_SIZE);
|
|
3438
|
+
toolbarStyleStore.getState().reset();
|
|
3032
3439
|
return;
|
|
3033
3440
|
}
|
|
3034
|
-
const updateSelectionState = () => {
|
|
3035
|
-
|
|
3036
|
-
if (selectedVariables.length > 0) {
|
|
3037
|
-
const formatting = readSelectedVariableFormatting(activeEditor);
|
|
3038
|
-
setActiveBlockType("paragraph");
|
|
3039
|
-
setActiveFontFamily(normalizeFontFamily(formatting.fontFamily));
|
|
3040
|
-
setActiveFontSize(formatting.fontSize ?? DEFAULT_FONT_SIZE);
|
|
3041
|
-
return;
|
|
3042
|
-
}
|
|
3043
|
-
setActiveBlockType(getActiveBlockType(activeEditor));
|
|
3044
|
-
let nextFontFamily = "Calibri";
|
|
3045
|
-
let nextFontSize = DEFAULT_FONT_SIZE;
|
|
3046
|
-
activeEditor.getEditorState().read(() => {
|
|
3047
|
-
const selection2 = lexical.$getSelection();
|
|
3048
|
-
if (!lexical.$isRangeSelection(selection2)) {
|
|
3049
|
-
return;
|
|
3050
|
-
}
|
|
3051
|
-
const textNode = selection2.getNodes().find(lexical.$isTextNode);
|
|
3052
|
-
if (!textNode) {
|
|
3053
|
-
return;
|
|
3054
|
-
}
|
|
3055
|
-
const style = textNode.getStyle();
|
|
3056
|
-
nextFontFamily = normalizeFontFamily(extractFontFamilyFromStyle(style));
|
|
3057
|
-
nextFontSize = extractFontSizePtFromStyle(style) ?? DEFAULT_FONT_SIZE;
|
|
3058
|
-
});
|
|
3059
|
-
setActiveFontFamily(nextFontFamily);
|
|
3060
|
-
setActiveFontSize(nextFontSize);
|
|
3441
|
+
const updateSelectionState = (editorState = activeEditor.getEditorState()) => {
|
|
3442
|
+
toolbarStyleStore.getState().setSnapshot(readToolbarStyleSnapshot(activeEditor, editorState));
|
|
3061
3443
|
};
|
|
3062
3444
|
updateSelectionState();
|
|
3063
3445
|
const unregisterSelectionChange = activeEditor.registerCommand(
|
|
@@ -3068,14 +3450,14 @@ const Toolbar = () => {
|
|
|
3068
3450
|
},
|
|
3069
3451
|
lexical.COMMAND_PRIORITY_LOW
|
|
3070
3452
|
);
|
|
3071
|
-
const unregisterUpdateListener = activeEditor.registerUpdateListener(() => {
|
|
3072
|
-
updateSelectionState();
|
|
3453
|
+
const unregisterUpdateListener = activeEditor.registerUpdateListener(({ editorState }) => {
|
|
3454
|
+
updateSelectionState(editorState);
|
|
3073
3455
|
});
|
|
3074
3456
|
return () => {
|
|
3075
3457
|
unregisterSelectionChange();
|
|
3076
3458
|
unregisterUpdateListener();
|
|
3077
3459
|
};
|
|
3078
|
-
}, [activeEditor,
|
|
3460
|
+
}, [activeEditor, toolbarStyleStore]);
|
|
3079
3461
|
const handleBold = React.useCallback(() => {
|
|
3080
3462
|
debug("toolbar", `bold (globalSelection=${globalSelectionActive}, editors=${editorRegistry.all().length}, hasEditor=${!!activeEditor})`);
|
|
3081
3463
|
runToolbarAction(t.history.actions.boldApplied, () => {
|
|
@@ -3260,17 +3642,17 @@ const Toolbar = () => {
|
|
|
3260
3642
|
] }),
|
|
3261
3643
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
3262
3644
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "format-group", children: [
|
|
3263
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.bold, testId: "btn-bold", onClick: handleBold, children: /* @__PURE__ */ jsxRuntime.jsx(Bold, { size: 15 }) }),
|
|
3264
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.italic, testId: "btn-italic", onClick: handleItalic, children: /* @__PURE__ */ jsxRuntime.jsx(Italic, { size: 15 }) }),
|
|
3265
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.underline, testId: "btn-underline", onClick: handleUnderline, children: /* @__PURE__ */ jsxRuntime.jsx(Underline, { size: 15 }) }),
|
|
3266
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.strikethrough, testId: "btn-strike", onClick: handleStrikethrough, children: /* @__PURE__ */ jsxRuntime.jsx(Strikethrough, { size: 15 }) })
|
|
3645
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.bold, testId: "btn-bold", active: isBoldActive, onClick: handleBold, children: /* @__PURE__ */ jsxRuntime.jsx(Bold, { size: 15 }) }),
|
|
3646
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.italic, testId: "btn-italic", active: isItalicActive, onClick: handleItalic, children: /* @__PURE__ */ jsxRuntime.jsx(Italic, { size: 15 }) }),
|
|
3647
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.underline, testId: "btn-underline", active: isUnderlineActive, onClick: handleUnderline, children: /* @__PURE__ */ jsxRuntime.jsx(Underline, { size: 15 }) }),
|
|
3648
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.strikethrough, testId: "btn-strike", active: isStrikethroughActive, onClick: handleStrikethrough, children: /* @__PURE__ */ jsxRuntime.jsx(Strikethrough, { size: 15 }) })
|
|
3267
3649
|
] }),
|
|
3268
3650
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
3269
3651
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "align-group", children: [
|
|
3270
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignLeft, testId: "btn-align-left", onClick: handleAlignLeft, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignStart, { size: 15 }) }),
|
|
3271
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignCenter, testId: "btn-align-center", onClick: handleAlignCenter, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignCenter, { size: 15 }) }),
|
|
3272
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignRight, testId: "btn-align-right", onClick: handleAlignRight, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignEnd, { size: 15 }) }),
|
|
3273
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.justify, testId: "btn-align-justify", onClick: handleAlignJustify, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignJustify, { size: 15 }) })
|
|
3652
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignLeft, testId: "btn-align-left", active: activeAlignment === "left", onClick: handleAlignLeft, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignStart, { size: 15 }) }),
|
|
3653
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignCenter, testId: "btn-align-center", active: activeAlignment === "center", onClick: handleAlignCenter, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignCenter, { size: 15 }) }),
|
|
3654
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignRight, testId: "btn-align-right", active: activeAlignment === "right", onClick: handleAlignRight, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignEnd, { size: 15 }) }),
|
|
3655
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.justify, testId: "btn-align-justify", active: activeAlignment === "justify", onClick: handleAlignJustify, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignJustify, { size: 15 }) })
|
|
3274
3656
|
] }),
|
|
3275
3657
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
3276
3658
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "list-group", children: [
|
|
@@ -3321,6 +3703,7 @@ const ToolbarIconButton = ({
|
|
|
3321
3703
|
type: "button",
|
|
3322
3704
|
title,
|
|
3323
3705
|
"aria-label": title,
|
|
3706
|
+
"aria-pressed": active,
|
|
3324
3707
|
disabled,
|
|
3325
3708
|
onMouseDown: (e) => e.preventDefault(),
|
|
3326
3709
|
onClick,
|