@yurikilian/lex4 1.5.9 → 1.7.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/Lex4Editor.d.ts.map +1 -1
- package/dist/components/PageView.d.ts.map +1 -1
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/context/document-context.d.ts +1 -1
- package/dist/context/document-context.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 +513 -159
- package/dist/lex4-editor.cjs.map +1 -1
- package/dist/lex4-editor.js +516 -162
- 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/lexical/plugins/active-editor-plugin.d.ts.map +1 -1
- package/dist/style.css +2 -2
- package/dist/utils/document-insert-target.d.ts +12 -0
- package/dist/utils/document-insert-target.d.ts.map +1 -0
- 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.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: "Calibri",
|
|
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) {
|
|
@@ -1026,7 +1135,11 @@ const DocumentProvider = ({
|
|
|
1026
1135
|
register: (pageId, editor) => {
|
|
1027
1136
|
editorMapRef.current.set(pageId, editor);
|
|
1028
1137
|
},
|
|
1029
|
-
unregister: (pageId) => {
|
|
1138
|
+
unregister: (pageId, editor) => {
|
|
1139
|
+
const currentEditor = editorMapRef.current.get(pageId);
|
|
1140
|
+
if (editor && currentEditor && currentEditor !== editor) {
|
|
1141
|
+
return;
|
|
1142
|
+
}
|
|
1030
1143
|
editorMapRef.current.delete(pageId);
|
|
1031
1144
|
},
|
|
1032
1145
|
get: (pageId) => editorMapRef.current.get(pageId),
|
|
@@ -1331,7 +1444,7 @@ const DocumentProvider = ({
|
|
|
1331
1444
|
undo,
|
|
1332
1445
|
redo,
|
|
1333
1446
|
editorRegistry
|
|
1334
|
-
}, children });
|
|
1447
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsx(ToolbarStyleStoreProvider, { children }) });
|
|
1335
1448
|
};
|
|
1336
1449
|
/**
|
|
1337
1450
|
* @license lucide-react v1.8.0 - ISC
|
|
@@ -2079,43 +2192,6 @@ function applyFontFamily(editor, fontFamily) {
|
|
|
2079
2192
|
}
|
|
2080
2193
|
});
|
|
2081
2194
|
}
|
|
2082
|
-
const SUPPORTED_FONT_SIZES = [
|
|
2083
|
-
8,
|
|
2084
|
-
9,
|
|
2085
|
-
10,
|
|
2086
|
-
11,
|
|
2087
|
-
12,
|
|
2088
|
-
14,
|
|
2089
|
-
16,
|
|
2090
|
-
18,
|
|
2091
|
-
20,
|
|
2092
|
-
24,
|
|
2093
|
-
28,
|
|
2094
|
-
32,
|
|
2095
|
-
36,
|
|
2096
|
-
48,
|
|
2097
|
-
72
|
|
2098
|
-
];
|
|
2099
|
-
const DEFAULT_FONT_SIZE = 12;
|
|
2100
|
-
function applyFontSize(editor, size) {
|
|
2101
|
-
editor.update(() => {
|
|
2102
|
-
const selection2 = lexical.$getSelection();
|
|
2103
|
-
if (!lexical.$isRangeSelection(selection2)) return;
|
|
2104
|
-
const nodes = selection2.getNodes();
|
|
2105
|
-
for (const node of nodes) {
|
|
2106
|
-
if (lexical.$isTextNode(node)) {
|
|
2107
|
-
const existing = node.getStyle();
|
|
2108
|
-
const updated = mergeFontSize(existing, size);
|
|
2109
|
-
node.setStyle(updated);
|
|
2110
|
-
}
|
|
2111
|
-
}
|
|
2112
|
-
});
|
|
2113
|
-
}
|
|
2114
|
-
function mergeFontSize(existingStyle, size) {
|
|
2115
|
-
const stripped = existingStyle.replace(/font-size:\s*[^;]+;?\s*/g, "").trim();
|
|
2116
|
-
const sizeDecl = `font-size: ${size}pt`;
|
|
2117
|
-
return stripped ? `${stripped}; ${sizeDecl}` : sizeDecl;
|
|
2118
|
-
}
|
|
2119
2195
|
function toggleFormat(editor, format) {
|
|
2120
2196
|
editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, format);
|
|
2121
2197
|
}
|
|
@@ -2147,48 +2223,77 @@ function indentContent(editor) {
|
|
|
2147
2223
|
function outdentContent(editor) {
|
|
2148
2224
|
editor.dispatchCommand(lexical.OUTDENT_CONTENT_COMMAND, void 0);
|
|
2149
2225
|
}
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
}
|
|
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;
|
|
2162
2267
|
}
|
|
2163
|
-
function
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
if (richText.$isHeadingNode(topLevelElement)) {
|
|
2173
|
-
blockType = topLevelElement.getTag();
|
|
2174
|
-
}
|
|
2175
|
-
});
|
|
2176
|
-
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";
|
|
2177
2277
|
}
|
|
2178
2278
|
function extractStyleValue(style, property) {
|
|
2179
|
-
const escapedProperty = property
|
|
2279
|
+
const escapedProperty = escapeStyleProperty(property);
|
|
2180
2280
|
const match = style.match(new RegExp(`${escapedProperty}:\\s*([^;]+)`));
|
|
2181
2281
|
return match ? match[1].trim().replace(/['"]/g, "") : void 0;
|
|
2182
2282
|
}
|
|
2283
|
+
function removeStyleDeclaration(existingStyle, property) {
|
|
2284
|
+
return stripStyleDeclaration(existingStyle, property);
|
|
2285
|
+
}
|
|
2183
2286
|
function mergeStyleDeclaration(existingStyle, property, value) {
|
|
2184
|
-
const
|
|
2185
|
-
const stripped = existingStyle.replace(
|
|
2186
|
-
new RegExp(`${escapedProperty}:\\s*[^;]+;?\\s*`, "g"),
|
|
2187
|
-
""
|
|
2188
|
-
).trim();
|
|
2287
|
+
const stripped = stripStyleDeclaration(existingStyle, property);
|
|
2189
2288
|
const declaration = `${property}: ${value}`;
|
|
2190
2289
|
return stripped ? `${stripped}; ${declaration}` : declaration;
|
|
2191
2290
|
}
|
|
2291
|
+
function mergeStyleDeclarations(existingStyle, declarations) {
|
|
2292
|
+
return Object.entries(declarations).reduce(
|
|
2293
|
+
(style, [property, value]) => mergeStyleDeclaration(style, property, value),
|
|
2294
|
+
existingStyle
|
|
2295
|
+
);
|
|
2296
|
+
}
|
|
2192
2297
|
function extractFontFamilyFromStyle(style) {
|
|
2193
2298
|
return extractStyleValue(style, "font-family");
|
|
2194
2299
|
}
|
|
@@ -2206,6 +2311,21 @@ function mergeFontFamilyStyle(existingStyle, fontFamily) {
|
|
|
2206
2311
|
function mergeFontSizeStyle(existingStyle, size) {
|
|
2207
2312
|
return mergeStyleDeclaration(existingStyle, "font-size", `${size}pt`);
|
|
2208
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
|
+
}
|
|
2209
2329
|
const EMPTY_CONTEXT = {
|
|
2210
2330
|
definitions: [],
|
|
2211
2331
|
refreshDefinitions: () => {
|
|
@@ -2347,9 +2467,11 @@ function VariableChip({
|
|
|
2347
2467
|
const style = React.useMemo(() => {
|
|
2348
2468
|
const fontFamily = extractFontFamilyFromStyle(styleValue);
|
|
2349
2469
|
const fontSize = extractFontSizePtFromStyle(styleValue);
|
|
2470
|
+
const fontWeight = extractStyleValue(styleValue, "font-weight");
|
|
2350
2471
|
return {
|
|
2351
2472
|
...fontFamily ? { fontFamily } : {},
|
|
2352
|
-
...fontSize ? { fontSize: `${fontSize}pt` } : {}
|
|
2473
|
+
...fontSize ? { fontSize: `${fontSize}pt` } : {},
|
|
2474
|
+
...fontWeight ? { fontWeight } : {}
|
|
2353
2475
|
};
|
|
2354
2476
|
}, [styleValue]);
|
|
2355
2477
|
const className = [
|
|
@@ -2407,9 +2529,43 @@ function VariableChip({
|
|
|
2407
2529
|
},
|
|
2408
2530
|
lexical.COMMAND_PRIORITY_LOW
|
|
2409
2531
|
);
|
|
2532
|
+
const moveCaretFromSelectedNode = (direction) => {
|
|
2533
|
+
editor.update(() => {
|
|
2534
|
+
const node = lexical.$getNodeByKey(nodeKey);
|
|
2535
|
+
if (!$isVariableNode(node)) {
|
|
2536
|
+
return;
|
|
2537
|
+
}
|
|
2538
|
+
if (direction === "backward") {
|
|
2539
|
+
node.selectPrevious();
|
|
2540
|
+
} else {
|
|
2541
|
+
node.selectNext();
|
|
2542
|
+
}
|
|
2543
|
+
});
|
|
2544
|
+
};
|
|
2545
|
+
const unregisterArrowNavigation = editor.registerCommand(
|
|
2546
|
+
lexical.KEY_DOWN_COMMAND,
|
|
2547
|
+
(event) => {
|
|
2548
|
+
if (!isSelected || event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) {
|
|
2549
|
+
return false;
|
|
2550
|
+
}
|
|
2551
|
+
if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
|
|
2552
|
+
event.preventDefault();
|
|
2553
|
+
moveCaretFromSelectedNode("backward");
|
|
2554
|
+
return true;
|
|
2555
|
+
}
|
|
2556
|
+
if (event.key === "ArrowRight" || event.key === "ArrowDown") {
|
|
2557
|
+
event.preventDefault();
|
|
2558
|
+
moveCaretFromSelectedNode("forward");
|
|
2559
|
+
return true;
|
|
2560
|
+
}
|
|
2561
|
+
return false;
|
|
2562
|
+
},
|
|
2563
|
+
lexical.COMMAND_PRIORITY_LOW
|
|
2564
|
+
);
|
|
2410
2565
|
return () => {
|
|
2411
2566
|
unregisterBackspace();
|
|
2412
2567
|
unregisterDelete();
|
|
2568
|
+
unregisterArrowNavigation();
|
|
2413
2569
|
};
|
|
2414
2570
|
}, [editor, isSelected, nodeKey]);
|
|
2415
2571
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2432,7 +2588,126 @@ function $createVariableNode(variableKey, format = 0, style = "") {
|
|
|
2432
2588
|
function $isVariableNode(node) {
|
|
2433
2589
|
return node instanceof VariableNode;
|
|
2434
2590
|
}
|
|
2435
|
-
|
|
2591
|
+
function getElementBlockType$1(element) {
|
|
2592
|
+
if (richText.$isHeadingNode(element)) {
|
|
2593
|
+
return element.getTag();
|
|
2594
|
+
}
|
|
2595
|
+
return "paragraph";
|
|
2596
|
+
}
|
|
2597
|
+
function getVariableTopLevelElement(variable) {
|
|
2598
|
+
const topLevelElement = variable.getTopLevelElementOrThrow();
|
|
2599
|
+
return lexical.$isElementNode(topLevelElement) ? topLevelElement : null;
|
|
2600
|
+
}
|
|
2601
|
+
function replaceTopLevelBlockType(element, blockType) {
|
|
2602
|
+
const currentType = getElementBlockType$1(element);
|
|
2603
|
+
if (currentType === blockType) {
|
|
2604
|
+
return;
|
|
2605
|
+
}
|
|
2606
|
+
const nextElement = blockType === "paragraph" ? lexical.$createParagraphNode() : richText.$createHeadingNode(blockType);
|
|
2607
|
+
nextElement.setFormat(element.getFormatType());
|
|
2608
|
+
nextElement.setIndent(element.getIndent());
|
|
2609
|
+
const children = element.getChildren();
|
|
2610
|
+
for (const child of children) {
|
|
2611
|
+
nextElement.append(child);
|
|
2612
|
+
}
|
|
2613
|
+
element.replace(nextElement);
|
|
2614
|
+
}
|
|
2615
|
+
function isPartialSingleBlockSelection(selection2) {
|
|
2616
|
+
if (selection2.isCollapsed()) {
|
|
2617
|
+
return false;
|
|
2618
|
+
}
|
|
2619
|
+
const anchorTopLevel = selection2.anchor.getNode().getTopLevelElementOrThrow();
|
|
2620
|
+
const focusTopLevel = selection2.focus.getNode().getTopLevelElementOrThrow();
|
|
2621
|
+
if (!anchorTopLevel.is(focusTopLevel)) {
|
|
2622
|
+
return false;
|
|
2623
|
+
}
|
|
2624
|
+
const selectedText = selection2.getTextContent().trim();
|
|
2625
|
+
const blockText = anchorTopLevel.getTextContent().trim();
|
|
2626
|
+
return selectedText.length > 0 && selectedText.length < blockText.length;
|
|
2627
|
+
}
|
|
2628
|
+
function applySemanticBlockType(selection$1, blockType) {
|
|
2629
|
+
if (blockType === "paragraph") {
|
|
2630
|
+
selection.$setBlocksType(selection$1, () => lexical.$createParagraphNode());
|
|
2631
|
+
return;
|
|
2632
|
+
}
|
|
2633
|
+
selection.$setBlocksType(selection$1, () => richText.$createHeadingNode(blockType));
|
|
2634
|
+
}
|
|
2635
|
+
function selectedVariablesOccupyEntireBlock(variables, topLevelElement) {
|
|
2636
|
+
const selectedKeys = new Set(variables.map((variable) => variable.getKey()));
|
|
2637
|
+
const meaningfulChildren = topLevelElement.getChildren().filter(
|
|
2638
|
+
(child) => !(lexical.$isTextNode(child) && child.getTextContent().trim() === "")
|
|
2639
|
+
);
|
|
2640
|
+
if (meaningfulChildren.length === 0) {
|
|
2641
|
+
return false;
|
|
2642
|
+
}
|
|
2643
|
+
return meaningfulChildren.every(
|
|
2644
|
+
(child) => $isVariableNode(child) && selectedKeys.has(child.getKey())
|
|
2645
|
+
);
|
|
2646
|
+
}
|
|
2647
|
+
function getStandaloneVariableChildren(topLevelElement) {
|
|
2648
|
+
const meaningfulChildren = topLevelElement.getChildren().filter(
|
|
2649
|
+
(child) => !(lexical.$isTextNode(child) && child.getTextContent().trim() === "")
|
|
2650
|
+
);
|
|
2651
|
+
if (meaningfulChildren.length === 0 || !meaningfulChildren.every($isVariableNode)) {
|
|
2652
|
+
return null;
|
|
2653
|
+
}
|
|
2654
|
+
return meaningfulChildren;
|
|
2655
|
+
}
|
|
2656
|
+
function setBlockType(editor, blockType) {
|
|
2657
|
+
editor.update(() => {
|
|
2658
|
+
const currentSelection = lexical.$getSelection();
|
|
2659
|
+
const selection$1 = lexical.$isNodeSelection(currentSelection) ? currentSelection : lexical.$createRangeSelectionFromDom(window.getSelection(), editor) ?? currentSelection;
|
|
2660
|
+
if (lexical.$isRangeSelection(selection$1)) {
|
|
2661
|
+
lexical.$setSelection(selection$1);
|
|
2662
|
+
}
|
|
2663
|
+
if (lexical.$isNodeSelection(selection$1)) {
|
|
2664
|
+
const variables = selection$1.getNodes().filter($isVariableNode);
|
|
2665
|
+
if (variables.length === 0) {
|
|
2666
|
+
return;
|
|
2667
|
+
}
|
|
2668
|
+
const firstTopLevelElement = getVariableTopLevelElement(variables[0]);
|
|
2669
|
+
if (!firstTopLevelElement) {
|
|
2670
|
+
return;
|
|
2671
|
+
}
|
|
2672
|
+
const sameTopLevelElement = variables.every(
|
|
2673
|
+
(variable) => {
|
|
2674
|
+
var _a;
|
|
2675
|
+
return ((_a = getVariableTopLevelElement(variable)) == null ? void 0 : _a.is(firstTopLevelElement)) ?? false;
|
|
2676
|
+
}
|
|
2677
|
+
);
|
|
2678
|
+
if (sameTopLevelElement && selectedVariablesOccupyEntireBlock(variables, firstTopLevelElement)) {
|
|
2679
|
+
for (const variable of variables) {
|
|
2680
|
+
variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
|
|
2681
|
+
}
|
|
2682
|
+
replaceTopLevelBlockType(firstTopLevelElement, blockType);
|
|
2683
|
+
const nextSelection = lexical.$createNodeSelection();
|
|
2684
|
+
for (const variable of variables) {
|
|
2685
|
+
nextSelection.add(variable.getKey());
|
|
2686
|
+
}
|
|
2687
|
+
lexical.$setSelection(nextSelection);
|
|
2688
|
+
return;
|
|
2689
|
+
}
|
|
2690
|
+
for (const variable of variables) {
|
|
2691
|
+
variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
|
|
2692
|
+
}
|
|
2693
|
+
return;
|
|
2694
|
+
}
|
|
2695
|
+
if (!lexical.$isRangeSelection(selection$1)) {
|
|
2696
|
+
return;
|
|
2697
|
+
}
|
|
2698
|
+
const anchorTopLevel = selection$1.anchor.getNode().getTopLevelElementOrThrow();
|
|
2699
|
+
const standaloneVariables = lexical.$isElementNode(anchorTopLevel) ? getStandaloneVariableChildren(anchorTopLevel) : null;
|
|
2700
|
+
if (isPartialSingleBlockSelection(selection$1)) {
|
|
2701
|
+
selection.$patchStyleText(selection$1, createInlineBlockTypeStylePatch(blockType));
|
|
2702
|
+
return;
|
|
2703
|
+
}
|
|
2704
|
+
for (const variable of standaloneVariables ?? []) {
|
|
2705
|
+
variable.setStyle(mergeInlineBlockTypeStyle(variable.getStyle(), blockType));
|
|
2706
|
+
}
|
|
2707
|
+
applySemanticBlockType(selection$1, blockType);
|
|
2708
|
+
});
|
|
2709
|
+
}
|
|
2710
|
+
const FORMAT_MASKS$1 = {
|
|
2436
2711
|
bold: 1,
|
|
2437
2712
|
italic: 2,
|
|
2438
2713
|
strikethrough: 4,
|
|
@@ -2454,19 +2729,8 @@ function withSelectedVariableNodes(editor, updater) {
|
|
|
2454
2729
|
});
|
|
2455
2730
|
return updated;
|
|
2456
2731
|
}
|
|
2457
|
-
function getSelectedVariableNodes(editor) {
|
|
2458
|
-
let nodes = [];
|
|
2459
|
-
editor.getEditorState().read(() => {
|
|
2460
|
-
const selection2 = lexical.$getSelection();
|
|
2461
|
-
if (!lexical.$isNodeSelection(selection2)) {
|
|
2462
|
-
return;
|
|
2463
|
-
}
|
|
2464
|
-
nodes = selection2.getNodes().filter($isVariableNode);
|
|
2465
|
-
});
|
|
2466
|
-
return nodes;
|
|
2467
|
-
}
|
|
2468
2732
|
function toggleSelectedVariableFormat(editor, format) {
|
|
2469
|
-
const mask = FORMAT_MASKS[format];
|
|
2733
|
+
const mask = FORMAT_MASKS$1[format];
|
|
2470
2734
|
if (!mask) {
|
|
2471
2735
|
return false;
|
|
2472
2736
|
}
|
|
@@ -2492,17 +2756,6 @@ function applyFontSizeToSelectedVariables(editor, size) {
|
|
|
2492
2756
|
}
|
|
2493
2757
|
});
|
|
2494
2758
|
}
|
|
2495
|
-
function readSelectedVariableFormatting(editor) {
|
|
2496
|
-
const firstNode = getSelectedVariableNodes(editor)[0];
|
|
2497
|
-
if (!firstNode) {
|
|
2498
|
-
return {};
|
|
2499
|
-
}
|
|
2500
|
-
const style = firstNode.getStyle();
|
|
2501
|
-
return {
|
|
2502
|
-
fontFamily: extractFontFamilyFromStyle(style),
|
|
2503
|
-
fontSize: extractFontSizePtFromStyle(style)
|
|
2504
|
-
};
|
|
2505
|
-
}
|
|
2506
2759
|
const BLOCK_TYPE_OPTIONS = [
|
|
2507
2760
|
{ value: "paragraph", shortLabel: "P" },
|
|
2508
2761
|
{ value: "h1", shortLabel: "H1" },
|
|
@@ -2918,6 +3171,108 @@ const CanvasControls = () => {
|
|
|
2918
3171
|
)
|
|
2919
3172
|
] });
|
|
2920
3173
|
};
|
|
3174
|
+
const FORMAT_MASKS = {
|
|
3175
|
+
bold: 1,
|
|
3176
|
+
italic: 2,
|
|
3177
|
+
strikethrough: 4,
|
|
3178
|
+
underline: 8
|
|
3179
|
+
};
|
|
3180
|
+
function normalizeFontFamily(fontFamily) {
|
|
3181
|
+
if (fontFamily && SUPPORTED_FONTS.includes(fontFamily)) {
|
|
3182
|
+
return fontFamily;
|
|
3183
|
+
}
|
|
3184
|
+
return "Calibri";
|
|
3185
|
+
}
|
|
3186
|
+
function normalizeAlignment(alignment) {
|
|
3187
|
+
if (alignment === "center" || alignment === "right" || alignment === "justify") {
|
|
3188
|
+
return alignment;
|
|
3189
|
+
}
|
|
3190
|
+
return "left";
|
|
3191
|
+
}
|
|
3192
|
+
function getElementBlockType(node) {
|
|
3193
|
+
const topLevelElement = node.getTopLevelElementOrThrow();
|
|
3194
|
+
if (richText.$isHeadingNode(topLevelElement)) {
|
|
3195
|
+
return topLevelElement.getTag();
|
|
3196
|
+
}
|
|
3197
|
+
return "paragraph";
|
|
3198
|
+
}
|
|
3199
|
+
function getElementAlignment(node) {
|
|
3200
|
+
const topLevelElement = node.getTopLevelElementOrThrow();
|
|
3201
|
+
if (lexical.$isElementNode(topLevelElement)) {
|
|
3202
|
+
return normalizeAlignment(topLevelElement.getFormatType());
|
|
3203
|
+
}
|
|
3204
|
+
return "left";
|
|
3205
|
+
}
|
|
3206
|
+
function getInlineStyleTarget(nodes, anchorNode) {
|
|
3207
|
+
if (lexical.$isTextNode(anchorNode) || $isVariableNode(anchorNode)) {
|
|
3208
|
+
return anchorNode;
|
|
3209
|
+
}
|
|
3210
|
+
return nodes.find((node) => lexical.$isTextNode(node) || $isVariableNode(node)) ?? null;
|
|
3211
|
+
}
|
|
3212
|
+
function getInlineStyleFromNode(node) {
|
|
3213
|
+
if (lexical.$isTextNode(node) || $isVariableNode(node)) {
|
|
3214
|
+
return node.getStyle();
|
|
3215
|
+
}
|
|
3216
|
+
return "";
|
|
3217
|
+
}
|
|
3218
|
+
function hasInlineFormat(node, format) {
|
|
3219
|
+
if ($isVariableNode(node)) {
|
|
3220
|
+
return (node.getFormat() & FORMAT_MASKS[format]) !== 0;
|
|
3221
|
+
}
|
|
3222
|
+
if (lexical.$isTextNode(node) && "hasFormat" in node && typeof node.hasFormat === "function") {
|
|
3223
|
+
return node.hasFormat(format);
|
|
3224
|
+
}
|
|
3225
|
+
if (lexical.$isTextNode(node) && "getFormat" in node && typeof node.getFormat === "function") {
|
|
3226
|
+
return (node.getFormat() & FORMAT_MASKS[format]) !== 0;
|
|
3227
|
+
}
|
|
3228
|
+
return false;
|
|
3229
|
+
}
|
|
3230
|
+
function readToolbarStyleSnapshot(editor, editorState = editor.getEditorState()) {
|
|
3231
|
+
let snapshot = DEFAULT_TOOLBAR_STYLE_SNAPSHOT;
|
|
3232
|
+
editorState.read(() => {
|
|
3233
|
+
const currentSelection = lexical.$getSelection();
|
|
3234
|
+
const selection2 = lexical.$isNodeSelection(currentSelection) ? currentSelection : lexical.$createRangeSelectionFromDom(window.getSelection(), editor) ?? currentSelection;
|
|
3235
|
+
if (lexical.$isNodeSelection(selection2)) {
|
|
3236
|
+
const variableNodes = selection2.getNodes().filter($isVariableNode);
|
|
3237
|
+
if (variableNodes.length === 0) {
|
|
3238
|
+
return;
|
|
3239
|
+
}
|
|
3240
|
+
const firstVariableNode = variableNodes[0];
|
|
3241
|
+
const style2 = firstVariableNode.getStyle();
|
|
3242
|
+
snapshot = {
|
|
3243
|
+
blockType: extractInlineBlockTypeFromStyle(style2) ?? getElementBlockType(firstVariableNode),
|
|
3244
|
+
fontFamily: normalizeFontFamily(extractFontFamilyFromStyle(style2)),
|
|
3245
|
+
fontSize: extractFontSizePtFromStyle(style2) ?? DEFAULT_FONT_SIZE,
|
|
3246
|
+
alignment: getElementAlignment(firstVariableNode),
|
|
3247
|
+
isBold: variableNodes.every((node) => (node.getFormat() & FORMAT_MASKS.bold) !== 0),
|
|
3248
|
+
isItalic: variableNodes.every((node) => (node.getFormat() & FORMAT_MASKS.italic) !== 0),
|
|
3249
|
+
isUnderline: variableNodes.every((node) => (node.getFormat() & FORMAT_MASKS.underline) !== 0),
|
|
3250
|
+
isStrikethrough: variableNodes.every((node) => (node.getFormat() & FORMAT_MASKS.strikethrough) !== 0),
|
|
3251
|
+
hasSelectedVariable: true
|
|
3252
|
+
};
|
|
3253
|
+
return;
|
|
3254
|
+
}
|
|
3255
|
+
if (!lexical.$isRangeSelection(selection2)) {
|
|
3256
|
+
return;
|
|
3257
|
+
}
|
|
3258
|
+
const anchorNode = selection2.anchor.getNode();
|
|
3259
|
+
const inlineStyleTarget = getInlineStyleTarget(selection2.getNodes(), anchorNode);
|
|
3260
|
+
const style = selection2.style || getInlineStyleFromNode(inlineStyleTarget);
|
|
3261
|
+
const isCollapsed = selection2.isCollapsed();
|
|
3262
|
+
snapshot = {
|
|
3263
|
+
blockType: extractInlineBlockTypeFromStyle(style) ?? getElementBlockType(anchorNode),
|
|
3264
|
+
fontFamily: normalizeFontFamily(extractFontFamilyFromStyle(style)),
|
|
3265
|
+
fontSize: extractFontSizePtFromStyle(style) ?? DEFAULT_FONT_SIZE,
|
|
3266
|
+
alignment: getElementAlignment(anchorNode),
|
|
3267
|
+
isBold: selection2.hasFormat("bold") || isCollapsed && hasInlineFormat(inlineStyleTarget, "bold"),
|
|
3268
|
+
isItalic: selection2.hasFormat("italic") || isCollapsed && hasInlineFormat(inlineStyleTarget, "italic"),
|
|
3269
|
+
isUnderline: selection2.hasFormat("underline") || isCollapsed && hasInlineFormat(inlineStyleTarget, "underline"),
|
|
3270
|
+
isStrikethrough: selection2.hasFormat("strikethrough") || isCollapsed && hasInlineFormat(inlineStyleTarget, "strikethrough"),
|
|
3271
|
+
hasSelectedVariable: false
|
|
3272
|
+
};
|
|
3273
|
+
});
|
|
3274
|
+
return snapshot;
|
|
3275
|
+
}
|
|
2921
3276
|
const Toolbar = () => {
|
|
2922
3277
|
const {
|
|
2923
3278
|
activeEditor,
|
|
@@ -2934,15 +3289,15 @@ const Toolbar = () => {
|
|
|
2934
3289
|
const { toolbarItems, toolbarEndItems } = useExtensions();
|
|
2935
3290
|
const toolbarConfig = useToolbarConfig();
|
|
2936
3291
|
const t = useTranslations();
|
|
2937
|
-
const
|
|
2938
|
-
const
|
|
2939
|
-
const
|
|
2940
|
-
const
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
3292
|
+
const toolbarStyleStore = useToolbarStyleStoreApi();
|
|
3293
|
+
const activeBlockType = useToolbarStyleStore((state) => state.blockType);
|
|
3294
|
+
const activeFontFamily = useToolbarStyleStore((state) => state.fontFamily);
|
|
3295
|
+
const activeFontSize = useToolbarStyleStore((state) => state.fontSize);
|
|
3296
|
+
const activeAlignment = useToolbarStyleStore((state) => state.alignment);
|
|
3297
|
+
const isBoldActive = useToolbarStyleStore((state) => state.isBold);
|
|
3298
|
+
const isItalicActive = useToolbarStyleStore((state) => state.isItalic);
|
|
3299
|
+
const isUnderlineActive = useToolbarStyleStore((state) => state.isUnderline);
|
|
3300
|
+
const isStrikethroughActive = useToolbarStyleStore((state) => state.isStrikethrough);
|
|
2946
3301
|
const withBodySelection = React.useCallback(
|
|
2947
3302
|
(editor, action) => {
|
|
2948
3303
|
editor.update(() => {
|
|
@@ -2980,38 +3335,11 @@ const Toolbar = () => {
|
|
|
2980
3335
|
);
|
|
2981
3336
|
React.useEffect(() => {
|
|
2982
3337
|
if (!activeEditor) {
|
|
2983
|
-
|
|
2984
|
-
setActiveFontFamily("Calibri");
|
|
2985
|
-
setActiveFontSize(DEFAULT_FONT_SIZE);
|
|
3338
|
+
toolbarStyleStore.getState().reset();
|
|
2986
3339
|
return;
|
|
2987
3340
|
}
|
|
2988
|
-
const updateSelectionState = () => {
|
|
2989
|
-
|
|
2990
|
-
if (selectedVariables.length > 0) {
|
|
2991
|
-
const formatting = readSelectedVariableFormatting(activeEditor);
|
|
2992
|
-
setActiveBlockType("paragraph");
|
|
2993
|
-
setActiveFontFamily(normalizeFontFamily(formatting.fontFamily));
|
|
2994
|
-
setActiveFontSize(formatting.fontSize ?? DEFAULT_FONT_SIZE);
|
|
2995
|
-
return;
|
|
2996
|
-
}
|
|
2997
|
-
setActiveBlockType(getActiveBlockType(activeEditor));
|
|
2998
|
-
let nextFontFamily = "Calibri";
|
|
2999
|
-
let nextFontSize = DEFAULT_FONT_SIZE;
|
|
3000
|
-
activeEditor.getEditorState().read(() => {
|
|
3001
|
-
const selection2 = lexical.$getSelection();
|
|
3002
|
-
if (!lexical.$isRangeSelection(selection2)) {
|
|
3003
|
-
return;
|
|
3004
|
-
}
|
|
3005
|
-
const textNode = selection2.getNodes().find(lexical.$isTextNode);
|
|
3006
|
-
if (!textNode) {
|
|
3007
|
-
return;
|
|
3008
|
-
}
|
|
3009
|
-
const style = textNode.getStyle();
|
|
3010
|
-
nextFontFamily = normalizeFontFamily(extractFontFamilyFromStyle(style));
|
|
3011
|
-
nextFontSize = extractFontSizePtFromStyle(style) ?? DEFAULT_FONT_SIZE;
|
|
3012
|
-
});
|
|
3013
|
-
setActiveFontFamily(nextFontFamily);
|
|
3014
|
-
setActiveFontSize(nextFontSize);
|
|
3341
|
+
const updateSelectionState = (editorState = activeEditor.getEditorState()) => {
|
|
3342
|
+
toolbarStyleStore.getState().setSnapshot(readToolbarStyleSnapshot(activeEditor, editorState));
|
|
3015
3343
|
};
|
|
3016
3344
|
updateSelectionState();
|
|
3017
3345
|
const unregisterSelectionChange = activeEditor.registerCommand(
|
|
@@ -3022,14 +3350,14 @@ const Toolbar = () => {
|
|
|
3022
3350
|
},
|
|
3023
3351
|
lexical.COMMAND_PRIORITY_LOW
|
|
3024
3352
|
);
|
|
3025
|
-
const unregisterUpdateListener = activeEditor.registerUpdateListener(() => {
|
|
3026
|
-
updateSelectionState();
|
|
3353
|
+
const unregisterUpdateListener = activeEditor.registerUpdateListener(({ editorState }) => {
|
|
3354
|
+
updateSelectionState(editorState);
|
|
3027
3355
|
});
|
|
3028
3356
|
return () => {
|
|
3029
3357
|
unregisterSelectionChange();
|
|
3030
3358
|
unregisterUpdateListener();
|
|
3031
3359
|
};
|
|
3032
|
-
}, [activeEditor,
|
|
3360
|
+
}, [activeEditor, toolbarStyleStore]);
|
|
3033
3361
|
const handleBold = React.useCallback(() => {
|
|
3034
3362
|
debug("toolbar", `bold (globalSelection=${globalSelectionActive}, editors=${editorRegistry.all().length}, hasEditor=${!!activeEditor})`);
|
|
3035
3363
|
runToolbarAction(t.history.actions.boldApplied, () => {
|
|
@@ -3214,17 +3542,17 @@ const Toolbar = () => {
|
|
|
3214
3542
|
] }),
|
|
3215
3543
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
3216
3544
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "format-group", children: [
|
|
3217
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.bold, testId: "btn-bold", onClick: handleBold, children: /* @__PURE__ */ jsxRuntime.jsx(Bold, { size: 15 }) }),
|
|
3218
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.italic, testId: "btn-italic", onClick: handleItalic, children: /* @__PURE__ */ jsxRuntime.jsx(Italic, { size: 15 }) }),
|
|
3219
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.underline, testId: "btn-underline", onClick: handleUnderline, children: /* @__PURE__ */ jsxRuntime.jsx(Underline, { size: 15 }) }),
|
|
3220
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.strikethrough, testId: "btn-strike", onClick: handleStrikethrough, children: /* @__PURE__ */ jsxRuntime.jsx(Strikethrough, { size: 15 }) })
|
|
3545
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.bold, testId: "btn-bold", active: isBoldActive, onClick: handleBold, children: /* @__PURE__ */ jsxRuntime.jsx(Bold, { size: 15 }) }),
|
|
3546
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.italic, testId: "btn-italic", active: isItalicActive, onClick: handleItalic, children: /* @__PURE__ */ jsxRuntime.jsx(Italic, { size: 15 }) }),
|
|
3547
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.underline, testId: "btn-underline", active: isUnderlineActive, onClick: handleUnderline, children: /* @__PURE__ */ jsxRuntime.jsx(Underline, { size: 15 }) }),
|
|
3548
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.strikethrough, testId: "btn-strike", active: isStrikethroughActive, onClick: handleStrikethrough, children: /* @__PURE__ */ jsxRuntime.jsx(Strikethrough, { size: 15 }) })
|
|
3221
3549
|
] }),
|
|
3222
3550
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
3223
3551
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "align-group", children: [
|
|
3224
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignLeft, testId: "btn-align-left", onClick: handleAlignLeft, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignStart, { size: 15 }) }),
|
|
3225
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignCenter, testId: "btn-align-center", onClick: handleAlignCenter, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignCenter, { size: 15 }) }),
|
|
3226
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignRight, testId: "btn-align-right", onClick: handleAlignRight, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignEnd, { size: 15 }) }),
|
|
3227
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.justify, testId: "btn-align-justify", onClick: handleAlignJustify, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignJustify, { size: 15 }) })
|
|
3552
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignLeft, testId: "btn-align-left", active: activeAlignment === "left", onClick: handleAlignLeft, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignStart, { size: 15 }) }),
|
|
3553
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignCenter, testId: "btn-align-center", active: activeAlignment === "center", onClick: handleAlignCenter, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignCenter, { size: 15 }) }),
|
|
3554
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignRight, testId: "btn-align-right", active: activeAlignment === "right", onClick: handleAlignRight, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignEnd, { size: 15 }) }),
|
|
3555
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.justify, testId: "btn-align-justify", active: activeAlignment === "justify", onClick: handleAlignJustify, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignJustify, { size: 15 }) })
|
|
3228
3556
|
] }),
|
|
3229
3557
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
3230
3558
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "list-group", children: [
|
|
@@ -3275,6 +3603,7 @@ const ToolbarIconButton = ({
|
|
|
3275
3603
|
type: "button",
|
|
3276
3604
|
title,
|
|
3277
3605
|
"aria-label": title,
|
|
3606
|
+
"aria-pressed": active,
|
|
3278
3607
|
disabled,
|
|
3279
3608
|
onMouseDown: (e) => e.preventDefault(),
|
|
3280
3609
|
onClick,
|
|
@@ -3785,14 +4114,18 @@ const ActiveEditorPlugin = ({
|
|
|
3785
4114
|
]);
|
|
3786
4115
|
React.useEffect(() => {
|
|
3787
4116
|
const caretPosition = { pageId, region };
|
|
3788
|
-
const
|
|
4117
|
+
const markEditorActive = () => {
|
|
3789
4118
|
setActivePageId(pageId);
|
|
3790
4119
|
setActiveEditor(editor, caretPosition);
|
|
3791
4120
|
onFocus == null ? void 0 : onFocus(editor);
|
|
3792
4121
|
};
|
|
3793
4122
|
return editor.registerRootListener((rootElement, prevRootElement) => {
|
|
3794
|
-
prevRootElement == null ? void 0 : prevRootElement.removeEventListener("focusin",
|
|
3795
|
-
|
|
4123
|
+
prevRootElement == null ? void 0 : prevRootElement.removeEventListener("focusin", markEditorActive);
|
|
4124
|
+
prevRootElement == null ? void 0 : prevRootElement.removeEventListener("mousedown", markEditorActive);
|
|
4125
|
+
prevRootElement == null ? void 0 : prevRootElement.removeEventListener("pointerdown", markEditorActive);
|
|
4126
|
+
rootElement == null ? void 0 : rootElement.addEventListener("focusin", markEditorActive);
|
|
4127
|
+
rootElement == null ? void 0 : rootElement.addEventListener("mousedown", markEditorActive);
|
|
4128
|
+
rootElement == null ? void 0 : rootElement.addEventListener("pointerdown", markEditorActive);
|
|
3796
4129
|
});
|
|
3797
4130
|
}, [editor, onFocus, pageId, region, setActiveEditor, setActivePageId]);
|
|
3798
4131
|
React.useEffect(() => {
|
|
@@ -4462,7 +4795,7 @@ const EditorRegistryPlugin = ({ pageId }) => {
|
|
|
4462
4795
|
editorRegistry.register(pageId, editor);
|
|
4463
4796
|
debug("registry", `registered editor for page ${shortId(pageId)}`);
|
|
4464
4797
|
return () => {
|
|
4465
|
-
editorRegistry.unregister(pageId);
|
|
4798
|
+
editorRegistry.unregister(pageId, editor);
|
|
4466
4799
|
debug("registry", `unregistered editor for page ${shortId(pageId)}`);
|
|
4467
4800
|
};
|
|
4468
4801
|
}, [editor, pageId, editorRegistry]);
|
|
@@ -4786,7 +5119,7 @@ const PageView = React.memo(({
|
|
|
4786
5119
|
onMoveToPreviousPage,
|
|
4787
5120
|
onMoveToNextPage
|
|
4788
5121
|
}) => {
|
|
4789
|
-
const { document: document2, dispatch, setActivePageId } = useDocument();
|
|
5122
|
+
const { document: document2, dispatch, editorRegistry, setActiveEditor, setActivePageId } = useDocument();
|
|
4790
5123
|
const t = useTranslations();
|
|
4791
5124
|
const page = document2.pages.find((p) => p.id === pageId);
|
|
4792
5125
|
const showHeaderFooter = document2.headerFooterEnabled;
|
|
@@ -4816,7 +5149,11 @@ const PageView = React.memo(({
|
|
|
4816
5149
|
);
|
|
4817
5150
|
const handleFocus = React.useCallback(() => {
|
|
4818
5151
|
setActivePageId(pageId);
|
|
4819
|
-
|
|
5152
|
+
const editor = editorRegistry.get(pageId);
|
|
5153
|
+
if (editor) {
|
|
5154
|
+
setActiveEditor(editor, { pageId, region: "body" });
|
|
5155
|
+
}
|
|
5156
|
+
}, [editorRegistry, pageId, setActiveEditor, setActivePageId]);
|
|
4820
5157
|
const handleOverflow = React.useCallback(
|
|
4821
5158
|
(overflowContent, cause) => {
|
|
4822
5159
|
onOverflow == null ? void 0 : onOverflow(overflowContent, cause);
|
|
@@ -5476,6 +5813,20 @@ function insertDocumentContent(editor, document2) {
|
|
|
5476
5813
|
});
|
|
5477
5814
|
return inserted;
|
|
5478
5815
|
}
|
|
5816
|
+
function resolveDocumentInsertTarget({
|
|
5817
|
+
activeEditor,
|
|
5818
|
+
activeCaretPosition,
|
|
5819
|
+
activePageId,
|
|
5820
|
+
editorRegistry
|
|
5821
|
+
}) {
|
|
5822
|
+
if (activeEditor && (activeCaretPosition == null ? void 0 : activeCaretPosition.region) === "body") {
|
|
5823
|
+
return activeEditor;
|
|
5824
|
+
}
|
|
5825
|
+
if (activePageId) {
|
|
5826
|
+
return editorRegistry.get(activePageId) ?? null;
|
|
5827
|
+
}
|
|
5828
|
+
return editorRegistry.all()[0] ?? null;
|
|
5829
|
+
}
|
|
5479
5830
|
function selectEntireDocument(rootElement, selectionBuffer) {
|
|
5480
5831
|
if (!rootElement || !selectionBuffer) {
|
|
5481
5832
|
return;
|
|
@@ -5681,8 +6032,10 @@ const EditorChrome = ({
|
|
|
5681
6032
|
const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, onSave, className }, ref) => {
|
|
5682
6033
|
const {
|
|
5683
6034
|
document: doc,
|
|
6035
|
+
activePageId,
|
|
5684
6036
|
activeEditor,
|
|
5685
6037
|
activeCaretPosition,
|
|
6038
|
+
editorRegistry,
|
|
5686
6039
|
historySidebarOpen,
|
|
5687
6040
|
runHistoryAction,
|
|
5688
6041
|
setHistorySidebarOpen
|
|
@@ -5691,7 +6044,6 @@ const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, on
|
|
|
5691
6044
|
const t = useTranslations();
|
|
5692
6045
|
const documentRef = React.useRef(doc);
|
|
5693
6046
|
const activeEditorRef = React.useRef(activeEditor);
|
|
5694
|
-
const activeCaretRegionRef = React.useRef(activeCaretPosition == null ? void 0 : activeCaretPosition.region);
|
|
5695
6047
|
const historySidebarOpenRef = React.useRef(historySidebarOpen);
|
|
5696
6048
|
const runHistoryActionRef = React.useRef(runHistoryAction);
|
|
5697
6049
|
const insertedDocumentContentLabelRef = React.useRef(t.history.actions.insertedDocumentContent);
|
|
@@ -5701,9 +6053,6 @@ const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, on
|
|
|
5701
6053
|
React.useEffect(() => {
|
|
5702
6054
|
activeEditorRef.current = activeEditor;
|
|
5703
6055
|
}, [activeEditor]);
|
|
5704
|
-
React.useEffect(() => {
|
|
5705
|
-
activeCaretRegionRef.current = activeCaretPosition == null ? void 0 : activeCaretPosition.region;
|
|
5706
|
-
}, [activeCaretPosition == null ? void 0 : activeCaretPosition.region]);
|
|
5707
6056
|
React.useEffect(() => {
|
|
5708
6057
|
historySidebarOpenRef.current = historySidebarOpen;
|
|
5709
6058
|
}, [historySidebarOpen]);
|
|
@@ -5726,8 +6075,13 @@ const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, on
|
|
|
5726
6075
|
setHistorySidebarOpen(!historySidebarOpenRef.current);
|
|
5727
6076
|
};
|
|
5728
6077
|
handle.insertDocumentContent = (documentToInsert) => {
|
|
5729
|
-
const
|
|
5730
|
-
|
|
6078
|
+
const targetEditor = resolveDocumentInsertTarget({
|
|
6079
|
+
activeEditor: activeEditorRef.current,
|
|
6080
|
+
activeCaretPosition,
|
|
6081
|
+
activePageId,
|
|
6082
|
+
editorRegistry
|
|
6083
|
+
});
|
|
6084
|
+
if (!targetEditor) {
|
|
5731
6085
|
return false;
|
|
5732
6086
|
}
|
|
5733
6087
|
let inserted = false;
|
|
@@ -5738,7 +6092,7 @@ const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, on
|
|
|
5738
6092
|
region: "document"
|
|
5739
6093
|
},
|
|
5740
6094
|
() => {
|
|
5741
|
-
inserted = insertDocumentContent(
|
|
6095
|
+
inserted = insertDocumentContent(targetEditor, documentToInsert);
|
|
5742
6096
|
}
|
|
5743
6097
|
);
|
|
5744
6098
|
return inserted;
|