]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/framework/blocks/table-creator.ts
Opensearch: Fixed XML declaration when php short tags enabled
[bookstack] / resources / js / wysiwyg / ui / framework / blocks / table-creator.ts
1 import {EditorUiElement} from "../core";
2 import {$createTableNodeWithDimensions} from "@lexical/table";
3 import {$insertNewBlockNodeAtSelection} from "../../../utils/selection";
4 import {el} from "../../../utils/dom";
5
6
7 export class EditorTableCreator extends EditorUiElement {
8
9     buildDOM(): HTMLElement {
10         const size = 10;
11         const rows: HTMLElement[] = [];
12         const cells: HTMLElement[] = [];
13
14         for (let row = 1; row < size + 1; row++) {
15             const rowCells = [];
16             for (let column = 1; column < size + 1; column++) {
17                 const cell = el('div', {
18                     class: 'editor-table-creator-cell',
19                     'data-rows': String(row),
20                     'data-columns': String(column),
21                 });
22                 rowCells.push(cell);
23                 cells.push(cell);
24             }
25             rows.push(el('div', {
26                 class: 'editor-table-creator-row'
27             }, rowCells));
28         }
29
30         const display = el('div', {class: 'editor-table-creator-display'}, ['0 x 0']);
31         const grid = el('div', {class: 'editor-table-creator-grid'}, rows);
32         grid.addEventListener('mousemove', event => {
33             const cell = (event.target as HTMLElement).closest('.editor-table-creator-cell') as HTMLElement|null;
34             if (cell) {
35                 const row = Number(cell.dataset.rows || 0);
36                 const column = Number(cell.dataset.columns || 0);
37                 this.updateGridSelection(row, column, cells, display)
38             }
39         });
40
41         grid.addEventListener('click', event => {
42             const cell = (event.target as HTMLElement).closest('.editor-table-creator-cell');
43             if (cell) {
44                 this.onCellClick(cell as HTMLElement);
45             }
46         });
47
48         grid.addEventListener('mouseleave', event => {
49              this.updateGridSelection(0, 0, cells, display);
50         });
51
52         return el('div', {
53             class: 'editor-table-creator',
54         }, [
55             grid,
56             display,
57         ]);
58     }
59
60     updateGridSelection(rows: number, columns: number, cells: HTMLElement[], display: HTMLElement) {
61         for (const cell of cells) {
62             const active = Number(cell.dataset.rows) <= rows && Number(cell.dataset.columns) <= columns;
63             cell.classList.toggle('active', active);
64         }
65
66         display.textContent = `${rows} x ${columns}`;
67     }
68
69     onCellClick(cell: HTMLElement) {
70         const rows = Number(cell.dataset.rows || 0);
71         const columns = Number(cell.dataset.columns || 0);
72         if (rows < 1 || columns < 1) {
73             return;
74         }
75
76         const targetColWidth = Math.min(Math.round(840 / columns), 240);
77         const colWidths = Array(columns).fill(targetColWidth + 'px');
78
79         this.getContext().editor.update(() => {
80             const table = $createTableNodeWithDimensions(rows, columns, false);
81             table.setColWidths(colWidths);
82             $insertNewBlockNodeAtSelection(table);
83         });
84     }
85 }