tablero 1.0.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.
- package/README.md +181 -0
- package/dist/core.d.mts +447 -0
- package/dist/core.d.ts +447 -0
- package/dist/core.js +426 -0
- package/dist/core.js.map +1 -0
- package/dist/core.mjs +376 -0
- package/dist/core.mjs.map +1 -0
- package/dist/react.d.mts +117 -0
- package/dist/react.d.ts +117 -0
- package/dist/react.js +543 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +541 -0
- package/dist/react.mjs.map +1 -0
- package/dist/ui.d.mts +160 -0
- package/dist/ui.d.ts +160 -0
- package/dist/ui.js +318 -0
- package/dist/ui.js.map +1 -0
- package/dist/ui.mjs +309 -0
- package/dist/ui.mjs.map +1 -0
- package/package.json +81 -0
package/dist/core.mjs
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
// packages/core/tableState.ts
|
|
2
|
+
function createInitialTableState(columnIds) {
|
|
3
|
+
return {
|
|
4
|
+
sorting: {
|
|
5
|
+
columnId: null,
|
|
6
|
+
direction: null
|
|
7
|
+
},
|
|
8
|
+
pagination: {
|
|
9
|
+
pageIndex: 0,
|
|
10
|
+
pageSize: 10
|
|
11
|
+
},
|
|
12
|
+
filtering: {
|
|
13
|
+
globalFilter: "",
|
|
14
|
+
columnFilters: {}
|
|
15
|
+
},
|
|
16
|
+
columnVisibility: columnIds.reduce((acc, id) => {
|
|
17
|
+
acc[id] = true;
|
|
18
|
+
return acc;
|
|
19
|
+
}, {}),
|
|
20
|
+
columnOrder: [...columnIds]
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function updateTableState(state, updates) {
|
|
24
|
+
return {
|
|
25
|
+
...state,
|
|
26
|
+
...updates
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function updateSorting(state, sorting) {
|
|
30
|
+
return updateTableState(state, { sorting });
|
|
31
|
+
}
|
|
32
|
+
function updatePagination(state, pagination) {
|
|
33
|
+
return updateTableState(state, {
|
|
34
|
+
pagination: {
|
|
35
|
+
...state.pagination,
|
|
36
|
+
...pagination
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function updateFiltering(state, filtering) {
|
|
41
|
+
return updateTableState(state, {
|
|
42
|
+
filtering: {
|
|
43
|
+
...state.filtering,
|
|
44
|
+
...filtering
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function updateColumnVisibility(state, columnId, visible) {
|
|
49
|
+
return updateTableState(state, {
|
|
50
|
+
columnVisibility: {
|
|
51
|
+
...state.columnVisibility,
|
|
52
|
+
[columnId]: visible
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function updateColumnOrder(state, columnOrder) {
|
|
57
|
+
return updateTableState(state, { columnOrder });
|
|
58
|
+
}
|
|
59
|
+
function isControlledState(handler) {
|
|
60
|
+
return "state" in handler && "setState" in handler;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// packages/core/sorting.ts
|
|
64
|
+
function createInitialSortState() {
|
|
65
|
+
return {
|
|
66
|
+
columnId: null,
|
|
67
|
+
direction: null
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function toggleSort(currentState, columnId) {
|
|
71
|
+
if (currentState.columnId === columnId) {
|
|
72
|
+
if (currentState.direction === "asc") {
|
|
73
|
+
return { columnId, direction: "desc" };
|
|
74
|
+
}
|
|
75
|
+
if (currentState.direction === "desc") {
|
|
76
|
+
return { columnId: null, direction: null };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return { columnId, direction: "asc" };
|
|
80
|
+
}
|
|
81
|
+
function setSort(columnId, direction) {
|
|
82
|
+
return {
|
|
83
|
+
columnId,
|
|
84
|
+
direction
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function clearSort() {
|
|
88
|
+
return createInitialSortState();
|
|
89
|
+
}
|
|
90
|
+
function isSortActive(state) {
|
|
91
|
+
return state.columnId !== null && state.direction !== null;
|
|
92
|
+
}
|
|
93
|
+
function defaultCompare(a, b) {
|
|
94
|
+
if (a === b) return 0;
|
|
95
|
+
if (a === null || a === void 0) return 1;
|
|
96
|
+
if (b === null || b === void 0) return -1;
|
|
97
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
98
|
+
return a - b;
|
|
99
|
+
}
|
|
100
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
101
|
+
return a.localeCompare(b);
|
|
102
|
+
}
|
|
103
|
+
if (a instanceof Date && b instanceof Date) {
|
|
104
|
+
return a.getTime() - b.getTime();
|
|
105
|
+
}
|
|
106
|
+
return String(a).localeCompare(String(b));
|
|
107
|
+
}
|
|
108
|
+
function createComparator(direction, compareFn = defaultCompare) {
|
|
109
|
+
return (a, b) => {
|
|
110
|
+
const result = compareFn(a, b);
|
|
111
|
+
return direction === "asc" ? result : -result;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function applySort(data, sortState, getValue, compareFn) {
|
|
115
|
+
if (!isSortActive(sortState) || !sortState.columnId) {
|
|
116
|
+
return [...data];
|
|
117
|
+
}
|
|
118
|
+
const comparator = createComparator(
|
|
119
|
+
sortState.direction,
|
|
120
|
+
compareFn || defaultCompare
|
|
121
|
+
);
|
|
122
|
+
return [...data].sort((a, b) => {
|
|
123
|
+
const valueA = getValue(a, sortState.columnId);
|
|
124
|
+
const valueB = getValue(b, sortState.columnId);
|
|
125
|
+
return comparator(valueA, valueB);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// packages/core/pagination.ts
|
|
130
|
+
function createInitialPaginationState(pageSize = 10) {
|
|
131
|
+
return {
|
|
132
|
+
pageIndex: 0,
|
|
133
|
+
pageSize
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function getPageCount(totalItems, pageSize) {
|
|
137
|
+
if (pageSize <= 0) return 0;
|
|
138
|
+
return Math.ceil(totalItems / pageSize);
|
|
139
|
+
}
|
|
140
|
+
function getPageStartIndex(pageIndex, pageSize) {
|
|
141
|
+
return pageIndex * pageSize;
|
|
142
|
+
}
|
|
143
|
+
function getPageEndIndex(pageIndex, pageSize, totalItems) {
|
|
144
|
+
return Math.min(getPageStartIndex(pageIndex, pageSize) + pageSize, totalItems);
|
|
145
|
+
}
|
|
146
|
+
function isValidPageIndex(pageIndex, totalPages) {
|
|
147
|
+
return pageIndex >= 0 && pageIndex < totalPages;
|
|
148
|
+
}
|
|
149
|
+
function clampPageIndex(pageIndex, totalPages) {
|
|
150
|
+
if (totalPages === 0) return 0;
|
|
151
|
+
return Math.max(0, Math.min(pageIndex, totalPages - 1));
|
|
152
|
+
}
|
|
153
|
+
function goToNextPage(state, totalPages) {
|
|
154
|
+
const nextIndex = clampPageIndex(state.pageIndex + 1, totalPages);
|
|
155
|
+
return {
|
|
156
|
+
...state,
|
|
157
|
+
pageIndex: nextIndex
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function goToPreviousPage(state, totalPages) {
|
|
161
|
+
const prevIndex = clampPageIndex(state.pageIndex - 1, totalPages);
|
|
162
|
+
return {
|
|
163
|
+
...state,
|
|
164
|
+
pageIndex: prevIndex
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function goToPage(state, pageIndex, totalPages) {
|
|
168
|
+
return {
|
|
169
|
+
...state,
|
|
170
|
+
pageIndex: clampPageIndex(pageIndex, totalPages)
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function setPageSize(state, pageSize, totalItems) {
|
|
174
|
+
const totalPages = getPageCount(totalItems, pageSize);
|
|
175
|
+
const clampedPageIndex = clampPageIndex(state.pageIndex, totalPages);
|
|
176
|
+
return {
|
|
177
|
+
pageIndex: clampedPageIndex,
|
|
178
|
+
pageSize
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function getPaginatedData(data, pagination) {
|
|
182
|
+
const start = getPageStartIndex(pagination.pageIndex, pagination.pageSize);
|
|
183
|
+
const end = getPageEndIndex(
|
|
184
|
+
pagination.pageIndex,
|
|
185
|
+
pagination.pageSize,
|
|
186
|
+
data.length
|
|
187
|
+
);
|
|
188
|
+
return data.slice(start, end);
|
|
189
|
+
}
|
|
190
|
+
function hasNextPage(pageIndex, totalPages) {
|
|
191
|
+
return pageIndex < totalPages - 1;
|
|
192
|
+
}
|
|
193
|
+
function hasPreviousPage(pageIndex) {
|
|
194
|
+
return pageIndex > 0;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// packages/core/filtering.ts
|
|
198
|
+
function createInitialFilterState() {
|
|
199
|
+
return {
|
|
200
|
+
globalFilter: "",
|
|
201
|
+
columnFilters: {}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function setGlobalFilter(filter) {
|
|
205
|
+
return {
|
|
206
|
+
globalFilter: filter,
|
|
207
|
+
columnFilters: {}
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function setColumnFilter(state, columnId, filter) {
|
|
211
|
+
return {
|
|
212
|
+
...state,
|
|
213
|
+
columnFilters: {
|
|
214
|
+
...state.columnFilters,
|
|
215
|
+
[columnId]: filter
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function clearColumnFilter(state, columnId) {
|
|
220
|
+
const { [columnId]: _, ...restFilters } = state.columnFilters;
|
|
221
|
+
return {
|
|
222
|
+
...state,
|
|
223
|
+
columnFilters: restFilters
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function clearAllFilters() {
|
|
227
|
+
return createInitialFilterState();
|
|
228
|
+
}
|
|
229
|
+
function isFilterActive(state) {
|
|
230
|
+
return state.globalFilter.trim() !== "" || Object.values(state.columnFilters).some((filter) => filter.trim() !== "");
|
|
231
|
+
}
|
|
232
|
+
function defaultMatch(value, filter) {
|
|
233
|
+
if (!filter.trim()) return true;
|
|
234
|
+
const normalizedFilter = filter.toLowerCase().trim();
|
|
235
|
+
const normalizedValue = String(value ?? "").toLowerCase();
|
|
236
|
+
return normalizedValue.includes(normalizedFilter);
|
|
237
|
+
}
|
|
238
|
+
function applyFilters(data, filterState, getValue, matchFn = defaultMatch) {
|
|
239
|
+
if (!isFilterActive(filterState)) {
|
|
240
|
+
return [...data];
|
|
241
|
+
}
|
|
242
|
+
return data.filter((item) => {
|
|
243
|
+
if (filterState.globalFilter.trim()) {
|
|
244
|
+
const matchesGlobal = Object.keys(filterState.columnFilters).length === 0 ? (
|
|
245
|
+
// If no column filters, check all columns for global filter
|
|
246
|
+
Object.values(item).some(
|
|
247
|
+
(value) => matchFn(value, filterState.globalFilter)
|
|
248
|
+
)
|
|
249
|
+
) : (
|
|
250
|
+
// If column filters exist, global filter is ignored (TODO: make configurable)
|
|
251
|
+
true
|
|
252
|
+
);
|
|
253
|
+
if (!matchesGlobal) return false;
|
|
254
|
+
}
|
|
255
|
+
for (const [columnId, filterValue] of Object.entries(filterState.columnFilters)) {
|
|
256
|
+
if (filterValue.trim()) {
|
|
257
|
+
const value = getValue(item, columnId);
|
|
258
|
+
if (!matchFn(value, filterValue)) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return true;
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
function getActiveFilterCount(state) {
|
|
267
|
+
let count = 0;
|
|
268
|
+
if (state.globalFilter.trim()) {
|
|
269
|
+
count++;
|
|
270
|
+
}
|
|
271
|
+
count += Object.values(state.columnFilters).filter((f) => f.trim() !== "").length;
|
|
272
|
+
return count;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// packages/core/columns.ts
|
|
276
|
+
function col(key, options) {
|
|
277
|
+
return {
|
|
278
|
+
id: String(key),
|
|
279
|
+
header: options?.header ?? String(key),
|
|
280
|
+
sortable: options?.sortable ?? false,
|
|
281
|
+
filter: options?.filter ?? "none",
|
|
282
|
+
width: options?.width,
|
|
283
|
+
minWidth: options?.minWidth,
|
|
284
|
+
maxWidth: options?.maxWidth,
|
|
285
|
+
visible: options?.visible ?? true,
|
|
286
|
+
align: options?.align ?? "left",
|
|
287
|
+
accessor: options?.accessor ?? key,
|
|
288
|
+
meta: options?.meta
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
function colWithAccessor(id, options) {
|
|
292
|
+
return {
|
|
293
|
+
id,
|
|
294
|
+
header: options.header ?? id,
|
|
295
|
+
sortable: options.sortable ?? false,
|
|
296
|
+
filter: options.filter ?? "none",
|
|
297
|
+
width: options.width,
|
|
298
|
+
minWidth: options.minWidth,
|
|
299
|
+
maxWidth: options.maxWidth,
|
|
300
|
+
visible: options.visible ?? true,
|
|
301
|
+
align: options.align ?? "left",
|
|
302
|
+
accessor: options.accessor,
|
|
303
|
+
meta: options.meta
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function defineColumns() {
|
|
307
|
+
return (columns) => columns;
|
|
308
|
+
}
|
|
309
|
+
function normalizeAccessor(accessor) {
|
|
310
|
+
if (typeof accessor === "function") {
|
|
311
|
+
return accessor;
|
|
312
|
+
}
|
|
313
|
+
return (data) => {
|
|
314
|
+
return data[String(accessor)];
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
function createColumn(def) {
|
|
318
|
+
const accessor = def.accessor ? normalizeAccessor(def.accessor) : () => void 0;
|
|
319
|
+
return {
|
|
320
|
+
def,
|
|
321
|
+
id: def.id,
|
|
322
|
+
header: def.header ?? def.id,
|
|
323
|
+
sortable: def.sortable ?? false,
|
|
324
|
+
filter: def.filter ?? "none",
|
|
325
|
+
width: def.width,
|
|
326
|
+
align: def.align ?? "left",
|
|
327
|
+
accessor
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function createColumns(definitions) {
|
|
331
|
+
return definitions.map(createColumn);
|
|
332
|
+
}
|
|
333
|
+
function getColumnById(columns, id) {
|
|
334
|
+
return columns.find((col2) => col2.id === id);
|
|
335
|
+
}
|
|
336
|
+
function getVisibleColumns(columns, visibility) {
|
|
337
|
+
return columns.filter((col2) => visibility[col2.id] !== false);
|
|
338
|
+
}
|
|
339
|
+
function getOrderedColumns(columns, order) {
|
|
340
|
+
const columnMap = new Map(columns.map((col2) => [col2.id, col2]));
|
|
341
|
+
const ordered = [];
|
|
342
|
+
for (const id of order) {
|
|
343
|
+
const col2 = columnMap.get(id);
|
|
344
|
+
if (col2) {
|
|
345
|
+
ordered.push(col2);
|
|
346
|
+
columnMap.delete(id);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
ordered.push(...columnMap.values());
|
|
350
|
+
return ordered;
|
|
351
|
+
}
|
|
352
|
+
function getColumnIds(definitions) {
|
|
353
|
+
return definitions.map((def) => def.id);
|
|
354
|
+
}
|
|
355
|
+
function validateColumns(definitions) {
|
|
356
|
+
const errors = [];
|
|
357
|
+
const ids = /* @__PURE__ */ new Set();
|
|
358
|
+
for (const def of definitions) {
|
|
359
|
+
if (!def.id || def.id.trim() === "") {
|
|
360
|
+
errors.push(`Column definition missing required 'id' field`);
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
if (ids.has(def.id)) {
|
|
364
|
+
errors.push(`Duplicate column ID: ${def.id}`);
|
|
365
|
+
}
|
|
366
|
+
ids.add(def.id);
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
valid: errors.length === 0,
|
|
370
|
+
errors
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export { applyFilters, applySort, clampPageIndex, clearAllFilters, clearColumnFilter, clearSort, col, colWithAccessor, createColumn, createColumns, createComparator, createInitialFilterState, createInitialPaginationState, createInitialSortState, createInitialTableState, defaultCompare, defaultMatch, defineColumns, getActiveFilterCount, getColumnById, getColumnIds, getOrderedColumns, getPageCount, getPageEndIndex, getPageStartIndex, getPaginatedData, getVisibleColumns, goToNextPage, goToPage, goToPreviousPage, hasNextPage, hasPreviousPage, isControlledState, isFilterActive, isSortActive, isValidPageIndex, normalizeAccessor, setColumnFilter, setGlobalFilter, setPageSize, setSort, toggleSort, updateColumnOrder, updateColumnVisibility, updateFiltering, updatePagination, updateSorting, updateTableState, validateColumns };
|
|
375
|
+
//# sourceMappingURL=core.mjs.map
|
|
376
|
+
//# sourceMappingURL=core.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../packages/core/tableState.ts","../packages/core/sorting.ts","../packages/core/pagination.ts","../packages/core/filtering.ts","../packages/core/columns.ts"],"names":["col"],"mappings":"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","file":"core.mjs","sourcesContent":["/**\r\n * Table state management\r\n * \r\n * Core state shape and management utilities for data tables.\r\n * Supports both controlled and uncontrolled state patterns.\r\n */\r\n\r\nimport type { SortState } from './sorting';\r\nimport type { PaginationState } from './pagination';\r\nimport type { FilterState } from './filtering';\r\n\r\n/**\r\n * Core table state interface\r\n * \r\n * Designed to be extensible for:\r\n * - Server-side mode (via mode: 'server' | 'client')\r\n * - Multi-sort (sorting can be extended to array)\r\n * - URL sync (state can be serialized/deserialized)\r\n */\r\nexport interface TableState {\r\n /** Sorting state - single column for now, extensible to array for multi-sort */\r\n sorting: SortState;\r\n \r\n /** Pagination state */\r\n pagination: PaginationState;\r\n \r\n /** Filtering state */\r\n filtering: FilterState;\r\n \r\n /** Column visibility state - maps column ID to visibility */\r\n columnVisibility: Record<string, boolean>;\r\n \r\n /** Column order - array of column IDs */\r\n columnOrder: string[];\r\n \r\n // TODO: Add server-side mode support\r\n // mode?: 'client' | 'server';\r\n \r\n // TODO: Add URL sync support\r\n // syncToUrl?: boolean;\r\n}\r\n\r\n/**\r\n * Initial table state with defaults\r\n */\r\nexport function createInitialTableState(columnIds: string[]): TableState {\r\n return {\r\n sorting: {\r\n columnId: null,\r\n direction: null,\r\n },\r\n pagination: {\r\n pageIndex: 0,\r\n pageSize: 10,\r\n },\r\n filtering: {\r\n globalFilter: '',\r\n columnFilters: {},\r\n },\r\n columnVisibility: columnIds.reduce((acc, id) => {\r\n acc[id] = true;\r\n return acc;\r\n }, {} as Record<string, boolean>),\r\n columnOrder: [...columnIds],\r\n };\r\n}\r\n\r\n/**\r\n * Update table state immutably\r\n * Returns a new state object with the update applied\r\n */\r\nexport function updateTableState<T extends TableState>(\r\n state: T,\r\n updates: Partial<TableState>\r\n): T {\r\n return {\r\n ...state,\r\n ...updates,\r\n };\r\n}\r\n\r\n/**\r\n * Update sorting state\r\n */\r\nexport function updateSorting(\r\n state: TableState,\r\n sorting: SortState\r\n): TableState {\r\n return updateTableState(state, { sorting });\r\n}\r\n\r\n/**\r\n * Update pagination state\r\n */\r\nexport function updatePagination(\r\n state: TableState,\r\n pagination: Partial<PaginationState>\r\n): TableState {\r\n return updateTableState(state, {\r\n pagination: {\r\n ...state.pagination,\r\n ...pagination,\r\n },\r\n });\r\n}\r\n\r\n/**\r\n * Update filtering state\r\n */\r\nexport function updateFiltering(\r\n state: TableState,\r\n filtering: Partial<FilterState>\r\n): TableState {\r\n return updateTableState(state, {\r\n filtering: {\r\n ...state.filtering,\r\n ...filtering,\r\n },\r\n });\r\n}\r\n\r\n/**\r\n * Update column visibility\r\n */\r\nexport function updateColumnVisibility(\r\n state: TableState,\r\n columnId: string,\r\n visible: boolean\r\n): TableState {\r\n return updateTableState(state, {\r\n columnVisibility: {\r\n ...state.columnVisibility,\r\n [columnId]: visible,\r\n },\r\n });\r\n}\r\n\r\n/**\r\n * Update column order\r\n */\r\nexport function updateColumnOrder(\r\n state: TableState,\r\n columnOrder: string[]\r\n): TableState {\r\n return updateTableState(state, { columnOrder });\r\n}\r\n\r\n/**\r\n * Controlled state handler type\r\n * Used when state is managed externally\r\n */\r\nexport type TableStateHandler = {\r\n state: TableState;\r\n setState: (state: TableState | ((prev: TableState) => TableState)) => void;\r\n};\r\n\r\n/**\r\n * Uncontrolled state handler type\r\n * Used when state is managed internally\r\n */\r\nexport type UncontrolledTableState = {\r\n initialState?: Partial<TableState>;\r\n onStateChange?: (state: TableState) => void;\r\n};\r\n\r\n/**\r\n * Check if state is controlled\r\n */\r\nexport function isControlledState(\r\n handler: TableStateHandler | UncontrolledTableState\r\n): handler is TableStateHandler {\r\n return 'state' in handler && 'setState' in handler;\r\n}\r\n","/**\r\n * Sorting functionality\r\n * \r\n * Single-column sorting implementation, extensible to multi-column sorting.\r\n */\r\n\r\n/**\r\n * Sort direction type\r\n */\r\nexport type SortDirection = 'asc' | 'desc' | null;\r\n\r\n/**\r\n * Sort state for single-column sorting\r\n * \r\n * TODO: Extend to multi-column sorting:\r\n * - Change to: sorting: Array<{ columnId: string; direction: 'asc' | 'desc' }>\r\n * - Add priority/order for multi-sort\r\n */\r\nexport interface SortState {\r\n /** Column ID to sort by, null if no sorting */\r\n columnId: string | null;\r\n \r\n /** Sort direction, null if no sorting */\r\n direction: SortDirection;\r\n}\r\n\r\n/**\r\n * Create initial sort state\r\n */\r\nexport function createInitialSortState(): SortState {\r\n return {\r\n columnId: null,\r\n direction: null,\r\n };\r\n}\r\n\r\n/**\r\n * Toggle sort state for a column\r\n * Cycles through: none -> asc -> desc -> none\r\n */\r\nexport function toggleSort(\r\n currentState: SortState,\r\n columnId: string\r\n): SortState {\r\n if (currentState.columnId === columnId) {\r\n // Same column - cycle direction\r\n if (currentState.direction === 'asc') {\r\n return { columnId, direction: 'desc' };\r\n }\r\n if (currentState.direction === 'desc') {\r\n return { columnId: null, direction: null };\r\n }\r\n }\r\n \r\n // New column or no current sort - start with ascending\r\n return { columnId, direction: 'asc' };\r\n}\r\n\r\n/**\r\n * Set sort state explicitly\r\n */\r\nexport function setSort(\r\n columnId: string | null,\r\n direction: SortDirection\r\n): SortState {\r\n return {\r\n columnId,\r\n direction,\r\n };\r\n}\r\n\r\n/**\r\n * Clear sort state\r\n */\r\nexport function clearSort(): SortState {\r\n return createInitialSortState();\r\n}\r\n\r\n/**\r\n * Type guard to check if sorting is active\r\n */\r\nexport function isSortActive(state: SortState): boolean {\r\n return state.columnId !== null && state.direction !== null;\r\n}\r\n\r\n/**\r\n * Value comparator function type\r\n */\r\nexport type CompareFn<T = unknown> = (a: T, b: T) => number;\r\n\r\n/**\r\n * Default comparator for primitive values\r\n */\r\nexport function defaultCompare(a: unknown, b: unknown): number {\r\n if (a === b) return 0;\r\n if (a === null || a === undefined) return 1;\r\n if (b === null || b === undefined) return -1;\r\n \r\n if (typeof a === 'number' && typeof b === 'number') {\r\n return a - b;\r\n }\r\n \r\n if (typeof a === 'string' && typeof b === 'string') {\r\n return a.localeCompare(b);\r\n }\r\n \r\n if (a instanceof Date && b instanceof Date) {\r\n return a.getTime() - b.getTime();\r\n }\r\n \r\n // Fallback to string comparison\r\n return String(a).localeCompare(String(b));\r\n}\r\n\r\n/**\r\n * Create a sorted comparator function\r\n */\r\nexport function createComparator<T>(\r\n direction: 'asc' | 'desc',\r\n compareFn: CompareFn<T> = defaultCompare as CompareFn<T>\r\n): CompareFn<T> {\r\n return (a: T, b: T) => {\r\n const result = compareFn(a, b);\r\n return direction === 'asc' ? result : -result;\r\n };\r\n}\r\n\r\n/**\r\n * Sort data array based on sort state\r\n * \r\n * @param data - Array of data items\r\n * @param sortState - Current sort state\r\n * @param getValue - Function to extract value from data item for the sorted column\r\n * @param compareFn - Optional custom comparator function\r\n * @returns New sorted array (immutable)\r\n */\r\nexport function applySort<T>(\r\n data: T[],\r\n sortState: SortState,\r\n getValue: (item: T, columnId: string) => unknown,\r\n compareFn?: CompareFn<unknown>\r\n): T[] {\r\n if (!isSortActive(sortState) || !sortState.columnId) {\r\n return [...data];\r\n }\r\n \r\n const comparator = createComparator(\r\n sortState.direction!,\r\n compareFn || defaultCompare\r\n );\r\n \r\n return [...data].sort((a, b) => {\r\n const valueA = getValue(a, sortState.columnId!);\r\n const valueB = getValue(b, sortState.columnId!);\r\n return comparator(valueA, valueB);\r\n });\r\n}\r\n","/**\r\n * Pagination functionality\r\n * \r\n * Client-side pagination implementation.\r\n */\r\n\r\n/**\r\n * Pagination state\r\n */\r\nexport interface PaginationState {\r\n /** Current page index (0-based) */\r\n pageIndex: number;\r\n \r\n /** Number of items per page */\r\n pageSize: number;\r\n \r\n // TODO: Add server-side pagination support\r\n // totalCount?: number; // For server-side mode\r\n // pageCount?: number; // For server-side mode\r\n}\r\n\r\n/**\r\n * Create initial pagination state\r\n */\r\nexport function createInitialPaginationState(\r\n pageSize: number = 10\r\n): PaginationState {\r\n return {\r\n pageIndex: 0,\r\n pageSize,\r\n };\r\n}\r\n\r\n/**\r\n * Calculate total number of pages\r\n */\r\nexport function getPageCount(\r\n totalItems: number,\r\n pageSize: number\r\n): number {\r\n if (pageSize <= 0) return 0;\r\n return Math.ceil(totalItems / pageSize);\r\n}\r\n\r\n/**\r\n * Get the start index of the current page\r\n */\r\nexport function getPageStartIndex(\r\n pageIndex: number,\r\n pageSize: number\r\n): number {\r\n return pageIndex * pageSize;\r\n}\r\n\r\n/**\r\n * Get the end index of the current page (exclusive)\r\n */\r\nexport function getPageEndIndex(\r\n pageIndex: number,\r\n pageSize: number,\r\n totalItems: number\r\n): number {\r\n return Math.min(getPageStartIndex(pageIndex, pageSize) + pageSize, totalItems);\r\n}\r\n\r\n/**\r\n * Check if page index is valid\r\n */\r\nexport function isValidPageIndex(\r\n pageIndex: number,\r\n totalPages: number\r\n): boolean {\r\n return pageIndex >= 0 && pageIndex < totalPages;\r\n}\r\n\r\n/**\r\n * Clamp page index to valid range\r\n */\r\nexport function clampPageIndex(\r\n pageIndex: number,\r\n totalPages: number\r\n): number {\r\n if (totalPages === 0) return 0;\r\n return Math.max(0, Math.min(pageIndex, totalPages - 1));\r\n}\r\n\r\n/**\r\n * Go to next page\r\n */\r\nexport function goToNextPage(\r\n state: PaginationState,\r\n totalPages: number\r\n): PaginationState {\r\n const nextIndex = clampPageIndex(state.pageIndex + 1, totalPages);\r\n return {\r\n ...state,\r\n pageIndex: nextIndex,\r\n };\r\n}\r\n\r\n/**\r\n * Go to previous page\r\n */\r\nexport function goToPreviousPage(\r\n state: PaginationState,\r\n totalPages: number\r\n): PaginationState {\r\n const prevIndex = clampPageIndex(state.pageIndex - 1, totalPages);\r\n return {\r\n ...state,\r\n pageIndex: prevIndex,\r\n };\r\n}\r\n\r\n/**\r\n * Go to specific page\r\n */\r\nexport function goToPage(\r\n state: PaginationState,\r\n pageIndex: number,\r\n totalPages: number\r\n): PaginationState {\r\n return {\r\n ...state,\r\n pageIndex: clampPageIndex(pageIndex, totalPages),\r\n };\r\n}\r\n\r\n/**\r\n * Change page size\r\n */\r\nexport function setPageSize(\r\n state: PaginationState,\r\n pageSize: number,\r\n totalItems: number\r\n): PaginationState {\r\n const totalPages = getPageCount(totalItems, pageSize);\r\n const clampedPageIndex = clampPageIndex(state.pageIndex, totalPages);\r\n \r\n return {\r\n pageIndex: clampedPageIndex,\r\n pageSize,\r\n };\r\n}\r\n\r\n/**\r\n * Get paginated slice of data\r\n * \r\n * @param data - Full data array\r\n * @param pagination - Pagination state\r\n * @returns Paginated data slice\r\n */\r\nexport function getPaginatedData<T>(\r\n data: T[],\r\n pagination: PaginationState\r\n): T[] {\r\n const start = getPageStartIndex(pagination.pageIndex, pagination.pageSize);\r\n const end = getPageEndIndex(\r\n pagination.pageIndex,\r\n pagination.pageSize,\r\n data.length\r\n );\r\n \r\n return data.slice(start, end);\r\n}\r\n\r\n/**\r\n * Check if there is a next page\r\n */\r\nexport function hasNextPage(\r\n pageIndex: number,\r\n totalPages: number\r\n): boolean {\r\n return pageIndex < totalPages - 1;\r\n}\r\n\r\n/**\r\n * Check if there is a previous page\r\n */\r\nexport function hasPreviousPage(pageIndex: number): boolean {\r\n return pageIndex > 0;\r\n}\r\n","/**\r\n * Filtering functionality\r\n * \r\n * Basic text filtering implementation, extensible to advanced filtering.\r\n */\r\n\r\n/**\r\n * Filter state\r\n * \r\n * TODO: Extend to support:\r\n * - Advanced filter types (number range, date range, etc.)\r\n * - Filter operators (equals, contains, greater than, etc.)\r\n * - Column-specific filter configurations\r\n */\r\nexport interface FilterState {\r\n /** Global text filter applied across all columns */\r\n globalFilter: string;\r\n \r\n /** Column-specific filters - maps column ID to filter value */\r\n columnFilters: Record<string, string>;\r\n \r\n // TODO: Add filter operators\r\n // filterOperators?: Record<string, FilterOperator>;\r\n \r\n // TODO: Add filter mode (AND/OR)\r\n // filterMode?: 'and' | 'or';\r\n}\r\n\r\n/**\r\n * Create initial filter state\r\n */\r\nexport function createInitialFilterState(): FilterState {\r\n return {\r\n globalFilter: '',\r\n columnFilters: {},\r\n };\r\n}\r\n\r\n/**\r\n * Set global filter\r\n */\r\nexport function setGlobalFilter(filter: string): FilterState {\r\n return {\r\n globalFilter: filter,\r\n columnFilters: {},\r\n };\r\n}\r\n\r\n/**\r\n * Set column filter\r\n */\r\nexport function setColumnFilter(\r\n state: FilterState,\r\n columnId: string,\r\n filter: string\r\n): FilterState {\r\n return {\r\n ...state,\r\n columnFilters: {\r\n ...state.columnFilters,\r\n [columnId]: filter,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Clear column filter\r\n */\r\nexport function clearColumnFilter(\r\n state: FilterState,\r\n columnId: string\r\n): FilterState {\r\n const { [columnId]: _, ...restFilters } = state.columnFilters;\r\n return {\r\n ...state,\r\n columnFilters: restFilters,\r\n };\r\n}\r\n\r\n/**\r\n * Clear all filters\r\n */\r\nexport function clearAllFilters(): FilterState {\r\n return createInitialFilterState();\r\n}\r\n\r\n/**\r\n * Check if any filter is active\r\n */\r\nexport function isFilterActive(state: FilterState): boolean {\r\n return (\r\n state.globalFilter.trim() !== '' ||\r\n Object.values(state.columnFilters).some((filter) => filter.trim() !== '')\r\n );\r\n}\r\n\r\n/**\r\n * Value matcher function type\r\n */\r\nexport type MatchFn = (value: unknown, filter: string) => boolean;\r\n\r\n/**\r\n * Default text matcher - case-insensitive substring match\r\n */\r\nexport function defaultMatch(value: unknown, filter: string): boolean {\r\n if (!filter.trim()) return true;\r\n \r\n const normalizedFilter = filter.toLowerCase().trim();\r\n const normalizedValue = String(value ?? '').toLowerCase();\r\n \r\n return normalizedValue.includes(normalizedFilter);\r\n}\r\n\r\n/**\r\n * Apply filters to data array\r\n * \r\n * @param data - Array of data items\r\n * @param filterState - Current filter state\r\n * @param getValue - Function to extract value from data item for a column\r\n * @param matchFn - Optional custom matcher function\r\n * @returns Filtered data array (immutable)\r\n */\r\nexport function applyFilters<T>(\r\n data: T[],\r\n filterState: FilterState,\r\n getValue: (item: T, columnId: string) => unknown,\r\n matchFn: MatchFn = defaultMatch\r\n): T[] {\r\n if (!isFilterActive(filterState)) {\r\n return [...data];\r\n }\r\n \r\n return data.filter((item) => {\r\n // Apply global filter - checks all columns\r\n if (filterState.globalFilter.trim()) {\r\n const matchesGlobal = Object.keys(filterState.columnFilters).length === 0\r\n ? // If no column filters, check all columns for global filter\r\n Object.values(item as Record<string, unknown>).some((value) =>\r\n matchFn(value, filterState.globalFilter)\r\n )\r\n : // If column filters exist, global filter is ignored (TODO: make configurable)\r\n true;\r\n \r\n if (!matchesGlobal) return false;\r\n }\r\n \r\n // Apply column-specific filters\r\n for (const [columnId, filterValue] of Object.entries(filterState.columnFilters)) {\r\n if (filterValue.trim()) {\r\n const value = getValue(item, columnId);\r\n if (!matchFn(value, filterValue)) {\r\n return false;\r\n }\r\n }\r\n }\r\n \r\n return true;\r\n });\r\n}\r\n\r\n/**\r\n * Get active filter count\r\n */\r\nexport function getActiveFilterCount(state: FilterState): number {\r\n let count = 0;\r\n \r\n if (state.globalFilter.trim()) {\r\n count++;\r\n }\r\n \r\n count += Object.values(state.columnFilters).filter((f) => f.trim() !== '').length;\r\n \r\n return count;\r\n}\r\n","/**\r\n * Column definitions and utilities\r\n *\r\n * Type-safe column definition API with extensibility for:\r\n * - Custom JSX renderers (via renderCell, renderHeader)\r\n * - Grouped headers (via parentId)\r\n * - Metadata extension (via meta)\r\n */\r\n\r\n/**\r\n * Filter type configuration\r\n *\r\n * TODO: Extend to support more filter types:\r\n * - 'number' | 'date' | 'select' | 'range'\r\n */\r\nexport type FilterType = \"text\" | \"none\";\r\n\r\n/**\r\n * Column accessor function type\r\n * Extracts a value from a data item\r\n */\r\nexport type AccessorFn<TData, TValue> = (data: TData) => TValue;\r\n\r\n/**\r\n * Column accessor - either a key path or a function\r\n */\r\nexport type ColumnAccessor<TData, TValue> =\r\n | keyof TData\r\n | AccessorFn<TData, TValue>;\r\n\r\n/**\r\n * Base column definition\r\n *\r\n * This is the serializable part of the column definition.\r\n * Renderers and other runtime functions are kept separate for serialization.\r\n *\r\n * TODO: Add support for:\r\n * - renderCell: (value: TValue, row: TData) => React.ReactNode\r\n * - renderHeader: () => React.ReactNode\r\n * - parentId?: string (for grouped headers)\r\n * - meta?: Record<string, unknown> (for extensible metadata)\r\n */\r\nexport interface ColumnDef<TData, TValue = unknown> {\r\n /** Unique column identifier - must be stable */\r\n id: string;\r\n\r\n /** Column header label */\r\n header?: string;\r\n\r\n /** Whether column is sortable */\r\n sortable?: boolean;\r\n\r\n /** Filter type for this column */\r\n filter?: FilterType;\r\n\r\n /** Column width in pixels */\r\n width?: number;\r\n\r\n /** Minimum column width */\r\n minWidth?: number;\r\n\r\n /** Maximum column width */\r\n maxWidth?: number;\r\n\r\n /** Whether column is visible by default */\r\n visible?: boolean;\r\n\r\n /** Column alignment */\r\n align?: \"left\" | \"center\" | \"right\";\r\n\r\n /** Accessor function or key path to extract value */\r\n accessor?: ColumnAccessor<TData, TValue>;\r\n\r\n /** Custom metadata for extensibility */\r\n meta?: Record<string, unknown>;\r\n\r\n // TODO: Add grouped header support\r\n // parentId?: string;\r\n\r\n // TODO: Add custom renderers (will be separate from serializable definition)\r\n // renderCell?: (value: TValue, row: TData) => React.ReactNode;\r\n // renderHeader?: () => React.ReactNode;\r\n}\r\n\r\n/**\r\n * Runtime column representation\r\n * Includes the definition plus computed properties\r\n */\r\nexport interface Column<TData> {\r\n /** Column definition */\r\n def: ColumnDef<TData>;\r\n\r\n /** Column ID (stable identifier) */\r\n id: string;\r\n\r\n /** Column header label */\r\n header: string;\r\n\r\n /** Whether column is sortable */\r\n sortable: boolean;\r\n\r\n /** Filter type */\r\n filter: FilterType;\r\n\r\n /** Column width */\r\n width?: number;\r\n\r\n /** Column alignment */\r\n align: \"left\" | \"center\" | \"right\";\r\n\r\n /** Accessor function to extract value from data */\r\n accessor: AccessorFn<TData, unknown>;\r\n}\r\n\r\n/**\r\n * Column definition builder options\r\n */\r\nexport interface ColumnOptions<TData, TValue> {\r\n header?: string;\r\n sortable?: boolean;\r\n filter?: FilterType;\r\n width?: number;\r\n minWidth?: number;\r\n maxWidth?: number;\r\n visible?: boolean;\r\n align?: \"left\" | \"center\" | \"right\";\r\n accessor?: ColumnAccessor<TData, TValue>;\r\n meta?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Create a column definition from a key\r\n *\r\n * @param key - Column key (must exist on TData)\r\n * @param options - Column configuration options\r\n * @returns Column definition\r\n */\r\nexport function col<TData, TKey extends keyof TData>(\r\n key: TKey,\r\n options?: ColumnOptions<TData, TData[TKey]>\r\n): ColumnDef<TData, TData[TKey]> {\r\n return {\r\n id: String(key),\r\n header: options?.header ?? String(key),\r\n sortable: options?.sortable ?? false,\r\n filter: options?.filter ?? \"none\",\r\n width: options?.width,\r\n minWidth: options?.minWidth,\r\n maxWidth: options?.maxWidth,\r\n visible: options?.visible ?? true,\r\n align: options?.align ?? \"left\",\r\n accessor: options?.accessor ?? key,\r\n meta: options?.meta,\r\n };\r\n}\r\n\r\n/**\r\n * Create a column definition with a custom accessor\r\n *\r\n * @param id - Unique column identifier\r\n * @param options - Column configuration options (must include accessor)\r\n * @returns Column definition\r\n */\r\nexport function colWithAccessor<TData, TValue>(\r\n id: string,\r\n options: ColumnOptions<TData, TValue> & {\r\n accessor: ColumnAccessor<TData, TValue>;\r\n }\r\n): ColumnDef<TData, TValue> {\r\n return {\r\n id,\r\n header: options.header ?? id,\r\n sortable: options.sortable ?? false,\r\n filter: options.filter ?? \"none\",\r\n width: options.width,\r\n minWidth: options.minWidth,\r\n maxWidth: options.maxWidth,\r\n visible: options.visible ?? true,\r\n align: options.align ?? \"left\",\r\n accessor: options.accessor,\r\n meta: options.meta,\r\n };\r\n}\r\n\r\n/**\r\n * Type-safe column definition array builder\r\n *\r\n * Provides type inference and validation for column definitions.\r\n *\r\n * @example\r\n * ```ts\r\n * const columns = defineColumns<User>()([\r\n * col(\"name\", { header: \"Name\", sortable: true }),\r\n * col(\"email\", { header: \"Email\", filter: \"text\" }),\r\n * ]);\r\n * ```\r\n */\r\nexport function defineColumns<TData>() {\r\n return <TColumns extends readonly ColumnDef<TData>[]>(\r\n columns: TColumns\r\n ): TColumns => columns;\r\n}\r\n\r\n/**\r\n * Normalize column accessor to a function\r\n */\r\nexport function normalizeAccessor<TData, TValue>(\r\n accessor: ColumnAccessor<TData, TValue>\r\n): AccessorFn<TData, TValue> {\r\n if (typeof accessor === \"function\") {\r\n return accessor as AccessorFn<TData, TValue>;\r\n }\r\n\r\n // Key path accessor\r\n return (data: TData) => {\r\n return (data as Record<string, unknown>)[String(accessor)] as TValue;\r\n };\r\n}\r\n\r\n/**\r\n * Convert column definition to runtime column\r\n */\r\nexport function createColumn<TData>(def: ColumnDef<TData>): Column<TData> {\r\n const accessor = def.accessor\r\n ? normalizeAccessor(def.accessor)\r\n : () => undefined;\r\n\r\n return {\r\n def,\r\n id: def.id,\r\n header: def.header ?? def.id,\r\n sortable: def.sortable ?? false,\r\n filter: def.filter ?? \"none\",\r\n width: def.width,\r\n align: def.align ?? \"left\",\r\n accessor,\r\n };\r\n}\r\n\r\n/**\r\n * Convert array of column definitions to runtime columns\r\n */\r\nexport function createColumns<TData>(\r\n definitions: readonly ColumnDef<TData>[]\r\n): Column<TData>[] {\r\n return definitions.map(createColumn);\r\n}\r\n\r\n/**\r\n * Get column by ID\r\n */\r\nexport function getColumnById<TData>(\r\n columns: Column<TData>[],\r\n id: string\r\n): Column<TData> | undefined {\r\n return columns.find((col) => col.id === id);\r\n}\r\n\r\n/**\r\n * Get visible columns\r\n */\r\nexport function getVisibleColumns<TData>(\r\n columns: Column<TData>[],\r\n visibility: Record<string, boolean>\r\n): Column<TData>[] {\r\n return columns.filter((col) => visibility[col.id] !== false);\r\n}\r\n\r\n/**\r\n * Get columns in specified order\r\n */\r\nexport function getOrderedColumns<TData>(\r\n columns: Column<TData>[],\r\n order: string[]\r\n): Column<TData>[] {\r\n const columnMap = new Map(columns.map((col) => [col.id, col]));\r\n const ordered: Column<TData>[] = [];\r\n\r\n // Add columns in specified order\r\n for (const id of order) {\r\n const col = columnMap.get(id);\r\n if (col) {\r\n ordered.push(col);\r\n columnMap.delete(id);\r\n }\r\n }\r\n\r\n // Add any remaining columns not in order\r\n ordered.push(...columnMap.values());\r\n\r\n return ordered;\r\n}\r\n\r\n/**\r\n * Extract column IDs from definitions\r\n */\r\nexport function getColumnIds<TData>(\r\n definitions: readonly ColumnDef<TData>[]\r\n): string[] {\r\n return definitions.map((def) => def.id);\r\n}\r\n\r\n/**\r\n * Validate column definitions\r\n * Ensures all columns have unique IDs\r\n */\r\nexport function validateColumns<TData>(\r\n definitions: readonly ColumnDef<TData>[]\r\n): { valid: boolean; errors: string[] } {\r\n const errors: string[] = [];\r\n const ids = new Set<string>();\r\n\r\n for (const def of definitions) {\r\n if (!def.id || def.id.trim() === \"\") {\r\n errors.push(`Column definition missing required 'id' field`);\r\n continue;\r\n }\r\n\r\n if (ids.has(def.id)) {\r\n errors.push(`Duplicate column ID: ${def.id}`);\r\n }\r\n\r\n ids.add(def.id);\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n };\r\n}\r\n"]}
|
package/dist/react.d.mts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { ColumnDef, TableStateHandler, UncontrolledTableState, TableState, Column } from './core.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* React hook for data table functionality
|
|
5
|
+
*
|
|
6
|
+
* Bridges core table logic to React components.
|
|
7
|
+
* Supports both controlled and uncontrolled state patterns.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Hook configuration options
|
|
12
|
+
*/
|
|
13
|
+
interface UseDataTableOptions<TData> {
|
|
14
|
+
/** Data array to display */
|
|
15
|
+
data: TData[];
|
|
16
|
+
/** Column definitions */
|
|
17
|
+
columns: readonly ColumnDef<TData>[];
|
|
18
|
+
/** Initial page size (default: 10) */
|
|
19
|
+
pageSize?: number;
|
|
20
|
+
/** Controlled or uncontrolled state configuration */
|
|
21
|
+
state?: TableStateHandler | UncontrolledTableState;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Table instance API returned by useDataTable
|
|
25
|
+
*/
|
|
26
|
+
interface TableInstance<TData> {
|
|
27
|
+
/** Current table state */
|
|
28
|
+
state: TableState;
|
|
29
|
+
/** Runtime columns (with normalized accessors) */
|
|
30
|
+
columns: Column<TData>[];
|
|
31
|
+
/** Visible columns in current order */
|
|
32
|
+
visibleColumns: Column<TData>[];
|
|
33
|
+
/** Original data array */
|
|
34
|
+
data: TData[];
|
|
35
|
+
/** Filtered data (after applying filters) */
|
|
36
|
+
filteredData: TData[];
|
|
37
|
+
/** Sorted data (after applying sorting) */
|
|
38
|
+
sortedData: TData[];
|
|
39
|
+
/** Paginated data (final data to display) */
|
|
40
|
+
paginatedData: TData[];
|
|
41
|
+
/** Total number of items after filtering */
|
|
42
|
+
filteredRowCount: number;
|
|
43
|
+
/** Total number of pages */
|
|
44
|
+
pageCount: number;
|
|
45
|
+
/** Current page index */
|
|
46
|
+
pageIndex: number;
|
|
47
|
+
/** Current page size */
|
|
48
|
+
pageSize: number;
|
|
49
|
+
/** Whether there is a next page */
|
|
50
|
+
hasNextPage: boolean;
|
|
51
|
+
/** Whether there is a previous page */
|
|
52
|
+
hasPreviousPage: boolean;
|
|
53
|
+
/** Sorting handlers */
|
|
54
|
+
sorting: {
|
|
55
|
+
/** Current sort state */
|
|
56
|
+
state: TableState["sorting"];
|
|
57
|
+
/** Toggle sort for a column */
|
|
58
|
+
toggle: (columnId: string) => void;
|
|
59
|
+
/** Set sort explicitly */
|
|
60
|
+
set: (columnId: string | null, direction: "asc" | "desc" | null) => void;
|
|
61
|
+
/** Clear sort */
|
|
62
|
+
clear: () => void;
|
|
63
|
+
};
|
|
64
|
+
/** Pagination handlers */
|
|
65
|
+
pagination: {
|
|
66
|
+
/** Current pagination state */
|
|
67
|
+
state: TableState["pagination"];
|
|
68
|
+
/** Go to next page */
|
|
69
|
+
nextPage: () => void;
|
|
70
|
+
/** Go to previous page */
|
|
71
|
+
previousPage: () => void;
|
|
72
|
+
/** Go to specific page */
|
|
73
|
+
goToPage: (pageIndex: number) => void;
|
|
74
|
+
/** Set page size */
|
|
75
|
+
setPageSize: (pageSize: number) => void;
|
|
76
|
+
};
|
|
77
|
+
/** Filtering handlers */
|
|
78
|
+
filtering: {
|
|
79
|
+
/** Current filter state */
|
|
80
|
+
state: TableState["filtering"];
|
|
81
|
+
/** Set global filter */
|
|
82
|
+
setGlobalFilter: (filter: string) => void;
|
|
83
|
+
/** Set column filter */
|
|
84
|
+
setColumnFilter: (columnId: string, filter: string) => void;
|
|
85
|
+
/** Clear column filter */
|
|
86
|
+
clearColumnFilter: (columnId: string) => void;
|
|
87
|
+
/** Clear all filters */
|
|
88
|
+
clearAllFilters: () => void;
|
|
89
|
+
};
|
|
90
|
+
/** Column management handlers */
|
|
91
|
+
columnManagement: {
|
|
92
|
+
/** Toggle column visibility */
|
|
93
|
+
toggleVisibility: (columnId: string) => void;
|
|
94
|
+
/** Set column visibility */
|
|
95
|
+
setVisibility: (columnId: string, visible: boolean) => void;
|
|
96
|
+
/** Reorder columns */
|
|
97
|
+
reorder: (columnOrder: string[]) => void;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* useDataTable hook
|
|
102
|
+
*
|
|
103
|
+
* Provides a complete table instance with state management,
|
|
104
|
+
* data transformations, and event handlers.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```tsx
|
|
108
|
+
* const table = useDataTable({
|
|
109
|
+
* data: users,
|
|
110
|
+
* columns: userColumns,
|
|
111
|
+
* pageSize: 10,
|
|
112
|
+
* });
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
declare function useDataTable<TData>(options: UseDataTableOptions<TData>): TableInstance<TData>;
|
|
116
|
+
|
|
117
|
+
export { type TableInstance, type UseDataTableOptions, useDataTable };
|