@ackplus/react-tanstack-data-table 1.1.17 → 1.1.19

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.
@@ -44,15 +44,19 @@ export function TableRefreshControl(props: TableRefreshControlProps = {}): React
44
44
  props.iconButtonProps || {}
45
45
  );
46
46
 
47
+ // Wrap in span so when IconButton is disabled (loading), the tooltip still
48
+ // receives pointer events and closes on mouse leave (disabled elements don't fire them).
47
49
  return (
48
50
  <Tooltip title="Refresh data" {...props.tooltipProps}>
49
- <IconButton {...mergedIconButtonProps}>
50
- {props.loading && props.showSpinnerWhileLoading ? (
51
- <CircularProgress size={16} />
52
- ) : (
53
- <RefreshIconSlot {...refreshIconSlotProps} />
54
- )}
55
- </IconButton>
51
+ <span style={{ display: 'inline-flex' }}>
52
+ <IconButton {...mergedIconButtonProps}>
53
+ {props.loading && props.showSpinnerWhileLoading ? (
54
+ <CircularProgress size={16} />
55
+ ) : (
56
+ <RefreshIconSlot {...refreshIconSlotProps} />
57
+ )}
58
+ </IconButton>
59
+ </span>
56
60
  </Tooltip>
57
61
  );
58
62
  }
@@ -49,7 +49,7 @@ declare module '@tanstack/react-table' {
49
49
  }
50
50
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
51
51
  interface Table<TData extends RowData> {
52
- setColumnFilterState: (updater: Updater<ColumnFilterState>) => void;
52
+ setColumnFilterState: (updater: Updater<ColumnFilterState> | ColumnFilterState) => void;
53
53
 
54
54
  // Pending filter methods (for draft state)
55
55
  addPendingColumnFilter: (columnId: string, operator: string, value: any) => void;
@@ -60,6 +60,7 @@ declare module '@tanstack/react-table' {
60
60
 
61
61
  // Apply pending filters to active filters
62
62
  applyPendingColumnFilters: () => void;
63
+ resetColumnFilter: () => void;
63
64
 
64
65
  // Legacy methods (for backward compatibility)
65
66
  addColumnFilter: (columnId: string, operator: string, value: any) => void;
@@ -187,6 +188,19 @@ export const ColumnFilterFeature: TableFeature<any> = {
187
188
  }));
188
189
  };
189
190
 
191
+ table.resetColumnFilter = () => {
192
+ if (!table.options.enableAdvanceColumnFilter) return;
193
+ const newState: ColumnFilterState = {
194
+ pendingFilters: [],
195
+ pendingLogic: 'AND',
196
+ filters: [],
197
+ logic: 'AND',
198
+ };
199
+ table.setColumnFilterState(newState);
200
+ // Notify engine so it can reset pagination and refetch (server mode)
201
+ table.options.onColumnFilterApply?.(newState);
202
+ };
203
+
190
204
  table.setPendingFilterLogic = (logic: 'AND' | 'OR') => {
191
205
  if (!table.options.enableAdvanceColumnFilter) return;
192
206
  table.setColumnFilterState((old) => ({
@@ -628,7 +628,10 @@ export function useDataTableEngine<T extends Record<string, any>>(
628
628
  const delay = nextFetchDelayRef.current ?? 0;
629
629
  nextFetchDelayRef.current = 0; // reset after using
630
630
 
631
- void fetchData({}, { delay, meta: { reason: "stateChange" } });
631
+ const timeoutId = setTimeout(() => {
632
+ void fetchData({}, { delay, meta: { reason: "stateChange" } });
633
+ }, 0);
634
+ return () => clearTimeout(timeoutId);
632
635
  }, [serverKey, fetchData]);
633
636
 
634
637
  // columnFilter apply handler stays explicit (button), but you can also auto-fetch on change if needed
@@ -862,22 +865,155 @@ export function useDataTableEngine<T extends Record<string, any>>(
862
865
  };
863
866
 
864
867
  // --- data
868
+ const getBaseData = () => {
869
+ const sData = serverDataRef.current;
870
+ return sData !== null ? sData : dataRef.current;
871
+ };
872
+ const getRowIndexById = (arr: T[], rowId: string) =>
873
+ arr.findIndex((row, i) => generateRowId(row, i, idKey) === rowId);
865
874
  api.data = {
866
875
  refresh: (options?: boolean | DataRefreshOptions) => void triggerRefresh(options, "refresh"),
867
876
  reload: (options: DataRefreshOptions = {}) => void triggerRefresh({ ...options, reason: options.reason ?? "reload" }, "reload"),
868
877
  resetAll: () => resetAllAndReload(),
878
+ getAllData: () => [...getBaseData()],
879
+ getRowData: (rowId: string) => {
880
+ const rows = tableRef.current.getRowModel().rows;
881
+ const row = rows.find((r: any) => r.id === rowId);
882
+ return row?.original as T | undefined;
883
+ },
884
+ getRowByIndex: (index: number) => tableRef.current.getRowModel().rows[index]?.original as T | undefined,
885
+ getDataCount: () => getBaseData().length,
886
+ getFilteredDataCount: () => tableRef.current.getFilteredRowModel().rows.length,
887
+ updateRow: (rowId: string, updates: Partial<T>) => {
888
+ const base = getBaseData();
889
+ const idx = getRowIndexById(base, rowId);
890
+ if (idx === -1) return;
891
+ const next = [...base];
892
+ next[idx] = { ...next[idx], ...updates } as T;
893
+ setServerData(next);
894
+ setServerTotal(next.length);
895
+ },
896
+ updateRowByIndex: (index: number, updates: Partial<T>) => {
897
+ const base = getBaseData();
898
+ if (index < 0 || index >= base.length) return;
899
+ const next = [...base];
900
+ next[index] = { ...next[index], ...updates } as T;
901
+ setServerData(next);
902
+ setServerTotal(next.length);
903
+ },
904
+ insertRow: (newRow: T, index?: number) => {
905
+ const base = getBaseData();
906
+ const next = index == null ? [...base, newRow] : [...base.slice(0, index), newRow, ...base.slice(index)];
907
+ setServerData(next);
908
+ setServerTotal(next.length);
909
+ },
910
+ deleteRow: (rowId: string) => {
911
+ const base = getBaseData();
912
+ const idx = getRowIndexById(base, rowId);
913
+ if (idx === -1) return;
914
+ const next = base.filter((_, i) => i !== idx);
915
+ setServerData(next);
916
+ setServerTotal(next.length);
917
+ },
918
+ deleteRowByIndex: (index: number) => {
919
+ const base = getBaseData();
920
+ if (index < 0 || index >= base.length) return;
921
+ const next = base.filter((_, i) => i !== index);
922
+ setServerData(next);
923
+ setServerTotal(next.length);
924
+ },
925
+ deleteSelectedRows: () => {
926
+ const state = tableRef.current.getSelectionState?.();
927
+ if (!state || state.type !== "include" || !state.ids.length) return;
928
+ const base = getBaseData();
929
+ const ids = new Set(state.ids);
930
+ const next = base.filter((row, i) => !ids.has(generateRowId(row, i, idKey)));
931
+ setServerData(next);
932
+ setServerTotal(next.length);
933
+ tableRef.current.deselectAll?.();
934
+ },
935
+ replaceAllData: (newData: T[]) => {
936
+ setServerData(newData);
937
+ setServerTotal(newData.length);
938
+ },
939
+ updateMultipleRows: (updates: Array<{ rowId: string; data: Partial<T> }>) => {
940
+ const base = getBaseData();
941
+ const next = [...base];
942
+ for (const { rowId, data: u } of updates) {
943
+ const idx = getRowIndexById(next, rowId);
944
+ if (idx !== -1) next[idx] = { ...next[idx], ...u } as T;
945
+ }
946
+ setServerData(next);
947
+ setServerTotal(next.length);
948
+ },
949
+ insertMultipleRows: (newRows: T[], startIndex?: number) => {
950
+ const base = getBaseData();
951
+ const idx = startIndex ?? base.length;
952
+ const next = [...base.slice(0, idx), ...newRows, ...base.slice(idx)];
953
+ setServerData(next);
954
+ setServerTotal(next.length);
955
+ },
956
+ deleteMultipleRows: (rowIds: string[]) => {
957
+ const ids = new Set(rowIds);
958
+ const base = getBaseData();
959
+ const next = base.filter((row, i) => !ids.has(generateRowId(row, i, idKey)));
960
+ setServerData(next);
961
+ setServerTotal(next.length);
962
+ },
963
+ updateField: (rowId: string, fieldName: keyof T, value: any) => {
964
+ api.data.updateRow(rowId, { [fieldName]: value } as Partial<T>);
965
+ },
966
+ updateFieldByIndex: (index: number, fieldName: keyof T, value: any) => {
967
+ api.data.updateRowByIndex(index, { [fieldName]: value } as Partial<T>);
968
+ },
969
+ findRows: (predicate: (row: T) => boolean) => getBaseData().filter(predicate),
970
+ findRowIndex: (predicate: (row: T) => boolean) => getBaseData().findIndex(predicate),
971
+ } as any;
869
972
 
870
- getAllData: () => {
871
- const sData = serverDataRef.current;
872
- const base = sData !== null ? sData : dataRef.current;
873
- return [...base];
973
+ // --- layout (save/restore column visibility, order, sizing, pinning)
974
+ api.layout = {
975
+ saveLayout: () => {
976
+ const s = tableRef.current.getState();
977
+ return {
978
+ columnVisibility: s.columnVisibility ?? {},
979
+ columnOrder: s.columnOrder ?? [],
980
+ columnSizing: s.columnSizing ?? {},
981
+ columnPinning: s.columnPinning ?? { left: [], right: [] },
982
+ pagination: s.pagination ?? { pageIndex: 0, pageSize: 10 },
983
+ globalFilter: s.globalFilter ?? "",
984
+ columnFilter: s.columnFilter ?? [],
985
+ };
874
986
  },
875
- getDataCount: () => {
876
- const sData = serverDataRef.current;
877
- const base = sData !== null ? sData : dataRef.current;
878
- return base.length;
987
+ restoreLayout: (layout: any) => {
988
+
989
+ if (layout.columnVisibility) dispatch({ type: "SET_COLUMN_VISIBILITY", payload: layout.columnVisibility });
990
+ if (layout.columnOrder) { dispatch({ type: "SET_COLUMN_ORDER", payload: layout.columnOrder }); onColumnDragEndRef.current?.(layout.columnOrder); }
991
+ if (layout.columnSizing) { dispatch({ type: "SET_COLUMN_SIZING", payload: layout.columnSizing }); onColumnSizingChangeRef.current?.(layout.columnSizing); }
992
+ if (layout.columnPinning) { dispatch({ type: "SET_COLUMN_PINNING", payload: layout.columnPinning }); onColumnPinningChangeRef.current?.(layout.columnPinning); }
993
+ if (layout.pagination && enablePagination) dispatch({ type: "SET_PAGINATION", payload: layout.pagination as any });
994
+ if (layout.globalFilter !== undefined) dispatch({ type: "SET_GLOBAL_FILTER_RESET_PAGE", payload: layout.globalFilter });
995
+ if (layout.columnFilter) dispatch({ type: "SET_COLUMN_FILTER", payload: layout.columnFilter as any });
996
+ },
997
+ resetLayout: () => {
998
+ const vis = initialStateConfig.columnVisibility || {};
999
+ const order = initialStateConfig.columnOrder || [];
1000
+ const sizing = initialStateConfig.columnSizing || {};
1001
+ const pinning = initialStateConfig.columnPinning || { left: [] as string[], right: [] as string[] };
1002
+ dispatch({ type: "SET_COLUMN_VISIBILITY", payload: vis });
1003
+ dispatch({ type: "SET_COLUMN_ORDER", payload: order });
1004
+ dispatch({ type: "SET_COLUMN_SIZING", payload: sizing });
1005
+ dispatch({ type: "SET_COLUMN_PINNING", payload: pinning });
1006
+ dispatch({ type: "SET_PAGINATION", payload: { pageIndex: 0, pageSize: 10 } });
1007
+ dispatch({ type: "SET_GLOBAL_FILTER_RESET_PAGE", payload: "" });
1008
+ dispatch({ type: "SET_COLUMN_FILTER", payload: [] });
1009
+ onColumnDragEndRef.current?.(order);
1010
+ onColumnSizingChangeRef.current?.(sizing);
1011
+ onColumnPinningChangeRef.current?.(pinning);
1012
+ },
1013
+ resetAll: () => {
1014
+ api.layout.resetLayout();
1015
+ resetAllAndReload();
879
1016
  },
880
- getFilteredDataCount: () => tableRef.current.getFilteredRowModel().rows.length,
881
1017
  } as any;
882
1018
 
883
1019
  // --- sorting/pagination/filtering - dispatch + callbacks + server fetch policies
@@ -888,6 +1024,12 @@ export function useDataTableEngine<T extends Record<string, any>>(
888
1024
  nextFetchDelayRef.current = 0;
889
1025
  dispatch({ type: "SET_SORTING_RESET_PAGE", payload: cleaned });
890
1026
  },
1027
+ sortColumn: (columnId: string, direction: 'asc' | 'desc' | false) => {
1028
+ const next: SortingState = direction === false ? [] : [{ id: columnId, desc: direction === 'desc' }];
1029
+ onSortingChangeRef.current?.(next);
1030
+ nextFetchDelayRef.current = 0;
1031
+ dispatch({ type: "SET_SORTING_RESET_PAGE", payload: next });
1032
+ },
891
1033
  clearSorting: () => {
892
1034
  onSortingChangeRef.current?.([]);
893
1035
  nextFetchDelayRef.current = 0;
@@ -909,12 +1051,25 @@ export function useDataTableEngine<T extends Record<string, any>>(
909
1051
  nextFetchDelayRef.current = 0;
910
1052
  dispatch({ type: "SET_PAGINATION", payload: next });
911
1053
  },
1054
+ nextPage: () => {
1055
+ const prev = uiRef.current.pagination;
1056
+ api.pagination.goToPage(Math.min(prev.pageIndex + 1, Math.max(0, Math.ceil((tableTotalRow ?? 0) / prev.pageSize) - 1)));
1057
+ },
1058
+ previousPage: () => {
1059
+ const prev = uiRef.current.pagination;
1060
+ api.pagination.goToPage(Math.max(0, prev.pageIndex - 1));
1061
+ },
912
1062
  setPageSize: (pageSize: number) => {
913
1063
  const next = { pageIndex: 0, pageSize };
914
1064
  onPaginationChangeRef.current?.(next);
915
1065
  nextFetchDelayRef.current = 0;
916
1066
  dispatch({ type: "SET_PAGINATION", payload: next });
917
1067
  },
1068
+ goToFirstPage: () => api.pagination.goToPage(0),
1069
+ goToLastPage: () => {
1070
+ const prev = uiRef.current.pagination;
1071
+ api.pagination.goToPage(Math.max(0, Math.ceil((tableTotalRow ?? 0) / prev.pageSize) - 1));
1072
+ },
918
1073
  resetPagination: () => {
919
1074
  const next = (initialStateConfig.pagination || { pageIndex: 0, pageSize: 10 }) as any;
920
1075
  onPaginationChangeRef.current?.(next);
@@ -935,11 +1090,24 @@ export function useDataTableEngine<T extends Record<string, any>>(
935
1090
  dispatch({ type: "SET_GLOBAL_FILTER_RESET_PAGE", payload: "" });
936
1091
  },
937
1092
  setColumnFilters: (filters: ColumnFilterState, isApply = false) => handleColumnFilterChangeHandler(filters, isApply),
1093
+ addColumnFilter: (columnId: string, operator: string, value: any) => tableRef.current.addColumnFilter?.(columnId, operator, value),
1094
+ removeColumnFilter: (filterId: string) => tableRef.current.removeColumnFilter?.(filterId),
1095
+ clearAllFilters: () => tableRef.current.resetColumnFilter?.(),
1096
+ resetFilters: () => {
1097
+ const reset = (initialStateConfig.columnFilter ?? DEFAULT_INITIAL_STATE.columnFilter) as ColumnFilterState;
1098
+ handleColumnFilterChangeHandler(reset, true);
1099
+ },
938
1100
  } as any;
939
1101
 
940
1102
  api.columnVisibility = {
941
1103
  showColumn: (id: string) => dispatch({ type: "SET_COLUMN_VISIBILITY", payload: { ...uiRef.current.columnVisibility, [id]: true } }),
942
1104
  hideColumn: (id: string) => dispatch({ type: "SET_COLUMN_VISIBILITY", payload: { ...uiRef.current.columnVisibility, [id]: false } }),
1105
+ toggleColumn: (id: string) => dispatch({ type: "SET_COLUMN_VISIBILITY", payload: { ...uiRef.current.columnVisibility, [id]: !uiRef.current.columnVisibility[id] } }),
1106
+ showAllColumns: () => dispatch({ type: "SET_COLUMN_VISIBILITY", payload: {} }),
1107
+ hideAllColumns: () => {
1108
+ const all = tableRef.current.getAllLeafColumns().reduce((acc, col) => ({ ...acc, [col.id]: false }), {} as Record<string, boolean>);
1109
+ dispatch({ type: "SET_COLUMN_VISIBILITY", payload: all });
1110
+ },
943
1111
  resetColumnVisibility: () => dispatch({ type: "SET_COLUMN_VISIBILITY", payload: initialStateConfig.columnVisibility || {} }),
944
1112
  } as any;
945
1113
 
@@ -948,10 +1116,41 @@ export function useDataTableEngine<T extends Record<string, any>>(
948
1116
  dispatch({ type: "SET_COLUMN_ORDER", payload: next });
949
1117
  onColumnDragEndRef.current?.(next);
950
1118
  },
1119
+ moveColumn: (columnId: string, toIndex: number) => {
1120
+ const order = uiRef.current.columnOrder.length ? uiRef.current.columnOrder : tableRef.current.getAllLeafColumns().map((c: any) => c.id);
1121
+ const from = order.indexOf(columnId);
1122
+ if (from === -1 || toIndex < 0 || toIndex >= order.length) return;
1123
+ const next = [...order];
1124
+ next.splice(from, 1);
1125
+ next.splice(toIndex, 0, columnId);
1126
+ dispatch({ type: "SET_COLUMN_ORDER", payload: next });
1127
+ onColumnDragEndRef.current?.(next);
1128
+ },
951
1129
  resetColumnOrder: () => dispatch({ type: "SET_COLUMN_ORDER", payload: initialStateConfig.columnOrder || [] }),
952
1130
  } as any;
953
1131
 
954
1132
  api.columnPinning = {
1133
+ pinColumnLeft: (columnId: string) => {
1134
+ const cur = uiRef.current.columnPinning;
1135
+ const left = cur.left.includes(columnId) ? cur.left : [...cur.left.filter((id: string) => id !== columnId), columnId];
1136
+ const right = cur.right.filter((id: string) => id !== columnId);
1137
+ dispatch({ type: "SET_COLUMN_PINNING", payload: { left, right } });
1138
+ onColumnPinningChangeRef.current?.({ left, right });
1139
+ },
1140
+ pinColumnRight: (columnId: string) => {
1141
+ const cur = uiRef.current.columnPinning;
1142
+ const left = cur.left.filter((id: string) => id !== columnId);
1143
+ const right = cur.right.includes(columnId) ? cur.right : [...cur.right.filter((id: string) => id !== columnId), columnId];
1144
+ dispatch({ type: "SET_COLUMN_PINNING", payload: { left, right } });
1145
+ onColumnPinningChangeRef.current?.({ left, right });
1146
+ },
1147
+ unpinColumn: (columnId: string) => {
1148
+ const cur = uiRef.current.columnPinning;
1149
+ const left = cur.left.filter((id: string) => id !== columnId);
1150
+ const right = cur.right.filter((id: string) => id !== columnId);
1151
+ dispatch({ type: "SET_COLUMN_PINNING", payload: { left, right } });
1152
+ onColumnPinningChangeRef.current?.({ left, right });
1153
+ },
955
1154
  setPinning: (next: ColumnPinningState) => {
956
1155
  dispatch({ type: "SET_COLUMN_PINNING", payload: next });
957
1156
  onColumnPinningChangeRef.current?.(next);
@@ -960,17 +1159,27 @@ export function useDataTableEngine<T extends Record<string, any>>(
960
1159
  } as any;
961
1160
 
962
1161
  api.columnResizing = {
1162
+ resizeColumn: (columnId: string, width: number) => {
1163
+ const cur = uiRef.current.columnSizing;
1164
+ dispatch({ type: "SET_COLUMN_SIZING", payload: { ...cur, [columnId]: width } });
1165
+ onColumnSizingChangeRef.current?.({ ...cur, [columnId]: width });
1166
+ },
1167
+ autoSizeColumn: (columnId: string) => { void columnId; /* no-op: would require measure; use reset for default */ },
1168
+ autoSizeAllColumns: () => { /* no-op */ },
963
1169
  resetColumnSizing: () => dispatch({ type: "SET_COLUMN_SIZING", payload: initialStateConfig.columnSizing || {} }),
964
1170
  } as any;
965
1171
 
966
1172
  api.selection = {
1173
+ selectRow: (rowId: string) => tableRef.current.selectRow?.(rowId),
1174
+ deselectRow: (rowId: string) => tableRef.current.deselectRow?.(rowId),
1175
+ toggleRowSelection: (rowId: string) => tableRef.current.toggleRowSelected?.(rowId),
1176
+ selectAll: () => tableRef.current.selectAll?.(),
1177
+ deselectAll: () => tableRef.current.deselectAll?.(),
1178
+ toggleSelectAll: () => tableRef.current.toggleAllRowsSelected?.(),
967
1179
  getSelectionState: () => tableRef.current.getSelectionState?.() || ({ ids: [], type: "include" } as const),
968
1180
  getSelectedRows: () => tableRef.current.getSelectedRows(),
969
1181
  getSelectedCount: () => tableRef.current.getSelectedCount(),
970
1182
  isRowSelected: (rowId: string) => tableRef.current.getIsRowSelected(rowId) || false,
971
- // keep using your table extension methods if you have them:
972
- selectAll: () => tableRef.current.selectAll?.(),
973
- deselectAll: () => tableRef.current.deselectAll?.(),
974
1183
  } as any;
975
1184
 
976
1185
  // --- export API (use your existing exportClientData/exportServerData)
@@ -1081,10 +1290,35 @@ export function useDataTableEngine<T extends Record<string, any>>(
1081
1290
  });
1082
1291
  },
1083
1292
 
1293
+ exportServerData: async (options: { format: 'csv' | 'excel'; filename?: string; fetchData: (filters?: Partial<any>, selection?: SelectionState, signal?: AbortSignal) => Promise<any>; pageSize?: number; includeHeaders?: boolean; chunkSize?: number; strictTotalCheck?: boolean; sanitizeCSV?: boolean }) => {
1294
+ const { format, filename: fn = exportFilename, fetchData: customFetchData, chunkSize: cs = exportChunkSize, strictTotalCheck: st = exportStrictTotalCheck, sanitizeCSV: san = exportSanitizeCSV } = options;
1295
+ await runExportWithPolicy({
1296
+ format,
1297
+ filename: fn,
1298
+ mode: "server",
1299
+ execute: async (controller) => {
1300
+ await exportServerData(tableRef.current, {
1301
+ format,
1302
+ filename: fn,
1303
+ fetchData: customFetchData,
1304
+ currentFilters: { globalFilter: tableRef.current.getState().globalFilter, columnFilter: tableRef.current.getState().columnFilter, sorting: tableRef.current.getState().sorting, pagination: tableRef.current.getState().pagination },
1305
+ selection: tableRef.current.getSelectionState?.(),
1306
+ onProgress: handleExportProgressInternal,
1307
+ onComplete: onExportCompleteRef.current,
1308
+ onError: onExportErrorRef.current,
1309
+ onStateChange: (s: any) => handleExportStateChangeInternal({ ...s, mode: "server", format, filename: fn, queueLength: queuedExportCount } as any),
1310
+ signal: controller.signal,
1311
+ chunkSize: cs,
1312
+ strictTotalCheck: st,
1313
+ sanitizeCSV: san,
1314
+ });
1315
+ },
1316
+ });
1317
+ },
1084
1318
  isExporting: () => exportControllerRef.current != null,
1085
1319
  cancelExport: () => handleCancelExport(),
1086
1320
  } as any;
1087
- }, [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]);
1321
+ }, [dataMode, exportChunkSize, exportFilename, exportSanitizeCSV, exportStrictTotalCheck, fetchData, handleCancelExport, handleColumnFilterChangeHandler, handleExportProgressInternal, handleExportStateChangeInternal, initialStateConfig, isServerMode, isServerPagination, isServerSorting, resetAllAndReload, resetPageToFirst, runExportWithPolicy, triggerRefresh, queuedExportCount, tableTotalRow, idKey, tableRef, uiRef, serverDataRef, dataRef, onSortingChangeRef, onPaginationChangeRef, onGlobalFilterChangeRef, onColumnDragEndRef, onColumnPinningChangeRef, onColumnSizingChangeRef, onServerExportRef, onExportCompleteRef, onExportErrorRef]);
1088
1322
 
1089
1323
  // --- imperative handlers (used by TanStack callbacks above or view)
1090
1324
  const handleSortingChange = useCallback(