@ackplus/react-tanstack-data-table 1.0.21 → 1.0.23

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 CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  A powerful, feature-rich, and highly customizable React data table component built with Material-UI (MUI) and TanStack Table. Perfect for building modern data-intensive applications with advanced table functionality.
4
4
 
5
+ ## 🚀 Live Demo
6
+
7
+ **[View Live Demo](https://ack-solutions.github.io/react-tanstack-data-table/)**
8
+
9
+ Experience all the features in action with our interactive demo showcasing advanced table functionality, filtering, sorting, pagination, and more.
10
+
5
11
  ## ✨ Features
6
12
 
7
13
  - 🚀 **High Performance**: Built on TanStack Table for excellent performance with large datasets
@@ -18,6 +24,7 @@ A powerful, feature-rich, and highly customizable React data table component bui
18
24
  - 🎛️ **Highly Customizable**: Extensive customization through slots and props
19
25
  - 📝 **TypeScript**: Full TypeScript support with comprehensive type definitions
20
26
  - 🔌 **Extensible**: Plugin architecture with custom components and hooks
27
+ - 🛠️ **Debug Logging**: Configurable console instrumentation with global or per-table controls
21
28
 
22
29
  ## 📦 Installation
23
30
 
@@ -1359,6 +1366,34 @@ const handleClick = useCallback(() => {
1359
1366
  />
1360
1367
  ```
1361
1368
 
1369
+ ### Logging & Debugging
1370
+
1371
+ Use the built-in logger to trace pagination, server calls, and state transitions without sprinkling `console.log` statements throughout your app.
1372
+
1373
+ ```tsx
1374
+ import { DataTable, configureDataTableLogging } from '@ackplus/react-tanstack-data-table';
1375
+
1376
+ configureDataTableLogging({
1377
+ enabled: true,
1378
+ level: 'debug',
1379
+ includeTimestamp: true,
1380
+ });
1381
+
1382
+ <DataTable
1383
+ columns={columns}
1384
+ data={rows}
1385
+ logging={{
1386
+ enabled: true,
1387
+ level: 'info',
1388
+ prefix: 'OrdersTable',
1389
+ }}
1390
+ />
1391
+ ```
1392
+
1393
+ - Call `configureDataTableLogging` once (for example in your app bootstrap) to set global defaults.
1394
+ - Use the `logging` prop to override settings per table or disable instrumentation for specific instances.
1395
+ - When `logging` is omitted, instances inherit the global configuration.
1396
+
1362
1397
  ### Troubleshooting
1363
1398
 
1364
1399
  #### Common Issues
@@ -1422,6 +1457,7 @@ MIT © [ACK Solutions](https://github.com/ack-solutions)
1422
1457
 
1423
1458
  ## 🆘 Support
1424
1459
 
1460
+ - 🚀 [Live Demo](https://ack-solutions.github.io/react-tanstack-data-table/) - Interactive examples and playground
1425
1461
  - 📖 [Documentation](https://github.com/ack-solutions/react-tanstack-data-table)
1426
1462
  - 🐛 [Issue Tracker](https://github.com/ack-solutions/react-tanstack-data-table/issues)
1427
1463
  - 💬 [Discussions](https://github.com/ack-solutions/react-tanstack-data-table/discussions)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ackplus/react-tanstack-data-table",
3
3
  "type": "commonjs",
4
- "version": "1.0.21",
4
+ "version": "1.0.23",
5
5
  "description": "A powerful React data table component built with MUI and TanStack Table",
6
6
  "keywords": [
7
7
  "react",
package/src/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export type { BulkActionsToolbarProps } from './lib/components/toolbar';
10
10
  export * from './lib/utils/styling-helpers';
11
11
  export * from './lib/utils/column-helpers';
12
12
  export * from './lib/utils/table-helpers';
13
+ export * from './lib/utils/logger';
13
14
  export * from './lib/hooks';
14
15
  export * from './lib/types';
15
16
  export type { Column, ColumnDef, Row, Table, Header, Cell, SortingState, ColumnFiltersState, VisibilityState, ColumnOrderState, ColumnPinningState, PaginationState, } from '@tanstack/react-table';
package/src/index.js CHANGED
@@ -20,6 +20,7 @@ Object.defineProperty(exports, "DataTableToolbar", { enumerable: true, get: func
20
20
  tslib_1.__exportStar(require("./lib/utils/styling-helpers"), exports);
21
21
  tslib_1.__exportStar(require("./lib/utils/column-helpers"), exports);
22
22
  tslib_1.__exportStar(require("./lib/utils/table-helpers"), exports);
23
+ tslib_1.__exportStar(require("./lib/utils/logger"), exports);
23
24
  tslib_1.__exportStar(require("./lib/hooks"), exports);
24
25
  tslib_1.__exportStar(require("./lib/types"), exports);
25
26
  tslib_1.__exportStar(require("./lib/features"), exports);
@@ -10,8 +10,6 @@ const slot_helpers_1 = require("../../utils/slot-helpers");
10
10
  exports.DataTablePagination = (0, react_1.memo)((props) => {
11
11
  const { footerFilter = null, pagination, totalRow, containerSx, paginationProps, footerSx, slots, slotProps } = props, otherProps = tslib_1.__rest(props, ["footerFilter", "pagination", "totalRow", "containerSx", "paginationProps", "footerSx", "slots", "slotProps"]);
12
12
  const { table } = (0, data_table_context_1.useDataTableContext)();
13
- const paginationSlotProps = (0, slot_helpers_1.extractSlotProps)(slotProps, 'pagination');
14
- const PaginationSlot = (0, slot_helpers_1.getSlotComponent)(slots, 'pagination', material_1.TablePagination);
15
13
  const mergedContainerProps = (0, slot_helpers_1.mergeSlotProps)({
16
14
  sx: Object.assign({ display: 'flex', alignItems: 'center', gap: 1, justifyContent: 'space-between', px: 2 }, containerSx),
17
15
  });
@@ -32,6 +30,6 @@ exports.DataTablePagination = (0, react_1.memo)((props) => {
32
30
  showLastButton: true,
33
31
  labelRowsPerPage: 'Rows per page:',
34
32
  labelDisplayedRows: ({ from, to, count }) => `${from}–${to} of ${count !== -1 ? count : `more than ${to}`}`,
35
- }, paginationSlotProps, Object.assign(Object.assign({}, paginationProps), otherProps));
36
- return ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({}, mergedContainerProps, { children: [footerFilter && ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: footerSx, children: footerFilter })), (0, jsx_runtime_1.jsx)(PaginationSlot, Object.assign({}, mergedPaginationProps))] })));
33
+ }, Object.assign(Object.assign({}, paginationProps), otherProps));
34
+ return ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({}, mergedContainerProps, { children: [footerFilter && ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: footerSx, children: footerFilter })), (0, jsx_runtime_1.jsx)(material_1.TablePagination, Object.assign({}, mergedPaginationProps))] })));
37
35
  });
@@ -10,7 +10,6 @@ const features_1 = require("../../features");
10
10
  const react_virtual_1 = require("@tanstack/react-virtual");
11
11
  const react_1 = require("react");
12
12
  const data_table_context_1 = require("../../contexts/data-table-context");
13
- const use_data_table_api_1 = require("../../hooks/use-data-table-api");
14
13
  const utils_1 = require("../../utils");
15
14
  const debounced_fetch_utils_1 = require("../../utils/debounced-fetch.utils");
16
15
  const slot_helpers_1 = require("../../utils/slot-helpers");
@@ -40,12 +39,31 @@ const DEFAULT_INITIAL_STATE = {
40
39
  pendingLogic: 'AND',
41
40
  },
42
41
  };
43
- exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, columns, data = [], totalRow = 0, idKey = 'id', extraFilter = null, footerFilter = null, dataMode = 'client', initialLoadData = true, onFetchData, onDataStateChange, enableRowSelection = false, enableMultiRowSelection = true, selectMode = 'page', isRowSelectable, onSelectionChange, enableBulkActions = false, bulkActions, enableColumnResizing = false, columnResizeMode = 'onChange', enableColumnDragging = false, onColumnDragEnd, enableColumnPinning = false, onColumnPinningChange, enableExpanding = false, getRowCanExpand, renderSubComponent, enablePagination = true, paginationMode = 'client', enableGlobalFilter = true, enableColumnFilter = false, filterMode = 'client', enableSorting = true, sortingMode = 'client', onSortingChange, exportFilename = 'export', onExportProgress, onExportComplete, onExportError, onServerExport, onExportCancel, enableHover = true, enableStripes = false, tableContainerProps = {}, tableProps = {}, fitToScreen = true, tableSize: initialTableSize = 'medium', enableStickyHeaderOrFooter = false, maxHeight = '400px', enableVirtualization = false, estimateRowHeight = 52, enableColumnVisibility = true, enableTableSizeControl = true, enableExport = true, enableReset = true, loading = false, emptyMessage = 'No data available', skeletonRows = 5, onColumnFiltersChange, onPaginationChange, onGlobalFilterChange, slots = {}, slotProps = {}, }, ref) {
42
+ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, columns, data = [], totalRow = 0, idKey = 'id', extraFilter = null, footerFilter = null, dataMode = 'client', initialLoadData = true, onFetchData, onDataStateChange, enableRowSelection = false, enableMultiRowSelection = true, selectMode = 'page', isRowSelectable, onSelectionChange, enableBulkActions = false, bulkActions, enableColumnResizing = false, columnResizeMode = 'onChange', enableColumnDragging = false, onColumnDragEnd, enableColumnPinning = false, onColumnPinningChange, enableExpanding = false, getRowCanExpand, renderSubComponent, enablePagination = true, paginationMode = 'client', enableGlobalFilter = true, enableColumnFilter = false, filterMode = 'client', enableSorting = true, sortingMode = 'client', onSortingChange, exportFilename = 'export', onExportProgress, onExportComplete, onExportError, onServerExport, onExportCancel, enableHover = true, enableStripes = false, tableContainerProps = {}, tableProps = {}, fitToScreen = true, tableSize: initialTableSize = 'medium', enableStickyHeaderOrFooter = false, maxHeight = '400px', enableVirtualization = false, estimateRowHeight = 52, enableColumnVisibility = true, enableTableSizeControl = true, enableExport = true, enableReset = true, loading = false, emptyMessage = 'No data available', skeletonRows = 5, onColumnFiltersChange, onPaginationChange, onGlobalFilterChange, slots = {}, slotProps = {}, logging, }, ref) {
44
43
  var _a;
45
44
  const isServerMode = dataMode === 'server';
46
45
  const isServerPagination = paginationMode === 'server' || isServerMode;
47
46
  const isServerFiltering = filterMode === 'server' || isServerMode;
48
47
  const isServerSorting = sortingMode === 'server' || isServerMode;
48
+ const logger = (0, react_1.useMemo)(() => (0, utils_1.createLogger)('DataTable', logging), [logging]);
49
+ const fetchLogger = (0, react_1.useMemo)(() => logger.child('fetch'), [logger]);
50
+ const paginationLogger = (0, react_1.useMemo)(() => logger.child('pagination'), [logger]);
51
+ const stateLogger = (0, react_1.useMemo)(() => logger.child('state'), [logger]);
52
+ (0, react_1.useEffect)(() => {
53
+ if (logger.isLevelEnabled('info')) {
54
+ logger.info('mounted', {
55
+ dataMode,
56
+ paginationMode,
57
+ filterMode,
58
+ sortingMode,
59
+ });
60
+ }
61
+ return () => {
62
+ if (logger.isLevelEnabled('info')) {
63
+ logger.info('unmounted');
64
+ }
65
+ };
66
+ }, [logger, dataMode, paginationMode, filterMode, sortingMode]);
49
67
  const initialStateConfig = (0, react_1.useMemo)(() => {
50
68
  return Object.assign(Object.assign({}, DEFAULT_INITIAL_STATE), initialState);
51
69
  }, [initialState]);
@@ -124,16 +142,40 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
124
142
  minWidth: '100%',
125
143
  }), [tableWidth]);
126
144
  const fetchData = (0, react_1.useCallback)((...args_1) => tslib_1.__awaiter(this, [...args_1], void 0, function* (overrides = {}) {
127
- if (!onFetchData)
145
+ var _a, _b;
146
+ if (!onFetchData) {
147
+ if (fetchLogger.isLevelEnabled('debug')) {
148
+ fetchLogger.debug('onFetchData not provided, skipping fetch', { overrides });
149
+ }
128
150
  return;
151
+ }
129
152
  const filters = Object.assign({ globalFilter,
130
153
  pagination,
131
154
  columnFilter,
132
155
  sorting }, overrides);
133
- const result = yield debouncedFetch(filters);
134
- if ((result === null || result === void 0 ? void 0 : result.data) && (result === null || result === void 0 ? void 0 : result.total) !== undefined) {
135
- setServerData(result.data);
136
- setServerTotal(result.total);
156
+ if (fetchLogger.isLevelEnabled('debug')) {
157
+ fetchLogger.debug('Requesting data', { filters });
158
+ }
159
+ try {
160
+ const result = yield debouncedFetch(filters);
161
+ if (fetchLogger.isLevelEnabled('debug')) {
162
+ fetchLogger.debug('Fetch resolved', {
163
+ rows: (_b = (_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0,
164
+ total: result === null || result === void 0 ? void 0 : result.total,
165
+ });
166
+ }
167
+ if ((result === null || result === void 0 ? void 0 : result.data) && (result === null || result === void 0 ? void 0 : result.total) !== undefined) {
168
+ setServerData(result.data);
169
+ setServerTotal(result.total);
170
+ }
171
+ else if (fetchLogger.isLevelEnabled('warn')) {
172
+ fetchLogger.warn('Fetch handler returned unexpected shape', result);
173
+ }
174
+ return result;
175
+ }
176
+ catch (error) {
177
+ fetchLogger.error('Fetch failed', error);
178
+ throw error;
137
179
  }
138
180
  }), [
139
181
  onFetchData,
@@ -142,6 +184,7 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
142
184
  columnFilter,
143
185
  sorting,
144
186
  debouncedFetch,
187
+ fetchLogger,
145
188
  ]);
146
189
  const handleSelectionStateChange = (0, react_1.useCallback)((updaterOrValue) => {
147
190
  setSelectionState((prevState) => {
@@ -162,15 +205,22 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
162
205
  }
163
206
  }, [onColumnFiltersChange]);
164
207
  const tableStateChange = (0, react_1.useCallback)((overrides = {}) => {
165
- if (onDataStateChange) {
166
- const currentState = Object.assign({ globalFilter,
167
- columnFilter,
168
- sorting,
169
- pagination,
170
- columnOrder,
171
- columnPinning }, overrides);
172
- onDataStateChange(currentState);
208
+ if (!onDataStateChange) {
209
+ if (stateLogger.isLevelEnabled('debug')) {
210
+ stateLogger.debug('No onDataStateChange handler registered; skipping state update notification', { overrides });
211
+ }
212
+ return;
173
213
  }
214
+ const currentState = Object.assign({ globalFilter,
215
+ columnFilter,
216
+ sorting,
217
+ pagination,
218
+ columnOrder,
219
+ columnPinning }, overrides);
220
+ if (stateLogger.isLevelEnabled('debug')) {
221
+ stateLogger.debug('Emitting tableStateChange', currentState);
222
+ }
223
+ onDataStateChange(currentState);
174
224
  }, [
175
225
  onDataStateChange,
176
226
  globalFilter,
@@ -179,6 +229,7 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
179
229
  pagination,
180
230
  columnOrder,
181
231
  columnPinning,
232
+ stateLogger,
182
233
  ]);
183
234
  const handleSortingChange = (0, react_1.useCallback)((updaterOrValue) => {
184
235
  let newSorting = typeof updaterOrValue === 'function'
@@ -187,8 +238,18 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
187
238
  newSorting = newSorting.filter((sort) => sort.id);
188
239
  setSorting(newSorting);
189
240
  onSortingChange === null || onSortingChange === void 0 ? void 0 : onSortingChange(newSorting);
241
+ if (stateLogger.isLevelEnabled('debug')) {
242
+ stateLogger.debug('Sorting change applied', {
243
+ sorting: newSorting,
244
+ serverMode: isServerMode,
245
+ serverSorting: isServerSorting,
246
+ });
247
+ }
190
248
  if (isServerMode || isServerSorting) {
191
249
  const pagination = resetPageToFirst();
250
+ if (stateLogger.isLevelEnabled('debug')) {
251
+ stateLogger.debug('Sorting change triggered server fetch', { pagination, sorting: newSorting });
252
+ }
192
253
  tableStateChange({ sorting: newSorting, pagination });
193
254
  fetchData({
194
255
  sorting: newSorting,
@@ -198,6 +259,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
198
259
  else if (onDataStateChange) {
199
260
  const pagination = resetPageToFirst();
200
261
  setTimeout(() => {
262
+ if (stateLogger.isLevelEnabled('debug')) {
263
+ stateLogger.debug('Sorting change notified client state change', { pagination, sorting: newSorting });
264
+ }
201
265
  tableStateChange({ sorting: newSorting, pagination });
202
266
  }, 0);
203
267
  }
@@ -209,6 +273,7 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
209
273
  isServerSorting,
210
274
  onDataStateChange,
211
275
  tableStateChange,
276
+ stateLogger,
212
277
  ]);
213
278
  const handleColumnOrderChange = (0, react_1.useCallback)((updatedColumnOrder) => {
214
279
  const newColumnOrder = typeof updatedColumnOrder === 'function'
@@ -229,30 +294,67 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
229
294
  }
230
295
  }, [onColumnPinningChange, columnPinning]);
231
296
  const handlePaginationChange = (0, react_1.useCallback)((updater) => {
232
- setPagination(updater);
233
297
  const newPagination = typeof updater === 'function' ? updater(pagination) : updater;
298
+ if (paginationLogger.isLevelEnabled('debug')) {
299
+ paginationLogger.debug('Pagination change requested', {
300
+ previous: pagination,
301
+ next: newPagination,
302
+ serverSide: isServerMode || isServerPagination,
303
+ });
304
+ }
305
+ setPagination(newPagination);
306
+ onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(newPagination);
307
+ if (paginationLogger.isLevelEnabled('debug')) {
308
+ paginationLogger.debug('Pagination state updated', newPagination);
309
+ }
234
310
  if (isServerMode || isServerPagination) {
235
311
  setTimeout(() => {
312
+ if (paginationLogger.isLevelEnabled('debug')) {
313
+ paginationLogger.debug('Notifying server-side pagination change', newPagination);
314
+ }
236
315
  tableStateChange({ pagination: newPagination });
237
316
  fetchData({ pagination: newPagination });
238
317
  }, 0);
239
318
  }
240
319
  else if (onDataStateChange) {
241
320
  setTimeout(() => {
321
+ if (paginationLogger.isLevelEnabled('debug')) {
322
+ paginationLogger.debug('Notifying client-side pagination change', newPagination);
323
+ }
242
324
  tableStateChange({ pagination: newPagination });
243
325
  }, 0);
244
326
  }
245
- setPagination(newPagination);
246
- onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(newPagination);
247
- }, [pagination, isServerMode, isServerPagination, onDataStateChange, fetchData, tableStateChange]);
327
+ }, [
328
+ pagination,
329
+ isServerMode,
330
+ isServerPagination,
331
+ onDataStateChange,
332
+ fetchData,
333
+ tableStateChange,
334
+ paginationLogger,
335
+ onPaginationChange,
336
+ ]);
248
337
  const handleGlobalFilterChange = (0, react_1.useCallback)((updaterOrValue) => {
249
338
  const newFilter = typeof updaterOrValue === 'function'
250
339
  ? updaterOrValue(globalFilter)
251
340
  : updaterOrValue;
252
341
  setGlobalFilter(newFilter);
342
+ if (stateLogger.isLevelEnabled('debug')) {
343
+ stateLogger.debug('Global filter change applied', {
344
+ value: newFilter,
345
+ serverMode: isServerMode,
346
+ serverFiltering: isServerFiltering,
347
+ });
348
+ }
253
349
  if (isServerMode || isServerFiltering) {
254
350
  const pagination = resetPageToFirst();
255
351
  setTimeout(() => {
352
+ if (stateLogger.isLevelEnabled('debug')) {
353
+ stateLogger.debug('Global filter change triggering server fetch', {
354
+ pagination,
355
+ value: newFilter,
356
+ });
357
+ }
256
358
  tableStateChange({ globalFilter: newFilter, pagination });
257
359
  fetchData({ globalFilter: newFilter, pagination });
258
360
  }, 0);
@@ -260,11 +362,17 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
260
362
  else if (onDataStateChange) {
261
363
  const pagination = resetPageToFirst();
262
364
  setTimeout(() => {
365
+ if (stateLogger.isLevelEnabled('debug')) {
366
+ stateLogger.debug('Global filter change notifying client listeners', {
367
+ pagination,
368
+ value: newFilter,
369
+ });
370
+ }
263
371
  tableStateChange({ globalFilter: newFilter, pagination });
264
372
  }, 0);
265
373
  }
266
374
  onGlobalFilterChange === null || onGlobalFilterChange === void 0 ? void 0 : onGlobalFilterChange(newFilter);
267
- }, [globalFilter, isServerMode, isServerFiltering, onDataStateChange, fetchData, tableStateChange]);
375
+ }, [globalFilter, isServerMode, isServerFiltering, onDataStateChange, fetchData, tableStateChange, stateLogger]);
268
376
  const onColumnFilterChangeHandler = (0, react_1.useCallback)((updater) => {
269
377
  const currentState = columnFilter;
270
378
  const newState = typeof updater === 'function'
@@ -312,6 +420,12 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
312
420
  enabled: enableVirtualization && !enablePagination && rows.length > 0,
313
421
  });
314
422
  const resetPageToFirst = () => {
423
+ if (paginationLogger.isLevelEnabled('info')) {
424
+ paginationLogger.info('Resetting to first page due to state change', {
425
+ previousPageIndex: pagination.pageIndex,
426
+ pageSize: pagination.pageSize,
427
+ });
428
+ }
315
429
  const newPagination = { pageIndex: 0, pageSize: pagination.pageSize };
316
430
  setPagination(newPagination);
317
431
  onPaginationChange === null || onPaginationChange === void 0 ? void 0 : onPaginationChange(newPagination);
@@ -355,29 +469,6 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
355
469
  setColumnOrder(initialOrder);
356
470
  }
357
471
  }, [enableColumnDragging, enhancedColumns, columnOrder.length]);
358
- (0, use_data_table_api_1.useDataTableApi)({
359
- table,
360
- idKey,
361
- enhancedColumns,
362
- enablePagination,
363
- enableColumnPinning,
364
- initialStateConfig: Object.assign(Object.assign({}, DEFAULT_INITIAL_STATE), initialState),
365
- selectMode,
366
- onSelectionChange: handleSelectionStateChange,
367
- handleColumnFilterStateChange,
368
- onDataStateChange,
369
- onFetchData: fetchData,
370
- exportFilename,
371
- onExportProgress,
372
- onExportComplete,
373
- onExportError,
374
- onServerExport,
375
- exportController,
376
- setExportController,
377
- isExporting,
378
- onDataChange: setServerData,
379
- dataMode,
380
- }, internalApiRef);
381
472
  (0, react_1.useImperativeHandle)(ref, () => internalApiRef.current, []);
382
473
  (0, react_1.useImperativeHandle)(ref, () => ({
383
474
  table: {
@@ -505,6 +596,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
505
596
  pendingFilters: columnFilter.pendingFilters || [],
506
597
  pendingLogic: columnFilter.pendingLogic || 'AND',
507
598
  });
599
+ if (stateLogger.isLevelEnabled('debug')) {
600
+ stateLogger.debug(`Adding column filter ${columnId} ${operator} ${value}`, newFilters);
601
+ }
508
602
  },
509
603
  removeColumnFilter: (filterId) => {
510
604
  const columnFilter = table.getState().columnFilter;
@@ -516,6 +610,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
516
610
  pendingFilters: columnFilter.pendingFilters || [],
517
611
  pendingLogic: columnFilter.pendingLogic || 'AND',
518
612
  });
613
+ if (stateLogger.isLevelEnabled('debug')) {
614
+ stateLogger.debug(`Removing column filter ${filterId}`, newFilters);
615
+ }
519
616
  },
520
617
  clearAllFilters: () => {
521
618
  table.setGlobalFilter('');
@@ -534,11 +631,17 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
534
631
  pendingFilters: [],
535
632
  pendingLogic: 'AND',
536
633
  });
634
+ if (stateLogger.isLevelEnabled('debug')) {
635
+ stateLogger.debug('Resetting filters');
636
+ }
537
637
  },
538
638
  },
539
639
  sorting: {
540
640
  setSorting: (sortingState) => {
541
641
  table.setSorting(sortingState);
642
+ if (stateLogger.isLevelEnabled('debug')) {
643
+ stateLogger.debug(`Setting sorting`, sortingState);
644
+ }
542
645
  },
543
646
  sortColumn: (columnId, direction) => {
544
647
  const column = table.getColumn(columnId);
@@ -561,23 +664,41 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
561
664
  pagination: {
562
665
  goToPage: (pageIndex) => {
563
666
  table.setPageIndex(pageIndex);
667
+ if (paginationLogger.isLevelEnabled('debug')) {
668
+ paginationLogger.debug(`Going to page ${pageIndex}`);
669
+ }
564
670
  },
565
671
  nextPage: () => {
566
672
  table.nextPage();
673
+ if (paginationLogger.isLevelEnabled('debug')) {
674
+ paginationLogger.debug('Next page');
675
+ }
567
676
  },
568
677
  previousPage: () => {
569
678
  table.previousPage();
679
+ if (paginationLogger.isLevelEnabled('debug')) {
680
+ paginationLogger.debug('Previous page');
681
+ }
570
682
  },
571
683
  setPageSize: (pageSize) => {
572
684
  table.setPageSize(pageSize);
685
+ if (paginationLogger.isLevelEnabled('debug')) {
686
+ paginationLogger.debug(`Setting page size to ${pageSize}`);
687
+ }
573
688
  },
574
689
  goToFirstPage: () => {
575
690
  table.setPageIndex(0);
691
+ if (paginationLogger.isLevelEnabled('debug')) {
692
+ paginationLogger.debug('Going to first page');
693
+ }
576
694
  },
577
695
  goToLastPage: () => {
578
696
  const pageCount = table.getPageCount();
579
697
  if (pageCount > 0) {
580
698
  table.setPageIndex(pageCount - 1);
699
+ if (paginationLogger.isLevelEnabled('debug')) {
700
+ paginationLogger.debug(`Going to last page ${pageCount - 1}`);
701
+ }
581
702
  }
582
703
  },
583
704
  },
@@ -602,13 +723,20 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
602
723
  pageSize: ((_a = filters.pagination) === null || _a === void 0 ? void 0 : _a.pageSize) || ((_b = initialStateConfig.pagination) === null || _b === void 0 ? void 0 : _b.pageSize) || 10,
603
724
  };
604
725
  const allState = table.getState();
726
+ setPagination(pagination);
605
727
  onDataStateChange === null || onDataStateChange === void 0 ? void 0 : onDataStateChange(allState);
606
728
  fetchData === null || fetchData === void 0 ? void 0 : fetchData({ pagination });
729
+ if (fetchLogger.isLevelEnabled('debug')) {
730
+ fetchLogger.debug('Refreshing data', { pagination, allState });
731
+ }
607
732
  },
608
733
  reload: () => {
609
734
  const allState = table.getState();
610
735
  onDataStateChange === null || onDataStateChange === void 0 ? void 0 : onDataStateChange(allState);
611
736
  onFetchData === null || onFetchData === void 0 ? void 0 : onFetchData({});
737
+ if (fetchLogger.isLevelEnabled('debug')) {
738
+ fetchLogger.debug('Reloading data', allState);
739
+ }
612
740
  },
613
741
  getAllData: () => {
614
742
  var _a;
@@ -627,6 +755,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
627
755
  const newData = (_a = table.getRowModel().rows) === null || _a === void 0 ? void 0 : _a.map(row => String(row.original[idKey]) === rowId
628
756
  ? Object.assign(Object.assign({}, row.original), updates) : row.original);
629
757
  setServerData === null || setServerData === void 0 ? void 0 : setServerData(newData || []);
758
+ if (fetchLogger.isLevelEnabled('debug')) {
759
+ fetchLogger.debug(`Updating row ${rowId}`, updates);
760
+ }
630
761
  },
631
762
  updateRowByIndex: (index, updates) => {
632
763
  var _a;
@@ -634,6 +765,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
634
765
  if (newData === null || newData === void 0 ? void 0 : newData[index]) {
635
766
  newData[index] = Object.assign(Object.assign({}, newData[index]), updates);
636
767
  setServerData(newData);
768
+ if (fetchLogger.isLevelEnabled('debug')) {
769
+ fetchLogger.debug(`Updating row by index ${index}`, updates);
770
+ }
637
771
  }
638
772
  },
639
773
  insertRow: (newRow, index) => {
@@ -646,17 +780,26 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
646
780
  newData.push(newRow);
647
781
  }
648
782
  setServerData(newData || []);
783
+ if (fetchLogger.isLevelEnabled('debug')) {
784
+ fetchLogger.debug(`Inserting row`, newRow);
785
+ }
649
786
  },
650
787
  deleteRow: (rowId) => {
651
788
  var _a;
652
789
  const newData = (_a = (table.getRowModel().rows || [])) === null || _a === void 0 ? void 0 : _a.filter(row => String(row.original[idKey]) !== rowId);
653
790
  setServerData === null || setServerData === void 0 ? void 0 : setServerData((newData === null || newData === void 0 ? void 0 : newData.map(row => row.original)) || []);
791
+ if (fetchLogger.isLevelEnabled('debug')) {
792
+ fetchLogger.debug(`Deleting row ${rowId}`);
793
+ }
654
794
  },
655
795
  deleteRowByIndex: (index) => {
656
796
  var _a;
657
797
  const newData = (_a = (table.getRowModel().rows || [])) === null || _a === void 0 ? void 0 : _a.map(row => row.original);
658
798
  newData.splice(index, 1);
659
799
  setServerData(newData);
800
+ if (fetchLogger.isLevelEnabled('debug')) {
801
+ fetchLogger.debug(`Deleting row by index ${index}`);
802
+ }
660
803
  },
661
804
  deleteSelectedRows: () => {
662
805
  var _a;
@@ -665,6 +808,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
665
808
  const newData = (_a = (table.getRowModel().rows || [])) === null || _a === void 0 ? void 0 : _a.filter(row => !selectedRowIds.includes(String(row.original[idKey])));
666
809
  setServerData((newData === null || newData === void 0 ? void 0 : newData.map(row => row.original)) || []);
667
810
  table.resetRowSelection();
811
+ if (fetchLogger.isLevelEnabled('debug')) {
812
+ fetchLogger.debug('Deleting selected rows');
813
+ }
668
814
  },
669
815
  replaceAllData: (newData) => {
670
816
  setServerData === null || setServerData === void 0 ? void 0 : setServerData(newData);
@@ -821,6 +967,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
821
967
  sorting: table.getState().sorting,
822
968
  pagination: table.getState().pagination,
823
969
  };
970
+ if (stateLogger.isLevelEnabled('debug')) {
971
+ stateLogger.debug('Server export CSV', { currentFilters });
972
+ }
824
973
  yield (0, utils_1.exportServerData)(table, {
825
974
  format: 'csv',
826
975
  filename,
@@ -840,6 +989,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
840
989
  onComplete: onExportComplete,
841
990
  onError: onExportError,
842
991
  });
992
+ if (stateLogger.isLevelEnabled('debug')) {
993
+ stateLogger.debug('Client export CSV', filename);
994
+ }
843
995
  }
844
996
  }
845
997
  catch (error) {
@@ -865,6 +1017,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
865
1017
  sorting: table.getState().sorting,
866
1018
  pagination: table.getState().pagination,
867
1019
  };
1020
+ if (stateLogger.isLevelEnabled('debug')) {
1021
+ stateLogger.debug('Server export Excel', { currentFilters });
1022
+ }
868
1023
  yield (0, utils_1.exportServerData)(table, {
869
1024
  format: 'excel',
870
1025
  filename,
@@ -884,6 +1039,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
884
1039
  onComplete: onExportComplete,
885
1040
  onError: onExportError,
886
1041
  });
1042
+ if (stateLogger.isLevelEnabled('debug')) {
1043
+ stateLogger.debug('Client export Excel', filename);
1044
+ }
887
1045
  }
888
1046
  }
889
1047
  catch (error) {
@@ -891,6 +1049,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
891
1049
  message: error.message || 'Export failed',
892
1050
  code: 'EXPORT_ERROR',
893
1051
  });
1052
+ if (stateLogger.isLevelEnabled('debug')) {
1053
+ stateLogger.debug('Server export Excel failed', error);
1054
+ }
894
1055
  }
895
1056
  finally {
896
1057
  setExportController === null || setExportController === void 0 ? void 0 : setExportController(null);
@@ -904,6 +1065,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
904
1065
  message: 'No server export function provided',
905
1066
  code: 'NO_SERVER_EXPORT',
906
1067
  });
1068
+ if (stateLogger.isLevelEnabled('debug')) {
1069
+ stateLogger.debug('Server export data failed', 'No server export function provided');
1070
+ }
907
1071
  return;
908
1072
  }
909
1073
  try {
@@ -915,6 +1079,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
915
1079
  sorting: table.getState().sorting,
916
1080
  pagination: table.getState().pagination,
917
1081
  };
1082
+ if (stateLogger.isLevelEnabled('debug')) {
1083
+ stateLogger.debug('Server export data', { currentFilters });
1084
+ }
918
1085
  yield (0, utils_1.exportServerData)(table, {
919
1086
  format,
920
1087
  filename,
@@ -931,6 +1098,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
931
1098
  message: error.message || 'Export failed',
932
1099
  code: 'EXPORT_ERROR',
933
1100
  });
1101
+ if (stateLogger.isLevelEnabled('debug')) {
1102
+ stateLogger.debug('Server export data failed', error);
1103
+ }
934
1104
  }
935
1105
  finally {
936
1106
  setExportController === null || setExportController === void 0 ? void 0 : setExportController(null);
@@ -940,6 +1110,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
940
1110
  cancelExport: () => {
941
1111
  exportController === null || exportController === void 0 ? void 0 : exportController.abort();
942
1112
  setExportController === null || setExportController === void 0 ? void 0 : setExportController(null);
1113
+ if (stateLogger.isLevelEnabled('debug')) {
1114
+ stateLogger.debug('Export cancelled');
1115
+ }
943
1116
  },
944
1117
  },
945
1118
  }), [
@@ -1,17 +1,17 @@
1
- import { Row, SortingState, ColumnResizeMode, ColumnPinningState, RowData, PaginationState } from '@tanstack/react-table';
1
+ import { Row, SortingState, ColumnResizeMode, ColumnPinningState, RowData, PaginationState, ColumnDef } from '@tanstack/react-table';
2
2
  import { ReactNode } from 'react';
3
3
  import type { ColumnFilterState, TableFilters, TableState } from '../../types';
4
- import { DataTableColumn } from '../../types';
5
4
  import { DataTableSlots, PartialSlotProps } from '../../types/slots.types';
6
5
  import { DataTableSize } from '../../utils/table-helpers';
7
6
  import { SelectionState } from '../../features';
7
+ import { DataTableLoggingOptions } from '../../utils/logger';
8
8
  export type SelectMode = 'page' | 'all';
9
9
  declare module '@tanstack/table-core' {
10
10
  interface ColumnMeta<TData extends RowData, TValue> {
11
11
  }
12
12
  }
13
13
  export interface DataTableProps<T> {
14
- columns: DataTableColumn<T>[];
14
+ columns: ColumnDef<T, any>[];
15
15
  data?: T[];
16
16
  totalRow?: number;
17
17
  idKey?: keyof T;
@@ -95,4 +95,5 @@ export interface DataTableProps<T> {
95
95
  onColumnFilterChange?: (columnFilter: ColumnFilterState) => void;
96
96
  slots?: Partial<DataTableSlots<T>>;
97
97
  slotProps?: PartialSlotProps<T>;
98
+ logging?: boolean | DataTableLoggingOptions;
98
99
  }
@@ -6,6 +6,7 @@ const react_1 = require("react");
6
6
  const material_1 = require("@mui/material");
7
7
  const icons_material_1 = require("@mui/icons-material");
8
8
  const components_1 = require("../components");
9
+ const types_1 = require("../types");
9
10
  const generateEmployeeData = () => {
10
11
  const departments = [
11
12
  { id: 1, name: 'Engineering', color: '#2196F3' },
@@ -218,6 +219,10 @@ function AdvancedFeaturesExample() {
218
219
  pageIndex: 0,
219
220
  pageSize: 10,
220
221
  },
222
+ columnPinning: {
223
+ left: [types_1.DEFAULT_SELECTION_COLUMN_NAME],
224
+ right: ['actions'],
225
+ },
221
226
  columnOrder: ['name', 'department.name', 'salary', 'performance.rating', 'skills'],
222
227
  }, tableContainerProps: {
223
228
  sx: {
@@ -35,7 +35,7 @@ function ServerSideFetchingExample() {
35
35
  const apiRef = (0, react_1.useRef)(null);
36
36
  const handleFetchData = (0, react_1.useCallback)((filters) => tslib_1.__awaiter(this, void 0, void 0, function* () {
37
37
  var _a, _b, _c;
38
- console.log('🔄 Fetching data with filters:', filters);
38
+ console.log('🔄 handleFetchData', { filters });
39
39
  setLoading(true);
40
40
  setError(null);
41
41
  setLastFetchParams(filters);
@@ -114,13 +114,12 @@ function ServerSideFetchingExample() {
114
114
  }
115
115
  }), [tab]);
116
116
  const handleSelectionChange = (0, react_1.useCallback)((selection) => {
117
- console.log('🔄 Selection changed:', selection);
118
117
  setSelectionInfo(selection);
119
118
  }, []);
120
119
  (0, react_1.useEffect)(() => {
121
120
  var _a;
122
- console.log('🔄 Tab changed:', tab);
123
- if (tab && tab !== 'all') {
121
+ if (tab) {
122
+ console.log('🔄 Refreshing data');
124
123
  (_a = apiRef.current) === null || _a === void 0 ? void 0 : _a.data.refresh();
125
124
  }
126
125
  }, [tab]);
@@ -233,7 +232,7 @@ function ServerSideFetchingExample() {
233
232
  }, children: "Update Selected" })] })), enableGlobalFilter: true, enableColumnFilter: true, enableSorting: true, enablePagination: true, initialState: {
234
233
  pagination: {
235
234
  pageIndex: 0,
236
- pageSize: 10,
235
+ pageSize: 50,
237
236
  },
238
237
  columnPinning: {
239
238
  left: [types_1.DEFAULT_SELECTION_COLUMN_NAME],
@@ -245,5 +244,9 @@ function ServerSideFetchingExample() {
245
244
  console.log('Export completed:', result);
246
245
  }, onExportError: (error) => {
247
246
  console.error('Export error:', error);
248
- }, enableHover: true, enableStripes: true, tableSize: "medium", enableColumnVisibility: true, enableTableSizeControl: true, enableReset: true, emptyMessage: "No employees found matching your criteria", skeletonRows: 10 })] }));
247
+ }, enableHover: true, enableStripes: true, tableSize: "medium", enableColumnVisibility: true, enableTableSizeControl: true, enableReset: true, emptyMessage: "No employees found matching your criteria", skeletonRows: 10, slotProps: {
248
+ pagination: {
249
+ rowsPerPageOptions: [5, 10, 20, 50, 100, 200],
250
+ },
251
+ } })] }));
249
252
  }
@@ -3,6 +3,7 @@ import { Ref } from 'react';
3
3
  import { ColumnFilterState, TableFilters, TableState } from '../types';
4
4
  import { DataTableApi } from '../types/data-table-api';
5
5
  import { SelectionState } from '../features';
6
+ import { DataTableLoggingOptions } from '../utils/logger';
6
7
  interface UseDataTableApiProps<T> {
7
8
  table: Table<T>;
8
9
  idKey: keyof T;
@@ -39,6 +40,7 @@ interface UseDataTableApiProps<T> {
39
40
  setExportController?: (controller: AbortController | null) => void;
40
41
  isExporting?: boolean;
41
42
  dataMode?: 'client' | 'server';
43
+ logging?: boolean | DataTableLoggingOptions;
42
44
  }
43
45
  export declare function useDataTableApi<T extends Record<string, any>>(props: UseDataTableApiProps<T>, ref: Ref<DataTableApi<T>>): void;
44
46
  export {};
@@ -4,8 +4,13 @@ exports.useDataTableApi = useDataTableApi;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = require("react");
6
6
  const export_utils_1 = require("../utils/export-utils");
7
+ const logger_1 = require("../utils/logger");
7
8
  function useDataTableApi(props, ref) {
8
- const { table, idKey, enhancedColumns, enablePagination, enableColumnPinning, initialStateConfig, selectMode = 'page', onSelectionChange, handleColumnFilterStateChange, onDataStateChange, onFetchData, onDataChange, exportFilename = 'export', onExportProgress, onExportComplete, onExportError, onServerExport, exportController, setExportController, isExporting, dataMode = 'client', } = props;
9
+ const { table, idKey, enhancedColumns, enablePagination, enableColumnPinning, initialStateConfig, selectMode = 'page', onSelectionChange, handleColumnFilterStateChange, onDataStateChange, onFetchData, onDataChange, exportFilename = 'export', onExportProgress, onExportComplete, onExportError, onServerExport, exportController, setExportController, isExporting, dataMode = 'client', logging, } = props;
10
+ const logger = (0, react_1.useMemo)(() => (0, logger_1.createLogger)('DataTableApi', logging), [logging]);
11
+ const fetchLogger = (0, react_1.useMemo)(() => logger.child('fetch'), [logger]);
12
+ const paginationLogger = (0, react_1.useMemo)(() => logger.child('pagination'), [logger]);
13
+ const stateLogger = (0, react_1.useMemo)(() => logger.child('state'), [logger]);
9
14
  const getTableFilters = (0, react_1.useCallback)((withAllState = false) => {
10
15
  const state = table.getState();
11
16
  return Object.assign({ sorting: state.sorting, globalFilter: state.globalFilter, columnFilter: state.columnFilter, pagination: state.pagination }, (withAllState ? {
@@ -55,6 +60,9 @@ function useDataTableApi(props, ref) {
55
60
  newOrder.splice(currentIndex, 1);
56
61
  newOrder.splice(toIndex, 0, columnId);
57
62
  table.setColumnOrder(newOrder);
63
+ if (stateLogger.isLevelEnabled('debug')) {
64
+ stateLogger.debug('Column order updated', `${columnId} from ${currentIndex} to ${toIndex}`);
65
+ }
58
66
  },
59
67
  resetColumnOrder: () => {
60
68
  const initialOrder = enhancedColumns.map((col, index) => {
@@ -67,6 +75,9 @@ function useDataTableApi(props, ref) {
67
75
  return `column_${index}`;
68
76
  });
69
77
  table.setColumnOrder(initialOrder);
78
+ if (stateLogger.isLevelEnabled('debug')) {
79
+ stateLogger.debug('Column order reset', initialOrder);
80
+ }
70
81
  },
71
82
  },
72
83
  columnPinning: {
@@ -76,6 +87,9 @@ function useDataTableApi(props, ref) {
76
87
  newPinning.right = (newPinning.right || []).filter(id => id !== columnId);
77
88
  newPinning.left = [...(newPinning.left || []).filter(id => id !== columnId), columnId];
78
89
  table.setColumnPinning(newPinning);
90
+ if (stateLogger.isLevelEnabled('debug')) {
91
+ stateLogger.debug('Column pinned left', `${columnId}`);
92
+ }
79
93
  },
80
94
  pinColumnRight: (columnId) => {
81
95
  const currentPinning = table.getState().columnPinning;
@@ -83,6 +97,9 @@ function useDataTableApi(props, ref) {
83
97
  newPinning.left = (newPinning.left || []).filter(id => id !== columnId);
84
98
  newPinning.right = [...(newPinning.right || []).filter(id => id !== columnId), columnId];
85
99
  table.setColumnPinning(newPinning);
100
+ if (stateLogger.isLevelEnabled('debug')) {
101
+ stateLogger.debug('Column pinned right', `${columnId}`);
102
+ }
86
103
  },
87
104
  unpinColumn: (columnId) => {
88
105
  const currentPinning = table.getState().columnPinning;
@@ -118,12 +135,21 @@ function useDataTableApi(props, ref) {
118
135
  filtering: {
119
136
  setGlobalFilter: (filter) => {
120
137
  table.setGlobalFilter(filter);
138
+ if (stateLogger.isLevelEnabled('debug')) {
139
+ stateLogger.debug('Global filter set', `${filter}`);
140
+ }
121
141
  },
122
142
  clearGlobalFilter: () => {
123
143
  table.setGlobalFilter('');
144
+ if (stateLogger.isLevelEnabled('debug')) {
145
+ stateLogger.debug('Global filter cleared');
146
+ }
124
147
  },
125
148
  setColumnFilters: (filters) => {
126
149
  handleColumnFilterStateChange(filters);
150
+ if (stateLogger.isLevelEnabled('debug')) {
151
+ stateLogger.debug('Column filters set', `${filters}`);
152
+ }
127
153
  },
128
154
  addColumnFilter: (columnId, operator, value) => {
129
155
  const newFilter = {
@@ -141,6 +167,9 @@ function useDataTableApi(props, ref) {
141
167
  pendingFilters: columnFilter.pendingFilters || [],
142
168
  pendingLogic: columnFilter.pendingLogic || 'AND',
143
169
  });
170
+ if (stateLogger.isLevelEnabled('debug')) {
171
+ stateLogger.debug(`Column filter added ${columnId} ${operator} ${value}`, newFilters);
172
+ }
144
173
  },
145
174
  removeColumnFilter: (filterId) => {
146
175
  const columnFilter = table.getState().columnFilter;
@@ -152,6 +181,9 @@ function useDataTableApi(props, ref) {
152
181
  pendingFilters: columnFilter.pendingFilters || [],
153
182
  pendingLogic: columnFilter.pendingLogic || 'AND',
154
183
  });
184
+ if (stateLogger.isLevelEnabled('debug')) {
185
+ stateLogger.debug(`Column filter removed ${filterId}`, newFilters);
186
+ }
155
187
  },
156
188
  clearAllFilters: () => {
157
189
  table.setGlobalFilter('');
@@ -161,6 +193,9 @@ function useDataTableApi(props, ref) {
161
193
  pendingFilters: [],
162
194
  pendingLogic: 'AND',
163
195
  });
196
+ if (stateLogger.isLevelEnabled('debug')) {
197
+ stateLogger.debug('Filters reset');
198
+ }
164
199
  },
165
200
  resetFilters: () => {
166
201
  table.resetGlobalFilter();
@@ -175,6 +210,9 @@ function useDataTableApi(props, ref) {
175
210
  sorting: {
176
211
  setSorting: (sortingState) => {
177
212
  table.setSorting(sortingState);
213
+ if (stateLogger.isLevelEnabled('debug')) {
214
+ stateLogger.debug('Sorting set', `${sortingState}`);
215
+ }
178
216
  },
179
217
  sortColumn: (columnId, direction) => {
180
218
  const column = table.getColumn(columnId);
@@ -197,24 +235,42 @@ function useDataTableApi(props, ref) {
197
235
  pagination: {
198
236
  goToPage: (pageIndex) => {
199
237
  table.setPageIndex(pageIndex);
238
+ if (paginationLogger.isLevelEnabled('debug')) {
239
+ paginationLogger.debug('Page index set', `${pageIndex}`);
240
+ }
200
241
  },
201
242
  nextPage: () => {
202
243
  table.nextPage();
244
+ if (paginationLogger.isLevelEnabled('debug')) {
245
+ paginationLogger.debug('Next page');
246
+ }
203
247
  },
204
248
  previousPage: () => {
205
249
  table.previousPage();
250
+ if (paginationLogger.isLevelEnabled('debug')) {
251
+ paginationLogger.debug('Previous page');
252
+ }
206
253
  },
207
254
  setPageSize: (pageSize) => {
208
255
  table.setPageSize(pageSize);
256
+ if (paginationLogger.isLevelEnabled('debug')) {
257
+ paginationLogger.debug('Page size set', `${pageSize}`);
258
+ }
209
259
  },
210
260
  goToFirstPage: () => {
211
261
  table.setPageIndex(0);
262
+ if (paginationLogger.isLevelEnabled('debug')) {
263
+ paginationLogger.debug('Page index set to 0');
264
+ }
212
265
  },
213
266
  goToLastPage: () => {
214
267
  const pageCount = table.getPageCount();
215
268
  if (pageCount > 0) {
216
269
  table.setPageIndex(pageCount - 1);
217
270
  }
271
+ if (paginationLogger.isLevelEnabled('debug')) {
272
+ paginationLogger.debug('Page index set to last page', `${pageCount - 1}`);
273
+ }
218
274
  },
219
275
  },
220
276
  selection: {
@@ -240,12 +296,18 @@ function useDataTableApi(props, ref) {
240
296
  const allState = getTableFilters(true);
241
297
  onDataStateChange === null || onDataStateChange === void 0 ? void 0 : onDataStateChange(allState);
242
298
  onFetchData === null || onFetchData === void 0 ? void 0 : onFetchData(filters);
299
+ if (fetchLogger.isLevelEnabled('debug')) {
300
+ fetchLogger.debug('Data refreshed', filters);
301
+ }
243
302
  },
244
303
  reload: () => {
245
304
  const filters = getTableFilters();
246
305
  const allState = getTableFilters(true);
247
306
  onDataStateChange === null || onDataStateChange === void 0 ? void 0 : onDataStateChange(allState);
248
307
  onFetchData === null || onFetchData === void 0 ? void 0 : onFetchData(filters);
308
+ if (fetchLogger.isLevelEnabled('debug')) {
309
+ fetchLogger.debug('Data reloaded', filters);
310
+ }
249
311
  },
250
312
  getAllData: () => {
251
313
  var _a;
@@ -264,6 +326,9 @@ function useDataTableApi(props, ref) {
264
326
  const newData = (_a = table.getRowModel().rows) === null || _a === void 0 ? void 0 : _a.map(row => String(row.original[idKey]) === rowId
265
327
  ? Object.assign(Object.assign({}, row.original), updates) : row.original);
266
328
  onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData || []);
329
+ if (fetchLogger.isLevelEnabled('debug')) {
330
+ fetchLogger.debug('Row updated', `${rowId}`, updates);
331
+ }
267
332
  },
268
333
  updateRowByIndex: (index, updates) => {
269
334
  var _a;
@@ -283,11 +348,17 @@ function useDataTableApi(props, ref) {
283
348
  newData.push(newRow);
284
349
  }
285
350
  onDataChange(newData || []);
351
+ if (stateLogger.isLevelEnabled('debug')) {
352
+ stateLogger.debug('Row inserted', `${newRow}`, index);
353
+ }
286
354
  },
287
355
  deleteRow: (rowId) => {
288
356
  var _a;
289
357
  const newData = (_a = (table.getRowModel().rows || [])) === null || _a === void 0 ? void 0 : _a.filter(row => String(row.original[idKey]) !== rowId);
290
358
  onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange((newData === null || newData === void 0 ? void 0 : newData.map(row => row.original)) || []);
359
+ if (stateLogger.isLevelEnabled('debug')) {
360
+ stateLogger.debug('Row deleted', `${rowId}`);
361
+ }
291
362
  },
292
363
  deleteRowByIndex: (index) => {
293
364
  var _a;
@@ -302,6 +373,9 @@ function useDataTableApi(props, ref) {
302
373
  const newData = (_a = (table.getRowModel().rows || [])) === null || _a === void 0 ? void 0 : _a.filter(row => !selectedRowIds.includes(String(row.original[idKey])));
303
374
  onDataChange((newData === null || newData === void 0 ? void 0 : newData.map(row => row.original)) || []);
304
375
  table.resetRowSelection();
376
+ if (stateLogger.isLevelEnabled('debug')) {
377
+ stateLogger.debug('Selected rows deleted', selectedRowIds);
378
+ }
305
379
  },
306
380
  replaceAllData: (newData) => {
307
381
  onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
@@ -315,6 +389,9 @@ function useDataTableApi(props, ref) {
315
389
  return updateData ? Object.assign(Object.assign({}, row.original), updateData) : row.original;
316
390
  });
317
391
  onDataChange(newData || []);
392
+ if (stateLogger.isLevelEnabled('debug')) {
393
+ stateLogger.debug('Multiple rows updated', updates);
394
+ }
318
395
  },
319
396
  insertMultipleRows: (newRows, startIndex) => {
320
397
  var _a;
@@ -326,12 +403,18 @@ function useDataTableApi(props, ref) {
326
403
  newData.push(...newRows);
327
404
  }
328
405
  onDataChange === null || onDataChange === void 0 ? void 0 : onDataChange(newData);
406
+ if (stateLogger.isLevelEnabled('debug')) {
407
+ stateLogger.debug('Multiple rows inserted', newRows);
408
+ }
329
409
  },
330
410
  deleteMultipleRows: (rowIds) => {
331
411
  var _a, _b;
332
412
  const idsToDelete = new Set(rowIds);
333
413
  const newData = (_b = (_a = (table.getRowModel().rows || [])) === null || _a === void 0 ? void 0 : _a.filter(row => !idsToDelete.has(String(row.original[idKey])))) === null || _b === void 0 ? void 0 : _b.map(row => row.original);
334
414
  onDataChange(newData);
415
+ if (stateLogger.isLevelEnabled('debug')) {
416
+ stateLogger.debug('Multiple rows deleted', rowIds);
417
+ }
335
418
  },
336
419
  updateField: (rowId, fieldName, value) => {
337
420
  var _a;
@@ -458,6 +541,9 @@ function useDataTableApi(props, ref) {
458
541
  sorting: table.getState().sorting,
459
542
  pagination: table.getState().pagination,
460
543
  };
544
+ if (stateLogger.isLevelEnabled('debug')) {
545
+ stateLogger.debug('Server export CSV', { currentFilters });
546
+ }
461
547
  yield (0, export_utils_1.exportServerData)(table, {
462
548
  format: 'csv',
463
549
  filename,
@@ -6,21 +6,14 @@ const react_1 = require("react");
6
6
  function useDebouncedFetch(onFetchData, delay = 300) {
7
7
  const [isLoading, setIsLoading] = (0, react_1.useState)(false);
8
8
  const debounceTimer = (0, react_1.useRef)(null);
9
- const lastFetchParams = (0, react_1.useRef)('');
10
9
  const debouncedFetch = (0, react_1.useCallback)((filters) => tslib_1.__awaiter(this, void 0, void 0, function* () {
11
10
  if (!onFetchData)
12
11
  return null;
13
- const currentParams = JSON.stringify(filters);
14
12
  if (debounceTimer.current) {
15
13
  clearTimeout(debounceTimer.current);
16
14
  }
17
15
  return new Promise((resolve) => {
18
16
  debounceTimer.current = setTimeout(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
19
- if (lastFetchParams.current === currentParams) {
20
- resolve(null);
21
- return;
22
- }
23
- lastFetchParams.current = currentParams;
24
17
  setIsLoading(true);
25
18
  try {
26
19
  const result = yield onFetchData(filters);
@@ -5,3 +5,4 @@ export * from './export-utils';
5
5
  export * from './special-columns.utils';
6
6
  export * from './debounced-fetch.utils';
7
7
  export * from './slot-helpers';
8
+ export * from './logger';
@@ -8,3 +8,4 @@ tslib_1.__exportStar(require("./export-utils"), exports);
8
8
  tslib_1.__exportStar(require("./special-columns.utils"), exports);
9
9
  tslib_1.__exportStar(require("./debounced-fetch.utils"), exports);
10
10
  tslib_1.__exportStar(require("./slot-helpers"), exports);
11
+ tslib_1.__exportStar(require("./logger"), exports);
@@ -0,0 +1,34 @@
1
+ export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
2
+ interface ConsoleLike {
3
+ debug?: (...args: unknown[]) => void;
4
+ info?: (...args: unknown[]) => void;
5
+ warn?: (...args: unknown[]) => void;
6
+ error?: (...args: unknown[]) => void;
7
+ log?: (...args: unknown[]) => void;
8
+ }
9
+ export interface DataTableLoggingOptions {
10
+ enabled?: boolean;
11
+ level?: LogLevel;
12
+ prefix?: string;
13
+ scope?: string;
14
+ includeTimestamp?: boolean;
15
+ logger?: ConsoleLike;
16
+ }
17
+ type LoggerInput = boolean | DataTableLoggingOptions;
18
+ type ResolvedLoggerConfig = Required<Omit<DataTableLoggingOptions, 'logger'>> & {
19
+ logger: ConsoleLike;
20
+ };
21
+ type LogMethodLevel = Exclude<LogLevel, 'silent'>;
22
+ export interface LoggerInstance {
23
+ debug: (...args: unknown[]) => void;
24
+ info: (...args: unknown[]) => void;
25
+ warn: (...args: unknown[]) => void;
26
+ error: (...args: unknown[]) => void;
27
+ child: (scope: string, overrides?: LoggerInput) => LoggerInstance;
28
+ isLevelEnabled: (level: LogMethodLevel) => boolean;
29
+ config: ResolvedLoggerConfig;
30
+ }
31
+ export declare const createLogger: (scope?: string, input?: LoggerInput, parentConfig?: ResolvedLoggerConfig) => LoggerInstance;
32
+ export declare const configureDataTableLogging: (options: DataTableLoggingOptions) => void;
33
+ export declare const getDataTableLoggingConfig: () => ResolvedLoggerConfig;
34
+ export {};
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDataTableLoggingConfig = exports.configureDataTableLogging = exports.createLogger = void 0;
4
+ const LOG_LEVEL_ORDER = {
5
+ silent: 0,
6
+ error: 1,
7
+ warn: 2,
8
+ info: 3,
9
+ debug: 4,
10
+ };
11
+ const defaultConsole = typeof console !== 'undefined'
12
+ ? console
13
+ : {
14
+ log: () => undefined,
15
+ debug: () => undefined,
16
+ info: () => undefined,
17
+ warn: () => undefined,
18
+ error: () => undefined,
19
+ };
20
+ let globalConfig = {
21
+ enabled: false,
22
+ level: 'warn',
23
+ prefix: 'DataTable',
24
+ scope: '',
25
+ includeTimestamp: false,
26
+ logger: defaultConsole,
27
+ };
28
+ const isLevelEnabled = (level, config) => {
29
+ if (!config.enabled) {
30
+ return false;
31
+ }
32
+ return LOG_LEVEL_ORDER[level] <= LOG_LEVEL_ORDER[config.level];
33
+ };
34
+ const formatPrefix = (level, config) => {
35
+ const segments = [];
36
+ if (config.prefix) {
37
+ segments.push(config.prefix);
38
+ }
39
+ if (config.scope) {
40
+ segments.push(config.scope);
41
+ }
42
+ const prefix = segments.length > 0 ? `[${segments.join(':')}]` : '';
43
+ return config.includeTimestamp
44
+ ? `[${new Date().toISOString()}]${prefix ? ` ${prefix}` : ''} [${level.toUpperCase()}]`
45
+ : `${prefix ? `${prefix} ` : ''}[${level.toUpperCase()}]`;
46
+ };
47
+ const getConsoleMethod = (level, logger) => {
48
+ var _a, _b, _c;
49
+ const methodName = level === 'debug' ? 'debug' : level;
50
+ return (_c = (_b = (_a = logger[methodName]) !== null && _a !== void 0 ? _a : logger.log) !== null && _b !== void 0 ? _b : defaultConsole.log) !== null && _c !== void 0 ? _c : (() => undefined);
51
+ };
52
+ const normaliseInput = (input) => {
53
+ if (typeof input === 'boolean') {
54
+ return { enabled: input };
55
+ }
56
+ return input !== null && input !== void 0 ? input : {};
57
+ };
58
+ const resolveConfig = (scope, input, parent) => {
59
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
60
+ const overrides = normaliseInput(input);
61
+ const base = parent !== null && parent !== void 0 ? parent : globalConfig;
62
+ return {
63
+ enabled: (_a = overrides.enabled) !== null && _a !== void 0 ? _a : base.enabled,
64
+ level: (_b = overrides.level) !== null && _b !== void 0 ? _b : base.level,
65
+ prefix: (_c = overrides.prefix) !== null && _c !== void 0 ? _c : base.prefix,
66
+ scope: (_f = (_e = (_d = overrides.scope) !== null && _d !== void 0 ? _d : scope) !== null && _e !== void 0 ? _e : base.scope) !== null && _f !== void 0 ? _f : '',
67
+ includeTimestamp: (_g = overrides.includeTimestamp) !== null && _g !== void 0 ? _g : base.includeTimestamp,
68
+ logger: (_j = (_h = overrides.logger) !== null && _h !== void 0 ? _h : base.logger) !== null && _j !== void 0 ? _j : defaultConsole,
69
+ };
70
+ };
71
+ const createLoggerMethods = (config) => {
72
+ const logWithLevel = (level) => {
73
+ const consoleMethod = getConsoleMethod(level, config.logger);
74
+ return (...args) => {
75
+ if (!isLevelEnabled(level, config)) {
76
+ return;
77
+ }
78
+ const prefix = formatPrefix(level, config);
79
+ consoleMethod(prefix, ...args);
80
+ };
81
+ };
82
+ return {
83
+ debug: logWithLevel('debug'),
84
+ info: logWithLevel('info'),
85
+ warn: logWithLevel('warn'),
86
+ error: logWithLevel('error'),
87
+ };
88
+ };
89
+ const createLogger = (scope, input, parentConfig) => {
90
+ const resolvedConfig = resolveConfig(scope, input, parentConfig);
91
+ const methods = createLoggerMethods(resolvedConfig);
92
+ const child = (childScope, overrides) => {
93
+ const combinedScope = childScope
94
+ ? (resolvedConfig.scope ? `${resolvedConfig.scope}.${childScope}` : childScope)
95
+ : resolvedConfig.scope;
96
+ return (0, exports.createLogger)(combinedScope, overrides, resolvedConfig);
97
+ };
98
+ return Object.assign(Object.assign({}, methods), { child, isLevelEnabled: (level) => isLevelEnabled(level, resolvedConfig), config: resolvedConfig });
99
+ };
100
+ exports.createLogger = createLogger;
101
+ const configureDataTableLogging = (options) => {
102
+ globalConfig = resolveConfig(options.scope, options, globalConfig);
103
+ };
104
+ exports.configureDataTableLogging = configureDataTableLogging;
105
+ const getDataTableLoggingConfig = () => (Object.assign({}, globalConfig));
106
+ exports.getDataTableLoggingConfig = getDataTableLoggingConfig;