@ackplus/react-tanstack-data-table 1.1.16 → 1.1.18

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 (42) hide show
  1. package/README.md +0 -8
  2. package/dist/index.d.ts +4 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +5 -1
  5. package/dist/lib/components/data-table-view.d.ts +7 -0
  6. package/dist/lib/components/data-table-view.d.ts.map +1 -0
  7. package/dist/lib/components/data-table-view.js +151 -0
  8. package/dist/lib/components/toolbar/column-filter-control.d.ts +3 -2
  9. package/dist/lib/components/toolbar/column-filter-control.d.ts.map +1 -1
  10. package/dist/lib/components/toolbar/column-filter-control.js +91 -92
  11. package/dist/lib/components/toolbar/data-table-toolbar.d.ts.map +1 -1
  12. package/dist/lib/components/toolbar/data-table-toolbar.js +14 -1
  13. package/dist/lib/components/toolbar/table-export-control.d.ts.map +1 -1
  14. package/dist/lib/components/toolbar/table-export-control.js +0 -2
  15. package/dist/lib/components/toolbar/table-refresh-control.d.ts.map +1 -1
  16. package/dist/lib/components/toolbar/table-refresh-control.js +3 -1
  17. package/dist/lib/data-table.d.ts +0 -3
  18. package/dist/lib/data-table.d.ts.map +1 -1
  19. package/dist/lib/data-table.js +9 -1638
  20. package/dist/lib/features/column-filter.feature.d.ts +2 -1
  21. package/dist/lib/features/column-filter.feature.d.ts.map +1 -1
  22. package/dist/lib/features/column-filter.feature.js +14 -0
  23. package/dist/lib/hooks/index.d.ts +3 -0
  24. package/dist/lib/hooks/index.d.ts.map +1 -0
  25. package/dist/lib/hooks/index.js +5 -0
  26. package/dist/lib/hooks/use-data-table-engine.d.ts +104 -0
  27. package/dist/lib/hooks/use-data-table-engine.d.ts.map +1 -0
  28. package/dist/lib/hooks/use-data-table-engine.js +964 -0
  29. package/dist/lib/types/data-table.types.d.ts +0 -1
  30. package/dist/lib/types/data-table.types.d.ts.map +1 -1
  31. package/package.json +1 -1
  32. package/src/index.ts +4 -0
  33. package/src/lib/components/data-table-view.tsx +386 -0
  34. package/src/lib/components/toolbar/column-filter-control.tsx +270 -212
  35. package/src/lib/components/toolbar/data-table-toolbar.tsx +15 -1
  36. package/src/lib/components/toolbar/table-export-control.tsx +0 -2
  37. package/src/lib/components/toolbar/table-refresh-control.tsx +11 -7
  38. package/src/lib/data-table.tsx +17 -2183
  39. package/src/lib/features/column-filter.feature.ts +15 -1
  40. package/src/lib/hooks/index.ts +2 -0
  41. package/src/lib/hooks/use-data-table-engine.ts +1285 -0
  42. package/src/lib/types/data-table.types.ts +0 -1
@@ -0,0 +1,964 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useDataTableEngine = useDataTableEngine;
4
+ const react_table_1 = require("@tanstack/react-table");
5
+ const react_virtual_1 = require("@tanstack/react-virtual");
6
+ const styles_1 = require("@mui/material/styles");
7
+ const react_1 = require("react");
8
+ // your features / utils
9
+ const column_filter_feature_1 = require("../features/column-filter.feature");
10
+ const features_1 = require("../features");
11
+ const special_columns_utils_1 = require("../utils/special-columns.utils");
12
+ const utils_1 = require("../utils");
13
+ const debounced_fetch_utils_1 = require("../utils/debounced-fetch.utils");
14
+ const DEFAULT_INITIAL_STATE = {
15
+ sorting: [],
16
+ pagination: { pageIndex: 0, pageSize: 10 },
17
+ selectionState: { ids: [], type: "include" },
18
+ globalFilter: "",
19
+ expanded: {},
20
+ columnOrder: [],
21
+ columnPinning: { left: [], right: [] },
22
+ columnVisibility: {},
23
+ columnSizing: {},
24
+ columnFilter: {
25
+ filters: [],
26
+ logic: "AND",
27
+ pendingFilters: [],
28
+ pendingLogic: "AND",
29
+ },
30
+ };
31
+ function uiReducer(state, action) {
32
+ switch (action.type) {
33
+ case "SET_SORTING_RESET_PAGE":
34
+ return { ...state, sorting: action.payload, pagination: { pageIndex: 0, pageSize: state.pagination.pageSize } };
35
+ case "SET_PAGINATION":
36
+ return { ...state, pagination: action.payload };
37
+ case "SET_GLOBAL_FILTER_RESET_PAGE":
38
+ return { ...state, globalFilter: action.payload, pagination: { pageIndex: 0, pageSize: state.pagination.pageSize } };
39
+ case "SET_SELECTION":
40
+ return { ...state, selectionState: action.payload };
41
+ case "SET_COLUMN_FILTER":
42
+ return { ...state, columnFilter: action.payload };
43
+ case "SET_COLUMN_FILTER_RESET_PAGE":
44
+ return { ...state, columnFilter: action.payload, pagination: { pageIndex: 0, pageSize: state.pagination.pageSize } };
45
+ case "SET_EXPANDED":
46
+ return { ...state, expanded: action.payload };
47
+ case "SET_TABLE_SIZE":
48
+ return { ...state, tableSize: action.payload };
49
+ case "SET_COLUMN_ORDER":
50
+ return { ...state, columnOrder: action.payload };
51
+ case "SET_COLUMN_PINNING":
52
+ return { ...state, columnPinning: action.payload };
53
+ case "SET_COLUMN_VISIBILITY":
54
+ return { ...state, columnVisibility: action.payload };
55
+ case "SET_COLUMN_SIZING":
56
+ return { ...state, columnSizing: action.payload };
57
+ case "RESTORE_LAYOUT":
58
+ return { ...state, ...action.payload };
59
+ case "RESET_ALL":
60
+ return { ...state, ...action.payload };
61
+ default:
62
+ return state;
63
+ }
64
+ }
65
+ function useLatestRef(value) {
66
+ const ref = (0, react_1.useRef)(value);
67
+ (0, react_1.useEffect)(() => {
68
+ ref.current = value;
69
+ }, [value]);
70
+ return ref;
71
+ }
72
+ function useEvent(fn) {
73
+ const fnRef = useLatestRef(fn);
74
+ return (0, react_1.useCallback)(((...args) => fnRef.current(...args)), [fnRef]);
75
+ }
76
+ function useDataTableEngine(props) {
77
+ const { initialState, columns, data = [], totalRow = 0, idKey = "id", dataMode = "client", initialLoadData = true, onFetchData, onFetchStateChange, onDataStateChange, enableRowSelection = false, enableMultiRowSelection = true, selectMode = "page", isRowSelectable, onSelectionChange, enableBulkActions = false, enableColumnResizing = false, columnResizeMode = "onChange", onColumnSizingChange, enableColumnDragging = false, onColumnDragEnd, enableColumnPinning = false, onColumnPinningChange, onColumnVisibilityChange, enableColumnVisibility = true, enableExpanding = false, getRowCanExpand, enablePagination = false, paginationMode = "client", enableGlobalFilter = true, enableColumnFilter = false, filterMode = "client", enableSorting = true, sortingMode = "client", onSortingChange, exportFilename = "export", exportConcurrency = "cancelAndRestart", exportChunkSize = 1000, exportStrictTotalCheck = false, exportSanitizeCSV = true, onExportProgress, onExportComplete, onExportError, onServerExport, onExportCancel, onExportStateChange, fitToScreen = true, tableSize: initialTableSize = "medium", enableVirtualization = false, estimateRowHeight = 52, loading = false, onColumnFiltersChange, onPaginationChange, onGlobalFilterChange, slots = {}, slotProps = {}, } = props;
78
+ const theme = (0, styles_1.useTheme)();
79
+ const isServerMode = dataMode === "server";
80
+ const isServerPagination = paginationMode === "server" || isServerMode;
81
+ const isServerFiltering = filterMode === "server" || isServerMode;
82
+ const isServerSorting = sortingMode === "server" || isServerMode;
83
+ // --- initial config (memo)
84
+ const initialStateConfig = (0, react_1.useMemo)(() => {
85
+ const config = { ...DEFAULT_INITIAL_STATE, ...initialState };
86
+ return config;
87
+ }, [initialState]);
88
+ const initialUIState = (0, react_1.useMemo)(() => {
89
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
90
+ return ({
91
+ sorting: (_a = initialStateConfig.sorting) !== null && _a !== void 0 ? _a : DEFAULT_INITIAL_STATE.sorting,
92
+ pagination: (_b = initialStateConfig.pagination) !== null && _b !== void 0 ? _b : DEFAULT_INITIAL_STATE.pagination,
93
+ globalFilter: (_c = initialStateConfig.globalFilter) !== null && _c !== void 0 ? _c : DEFAULT_INITIAL_STATE.globalFilter,
94
+ selectionState: (_d = initialStateConfig.selectionState) !== null && _d !== void 0 ? _d : DEFAULT_INITIAL_STATE.selectionState,
95
+ columnFilter: (_e = initialStateConfig.columnFilter) !== null && _e !== void 0 ? _e : DEFAULT_INITIAL_STATE.columnFilter,
96
+ expanded: (_f = initialStateConfig.expanded) !== null && _f !== void 0 ? _f : {},
97
+ tableSize: (initialTableSize || "medium"),
98
+ columnOrder: (_g = initialStateConfig.columnOrder) !== null && _g !== void 0 ? _g : DEFAULT_INITIAL_STATE.columnOrder,
99
+ columnPinning: (_h = initialStateConfig.columnPinning) !== null && _h !== void 0 ? _h : DEFAULT_INITIAL_STATE.columnPinning,
100
+ columnVisibility: (_j = initialStateConfig.columnVisibility) !== null && _j !== void 0 ? _j : DEFAULT_INITIAL_STATE.columnVisibility,
101
+ columnSizing: (_k = initialStateConfig.columnSizing) !== null && _k !== void 0 ? _k : DEFAULT_INITIAL_STATE.columnSizing,
102
+ });
103
+ }, [initialStateConfig, initialTableSize]);
104
+ // --- UI state (reducer)
105
+ const [ui, dispatch] = (0, react_1.useReducer)(uiReducer, initialUIState);
106
+ // --- server data state (UI-affecting)
107
+ const [serverData, setServerData] = (0, react_1.useState)(null);
108
+ const [serverTotal, setServerTotal] = (0, react_1.useState)(0);
109
+ // --- export UI state
110
+ const [exportPhase, setExportPhase] = (0, react_1.useState)(null);
111
+ const [exportProgress, setExportProgress] = (0, react_1.useState)({});
112
+ const [exportController, setExportController] = (0, react_1.useState)(null);
113
+ const [queuedExportCount, setQueuedExportCount] = (0, react_1.useState)(0);
114
+ // --- refs (no-render control)
115
+ const tableContainerRef = (0, react_1.useRef)(null);
116
+ const apiRef = (0, react_1.useRef)(null);
117
+ const exportControllerRef = (0, react_1.useRef)(null);
118
+ const exportQueueRef = (0, react_1.useRef)(Promise.resolve());
119
+ const lastSentRef = (0, react_1.useRef)("");
120
+ // --- latest refs (prevent stale closures in stable API)
121
+ const uiRef = useLatestRef(ui);
122
+ const dataRef = useLatestRef(data);
123
+ ;
124
+ const serverDataRef = useLatestRef(serverData);
125
+ const nextFetchDelayRef = (0, react_1.useRef)(0);
126
+ // callbacks refs (super important)
127
+ const onFetchDataRef = useLatestRef(onFetchData);
128
+ const onFetchStateChangeRef = useLatestRef(onFetchStateChange);
129
+ const onDataStateChangeRef = useLatestRef(onDataStateChange);
130
+ const onSortingChangeRef = useLatestRef(onSortingChange);
131
+ const onPaginationChangeRef = useLatestRef(onPaginationChange);
132
+ const onGlobalFilterChangeRef = useLatestRef(onGlobalFilterChange);
133
+ const onColumnFiltersChangeRef = useLatestRef(onColumnFiltersChange);
134
+ const onColumnDragEndRef = useLatestRef(onColumnDragEnd);
135
+ const onColumnPinningChangeRef = useLatestRef(onColumnPinningChange);
136
+ const onColumnVisibilityChangeRef = useLatestRef(onColumnVisibilityChange);
137
+ const onColumnSizingChangeRef = useLatestRef(onColumnSizingChange);
138
+ const onSelectionChangeRef = useLatestRef(onSelectionChange);
139
+ const onExportProgressRef = useLatestRef(onExportProgress);
140
+ const onExportCompleteRef = useLatestRef(onExportComplete);
141
+ const onExportErrorRef = useLatestRef(onExportError);
142
+ const onExportCancelRef = useLatestRef(onExportCancel);
143
+ const onExportStateChangeRef = useLatestRef(onExportStateChange);
144
+ const onServerExportRef = useLatestRef(onServerExport);
145
+ // --- debounced fetch helper (can stay as-is)
146
+ const fetchHandler = useEvent((filters, opts) => { var _a; return (_a = onFetchDataRef.current) === null || _a === void 0 ? void 0 : _a.call(onFetchDataRef, filters, opts); });
147
+ const { debouncedFetch, isLoading: fetchLoading } = (0, debounced_fetch_utils_1.useDebouncedFetch)(fetchHandler);
148
+ const tableData = (0, react_1.useMemo)(() => {
149
+ return serverData !== null ? serverData : data;
150
+ }, [serverData, data]);
151
+ const tableTotalRow = (0, react_1.useMemo)(() => {
152
+ return serverData !== null ? serverTotal : totalRow || data.length;
153
+ }, [serverData, serverTotal, totalRow, data]);
154
+ const tableLoading = (0, react_1.useMemo)(() => {
155
+ return onFetchData ? loading || fetchLoading : loading;
156
+ }, [onFetchData, loading, fetchLoading]);
157
+ // --- columns enhancement
158
+ const enhancedColumns = (0, react_1.useMemo)(() => {
159
+ let cols = [...columns];
160
+ if (enableExpanding) {
161
+ cols = [
162
+ (0, special_columns_utils_1.createExpandingColumn)({
163
+ ...((slotProps === null || slotProps === void 0 ? void 0 : slotProps.expandColumn) && typeof slotProps.expandColumn === "object"
164
+ ? slotProps.expandColumn
165
+ : {}),
166
+ }),
167
+ ...cols,
168
+ ];
169
+ }
170
+ if (enableRowSelection) {
171
+ cols = [
172
+ (0, special_columns_utils_1.createSelectionColumn)({
173
+ ...((slotProps === null || slotProps === void 0 ? void 0 : slotProps.selectionColumn) && typeof slotProps.selectionColumn === "object"
174
+ ? slotProps.selectionColumn
175
+ : {}),
176
+ multiSelect: enableMultiRowSelection,
177
+ }),
178
+ ...cols,
179
+ ];
180
+ }
181
+ return (0, utils_1.withIdsDeep)(cols);
182
+ }, [
183
+ columns,
184
+ enableExpanding,
185
+ enableRowSelection,
186
+ enableMultiRowSelection,
187
+ slotProps === null || slotProps === void 0 ? void 0 : slotProps.expandColumn,
188
+ slotProps === null || slotProps === void 0 ? void 0 : slotProps.selectionColumn,
189
+ ]);
190
+ // --- fetchData: useEvent so it's stable but reads latest state refs
191
+ const fetchData = useEvent(async (overrides = {}, options) => {
192
+ var _a, _b;
193
+ const s = uiRef.current;
194
+ const filters = {
195
+ globalFilter: s.globalFilter,
196
+ pagination: s.pagination,
197
+ columnFilter: s.columnFilter,
198
+ sorting: s.sorting,
199
+ ...overrides,
200
+ };
201
+ (_a = onFetchStateChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onFetchStateChangeRef, filters, options === null || options === void 0 ? void 0 : options.meta);
202
+ const handler = onFetchDataRef.current;
203
+ if (!handler)
204
+ return;
205
+ const delay = (_b = options === null || options === void 0 ? void 0 : options.delay) !== null && _b !== void 0 ? _b : 0;
206
+ const result = await debouncedFetch(filters, { debounceDelay: delay, meta: options === null || options === void 0 ? void 0 : options.meta });
207
+ if (result && Array.isArray(result.data) && result.total !== undefined) {
208
+ setServerData(result.data);
209
+ setServerTotal(result.total);
210
+ }
211
+ return result;
212
+ });
213
+ // --- derived selection counts
214
+ const isSomeRowsSelected = (0, react_1.useMemo)(() => {
215
+ if (!enableBulkActions || !enableRowSelection)
216
+ return false;
217
+ if (ui.selectionState.type === "exclude")
218
+ return ui.selectionState.ids.length < tableTotalRow;
219
+ return ui.selectionState.ids.length > 0;
220
+ }, [enableBulkActions, enableRowSelection, ui.selectionState, tableTotalRow]);
221
+ const selectedRowCount = (0, react_1.useMemo)(() => {
222
+ if (!enableBulkActions || !enableRowSelection)
223
+ return 0;
224
+ if (ui.selectionState.type === "exclude")
225
+ return tableTotalRow - ui.selectionState.ids.length;
226
+ return ui.selectionState.ids.length;
227
+ }, [enableBulkActions, enableRowSelection, ui.selectionState, tableTotalRow]);
228
+ // --- TanStack Table
229
+ const table = (0, react_table_1.useReactTable)({
230
+ _features: [column_filter_feature_1.ColumnFilterFeature, features_1.SelectionFeature],
231
+ data: tableData,
232
+ columns: enhancedColumns,
233
+ initialState: initialStateConfig,
234
+ state: {
235
+ ...(enableSorting ? { sorting: ui.sorting } : {}),
236
+ ...(enablePagination ? { pagination: ui.pagination } : {}),
237
+ ...(enableGlobalFilter ? { globalFilter: ui.globalFilter } : {}),
238
+ ...(enableExpanding ? { expanded: ui.expanded } : {}),
239
+ ...(enableColumnDragging ? { columnOrder: ui.columnOrder } : {}),
240
+ ...(enableColumnPinning ? { columnPinning: ui.columnPinning } : {}),
241
+ ...(enableColumnVisibility ? { columnVisibility: ui.columnVisibility } : {}),
242
+ ...(enableColumnResizing ? { columnSizing: ui.columnSizing } : {}),
243
+ ...(enableColumnFilter ? { columnFilter: ui.columnFilter } : {}),
244
+ ...(enableRowSelection ? { selectionState: ui.selectionState } : {}),
245
+ },
246
+ selectMode,
247
+ enableAdvanceSelection: !!enableRowSelection,
248
+ isRowSelectable: isRowSelectable,
249
+ ...(enableRowSelection
250
+ ? {
251
+ onSelectionStateChange: (updaterOrValue) => {
252
+ dispatch({
253
+ type: "SET_SELECTION",
254
+ payload: typeof updaterOrValue === "function"
255
+ ? updaterOrValue(uiRef.current.selectionState)
256
+ : updaterOrValue,
257
+ });
258
+ },
259
+ }
260
+ : {}),
261
+ enableAdvanceColumnFilter: enableColumnFilter,
262
+ onColumnFilterChange: (updater) => {
263
+ const next = typeof updater === "function" ? updater(uiRef.current.columnFilter) : updater;
264
+ dispatch({ type: "SET_COLUMN_FILTER", payload: next });
265
+ },
266
+ onColumnFilterApply: (state) => {
267
+ dispatch({ type: "SET_COLUMN_FILTER_RESET_PAGE", payload: state });
268
+ },
269
+ ...(enableSorting
270
+ ? {
271
+ onSortingChange: (updaterOrValue) => {
272
+ var _a;
273
+ const prev = uiRef.current.sorting;
274
+ const next = typeof updaterOrValue === "function" ? updaterOrValue(prev) : updaterOrValue;
275
+ const cleaned = (next || []).filter((s) => s === null || s === void 0 ? void 0 : s.id);
276
+ (_a = onSortingChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onSortingChangeRef, cleaned);
277
+ dispatch({ type: "SET_SORTING_RESET_PAGE", payload: cleaned });
278
+ },
279
+ }
280
+ : {}),
281
+ ...(enablePagination
282
+ ? {
283
+ onPaginationChange: (updater) => {
284
+ var _a;
285
+ const prev = uiRef.current.pagination;
286
+ const next = typeof updater === "function" ? updater(prev) : updater;
287
+ (_a = onPaginationChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onPaginationChangeRef, next);
288
+ dispatch({ type: "SET_PAGINATION", payload: next });
289
+ },
290
+ }
291
+ : {}),
292
+ ...(enableGlobalFilter
293
+ ? {
294
+ onGlobalFilterChange: (updaterOrValue) => {
295
+ var _a;
296
+ const prev = uiRef.current.globalFilter;
297
+ const next = typeof updaterOrValue === "function" ? updaterOrValue(prev) : updaterOrValue;
298
+ (_a = onGlobalFilterChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onGlobalFilterChangeRef, next);
299
+ nextFetchDelayRef.current = 400;
300
+ dispatch({ type: "SET_GLOBAL_FILTER_RESET_PAGE", payload: next });
301
+ },
302
+ }
303
+ : {}),
304
+ ...(enableExpanding ? { onExpandedChange: (u) => dispatch({ type: "SET_EXPANDED", payload: typeof u === "function" ? u(uiRef.current.expanded) : u }) } : {}),
305
+ ...(enableColumnDragging ? { onColumnOrderChange: (u) => dispatch({ type: "SET_COLUMN_ORDER", payload: typeof u === "function" ? u(uiRef.current.columnOrder) : u }) } : {}),
306
+ ...(enableColumnPinning ? { onColumnPinningChange: (u) => dispatch({ type: "SET_COLUMN_PINNING", payload: typeof u === "function" ? u(uiRef.current.columnPinning) : u }) } : {}),
307
+ ...(enableColumnVisibility ? { onColumnVisibilityChange: (u) => dispatch({ type: "SET_COLUMN_VISIBILITY", payload: typeof u === "function" ? u(uiRef.current.columnVisibility) : u }) } : {}),
308
+ ...(enableColumnResizing ? { onColumnSizingChange: (u) => dispatch({ type: "SET_COLUMN_SIZING", payload: typeof u === "function" ? u(uiRef.current.columnSizing) : u }) } : {}),
309
+ getCoreRowModel: (0, react_table_1.getCoreRowModel)(),
310
+ ...(enableSorting ? { getSortedRowModel: (0, react_table_1.getSortedRowModel)() } : {}),
311
+ ...(enableColumnFilter || enableGlobalFilter ? { getFilteredRowModel: (0, column_filter_feature_1.getCombinedFilteredRowModel)() } : {}),
312
+ ...(enablePagination && !isServerPagination ? { getPaginationRowModel: (0, react_table_1.getPaginationRowModel)() } : {}),
313
+ enableSorting,
314
+ manualSorting: isServerSorting,
315
+ manualFiltering: isServerFiltering,
316
+ enableColumnResizing,
317
+ columnResizeMode,
318
+ columnResizeDirection: theme.direction,
319
+ enableColumnPinning,
320
+ ...(enableExpanding ? { getRowCanExpand: getRowCanExpand } : {}),
321
+ manualPagination: isServerPagination,
322
+ autoResetPageIndex: false,
323
+ rowCount: enablePagination ? (tableTotalRow !== null && tableTotalRow !== void 0 ? tableTotalRow : tableData.length) : tableData.length,
324
+ getRowId: (row, index) => (0, utils_1.generateRowId)(row, index, idKey),
325
+ });
326
+ // --- layout sizing
327
+ const allLeafColumns = table.getAllLeafColumns();
328
+ const hasExplicitSizing = allLeafColumns.some((col) => {
329
+ const { size, minSize, maxSize } = col.columnDef;
330
+ return size !== undefined || minSize !== undefined || maxSize !== undefined;
331
+ });
332
+ const useFixedLayout = fitToScreen || enableColumnResizing || hasExplicitSizing;
333
+ const tableTotalSize = table.getTotalSize();
334
+ const tableWidth = fitToScreen ? "100%" : useFixedLayout ? tableTotalSize : "100%";
335
+ const tableStyle = {
336
+ width: tableWidth,
337
+ minWidth: fitToScreen ? tableTotalSize : undefined,
338
+ tableLayout: useFixedLayout ? "fixed" : "auto",
339
+ };
340
+ // --- virtualization
341
+ const rows = table.getRowModel().rows;
342
+ const rowVirtualizer = (0, react_virtual_1.useVirtualizer)({
343
+ count: rows.length,
344
+ getScrollElement: () => tableContainerRef.current,
345
+ estimateSize: () => estimateRowHeight,
346
+ overscan: 10,
347
+ enabled: enableVirtualization && !enablePagination && rows.length > 0,
348
+ });
349
+ const serverKey = (0, react_1.useMemo)(() => {
350
+ if (!(isServerMode || isServerPagination || isServerFiltering || isServerSorting))
351
+ return null;
352
+ return JSON.stringify({
353
+ sorting: ui.sorting,
354
+ pagination: ui.pagination,
355
+ globalFilter: ui.globalFilter,
356
+ columnFilter: { filters: ui.columnFilter.filters, logic: ui.columnFilter.logic }, // only applied
357
+ });
358
+ }, [isServerMode, isServerPagination, isServerFiltering, isServerSorting, ui.sorting, ui.pagination, ui.globalFilter, ui.columnFilter]);
359
+ const serverKeyRef = useLatestRef(serverKey);
360
+ const lastServerKeyRef = (0, react_1.useRef)(null);
361
+ // --- initial fetch
362
+ (0, react_1.useEffect)(() => {
363
+ if (!initialLoadData)
364
+ return;
365
+ // If we're in server mode, mark current serverKey as already handled
366
+ // so the serverKey effect doesn't immediately fetch again.
367
+ if (serverKeyRef.current) {
368
+ lastServerKeyRef.current = serverKeyRef.current;
369
+ }
370
+ if (onFetchData || onFetchStateChange) {
371
+ void fetchData({}, { delay: 0, meta: { reason: "initial" } });
372
+ }
373
+ // eslint-disable-next-line react-hooks/exhaustive-deps
374
+ }, []);
375
+ (0, react_1.useEffect)(() => {
376
+ var _a;
377
+ if (!serverKey)
378
+ return;
379
+ if (serverKey === lastServerKeyRef.current)
380
+ return;
381
+ lastServerKeyRef.current = serverKey;
382
+ const delay = (_a = nextFetchDelayRef.current) !== null && _a !== void 0 ? _a : 0;
383
+ nextFetchDelayRef.current = 0; // reset after using
384
+ const timeoutId = setTimeout(() => {
385
+ void fetchData({}, { delay, meta: { reason: "stateChange" } });
386
+ }, 0);
387
+ return () => clearTimeout(timeoutId);
388
+ }, [serverKey, fetchData]);
389
+ // columnFilter apply handler stays explicit (button), but you can also auto-fetch on change if needed
390
+ const handleColumnFilterChangeHandler = (0, react_1.useCallback)((updater, isApply = false) => {
391
+ var _a;
392
+ const prev = uiRef.current.columnFilter;
393
+ const next = typeof updater === "function" ? updater(prev) : updater;
394
+ if (isApply) {
395
+ nextFetchDelayRef.current = 0;
396
+ dispatch({ type: "SET_COLUMN_FILTER_RESET_PAGE", payload: next });
397
+ }
398
+ else {
399
+ dispatch({ type: "SET_COLUMN_FILTER", payload: next });
400
+ }
401
+ (_a = onColumnFiltersChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onColumnFiltersChangeRef, next, isApply);
402
+ }, [onColumnFiltersChangeRef, uiRef]);
403
+ // --- emit table state (dedupe)
404
+ (0, react_1.useEffect)(() => {
405
+ const cb = onDataStateChangeRef.current;
406
+ if (!cb)
407
+ return;
408
+ const live = table.getState();
409
+ const payload = {
410
+ sorting: live.sorting,
411
+ pagination: live.pagination,
412
+ globalFilter: live.globalFilter,
413
+ columnFilter: live.columnFilter,
414
+ columnVisibility: live.columnVisibility,
415
+ columnSizing: live.columnSizing,
416
+ columnOrder: live.columnOrder,
417
+ columnPinning: live.columnPinning,
418
+ };
419
+ const key = JSON.stringify(payload);
420
+ if (key === lastSentRef.current)
421
+ return;
422
+ lastSentRef.current = key;
423
+ cb(payload);
424
+ }, [table, ui.sorting, ui.pagination, ui.globalFilter, ui.columnFilter, ui.columnVisibility, ui.columnSizing, ui.columnOrder, ui.columnPinning, onDataStateChangeRef]);
425
+ // --- helpers
426
+ const resetPageToFirst = (0, react_1.useCallback)(() => {
427
+ return { pageIndex: 0, pageSize: uiRef.current.pagination.pageSize };
428
+ }, [uiRef]);
429
+ const normalizeRefreshOptions = (0, react_1.useCallback)((options, fallbackReason = "refresh") => {
430
+ var _a, _b, _c;
431
+ if (typeof options === "boolean")
432
+ return { resetPagination: options, force: false, reason: fallbackReason };
433
+ return {
434
+ resetPagination: (_a = options === null || options === void 0 ? void 0 : options.resetPagination) !== null && _a !== void 0 ? _a : false,
435
+ force: (_b = options === null || options === void 0 ? void 0 : options.force) !== null && _b !== void 0 ? _b : false,
436
+ reason: (_c = options === null || options === void 0 ? void 0 : options.reason) !== null && _c !== void 0 ? _c : fallbackReason,
437
+ };
438
+ }, []);
439
+ const triggerRefresh = (0, react_1.useCallback)(async (options, fallbackReason = "refresh") => {
440
+ var _a;
441
+ const n = normalizeRefreshOptions(options, fallbackReason);
442
+ const current = uiRef.current.pagination;
443
+ const nextPagination = enablePagination
444
+ ? { pageIndex: n.resetPagination ? 0 : current.pageIndex, pageSize: current.pageSize }
445
+ : undefined;
446
+ if (nextPagination) {
447
+ nextFetchDelayRef.current = 0;
448
+ dispatch({ type: "SET_PAGINATION", payload: nextPagination });
449
+ (_a = onPaginationChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onPaginationChangeRef, nextPagination);
450
+ }
451
+ const paginationChanged = !!nextPagination &&
452
+ (nextPagination.pageIndex !== current.pageIndex || nextPagination.pageSize !== current.pageSize);
453
+ if (!paginationChanged) {
454
+ await fetchData({}, { delay: 0, meta: { reason: n.reason, force: n.force } });
455
+ }
456
+ }, [enablePagination, fetchData, normalizeRefreshOptions, onPaginationChangeRef, uiRef]);
457
+ const getResetPayload = (0, react_1.useCallback)(() => {
458
+ var _a, _b, _c;
459
+ const resetSorting = initialStateConfig.sorting || [];
460
+ const resetGlobalFilter = (_a = initialStateConfig.globalFilter) !== null && _a !== void 0 ? _a : "";
461
+ const resetColumnFilter = ((_b = initialStateConfig.columnFilter) !== null && _b !== void 0 ? _b : DEFAULT_INITIAL_STATE.columnFilter);
462
+ const resetPagination = enablePagination
463
+ ? (initialStateConfig.pagination || { pageIndex: 0, pageSize: 10 })
464
+ : uiRef.current.pagination;
465
+ return {
466
+ sorting: resetSorting,
467
+ globalFilter: resetGlobalFilter,
468
+ columnFilter: resetColumnFilter,
469
+ ...(enablePagination ? { pagination: resetPagination } : {}),
470
+ selectionState: (_c = initialStateConfig.selectionState) !== null && _c !== void 0 ? _c : DEFAULT_INITIAL_STATE.selectionState,
471
+ expanded: {},
472
+ columnVisibility: initialStateConfig.columnVisibility || {},
473
+ columnSizing: initialStateConfig.columnSizing || {},
474
+ columnOrder: initialStateConfig.columnOrder || [],
475
+ columnPinning: initialStateConfig.columnPinning || { left: [], right: [] },
476
+ };
477
+ }, [enablePagination, initialStateConfig]);
478
+ const resetAllAndReload = (0, react_1.useCallback)(() => {
479
+ const payload = getResetPayload();
480
+ dispatch({ type: "RESET_ALL", payload });
481
+ void fetchData({
482
+ sorting: payload.sorting,
483
+ globalFilter: payload.globalFilter,
484
+ columnFilter: payload.columnFilter,
485
+ ...(enablePagination ? { pagination: payload.pagination } : {}),
486
+ }, { delay: 0, meta: { reason: "reset", force: true } });
487
+ }, [enablePagination, fetchData, getResetPayload]);
488
+ // --- export (refs + small UI state)
489
+ const setExportControllerSafely = (0, react_1.useCallback)((value) => {
490
+ setExportController((current) => {
491
+ const next = typeof value === "function" ? value(current) : value;
492
+ exportControllerRef.current = next;
493
+ return next;
494
+ });
495
+ }, []);
496
+ const handleExportProgressInternal = (0, react_1.useCallback)((p) => {
497
+ var _a;
498
+ setExportProgress(p || {});
499
+ (_a = onExportProgressRef.current) === null || _a === void 0 ? void 0 : _a.call(onExportProgressRef, p);
500
+ }, []);
501
+ const handleExportStateChangeInternal = (0, react_1.useCallback)((s) => {
502
+ var _a;
503
+ setExportPhase(s.phase);
504
+ if (s.processedRows !== undefined || s.totalRows !== undefined || s.percentage !== undefined) {
505
+ setExportProgress({
506
+ processedRows: s.processedRows,
507
+ totalRows: s.totalRows,
508
+ percentage: s.percentage,
509
+ });
510
+ }
511
+ (_a = onExportStateChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onExportStateChangeRef, s);
512
+ }, []);
513
+ const runExportWithPolicy = (0, react_1.useCallback)(async (options) => {
514
+ var _a;
515
+ const { format, filename, mode, execute } = options;
516
+ const startExecution = async () => {
517
+ const controller = new AbortController();
518
+ setExportProgress({});
519
+ setExportControllerSafely(controller);
520
+ try {
521
+ await execute(controller);
522
+ }
523
+ finally {
524
+ setExportControllerSafely((cur) => (cur === controller ? null : cur));
525
+ }
526
+ };
527
+ if (exportConcurrency === "queue") {
528
+ setQueuedExportCount((p) => p + 1);
529
+ const runQueued = async () => {
530
+ setQueuedExportCount((p) => Math.max(0, p - 1));
531
+ await startExecution();
532
+ };
533
+ const queuedPromise = exportQueueRef.current.catch(() => undefined).then(runQueued);
534
+ exportQueueRef.current = queuedPromise;
535
+ return queuedPromise;
536
+ }
537
+ const active = exportControllerRef.current;
538
+ if (active) {
539
+ if (exportConcurrency === "ignoreIfRunning") {
540
+ handleExportStateChangeInternal({
541
+ phase: "error",
542
+ mode,
543
+ format,
544
+ filename,
545
+ message: "An export is already running",
546
+ code: "EXPORT_IN_PROGRESS",
547
+ endedAt: Date.now(),
548
+ });
549
+ (_a = onExportErrorRef.current) === null || _a === void 0 ? void 0 : _a.call(onExportErrorRef, { message: "An export is already running", code: "EXPORT_IN_PROGRESS" });
550
+ return;
551
+ }
552
+ if (exportConcurrency === "cancelAndRestart")
553
+ active.abort();
554
+ }
555
+ await startExecution();
556
+ }, [exportConcurrency, handleExportStateChangeInternal, onExportErrorRef, setExportControllerSafely]);
557
+ const handleCancelExport = (0, react_1.useCallback)(() => {
558
+ var _a;
559
+ const active = exportControllerRef.current;
560
+ if (!active)
561
+ return;
562
+ active.abort();
563
+ setExportControllerSafely((cur) => (cur === active ? null : cur));
564
+ (_a = onExportCancelRef.current) === null || _a === void 0 ? void 0 : _a.call(onExportCancelRef);
565
+ }, [onExportCancelRef, setExportControllerSafely]);
566
+ const isExporting = exportController !== null;
567
+ // --- stable API (created once)
568
+ if (!apiRef.current) {
569
+ apiRef.current = {};
570
+ // IMPORTANT: do NOT capture `table/ui/data` here. Always read from refs inside methods.
571
+ apiRef.current.table = { getTable: () => table }; // will be updated below via tableRef
572
+ // We'll overwrite getTable below with a ref-backed function.
573
+ }
574
+ // table ref so API always returns latest table instance
575
+ const tableRef = useLatestRef(table);
576
+ (0, react_1.useEffect)(() => {
577
+ const api = apiRef.current;
578
+ api.table = { getTable: () => tableRef.current };
579
+ // --- state getters
580
+ api.state = {
581
+ getTableState: () => tableRef.current.getState(),
582
+ getCurrentFilters: () => tableRef.current.getState().columnFilter,
583
+ getCurrentSorting: () => tableRef.current.getState().sorting,
584
+ getCurrentPagination: () => tableRef.current.getState().pagination,
585
+ getCurrentSelection: () => uiRef.current.selectionState,
586
+ getGlobalFilter: () => tableRef.current.getState().globalFilter,
587
+ };
588
+ // --- data
589
+ api.data = {
590
+ refresh: (options) => void triggerRefresh(options, "refresh"),
591
+ reload: (options = {}) => { var _a; return void triggerRefresh({ ...options, reason: (_a = options.reason) !== null && _a !== void 0 ? _a : "reload" }, "reload"); },
592
+ resetAll: () => resetAllAndReload(),
593
+ getAllData: () => {
594
+ const sData = serverDataRef.current;
595
+ const base = sData !== null ? sData : dataRef.current;
596
+ return [...base];
597
+ },
598
+ getDataCount: () => {
599
+ const sData = serverDataRef.current;
600
+ const base = sData !== null ? sData : dataRef.current;
601
+ return base.length;
602
+ },
603
+ getFilteredDataCount: () => tableRef.current.getFilteredRowModel().rows.length,
604
+ };
605
+ // --- sorting/pagination/filtering - dispatch + callbacks + server fetch policies
606
+ api.sorting = {
607
+ setSorting: (next) => {
608
+ var _a;
609
+ const cleaned = (next || []).filter((s) => s === null || s === void 0 ? void 0 : s.id);
610
+ (_a = onSortingChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onSortingChangeRef, cleaned);
611
+ nextFetchDelayRef.current = 0;
612
+ dispatch({ type: "SET_SORTING_RESET_PAGE", payload: cleaned });
613
+ },
614
+ clearSorting: () => {
615
+ var _a;
616
+ (_a = onSortingChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onSortingChangeRef, []);
617
+ nextFetchDelayRef.current = 0;
618
+ dispatch({ type: "SET_SORTING_RESET_PAGE", payload: [] });
619
+ },
620
+ resetSorting: () => {
621
+ var _a;
622
+ const next = (initialStateConfig.sorting || []);
623
+ (_a = onSortingChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onSortingChangeRef, next);
624
+ nextFetchDelayRef.current = 0;
625
+ dispatch({ type: "SET_SORTING_RESET_PAGE", payload: next });
626
+ },
627
+ };
628
+ api.pagination = {
629
+ goToPage: (pageIndex) => {
630
+ var _a;
631
+ const prev = uiRef.current.pagination;
632
+ const next = { ...prev, pageIndex };
633
+ (_a = onPaginationChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onPaginationChangeRef, next);
634
+ nextFetchDelayRef.current = 0;
635
+ dispatch({ type: "SET_PAGINATION", payload: next });
636
+ },
637
+ setPageSize: (pageSize) => {
638
+ var _a;
639
+ const next = { pageIndex: 0, pageSize };
640
+ (_a = onPaginationChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onPaginationChangeRef, next);
641
+ nextFetchDelayRef.current = 0;
642
+ dispatch({ type: "SET_PAGINATION", payload: next });
643
+ },
644
+ resetPagination: () => {
645
+ var _a;
646
+ const next = (initialStateConfig.pagination || { pageIndex: 0, pageSize: 10 });
647
+ (_a = onPaginationChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onPaginationChangeRef, next);
648
+ nextFetchDelayRef.current = 0;
649
+ dispatch({ type: "SET_PAGINATION", payload: next });
650
+ },
651
+ };
652
+ api.filtering = {
653
+ setGlobalFilter: (filter) => {
654
+ var _a;
655
+ (_a = onGlobalFilterChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onGlobalFilterChangeRef, filter);
656
+ nextFetchDelayRef.current = 400;
657
+ dispatch({ type: "SET_GLOBAL_FILTER_RESET_PAGE", payload: filter });
658
+ },
659
+ clearGlobalFilter: () => {
660
+ var _a;
661
+ (_a = onGlobalFilterChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onGlobalFilterChangeRef, "");
662
+ nextFetchDelayRef.current = 400;
663
+ dispatch({ type: "SET_GLOBAL_FILTER_RESET_PAGE", payload: "" });
664
+ },
665
+ setColumnFilters: (filters, isApply = false) => handleColumnFilterChangeHandler(filters, isApply),
666
+ };
667
+ api.columnVisibility = {
668
+ showColumn: (id) => dispatch({ type: "SET_COLUMN_VISIBILITY", payload: { ...uiRef.current.columnVisibility, [id]: true } }),
669
+ hideColumn: (id) => dispatch({ type: "SET_COLUMN_VISIBILITY", payload: { ...uiRef.current.columnVisibility, [id]: false } }),
670
+ resetColumnVisibility: () => dispatch({ type: "SET_COLUMN_VISIBILITY", payload: initialStateConfig.columnVisibility || {} }),
671
+ };
672
+ api.columnOrdering = {
673
+ setColumnOrder: (next) => {
674
+ var _a;
675
+ dispatch({ type: "SET_COLUMN_ORDER", payload: next });
676
+ (_a = onColumnDragEndRef.current) === null || _a === void 0 ? void 0 : _a.call(onColumnDragEndRef, next);
677
+ },
678
+ resetColumnOrder: () => dispatch({ type: "SET_COLUMN_ORDER", payload: initialStateConfig.columnOrder || [] }),
679
+ };
680
+ api.columnPinning = {
681
+ setPinning: (next) => {
682
+ var _a;
683
+ dispatch({ type: "SET_COLUMN_PINNING", payload: next });
684
+ (_a = onColumnPinningChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onColumnPinningChangeRef, next);
685
+ },
686
+ resetColumnPinning: () => dispatch({ type: "SET_COLUMN_PINNING", payload: initialStateConfig.columnPinning || { left: [], right: [] } }),
687
+ };
688
+ api.columnResizing = {
689
+ resetColumnSizing: () => dispatch({ type: "SET_COLUMN_SIZING", payload: initialStateConfig.columnSizing || {} }),
690
+ };
691
+ api.selection = {
692
+ getSelectionState: () => { var _a, _b; return ((_b = (_a = tableRef.current).getSelectionState) === null || _b === void 0 ? void 0 : _b.call(_a)) || { ids: [], type: "include" }; },
693
+ getSelectedRows: () => tableRef.current.getSelectedRows(),
694
+ getSelectedCount: () => tableRef.current.getSelectedCount(),
695
+ isRowSelected: (rowId) => tableRef.current.getIsRowSelected(rowId) || false,
696
+ // keep using your table extension methods if you have them:
697
+ selectAll: () => { var _a, _b; return (_b = (_a = tableRef.current).selectAll) === null || _b === void 0 ? void 0 : _b.call(_a); },
698
+ deselectAll: () => { var _a, _b; return (_b = (_a = tableRef.current).deselectAll) === null || _b === void 0 ? void 0 : _b.call(_a); },
699
+ };
700
+ // --- export API (use your existing exportClientData/exportServerData)
701
+ api.export = {
702
+ exportCSV: async (options = {}) => {
703
+ var _a, _b, _c, _d;
704
+ const fn = (_a = options.filename) !== null && _a !== void 0 ? _a : exportFilename;
705
+ const chunkSize = (_b = options.chunkSize) !== null && _b !== void 0 ? _b : exportChunkSize;
706
+ const strictTotalCheck = (_c = options.strictTotalCheck) !== null && _c !== void 0 ? _c : exportStrictTotalCheck;
707
+ const sanitizeCSV = (_d = options.sanitizeCSV) !== null && _d !== void 0 ? _d : exportSanitizeCSV;
708
+ const mode = dataMode === "server" && !!onServerExportRef.current ? "server" : "client";
709
+ await runExportWithPolicy({
710
+ format: "csv",
711
+ filename: fn,
712
+ mode,
713
+ execute: async (controller) => {
714
+ var _a, _b;
715
+ // TODO: keep your state-change event mapping (starting/progress/completed/cancel/error)
716
+ if (mode === "server" && onServerExportRef.current) {
717
+ await (0, utils_1.exportServerData)(tableRef.current, {
718
+ format: "csv",
719
+ filename: fn,
720
+ fetchData: (filters, selection, signal) => { var _a; return (_a = onServerExportRef.current) === null || _a === void 0 ? void 0 : _a.call(onServerExportRef, filters, selection, signal); },
721
+ currentFilters: {
722
+ globalFilter: tableRef.current.getState().globalFilter,
723
+ columnFilter: tableRef.current.getState().columnFilter,
724
+ sorting: tableRef.current.getState().sorting,
725
+ pagination: tableRef.current.getState().pagination,
726
+ },
727
+ selection: (_b = (_a = tableRef.current).getSelectionState) === null || _b === void 0 ? void 0 : _b.call(_a),
728
+ onProgress: handleExportProgressInternal,
729
+ onComplete: onExportCompleteRef.current,
730
+ onError: onExportErrorRef.current,
731
+ onStateChange: (s) => handleExportStateChangeInternal({ ...s, mode, format: "csv", filename: fn, queueLength: queuedExportCount }),
732
+ signal: controller.signal,
733
+ chunkSize,
734
+ strictTotalCheck,
735
+ sanitizeCSV,
736
+ });
737
+ return;
738
+ }
739
+ await (0, utils_1.exportClientData)(tableRef.current, {
740
+ format: "csv",
741
+ filename: fn,
742
+ onProgress: handleExportProgressInternal,
743
+ onComplete: onExportCompleteRef.current,
744
+ onError: onExportErrorRef.current,
745
+ onStateChange: (s) => handleExportStateChangeInternal({ ...s, mode, format: "csv", filename: fn, queueLength: queuedExportCount }),
746
+ signal: controller.signal,
747
+ sanitizeCSV,
748
+ });
749
+ },
750
+ });
751
+ },
752
+ exportExcel: async (options = {}) => {
753
+ var _a, _b, _c, _d;
754
+ const fn = (_a = options.filename) !== null && _a !== void 0 ? _a : exportFilename;
755
+ const chunkSize = (_b = options.chunkSize) !== null && _b !== void 0 ? _b : exportChunkSize;
756
+ const strictTotalCheck = (_c = options.strictTotalCheck) !== null && _c !== void 0 ? _c : exportStrictTotalCheck;
757
+ const sanitizeCSV = (_d = options.sanitizeCSV) !== null && _d !== void 0 ? _d : exportSanitizeCSV;
758
+ const mode = dataMode === "server" && !!onServerExportRef.current ? "server" : "client";
759
+ await runExportWithPolicy({
760
+ format: "excel",
761
+ filename: fn,
762
+ mode,
763
+ execute: async (controller) => {
764
+ var _a, _b;
765
+ // TODO: keep your state-change event mapping (starting/progress/completed/cancel/error)
766
+ if (mode === "server" && onServerExportRef.current) {
767
+ await (0, utils_1.exportServerData)(tableRef.current, {
768
+ format: "excel",
769
+ filename: fn,
770
+ fetchData: (filters, selection, signal) => { var _a; return (_a = onServerExportRef.current) === null || _a === void 0 ? void 0 : _a.call(onServerExportRef, filters, selection, signal); },
771
+ currentFilters: {
772
+ globalFilter: tableRef.current.getState().globalFilter,
773
+ columnFilter: tableRef.current.getState().columnFilter,
774
+ sorting: tableRef.current.getState().sorting,
775
+ pagination: tableRef.current.getState().pagination,
776
+ },
777
+ selection: (_b = (_a = tableRef.current).getSelectionState) === null || _b === void 0 ? void 0 : _b.call(_a),
778
+ onProgress: handleExportProgressInternal,
779
+ onComplete: onExportCompleteRef.current,
780
+ onError: onExportErrorRef.current,
781
+ onStateChange: (s) => handleExportStateChangeInternal({ ...s, mode, format: "csv", filename: fn, queueLength: queuedExportCount }),
782
+ signal: controller.signal,
783
+ chunkSize,
784
+ strictTotalCheck,
785
+ sanitizeCSV,
786
+ });
787
+ return;
788
+ }
789
+ await (0, utils_1.exportClientData)(tableRef.current, {
790
+ format: "excel",
791
+ filename: fn,
792
+ onProgress: handleExportProgressInternal,
793
+ onComplete: onExportCompleteRef.current,
794
+ onError: onExportErrorRef.current,
795
+ onStateChange: (s) => handleExportStateChangeInternal({ ...s, mode, format: "csv", filename: fn, queueLength: queuedExportCount }),
796
+ signal: controller.signal,
797
+ sanitizeCSV,
798
+ });
799
+ },
800
+ });
801
+ },
802
+ isExporting: () => exportControllerRef.current != null,
803
+ cancelExport: () => handleCancelExport(),
804
+ };
805
+ }, [dataMode, exportChunkSize, exportFilename, exportSanitizeCSV, exportStrictTotalCheck, fetchData, handleCancelExport, handleColumnFilterChangeHandler, handleExportProgressInternal, handleExportStateChangeInternal, initialStateConfig, isServerMode, isServerPagination, isServerSorting, resetAllAndReload, resetPageToFirst, runExportWithPolicy, triggerRefresh, queuedExportCount, tableRef, uiRef, serverDataRef, dataRef, onSortingChangeRef, onPaginationChangeRef, onGlobalFilterChangeRef, onColumnDragEndRef, onColumnPinningChangeRef, onServerExportRef, onExportCompleteRef, onExportErrorRef]);
806
+ // --- imperative handlers (used by TanStack callbacks above or view)
807
+ const handleSortingChange = (0, react_1.useCallback)((updaterOrValue) => {
808
+ var _a;
809
+ const prev = uiRef.current.sorting;
810
+ const next = typeof updaterOrValue === "function" ? updaterOrValue(prev) : updaterOrValue;
811
+ const cleaned = (next || []).filter((s) => s === null || s === void 0 ? void 0 : s.id);
812
+ (_a = onSortingChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onSortingChangeRef, cleaned);
813
+ nextFetchDelayRef.current = 0;
814
+ dispatch({ type: "SET_SORTING_RESET_PAGE", payload: cleaned });
815
+ }, [onSortingChangeRef, uiRef]);
816
+ const handlePaginationChange = (0, react_1.useCallback)((updater) => {
817
+ var _a;
818
+ const prev = uiRef.current.pagination;
819
+ const next = typeof updater === "function" ? updater(prev) : updater;
820
+ (_a = onPaginationChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onPaginationChangeRef, next);
821
+ nextFetchDelayRef.current = 0;
822
+ dispatch({ type: "SET_PAGINATION", payload: next });
823
+ }, [onPaginationChangeRef, uiRef]);
824
+ const handleGlobalFilterChange = (0, react_1.useCallback)((updaterOrValue) => {
825
+ var _a;
826
+ const prev = uiRef.current.globalFilter;
827
+ const next = typeof updaterOrValue === "function" ? updaterOrValue(prev) : updaterOrValue;
828
+ (_a = onGlobalFilterChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onGlobalFilterChangeRef, next);
829
+ nextFetchDelayRef.current = 400;
830
+ dispatch({ type: "SET_GLOBAL_FILTER_RESET_PAGE", payload: next });
831
+ }, [onGlobalFilterChangeRef, uiRef]);
832
+ const handleColumnOrderChange = (0, react_1.useCallback)((updated) => {
833
+ var _a;
834
+ const prev = uiRef.current.columnOrder;
835
+ const next = typeof updated === "function" ? updated(prev) : updated;
836
+ dispatch({ type: "SET_COLUMN_ORDER", payload: next });
837
+ (_a = onColumnDragEndRef.current) === null || _a === void 0 ? void 0 : _a.call(onColumnDragEndRef, next);
838
+ }, [onColumnDragEndRef, uiRef]);
839
+ const handleColumnPinningChange = (0, react_1.useCallback)((updated) => {
840
+ var _a;
841
+ const prev = uiRef.current.columnPinning;
842
+ const next = typeof updated === "function" ? updated(prev) : updated;
843
+ dispatch({ type: "SET_COLUMN_PINNING", payload: next });
844
+ (_a = onColumnPinningChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onColumnPinningChangeRef, next);
845
+ }, [onColumnPinningChangeRef, uiRef]);
846
+ const handleColumnVisibilityChange = (0, react_1.useCallback)((updated) => {
847
+ var _a;
848
+ const prev = uiRef.current.columnVisibility;
849
+ const next = typeof updated === "function" ? updated(prev) : updated;
850
+ dispatch({ type: "SET_COLUMN_VISIBILITY", payload: next });
851
+ (_a = onColumnVisibilityChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onColumnVisibilityChangeRef, next);
852
+ }, [onColumnVisibilityChangeRef, uiRef]);
853
+ const handleColumnSizingChange = (0, react_1.useCallback)((updated) => {
854
+ var _a;
855
+ const prev = uiRef.current.columnSizing;
856
+ const next = typeof updated === "function" ? updated(prev) : updated;
857
+ dispatch({ type: "SET_COLUMN_SIZING", payload: next });
858
+ (_a = onColumnSizingChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onColumnSizingChangeRef, next);
859
+ }, [onColumnSizingChangeRef, uiRef]);
860
+ const handleColumnReorder = (0, react_1.useCallback)((draggedId, targetId) => {
861
+ const currentOrder = uiRef.current.columnOrder.length > 0
862
+ ? uiRef.current.columnOrder
863
+ : enhancedColumns.map((c, idx) => { var _a, _b; return (_b = (_a = c.id) !== null && _a !== void 0 ? _a : c.accessorKey) !== null && _b !== void 0 ? _b : `column_${idx}`; });
864
+ const from = currentOrder.indexOf(draggedId);
865
+ const to = currentOrder.indexOf(targetId);
866
+ if (from === -1 || to === -1)
867
+ return;
868
+ const next = [...currentOrder];
869
+ next.splice(from, 1);
870
+ next.splice(to, 0, draggedId);
871
+ handleColumnOrderChange(next);
872
+ }, [enhancedColumns, handleColumnOrderChange, uiRef]);
873
+ // optional: selection callback
874
+ (0, react_1.useEffect)(() => {
875
+ var _a;
876
+ (_a = onSelectionChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onSelectionChangeRef, ui.selectionState);
877
+ }, [onSelectionChangeRef, ui.selectionState]);
878
+ // --- provider props
879
+ const providerProps = (0, react_1.useMemo)(() => ({
880
+ table,
881
+ apiRef,
882
+ dataMode,
883
+ tableSize: ui.tableSize,
884
+ onTableSizeChange: (size) => dispatch({ type: "SET_TABLE_SIZE", payload: size }),
885
+ columnFilter: ui.columnFilter,
886
+ onChangeColumnFilter: (f) => handleColumnFilterChangeHandler(f, false),
887
+ slots,
888
+ slotProps,
889
+ isExporting,
890
+ exportController,
891
+ exportPhase,
892
+ exportProgress,
893
+ onCancelExport: handleCancelExport,
894
+ exportFilename,
895
+ onExportProgress,
896
+ onExportComplete,
897
+ onExportError,
898
+ onServerExport,
899
+ }), [
900
+ table,
901
+ dataMode,
902
+ ui.tableSize,
903
+ ui.columnFilter,
904
+ slots,
905
+ slotProps,
906
+ isExporting,
907
+ exportController,
908
+ exportPhase,
909
+ exportProgress,
910
+ handleCancelExport,
911
+ exportFilename,
912
+ onExportProgress,
913
+ onExportComplete,
914
+ onExportError,
915
+ onServerExport,
916
+ handleColumnFilterChangeHandler,
917
+ ]);
918
+ return {
919
+ table,
920
+ refs: {
921
+ tableContainerRef,
922
+ apiRef,
923
+ exportControllerRef,
924
+ },
925
+ derived: {
926
+ isServerMode,
927
+ isServerPagination,
928
+ isServerFiltering,
929
+ isServerSorting,
930
+ tableData,
931
+ tableTotalRow,
932
+ tableLoading,
933
+ rows,
934
+ visibleLeafColumns: table.getVisibleLeafColumns,
935
+ useFixedLayout,
936
+ tableStyle,
937
+ isExporting,
938
+ exportPhase,
939
+ exportProgress,
940
+ isSomeRowsSelected,
941
+ selectedRowCount,
942
+ },
943
+ state: ui,
944
+ actions: {
945
+ fetchData,
946
+ handleSortingChange,
947
+ handlePaginationChange,
948
+ handleGlobalFilterChange,
949
+ handleColumnFilterChangeHandler,
950
+ handleColumnOrderChange,
951
+ handleColumnPinningChange,
952
+ handleColumnVisibilityChange,
953
+ handleColumnSizingChange,
954
+ handleColumnReorder,
955
+ resetAllAndReload,
956
+ triggerRefresh,
957
+ setTableSize: (size) => dispatch({ type: "SET_TABLE_SIZE", payload: size }),
958
+ handleCancelExport,
959
+ renderRowModel: { rowVirtualizer },
960
+ },
961
+ api: apiRef.current,
962
+ providerProps,
963
+ };
964
+ }