]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/defaults/forms/tables.ts
Lexical: Kinda made row copy/paste work
[bookstack] / resources / js / wysiwyg / ui / defaults / forms / tables.ts
1 import {
2     EditorFormDefinition,
3     EditorFormFieldDefinition,
4     EditorFormTabs,
5     EditorSelectFormFieldDefinition
6 } from "../../framework/forms";
7 import {EditorUiContext} from "../../framework/core";
8 import {CustomTableCellNode} from "../../../nodes/custom-table-cell";
9 import {EditorFormModal} from "../../framework/modals";
10 import {$getSelection, ElementFormatType} from "lexical";
11 import {
12     $getTableCellColumnWidth,
13     $getTableCellsFromSelection,
14     $getTableRowsFromSelection,
15     $setTableCellColumnWidth
16 } from "../../../utils/tables";
17 import {formatSizeValue} from "../../../utils/dom";
18 import {CustomTableRowNode} from "../../../nodes/custom-table-row";
19
20 const borderStyleInput: EditorSelectFormFieldDefinition = {
21     label: 'Border style',
22     name: 'border_style',
23     type: 'select',
24     valuesByLabel: {
25         'Select...': '',
26         "Solid": 'solid',
27         "Dotted": 'dotted',
28         "Dashed": 'dashed',
29         "Double": 'double',
30         "Groove": 'groove',
31         "Ridge": 'ridge',
32         "Inset": 'inset',
33         "Outset": 'outset',
34         "None": 'none',
35         "Hidden": 'hidden',
36     }
37 };
38
39 const borderColorInput: EditorFormFieldDefinition = {
40     label: 'Border color',
41     name: 'border_color',
42     type: 'text',
43 };
44
45 const backgroundColorInput: EditorFormFieldDefinition = {
46     label: 'Background color',
47     name: 'background_color',
48     type: 'text',
49 };
50
51 const alignmentInput: EditorSelectFormFieldDefinition = {
52     label: 'Alignment',
53     name: 'align',
54     type: 'select',
55     valuesByLabel: {
56         'None': '',
57         'Left': 'left',
58         'Center': 'center',
59         'Right': 'right',
60     }
61 };
62
63 export function $showCellPropertiesForm(cell: CustomTableCellNode, context: EditorUiContext): EditorFormModal {
64     const styles = cell.getStyles();
65     const modalForm = context.manager.createModal('cell_properties');
66     modalForm.show({
67         width: $getTableCellColumnWidth(context.editor, cell),
68         height: styles.get('height') || '',
69         type: cell.getTag(),
70         h_align: cell.getFormatType(),
71         v_align: styles.get('vertical-align') || '',
72         border_width: styles.get('border-width') || '',
73         border_style: styles.get('border-style') || '',
74         border_color: styles.get('border-color') || '',
75         background_color: styles.get('background-color') || '',
76     });
77     return modalForm;
78 }
79
80 export const cellProperties: EditorFormDefinition = {
81     submitText: 'Save',
82     async action(formData, context: EditorUiContext) {
83         context.editor.update(() => {
84             const cells = $getTableCellsFromSelection($getSelection());
85             for (const cell of cells) {
86                 const width = formData.get('width')?.toString() || '';
87
88                 $setTableCellColumnWidth(cell, width);
89                 cell.updateTag(formData.get('type')?.toString() || '');
90                 cell.setFormat((formData.get('h_align')?.toString() || '') as ElementFormatType);
91
92                 const styles = cell.getStyles();
93                 styles.set('height', formatSizeValue(formData.get('height')?.toString() || ''));
94                 styles.set('vertical-align', formData.get('v_align')?.toString() || '');
95                 styles.set('border-width', formatSizeValue(formData.get('border_width')?.toString() || ''));
96                 styles.set('border-style', formData.get('border_style')?.toString() || '');
97                 styles.set('border-color', formData.get('border_color')?.toString() || '');
98                 styles.set('background-color', formData.get('background_color')?.toString() || '');
99
100                 cell.setStyles(styles);
101             }
102         });
103
104         return true;
105     },
106     fields: [
107         {
108             build() {
109                 const generalFields: EditorFormFieldDefinition[] = [
110                     {
111                         label: 'Width', // Colgroup width
112                         name: 'width',
113                         type: 'text',
114                     },
115                     {
116                         label: 'Height', // inline-style: height
117                         name: 'height',
118                         type: 'text',
119                     },
120                     {
121                         label: 'Cell type', // element
122                         name: 'type',
123                         type: 'select',
124                         valuesByLabel: {
125                             'Cell': 'td',
126                             'Header cell': 'th',
127                         }
128                     } as EditorSelectFormFieldDefinition,
129                     {
130                         ...alignmentInput, // class: 'align-right/left/center'
131                         label: 'Horizontal align',
132                         name: 'h_align',
133                     },
134                     {
135                         label: 'Vertical align', // inline-style: vertical-align
136                         name: 'v_align',
137                         type: 'select',
138                         valuesByLabel: {
139                             'None': '',
140                             'Top': 'top',
141                             'Middle': 'middle',
142                             'Bottom': 'bottom',
143                         }
144                     } as EditorSelectFormFieldDefinition,
145                 ];
146
147                 const advancedFields: EditorFormFieldDefinition[] = [
148                     {
149                         label: 'Border width', // inline-style: border-width
150                         name: 'border_width',
151                         type: 'text',
152                     },
153                     borderStyleInput, // inline-style: border-style
154                     borderColorInput, // inline-style: border-color
155                     backgroundColorInput, // inline-style: background-color
156                 ];
157
158                 return new EditorFormTabs([
159                     {
160                         label: 'General',
161                         contents: generalFields,
162                     },
163                     {
164                         label: 'Advanced',
165                         contents: advancedFields,
166                     }
167                 ])
168             }
169         },
170     ],
171 };
172
173 export function $showRowPropertiesForm(row: CustomTableRowNode, context: EditorUiContext): EditorFormModal {
174     const styles = row.getStyles();
175     const modalForm = context.manager.createModal('row_properties');
176     modalForm.show({
177         height: styles.get('height') || '',
178         border_style: styles.get('border-style') || '',
179         border_color: styles.get('border-color') || '',
180         background_color: styles.get('background-color') || '',
181     });
182     return modalForm;
183 }
184
185 export const rowProperties: EditorFormDefinition = {
186     submitText: 'Save',
187     async action(formData, context: EditorUiContext) {
188         context.editor.update(() => {
189             const rows = $getTableRowsFromSelection($getSelection());
190             for (const row of rows) {
191                 const styles = row.getStyles();
192                 styles.set('height', formatSizeValue(formData.get('height')?.toString() || ''));
193                 styles.set('border-style', formData.get('border_style')?.toString() || '');
194                 styles.set('border-color', formData.get('border_color')?.toString() || '');
195                 styles.set('background-color', formData.get('background_color')?.toString() || '');
196                 row.setStyles(styles);
197             }
198         });
199         return true;
200     },
201     fields: [
202         // Removed fields:
203         // Removed 'Row Type' as we don't currently support thead/tfoot elements
204         //  TinyMCE would move rows up/down into these parents when set
205         // Removed 'Alignment' since this was broken in our editor (applied alignment class to whole parent table)
206         {
207             label: 'Height', // style on tr: height
208             name: 'height',
209             type: 'text',
210         },
211         borderStyleInput, // style on tr: height
212         borderColorInput, // style on tr: height
213         backgroundColorInput, // style on tr: height
214     ],
215 };
216 export const tableProperties: EditorFormDefinition = {
217     submitText: 'Save',
218     async action(formData, context: EditorUiContext) {
219         // TODO
220         return true;
221     },
222     fields: [
223         {
224             build() {
225                 const generalFields: EditorFormFieldDefinition[] = [
226                     {
227                         label: 'Width',
228                         name: 'width',
229                         type: 'text',
230                     },
231                     {
232                         label: 'Height',
233                         name: 'height',
234                         type: 'text',
235                     },
236                     {
237                         label: 'Cell spacing',
238                         name: 'cell_spacing',
239                         type: 'text',
240                     },
241                     {
242                         label: 'Cell padding',
243                         name: 'cell_padding',
244                         type: 'text',
245                     },
246                     {
247                         label: 'Border width',
248                         name: 'border_width',
249                         type: 'text',
250                     },
251                     {
252                         label: 'caption',
253                         name: 'height',
254                         type: 'text', // TODO -
255                     },
256                     alignmentInput,
257                 ];
258
259                 const advancedFields: EditorFormFieldDefinition[] = [
260                     borderStyleInput,
261                     borderColorInput,
262                     backgroundColorInput,
263                 ];
264
265                 return new EditorFormTabs([
266                     {
267                         label: 'General',
268                         contents: generalFields,
269                     },
270                     {
271                         label: 'Advanced',
272                         contents: advancedFields,
273                     }
274                 ])
275             }
276         },
277     ],
278 };