@ackplus/react-tanstack-data-table 1.0.35 → 1.1.3

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.
Files changed (272) hide show
  1. package/LICENSE +21 -0
  2. package/{src → dist}/index.d.ts +21 -4
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +63 -0
  5. package/{src → dist}/lib/components/droupdown/menu-dropdown.d.ts +2 -1
  6. package/dist/lib/components/droupdown/menu-dropdown.d.ts.map +1 -0
  7. package/{src → dist}/lib/components/droupdown/menu-dropdown.js +38 -7
  8. package/{src → dist}/lib/components/filters/filter-value-input.d.ts +3 -1
  9. package/dist/lib/components/filters/filter-value-input.d.ts.map +1 -0
  10. package/dist/lib/components/filters/filter-value-input.js +83 -0
  11. package/{src → dist}/lib/components/filters/index.d.ts +1 -0
  12. package/dist/lib/components/filters/index.d.ts.map +1 -0
  13. package/dist/lib/components/filters/index.js +142 -0
  14. package/{src → dist}/lib/components/headers/draggable-header.d.ts +2 -2
  15. package/dist/lib/components/headers/draggable-header.d.ts.map +1 -0
  16. package/{src → dist}/lib/components/headers/draggable-header.js +81 -17
  17. package/dist/lib/components/headers/index.d.ts +6 -0
  18. package/dist/lib/components/headers/index.d.ts.map +1 -0
  19. package/dist/lib/components/headers/index.js +21 -0
  20. package/{src → dist}/lib/components/headers/table-header.d.ts +15 -1
  21. package/dist/lib/components/headers/table-header.d.ts.map +1 -0
  22. package/{src → dist}/lib/components/headers/table-header.js +50 -17
  23. package/{src → dist}/lib/components/index.d.ts +6 -1
  24. package/dist/lib/components/index.d.ts.map +1 -0
  25. package/dist/lib/components/index.js +32 -0
  26. package/{src → dist}/lib/components/pagination/data-table-pagination.d.ts +2 -1
  27. package/dist/lib/components/pagination/data-table-pagination.d.ts.map +1 -0
  28. package/{src → dist}/lib/components/pagination/data-table-pagination.js +20 -6
  29. package/dist/lib/components/pagination/index.d.ts +5 -0
  30. package/dist/lib/components/pagination/index.d.ts.map +1 -0
  31. package/dist/lib/components/pagination/index.js +20 -0
  32. package/{src → dist}/lib/components/rows/data-table-row.d.ts +15 -2
  33. package/dist/lib/components/rows/data-table-row.d.ts.map +1 -0
  34. package/{src → dist}/lib/components/rows/data-table-row.js +58 -25
  35. package/{src → dist}/lib/components/rows/empty-data-row.d.ts +3 -3
  36. package/dist/lib/components/rows/empty-data-row.d.ts.map +1 -0
  37. package/{src → dist}/lib/components/rows/empty-data-row.js +12 -4
  38. package/dist/lib/components/rows/index.d.ts +7 -0
  39. package/dist/lib/components/rows/index.d.ts.map +1 -0
  40. package/dist/lib/components/rows/index.js +22 -0
  41. package/{src → dist}/lib/components/rows/loading-rows.d.ts +3 -1
  42. package/dist/lib/components/rows/loading-rows.d.ts.map +1 -0
  43. package/{src → dist}/lib/components/rows/loading-rows.js +27 -19
  44. package/{src → dist}/lib/components/toolbar/bulk-actions-toolbar.d.ts +4 -3
  45. package/dist/lib/components/toolbar/bulk-actions-toolbar.d.ts.map +1 -0
  46. package/dist/lib/components/toolbar/bulk-actions-toolbar.js +49 -0
  47. package/{src → dist}/lib/components/toolbar/column-filter-control.d.ts +3 -1
  48. package/dist/lib/components/toolbar/column-filter-control.d.ts.map +1 -0
  49. package/{src → dist}/lib/components/toolbar/column-filter-control.js +73 -4
  50. package/{src → dist}/lib/components/toolbar/column-pinning-control.d.ts +2 -1
  51. package/dist/lib/components/toolbar/column-pinning-control.d.ts.map +1 -0
  52. package/{src → dist}/lib/components/toolbar/column-pinning-control.js +70 -6
  53. package/{src → dist}/lib/components/toolbar/column-reset-control.d.ts +3 -1
  54. package/dist/lib/components/toolbar/column-reset-control.d.ts.map +1 -0
  55. package/{src → dist}/lib/components/toolbar/column-reset-control.js +9 -2
  56. package/{src → dist}/lib/components/toolbar/column-visibility-control.d.ts +2 -1
  57. package/dist/lib/components/toolbar/column-visibility-control.d.ts.map +1 -0
  58. package/dist/lib/components/toolbar/column-visibility-control.js +77 -0
  59. package/{src → dist}/lib/components/toolbar/data-table-toolbar.d.ts +3 -2
  60. package/dist/lib/components/toolbar/data-table-toolbar.d.ts.map +1 -0
  61. package/{src → dist}/lib/components/toolbar/data-table-toolbar.js +17 -4
  62. package/{src → dist}/lib/components/toolbar/index.d.ts +4 -0
  63. package/dist/lib/components/toolbar/index.d.ts.map +1 -0
  64. package/{src → dist}/lib/components/toolbar/index.js +6 -0
  65. package/dist/lib/components/toolbar/table-export-control.d.ts +12 -0
  66. package/dist/lib/components/toolbar/table-export-control.d.ts.map +1 -0
  67. package/dist/lib/components/toolbar/table-export-control.js +67 -0
  68. package/{src → dist}/lib/components/toolbar/table-search-control.d.ts +3 -1
  69. package/dist/lib/components/toolbar/table-search-control.d.ts.map +1 -0
  70. package/{src → dist}/lib/components/toolbar/table-search-control.js +45 -2
  71. package/{src → dist}/lib/components/toolbar/table-size-control.d.ts +3 -1
  72. package/dist/lib/components/toolbar/table-size-control.d.ts.map +1 -0
  73. package/{src → dist}/lib/components/toolbar/table-size-control.js +20 -8
  74. package/{src → dist}/lib/contexts/data-table-context.d.ts +6 -2
  75. package/dist/lib/contexts/data-table-context.d.ts.map +1 -0
  76. package/{src → dist}/lib/contexts/data-table-context.js +34 -1
  77. package/dist/lib/data-table.d.ts +5 -0
  78. package/dist/lib/data-table.d.ts.map +1 -0
  79. package/{src/lib/components/table → dist/lib}/data-table.js +427 -143
  80. package/dist/lib/features/column-filter.feature.d.ts +55 -0
  81. package/dist/lib/features/column-filter.feature.d.ts.map +1 -0
  82. package/{src → dist}/lib/features/column-filter.feature.js +116 -18
  83. package/dist/lib/features/index.d.ts +9 -0
  84. package/dist/lib/features/index.d.ts.map +1 -0
  85. package/{src → dist}/lib/features/index.js +7 -0
  86. package/{src → dist}/lib/features/selection.feature.d.ts +8 -1
  87. package/dist/lib/features/selection.feature.d.ts.map +1 -0
  88. package/{src → dist}/lib/features/selection.feature.js +76 -15
  89. package/dist/lib/icons/add-icon.d.ts +4 -0
  90. package/dist/lib/icons/add-icon.d.ts.map +1 -0
  91. package/dist/lib/icons/add-icon.js +12 -0
  92. package/dist/lib/icons/csv-icon.d.ts +4 -0
  93. package/dist/lib/icons/csv-icon.d.ts.map +1 -0
  94. package/dist/lib/icons/csv-icon.js +12 -0
  95. package/dist/lib/icons/delete-icon.d.ts +4 -0
  96. package/dist/lib/icons/delete-icon.d.ts.map +1 -0
  97. package/dist/lib/icons/delete-icon.js +12 -0
  98. package/dist/lib/icons/excel-icon.d.ts +4 -0
  99. package/dist/lib/icons/excel-icon.d.ts.map +1 -0
  100. package/dist/lib/icons/excel-icon.js +12 -0
  101. package/dist/lib/icons/index.d.ts +8 -0
  102. package/dist/lib/icons/index.d.ts.map +1 -0
  103. package/dist/lib/icons/unpin-icon.d.ts +4 -0
  104. package/dist/lib/icons/unpin-icon.d.ts.map +1 -0
  105. package/dist/lib/icons/unpin-icon.js +12 -0
  106. package/{src → dist}/lib/icons/view-comfortable-icon.d.ts +3 -1
  107. package/dist/lib/icons/view-comfortable-icon.d.ts.map +1 -0
  108. package/dist/lib/icons/view-comfortable-icon.js +12 -0
  109. package/dist/lib/icons/view-compact-icon.d.ts +4 -0
  110. package/dist/lib/icons/view-compact-icon.d.ts.map +1 -0
  111. package/dist/lib/icons/view-compact-icon.js +12 -0
  112. package/{src → dist}/lib/types/column.types.d.ts +10 -1
  113. package/dist/lib/types/column.types.d.ts.map +1 -0
  114. package/{src → dist}/lib/types/data-table-api.d.ts +2 -1
  115. package/dist/lib/types/data-table-api.d.ts.map +1 -0
  116. package/{src/lib/components/table → dist/lib/types}/data-table.types.d.ts +10 -11
  117. package/dist/lib/types/data-table.types.d.ts.map +1 -0
  118. package/{src → dist}/lib/types/export.types.d.ts +38 -0
  119. package/dist/lib/types/export.types.d.ts.map +1 -0
  120. package/dist/lib/types/export.types.js +6 -0
  121. package/{src → dist}/lib/types/index.d.ts +6 -0
  122. package/dist/lib/types/index.d.ts.map +1 -0
  123. package/dist/lib/types/index.js +32 -0
  124. package/{src → dist}/lib/types/slots.types.d.ts +50 -3
  125. package/dist/lib/types/slots.types.d.ts.map +1 -0
  126. package/{src → dist}/lib/types/table.types.d.ts +14 -0
  127. package/dist/lib/types/table.types.d.ts.map +1 -0
  128. package/{src → dist}/lib/utils/column-helpers.d.ts +10 -0
  129. package/dist/lib/utils/column-helpers.d.ts.map +1 -0
  130. package/{src → dist}/lib/utils/column-helpers.js +20 -4
  131. package/{src → dist}/lib/utils/debounced-fetch.utils.d.ts +3 -5
  132. package/dist/lib/utils/debounced-fetch.utils.d.ts.map +1 -0
  133. package/{src → dist}/lib/utils/debounced-fetch.utils.js +12 -6
  134. package/{src → dist}/lib/utils/export-utils.d.ts +13 -0
  135. package/dist/lib/utils/export-utils.d.ts.map +1 -0
  136. package/dist/lib/utils/export-utils.js +252 -0
  137. package/{src → dist}/lib/utils/index.d.ts +4 -0
  138. package/dist/lib/utils/index.d.ts.map +1 -0
  139. package/dist/lib/utils/index.js +35 -0
  140. package/{src → dist}/lib/utils/logger.d.ts +43 -0
  141. package/dist/lib/utils/logger.d.ts.map +1 -0
  142. package/{src → dist}/lib/utils/logger.js +22 -2
  143. package/{src → dist}/lib/utils/slot-helpers.d.ts +39 -1
  144. package/dist/lib/utils/slot-helpers.d.ts.map +1 -0
  145. package/{src → dist}/lib/utils/slot-helpers.js +55 -6
  146. package/{src → dist}/lib/utils/special-columns.utils.d.ts +10 -0
  147. package/dist/lib/utils/special-columns.utils.d.ts.map +1 -0
  148. package/{src → dist}/lib/utils/special-columns.utils.js +41 -5
  149. package/{src → dist}/lib/utils/styling-helpers.d.ts +20 -0
  150. package/dist/lib/utils/styling-helpers.d.ts.map +1 -0
  151. package/dist/lib/utils/styling-helpers.js +108 -0
  152. package/{src → dist}/lib/utils/table-helpers.d.ts +25 -0
  153. package/dist/lib/utils/table-helpers.d.ts.map +1 -0
  154. package/{src → dist}/lib/utils/table-helpers.js +24 -0
  155. package/package.json +36 -11
  156. package/src/index.ts +71 -0
  157. package/src/lib/components/droupdown/menu-dropdown.tsx +97 -0
  158. package/src/lib/components/filters/filter-value-input.tsx +225 -0
  159. package/src/lib/components/filters/{index.js → index.ts} +3 -6
  160. package/src/lib/components/headers/draggable-header.tsx +326 -0
  161. package/src/lib/components/headers/{index.d.ts → index.ts} +4 -0
  162. package/src/lib/components/headers/table-header.tsx +173 -0
  163. package/src/lib/components/index.ts +21 -0
  164. package/src/lib/components/pagination/data-table-pagination.tsx +99 -0
  165. package/src/lib/components/pagination/index.ts +5 -0
  166. package/src/lib/components/rows/data-table-row.tsx +208 -0
  167. package/src/lib/components/rows/empty-data-row.tsx +69 -0
  168. package/src/lib/components/rows/{index.d.ts → index.ts} +4 -0
  169. package/src/lib/components/rows/loading-rows.tsx +160 -0
  170. package/src/lib/components/toolbar/bulk-actions-toolbar.tsx +125 -0
  171. package/src/lib/components/toolbar/column-filter-control.tsx +374 -0
  172. package/src/lib/components/toolbar/column-pinning-control.tsx +275 -0
  173. package/src/lib/components/toolbar/column-reset-control.tsx +74 -0
  174. package/src/lib/components/toolbar/column-visibility-control.tsx +105 -0
  175. package/src/lib/components/toolbar/data-table-toolbar.tsx +229 -0
  176. package/src/lib/components/toolbar/index.ts +17 -0
  177. package/src/lib/components/toolbar/table-export-control.tsx +179 -0
  178. package/src/lib/components/toolbar/table-search-control.tsx +155 -0
  179. package/src/lib/components/toolbar/table-size-control.tsx +102 -0
  180. package/src/lib/contexts/data-table-context.tsx +112 -0
  181. package/src/lib/data-table.tsx +1911 -0
  182. package/src/lib/features/README.md +161 -0
  183. package/src/lib/features/column-filter.feature.ts +456 -0
  184. package/src/lib/features/index.ts +23 -0
  185. package/src/lib/features/selection.feature.ts +318 -0
  186. package/src/lib/icons/add-icon.tsx +23 -0
  187. package/src/lib/icons/csv-icon.tsx +15 -0
  188. package/src/lib/icons/delete-icon.tsx +30 -0
  189. package/src/lib/icons/excel-icon.tsx +15 -0
  190. package/src/lib/icons/unpin-icon.tsx +18 -0
  191. package/src/lib/icons/view-comfortable-icon.tsx +45 -0
  192. package/src/lib/icons/view-compact-icon.tsx +55 -0
  193. package/src/lib/types/column.types.ts +44 -0
  194. package/src/lib/types/data-table-api.ts +169 -0
  195. package/src/lib/types/data-table.types.ts +136 -0
  196. package/src/lib/types/export.types.ts +154 -0
  197. package/src/lib/types/index.ts +24 -0
  198. package/src/lib/types/slots.types.ts +332 -0
  199. package/src/lib/types/table.types.ts +90 -0
  200. package/src/lib/utils/column-helpers.ts +72 -0
  201. package/src/lib/utils/debounced-fetch.utils.ts +54 -0
  202. package/src/lib/utils/export-utils.ts +285 -0
  203. package/src/lib/utils/index.ts +27 -0
  204. package/src/lib/utils/logger.ts +203 -0
  205. package/src/lib/utils/slot-helpers.tsx +194 -0
  206. package/src/lib/utils/special-columns.utils.ts +94 -0
  207. package/src/lib/utils/styling-helpers.ts +126 -0
  208. package/src/lib/utils/table-helpers.ts +106 -0
  209. package/src/index.js +0 -27
  210. package/src/lib/components/filters/filter-value-input.js +0 -41
  211. package/src/lib/components/headers/index.js +0 -5
  212. package/src/lib/components/index.js +0 -10
  213. package/src/lib/components/pagination/index.d.ts +0 -1
  214. package/src/lib/components/pagination/index.js +0 -4
  215. package/src/lib/components/rows/index.js +0 -6
  216. package/src/lib/components/table/data-table.d.ts +0 -4
  217. package/src/lib/components/table/index.d.ts +0 -2
  218. package/src/lib/components/table/index.js +0 -5
  219. package/src/lib/components/toolbar/bulk-actions-toolbar.js +0 -30
  220. package/src/lib/components/toolbar/column-visibility-control.js +0 -31
  221. package/src/lib/components/toolbar/table-export-control.d.ts +0 -31
  222. package/src/lib/components/toolbar/table-export-control.js +0 -56
  223. package/src/lib/examples/advanced-features-example.d.ts +0 -1
  224. package/src/lib/examples/advanced-features-example.js +0 -269
  225. package/src/lib/examples/bulk-actions-test.d.ts +0 -1
  226. package/src/lib/examples/bulk-actions-test.js +0 -44
  227. package/src/lib/examples/custom-column-filter-example.d.ts +0 -1
  228. package/src/lib/examples/custom-column-filter-example.js +0 -60
  229. package/src/lib/examples/index.d.ts +0 -8
  230. package/src/lib/examples/index.js +0 -19
  231. package/src/lib/examples/selection-test-example.d.ts +0 -1
  232. package/src/lib/examples/selection-test-example.js +0 -101
  233. package/src/lib/examples/server-side-fetching-example.d.ts +0 -1
  234. package/src/lib/examples/server-side-fetching-example.js +0 -245
  235. package/src/lib/examples/server-side-test.d.ts +0 -1
  236. package/src/lib/examples/server-side-test.js +0 -9
  237. package/src/lib/examples/simple-local-example.d.ts +0 -1
  238. package/src/lib/examples/simple-local-example.js +0 -95
  239. package/src/lib/examples/simple-slots-example.d.ts +0 -1
  240. package/src/lib/examples/simple-slots-example.js +0 -115
  241. package/src/lib/features/column-filter.feature.d.ts +0 -45
  242. package/src/lib/features/index.d.ts +0 -2
  243. package/src/lib/hooks/index.d.ts +0 -1
  244. package/src/lib/hooks/index.js +0 -4
  245. package/src/lib/hooks/use-data-table-api.d.ts +0 -46
  246. package/src/lib/hooks/use-data-table-api.js +0 -690
  247. package/src/lib/icons/add-icon.d.ts +0 -2
  248. package/src/lib/icons/add-icon.js +0 -8
  249. package/src/lib/icons/csv-icon.d.ts +0 -2
  250. package/src/lib/icons/csv-icon.js +0 -8
  251. package/src/lib/icons/delete-icon.d.ts +0 -2
  252. package/src/lib/icons/delete-icon.js +0 -8
  253. package/src/lib/icons/excel-icon.d.ts +0 -2
  254. package/src/lib/icons/excel-icon.js +0 -8
  255. package/src/lib/icons/unpin-icon.d.ts +0 -2
  256. package/src/lib/icons/unpin-icon.js +0 -8
  257. package/src/lib/icons/view-comfortable-icon.js +0 -8
  258. package/src/lib/icons/view-compact-icon.d.ts +0 -2
  259. package/src/lib/icons/view-compact-icon.js +0 -8
  260. package/src/lib/types/export.types.js +0 -2
  261. package/src/lib/types/index.js +0 -8
  262. package/src/lib/utils/export-utils.js +0 -175
  263. package/src/lib/utils/index.js +0 -11
  264. package/src/lib/utils/styling-helpers.js +0 -70
  265. package/tsconfig.tsbuildinfo +0 -1
  266. /package/{src → dist}/lib/icons/index.js +0 -0
  267. /package/{src → dist}/lib/types/column.types.js +0 -0
  268. /package/{src → dist}/lib/types/data-table-api.js +0 -0
  269. /package/{src/lib/components/table → dist/lib/types}/data-table.types.js +0 -0
  270. /package/{src → dist}/lib/types/slots.types.js +0 -0
  271. /package/{src → dist}/lib/types/table.types.js +0 -0
  272. /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
+