]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/framework/helpers/table-selection-handler.ts
Opensearch: Fixed XML declaration when php short tags enabled
[bookstack] / resources / js / wysiwyg / ui / framework / helpers / table-selection-handler.ts
1 import {$getNodeByKey, LexicalEditor} from "lexical";
2 import {NodeKey} from "lexical/LexicalNode";
3 import {
4     $isTableNode,
5     applyTableHandlers,
6     HTMLTableElementWithWithTableSelectionState,
7     TableNode,
8     TableObserver
9 } from "@lexical/table";
10
11 // File adapted from logic in:
12 // https://github.com/facebook/lexical/blob/f373759a7849f473d34960a6bf4e34b2a011e762/packages/lexical-react/src/LexicalTablePlugin.ts#L49
13 // Copyright (c) Meta Platforms, Inc. and affiliates.
14 // License: MIT
15
16 class TableSelectionHandler {
17
18     protected editor: LexicalEditor
19     protected tableSelections = new Map<NodeKey, TableObserver>();
20     protected unregisterMutationListener = () => {};
21
22     constructor(editor: LexicalEditor) {
23         this.editor = editor;
24         this.init();
25     }
26
27     protected init() {
28         this.unregisterMutationListener = this.editor.registerMutationListener(TableNode, (mutations) => {
29             for (const [nodeKey, mutation] of mutations) {
30                 if (mutation === 'created') {
31                     this.editor.getEditorState().read(() => {
32                         const tableNode = $getNodeByKey<TableNode>(nodeKey);
33                         if ($isTableNode(tableNode)) {
34                             this.initializeTableNode(tableNode);
35                         }
36                     });
37                 } else if (mutation === 'destroyed') {
38                     const tableSelection = this.tableSelections.get(nodeKey);
39
40                     if (tableSelection !== undefined) {
41                         tableSelection.removeListeners();
42                         this.tableSelections.delete(nodeKey);
43                     }
44                 }
45             }
46         });
47     }
48
49     protected initializeTableNode(tableNode: TableNode) {
50         const nodeKey = tableNode.getKey();
51         const tableElement = this.editor.getElementByKey(
52             nodeKey,
53         ) as HTMLTableElementWithWithTableSelectionState;
54         if (tableElement && !this.tableSelections.has(nodeKey)) {
55             const tableSelection = applyTableHandlers(
56                 tableNode,
57                 tableElement,
58                 this.editor,
59                 true,
60             );
61             this.tableSelections.set(nodeKey, tableSelection);
62         }
63     };
64
65     teardown() {
66         this.unregisterMutationListener();
67         for (const [, tableSelection] of this.tableSelections) {
68             tableSelection.removeListeners();
69         }
70     }
71 }
72
73 export function registerTableSelectionHandler(editor: LexicalEditor): (() => void) {
74     const resizer = new TableSelectionHandler(editor);
75
76     return () => {
77         resizer.teardown();
78     };
79 }