@domternal/extension-table 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,273 @@
1
+ import { CommandSpec, Node } from '@domternal/core';
2
+ import { Node as Node$1, Schema } from '@domternal/pm/model';
3
+ import { EditorView, NodeView } from '@domternal/pm/view';
4
+ import { EditorState, Transaction } from '@domternal/pm/state';
5
+ export { CellSelection, TableMap } from '@domternal/pm/tables';
6
+
7
+ /**
8
+ * Table Node
9
+ *
10
+ * Block-level table container using HTML <table>.
11
+ * Built on prosemirror-tables for cell selection, keyboard nav, and table editing.
12
+ *
13
+ * Commands (18):
14
+ * - insertTable: Insert new table with configurable rows/cols/header
15
+ * - deleteTable: Delete entire table
16
+ * - addRowBefore / addRowAfter: Insert row
17
+ * - deleteRow: Delete current row
18
+ * - addColumnBefore / addColumnAfter: Insert column
19
+ * - deleteColumn: Delete current column
20
+ * - mergeCells: Merge selected cells into one
21
+ * - splitCell: Split a merged cell back to individual cells
22
+ * - toggleHeaderRow / toggleHeaderColumn / toggleHeaderCell: Toggle header
23
+ * - setCellAttribute: Set cell attribute
24
+ * - goToNextCell / goToPreviousCell: Cell navigation
25
+ * - fixTables: Repair malformed tables
26
+ * - setCellSelection: Programmatic cell selection
27
+ *
28
+ * Features:
29
+ * - goToNextCell/goToPreviousCell exposed as standalone commands
30
+ * - fixTables exposed as command
31
+ * - setCellSelection for programmatic cell range selection
32
+ * - Fully typed options and command params
33
+ * - Framework-agnostic: TableView isolated for wrapper replacement
34
+ */
35
+
36
+ declare module '@domternal/core' {
37
+ interface RawCommands {
38
+ insertTable: CommandSpec<[options?: {
39
+ rows?: number;
40
+ cols?: number;
41
+ withHeaderRow?: boolean;
42
+ }]>;
43
+ deleteTable: CommandSpec;
44
+ addRowBefore: CommandSpec;
45
+ addRowAfter: CommandSpec;
46
+ deleteRow: CommandSpec;
47
+ addColumnBefore: CommandSpec;
48
+ addColumnAfter: CommandSpec;
49
+ deleteColumn: CommandSpec;
50
+ toggleHeaderRow: CommandSpec;
51
+ toggleHeaderColumn: CommandSpec;
52
+ toggleHeaderCell: CommandSpec;
53
+ mergeCells: CommandSpec;
54
+ splitCell: CommandSpec;
55
+ setCellAttribute: CommandSpec<[name: string, value: unknown]>;
56
+ goToNextCell: CommandSpec;
57
+ goToPreviousCell: CommandSpec;
58
+ fixTables: CommandSpec;
59
+ setCellSelection: CommandSpec<[position: {
60
+ anchorCell: number;
61
+ headCell?: number;
62
+ }]>;
63
+ }
64
+ }
65
+ interface TableOptions {
66
+ /**
67
+ * Custom HTML attributes for the rendered table element.
68
+ */
69
+ HTMLAttributes: Record<string, unknown>;
70
+ /**
71
+ * Minimum cell width in pixels (floor when dragging).
72
+ * @default 25
73
+ */
74
+ cellMinWidth: number;
75
+ /**
76
+ * Default width for columns without an explicit colwidth attribute.
77
+ * Must match the columnResizing plugin default for consistent resize behavior.
78
+ * @default 100
79
+ */
80
+ defaultCellMinWidth: number;
81
+ /**
82
+ * Column resize behavior when dragging a column border.
83
+ * - `'neighbor'`: adjacent column compensates, table width stays constant (Google Docs style)
84
+ * - `'independent'`: only dragged column changes, table width grows/shrinks
85
+ * - `'redistribute'`: all columns redistribute to fill available width (prosemirror-tables default)
86
+ * @default 'neighbor'
87
+ */
88
+ resizeBehavior: 'neighbor' | 'independent' | 'redistribute';
89
+ /**
90
+ * Prevent the table from exceeding its container (.tableWrapper) width.
91
+ * When true: last-column resize is capped, add-column redistributes if needed.
92
+ * When false: original behavior (table can grow beyond container).
93
+ * @default true
94
+ */
95
+ constrainToContainer: boolean;
96
+ /**
97
+ * Allow selecting the entire table as a node selection.
98
+ * @default false
99
+ */
100
+ allowTableNodeSelection: boolean;
101
+ /**
102
+ * Custom NodeView constructor. Override to provide framework-specific rendering.
103
+ * Set to null to disable custom NodeView.
104
+ */
105
+ View: (new (node: Node$1, cellMinWidth: number, view: EditorView, defaultCellMinWidth?: number, constrainToContainer?: boolean) => NodeView) | null;
106
+ }
107
+ declare const Table: Node<TableOptions, unknown>;
108
+
109
+ /**
110
+ * TableRow Node
111
+ *
112
+ * Table row (<tr>). Contains table cells and/or table header cells.
113
+ */
114
+
115
+ interface TableRowOptions {
116
+ HTMLAttributes: Record<string, unknown>;
117
+ }
118
+ declare const TableRow: Node<TableRowOptions, unknown>;
119
+
120
+ /**
121
+ * TableCell Node
122
+ *
123
+ * Table data cell (<td>). Contains block content.
124
+ * Supports colspan, rowspan, colwidth, and background attributes.
125
+ */
126
+
127
+ interface TableCellOptions {
128
+ HTMLAttributes: Record<string, unknown>;
129
+ }
130
+ declare const TableCell: Node<TableCellOptions, unknown>;
131
+
132
+ /**
133
+ * TableHeader Node
134
+ *
135
+ * Table header cell (<th>). Contains block content.
136
+ * Same attributes as TableCell (colspan, rowspan, colwidth, background).
137
+ */
138
+
139
+ interface TableHeaderOptions {
140
+ HTMLAttributes: Record<string, unknown>;
141
+ }
142
+ declare const TableHeader: Node<TableHeaderOptions, unknown>;
143
+
144
+ /**
145
+ * TableView - Custom NodeView for table rendering
146
+ *
147
+ * Creates: div.dm-table-container > [handles] + div.tableWrapper > table > colgroup + tbody
148
+ * - Container enables row/column hover controls (handles with dropdown menus)
149
+ * - Wrapper div enables horizontal scrolling for wide tables
150
+ * - Colgroup reflects column widths from the columnResizing plugin
151
+ * - ContentDOM = tbody (ProseMirror renders row content into tbody)
152
+ */
153
+
154
+ declare class TableView implements NodeView {
155
+ node: Node$1;
156
+ cellMinWidth: number;
157
+ defaultCellMinWidth: number;
158
+ view: EditorView;
159
+ constrainToContainer: boolean;
160
+ dom: HTMLElement;
161
+ table: HTMLTableElement;
162
+ colgroup: HTMLTableColElement;
163
+ contentDOM: HTMLElement;
164
+ private wrapper;
165
+ private colHandle;
166
+ private rowHandle;
167
+ private cellToolbar;
168
+ private colorBtn;
169
+ private alignBtn;
170
+ private mergeBtn;
171
+ private splitBtn;
172
+ private headerBtn;
173
+ private cellHandle;
174
+ private cellHandleCell;
175
+ private dropdown;
176
+ /** When true, the plugin skips showing the cell toolbar (row/col dropdown is open). */
177
+ suppressCellToolbar: boolean;
178
+ /** When true, column resize drag is active — all handles/menus are hidden. */
179
+ private _resizeDragging;
180
+ private hoveredCell;
181
+ private hoveredRow;
182
+ private hoveredCol;
183
+ private hideTimeout;
184
+ private boundMouseMove;
185
+ private boundMouseLeave;
186
+ private boundCancelHide;
187
+ private boundDocMouseDown;
188
+ private boundDocKeyDown;
189
+ private boundScroll;
190
+ constructor(node: Node$1, cellMinWidth: number, view: EditorView, defaultCellMinWidth?: number, constrainToContainer?: boolean);
191
+ update(node: Node$1): boolean;
192
+ destroy(): void;
193
+ ignoreMutation(mutation: MutationRecord | {
194
+ type: 'selection';
195
+ }): boolean;
196
+ private createHandle;
197
+ private buildCellToolbar;
198
+ private createToolbarButton;
199
+ private onMouseMove;
200
+ private onMouseLeave;
201
+ private cancelHide;
202
+ private showHandles;
203
+ private hideHandles;
204
+ private positionHandles;
205
+ private getCellIndices;
206
+ /** Called by the cellHandlePlugin when CellSelection changes. */
207
+ updateCellHandle(active: boolean): void;
208
+ /** Hide all controls during column resize drag. Called by the plugin. */
209
+ hideForResize(): void;
210
+ /** Re-enable controls after column resize drag ends. Called by the plugin. */
211
+ showAfterResize(): void;
212
+ /** Show cell handle at the top-center of the given cell. Always repositions (no early return). */
213
+ showCellHandle(cell: HTMLTableCellElement): void;
214
+ /** Hide cell handle. */
215
+ hideCellHandle(): void;
216
+ /** Click on cell handle → create CellSelection for that cell. */
217
+ private onCellHandleClick;
218
+ /** Dismiss other floating overlays (bubble menu, etc.) */
219
+ private dismissOverlays;
220
+ private onColClick;
221
+ private onRowClick;
222
+ private getTablePos;
223
+ /** Dispatch a CellSelection and focus the editor. */
224
+ private dispatchCellSelection;
225
+ private selectRow;
226
+ private selectColumn;
227
+ private setCursorInCell;
228
+ private showDropdown;
229
+ /** Shared open/toggle for toolbar dropdown buttons. */
230
+ private openToolbarDropdown;
231
+ private showColorDropdown;
232
+ private showAlignmentDropdown;
233
+ private createAlignItem;
234
+ private positionToolbarDropdown;
235
+ private addDropdownListeners;
236
+ private removeDropdownListeners;
237
+ private closeDropdown;
238
+ private onDocMouseDown;
239
+ private onDocKeyDown;
240
+ private execRowCmd;
241
+ private execColCmd;
242
+ /**
243
+ * Update colgroup col elements based on cell widths.
244
+ * Matches prosemirror-tables' updateColumnsOnResize behavior:
245
+ * - Reuses existing col elements (avoids DOM churn during resize)
246
+ * - Uses defaultCellMinWidth for totalWidth calc (matches columnResizing plugin)
247
+ * - Columns without explicit widths get empty style.width (table-layout: fixed distributes)
248
+ */
249
+ private updateColumns;
250
+ }
251
+
252
+ /**
253
+ * Creates a table node from schema types.
254
+ *
255
+ * Builds table → rows → cells structure.
256
+ * First row gets tableHeader cells if withHeaderRow is true.
257
+ */
258
+
259
+ declare function createTable(schema: Schema, rows: number, cols: number, withHeaderRow: boolean, cellContent?: Node$1): Node$1;
260
+
261
+ /**
262
+ * Keyboard handler that deletes the table when all cells are selected.
263
+ *
264
+ * Used for Backspace, Delete, Mod-Backspace, Mod-Delete.
265
+ * When a CellSelection covers all cells in a table, delete the entire table.
266
+ */
267
+
268
+ declare function deleteTableWhenAllCellsSelected({ state, dispatch, }: {
269
+ state: EditorState;
270
+ dispatch?: (tr: Transaction) => void;
271
+ }): boolean;
272
+
273
+ export { Table, TableCell, type TableCellOptions, TableHeader, type TableHeaderOptions, type TableOptions, TableRow, type TableRowOptions, TableView, createTable, deleteTableWhenAllCellsSelected };
@@ -0,0 +1,273 @@
1
+ import { CommandSpec, Node } from '@domternal/core';
2
+ import { Node as Node$1, Schema } from '@domternal/pm/model';
3
+ import { EditorView, NodeView } from '@domternal/pm/view';
4
+ import { EditorState, Transaction } from '@domternal/pm/state';
5
+ export { CellSelection, TableMap } from '@domternal/pm/tables';
6
+
7
+ /**
8
+ * Table Node
9
+ *
10
+ * Block-level table container using HTML <table>.
11
+ * Built on prosemirror-tables for cell selection, keyboard nav, and table editing.
12
+ *
13
+ * Commands (18):
14
+ * - insertTable: Insert new table with configurable rows/cols/header
15
+ * - deleteTable: Delete entire table
16
+ * - addRowBefore / addRowAfter: Insert row
17
+ * - deleteRow: Delete current row
18
+ * - addColumnBefore / addColumnAfter: Insert column
19
+ * - deleteColumn: Delete current column
20
+ * - mergeCells: Merge selected cells into one
21
+ * - splitCell: Split a merged cell back to individual cells
22
+ * - toggleHeaderRow / toggleHeaderColumn / toggleHeaderCell: Toggle header
23
+ * - setCellAttribute: Set cell attribute
24
+ * - goToNextCell / goToPreviousCell: Cell navigation
25
+ * - fixTables: Repair malformed tables
26
+ * - setCellSelection: Programmatic cell selection
27
+ *
28
+ * Features:
29
+ * - goToNextCell/goToPreviousCell exposed as standalone commands
30
+ * - fixTables exposed as command
31
+ * - setCellSelection for programmatic cell range selection
32
+ * - Fully typed options and command params
33
+ * - Framework-agnostic: TableView isolated for wrapper replacement
34
+ */
35
+
36
+ declare module '@domternal/core' {
37
+ interface RawCommands {
38
+ insertTable: CommandSpec<[options?: {
39
+ rows?: number;
40
+ cols?: number;
41
+ withHeaderRow?: boolean;
42
+ }]>;
43
+ deleteTable: CommandSpec;
44
+ addRowBefore: CommandSpec;
45
+ addRowAfter: CommandSpec;
46
+ deleteRow: CommandSpec;
47
+ addColumnBefore: CommandSpec;
48
+ addColumnAfter: CommandSpec;
49
+ deleteColumn: CommandSpec;
50
+ toggleHeaderRow: CommandSpec;
51
+ toggleHeaderColumn: CommandSpec;
52
+ toggleHeaderCell: CommandSpec;
53
+ mergeCells: CommandSpec;
54
+ splitCell: CommandSpec;
55
+ setCellAttribute: CommandSpec<[name: string, value: unknown]>;
56
+ goToNextCell: CommandSpec;
57
+ goToPreviousCell: CommandSpec;
58
+ fixTables: CommandSpec;
59
+ setCellSelection: CommandSpec<[position: {
60
+ anchorCell: number;
61
+ headCell?: number;
62
+ }]>;
63
+ }
64
+ }
65
+ interface TableOptions {
66
+ /**
67
+ * Custom HTML attributes for the rendered table element.
68
+ */
69
+ HTMLAttributes: Record<string, unknown>;
70
+ /**
71
+ * Minimum cell width in pixels (floor when dragging).
72
+ * @default 25
73
+ */
74
+ cellMinWidth: number;
75
+ /**
76
+ * Default width for columns without an explicit colwidth attribute.
77
+ * Must match the columnResizing plugin default for consistent resize behavior.
78
+ * @default 100
79
+ */
80
+ defaultCellMinWidth: number;
81
+ /**
82
+ * Column resize behavior when dragging a column border.
83
+ * - `'neighbor'`: adjacent column compensates, table width stays constant (Google Docs style)
84
+ * - `'independent'`: only dragged column changes, table width grows/shrinks
85
+ * - `'redistribute'`: all columns redistribute to fill available width (prosemirror-tables default)
86
+ * @default 'neighbor'
87
+ */
88
+ resizeBehavior: 'neighbor' | 'independent' | 'redistribute';
89
+ /**
90
+ * Prevent the table from exceeding its container (.tableWrapper) width.
91
+ * When true: last-column resize is capped, add-column redistributes if needed.
92
+ * When false: original behavior (table can grow beyond container).
93
+ * @default true
94
+ */
95
+ constrainToContainer: boolean;
96
+ /**
97
+ * Allow selecting the entire table as a node selection.
98
+ * @default false
99
+ */
100
+ allowTableNodeSelection: boolean;
101
+ /**
102
+ * Custom NodeView constructor. Override to provide framework-specific rendering.
103
+ * Set to null to disable custom NodeView.
104
+ */
105
+ View: (new (node: Node$1, cellMinWidth: number, view: EditorView, defaultCellMinWidth?: number, constrainToContainer?: boolean) => NodeView) | null;
106
+ }
107
+ declare const Table: Node<TableOptions, unknown>;
108
+
109
+ /**
110
+ * TableRow Node
111
+ *
112
+ * Table row (<tr>). Contains table cells and/or table header cells.
113
+ */
114
+
115
+ interface TableRowOptions {
116
+ HTMLAttributes: Record<string, unknown>;
117
+ }
118
+ declare const TableRow: Node<TableRowOptions, unknown>;
119
+
120
+ /**
121
+ * TableCell Node
122
+ *
123
+ * Table data cell (<td>). Contains block content.
124
+ * Supports colspan, rowspan, colwidth, and background attributes.
125
+ */
126
+
127
+ interface TableCellOptions {
128
+ HTMLAttributes: Record<string, unknown>;
129
+ }
130
+ declare const TableCell: Node<TableCellOptions, unknown>;
131
+
132
+ /**
133
+ * TableHeader Node
134
+ *
135
+ * Table header cell (<th>). Contains block content.
136
+ * Same attributes as TableCell (colspan, rowspan, colwidth, background).
137
+ */
138
+
139
+ interface TableHeaderOptions {
140
+ HTMLAttributes: Record<string, unknown>;
141
+ }
142
+ declare const TableHeader: Node<TableHeaderOptions, unknown>;
143
+
144
+ /**
145
+ * TableView - Custom NodeView for table rendering
146
+ *
147
+ * Creates: div.dm-table-container > [handles] + div.tableWrapper > table > colgroup + tbody
148
+ * - Container enables row/column hover controls (handles with dropdown menus)
149
+ * - Wrapper div enables horizontal scrolling for wide tables
150
+ * - Colgroup reflects column widths from the columnResizing plugin
151
+ * - ContentDOM = tbody (ProseMirror renders row content into tbody)
152
+ */
153
+
154
+ declare class TableView implements NodeView {
155
+ node: Node$1;
156
+ cellMinWidth: number;
157
+ defaultCellMinWidth: number;
158
+ view: EditorView;
159
+ constrainToContainer: boolean;
160
+ dom: HTMLElement;
161
+ table: HTMLTableElement;
162
+ colgroup: HTMLTableColElement;
163
+ contentDOM: HTMLElement;
164
+ private wrapper;
165
+ private colHandle;
166
+ private rowHandle;
167
+ private cellToolbar;
168
+ private colorBtn;
169
+ private alignBtn;
170
+ private mergeBtn;
171
+ private splitBtn;
172
+ private headerBtn;
173
+ private cellHandle;
174
+ private cellHandleCell;
175
+ private dropdown;
176
+ /** When true, the plugin skips showing the cell toolbar (row/col dropdown is open). */
177
+ suppressCellToolbar: boolean;
178
+ /** When true, column resize drag is active — all handles/menus are hidden. */
179
+ private _resizeDragging;
180
+ private hoveredCell;
181
+ private hoveredRow;
182
+ private hoveredCol;
183
+ private hideTimeout;
184
+ private boundMouseMove;
185
+ private boundMouseLeave;
186
+ private boundCancelHide;
187
+ private boundDocMouseDown;
188
+ private boundDocKeyDown;
189
+ private boundScroll;
190
+ constructor(node: Node$1, cellMinWidth: number, view: EditorView, defaultCellMinWidth?: number, constrainToContainer?: boolean);
191
+ update(node: Node$1): boolean;
192
+ destroy(): void;
193
+ ignoreMutation(mutation: MutationRecord | {
194
+ type: 'selection';
195
+ }): boolean;
196
+ private createHandle;
197
+ private buildCellToolbar;
198
+ private createToolbarButton;
199
+ private onMouseMove;
200
+ private onMouseLeave;
201
+ private cancelHide;
202
+ private showHandles;
203
+ private hideHandles;
204
+ private positionHandles;
205
+ private getCellIndices;
206
+ /** Called by the cellHandlePlugin when CellSelection changes. */
207
+ updateCellHandle(active: boolean): void;
208
+ /** Hide all controls during column resize drag. Called by the plugin. */
209
+ hideForResize(): void;
210
+ /** Re-enable controls after column resize drag ends. Called by the plugin. */
211
+ showAfterResize(): void;
212
+ /** Show cell handle at the top-center of the given cell. Always repositions (no early return). */
213
+ showCellHandle(cell: HTMLTableCellElement): void;
214
+ /** Hide cell handle. */
215
+ hideCellHandle(): void;
216
+ /** Click on cell handle → create CellSelection for that cell. */
217
+ private onCellHandleClick;
218
+ /** Dismiss other floating overlays (bubble menu, etc.) */
219
+ private dismissOverlays;
220
+ private onColClick;
221
+ private onRowClick;
222
+ private getTablePos;
223
+ /** Dispatch a CellSelection and focus the editor. */
224
+ private dispatchCellSelection;
225
+ private selectRow;
226
+ private selectColumn;
227
+ private setCursorInCell;
228
+ private showDropdown;
229
+ /** Shared open/toggle for toolbar dropdown buttons. */
230
+ private openToolbarDropdown;
231
+ private showColorDropdown;
232
+ private showAlignmentDropdown;
233
+ private createAlignItem;
234
+ private positionToolbarDropdown;
235
+ private addDropdownListeners;
236
+ private removeDropdownListeners;
237
+ private closeDropdown;
238
+ private onDocMouseDown;
239
+ private onDocKeyDown;
240
+ private execRowCmd;
241
+ private execColCmd;
242
+ /**
243
+ * Update colgroup col elements based on cell widths.
244
+ * Matches prosemirror-tables' updateColumnsOnResize behavior:
245
+ * - Reuses existing col elements (avoids DOM churn during resize)
246
+ * - Uses defaultCellMinWidth for totalWidth calc (matches columnResizing plugin)
247
+ * - Columns without explicit widths get empty style.width (table-layout: fixed distributes)
248
+ */
249
+ private updateColumns;
250
+ }
251
+
252
+ /**
253
+ * Creates a table node from schema types.
254
+ *
255
+ * Builds table → rows → cells structure.
256
+ * First row gets tableHeader cells if withHeaderRow is true.
257
+ */
258
+
259
+ declare function createTable(schema: Schema, rows: number, cols: number, withHeaderRow: boolean, cellContent?: Node$1): Node$1;
260
+
261
+ /**
262
+ * Keyboard handler that deletes the table when all cells are selected.
263
+ *
264
+ * Used for Backspace, Delete, Mod-Backspace, Mod-Delete.
265
+ * When a CellSelection covers all cells in a table, delete the entire table.
266
+ */
267
+
268
+ declare function deleteTableWhenAllCellsSelected({ state, dispatch, }: {
269
+ state: EditorState;
270
+ dispatch?: (tr: Transaction) => void;
271
+ }): boolean;
272
+
273
+ export { Table, TableCell, type TableCellOptions, TableHeader, type TableHeaderOptions, type TableOptions, TableRow, type TableRowOptions, TableView, createTable, deleteTableWhenAllCellsSelected };