@ackplus/react-tanstack-data-table 1.0.35 → 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 +70 -6
- 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 -2
- 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 +427 -143
- 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,285 @@
|
|
|
1
|
+
import { Table } from '@tanstack/react-table';
|
|
2
|
+
import * as XLSX from 'xlsx';
|
|
3
|
+
import { SelectionState } from '../features';
|
|
4
|
+
|
|
5
|
+
// Local types for the utility functions (keep simpler for actual implementation)
|
|
6
|
+
export interface ExportOptions {
|
|
7
|
+
format: 'csv' | 'excel';
|
|
8
|
+
filename: string;
|
|
9
|
+
onProgress?: (progress: { processedRows?: number; totalRows?: number; percentage?: number }) => void;
|
|
10
|
+
onComplete?: (result: { success: boolean; filename: string; totalRows: number }) => void;
|
|
11
|
+
onError?: (error: { message: string; code: string }) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export interface ServerExportOptions extends ExportOptions {
|
|
16
|
+
fetchData: (filters?: any, selection?: SelectionState) => Promise<{ data: any[]; total: number }>;
|
|
17
|
+
currentFilters?: any;
|
|
18
|
+
selection?: SelectionState;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Export data for client-side tables
|
|
23
|
+
* - If rows are selected, export only selected rows
|
|
24
|
+
* - Otherwise export all filtered/visible rows
|
|
25
|
+
* - Only export visible columns
|
|
26
|
+
*/
|
|
27
|
+
export async function exportClientData<TData>(
|
|
28
|
+
table: Table<TData>,
|
|
29
|
+
options: ExportOptions,
|
|
30
|
+
): Promise<void> {
|
|
31
|
+
const { format, filename, onProgress, onComplete, onError } = options;
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
// Get selected rows if any are selected
|
|
35
|
+
// const selectedRowIds = Object.keys(table.getState().rowSelection).filter(
|
|
36
|
+
// key => table.getState().rowSelection[key]
|
|
37
|
+
// );
|
|
38
|
+
|
|
39
|
+
// const hasSelectedRows = selectedRowIds.length > 0;
|
|
40
|
+
|
|
41
|
+
// // Get the rows to export
|
|
42
|
+
// const rowsToExport = hasSelectedRows ? table.getSelectedRowModel().rows : table.getFilteredRowModel().rows;
|
|
43
|
+
|
|
44
|
+
const selectedRows = table.getSelectedRows ? table.getSelectedRows() : [];
|
|
45
|
+
const hasSelectedRows = selectedRows.length > 0;
|
|
46
|
+
const rowsToExport = hasSelectedRows ? selectedRows : table.getFilteredRowModel().rows;
|
|
47
|
+
// Prepare data for export - get all visible columns and their values, excluding hideInExport columns
|
|
48
|
+
const exportData = rowsToExport.map((row, index) => {
|
|
49
|
+
onProgress?.({
|
|
50
|
+
processedRows: index + 1,
|
|
51
|
+
totalRows: rowsToExport.length,
|
|
52
|
+
percentage: Math.round(((index + 1) / rowsToExport.length) * 100),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const rowData: Record<string, any> = {};
|
|
56
|
+
|
|
57
|
+
// Get all visible cells for this row, excluding columns marked as hideInExport
|
|
58
|
+
row.getVisibleCells().forEach(cell => {
|
|
59
|
+
const columnDef = cell.column.columnDef
|
|
60
|
+
|
|
61
|
+
// Skip columns marked as hideInExport
|
|
62
|
+
if (columnDef.hideInExport === true) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const header = typeof columnDef.header === 'string' ? columnDef.header : cell.column.id;
|
|
67
|
+
|
|
68
|
+
// Use getValue() - it already handles all formatting
|
|
69
|
+
rowData[header] = cell.getValue() || '';
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
return rowData;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Export the data
|
|
76
|
+
await exportToFile(exportData, format, filename);
|
|
77
|
+
|
|
78
|
+
onComplete?.({
|
|
79
|
+
success: true,
|
|
80
|
+
filename: `${filename}.${format === 'excel' ? 'xlsx' : 'csv'}`,
|
|
81
|
+
totalRows: exportData.length,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error('Client export failed:', error);
|
|
86
|
+
onError?.({
|
|
87
|
+
message: error instanceof Error ? error.message : 'Export failed',
|
|
88
|
+
code: 'CLIENT_EXPORT_ERROR',
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Export data for server-side tables
|
|
95
|
+
* - Fetch data using provided fetchData function
|
|
96
|
+
* - Pass selection information to server for filtering
|
|
97
|
+
* - Export all returned data (server handles selection/filtering)
|
|
98
|
+
*/
|
|
99
|
+
export async function exportServerData<TData>(
|
|
100
|
+
table: Table<TData>,
|
|
101
|
+
options: ServerExportOptions,
|
|
102
|
+
): Promise<void> {
|
|
103
|
+
const { format, filename, fetchData, currentFilters, selection, onProgress, onComplete, onError } = options;
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
// Initial progress
|
|
107
|
+
onProgress?.({ });
|
|
108
|
+
|
|
109
|
+
// First, get total count to determine if we need chunking
|
|
110
|
+
const initialResponse = await fetchData({
|
|
111
|
+
...currentFilters,
|
|
112
|
+
pagination: { pageIndex: 0, pageSize: 1 }
|
|
113
|
+
}, selection);
|
|
114
|
+
|
|
115
|
+
if (!initialResponse || !initialResponse.data || !Array.isArray(initialResponse.data)) {
|
|
116
|
+
throw new Error('Invalid data received from server');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const totalRows = initialResponse.total || initialResponse.data.length;
|
|
120
|
+
const CHUNK_SIZE = 1000; // Fetch 1000 rows per request
|
|
121
|
+
const needsChunking = totalRows > CHUNK_SIZE;
|
|
122
|
+
|
|
123
|
+
let allData: TData[] = [];
|
|
124
|
+
|
|
125
|
+
if (needsChunking) {
|
|
126
|
+
// Fetch data in chunks (no progress events during fetching)
|
|
127
|
+
const totalPages = Math.ceil(totalRows / CHUNK_SIZE);
|
|
128
|
+
|
|
129
|
+
for (let page = 1; page <= totalPages; page++) {
|
|
130
|
+
// Fetch current chunk
|
|
131
|
+
const chunkFilters = {
|
|
132
|
+
...currentFilters,
|
|
133
|
+
pagination: {
|
|
134
|
+
pageIndex: page - 1,
|
|
135
|
+
pageSize: CHUNK_SIZE,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const chunkResponse = await fetchData(chunkFilters, selection);
|
|
140
|
+
|
|
141
|
+
if (!chunkResponse || !chunkResponse.data || !Array.isArray(chunkResponse.data)) {
|
|
142
|
+
throw new Error(`Failed to fetch chunk ${page}`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
allData = [...allData, ...chunkResponse.data];
|
|
146
|
+
|
|
147
|
+
// Small delay to prevent overwhelming the server
|
|
148
|
+
if (page < totalPages) {
|
|
149
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
// Small dataset, use single request
|
|
154
|
+
allData = initialResponse.data;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Get visible columns for proper headers and data processing, excluding hideInExport columns
|
|
158
|
+
const visibleColumns = table.getVisibleLeafColumns().filter(col => {
|
|
159
|
+
const columnDef = col.columnDef;
|
|
160
|
+
return col.getIsVisible() && columnDef.hideInExport !== true;
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Prepare data for export with proper column processing
|
|
164
|
+
const exportData: Record<string, any>[] = [];
|
|
165
|
+
|
|
166
|
+
for (let index = 0; index < allData.length; index++) {
|
|
167
|
+
const rowData = allData[index];
|
|
168
|
+
|
|
169
|
+
const exportRow: Record<string, any> = {};
|
|
170
|
+
|
|
171
|
+
visibleColumns.forEach(column => {
|
|
172
|
+
const columnId = column.id;
|
|
173
|
+
const columnDef = column.columnDef;
|
|
174
|
+
const header = typeof columnDef.header === 'string'
|
|
175
|
+
? columnDef.header
|
|
176
|
+
: columnId;
|
|
177
|
+
|
|
178
|
+
// Get value from raw data
|
|
179
|
+
let value = rowData[columnId];
|
|
180
|
+
|
|
181
|
+
// Apply accessorFn if defined
|
|
182
|
+
if (column.accessorFn && typeof column.accessorFn === 'function') {
|
|
183
|
+
value = (column.accessorFn(rowData, index) || '')?.toString() || '';
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Convert to string for export
|
|
187
|
+
if (value === null || value === undefined) {
|
|
188
|
+
value = '';
|
|
189
|
+
} else if (typeof value === 'object') {
|
|
190
|
+
value = JSON.stringify(value);
|
|
191
|
+
} else {
|
|
192
|
+
value = String(value);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
exportRow[header] = value;
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
exportData.push(exportRow);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
await exportToFile(exportData, format, filename);
|
|
202
|
+
|
|
203
|
+
onComplete?.({
|
|
204
|
+
success: true,
|
|
205
|
+
filename: `${filename}.${format === 'excel' ? 'xlsx' : 'csv'}`,
|
|
206
|
+
totalRows: exportData.length,
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error('Server export failed:', error);
|
|
211
|
+
onError?.({
|
|
212
|
+
message: error instanceof Error ? error.message : 'Export failed',
|
|
213
|
+
code: 'SERVER_EXPORT_ERROR',
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Export data to file (CSV or Excel)
|
|
220
|
+
*/
|
|
221
|
+
async function exportToFile(
|
|
222
|
+
data: Record<string, any>[],
|
|
223
|
+
format: 'csv' | 'excel',
|
|
224
|
+
filename: string,
|
|
225
|
+
): Promise<void> {
|
|
226
|
+
if (data.length === 0) {
|
|
227
|
+
throw new Error('No data to export');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (format === 'csv') {
|
|
231
|
+
const csv = convertToCSV(data);
|
|
232
|
+
downloadFile(csv, `${filename}.csv`, 'text/csv');
|
|
233
|
+
} else {
|
|
234
|
+
const workbook = XLSX.utils.book_new();
|
|
235
|
+
const worksheet = XLSX.utils.json_to_sheet(data);
|
|
236
|
+
XLSX.utils.book_append_sheet(workbook, worksheet, 'Data');
|
|
237
|
+
|
|
238
|
+
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
|
|
239
|
+
const blob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
|
240
|
+
downloadFile(blob, `${filename}.xlsx`, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Convert data to CSV format
|
|
246
|
+
*/
|
|
247
|
+
function convertToCSV(data: Record<string, any>[]): string {
|
|
248
|
+
if (data.length === 0) return '';
|
|
249
|
+
|
|
250
|
+
const headers = Object.keys(data[0]);
|
|
251
|
+
const csvRows = [headers.join(',')];
|
|
252
|
+
|
|
253
|
+
for (const row of data) {
|
|
254
|
+
const values = headers.map(header => {
|
|
255
|
+
const value = row[header] || '';
|
|
256
|
+
// Escape quotes and wrap in quotes if contains comma or quote
|
|
257
|
+
if (typeof value === 'string' && (value.includes(',') || value.includes('"') || value.includes('\n'))) {
|
|
258
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
259
|
+
}
|
|
260
|
+
return value;
|
|
261
|
+
});
|
|
262
|
+
csvRows.push(values.join(','));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return csvRows.join('\n');
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Download file to user's device
|
|
270
|
+
*/
|
|
271
|
+
function downloadFile(content: string | Blob, filename: string, mimeType: string): void {
|
|
272
|
+
const blob = content instanceof Blob ? content : new Blob([content], { type: mimeType });
|
|
273
|
+
const url = URL.createObjectURL(blob);
|
|
274
|
+
|
|
275
|
+
const link = document.createElement('a');
|
|
276
|
+
link.href = url;
|
|
277
|
+
link.download = filename;
|
|
278
|
+
link.style.display = 'none';
|
|
279
|
+
|
|
280
|
+
document.body.appendChild(link);
|
|
281
|
+
link.click();
|
|
282
|
+
document.body.removeChild(link);
|
|
283
|
+
|
|
284
|
+
URL.revokeObjectURL(url);
|
|
285
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for DataTable components
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Styling utilities
|
|
6
|
+
export * from './styling-helpers';
|
|
7
|
+
|
|
8
|
+
// Table utilities
|
|
9
|
+
export * from './table-helpers';
|
|
10
|
+
|
|
11
|
+
// Column utilities
|
|
12
|
+
export * from './column-helpers';
|
|
13
|
+
|
|
14
|
+
// Export utilities
|
|
15
|
+
export * from './export-utils';
|
|
16
|
+
|
|
17
|
+
// Special columns utilities
|
|
18
|
+
export * from './special-columns.utils';
|
|
19
|
+
|
|
20
|
+
// Debounced fetch utilities
|
|
21
|
+
export * from './debounced-fetch.utils';
|
|
22
|
+
|
|
23
|
+
// Slot helper utilities
|
|
24
|
+
export * from './slot-helpers';
|
|
25
|
+
|
|
26
|
+
// Logging utilities
|
|
27
|
+
export * from './logger';
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging utilities for the DataTable package.
|
|
3
|
+
*
|
|
4
|
+
* Provides a lightweight wrapper around `console` that can be configured globally
|
|
5
|
+
* or per-instance to help troubleshoot behaviour in consuming applications.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
|
|
9
|
+
|
|
10
|
+
interface ConsoleLike {
|
|
11
|
+
debug?: (...args: unknown[]) => void;
|
|
12
|
+
info?: (...args: unknown[]) => void;
|
|
13
|
+
warn?: (...args: unknown[]) => void;
|
|
14
|
+
error?: (...args: unknown[]) => void;
|
|
15
|
+
log?: (...args: unknown[]) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface DataTableLoggingOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Whether logging should be enabled.
|
|
21
|
+
*/
|
|
22
|
+
enabled?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Minimum level that will be emitted. Defaults to `warn`.
|
|
25
|
+
*/
|
|
26
|
+
level?: LogLevel;
|
|
27
|
+
/**
|
|
28
|
+
* Prefix prepended to every log message. Defaults to `DataTable`.
|
|
29
|
+
*/
|
|
30
|
+
prefix?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Optional scope that will be appended after the prefix when present.
|
|
33
|
+
*/
|
|
34
|
+
scope?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Include an ISO timestamp ahead of each log line.
|
|
37
|
+
*/
|
|
38
|
+
includeTimestamp?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* A custom logger implementation. Defaults to `console`.
|
|
41
|
+
*/
|
|
42
|
+
logger?: ConsoleLike;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type LoggerInput = boolean | DataTableLoggingOptions;
|
|
46
|
+
|
|
47
|
+
type ResolvedLoggerConfig = Required<Omit<DataTableLoggingOptions, 'logger'>> & {
|
|
48
|
+
logger: ConsoleLike;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
type LogMethodLevel = Exclude<LogLevel, 'silent'>;
|
|
52
|
+
|
|
53
|
+
const LOG_LEVEL_ORDER: Record<LogLevel, number> = {
|
|
54
|
+
silent: 0,
|
|
55
|
+
error: 1,
|
|
56
|
+
warn: 2,
|
|
57
|
+
info: 3,
|
|
58
|
+
debug: 4,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const defaultConsole: ConsoleLike = typeof console !== 'undefined'
|
|
62
|
+
? console
|
|
63
|
+
: {
|
|
64
|
+
log: () => undefined,
|
|
65
|
+
debug: () => undefined,
|
|
66
|
+
info: () => undefined,
|
|
67
|
+
warn: () => undefined,
|
|
68
|
+
error: () => undefined,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
let globalConfig: ResolvedLoggerConfig = {
|
|
72
|
+
enabled: false,
|
|
73
|
+
level: 'warn',
|
|
74
|
+
prefix: 'DataTable',
|
|
75
|
+
scope: '',
|
|
76
|
+
includeTimestamp: false,
|
|
77
|
+
logger: defaultConsole,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const isLevelEnabled = (level: LogMethodLevel, config: ResolvedLoggerConfig) => {
|
|
81
|
+
if (!config.enabled) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
return LOG_LEVEL_ORDER[level] <= LOG_LEVEL_ORDER[config.level];
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const formatPrefix = (level: LogMethodLevel, config: ResolvedLoggerConfig) => {
|
|
88
|
+
const segments: string[] = [];
|
|
89
|
+
if (config.prefix) {
|
|
90
|
+
segments.push(config.prefix);
|
|
91
|
+
}
|
|
92
|
+
if (config.scope) {
|
|
93
|
+
segments.push(config.scope);
|
|
94
|
+
}
|
|
95
|
+
const prefix = segments.length > 0 ? `[${segments.join(':')}]` : '';
|
|
96
|
+
return config.includeTimestamp
|
|
97
|
+
? `[${new Date().toISOString()}]${prefix ? ` ${prefix}` : ''} [${level.toUpperCase()}]`
|
|
98
|
+
: `${prefix ? `${prefix} ` : ''}[${level.toUpperCase()}]`;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const getConsoleMethod = (level: LogMethodLevel, logger: ConsoleLike) => {
|
|
102
|
+
const methodName = level === 'debug' ? 'debug' : level;
|
|
103
|
+
return logger[methodName] ?? logger.log ?? defaultConsole.log ?? (() => undefined);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const normaliseInput = (input?: LoggerInput): DataTableLoggingOptions => {
|
|
107
|
+
if (typeof input === 'boolean') {
|
|
108
|
+
return { enabled: input };
|
|
109
|
+
}
|
|
110
|
+
return input ?? {};
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const resolveConfig = (
|
|
114
|
+
scope: string | undefined,
|
|
115
|
+
input?: LoggerInput,
|
|
116
|
+
parent?: ResolvedLoggerConfig,
|
|
117
|
+
): ResolvedLoggerConfig => {
|
|
118
|
+
const overrides = normaliseInput(input);
|
|
119
|
+
const base = parent ?? globalConfig;
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
enabled: overrides.enabled ?? base.enabled,
|
|
123
|
+
level: overrides.level ?? base.level,
|
|
124
|
+
prefix: overrides.prefix ?? base.prefix,
|
|
125
|
+
scope: overrides.scope ?? scope ?? base.scope ?? '',
|
|
126
|
+
includeTimestamp: overrides.includeTimestamp ?? base.includeTimestamp,
|
|
127
|
+
logger: overrides.logger ?? base.logger ?? defaultConsole,
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export interface LoggerInstance {
|
|
132
|
+
debug: (...args: unknown[]) => void;
|
|
133
|
+
info: (...args: unknown[]) => void;
|
|
134
|
+
warn: (...args: unknown[]) => void;
|
|
135
|
+
error: (...args: unknown[]) => void;
|
|
136
|
+
/**
|
|
137
|
+
* Create a new logger that inherits configuration and extends the scope.
|
|
138
|
+
*/
|
|
139
|
+
child: (scope: string, overrides?: LoggerInput) => LoggerInstance;
|
|
140
|
+
/**
|
|
141
|
+
* Check whether a level would emit given current configuration.
|
|
142
|
+
*/
|
|
143
|
+
isLevelEnabled: (level: LogMethodLevel) => boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Access the resolved configuration for inspection.
|
|
146
|
+
*/
|
|
147
|
+
config: ResolvedLoggerConfig;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const createLoggerMethods = (config: ResolvedLoggerConfig): Omit<LoggerInstance, 'child' | 'isLevelEnabled' | 'config'> => {
|
|
151
|
+
const logWithLevel = (level: LogMethodLevel) => {
|
|
152
|
+
const consoleMethod = getConsoleMethod(level, config.logger);
|
|
153
|
+
return (...args: unknown[]) => {
|
|
154
|
+
if (!isLevelEnabled(level, config)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const prefix = formatPrefix(level, config);
|
|
158
|
+
consoleMethod(prefix, ...args);
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
debug: logWithLevel('debug'),
|
|
164
|
+
info: logWithLevel('info'),
|
|
165
|
+
warn: logWithLevel('warn'),
|
|
166
|
+
error: logWithLevel('error'),
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Create a new logger instance. Configuration cascades from the global config unless overridden.
|
|
172
|
+
*/
|
|
173
|
+
export const createLogger = (scope?: string, input?: LoggerInput, parentConfig?: ResolvedLoggerConfig): LoggerInstance => {
|
|
174
|
+
const resolvedConfig = resolveConfig(scope, input, parentConfig);
|
|
175
|
+
const methods = createLoggerMethods(resolvedConfig);
|
|
176
|
+
|
|
177
|
+
const child = (childScope: string, overrides?: LoggerInput) => {
|
|
178
|
+
const combinedScope = childScope
|
|
179
|
+
? (resolvedConfig.scope ? `${resolvedConfig.scope}.${childScope}` : childScope)
|
|
180
|
+
: resolvedConfig.scope;
|
|
181
|
+
return createLogger(combinedScope, overrides, resolvedConfig);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
...methods,
|
|
186
|
+
child,
|
|
187
|
+
isLevelEnabled: (level: LogMethodLevel) => isLevelEnabled(level, resolvedConfig),
|
|
188
|
+
config: resolvedConfig,
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Configure the global logger defaults for every DataTable instance.
|
|
194
|
+
*/
|
|
195
|
+
export const configureDataTableLogging = (options: DataTableLoggingOptions) => {
|
|
196
|
+
globalConfig = resolveConfig(options.scope, options, globalConfig);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Read the current global logging configuration.
|
|
201
|
+
*/
|
|
202
|
+
export const getDataTableLoggingConfig = (): ResolvedLoggerConfig => ({ ...globalConfig });
|
|
203
|
+
|