1 import {EditorBasicButtonDefinition, EditorButtonDefinition} from "../../framework/buttons";
2 import tableIcon from "@icons/editor/table.svg";
3 import deleteIcon from "@icons/editor/table-delete.svg";
4 import deleteColumnIcon from "@icons/editor/table-delete-column.svg";
5 import deleteRowIcon from "@icons/editor/table-delete-row.svg";
6 import insertColumnAfterIcon from "@icons/editor/table-insert-column-after.svg";
7 import insertColumnBeforeIcon from "@icons/editor/table-insert-column-before.svg";
8 import insertRowAboveIcon from "@icons/editor/table-insert-row-above.svg";
9 import insertRowBelowIcon from "@icons/editor/table-insert-row-below.svg";
10 import {EditorUiContext} from "../../framework/core";
11 import {$getSelection, BaseSelection} from "lexical";
12 import {$isCustomTableNode} from "../../../nodes/custom-table";
14 $deleteTableColumn__EXPERIMENTAL,
15 $deleteTableRow__EXPERIMENTAL,
16 $insertTableColumn__EXPERIMENTAL,
17 $insertTableRow__EXPERIMENTAL,
18 $isTableNode, $isTableRowNode, $isTableSelection, $unmergeCell, TableCellNode,
19 } from "@lexical/table";
20 import {$getNodeFromSelection, $selectionContainsNodeType} from "../../../utils/selection";
21 import {$getParentOfType} from "../../../utils/nodes";
22 import {$isCustomTableCellNode} from "../../../nodes/custom-table-cell";
23 import {$showCellPropertiesForm, $showRowPropertiesForm} from "../forms/tables";
24 import {$mergeTableCellsInSelection} from "../../../utils/tables";
25 import {$isCustomTableRowNode} from "../../../nodes/custom-table-row";
27 const neverActive = (): boolean => false;
28 const cellNotSelected = (selection: BaseSelection|null) => !$selectionContainsNodeType(selection, $isCustomTableCellNode);
30 export const table: EditorBasicButtonDefinition = {
35 export const tableProperties: EditorButtonDefinition = {
36 label: 'Table properties',
38 action(context: EditorUiContext) {
39 context.editor.getEditorState().read(() => {
40 const cell = $getNodeFromSelection($getSelection(), $isCustomTableCellNode);
41 if (!$isCustomTableCellNode(cell)) {
45 const table = $getParentOfType(cell, $isTableNode);
46 const modalForm = context.manager.createModal('table_properties');
51 isActive: neverActive,
52 isDisabled: cellNotSelected,
55 export const clearTableFormatting: EditorButtonDefinition = {
56 label: 'Clear table formatting',
58 action(context: EditorUiContext) {
59 context.editor.getEditorState().read(() => {
60 const cell = $getNodeFromSelection($getSelection(), $isCustomTableCellNode);
61 if (!$isCustomTableCellNode(cell)) {
65 const table = $getParentOfType(cell, $isTableNode);
69 isActive: neverActive,
70 isDisabled: cellNotSelected,
73 export const resizeTableToContents: EditorButtonDefinition = {
74 label: 'Resize to contents',
76 action(context: EditorUiContext) {
77 context.editor.getEditorState().read(() => {
78 const cell = $getNodeFromSelection($getSelection(), $isCustomTableCellNode);
79 if (!$isCustomTableCellNode(cell)) {
83 const table = $getParentOfType(cell, $isCustomTableNode);
84 if (!$isCustomTableNode(table)) {
88 for (const row of table.getChildren()) {
89 if ($isTableRowNode(row)) {
90 // TODO - Come back later as this may depend on if we
91 // are using a custom table row
96 isActive: neverActive,
97 isDisabled: cellNotSelected,
100 export const deleteTable: EditorButtonDefinition = {
101 label: 'Delete table',
103 action(context: EditorUiContext) {
104 context.editor.update(() => {
105 const table = $getNodeFromSelection($getSelection(), $isCustomTableNode);
116 export const deleteTableMenuAction: EditorButtonDefinition = {
119 isDisabled(selection) {
120 return !$selectionContainsNodeType(selection, $isTableNode);
124 export const insertRowAbove: EditorButtonDefinition = {
125 label: 'Insert row before',
126 icon: insertRowAboveIcon,
127 action(context: EditorUiContext) {
128 context.editor.update(() => {
129 $insertTableRow__EXPERIMENTAL(false);
132 isActive: neverActive,
133 isDisabled: cellNotSelected,
136 export const insertRowBelow: EditorButtonDefinition = {
137 label: 'Insert row after',
138 icon: insertRowBelowIcon,
139 action(context: EditorUiContext) {
140 context.editor.update(() => {
141 $insertTableRow__EXPERIMENTAL(true);
144 isActive: neverActive,
145 isDisabled: cellNotSelected,
148 export const deleteRow: EditorButtonDefinition = {
151 action(context: EditorUiContext) {
152 context.editor.update(() => {
153 $deleteTableRow__EXPERIMENTAL();
156 isActive: neverActive,
157 isDisabled: cellNotSelected,
160 export const rowProperties: EditorButtonDefinition = {
161 label: 'Row properties',
163 action(context: EditorUiContext) {
164 context.editor.getEditorState().read(() => {
165 const cell = $getNodeFromSelection($getSelection(), $isCustomTableCellNode);
166 if (!$isCustomTableCellNode(cell)) {
170 const row = $getParentOfType(cell, $isCustomTableRowNode);
171 if ($isCustomTableRowNode(row)) {
172 $showRowPropertiesForm(row, context);
176 isActive: neverActive,
177 isDisabled: cellNotSelected,
180 export const cutRow: EditorButtonDefinition = {
183 action(context: EditorUiContext) {
184 context.editor.getEditorState().read(() => {
188 isActive: neverActive,
189 isDisabled: cellNotSelected,
192 export const copyRow: EditorButtonDefinition = {
195 action(context: EditorUiContext) {
196 context.editor.getEditorState().read(() => {
200 isActive: neverActive,
201 isDisabled: cellNotSelected,
204 export const pasteRowBefore: EditorButtonDefinition = {
205 label: 'Paste row before',
207 action(context: EditorUiContext) {
208 context.editor.getEditorState().read(() => {
212 isActive: neverActive,
213 isDisabled: cellNotSelected,
216 export const pasteRowAfter: EditorButtonDefinition = {
217 label: 'Paste row after',
219 action(context: EditorUiContext) {
220 context.editor.getEditorState().read(() => {
224 isActive: neverActive,
225 isDisabled: cellNotSelected,
228 export const cutColumn: EditorButtonDefinition = {
231 action(context: EditorUiContext) {
232 context.editor.getEditorState().read(() => {
236 isActive: neverActive,
237 isDisabled: cellNotSelected,
240 export const copyColumn: EditorButtonDefinition = {
241 label: 'Copy column',
243 action(context: EditorUiContext) {
244 context.editor.getEditorState().read(() => {
248 isActive: neverActive,
249 isDisabled: cellNotSelected,
252 export const pasteColumnBefore: EditorButtonDefinition = {
253 label: 'Paste column before',
255 action(context: EditorUiContext) {
256 context.editor.getEditorState().read(() => {
260 isActive: neverActive,
261 isDisabled: cellNotSelected,
264 export const pasteColumnAfter: EditorButtonDefinition = {
265 label: 'Paste column after',
267 action(context: EditorUiContext) {
268 context.editor.getEditorState().read(() => {
272 isActive: neverActive,
273 isDisabled: cellNotSelected,
276 export const insertColumnBefore: EditorButtonDefinition = {
277 label: 'Insert column before',
278 icon: insertColumnBeforeIcon,
279 action(context: EditorUiContext) {
280 context.editor.update(() => {
281 $insertTableColumn__EXPERIMENTAL(false);
289 export const insertColumnAfter: EditorButtonDefinition = {
290 label: 'Insert column after',
291 icon: insertColumnAfterIcon,
292 action(context: EditorUiContext) {
293 context.editor.update(() => {
294 $insertTableColumn__EXPERIMENTAL(true);
302 export const deleteColumn: EditorButtonDefinition = {
303 label: 'Delete column',
304 icon: deleteColumnIcon,
305 action(context: EditorUiContext) {
306 context.editor.update(() => {
307 $deleteTableColumn__EXPERIMENTAL();
315 export const cellProperties: EditorButtonDefinition = {
316 label: 'Cell properties',
317 action(context: EditorUiContext) {
318 context.editor.getEditorState().read(() => {
319 const cell = $getNodeFromSelection($getSelection(), $isCustomTableCellNode);
320 if ($isCustomTableCellNode(cell)) {
321 $showCellPropertiesForm(cell, context);
325 isActive: neverActive,
326 isDisabled: cellNotSelected,
329 export const mergeCells: EditorButtonDefinition = {
330 label: 'Merge cells',
331 action(context: EditorUiContext) {
332 context.editor.update(() => {
333 const selection = $getSelection();
334 if ($isTableSelection(selection)) {
335 $mergeTableCellsInSelection(selection);
339 isActive: neverActive,
340 isDisabled(selection) {
341 return !$isTableSelection(selection);
345 export const splitCell: EditorButtonDefinition = {
347 action(context: EditorUiContext) {
348 context.editor.update(() => {
352 isActive: neverActive,
353 isDisabled(selection) {
354 const cell = $getNodeFromSelection(selection, $isCustomTableCellNode) as TableCellNode|null;
356 const merged = cell.getRowSpan() > 1 || cell.getColSpan() > 1;