@mikestools/usetable 0.0.3 → 0.0.4

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.
package/dist/index.d.ts CHANGED
@@ -1,15 +1,6 @@
1
+ import { ComputedRef } from 'vue';
1
2
  import { Ref } from 'vue';
2
3
 
3
- /**
4
- * Configuration for custom aggregation.
5
- */
6
- export declare interface AggregateConfig<T> {
7
- /** Initial accumulator value */
8
- readonly initial: T;
9
- /** Reducer function */
10
- readonly reducer: (accumulator: T, value: unknown, rowIndex: number) => T;
11
- }
12
-
13
4
  /**
14
5
  * Base record interface - all records must have an id.
15
6
  * This is the foundation for the shared reactive data schema.
@@ -20,129 +11,71 @@ export declare interface BaseRecord {
20
11
  }
21
12
 
22
13
  /**
23
- * Cell change record for dirty tracking.
14
+ * Cell change record for tracking modifications.
24
15
  */
25
16
  export declare interface CellChange {
26
- /** Row index */
27
17
  readonly row: number;
28
- /** Column index */
29
18
  readonly column: number;
30
- /** Previous value */
31
- readonly oldValue: unknown;
32
- /** New value */
33
- readonly newValue: unknown;
19
+ readonly oldValue: CellValue;
20
+ readonly newValue: CellValue;
34
21
  }
35
22
 
36
- /**
37
- * Configuration for a table cell with content and attributes.
38
- */
39
- export declare interface CellConfig {
40
- /** The cell value - can be any type including HTML elements */
41
- readonly value: unknown;
42
- /** Optional HTML attributes to apply to the cell */
43
- readonly attributes?: ElementAttributes;
44
- /** Column span (colspan attribute) */
45
- readonly columnSpan?: number;
46
- /** Row span (rowspan attribute) */
47
- readonly rowSpan?: number;
48
- }
23
+ export declare type CellChangeCallback = (row: number, column: number, oldValue: CellValue, newValue: CellValue) => void;
49
24
 
50
25
  /**
51
- * Cell position for focus/navigation.
26
+ * Cell position for navigation and selection.
52
27
  */
53
28
  export declare interface CellPosition {
54
- /** Row index */
55
29
  readonly row: number;
56
- /** Column index */
57
30
  readonly column: number;
58
31
  }
59
32
 
60
33
  /**
61
- * Validator function for a single cell.
62
- * Returns true if valid, or a string error message if invalid.
63
- */
64
- export declare type CellValidator = (value: unknown) => boolean | string;
65
-
66
- /**
67
- * Configuration for a table column.
68
- */
69
- export declare interface ColumnConfig {
70
- /** Header content - string or CellConfig */
71
- readonly header: string | CellConfig;
72
- /** Default value for new cells in this column */
73
- readonly defaultValue?: unknown;
74
- /** Default attributes for cells in this column */
75
- readonly defaultAttributes?: ElementAttributes;
76
- }
77
-
78
- /**
79
- * Column definition for type parsing/formatting.
34
+ * Cell value can be a string, number, or DOM element.
80
35
  */
81
- export declare interface ColumnDefinition {
82
- /** Data type of the column */
83
- readonly type: 'string' | 'number' | 'date' | 'boolean';
84
- /** Custom parser function */
85
- readonly parser?: (value: unknown) => unknown;
86
- /** Custom formatter function */
87
- readonly formatter?: (value: unknown) => string;
88
- /** Default value when cell is empty */
89
- readonly defaultValue?: unknown;
90
- /** Whether null/undefined values are allowed */
91
- readonly nullable?: boolean;
92
- }
36
+ export declare type CellValue = string | number | boolean | null | undefined | HTMLElement | Node;
93
37
 
94
38
  /**
95
- * Configuration for computed columns.
39
+ * Create a table instance for manipulating an HTML table element.
40
+ *
41
+ * Uses native table DOM APIs exclusively - no querySelector/querySelectorAll.
42
+ * DOM-first architecture where the HTML table is the source of truth.
43
+ *
44
+ * @param element - The HTML table element
45
+ * @param initialData - Optional initial body data
46
+ * @param options - Configuration options
47
+ * @returns TableInstance for table manipulation
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * const table = document.createElement('table')
52
+ * const instance = createTable(table, [['Alice', 30], ['Bob', 25]], {
53
+ * headers: ['Name', 'Age'],
54
+ * caption: 'Users'
55
+ * })
56
+ *
57
+ * instance.addRow(['Carol', 35])
58
+ * instance.setCell(0, 1, 31)
59
+ * console.log(instance. getData())
60
+ * ```
96
61
  */
97
- export declare interface ComputedColumnConfig {
98
- /** Function to compute the column value from row data */
99
- readonly computeFunction: (row: unknown[]) => unknown;
100
- /** Column header label */
101
- readonly label: string;
102
- /** Position to insert the column */
103
- readonly index?: number;
104
- }
62
+ export declare function createTable(element: HTMLTableElement, initialData?: TableData, options?: CreateTableOptions): TableInstance;
105
63
 
106
64
  /**
107
- * Configuration for editable cells.
65
+ * Options for creating a table.
108
66
  */
109
- export declare interface EditableConfig {
110
- /** Enable cell editing */
111
- readonly cells?: boolean;
112
- /** Enable header editing */
113
- readonly headers?: boolean;
114
- /** Enable footer editing */
115
- readonly footers?: boolean;
116
- /** Specific columns that are editable */
117
- readonly editableColumns?: readonly number[];
118
- /** Specific rows that are editable */
119
- readonly editableRows?: readonly number[];
120
- /** Validator function */
121
- readonly validator?: (value: string, row: number, column: number) => boolean | string;
122
- /** Parser function to convert string input to stored value */
123
- readonly parser?: (value: string, row: number, column: number) => unknown;
124
- /** Callback when a cell is edited */
125
- readonly onEdit?: (value: unknown, row: number, column: number) => void;
67
+ export declare interface CreateTableOptions {
68
+ /** Initial headers */
69
+ readonly headers?: readonly string[];
70
+ /** Initial footer data */
71
+ readonly footer?: RowData;
72
+ /** Caption text */
73
+ readonly caption?: string;
74
+ /** ID generator for records */
75
+ readonly idGenerator?: IdGenerator;
126
76
  }
127
77
 
128
- /**
129
- * Comprehensive HTML element attributes for table elements.
130
- * Supports class, style, data attributes, ARIA attributes, and event handlers.
131
- */
132
- export declare interface ElementAttributes extends Partial<Omit<HTMLElement, 'style' | 'className' | 'classList' | 'children' | 'childNodes' | 'parentNode' | 'parentElement' | 'attributes' | 'tagName' | 'namespaceURI' | 'shadowRoot' | 'assignedSlot' | 'offsetParent' | 'offsetTop' | 'offsetLeft' | 'offsetWidth' | 'offsetHeight' | 'clientTop' | 'clientLeft' | 'clientWidth' | 'clientHeight' | 'scrollTop' | 'scrollLeft' | 'scrollWidth' | 'scrollHeight' | 'innerHTML' | 'outerHTML' | 'innerText' | 'outerText' | 'textContent' | 'addEventListener' | 'removeEventListener' | 'dispatchEvent' | 'getAttribute' | 'setAttribute' | 'removeAttribute' | 'hasAttribute' | 'appendChild' | 'removeChild' | 'replaceChild' | 'insertBefore' | 'querySelector' | 'querySelectorAll' | 'getElementsByTagName' | 'getElementsByClassName' | 'getElementById' | 'animate' | 'getAnimations' | 'attachShadow' | 'closest' | 'matches' | 'webkitMatchesSelector' | 'getBoundingClientRect' | 'getClientRects' | 'scrollIntoView' | 'scroll' | 'scrollBy' | 'scrollTo' | 'focus' | 'blur' | 'click'>>, Partial<GlobalEventHandlers>, Partial<ARIAMixin> {
133
- /** CSS class - string, array of strings, or object with boolean values */
134
- class?: string | string[] | Record<string, boolean>;
135
- /** Inline styles - string or object */
136
- style?: string | Partial<CSSStyleDeclaration> | Record<string, string | number>;
137
- /** Data attributes as object */
138
- dataset?: Record<string, string>;
139
- /** Data attributes with prefix */
140
- [key: `data-${string}`]: string | undefined;
141
- /** ARIA attributes with prefix */
142
- [key: `aria-${string}`]: string | undefined;
143
- /** Allow any other attributes */
144
- [key: string]: unknown;
145
- }
78
+ export declare type DataChangeCallback = (data: CellValue[][]) => void;
146
79
 
147
80
  /**
148
81
  * Ensure a record has an ID, generating one if missing.
@@ -151,34 +84,26 @@ export declare function ensureId<T extends Record<string, unknown>>(record: T, g
151
84
  id: string;
152
85
  };
153
86
 
154
- /**
155
- * Filter state for tracking row filtering.
156
- */
157
- export declare interface FilterState {
158
- /** Whether any filter is active */
159
- readonly isFiltered: Readonly<Ref<boolean>>;
160
- /** Number of visible rows after filtering */
161
- readonly filteredRowCount: Readonly<Ref<number>>;
162
- /** Indices of visible rows */
163
- readonly filteredIndices: Readonly<Ref<readonly number[]>>;
164
- }
165
-
166
87
  /**
167
88
  * Find record by ID in array.
168
89
  */
169
90
  export declare function findById<T extends BaseRecord>(records: readonly T[], id: string): T | undefined;
170
91
 
171
92
  /**
172
- * Validator function for all cells.
173
- * Returns null if valid, or a string error message if invalid.
93
+ * Focus state.
174
94
  */
175
- export declare type FullValidator = (value: unknown, row: number, column: number) => string | null;
95
+ export declare interface FocusState {
96
+ /** Currently focused cell position */
97
+ readonly cell: Readonly<Ref<CellPosition | null>>;
98
+ }
176
99
 
177
100
  /**
178
101
  * Default ID generator using crypto.randomUUID.
179
102
  */
180
103
  export declare function generateId(): string;
181
104
 
105
+ export declare type HeaderChangeCallback = (headers: readonly string[]) => void;
106
+
182
107
  /**
183
108
  * Symbol for tracking auto-generated IDs.
184
109
  * Internal use only - invisible to JSON.stringify, Object.keys, for...in.
@@ -195,172 +120,33 @@ export declare type IdGenerator = () => string;
195
120
  */
196
121
  export declare function indexById<T extends BaseRecord>(records: readonly T[], id: string): number;
197
122
 
198
- /**
199
- * Type guard for CellConfig.
200
- */
201
- export declare function isCellConfig(value: unknown): value is CellConfig;
202
-
203
- /**
204
- * Type guard for ValidationError.
205
- */
206
- export declare function isValidationError(value: unknown): value is ValidationError;
207
-
208
- /**
209
- * Type guard for ValidationError array.
210
- */
211
- export declare function isValidationErrorArray(value: unknown): value is ValidationError[];
212
-
213
- /**
214
- * Type guard for ValidationResult.
215
- */
216
- export declare function isValidationResult(value: unknown): value is ValidationResult;
217
-
218
123
  /**
219
124
  * Check if a value is a valid ID.
220
125
  */
221
126
  export declare function isValidId(value: unknown): value is string;
222
127
 
223
128
  /**
224
- * Pagination configuration.
129
+ * Event callback types.
225
130
  */
226
- export declare interface PaginationConfig {
227
- /** Number of rows per page */
228
- readonly pageSize: number;
229
- /** Initial page (1-based) */
230
- readonly currentPage?: number;
231
- }
131
+ export declare type RowAddCallback = (rowData: CellValue[], rowIndex: number, rowId: string | undefined) => void;
232
132
 
233
133
  /**
234
- * Pagination state.
134
+ * Row data is an array of cell values.
235
135
  */
236
- export declare interface PaginationState {
237
- /** Total number of pages */
238
- readonly totalPages: Readonly<Ref<number>>;
239
- /** Current page (1-based) */
240
- readonly currentPage: Ref<number>;
241
- /** Number of rows per page */
242
- readonly pageSize: Ref<number>;
243
- /** Indices of visible rows on current page */
244
- readonly visibleRows: Ref<number[]>;
245
- }
136
+ export declare type RowData = readonly CellValue[];
246
137
 
247
- /**
248
- * Reactive wrapper for table cells.
249
- */
250
- export declare interface ReactiveCellCollection {
251
- /** All cell elements */
252
- readonly cells: Readonly<Ref<readonly HTMLTableCellElement[]>>;
253
- /** Number of cells */
254
- readonly cellCount: Readonly<Ref<number>>;
255
- }
138
+ export declare type RowRemoveCallback = (rowData: CellValue[], rowIndex: number, rowId: string | undefined) => void;
256
139
 
257
- /**
258
- * Reactive wrapper for table rows.
259
- */
260
- export declare interface ReactiveRowCollection {
261
- /** All row elements */
262
- readonly rows: Readonly<Ref<readonly HTMLTableRowElement[]>>;
263
- /** Number of rows */
264
- readonly rowCount: Readonly<Ref<number>>;
265
- }
140
+ export declare type RowUpdateCallback = (rowIndex: number, oldData: CellValue[], newData: CellValue[], rowId: string | undefined) => void;
266
141
 
267
142
  /**
268
- * Reactive wrapper for tbody elements.
143
+ * Selection state.
269
144
  */
270
- export declare interface ReactiveTBodyCollection {
271
- /** All tbody elements */
272
- readonly tBodies: Readonly<Ref<readonly HTMLTableSectionElement[]>>;
273
- /** Number of tbody elements */
274
- readonly tBodyCount: Readonly<Ref<number>>;
275
- }
276
-
277
- /**
278
- * Column definition for record-based tables.
279
- * Maps record fields to table columns.
280
- */
281
- export declare interface RecordColumnDef<T extends BaseRecord = BaseRecord> {
282
- /** Field name (string) or accessor function */
283
- readonly field: string | ((record: T) => unknown);
284
- /** Column header text */
285
- readonly header: string;
286
- /** Format value for display */
287
- readonly format?: (value: unknown, record: T) => string;
288
- /** Parse display value back to data value */
289
- readonly parse?: (value: string, record: T) => unknown;
290
- /** Whether column is editable (default: true for fields, false for functions) */
291
- readonly editable?: boolean;
292
- /** Column width */
293
- readonly width?: string | number;
294
- /** Default value for new records */
295
- readonly defaultValue?: unknown;
296
- }
297
-
298
- /**
299
- * Options for record-based table configuration.
300
- */
301
- export declare interface RecordTableOptions<T extends BaseRecord = BaseRecord> {
302
- /** Column definitions mapping fields to columns */
303
- readonly columns: readonly RecordColumnDef<T>[];
304
- /** ID generator for new records */
305
- readonly idGenerator?: IdGenerator;
306
- /** Callback when a cell is edited */
307
- readonly onCellEdit?: (recordId: string, field: keyof T | string, value: unknown) => void;
308
- /** Callback when a row is inserted */
309
- readonly onRowInsert?: (values: Omit<T, 'id'>) => void;
310
- /** Callback when a row is deleted */
311
- readonly onRowDelete?: (recordId: string) => void;
312
- /** Callback when row selection changes */
313
- readonly onRowSelect?: (recordId: string | null) => void;
314
- }
315
-
316
- /**
317
- * Record-based table state.
318
- */
319
- export declare interface RecordTableState<T extends BaseRecord = BaseRecord> {
320
- /** All records in the table */
321
- readonly records: readonly T[];
322
- /** Currently selected record ID */
323
- readonly selectedRecordId: string | null;
324
- /** Record IDs in display order */
325
- readonly displayOrder: readonly string[];
326
- }
327
-
328
- /**
329
- * Validator function for a row.
330
- * Returns true if valid, or a string error message if invalid.
331
- */
332
- export declare type RowValidator = (rowData: unknown[]) => boolean | string;
333
-
334
- /**
335
- * Options for search operations.
336
- */
337
- export declare interface SearchOptions {
338
- /** Whether search is case-sensitive */
339
- readonly caseSensitive?: boolean;
340
- }
341
-
342
- /**
343
- * Search result for a found cell.
344
- */
345
- export declare interface SearchResult {
346
- /** Row index */
347
- readonly row: number;
348
- /** Column index */
349
- readonly column: number;
350
- /** The found value */
351
- readonly value: unknown;
352
- }
353
-
354
- /**
355
- * Sort state for tracking column sorting.
356
- */
357
- export declare interface SortState {
358
- /** Currently sorted column index */
359
- readonly columnIndex: Readonly<Ref<number | null>>;
360
- /** Whether sorted ascending */
361
- readonly ascending: Readonly<Ref<boolean>>;
362
- /** Whether sorted descending */
363
- readonly descending: Readonly<Ref<boolean>>;
145
+ export declare interface SelectionState {
146
+ /** Selected row indices */
147
+ readonly rows: Readonly<Ref<ReadonlySet<number>>>;
148
+ /** Selected cell positions as "row,column" strings */
149
+ readonly cells: Readonly<Ref<ReadonlySet<string>>>;
364
150
  }
365
151
 
366
152
  /**
@@ -371,428 +157,369 @@ export declare function stripGeneratedId<T extends {
371
157
  }>(record: T): Omit<T, 'id'> | T;
372
158
 
373
159
  /**
374
- * Table cell composable.
160
+ * Table data is a 2D array of cell values.
375
161
  */
376
- export declare interface TableCell {
377
- /** The cell element */
378
- readonly element: Readonly<Ref<HTMLTableCellElement>>;
379
- /** Cell index within row */
380
- readonly cellIndex: Readonly<Ref<number>>;
381
- /** Column span */
382
- readonly columnSpan: Ref<number>;
383
- /** Row span */
384
- readonly rowSpan: Ref<number>;
385
- /** Header IDs */
386
- readonly headers: Ref<string>;
387
- /** Abbreviated text */
388
- readonly abbr: Ref<string>;
389
- /** Scope (for th elements) */
390
- readonly scope: Ref<string>;
391
- }
162
+ export declare type TableData = readonly RowData[];
392
163
 
393
164
  /**
394
- * Table row composable.
165
+ * Return type for createTable.
395
166
  */
396
- export declare interface TableRow extends ReactiveCellCollection {
397
- /** The row element */
398
- readonly element: Readonly<Ref<HTMLTableRowElement>>;
399
- /** Row index in table */
400
- readonly rowIndex: Readonly<Ref<number>>;
401
- /** Row index in parent section */
402
- readonly sectionRowIndex: Readonly<Ref<number>>;
403
- /** Insert a cell at index */
404
- insertCell(index?: number): HTMLTableCellElement;
405
- /** Delete a cell at index */
406
- deleteCell(index: number): void;
407
- /** Get TableCell composable for cell at index */
408
- getCell(index: number): TableCell | undefined;
167
+ export declare interface TableInstance {
168
+ /** The table element */
169
+ readonly element: HTMLTableElement;
170
+ /** Get caption element */
171
+ getCaption(): HTMLTableCaptionElement | null;
172
+ /** Get thead element */
173
+ getTHead(): HTMLTableSectionElement | null;
174
+ /** Get tfoot element */
175
+ getTFoot(): HTMLTableSectionElement | null;
176
+ /** Get all tbody elements */
177
+ getTBodies(): HTMLCollectionOf<HTMLTableSectionElement>;
178
+ /** Get primary tbody (first one, created if needed) */
179
+ getPrimaryTBody(): HTMLTableSectionElement;
180
+ /** Get all rows in tbody sections */
181
+ getBodyRows(): readonly HTMLTableRowElement[];
182
+ /** Get row by index (body rows only) */
183
+ getRow(index: number): HTMLTableRowElement | undefined;
184
+ /** Get row by ID */
185
+ getRowById(id: string): HTMLTableRowElement | undefined;
186
+ /** Get cell at position */
187
+ getCell(row: number, column: number): HTMLTableCellElement | undefined;
188
+ /** Get cell by row ID and column index */
189
+ getCellByRowId(rowId: string, column: number): HTMLTableCellElement | undefined;
190
+ /** Get current headers */
191
+ getHeaders(): string[];
192
+ /** Get header at index */
193
+ getHeader(index: number): string | undefined;
194
+ /** Get body data as 2D array */
195
+ getData(): CellValue[][];
196
+ /** Get row data by index */
197
+ getRowData(index: number): CellValue[] | undefined;
198
+ /** Get row data by ID */
199
+ getRowDataById(id: string): CellValue[] | undefined;
200
+ /** Get cell value */
201
+ getCellValue(row: number, column: number): CellValue;
202
+ /** Get column data */
203
+ getColumnData(index: number): CellValue[];
204
+ /** Get footer data */
205
+ getFooterData(): CellValue[] | undefined;
206
+ /** Get row count (body rows only) */
207
+ getRowCount(): number;
208
+ /** Get column count (based on headers or first row) */
209
+ getColumnCount(): number;
210
+ /** Get row ID by index */
211
+ getRowId(index: number): string | undefined;
212
+ /** Get row index by ID */
213
+ getRowIndex(id: string): number;
214
+ /** Get all row IDs */
215
+ getAllRowIds(): string[];
216
+ /** Create or get caption */
217
+ createCaption(): HTMLTableCaptionElement;
218
+ /** Delete caption */
219
+ deleteCaption(): void;
220
+ /** Create or get thead */
221
+ createTHead(): HTMLTableSectionElement;
222
+ /** Delete thead */
223
+ deleteTHead(): void;
224
+ /** Create or get tfoot */
225
+ createTFoot(): HTMLTableSectionElement;
226
+ /** Delete tfoot */
227
+ deleteTFoot(): void;
228
+ /** Create a new tbody */
229
+ createTBody(): HTMLTableSectionElement;
230
+ /** Set all headers */
231
+ setHeaders(headers: readonly string[]): void;
232
+ /** Set single header */
233
+ setHeader(index: number, text: string): void;
234
+ /** Add header column */
235
+ addHeader(text: string, index?: number): void;
236
+ /** Remove header column */
237
+ removeHeader(index: number): void;
238
+ /** Add a row with data */
239
+ addRow(data: RowData, index?: number, id?: string): HTMLTableRowElement;
240
+ /** Remove row by index */
241
+ removeRow(index: number): CellValue[] | undefined;
242
+ /** Remove row by ID */
243
+ removeRowById(id: string): CellValue[] | undefined;
244
+ /** Update entire row */
245
+ updateRow(index: number, data: RowData): void;
246
+ /** Update row by ID */
247
+ updateRowById(id: string, data: RowData): void;
248
+ /** Move row from one index to another */
249
+ moveRow(fromIndex: number, toIndex: number): void;
250
+ /** Swap two rows */
251
+ swapRows(indexA: number, indexB: number): void;
252
+ /** Clear all body rows */
253
+ clearRows(): void;
254
+ /** Add a column */
255
+ addColumn(header: string, defaultValue?: CellValue, index?: number): void;
256
+ /** Remove a column */
257
+ removeColumn(index: number): void;
258
+ /** Move column */
259
+ moveColumn(fromIndex: number, toIndex: number): void;
260
+ /** Swap two columns */
261
+ swapColumns(indexA: number, indexB: number): void;
262
+ /** Set column data */
263
+ setColumnData(index: number, data: readonly CellValue[]): void;
264
+ /** Set cell value */
265
+ setCell(row: number, column: number, value: CellValue): void;
266
+ /** Set cell by row ID */
267
+ setCellByRowId(rowId: string, column: number, value: CellValue): void;
268
+ /** Set cell range */
269
+ setCellRange(startRow: number, startColumn: number, data: TableData): void;
270
+ /** Set footer row */
271
+ setFooter(data: RowData): void;
272
+ /** Set footer cell */
273
+ setFooterCell(index: number, value: CellValue): void;
274
+ /** Get footer cell */
275
+ getFooterCell(index: number): CellValue;
276
+ /** Clear footer */
277
+ clearFooter(): void;
278
+ /** Set caption text */
279
+ setCaption(text: string): void;
280
+ /** Get caption text */
281
+ getCaptionText(): string | undefined;
282
+ /** Set all data (replaces body rows) */
283
+ setData(data: TableData): void;
284
+ /** Reset table (clear all content) */
285
+ reset(): void;
286
+ /** Sync internal state with DOM (if external changes made) */
287
+ sync(): void;
288
+ /** Set records with column mapping */
289
+ setRecords<T extends BaseRecord>(records: readonly T[], fields: readonly (keyof T | ((record: T) => CellValue))[]): void;
290
+ /** Get record by ID */
291
+ getRecordData(id: string): CellValue[] | undefined;
292
+ /** Add a record */
293
+ addRecord<T extends BaseRecord>(record: T | Omit<T, 'id'>, fields: readonly (keyof T | ((record: T) => CellValue))[], index?: number): string;
294
+ /** Update a record by ID */
295
+ updateRecordRow(id: string, data: RowData): boolean;
296
+ /** Remove a record by ID */
297
+ removeRecord(id: string): boolean;
298
+ /** Check if record exists */
299
+ hasRecord(id: string): boolean;
300
+ /** Set the ID generator function */
301
+ setIdGenerator(generator: IdGenerator): void;
302
+ /** Generate a new ID */
303
+ generateId(): string;
304
+ /** Subscribe to row add events */
305
+ onRowAdd(callback: RowAddCallback): () => void;
306
+ /** Subscribe to row remove events */
307
+ onRowRemove(callback: RowRemoveCallback): () => void;
308
+ /** Subscribe to row update events */
309
+ onRowUpdate(callback: RowUpdateCallback): () => void;
310
+ /** Subscribe to cell change events */
311
+ onCellChange(callback: CellChangeCallback): () => void;
312
+ /** Subscribe to header change events */
313
+ onHeaderChange(callback: HeaderChangeCallback): () => void;
314
+ /** Subscribe to data change events */
315
+ onDataChange(callback: DataChangeCallback): () => void;
316
+ /** Destroy and clean up */
317
+ destroy(): void;
409
318
  }
410
319
 
411
320
  /**
412
- * Table section composable.
321
+ * Vue 3 composable for HTML table manipulation.
322
+ *
323
+ * Wraps createTable with Vue reactivity and state management.
324
+ * Uses native table DOM APIs - no querySelector/querySelectorAll.
325
+ *
326
+ * @param elementRef - Ref to the HTML table element
327
+ * @param initialData - Optional initial body data
328
+ * @param options - Configuration options
329
+ * @returns UseTableReturn for reactive table manipulation
330
+ *
331
+ * @example
332
+ * ```vue
333
+ * <script setup lang="ts">
334
+ * import { ref, onMounted } from 'vue'
335
+ * import { useTable } from '@mikestools/usetable'
336
+ *
337
+ * const tableRef = ref<HTMLTableElement>()
338
+ *
339
+ * onMounted(() => {
340
+ * if (! tableRef.value) return
341
+ *
342
+ * const table = useTable(ref(tableRef.value), [
343
+ * ['Alice', 30],
344
+ * ['Bob', 25]
345
+ * ], {
346
+ * headers: ['Name', 'Age']
347
+ * })
348
+ *
349
+ * // Reactive access
350
+ * console. log(table.data. value)
351
+ * console.log(table.rowCount. value)
352
+ *
353
+ * // Mutations
354
+ * table.addRow(['Carol', 35])
355
+ * table.setCell(0, 1, 31)
356
+ * })
357
+ * </script>
358
+ *
359
+ * <template>
360
+ * <table ref="tableRef"></table>
361
+ * </template>
362
+ * ```
413
363
  */
414
- export declare interface TableSection extends ReactiveRowCollection {
415
- /** The section element */
416
- readonly element: Readonly<Ref<HTMLTableSectionElement>>;
417
- /** Insert a row at index */
418
- insertRow(index?: number): HTMLTableRowElement;
419
- /** Delete a row at index */
420
- deleteRow(index: number): void;
421
- /** Get TableRow composable for row at index */
422
- getRow(index: number): TableRow | undefined;
423
- }
364
+ export declare function useTable(elementRef: Ref<HTMLTableElement>, initialData?: TableData, options?: UseTableOptions): UseTableReturn;
424
365
 
425
366
  /**
426
- * A comprehensive Vue composable for direct HTML table DOM manipulation.
427
- * DOM is the source of truth - data and headers are computed from DOM state.
428
- * @public
367
+ * Options for useTable composable.
429
368
  */
430
- export declare function useTable(element: Ref<HTMLTableElement>): UseTableReturn;
369
+ export declare type UseTableOptions = CreateTableOptions;
431
370
 
432
371
  /**
433
- * Main table composable return type.
434
- *
435
- * Provides comprehensive table manipulation capabilities including:
436
- * - DOM structure methods
437
- * - Data layer methods
438
- * - Sorting, filtering, and searching
439
- * - Selection and focus management
440
- * - Validation and transformation
441
- * - Import/export functionality
442
- * - Undo/redo support
443
- * - Pagination and virtual scrolling
372
+ * Return type for useTable composable.
444
373
  */
445
- export declare interface UseTableReturn extends ReactiveRowCollection, ReactiveTBodyCollection {
374
+ export declare interface UseTableReturn {
375
+ /** Underlying table instance */
376
+ readonly instance: TableInstance;
446
377
  /** The table element */
447
378
  readonly element: Readonly<Ref<HTMLTableElement>>;
448
- /** Caption element */
449
- readonly caption: Ref<HTMLTableCaptionElement | null>;
450
- /** Thead element */
451
- readonly tHead: Ref<HTMLTableSectionElement | null>;
452
- /** Tfoot element */
453
- readonly tFoot: Ref<HTMLTableSectionElement | null>;
454
- /** Table body data as 2D array */
455
- readonly data: Ref<unknown[][]>;
456
- /** Header texts */
457
- readonly headers: Ref<string[]>;
458
- /** Number of columns */
459
- readonly columnCount: Readonly<Ref<number>>;
460
- /** Create or get existing caption */
379
+ /** Reactive headers */
380
+ readonly headers: ComputedRef<readonly string[]>;
381
+ /** Reactive body data */
382
+ readonly data: ComputedRef<readonly (readonly CellValue[])[]>;
383
+ /** Reactive row count */
384
+ readonly rowCount: ComputedRef<number>;
385
+ /** Reactive column count */
386
+ readonly columnCount: ComputedRef<number>;
387
+ /** Reactive row IDs */
388
+ readonly rowIds: ComputedRef<readonly string[]>;
389
+ /** Reactive footer data */
390
+ readonly footerData: ComputedRef<readonly CellValue[] | undefined>;
391
+ /** Reactive caption text */
392
+ readonly captionText: ComputedRef<string | undefined>;
393
+ /** Version counter for reactivity (incremented on changes) */
394
+ readonly version: Readonly<Ref<number>>;
395
+ /** Selection state */
396
+ readonly selection: SelectionState;
397
+ /** Focus state */
398
+ readonly focus: FocusState;
399
+ /** Create or get caption */
461
400
  createCaption(): HTMLTableCaptionElement;
462
401
  /** Delete caption */
463
402
  deleteCaption(): void;
464
- /** Create or get existing thead */
403
+ /** Create or get thead */
465
404
  createTHead(): HTMLTableSectionElement;
466
405
  /** Delete thead */
467
406
  deleteTHead(): void;
468
- /** Create or get existing tfoot */
407
+ /** Create or get tfoot */
469
408
  createTFoot(): HTMLTableSectionElement;
470
409
  /** Delete tfoot */
471
410
  deleteTFoot(): void;
472
- /** Create new tbody */
411
+ /** Create a new tbody */
473
412
  createTBody(): HTMLTableSectionElement;
474
- /** Insert row at index */
475
- insertRow(index?: number): HTMLTableRowElement;
476
- /** Delete row at index */
477
- deleteRow(index: number): void;
478
- /** Get thead as TableSection */
479
- getTHead(): TableSection | undefined;
480
- /** Get tfoot as TableSection */
481
- getTFoot(): TableSection | undefined;
482
- /** Get tbody at index as TableSection */
483
- getTBody(index: number): TableSection | undefined;
484
- /** Get row at index as TableRow */
485
- getRow(index: number): TableRow | undefined;
413
+ /** Set all headers */
414
+ setHeaders(headers: readonly string[]): void;
415
+ /** Set single header */
416
+ setHeader(index: number, text: string): void;
417
+ /** Add header column */
418
+ addHeader(text: string, index?: number): void;
419
+ /** Remove header column */
420
+ removeHeader(index: number): void;
486
421
  /** Add a row with data */
487
- addRow(rowData: readonly unknown[], index?: number): HTMLTableRowElement;
488
- /** Remove row at index */
489
- removeRow(index: number): void;
422
+ addRow(data: RowData, index?: number, id?: string): HTMLTableRowElement;
423
+ /** Remove row by index */
424
+ removeRow(index: number): CellValue[] | undefined;
425
+ /** Remove row by ID */
426
+ removeRowById(id: string): CellValue[] | undefined;
427
+ /** Update entire row */
428
+ updateRow(index: number, data: RowData): void;
429
+ /** Update row by ID */
430
+ updateRowById(id: string, data: RowData): void;
431
+ /** Move row from one index to another */
432
+ moveRow(fromIndex: number, toIndex: number): void;
433
+ /** Swap two rows */
434
+ swapRows(indexA: number, indexB: number): void;
435
+ /** Clear all body rows */
436
+ clearRows(): void;
490
437
  /** Add a column */
491
- addColumn(headerText?: string, defaultValue?: unknown, index?: number): void;
492
- /** Remove column at index */
438
+ addColumn(header: string, defaultValue?: CellValue, index?: number): void;
439
+ /** Remove a column */
493
440
  removeColumn(index: number): void;
494
- /** Set cell value */
495
- setCell(rowIndex: number, columnIndex: number, value: unknown): void;
441
+ /** Move column */
442
+ moveColumn(fromIndex: number, toIndex: number): void;
443
+ /** Swap two columns */
444
+ swapColumns(indexA: number, indexB: number): void;
445
+ /** Set column data */
446
+ setColumnData(index: number, data: readonly CellValue[]): void;
496
447
  /** Get cell value */
497
- getCell(rowIndex: number, columnIndex: number): unknown;
448
+ getCell(row: number, column: number): CellValue;
449
+ /** Set cell value */
450
+ setCell(row: number, column: number, value: CellValue): void;
451
+ /** Set cell by row ID */
452
+ setCellByRowId(rowId: string, column: number, value: CellValue): void;
453
+ /** Set cell range */
454
+ setCellRange(startRow: number, startColumn: number, data: TableData): void;
455
+ /** Get cell element */
456
+ getCellElement(row: number, column: number): HTMLTableCellElement | undefined;
457
+ /** Get row data by index */
458
+ getRowData(index: number): CellValue[] | undefined;
459
+ /** Get row data by ID */
460
+ getRowDataById(id: string): CellValue[] | undefined;
461
+ /** Get row element */
462
+ getRowElement(index: number): HTMLTableRowElement | undefined;
463
+ /** Get row by ID */
464
+ getRowById(id: string): HTMLTableRowElement | undefined;
465
+ /** Get row ID by index */
466
+ getRowId(index: number): string | undefined;
467
+ /** Get row index by ID */
468
+ getRowIndex(id: string): number;
469
+ /** Get column data */
470
+ getColumnData(index: number): CellValue[];
471
+ /** Set footer row */
472
+ setFooter(data: RowData): void;
473
+ /** Set footer cell */
474
+ setFooterCell(index: number, value: CellValue): void;
475
+ /** Get footer cell */
476
+ getFooterCell(index: number): CellValue;
477
+ /** Clear footer */
478
+ clearFooter(): void;
498
479
  /** Set caption text */
499
480
  setCaption(text: string): void;
500
- /** Set all headers */
501
- setHeaders(headerTexts: readonly string[]): void;
502
- /** Set footer row */
503
- setFooter(footerData: readonly unknown[]): void;
504
- /** Set all data */
505
- setData(newData: readonly (readonly unknown[])[]): void;
506
- /** Clear body data (keep headers) */
507
- clearData(): void;
508
- /** Reset entire table */
481
+ /** Set all data (replaces body rows) */
482
+ setData(data: TableData): void;
483
+ /** Reset table (clear all content) */
509
484
  reset(): void;
510
- /** Sync reactive state with DOM */
485
+ /** Sync internal state with DOM */
511
486
  sync(): void;
512
- /** Add row with cell configs */
513
- addRowWithAttributes(rowData: readonly (unknown | CellConfig)[], attributes?: ElementAttributes, index?: number): HTMLTableRowElement;
514
- /** Add column with config */
515
- addColumnWithAttributes(config: ColumnConfig, index?: number): void;
516
- /** Set headers with configs */
517
- setHeadersWithAttributes(headerConfigs: readonly (string | CellConfig)[]): void;
518
- /** Set cell with attributes */
519
- setCellWithAttributes(rowIndex: number, columnIndex: number, value: unknown, attributes?: ElementAttributes): void;
520
- /** Get row data copy */
521
- getRowData(index: number): unknown[] | undefined;
522
- /** Set row data */
523
- setRowData(index: number, rowData: readonly unknown[]): void;
524
- /** Get all row data as copy */
525
- getAllRowData(): unknown[][];
526
- /** Get column data */
527
- getColumnData(index: number): unknown[];
528
- /** Set column data */
529
- setColumnData(index: number, columnData: readonly unknown[]): void;
530
- /** Get cell range */
531
- getCellRange(rowStart: number, rowEnd: number, columnStart: number, columnEnd: number): unknown[][];
532
- /** Set cell range */
533
- setCellRange(rowStart: number, columnStart: number, rangeData: readonly (readonly unknown[])[]): void;
534
- /** Get header data copy */
535
- getHeaderData(): string[];
536
- /** Get footer data */
537
- getFooterData(): unknown[] | undefined;
538
- /** Set footer cell */
539
- setFooterCell(columnIndex: number, value: unknown): void;
540
- /** Get footer cell */
541
- getFooterCell(columnIndex: number): unknown;
542
- /** Update cell with config */
543
- updateCell(rowIndex: number, columnIndex: number, config: CellConfig): void;
544
- /** Update row data */
545
- updateRow(index: number, rowData: readonly (unknown | CellConfig)[]): void;
546
- /** Get cell DOM element */
547
- getCellElement(rowIndex: number, columnIndex: number): HTMLTableCellElement | undefined;
548
- /** Get row DOM element */
549
- getRowElement(index: number): HTMLTableRowElement | undefined;
550
- /** Select multiple rows */
551
- selectRows(indices: readonly number[]): unknown[][];
552
- /** Select multiple columns */
553
- selectColumns(indices: readonly number[]): unknown[][];
554
- /** Update multiple rows */
555
- updateRows(updates: ReadonlyMap<number, readonly (unknown | CellConfig)[]>): void;
556
- /** Update multiple cells */
557
- updateCells(updates: ReadonlyMap<readonly [number, number], unknown | CellConfig>): void;
558
- /** Get all row elements */
559
- getRowElements(): readonly HTMLTableRowElement[];
560
- /** Get cells for a row */
561
- getRowCellElements(rowIndex: number): readonly HTMLTableCellElement[];
562
- /** Set multiple rows */
563
- setRows(startIndex: number, rows: readonly (readonly (unknown | CellConfig)[])[]): void;
564
- /** Validate single cell */
565
- validateCell(rowIndex: number, columnIndex: number, validator: CellValidator): true | ValidationError;
566
- /** Validate single row */
567
- validateRow(index: number, validator: RowValidator): true | ValidationError[];
568
- /** Validate single column */
569
- validateColumn(index: number, validator: CellValidator): true | ValidationError[];
570
- /** Validate all cells */
571
- validateAll(validator: FullValidator): ValidationResult;
572
- /** Sum of column values */
573
- sum(columnIndex: number): number;
574
- /** Average of column values */
575
- average(columnIndex: number): number;
576
- /** Minimum value in column */
577
- min(columnIndex: number): unknown;
578
- /** Maximum value in column */
579
- max(columnIndex: number): unknown;
580
- /** Count values in column */
581
- count(columnIndex: number, predicate?: (value: unknown) => boolean): number;
582
- /** Custom aggregation */
583
- aggregate<T>(columnIndex: number, options: AggregateConfig<T>): T;
584
- /** Transform all cells in column */
585
- transformColumn(columnIndex: number, transformer: (value: unknown, rowIndex: number) => unknown): void;
586
- /** Transform all cells in row */
587
- transformRow(rowIndex: number, transformer: (value: unknown, colIndex: number) => unknown): void;
588
- /** Transform all cells */
589
- transformCells(transformer: (value: unknown, rowIndex: number, colIndex: number) => unknown): void;
590
- /** Export to CSV string */
591
- exportToCSV(): string;
592
- /** Export to JSON string */
593
- exportToJSON(): string;
594
- /** Import from 2D array */
595
- importFromArray(data: readonly (readonly unknown[])[]): void;
596
- /** Import from CSV string */
597
- importFromCSV(csv: string): void;
598
- /** Import from JSON string */
599
- importFromJSON(json: string): void;
600
- /** Search all cells */
601
- search(query: string, options?: SearchOptions): SearchResult[];
602
- /** Search single column */
603
- searchColumn(columnIndex: number, query: string, options?: SearchOptions): SearchResult[];
604
- /** Selected row indices */
605
- readonly selectedRows: Readonly<Ref<Set<number>>>;
606
- /** Selected cell keys (row,column format) */
607
- readonly selectedCells: Readonly<Ref<Set<string>>>;
608
- /** Select a row */
487
+ /** Select a row by index */
609
488
  selectRow(index: number): void;
610
- /** Deselect a row */
489
+ /** Deselect a row by index */
611
490
  deselectRow(index: number): void;
612
491
  /** Toggle row selection */
613
492
  toggleRowSelection(index: number): void;
614
- /** Check if row is selected */
615
- isRowSelected(index: number): boolean;
616
- /** Select a cell */
617
- selectCell(rowIndex: number, columnIndex: number): void;
618
- /** Clear all selection */
619
- clearSelection(): void;
620
- /** Enable cell editing */
621
- enableCellEditing(config?: EditableConfig): void;
622
- /** Disable cell editing */
623
- disableCellEditing(): void;
624
- /** Enable header editing */
625
- enableHeaderEditing(config?: Omit<EditableConfig, 'cells'>): void;
626
- /** Disable header editing */
627
- disableHeaderEditing(): void;
628
- /** Enable editing for specific column */
629
- enableColumnEditing(columnIndex: number, config?: EditableConfig): void;
630
- /** Disable editing for specific column */
631
- disableColumnEditing(columnIndex: number): void;
632
- /** Enable editing for specific row */
633
- enableRowEditing(rowIndex: number, config?: EditableConfig): void;
634
- /** Disable editing for specific row */
635
- disableRowEditing(rowIndex: number): void;
636
- /** Enable double-click to edit (returns cleanup) */
637
- enableEditing(): () => void;
638
- /** Group rows by key function */
639
- groupBy(keyFunction: (row: unknown[]) => string | number): Map<string | number, number[]>;
640
- /** Add computed column */
641
- addComputedColumn(config: ComputedColumnConfig): number;
642
- /** Remove computed column */
643
- removeComputedColumn(index: number): void;
644
- /** Current pagination state */
645
- readonly pagination: PaginationState | null;
646
- /** Enable pagination */
647
- paginate(config: PaginationConfig): void;
648
- /** Go to next page */
649
- nextPage(): void;
650
- /** Go to previous page */
651
- previousPage(): void;
652
- /** Go to specific page */
653
- goToPage(page: number): void;
654
- /** Current virtual scroll state */
655
- readonly virtualScroll: VirtualScrollState | null;
656
- /** Enable virtual scrolling */
657
- enableVirtualScrolling(config: VirtualScrollConfig): void;
658
- /** Disable virtual scrolling */
659
- disableVirtualScrolling(): void;
660
- /** Execute operations with rollback on error */
661
- transaction<T>(callback: () => T | Promise<T>): T | Promise<T>;
662
- /** Subscribe to data changes (returns unsubscribe) */
663
- onDataChange(callback: (data: unknown[][]) => void): () => void;
664
- /** Current sort state */
665
- readonly sortState: SortState;
666
- /** Sort column ascending */
667
- sortColumnAscending(columnIndex: number): void;
668
- /** Sort column descending */
669
- sortColumnDescending(columnIndex: number): void;
670
- /** Sort column ascending with custom comparator */
671
- sortColumnAscendingWith(columnIndex: number, comparator: (a: unknown, b: unknown) => number): void;
672
- /** Sort column descending with custom comparator */
673
- sortColumnDescendingWith(columnIndex: number, comparator: (a: unknown, b: unknown) => number): void;
674
- /** Clear sorting */
675
- clearColumnSort(): void;
676
- /** Get sorted column index */
677
- getSortedColumnIndex(): number | null;
678
- /** Check if sorted ascending */
679
- isSortedAscending(): boolean;
680
- /** Check if sorted descending */
681
- isSortedDescending(): boolean;
682
- /** Check if any sort is active */
683
- isSorted(): boolean;
684
- /** Current filter state */
685
- readonly filterState: FilterState;
686
- /** Filter rows by predicate */
687
- filterRows(predicate: (rowData: unknown[], rowIndex: number) => boolean): void;
688
- /** Filter by column predicate */
689
- filterColumn(columnIndex: number, predicate: (value: unknown) => boolean): void;
690
- /** Filter by exact value */
691
- filterColumnByValue(columnIndex: number, value: unknown): void;
692
- /** Filter by multiple values */
693
- filterColumnByValues(columnIndex: number, values: readonly unknown[]): void;
694
- /** Clear all filters */
695
- clearFilters(): void;
696
- /** Get visible row indices */
697
- getFilteredRowIndices(): readonly number[];
698
- /** Set function to generate row keys */
699
- setRowKeyFunction(keyFunction: (rowData: unknown[], rowIndex: number) => string | number): void;
700
- /** Clear row key function */
701
- clearRowKeyFunction(): void;
702
- /** Check if row key function is set */
703
- hasRowKeyFunction(): boolean;
704
- /** Get row data by key */
705
- getRowByKey(key: string | number): unknown[] | undefined;
706
- /** Get row index by key */
707
- getRowIndexByKey(key: string | number): number | undefined;
708
- /** Update row by key */
709
- updateRowByKey(key: string | number, rowData: readonly unknown[]): boolean;
710
- /** Remove row by key */
711
- removeRowByKey(key: string | number): boolean;
712
- /** Check if row with key exists */
713
- hasRowWithKey(key: string | number): boolean;
714
- /** Get key for row */
715
- getRowKey(rowIndex: number): string | number | undefined;
716
- /** Get all row keys */
717
- getAllRowKeys(): readonly (string | number)[];
718
- /** Set column definition */
719
- setColumnDefinition(columnIndex: number, definition: ColumnDefinition): void;
720
- /** Set all column definitions */
721
- setColumnDefinitions(definitions: readonly (ColumnDefinition | undefined)[]): void;
722
- /** Clear column definition */
723
- clearColumnDefinition(columnIndex: number): void;
724
- /** Clear all column definitions */
725
- clearColumnDefinitions(): void;
726
- /** Get column definition */
727
- getColumnDefinition(columnIndex: number): ColumnDefinition | undefined;
728
- /** Check if column has definition */
729
- hasColumnDefinition(columnIndex: number): boolean;
730
- /** Get parsed cell value */
731
- getParsedCell(rowIndex: number, columnIndex: number): unknown;
732
- /** Get parsed row data */
733
- getParsedRowData(rowIndex: number): unknown[];
734
- /** Get parsed column data */
735
- getParsedColumnData(columnIndex: number): unknown[];
736
- /** Get all parsed data */
737
- getParsedData(): unknown[][];
738
- /** Whether table has unsaved changes */
739
- readonly dirtyState: Readonly<Ref<boolean>>;
740
- /** Mark as clean (save point) */
741
- markClean(): void;
742
- /** Mark as dirty */
743
- markDirty(): void;
744
- /** Check if dirty */
745
- isDirty(): boolean;
746
- /** Check if has changes */
747
- hasChanges(): boolean;
748
- /** Get all cell changes */
749
- getChangedCells(): readonly CellChange[];
750
- /** Get changed row indices */
751
- getChangedRowIndices(): readonly number[];
752
- /** Get changed column indices */
753
- getChangedColumnIndices(): readonly number[];
754
- /** Undo last change */
755
- undo(): boolean;
756
- /** Redo last undone change */
757
- redo(): boolean;
758
- /** Clear history */
759
- clearHistory(): void;
760
- /** Check if can undo */
761
- canUndo(): boolean;
762
- /** Check if can redo */
763
- canRedo(): boolean;
764
- /** Get undo stack size */
765
- getUndoStackSize(): number;
766
- /** Get redo stack size */
767
- getRedoStackSize(): number;
768
- /** Set history limit */
769
- setHistoryLimit(limit: number): void;
770
- /** Get history limit */
771
- getHistoryLimit(): number;
772
493
  /** Select all rows */
773
494
  selectAllRows(): void;
774
495
  /** Deselect all rows */
775
496
  deselectAllRows(): void;
776
- /** Select range of rows */
497
+ /** Select row range */
777
498
  selectRowRange(startIndex: number, endIndex: number): void;
778
- /** Invert row selection */
779
- invertRowSelection(): void;
780
- /** Get data for selected rows */
781
- getSelectedRowData(): readonly unknown[][];
499
+ /** Check if row is selected */
500
+ isRowSelected(index: number): boolean;
782
501
  /** Get selected row indices */
783
502
  getSelectedRowIndices(): readonly number[];
784
- /** Get selected cell positions */
785
- getSelectedCellIndices(): readonly CellPosition[];
786
- /** Currently focused cell */
787
- readonly focusedCell: Readonly<Ref<CellPosition | null>>;
503
+ /** Get selected row data */
504
+ getSelectedRowData(): readonly (readonly CellValue[])[];
505
+ /** Select a cell */
506
+ selectCell(row: number, column: number): void;
507
+ /** Deselect a cell */
508
+ deselectCell(row: number, column: number): void;
509
+ /** Toggle cell selection */
510
+ toggleCellSelection(row: number, column: number): void;
511
+ /** Check if cell is selected */
512
+ isCellSelected(row: number, column: number): boolean;
513
+ /** Clear all selection */
514
+ clearSelection(): void;
788
515
  /** Focus a cell */
789
- focusCell(rowIndex: number, columnIndex: number): void;
516
+ focusCell(row: number, column: number): void;
790
517
  /** Clear cell focus */
791
- clearCellFocus(): void;
518
+ clearFocus(): void;
792
519
  /** Get focused cell position */
793
520
  getFocusedCell(): CellPosition | null;
794
521
  /** Check if cell is focused */
795
- isCellFocused(rowIndex: number, columnIndex: number): boolean;
522
+ isCellFocused(row: number, column: number): boolean;
796
523
  /** Move focus up */
797
524
  moveFocusUp(): boolean;
798
525
  /** Move focus down */
@@ -802,369 +529,51 @@ export declare interface UseTableReturn extends ReactiveRowCollection, ReactiveT
802
529
  /** Move focus right */
803
530
  moveFocusRight(): boolean;
804
531
  /** Move focus to first cell */
805
- moveFocusToFirstCell(): void;
532
+ moveFocusToFirst(): void;
806
533
  /** Move focus to last cell */
807
- moveFocusToLastCell(): void;
808
- /** Move focus to row start */
809
- moveFocusToRowStart(): void;
810
- /** Move focus to row end */
811
- moveFocusToRowEnd(): void;
812
- /** Enable keyboard navigation (returns cleanup) */
534
+ moveFocusToLast(): void;
535
+ /** Enable keyboard navigation (returns cleanup function) */
813
536
  enableKeyboardNavigation(): () => void;
814
- /** Count of visible columns */
815
- readonly visibleColumnCount: Readonly<Ref<number>>;
816
- /** Hide a column */
817
- hideColumn(columnIndex: number): void;
818
- /** Show a column */
819
- showColumn(columnIndex: number): void;
820
- /** Toggle column visibility */
821
- toggleColumnVisibility(columnIndex: number): void;
822
- /** Check if column is visible */
823
- isColumnVisible(columnIndex: number): boolean;
824
- /** Get visible column indices */
825
- getVisibleColumnIndices(): readonly number[];
826
- /** Get hidden column indices */
827
- getHiddenColumnIndices(): readonly number[];
828
- /** Move row from one position to another */
829
- moveRow(fromIndex: number, toIndex: number): void;
830
- /** Move row up */
831
- moveRowUp(rowIndex: number): boolean;
832
- /** Move row down */
833
- moveRowDown(rowIndex: number): boolean;
834
- /** Move row to top */
835
- moveRowToTop(rowIndex: number): void;
836
- /** Move row to bottom */
837
- moveRowToBottom(rowIndex: number): void;
838
- /** Swap two rows */
839
- swapRows(indexA: number, indexB: number): void;
840
- /** Move column from one position to another */
841
- moveColumn(fromIndex: number, toIndex: number): void;
842
- /** Move column left */
843
- moveColumnLeft(columnIndex: number): boolean;
844
- /** Move column right */
845
- moveColumnRight(columnIndex: number): boolean;
846
- /** Move column to start */
847
- moveColumnToStart(columnIndex: number): void;
848
- /** Move column to end */
849
- moveColumnToEnd(columnIndex: number): void;
850
- /** Swap two columns */
851
- swapColumns(indexA: number, indexB: number): void;
852
- /** Copy selected cells to string */
853
- copySelectedCells(): string;
854
- /** Copy selected rows to string */
855
- copySelectedRows(): string;
856
- /** Copy row to string */
857
- copyRow(rowIndex: number): string;
858
- /** Copy column to string */
859
- copyColumn(columnIndex: number): string;
860
- /** Copy cell to string */
861
- copyCell(rowIndex: number, columnIndex: number): string;
862
- /** Copy cell range to string */
863
- copyCellRange(rowStart: number, columnStart: number, rowEnd: number, columnEnd: number): string;
864
- /** Paste data at cell */
865
- pasteAtCell(rowIndex: number, columnIndex: number, data: string): void;
866
- /** Expanded row indices */
867
- readonly expandedRows: Readonly<Ref<ReadonlySet<number>>>;
868
- /** Rows pinned to top */
869
- readonly pinnedTopRows: Readonly<Ref<readonly number[]>>;
870
- /** Rows pinned to bottom */
871
- readonly pinnedBottomRows: Readonly<Ref<readonly number[]>>;
872
- /** Expand a row */
873
- expandRow(rowIndex: number): void;
874
- /** Collapse a row */
875
- collapseRow(rowIndex: number): void;
876
- /** Toggle row expansion */
877
- toggleRowExpansion(rowIndex: number): void;
878
- /** Expand all rows */
879
- expandAllRows(): void;
880
- /** Collapse all rows */
881
- collapseAllRows(): void;
882
- /** Check if row is expanded */
883
- isRowExpanded(rowIndex: number): boolean;
884
- /** Get expanded row indices */
885
- getExpandedRowIndices(): readonly number[];
886
- /** Pin row to top */
887
- pinRowTop(rowIndex: number): void;
888
- /** Pin row to bottom */
889
- pinRowBottom(rowIndex: number): void;
890
- /** Unpin a row */
891
- unpinRow(rowIndex: number): void;
892
- /** Unpin all rows */
893
- unpinAllRows(): void;
894
- /** Check if row is pinned to top */
895
- isRowPinnedTop(rowIndex: number): boolean;
896
- /** Check if row is pinned to bottom */
897
- isRowPinnedBottom(rowIndex: number): boolean;
898
- /** Get indices of rows pinned to top */
899
- getPinnedTopRowIndices(): readonly number[];
900
- /** Get indices of rows pinned to bottom */
901
- getPinnedBottomRowIndices(): readonly number[];
902
- /** Set cell metadata */
903
- setCellMeta<T>(rowIndex: number, columnIndex: number, key: string, value: T): void;
904
- /** Get cell metadata */
905
- getCellMeta<T>(rowIndex: number, columnIndex: number, key: string): T | undefined;
906
- /** Check if cell has metadata */
907
- hasCellMeta(rowIndex: number, columnIndex: number, key: string): boolean;
908
- /** Clear all cell metadata */
909
- clearCellMeta(rowIndex: number, columnIndex: number): void;
910
- /** Clear specific cell metadata key */
911
- clearCellMetaKey(rowIndex: number, columnIndex: number, key: string): void;
912
- /** Set row metadata */
913
- setRowMeta<T>(rowIndex: number, key: string, value: T): void;
914
- /** Get row metadata */
915
- getRowMeta<T>(rowIndex: number, key: string): T | undefined;
916
- /** Check if row has metadata */
917
- hasRowMeta(rowIndex: number, key: string): boolean;
918
- /** Clear all row metadata */
919
- clearRowMeta(rowIndex: number): void;
920
- /** Clear specific row metadata key */
921
- clearRowMetaKey(rowIndex: number, key: string): void;
922
- /** Set column metadata */
923
- setColumnMeta<T>(columnIndex: number, key: string, value: T): void;
924
- /** Get column metadata */
925
- getColumnMeta<T>(columnIndex: number, key: string): T | undefined;
926
- /** Check if column has metadata */
927
- hasColumnMeta(columnIndex: number, key: string): boolean;
928
- /** Clear all column metadata */
929
- clearColumnMeta(columnIndex: number): void;
930
- /** Clear specific column metadata key */
931
- clearColumnMetaKey(columnIndex: number, key: string): void;
932
- /** Subscribe to row add events */
933
- onRowAdd(callback: (rowData: unknown[], rowIndex: number) => void): () => void;
934
- /** Subscribe to row remove events */
935
- onRowRemove(callback: (rowData: unknown[], rowIndex: number) => void): () => void;
936
- /** Subscribe to row update events */
937
- onRowUpdate(callback: (rowIndex: number, oldRowData: unknown[], newRowData: unknown[]) => void): () => void;
938
- /** Subscribe to cell change events */
939
- onCellChange(callback: (rowIndex: number, columnIndex: number, oldValue: unknown, newValue: unknown) => void): () => void;
940
- /** Subscribe to row selection change events */
941
- onRowSelectionChange(callback: (selectedIndices: ReadonlySet<number>) => void): () => void;
942
- /** Subscribe to cell selection change events */
943
- onCellSelectionChange(callback: (selectedCells: ReadonlySet<string>) => void): () => void;
944
- /** Subscribe to sort change events */
945
- onSortChange(callback: (columnIndex: number | null, ascending: boolean) => void): () => void;
946
- /** Subscribe to filter change events */
947
- onFilterChange(callback: (filteredIndices: readonly number[]) => void): () => void;
948
- /** Subscribe to cell focus change events */
949
- onCellFocusChange(callback: (cell: CellPosition | null) => void): () => void;
950
- /** Subscribe to column visibility change events */
951
- onColumnVisibilityChange(callback: (columnIndex: number, visible: boolean) => void): () => void;
952
- /** Begin batch update (defer reactivity) */
953
- beginBatchUpdate(): void;
954
- /** End batch update (commit changes) */
955
- endBatchUpdate(): void;
956
- /** Cancel batch update (rollback) */
957
- cancelBatchUpdate(): void;
958
- /** Check if batch updating */
959
- isBatchUpdating(): boolean;
960
- /** Execute callback as batch */
961
- batchUpdate(callback: () => void): void;
962
- /** Whether table is loading */
963
- readonly tableLoading: Readonly<Ref<boolean>>;
964
- /** Set table loading state */
965
- setTableLoading(loading: boolean): void;
966
- /** Set cell loading state */
967
- setCellLoading(rowIndex: number, columnIndex: number, loading: boolean): void;
968
- /** Set row loading state */
969
- setRowLoading(rowIndex: number, loading: boolean): void;
970
- /** Set column loading state */
971
- setColumnLoading(columnIndex: number, loading: boolean): void;
972
- /** Check if table is loading */
973
- isTableLoading(): boolean;
974
- /** Check if cell is loading */
975
- isCellLoading(rowIndex: number, columnIndex: number): boolean;
976
- /** Check if row is loading */
977
- isRowLoading(rowIndex: number): boolean;
978
- /** Check if column is loading */
979
- isColumnLoading(columnIndex: number): boolean;
980
- /** Load data with fetcher */
981
- loadData(fetcher: () => Promise<readonly (readonly unknown[])[]>): Promise<void>;
982
- /** Append rows asynchronously */
983
- appendRowsAsync(fetcher: () => Promise<readonly (readonly unknown[])[]>): Promise<void>;
984
- /** Prepend rows asynchronously */
985
- prependRowsAsync(fetcher: () => Promise<readonly (readonly unknown[])[]>): Promise<void>;
986
- /** Number of columns frozen on left */
987
- readonly frozenLeftColumnCount: Readonly<Ref<number>>;
988
- /** Number of columns frozen on right */
989
- readonly frozenRightColumnCount: Readonly<Ref<number>>;
990
- /** Freeze columns on left */
991
- freezeColumnsLeft(count: number): void;
992
- /** Freeze columns on right */
993
- freezeColumnsRight(count: number): void;
994
- /** Unfreeze columns on left */
995
- unfreezeColumnsLeft(): void;
996
- /** Unfreeze columns on right */
997
- unfreezeColumnsRight(): void;
998
- /** Unfreeze all columns */
999
- unfreezeAllColumns(): void;
1000
- /** Get frozen left column count */
1001
- getFrozenLeftColumnCount(): number;
1002
- /** Get frozen right column count */
1003
- getFrozenRightColumnCount(): number;
1004
- /** Check if column is frozen on left */
1005
- isColumnFrozenLeft(columnIndex: number): boolean;
1006
- /** Check if column is frozen on right */
1007
- isColumnFrozenRight(columnIndex: number): boolean;
1008
- /** Check if any columns are frozen */
1009
- hasFrozenColumns(): boolean;
1010
- /**
1011
- * Configure table for record-based data.
1012
- * This enables integration with useDatabase and other composables.
1013
- */
1014
- setRecordColumns<T extends BaseRecord>(columns: readonly RecordColumnDef<T>[]): void;
1015
- /**
1016
- * Clear record column configuration.
1017
- */
1018
- clearRecordColumns(): void;
1019
- /**
1020
- * Check if record columns are configured.
1021
- */
1022
- hasRecordColumns(): boolean;
1023
- /**
1024
- * Get the configured record columns.
1025
- */
1026
- getRecordColumns<T extends BaseRecord>(): readonly RecordColumnDef<T>[] | undefined;
1027
- /**
1028
- * Set table data from an array of records.
1029
- * Records must have an `id` field.
1030
- */
1031
- setRecords<T extends BaseRecord>(records: readonly T[]): void;
1032
- /**
1033
- * Get all records from the table.
1034
- * Returns records reconstructed from table data using column definitions.
1035
- */
1036
- getRecords<T extends BaseRecord>(): readonly T[];
1037
- /**
1038
- * Get a single record by ID.
1039
- */
1040
- getRecordById<T extends BaseRecord>(id: string): T | undefined;
1041
- /**
1042
- * Get record ID for a row index.
1043
- */
1044
- getRecordId(rowIndex: number): string | undefined;
1045
- /**
1046
- * Get row index for a record ID.
1047
- */
1048
- getRowIndexForRecord(recordId: string): number | undefined;
1049
- /**
1050
- * Update a record by ID.
1051
- * Only updates the specified fields.
1052
- */
1053
- updateRecord<T extends BaseRecord>(id: string, updates: Partial<Omit<T, 'id'>>): boolean;
1054
- /**
1055
- * Add a new record to the table.
1056
- * If no ID is provided, one will be generated.
1057
- */
1058
- addRecord<T extends BaseRecord>(record: T | Omit<T, 'id'>, index?: number): string;
1059
- /**
1060
- * Remove a record by ID.
1061
- */
537
+ /** Set records with column mapping */
538
+ setRecords<T extends BaseRecord>(records: readonly T[], fields: readonly (keyof T | ((record: T) => CellValue))[]): void;
539
+ /** Get record data by ID */
540
+ getRecordData(id: string): CellValue[] | undefined;
541
+ /** Add a record */
542
+ addRecord<T extends BaseRecord>(record: T | Omit<T, 'id'>, fields: readonly (keyof T | ((record: T) => CellValue))[], index?: number): string;
543
+ /** Update a record row by ID */
544
+ updateRecordRow(id: string, data: RowData): boolean;
545
+ /** Remove a record by ID */
1062
546
  removeRecord(id: string): boolean;
1063
- /**
1064
- * Check if a record with the given ID exists.
1065
- */
547
+ /** Check if record exists */
1066
548
  hasRecord(id: string): boolean;
1067
- /**
1068
- * Get record IDs for selected rows.
1069
- */
549
+ /** Get selected record IDs */
1070
550
  getSelectedRecordIds(): readonly string[];
1071
- /**
1072
- * Select rows by record IDs.
1073
- */
551
+ /** Select records by IDs */
1074
552
  selectRecords(ids: readonly string[]): void;
1075
- /**
1076
- * Deselect rows by record IDs.
1077
- */
553
+ /** Deselect records by IDs */
1078
554
  deselectRecords(ids: readonly string[]): void;
1079
- /**
1080
- * Get the selected records.
1081
- */
1082
- getSelectedRecords<T extends BaseRecord>(): readonly T[];
1083
- /**
1084
- * Subscribe to record changes.
1085
- * Callback receives the record ID and the updated record.
1086
- */
1087
- onRecordChange<T extends BaseRecord>(callback: (recordId: string, record: T, changeType: 'add' | 'update' | 'remove') => void): () => void;
1088
- /**
1089
- * Set the ID generator for new records.
1090
- */
555
+ /** Set the ID generator function */
1091
556
  setIdGenerator(generator: IdGenerator): void;
1092
- /**
1093
- * Convert array row data to a record object using column definitions.
1094
- */
1095
- rowToRecord<T extends BaseRecord>(rowIndex: number): T | undefined;
1096
- /**
1097
- * Convert a record to array row data using column definitions.
1098
- */
1099
- recordToRow<T extends BaseRecord>(record: T): unknown[];
1100
- /**
1101
- * Export records to JSON (uses column definitions).
1102
- */
1103
- exportRecordsToJSON(): string;
1104
- /**
1105
- * Import records from JSON.
1106
- */
1107
- importRecordsFromJSON(json: string): void;
1108
- }
1109
-
1110
- /**
1111
- * Validation error for a specific cell.
1112
- */
1113
- export declare interface ValidationError {
1114
- /** Row index */
1115
- readonly row: number;
1116
- /** Column index */
1117
- readonly column: number;
1118
- /** The invalid value */
1119
- readonly value: unknown;
1120
- /** Error message */
1121
- readonly message: string;
1122
- }
1123
-
1124
- /**
1125
- * Result of validation operations.
1126
- */
1127
- export declare interface ValidationResult {
1128
- /** Whether validation passed */
1129
- readonly valid: boolean;
1130
- /** Array of validation errors */
1131
- readonly errors: readonly ValidationError[];
1132
- }
1133
-
1134
- /**
1135
- * Virtual scrolling configuration.
1136
- */
1137
- export declare interface VirtualScrollConfig {
1138
- /** Height of each row in pixels */
1139
- readonly rowHeight: number;
1140
- /** Number of extra rows to render above/below viewport */
1141
- readonly overscan: number;
1142
- /** Height of the scroll container in pixels */
1143
- readonly containerHeight: number;
1144
- }
1145
-
1146
- /**
1147
- * Virtual scrolling state.
1148
- */
1149
- export declare interface VirtualScrollState {
1150
- /** Current scroll position */
1151
- readonly scrollTop: Ref<number>;
1152
- /** Height of each row */
1153
- readonly rowHeight: number;
1154
- /** Overscan count */
1155
- readonly overscan: number;
1156
- /** Container height */
1157
- readonly containerHeight: number;
1158
- /** Indices of currently visible rows */
1159
- readonly visibleRows: Ref<number[]>;
1160
- /** Start index of visible range */
1161
- readonly startIndex: Ref<number>;
1162
- /** End index of visible range */
1163
- readonly endIndex: Ref<number>;
1164
- /** Scroll event handler (internal) */
1165
- scrollHandler?: () => void;
1166
- /** Container element (internal) */
1167
- container?: HTMLElement;
557
+ /** Generate a new ID */
558
+ generateId(): string;
559
+ /** Subscribe to row add events */
560
+ onRowAdd(callback: RowAddCallback): () => void;
561
+ /** Subscribe to row remove events */
562
+ onRowRemove(callback: RowRemoveCallback): () => void;
563
+ /** Subscribe to row update events */
564
+ onRowUpdate(callback: RowUpdateCallback): () => void;
565
+ /** Subscribe to cell change events */
566
+ onCellChange(callback: CellChangeCallback): () => void;
567
+ /** Subscribe to header change events */
568
+ onHeaderChange(callback: HeaderChangeCallback): () => void;
569
+ /** Subscribe to data change events */
570
+ onDataChange(callback: DataChangeCallback): () => void;
571
+ /** Subscribe to selection change events */
572
+ onSelectionChange(callback: (selectedRows: ReadonlySet<number>, selectedCells: ReadonlySet<string>) => void): () => void;
573
+ /** Subscribe to focus change events */
574
+ onFocusChange(callback: (cell: CellPosition | null) => void): () => void;
575
+ /** Destroy and clean up */
576
+ destroy(): void;
1168
577
  }
1169
578
 
1170
579
  /**