]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/nodes/custom-table-cell-node.ts
Lexical: Started linking up cell properties form
[bookstack] / resources / js / wysiwyg / nodes / custom-table-cell-node.ts
1 import {EditorConfig} from "lexical/LexicalEditor";
2 import {DOMExportOutput, LexicalEditor, LexicalNode, Spread} from "lexical";
3
4 import {SerializedTableCellNode, TableCellHeaderStates, TableCellNode} from "@lexical/table";
5 import {TableCellHeaderState} from "@lexical/table/LexicalTableCellNode";
6
7 export type SerializedCustomTableCellNode = Spread<{
8     styles: Record<string, string>,
9 }, SerializedTableCellNode>
10
11 export class CustomTableCellNode extends TableCellNode {
12     __styles: Map<string, string> = new Map;
13
14     static getType(): string {
15         return 'custom-table-cell';
16     }
17
18     static clone(node: CustomTableCellNode): CustomTableCellNode {
19         const cellNode = new CustomTableCellNode(
20             node.__headerState,
21             node.__colSpan,
22             node.__width,
23             node.__key,
24         );
25         cellNode.__rowSpan = node.__rowSpan;
26         cellNode.__styles = new Map(node.__styles);
27         return cellNode;
28     }
29
30     getStyles(): Map<string, string> {
31         const self = this.getLatest();
32         return new Map(self.__styles);
33     }
34
35     setStyles(styles: Map<string, string>): void {
36         const self = this.getWritable();
37         self.__styles = new Map(styles);
38     }
39
40     updateTag(tag: string): void {
41         const isHeader = tag.toLowerCase() === 'th';
42         const state = isHeader ? TableCellHeaderStates.ROW : TableCellHeaderStates.NO_STATUS;
43         const self = this.getWritable();
44         self.__headerState = state;
45     }
46
47     createDOM(config: EditorConfig): HTMLElement {
48         const element = super.createDOM(config);
49
50         for (const [name, value] of this.__styles.entries()) {
51             element.style.setProperty(name, value);
52         }
53
54         return element;
55     }
56
57     // TODO - Import DOM
58
59     updateDOM(prevNode: CustomTableCellNode): boolean {
60         return super.updateDOM(prevNode)
61             || this.__styles !== prevNode.__styles;
62     }
63
64     exportDOM(editor: LexicalEditor): DOMExportOutput {
65         const element = this.createDOM(editor._config);
66         return {
67             element
68         };
69     }
70
71     exportJSON(): SerializedCustomTableCellNode {
72         return {
73             ...super.exportJSON(),
74             type: 'custom-table-cell',
75             styles: Object.fromEntries(this.__styles),
76         };
77     }
78 }
79
80 export function $createCustomTableCellNode(
81     headerState: TableCellHeaderState,
82     colSpan = 1,
83     width?: number,
84 ): CustomTableCellNode {
85     return new CustomTableCellNode(headerState, colSpan, width);
86 }
87
88 export function $isCustomTableCellNode(node: LexicalNode | null | undefined): node is CustomTableCellNode {
89     return node instanceof CustomTableCellNode;
90 }