@ackplus/react-tanstack-data-table 1.0.34 → 1.1.1
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/LICENSE +21 -0
- package/{src → dist}/index.d.ts +21 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/{src → dist}/lib/components/droupdown/menu-dropdown.d.ts +2 -1
- package/dist/lib/components/droupdown/menu-dropdown.d.ts.map +1 -0
- package/{src → dist}/lib/components/droupdown/menu-dropdown.js +38 -7
- package/{src → dist}/lib/components/filters/filter-value-input.d.ts +3 -1
- package/dist/lib/components/filters/filter-value-input.d.ts.map +1 -0
- package/dist/lib/components/filters/filter-value-input.js +83 -0
- package/{src → dist}/lib/components/filters/index.d.ts +1 -0
- package/dist/lib/components/filters/index.d.ts.map +1 -0
- package/dist/lib/components/filters/index.js +142 -0
- package/{src → dist}/lib/components/headers/draggable-header.d.ts +2 -2
- package/dist/lib/components/headers/draggable-header.d.ts.map +1 -0
- package/{src → dist}/lib/components/headers/draggable-header.js +81 -17
- package/dist/lib/components/headers/index.d.ts +6 -0
- package/dist/lib/components/headers/index.d.ts.map +1 -0
- package/dist/lib/components/headers/index.js +21 -0
- package/{src → dist}/lib/components/headers/table-header.d.ts +15 -1
- package/dist/lib/components/headers/table-header.d.ts.map +1 -0
- package/{src → dist}/lib/components/headers/table-header.js +50 -17
- package/{src → dist}/lib/components/index.d.ts +6 -1
- package/dist/lib/components/index.d.ts.map +1 -0
- package/dist/lib/components/index.js +32 -0
- package/{src → dist}/lib/components/pagination/data-table-pagination.d.ts +2 -1
- package/dist/lib/components/pagination/data-table-pagination.d.ts.map +1 -0
- package/{src → dist}/lib/components/pagination/data-table-pagination.js +20 -6
- package/dist/lib/components/pagination/index.d.ts +5 -0
- package/dist/lib/components/pagination/index.d.ts.map +1 -0
- package/dist/lib/components/pagination/index.js +20 -0
- package/{src → dist}/lib/components/rows/data-table-row.d.ts +15 -2
- package/dist/lib/components/rows/data-table-row.d.ts.map +1 -0
- package/{src → dist}/lib/components/rows/data-table-row.js +58 -25
- package/{src → dist}/lib/components/rows/empty-data-row.d.ts +3 -3
- package/dist/lib/components/rows/empty-data-row.d.ts.map +1 -0
- package/{src → dist}/lib/components/rows/empty-data-row.js +12 -4
- package/dist/lib/components/rows/index.d.ts +7 -0
- package/dist/lib/components/rows/index.d.ts.map +1 -0
- package/dist/lib/components/rows/index.js +22 -0
- package/{src → dist}/lib/components/rows/loading-rows.d.ts +3 -1
- package/dist/lib/components/rows/loading-rows.d.ts.map +1 -0
- package/{src → dist}/lib/components/rows/loading-rows.js +27 -19
- package/{src → dist}/lib/components/toolbar/bulk-actions-toolbar.d.ts +4 -3
- package/dist/lib/components/toolbar/bulk-actions-toolbar.d.ts.map +1 -0
- package/dist/lib/components/toolbar/bulk-actions-toolbar.js +49 -0
- package/{src → dist}/lib/components/toolbar/column-filter-control.d.ts +3 -1
- package/dist/lib/components/toolbar/column-filter-control.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/column-filter-control.js +73 -4
- package/{src → dist}/lib/components/toolbar/column-pinning-control.d.ts +2 -1
- package/dist/lib/components/toolbar/column-pinning-control.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/column-pinning-control.js +71 -7
- package/{src → dist}/lib/components/toolbar/column-reset-control.d.ts +3 -1
- package/dist/lib/components/toolbar/column-reset-control.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/column-reset-control.js +9 -3
- package/{src → dist}/lib/components/toolbar/column-visibility-control.d.ts +2 -1
- package/dist/lib/components/toolbar/column-visibility-control.d.ts.map +1 -0
- package/dist/lib/components/toolbar/column-visibility-control.js +77 -0
- package/{src → dist}/lib/components/toolbar/data-table-toolbar.d.ts +3 -2
- package/dist/lib/components/toolbar/data-table-toolbar.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/data-table-toolbar.js +17 -4
- package/{src → dist}/lib/components/toolbar/index.d.ts +4 -0
- package/dist/lib/components/toolbar/index.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/index.js +6 -0
- package/dist/lib/components/toolbar/table-export-control.d.ts +12 -0
- package/dist/lib/components/toolbar/table-export-control.d.ts.map +1 -0
- package/dist/lib/components/toolbar/table-export-control.js +67 -0
- package/{src → dist}/lib/components/toolbar/table-search-control.d.ts +3 -1
- package/dist/lib/components/toolbar/table-search-control.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/table-search-control.js +45 -2
- package/{src → dist}/lib/components/toolbar/table-size-control.d.ts +3 -1
- package/dist/lib/components/toolbar/table-size-control.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/table-size-control.js +20 -8
- package/{src → dist}/lib/contexts/data-table-context.d.ts +6 -2
- package/dist/lib/contexts/data-table-context.d.ts.map +1 -0
- package/{src → dist}/lib/contexts/data-table-context.js +34 -1
- package/dist/lib/data-table.d.ts +5 -0
- package/dist/lib/data-table.d.ts.map +1 -0
- package/{src/lib/components/table → dist/lib}/data-table.js +449 -151
- package/dist/lib/features/column-filter.feature.d.ts +55 -0
- package/dist/lib/features/column-filter.feature.d.ts.map +1 -0
- package/{src → dist}/lib/features/column-filter.feature.js +116 -18
- package/dist/lib/features/index.d.ts +9 -0
- package/dist/lib/features/index.d.ts.map +1 -0
- package/{src → dist}/lib/features/index.js +7 -0
- package/{src → dist}/lib/features/selection.feature.d.ts +8 -1
- package/dist/lib/features/selection.feature.d.ts.map +1 -0
- package/{src → dist}/lib/features/selection.feature.js +76 -15
- package/dist/lib/icons/add-icon.d.ts +4 -0
- package/dist/lib/icons/add-icon.d.ts.map +1 -0
- package/dist/lib/icons/add-icon.js +12 -0
- package/dist/lib/icons/csv-icon.d.ts +4 -0
- package/dist/lib/icons/csv-icon.d.ts.map +1 -0
- package/dist/lib/icons/csv-icon.js +12 -0
- package/dist/lib/icons/delete-icon.d.ts +4 -0
- package/dist/lib/icons/delete-icon.d.ts.map +1 -0
- package/dist/lib/icons/delete-icon.js +12 -0
- package/dist/lib/icons/excel-icon.d.ts +4 -0
- package/dist/lib/icons/excel-icon.d.ts.map +1 -0
- package/dist/lib/icons/excel-icon.js +12 -0
- package/dist/lib/icons/index.d.ts +8 -0
- package/dist/lib/icons/index.d.ts.map +1 -0
- package/dist/lib/icons/unpin-icon.d.ts +4 -0
- package/dist/lib/icons/unpin-icon.d.ts.map +1 -0
- package/dist/lib/icons/unpin-icon.js +12 -0
- package/{src → dist}/lib/icons/view-comfortable-icon.d.ts +3 -1
- package/dist/lib/icons/view-comfortable-icon.d.ts.map +1 -0
- package/dist/lib/icons/view-comfortable-icon.js +12 -0
- package/dist/lib/icons/view-compact-icon.d.ts +4 -0
- package/dist/lib/icons/view-compact-icon.d.ts.map +1 -0
- package/dist/lib/icons/view-compact-icon.js +12 -0
- package/{src → dist}/lib/types/column.types.d.ts +10 -1
- package/dist/lib/types/column.types.d.ts.map +1 -0
- package/{src → dist}/lib/types/data-table-api.d.ts +2 -1
- package/dist/lib/types/data-table-api.d.ts.map +1 -0
- package/{src/lib/components/table → dist/lib/types}/data-table.types.d.ts +10 -10
- package/dist/lib/types/data-table.types.d.ts.map +1 -0
- package/{src → dist}/lib/types/export.types.d.ts +38 -0
- package/dist/lib/types/export.types.d.ts.map +1 -0
- package/dist/lib/types/export.types.js +6 -0
- package/{src → dist}/lib/types/index.d.ts +5 -0
- package/dist/lib/types/index.d.ts.map +1 -0
- package/dist/lib/types/index.js +30 -0
- package/{src → dist}/lib/types/slots.types.d.ts +50 -3
- package/dist/lib/types/slots.types.d.ts.map +1 -0
- package/{src → dist}/lib/types/table.types.d.ts +14 -0
- package/dist/lib/types/table.types.d.ts.map +1 -0
- package/{src → dist}/lib/utils/column-helpers.d.ts +10 -0
- package/dist/lib/utils/column-helpers.d.ts.map +1 -0
- package/{src → dist}/lib/utils/column-helpers.js +20 -4
- package/{src → dist}/lib/utils/debounced-fetch.utils.d.ts +3 -5
- package/dist/lib/utils/debounced-fetch.utils.d.ts.map +1 -0
- package/{src → dist}/lib/utils/debounced-fetch.utils.js +12 -6
- package/{src → dist}/lib/utils/export-utils.d.ts +13 -0
- package/dist/lib/utils/export-utils.d.ts.map +1 -0
- package/dist/lib/utils/export-utils.js +252 -0
- package/{src → dist}/lib/utils/index.d.ts +4 -0
- package/dist/lib/utils/index.d.ts.map +1 -0
- package/dist/lib/utils/index.js +35 -0
- package/{src → dist}/lib/utils/logger.d.ts +43 -0
- package/dist/lib/utils/logger.d.ts.map +1 -0
- package/{src → dist}/lib/utils/logger.js +22 -2
- package/{src → dist}/lib/utils/slot-helpers.d.ts +39 -1
- package/dist/lib/utils/slot-helpers.d.ts.map +1 -0
- package/{src → dist}/lib/utils/slot-helpers.js +55 -6
- package/{src → dist}/lib/utils/special-columns.utils.d.ts +10 -0
- package/dist/lib/utils/special-columns.utils.d.ts.map +1 -0
- package/{src → dist}/lib/utils/special-columns.utils.js +41 -5
- package/{src → dist}/lib/utils/styling-helpers.d.ts +20 -0
- package/dist/lib/utils/styling-helpers.d.ts.map +1 -0
- package/dist/lib/utils/styling-helpers.js +108 -0
- package/{src → dist}/lib/utils/table-helpers.d.ts +25 -0
- package/dist/lib/utils/table-helpers.d.ts.map +1 -0
- package/{src → dist}/lib/utils/table-helpers.js +24 -0
- package/package.json +36 -11
- package/src/index.ts +71 -0
- package/src/lib/components/droupdown/menu-dropdown.tsx +97 -0
- package/src/lib/components/filters/filter-value-input.tsx +225 -0
- package/src/lib/components/filters/{index.js → index.ts} +3 -6
- package/src/lib/components/headers/draggable-header.tsx +326 -0
- package/src/lib/components/headers/{index.d.ts → index.ts} +4 -0
- package/src/lib/components/headers/table-header.tsx +173 -0
- package/src/lib/components/index.ts +21 -0
- package/src/lib/components/pagination/data-table-pagination.tsx +99 -0
- package/src/lib/components/pagination/index.ts +5 -0
- package/src/lib/components/rows/data-table-row.tsx +208 -0
- package/src/lib/components/rows/empty-data-row.tsx +69 -0
- package/src/lib/components/rows/{index.d.ts → index.ts} +4 -0
- package/src/lib/components/rows/loading-rows.tsx +160 -0
- package/src/lib/components/toolbar/bulk-actions-toolbar.tsx +125 -0
- package/src/lib/components/toolbar/column-filter-control.tsx +374 -0
- package/src/lib/components/toolbar/column-pinning-control.tsx +275 -0
- package/src/lib/components/toolbar/column-reset-control.tsx +74 -0
- package/src/lib/components/toolbar/column-visibility-control.tsx +105 -0
- package/src/lib/components/toolbar/data-table-toolbar.tsx +229 -0
- package/src/lib/components/toolbar/index.ts +17 -0
- package/src/lib/components/toolbar/table-export-control.tsx +179 -0
- package/src/lib/components/toolbar/table-search-control.tsx +155 -0
- package/src/lib/components/toolbar/table-size-control.tsx +102 -0
- package/src/lib/contexts/data-table-context.tsx +112 -0
- package/src/lib/data-table.tsx +1911 -0
- package/src/lib/features/README.md +161 -0
- package/src/lib/features/column-filter.feature.ts +456 -0
- package/src/lib/features/index.ts +23 -0
- package/src/lib/features/selection.feature.ts +318 -0
- package/src/lib/icons/add-icon.tsx +23 -0
- package/src/lib/icons/csv-icon.tsx +15 -0
- package/src/lib/icons/delete-icon.tsx +30 -0
- package/src/lib/icons/excel-icon.tsx +15 -0
- package/src/lib/icons/unpin-icon.tsx +18 -0
- package/src/lib/icons/view-comfortable-icon.tsx +45 -0
- package/src/lib/icons/view-compact-icon.tsx +55 -0
- package/src/lib/types/column.types.ts +44 -0
- package/src/lib/types/data-table-api.ts +169 -0
- package/src/lib/types/data-table.types.ts +139 -0
- package/src/lib/types/export.types.ts +154 -0
- package/src/lib/types/index.ts +22 -0
- package/src/lib/types/slots.types.ts +332 -0
- package/src/lib/types/table.types.ts +90 -0
- package/src/lib/utils/column-helpers.ts +72 -0
- package/src/lib/utils/debounced-fetch.utils.ts +54 -0
- package/src/lib/utils/export-utils.ts +285 -0
- package/src/lib/utils/index.ts +27 -0
- package/src/lib/utils/logger.ts +203 -0
- package/src/lib/utils/slot-helpers.tsx +194 -0
- package/src/lib/utils/special-columns.utils.ts +94 -0
- package/src/lib/utils/styling-helpers.ts +126 -0
- package/src/lib/utils/table-helpers.ts +106 -0
- package/src/index.js +0 -27
- package/src/lib/components/filters/filter-value-input.js +0 -41
- package/src/lib/components/headers/index.js +0 -5
- package/src/lib/components/index.js +0 -10
- package/src/lib/components/pagination/index.d.ts +0 -1
- package/src/lib/components/pagination/index.js +0 -4
- package/src/lib/components/rows/index.js +0 -6
- package/src/lib/components/table/data-table.d.ts +0 -4
- package/src/lib/components/table/index.d.ts +0 -2
- package/src/lib/components/table/index.js +0 -5
- package/src/lib/components/toolbar/bulk-actions-toolbar.js +0 -30
- package/src/lib/components/toolbar/column-visibility-control.js +0 -31
- package/src/lib/components/toolbar/table-export-control.d.ts +0 -31
- package/src/lib/components/toolbar/table-export-control.js +0 -56
- package/src/lib/examples/advanced-features-example.d.ts +0 -1
- package/src/lib/examples/advanced-features-example.js +0 -269
- package/src/lib/examples/bulk-actions-test.d.ts +0 -1
- package/src/lib/examples/bulk-actions-test.js +0 -44
- package/src/lib/examples/custom-column-filter-example.d.ts +0 -1
- package/src/lib/examples/custom-column-filter-example.js +0 -60
- package/src/lib/examples/index.d.ts +0 -8
- package/src/lib/examples/index.js +0 -19
- package/src/lib/examples/selection-test-example.d.ts +0 -1
- package/src/lib/examples/selection-test-example.js +0 -101
- package/src/lib/examples/server-side-fetching-example.d.ts +0 -1
- package/src/lib/examples/server-side-fetching-example.js +0 -245
- package/src/lib/examples/server-side-test.d.ts +0 -1
- package/src/lib/examples/server-side-test.js +0 -9
- package/src/lib/examples/simple-local-example.d.ts +0 -1
- package/src/lib/examples/simple-local-example.js +0 -95
- package/src/lib/examples/simple-slots-example.d.ts +0 -1
- package/src/lib/examples/simple-slots-example.js +0 -115
- package/src/lib/features/column-filter.feature.d.ts +0 -45
- package/src/lib/features/index.d.ts +0 -2
- package/src/lib/hooks/index.d.ts +0 -1
- package/src/lib/hooks/index.js +0 -4
- package/src/lib/hooks/use-data-table-api.d.ts +0 -46
- package/src/lib/hooks/use-data-table-api.js +0 -690
- package/src/lib/icons/add-icon.d.ts +0 -2
- package/src/lib/icons/add-icon.js +0 -8
- package/src/lib/icons/csv-icon.d.ts +0 -2
- package/src/lib/icons/csv-icon.js +0 -8
- package/src/lib/icons/delete-icon.d.ts +0 -2
- package/src/lib/icons/delete-icon.js +0 -8
- package/src/lib/icons/excel-icon.d.ts +0 -2
- package/src/lib/icons/excel-icon.js +0 -8
- package/src/lib/icons/unpin-icon.d.ts +0 -2
- package/src/lib/icons/unpin-icon.js +0 -8
- package/src/lib/icons/view-comfortable-icon.js +0 -8
- package/src/lib/icons/view-compact-icon.d.ts +0 -2
- package/src/lib/icons/view-compact-icon.js +0 -8
- package/src/lib/types/export.types.js +0 -2
- package/src/lib/types/index.js +0 -8
- package/src/lib/utils/export-utils.js +0 -175
- package/src/lib/utils/index.js +0 -11
- package/src/lib/utils/styling-helpers.js +0 -70
- package/tsconfig.tsbuildinfo +0 -1
- /package/{src → dist}/lib/icons/index.js +0 -0
- /package/{src → dist}/lib/types/column.types.js +0 -0
- /package/{src → dist}/lib/types/data-table-api.js +0 -0
- /package/{src/lib/components/table → dist/lib/types}/data-table.types.js +0 -0
- /package/{src → dist}/lib/types/slots.types.js +0 -0
- /package/{src → dist}/lib/types/table.types.js +0 -0
- /package/src/lib/icons/{index.d.ts → index.ts} +0 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Slots and SlotProps Type System for DataTable
|
|
3
|
+
*
|
|
4
|
+
* This file defines all available slots and their corresponding prop types,
|
|
5
|
+
* following the MUI DataGrid pattern for maximum flexibility and extensibility.
|
|
6
|
+
*
|
|
7
|
+
* Key improvements:
|
|
8
|
+
* - Full component props inheritance without limitations
|
|
9
|
+
* - Better type safety with generic support
|
|
10
|
+
* - Flexible prop merging and overriding
|
|
11
|
+
* - Support for custom styling and behavior
|
|
12
|
+
*/
|
|
13
|
+
import { TableProps, TableContainerProps, BoxProps, ToolbarProps, TableRowProps, TableCellProps, TableHeadProps, TableBodyProps } from '@mui/material';
|
|
14
|
+
import { Table, Row, Column } from '@tanstack/react-table';
|
|
15
|
+
import { ComponentType, ReactNode, HTMLAttributes, ComponentProps } from 'react';
|
|
16
|
+
|
|
17
|
+
import { DataTableColumn, TableFilters, ExportProgress, ExportResult, ExportError, ServerExportColumn } from './index';
|
|
18
|
+
import { DataTableSize } from '../utils/table-helpers';
|
|
19
|
+
import { DataTablePaginationProps } from "../components/pagination";
|
|
20
|
+
import { DataTableToolbarProps } from '../components/toolbar/data-table-toolbar';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Enhanced slot component type that supports full component customization
|
|
24
|
+
*/
|
|
25
|
+
export type SlotComponent<TProps = any> = ComponentType<TProps>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Base slot props interface that includes common props for all slots
|
|
29
|
+
*/
|
|
30
|
+
export interface BaseSlotProps<T = any> {
|
|
31
|
+
table: Table<T>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Enhanced slot props that merge base props with component-specific props
|
|
36
|
+
*/
|
|
37
|
+
export type EnhancedSlotProps<TBase, TComponent> = TBase & TComponent & {
|
|
38
|
+
// Allow any additional props for maximum flexibility
|
|
39
|
+
[key: string]: any;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Available slots for customization with enhanced typing
|
|
44
|
+
*/
|
|
45
|
+
export interface DataTableSlots<T = any> {
|
|
46
|
+
// Container and wrapper slots
|
|
47
|
+
root?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, BoxProps & { children: ReactNode }>>;
|
|
48
|
+
tableContainer?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, TableContainerProps & {
|
|
49
|
+
children: ReactNode;
|
|
50
|
+
enableStickyHeader?: boolean;
|
|
51
|
+
maxHeight?: string | number;
|
|
52
|
+
enableVirtualization?: boolean;
|
|
53
|
+
}>>;
|
|
54
|
+
table?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, TableProps & {
|
|
55
|
+
children: ReactNode;
|
|
56
|
+
tableSize?: DataTableSize;
|
|
57
|
+
enableStickyHeader?: boolean;
|
|
58
|
+
fitToScreen?: boolean;
|
|
59
|
+
tableStyle?: React.CSSProperties;
|
|
60
|
+
}>>;
|
|
61
|
+
|
|
62
|
+
// Header slots
|
|
63
|
+
toolbar?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, ToolbarProps & DataTableToolbarProps & {
|
|
64
|
+
title?: string;
|
|
65
|
+
subtitle?: string;
|
|
66
|
+
enableGlobalFilter?: boolean;
|
|
67
|
+
enableColumnVisibility?: boolean;
|
|
68
|
+
enableColumnFilter?: boolean;
|
|
69
|
+
enableExport?: boolean;
|
|
70
|
+
enableReset?: boolean;
|
|
71
|
+
enableTableSizeControl?: boolean;
|
|
72
|
+
enableColumnPinning?: boolean;
|
|
73
|
+
extraFilter?: ReactNode;
|
|
74
|
+
serverExport?: {
|
|
75
|
+
fetchData: (page: number, pageSize: number, filters: TableFilters) => Promise<{ data: T[]; total: number }>;
|
|
76
|
+
columns: ServerExportColumn<T>[];
|
|
77
|
+
pageSize?: number;
|
|
78
|
+
};
|
|
79
|
+
currentFilters?: TableFilters;
|
|
80
|
+
onExportStart?: (format: 'csv' | 'excel', summary: { mode: 'client' | 'server'; totalRows: number; estimatedMemoryMB?: number }) => void;
|
|
81
|
+
onExportProgress?: (progress: ExportProgress) => void;
|
|
82
|
+
onExportComplete?: (result: ExportResult) => void;
|
|
83
|
+
onExportError?: (error: ExportError) => void;
|
|
84
|
+
onExportCancel?: () => void;
|
|
85
|
+
}>>;
|
|
86
|
+
|
|
87
|
+
header?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, TableHeadProps & {
|
|
88
|
+
enableSorting?: boolean;
|
|
89
|
+
draggable?: boolean;
|
|
90
|
+
enableColumnResizing?: boolean;
|
|
91
|
+
enableStickyHeader?: boolean;
|
|
92
|
+
fitToScreen?: boolean;
|
|
93
|
+
onColumnReorder?: (draggedColumnId: string, targetColumnId: string) => void;
|
|
94
|
+
}>>;
|
|
95
|
+
|
|
96
|
+
headerRow?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, TableRowProps & {
|
|
97
|
+
headerGroups: any[];
|
|
98
|
+
}>>;
|
|
99
|
+
|
|
100
|
+
headerCell?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, TableCellProps & {
|
|
101
|
+
header: any;
|
|
102
|
+
column: Column<T>;
|
|
103
|
+
enableSorting?: boolean;
|
|
104
|
+
draggable?: boolean;
|
|
105
|
+
enableColumnResizing?: boolean;
|
|
106
|
+
onColumnReorder?: (draggedColumnId: string, targetColumnId: string) => void;
|
|
107
|
+
isPinned?: boolean | 'left' | 'right';
|
|
108
|
+
pinnedPosition?: number;
|
|
109
|
+
pinnedRightPosition?: number;
|
|
110
|
+
}>>;
|
|
111
|
+
|
|
112
|
+
// Icon slots with full component props
|
|
113
|
+
sortIconAsc?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
114
|
+
sortIconDesc?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
115
|
+
|
|
116
|
+
// Body slots
|
|
117
|
+
body?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, TableBodyProps & {
|
|
118
|
+
children: ReactNode;
|
|
119
|
+
rows: Row<T>[];
|
|
120
|
+
loading?: boolean;
|
|
121
|
+
emptyMessage?: string;
|
|
122
|
+
enableVirtualization?: boolean;
|
|
123
|
+
enablePagination?: boolean;
|
|
124
|
+
}>>;
|
|
125
|
+
|
|
126
|
+
row?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, TableRowProps & {
|
|
127
|
+
row: Row<T>;
|
|
128
|
+
index: number;
|
|
129
|
+
enableHover?: boolean;
|
|
130
|
+
enableStripes?: boolean;
|
|
131
|
+
isOdd?: boolean;
|
|
132
|
+
renderSubComponent?: (row: Row<T>) => ReactNode;
|
|
133
|
+
disableStickyHeader?: boolean;
|
|
134
|
+
}>>;
|
|
135
|
+
|
|
136
|
+
cell?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, TableCellProps & {
|
|
137
|
+
row: Row<T>;
|
|
138
|
+
cell: any;
|
|
139
|
+
column: Column<T>;
|
|
140
|
+
value: any;
|
|
141
|
+
isPinned?: boolean | 'left' | 'right';
|
|
142
|
+
pinnedPosition?: number;
|
|
143
|
+
pinnedRightPosition?: number;
|
|
144
|
+
alignment?: 'left' | 'center' | 'right';
|
|
145
|
+
}>>;
|
|
146
|
+
|
|
147
|
+
// Special row slots
|
|
148
|
+
loadingRow?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, TableRowProps & {
|
|
149
|
+
rowCount: number;
|
|
150
|
+
colSpan: number;
|
|
151
|
+
}>>;
|
|
152
|
+
|
|
153
|
+
emptyRow?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, TableRowProps & {
|
|
154
|
+
colSpan: number;
|
|
155
|
+
message: string;
|
|
156
|
+
}>>;
|
|
157
|
+
|
|
158
|
+
expandedRow?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, TableRowProps & {
|
|
159
|
+
row: Row<T>;
|
|
160
|
+
colSpan: number;
|
|
161
|
+
children: ReactNode;
|
|
162
|
+
}>>;
|
|
163
|
+
|
|
164
|
+
// Footer slots
|
|
165
|
+
footer?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, BoxProps & {
|
|
166
|
+
children: ReactNode;
|
|
167
|
+
enableStickyFooter?: boolean;
|
|
168
|
+
}>>;
|
|
169
|
+
|
|
170
|
+
pagination?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, DataTablePaginationProps>>;
|
|
171
|
+
|
|
172
|
+
// Toolbar component slots with full component inheritance
|
|
173
|
+
searchInput?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, ComponentProps<'input'> & {
|
|
174
|
+
value: string;
|
|
175
|
+
onChange: (value: string) => void;
|
|
176
|
+
placeholder?: string;
|
|
177
|
+
autoFocus?: boolean;
|
|
178
|
+
}>>;
|
|
179
|
+
|
|
180
|
+
columnVisibilityControl?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, HTMLAttributes<HTMLDivElement>>>;
|
|
181
|
+
columnCustomFilterControl?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, HTMLAttributes<HTMLDivElement>>>;
|
|
182
|
+
columnPinningControl?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, HTMLAttributes<HTMLDivElement>>>;
|
|
183
|
+
resetButton?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, ComponentProps<'button'>>>;
|
|
184
|
+
tableSizeControl?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, HTMLAttributes<HTMLDivElement>>>;
|
|
185
|
+
|
|
186
|
+
// Bulk action slots
|
|
187
|
+
bulkActionsToolbar?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, ToolbarProps & {
|
|
188
|
+
selectionState: any;
|
|
189
|
+
selectedRowCount: number;
|
|
190
|
+
bulkActions?: (selectionState: any) => ReactNode;
|
|
191
|
+
onBulkAction?: (action: string, selectionState: T[]) => void;
|
|
192
|
+
enableSelectAll?: boolean;
|
|
193
|
+
onSelectAll?: () => void;
|
|
194
|
+
onDeselectAll?: () => void;
|
|
195
|
+
}>>;
|
|
196
|
+
|
|
197
|
+
exportButton?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, ComponentProps<'button'> & {
|
|
198
|
+
filename?: string;
|
|
199
|
+
dataMode?: 'client' | 'server';
|
|
200
|
+
serverExport?: {
|
|
201
|
+
fetchData: (page: number, pageSize: number, filters: TableFilters) => Promise<{ data: T[]; total: number }>;
|
|
202
|
+
columns: ServerExportColumn<T>[];
|
|
203
|
+
pageSize?: number;
|
|
204
|
+
};
|
|
205
|
+
currentFilters?: TableFilters;
|
|
206
|
+
onExportStart?: (format: 'csv' | 'excel', summary: { mode: 'client' | 'server'; totalRows: number; estimatedMemoryMB?: number }) => void;
|
|
207
|
+
onExportProgress?: (progress: ExportProgress) => void;
|
|
208
|
+
onExportComplete?: (result: ExportResult) => void;
|
|
209
|
+
onExportError?: (error: ExportError) => void;
|
|
210
|
+
onExportCancel?: () => void;
|
|
211
|
+
}>>;
|
|
212
|
+
|
|
213
|
+
// Icon slots with full SVG component props
|
|
214
|
+
searchIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
215
|
+
clearIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
216
|
+
exportIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
217
|
+
columnIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
218
|
+
resetIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
219
|
+
moreIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
220
|
+
filterIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
221
|
+
pinIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
222
|
+
unpinIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
223
|
+
leftIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
224
|
+
rightIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
225
|
+
csvIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
226
|
+
excelIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
227
|
+
selectAllIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
228
|
+
deselectIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
229
|
+
tableSizeIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
230
|
+
tableSizeSmallIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
231
|
+
tableSizeMediumIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
232
|
+
|
|
233
|
+
// Selection slots
|
|
234
|
+
checkboxSelection?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, ComponentProps<'input'> & {
|
|
235
|
+
row?: Row<T>;
|
|
236
|
+
checked: boolean;
|
|
237
|
+
indeterminate?: boolean;
|
|
238
|
+
onChange: (checked: boolean) => void;
|
|
239
|
+
disabled?: boolean;
|
|
240
|
+
}>>;
|
|
241
|
+
|
|
242
|
+
// Expansion slots
|
|
243
|
+
expandIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
244
|
+
collapseIcon?: SlotComponent<ComponentProps<'svg'> & { [key: string]: any }>;
|
|
245
|
+
|
|
246
|
+
// Loading and empty state slots
|
|
247
|
+
loadingSkeleton?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, HTMLAttributes<HTMLDivElement> & {
|
|
248
|
+
rows: number;
|
|
249
|
+
columns: number;
|
|
250
|
+
}>>;
|
|
251
|
+
|
|
252
|
+
noDataOverlay?: SlotComponent<EnhancedSlotProps<BaseSlotProps<T>, HTMLAttributes<HTMLDivElement> & {
|
|
253
|
+
message: string;
|
|
254
|
+
}>>;
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
// Special column slots
|
|
259
|
+
selectionColumn?: DataTableColumn<T>;
|
|
260
|
+
expandColumn?: DataTableColumn<T>;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Enhanced slot props type that allows full customization
|
|
265
|
+
*/
|
|
266
|
+
export type DataTableSlotProps<T = any> = {
|
|
267
|
+
[K in keyof DataTableSlots<T>]?: Record<string, any>;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Columns panel props for slot customization
|
|
272
|
+
*/
|
|
273
|
+
export interface ColumnsPanelSlotProps<T = any> {
|
|
274
|
+
getTogglableColumns?: (columns: DataTableColumn<T>[]) => DataTableColumn<T>[];
|
|
275
|
+
getPinnableColumns?: (columns: DataTableColumn<T>[]) => DataTableColumn<T>[];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Utility type to make all slot props optional for easier usage
|
|
280
|
+
*/
|
|
281
|
+
export type PartialSlotProps<T = any> = {
|
|
282
|
+
[K in keyof DataTableSlotProps<T>]?: Partial<DataTableSlotProps<T>[K]>;
|
|
283
|
+
} & {
|
|
284
|
+
// Special props for columns panel
|
|
285
|
+
columnsPanel?: ColumnsPanelSlotProps<T>;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Utility type for slot component props with proper generic support
|
|
290
|
+
*/
|
|
291
|
+
export type SlotComponentProps<
|
|
292
|
+
TSlot extends keyof DataTableSlots<T>,
|
|
293
|
+
T = any
|
|
294
|
+
> = DataTableSlots<T>[TSlot] extends SlotComponent<infer TProps> ? TProps : never;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Helper type to extract component props from a slot
|
|
298
|
+
*/
|
|
299
|
+
export type ExtractSlotProps<TSlot> = TSlot extends SlotComponent<infer TProps> ? TProps : never;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Default slot components - can be overridden by users
|
|
303
|
+
*/
|
|
304
|
+
// export interface DefaultSlots<T = any> extends DataTableSlots<T> {
|
|
305
|
+
// // All slots should have default implementations
|
|
306
|
+
// }
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Enhanced slot configuration with better prop merging
|
|
310
|
+
*/
|
|
311
|
+
export interface SlotConfiguration<T = any> {
|
|
312
|
+
slots?: Partial<DataTableSlots<T>>;
|
|
313
|
+
slotProps?: PartialSlotProps<T>;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Slot override configuration for advanced customization
|
|
318
|
+
*/
|
|
319
|
+
export interface SlotOverrideConfig<T = any> {
|
|
320
|
+
// Override specific slot behavior
|
|
321
|
+
overrideSlot?: <K extends keyof DataTableSlots<T>>(
|
|
322
|
+
slotName: K,
|
|
323
|
+
component: DataTableSlots<T>[K],
|
|
324
|
+
props?: Partial<SlotComponentProps<K, T>>
|
|
325
|
+
) => void;
|
|
326
|
+
|
|
327
|
+
// Merge props with existing slot props
|
|
328
|
+
mergeSlotProps?: <K extends keyof DataTableSlots<T>>(
|
|
329
|
+
slotName: K,
|
|
330
|
+
props: Partial<SlotComponentProps<K, T>>
|
|
331
|
+
) => Partial<SlotComponentProps<K, T>>;
|
|
332
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { SortingState } from '@tanstack/react-table';
|
|
2
|
+
|
|
3
|
+
import { ColumnFilterRule, SelectionState } from '../features';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Table State and Configuration Types
|
|
8
|
+
* Consolidated table-related interfaces from data-table.types.ts
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Table filters configuration
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export type TableSize = 'small' | 'medium';
|
|
16
|
+
|
|
17
|
+
// Extended table state interface with custom column filter support
|
|
18
|
+
|
|
19
|
+
export interface TableState {
|
|
20
|
+
columnFilter: ColumnFilterState;
|
|
21
|
+
selectionState?: SelectionState; // Selection state for CustomSelectionFeature
|
|
22
|
+
globalFilter?: string;
|
|
23
|
+
sorting?: SortingState;
|
|
24
|
+
pagination?: {
|
|
25
|
+
pageIndex: number;
|
|
26
|
+
pageSize: number;
|
|
27
|
+
};
|
|
28
|
+
columnOrder?: string[];
|
|
29
|
+
columnPinning?: {
|
|
30
|
+
left?: string[];
|
|
31
|
+
right?: string[];
|
|
32
|
+
};
|
|
33
|
+
columnVisibility?: Record<string, boolean>;
|
|
34
|
+
columnSizing?: Record<string, number>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface TableFilters {
|
|
38
|
+
globalFilter: string;
|
|
39
|
+
columnFilter: ColumnFilterState;
|
|
40
|
+
sorting: SortingState;
|
|
41
|
+
pagination: {
|
|
42
|
+
pageIndex: number;
|
|
43
|
+
pageSize: number;
|
|
44
|
+
};
|
|
45
|
+
columnOrder: string[];
|
|
46
|
+
columnPinning: {
|
|
47
|
+
left?: string[];
|
|
48
|
+
right?: string[];
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface TableFiltersForFetch {
|
|
53
|
+
search?: string;
|
|
54
|
+
page?: number;
|
|
55
|
+
pageSize?: number;
|
|
56
|
+
sorting?: SortingState;
|
|
57
|
+
columnFilter?: ColumnFilterState;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface ColumnFilterState {
|
|
61
|
+
filters: ColumnFilterRule[];
|
|
62
|
+
logic: 'AND' | 'OR';
|
|
63
|
+
// Add pending state for draft filters before applying
|
|
64
|
+
pendingFilters: ColumnFilterRule[];
|
|
65
|
+
pendingLogic: 'AND' | 'OR';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Table performance metrics
|
|
70
|
+
*/
|
|
71
|
+
export interface TablePerformanceMetrics {
|
|
72
|
+
renderTime: number;
|
|
73
|
+
dataProcessingTime: number;
|
|
74
|
+
totalRows: number;
|
|
75
|
+
visibleRows: number;
|
|
76
|
+
memoryUsage?: number;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Table metrics for debugging and optimization
|
|
81
|
+
*/
|
|
82
|
+
export interface TableMetrics {
|
|
83
|
+
totalRows: number;
|
|
84
|
+
visibleRows: number;
|
|
85
|
+
totalColumns?: number;
|
|
86
|
+
visibleColumns?: number;
|
|
87
|
+
pinnedColumns?: number;
|
|
88
|
+
renderTime: number;
|
|
89
|
+
lastUpdated?: Date;
|
|
90
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Column utilities for DataTable components
|
|
3
|
+
*/
|
|
4
|
+
import { Column, ColumnDef } from "@tanstack/react-table";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export type ColumnType = 'text' | 'number' | 'date' | 'boolean' | 'select' | 'actions';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Get the type of a column from its metadata
|
|
11
|
+
*/
|
|
12
|
+
export function getColumnType(column: Column<any, unknown>): ColumnType {
|
|
13
|
+
// Check if column has explicit type in columnDef
|
|
14
|
+
if (column?.columnDef?.type) {
|
|
15
|
+
return column.columnDef.type;
|
|
16
|
+
}
|
|
17
|
+
return 'text'; // Default to text
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function getCustomFilterComponent(column: Column<any, unknown>): any {
|
|
21
|
+
// Check if column has custom filter component in meta
|
|
22
|
+
return column?.columnDef?.filterComponent || column?.columnDef?.editComponent;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
export function getColumnOptions(column: Column<any, unknown>): any[] {
|
|
27
|
+
// Check if column has explicit options in meta
|
|
28
|
+
if (column?.columnDef?.options) {
|
|
29
|
+
return column?.columnDef.options || [];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Default options for boolean type
|
|
33
|
+
const columnType = getColumnType(column);
|
|
34
|
+
if (columnType === 'boolean') {
|
|
35
|
+
return [
|
|
36
|
+
{
|
|
37
|
+
value: true,
|
|
38
|
+
label: 'Yes',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
value: false,
|
|
42
|
+
label: 'No',
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function withIdsDeep<T>(cols: ColumnDef<T, any>[]): ColumnDef<T, any>[] {
|
|
51
|
+
return cols.map((c, i) => ({
|
|
52
|
+
...c,
|
|
53
|
+
id: c.id ?? (c as any).accessorKey ?? `col_${i}`,
|
|
54
|
+
...(Array.isArray((c as any).columns) && {
|
|
55
|
+
columns: withIdsDeep((c as any).columns)
|
|
56
|
+
}),
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Determine if a column should be filterable
|
|
63
|
+
*/
|
|
64
|
+
export function isColumnFilterable(column: Column<any, unknown>): boolean {
|
|
65
|
+
// Check if column is explicitly marked as filterable
|
|
66
|
+
if (column?.columnDef?.filterable !== undefined) {
|
|
67
|
+
return column?.columnDef?.filterable;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Default to filterable for data columns
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { TableFiltersForFetch } from '../types';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export function useDebouncedFetch<T extends Record<string, any>>(
|
|
7
|
+
onFetchData: ((filters: TableFiltersForFetch) => Promise<{ data: T[]; total: number }>) | undefined,
|
|
8
|
+
delay = 300,
|
|
9
|
+
) {
|
|
10
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
11
|
+
const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
12
|
+
|
|
13
|
+
const debouncedFetch = useCallback(async (filters: TableFiltersForFetch) => {
|
|
14
|
+
if (!onFetchData) return null;
|
|
15
|
+
|
|
16
|
+
// Create a unique key for the current fetch parameters
|
|
17
|
+
// const currentParams = JSON.stringify(filters);
|
|
18
|
+
// Clear existing timer
|
|
19
|
+
if (debounceTimer.current) {
|
|
20
|
+
clearTimeout(debounceTimer.current);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return new Promise<{ data: T[]; total: number } | null>((resolve) => {
|
|
24
|
+
debounceTimer.current = setTimeout(async () => {
|
|
25
|
+
setIsLoading(true);
|
|
26
|
+
try {
|
|
27
|
+
const result = await onFetchData(filters);
|
|
28
|
+
resolve(result);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
// Handle fetch error silently or could be passed to onError callback
|
|
31
|
+
console.error('Error fetching data:', error);
|
|
32
|
+
resolve(null);
|
|
33
|
+
} finally {
|
|
34
|
+
setIsLoading(false);
|
|
35
|
+
}
|
|
36
|
+
}, delay);
|
|
37
|
+
});
|
|
38
|
+
}, [onFetchData, delay]);
|
|
39
|
+
|
|
40
|
+
// Cleanup timer on unmount
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
// Fetch data when dependencies change
|
|
43
|
+
return () => {
|
|
44
|
+
if (debounceTimer.current) {
|
|
45
|
+
clearTimeout(debounceTimer.current);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}, []);
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
debouncedFetch,
|
|
52
|
+
isLoading,
|
|
53
|
+
};
|
|
54
|
+
}
|