]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/lexical/table/LexicalTableRowNode.ts
Lexical: Imported core lexical libs
[bookstack] / resources / js / wysiwyg / lexical / table / LexicalTableRowNode.ts
1 /**
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  *
7  */
8
9 import type {Spread} from 'lexical';
10
11 import {addClassNamesToElement} from '@lexical/utils';
12 import {
13   $applyNodeReplacement,
14   DOMConversionMap,
15   DOMConversionOutput,
16   EditorConfig,
17   ElementNode,
18   LexicalNode,
19   NodeKey,
20   SerializedElementNode,
21 } from 'lexical';
22
23 import {PIXEL_VALUE_REG_EXP} from './constants';
24
25 export type SerializedTableRowNode = Spread<
26   {
27     height?: number;
28   },
29   SerializedElementNode
30 >;
31
32 /** @noInheritDoc */
33 export class TableRowNode extends ElementNode {
34   /** @internal */
35   __height?: number;
36
37   static getType(): string {
38     return 'tablerow';
39   }
40
41   static clone(node: TableRowNode): TableRowNode {
42     return new TableRowNode(node.__height, node.__key);
43   }
44
45   static importDOM(): DOMConversionMap | null {
46     return {
47       tr: (node: Node) => ({
48         conversion: $convertTableRowElement,
49         priority: 0,
50       }),
51     };
52   }
53
54   static importJSON(serializedNode: SerializedTableRowNode): TableRowNode {
55     return $createTableRowNode(serializedNode.height);
56   }
57
58   constructor(height?: number, key?: NodeKey) {
59     super(key);
60     this.__height = height;
61   }
62
63   exportJSON(): SerializedTableRowNode {
64     return {
65       ...super.exportJSON(),
66       ...(this.getHeight() && {height: this.getHeight()}),
67       type: 'tablerow',
68       version: 1,
69     };
70   }
71
72   createDOM(config: EditorConfig): HTMLElement {
73     const element = document.createElement('tr');
74
75     if (this.__height) {
76       element.style.height = `${this.__height}px`;
77     }
78
79     addClassNamesToElement(element, config.theme.tableRow);
80
81     return element;
82   }
83
84   isShadowRoot(): boolean {
85     return true;
86   }
87
88   setHeight(height: number): number | null | undefined {
89     const self = this.getWritable();
90     self.__height = height;
91     return this.__height;
92   }
93
94   getHeight(): number | undefined {
95     return this.getLatest().__height;
96   }
97
98   updateDOM(prevNode: TableRowNode): boolean {
99     return prevNode.__height !== this.__height;
100   }
101
102   canBeEmpty(): false {
103     return false;
104   }
105
106   canIndent(): false {
107     return false;
108   }
109 }
110
111 export function $convertTableRowElement(domNode: Node): DOMConversionOutput {
112   const domNode_ = domNode as HTMLTableCellElement;
113   let height: number | undefined = undefined;
114
115   if (PIXEL_VALUE_REG_EXP.test(domNode_.style.height)) {
116     height = parseFloat(domNode_.style.height);
117   }
118
119   return {node: $createTableRowNode(height)};
120 }
121
122 export function $createTableRowNode(height?: number): TableRowNode {
123   return $applyNodeReplacement(new TableRowNode(height));
124 }
125
126 export function $isTableRowNode(
127   node: LexicalNode | null | undefined,
128 ): node is TableRowNode {
129   return node instanceof TableRowNode;
130 }