@ackplus/react-tanstack-data-table 1.1.12 → 1.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -11
- package/dist/lib/components/droupdown/menu-dropdown.d.ts.map +1 -1
- package/dist/lib/components/droupdown/menu-dropdown.js +8 -1
- package/dist/lib/components/filters/filter-value-input.js +2 -2
- package/dist/lib/components/pagination/data-table-pagination.d.ts.map +1 -1
- package/dist/lib/components/pagination/data-table-pagination.js +10 -1
- package/dist/lib/components/toolbar/table-export-control.d.ts.map +1 -1
- package/dist/lib/components/toolbar/table-export-control.js +46 -12
- package/dist/lib/contexts/data-table-context.d.ts +7 -10
- package/dist/lib/contexts/data-table-context.d.ts.map +1 -1
- package/dist/lib/contexts/data-table-context.js +5 -1
- package/dist/lib/data-table.d.ts.map +1 -1
- package/dist/lib/data-table.js +517 -237
- package/dist/lib/features/column-filter.feature.js +38 -21
- package/dist/lib/features/selection.feature.d.ts.map +1 -1
- package/dist/lib/features/selection.feature.js +11 -3
- package/dist/lib/types/column.types.d.ts +19 -0
- package/dist/lib/types/column.types.d.ts.map +1 -1
- package/dist/lib/types/data-table-api.d.ts +24 -18
- package/dist/lib/types/data-table-api.d.ts.map +1 -1
- package/dist/lib/types/data-table.types.d.ts +37 -10
- package/dist/lib/types/data-table.types.d.ts.map +1 -1
- package/dist/lib/types/export.types.d.ts +57 -13
- package/dist/lib/types/export.types.d.ts.map +1 -1
- package/dist/lib/types/slots.types.d.ts +3 -1
- package/dist/lib/types/slots.types.d.ts.map +1 -1
- package/dist/lib/types/table.types.d.ts +1 -3
- package/dist/lib/types/table.types.d.ts.map +1 -1
- package/dist/lib/utils/debounced-fetch.utils.d.ts +8 -4
- package/dist/lib/utils/debounced-fetch.utils.d.ts.map +1 -1
- package/dist/lib/utils/debounced-fetch.utils.js +63 -14
- package/dist/lib/utils/export-utils.d.ts +14 -4
- package/dist/lib/utils/export-utils.d.ts.map +1 -1
- package/dist/lib/utils/export-utils.js +362 -66
- package/package.json +4 -2
- package/src/lib/components/droupdown/menu-dropdown.tsx +9 -3
- package/src/lib/components/filters/filter-value-input.tsx +2 -2
- package/src/lib/components/pagination/data-table-pagination.tsx +14 -2
- package/src/lib/components/toolbar/table-export-control.tsx +65 -9
- package/src/lib/contexts/data-table-context.tsx +16 -2
- package/src/lib/data-table.tsx +647 -231
- package/src/lib/features/column-filter.feature.ts +40 -19
- package/src/lib/features/selection.feature.ts +11 -5
- package/src/lib/types/column.types.ts +20 -1
- package/src/lib/types/data-table-api.ts +33 -15
- package/src/lib/types/data-table.types.ts +59 -3
- package/src/lib/types/export.types.ts +79 -10
- package/src/lib/types/slots.types.ts +3 -1
- package/src/lib/types/table.types.ts +1 -3
- package/src/lib/utils/debounced-fetch.utils.ts +90 -18
- package/src/lib/utils/export-utils.ts +496 -69
package/README.md
CHANGED
|
@@ -129,7 +129,9 @@ function MyDataTable() {
|
|
|
129
129
|
|------|------|---------|-------------|
|
|
130
130
|
| `dataMode` | `'client' \| 'server'` | `'client'` | Data management mode |
|
|
131
131
|
| `initialLoadData` | `boolean` | `true` | Load data on component mount |
|
|
132
|
-
| `onFetchData` | `(filters) => Promise<{data, total}>` | - | Server-side data fetching |
|
|
132
|
+
| `onFetchData` | `(filters, meta?) => Promise<{data, total}>` | - | Server-side data fetching with optional refresh metadata (`reason`, `force`) |
|
|
133
|
+
| `onRefreshData` | `(context) => void \| Promise<void>` | - | External refresh handler for controlled data sources (React Query, SWR, etc.) |
|
|
134
|
+
| `onDataChange` | `(nextData, context) => void` | - | Receives mutations from `apiRef.data.*` when data is controlled by props |
|
|
133
135
|
| `onDataStateChange` | `(state) => void` | - | Called when table state changes |
|
|
134
136
|
| `totalRow` | `number` | `0` | Total rows for server-side pagination |
|
|
135
137
|
|
|
@@ -165,10 +167,10 @@ This allows for efficient handling of large datasets where you might select "all
|
|
|
165
167
|
|
|
166
168
|
| Prop | Type | Default | Description |
|
|
167
169
|
|------|------|---------|-------------|
|
|
168
|
-
| `enablePagination` | `boolean` | `
|
|
170
|
+
| `enablePagination` | `boolean` | `false` | Enable pagination |
|
|
169
171
|
| `paginationMode` | `'client' \| 'server'` | `'client'` | Pagination mode |
|
|
170
172
|
| `onPaginationChange` | `(pagination: PaginationState) => void` | - | Pagination change callback |
|
|
171
|
-
| `initialState.pagination` | `{pageIndex: number, pageSize: number}` | `{pageIndex: 0, pageSize:
|
|
173
|
+
| `initialState.pagination` | `{pageIndex: number, pageSize: number}` | `{pageIndex: 0, pageSize: 10}` | Initial pagination state |
|
|
172
174
|
|
|
173
175
|
### Filtering & Search
|
|
174
176
|
|
|
@@ -206,12 +208,17 @@ This allows for efficient handling of large datasets where you might select "all
|
|
|
206
208
|
|
|
207
209
|
| Prop | Type | Default | Description |
|
|
208
210
|
|------|------|---------|-------------|
|
|
209
|
-
| `enableExport` | `boolean` | `
|
|
211
|
+
| `enableExport` | `boolean` | `false` | Enable data export |
|
|
210
212
|
| `exportFilename` | `string` | `'export'` | Default export filename |
|
|
213
|
+
| `exportConcurrency` | `'ignoreIfRunning' \| 'cancelAndRestart' \| 'queue'` | `'cancelAndRestart'` | How export requests are handled while another export is running |
|
|
214
|
+
| `exportChunkSize` | `number` | `1000` | Chunk size for server export pagination |
|
|
215
|
+
| `exportStrictTotalCheck` | `boolean` | `false` | Validate server export row count against reported total |
|
|
216
|
+
| `exportSanitizeCSV` | `boolean` | `true` | Protect CSV against spreadsheet formula injection |
|
|
211
217
|
| `onExportProgress` | `(progress: {processedRows?, totalRows?, percentage?}) => void` | - | Export progress callback |
|
|
212
218
|
| `onExportComplete` | `(result: {success: boolean, filename: string, totalRows: number}) => void` | - | Export completion callback |
|
|
213
219
|
| `onExportError` | `(error: {message: string, code: string}) => void` | - | Export error callback |
|
|
214
|
-
| `
|
|
220
|
+
| `onExportStateChange` | `(state: ExportStateChange) => void` | - | Export lifecycle callback (`starting`, `fetching`, `processing`, `downloading`, `completed`, `cancelled`, `error`) |
|
|
221
|
+
| `onServerExport` | `(filters?: Partial<TableState>, selection?: SelectionState, signal?: AbortSignal) => Promise<ServerExportResult<any>>` | - | Server-side export handler (paged data or file URL/blob streaming) |
|
|
215
222
|
| `onExportCancel` | `() => void` | - | Export cancellation callback |
|
|
216
223
|
|
|
217
224
|
### Expandable Rows (Enhanced Slot System)
|
|
@@ -533,6 +540,98 @@ function ServerSideTable() {
|
|
|
533
540
|
}
|
|
534
541
|
```
|
|
535
542
|
|
|
543
|
+
### React Query Controlled Data (No `onFetchData`)
|
|
544
|
+
|
|
545
|
+
```tsx
|
|
546
|
+
import { useMemo, useRef, useState } from 'react';
|
|
547
|
+
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
548
|
+
import { DataTable, DataTableApi, SelectionState, TableState } from '@ackplus/react-tanstack-data-table';
|
|
549
|
+
|
|
550
|
+
function ReactQueryTable() {
|
|
551
|
+
const apiRef = useRef<DataTableApi<User>>(null);
|
|
552
|
+
const queryClient = useQueryClient();
|
|
553
|
+
const [tableState, setTableState] = useState<Partial<TableState>>({
|
|
554
|
+
pagination: { pageIndex: 0, pageSize: 10 },
|
|
555
|
+
sorting: [],
|
|
556
|
+
globalFilter: '',
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
const queryKey = useMemo(() => ['users', tableState], [tableState]);
|
|
560
|
+
|
|
561
|
+
const usersQuery = useQuery({
|
|
562
|
+
queryKey,
|
|
563
|
+
queryFn: async () => {
|
|
564
|
+
const res = await fetch('/api/users/query', {
|
|
565
|
+
method: 'POST',
|
|
566
|
+
headers: { 'Content-Type': 'application/json' },
|
|
567
|
+
body: JSON.stringify(tableState),
|
|
568
|
+
});
|
|
569
|
+
return res.json() as Promise<{ data: User[]; total: number }>;
|
|
570
|
+
},
|
|
571
|
+
placeholderData: (prev) => prev,
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
const applyUserPatch = async (id: string, patch: Partial<User>) => {
|
|
575
|
+
const res = await fetch(`/api/users/${id}`, {
|
|
576
|
+
method: 'PATCH',
|
|
577
|
+
headers: { 'Content-Type': 'application/json' },
|
|
578
|
+
body: JSON.stringify(patch),
|
|
579
|
+
});
|
|
580
|
+
const updated = (await res.json()) as User;
|
|
581
|
+
apiRef.current?.data.updateRow(String(updated.id), updated);
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
const handleServerExport = async (
|
|
585
|
+
filters?: Partial<TableState>,
|
|
586
|
+
selection?: SelectionState,
|
|
587
|
+
signal?: AbortSignal,
|
|
588
|
+
) => {
|
|
589
|
+
const res = await fetch('/api/users/export', {
|
|
590
|
+
method: 'POST',
|
|
591
|
+
headers: { 'Content-Type': 'application/json' },
|
|
592
|
+
body: JSON.stringify({ filters, selection }),
|
|
593
|
+
signal,
|
|
594
|
+
});
|
|
595
|
+
return res.json() as Promise<{ data: User[]; total: number }>;
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
return (
|
|
599
|
+
<DataTable
|
|
600
|
+
ref={apiRef}
|
|
601
|
+
dataMode="server"
|
|
602
|
+
columns={columns}
|
|
603
|
+
data={usersQuery.data?.data ?? []}
|
|
604
|
+
totalRow={usersQuery.data?.total ?? 0}
|
|
605
|
+
loading={usersQuery.isFetching}
|
|
606
|
+
enablePagination
|
|
607
|
+
enableSorting
|
|
608
|
+
enableGlobalFilter
|
|
609
|
+
onServerExport={handleServerExport}
|
|
610
|
+
onDataStateChange={setTableState}
|
|
611
|
+
// Fetch-on-state-change stays outside DataTable
|
|
612
|
+
onRefreshData={({ options }) =>
|
|
613
|
+
queryClient.invalidateQueries({
|
|
614
|
+
queryKey: ['users'],
|
|
615
|
+
exact: false,
|
|
616
|
+
refetchType: options.force ? 'all' : 'active',
|
|
617
|
+
})
|
|
618
|
+
}
|
|
619
|
+
// Row mutation sync stays outside DataTable
|
|
620
|
+
onDataChange={(nextData) => {
|
|
621
|
+
queryClient.setQueryData(queryKey, (prev: any) => {
|
|
622
|
+
if (!prev) return prev;
|
|
623
|
+
return { ...prev, data: nextData };
|
|
624
|
+
});
|
|
625
|
+
}}
|
|
626
|
+
/>
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// Manual refresh
|
|
631
|
+
apiRef.current?.data.refresh(); // normal refresh
|
|
632
|
+
apiRef.current?.data.refresh({ force: true, reason: 'manual-hard-refresh' }); // hard refresh
|
|
633
|
+
```
|
|
634
|
+
|
|
536
635
|
### Row Selection with Bulk Actions and Enhanced Slot System
|
|
537
636
|
|
|
538
637
|
```tsx
|
|
@@ -738,6 +837,7 @@ function ManageableColumnsTable() {
|
|
|
738
837
|
```tsx
|
|
739
838
|
function ExportableTable() {
|
|
740
839
|
const [exportProgress, setExportProgress] = useState(null);
|
|
840
|
+
const [exportState, setExportState] = useState(null);
|
|
741
841
|
|
|
742
842
|
const handleExportProgress = (progress) => {
|
|
743
843
|
setExportProgress(progress);
|
|
@@ -753,7 +853,12 @@ function ExportableTable() {
|
|
|
753
853
|
data={data}
|
|
754
854
|
enableExport
|
|
755
855
|
exportFilename="users-export"
|
|
856
|
+
exportConcurrency="queue"
|
|
857
|
+
exportChunkSize={500}
|
|
858
|
+
exportStrictTotalCheck
|
|
859
|
+
exportSanitizeCSV
|
|
756
860
|
onExportProgress={handleExportProgress}
|
|
861
|
+
onExportStateChange={setExportState}
|
|
757
862
|
onExportComplete={handleExportComplete}
|
|
758
863
|
onExportError={(error) => console.error('Export failed:', error)}
|
|
759
864
|
/>
|
|
@@ -761,6 +866,30 @@ function ExportableTable() {
|
|
|
761
866
|
}
|
|
762
867
|
```
|
|
763
868
|
|
|
869
|
+
### Server Export with Streaming File Response
|
|
870
|
+
|
|
871
|
+
```tsx
|
|
872
|
+
const handleServerExport = async (filters, selection, signal) => {
|
|
873
|
+
const res = await fetch('/api/users/export-stream', {
|
|
874
|
+
method: 'POST',
|
|
875
|
+
headers: { 'Content-Type': 'application/json' },
|
|
876
|
+
body: JSON.stringify({ filters, selection }),
|
|
877
|
+
signal,
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
// Option 1: backend returns generated file payload directly
|
|
881
|
+
const blob = await res.blob();
|
|
882
|
+
return {
|
|
883
|
+
blob,
|
|
884
|
+
filename: 'users-stream-export.csv',
|
|
885
|
+
mimeType: 'text/csv',
|
|
886
|
+
};
|
|
887
|
+
|
|
888
|
+
// Option 2: backend returns URL (alternative shape)
|
|
889
|
+
// return { fileUrl: signedDownloadUrl, filename: 'users-export.csv' };
|
|
890
|
+
};
|
|
891
|
+
```
|
|
892
|
+
|
|
764
893
|
## 🎛️ API Reference
|
|
765
894
|
|
|
766
895
|
### DataTable Component
|
|
@@ -790,6 +919,9 @@ interface DataTableColumn<T> extends ColumnDef<T> {
|
|
|
790
919
|
|
|
791
920
|
// Export
|
|
792
921
|
hideInExport?: boolean;
|
|
922
|
+
exportHeader?: string | ((context) => string);
|
|
923
|
+
exportValue?: (context) => any;
|
|
924
|
+
exportFormat?: 'auto' | 'string' | 'number' | 'boolean' | 'json' | 'date' | ((context) => any);
|
|
793
925
|
}
|
|
794
926
|
```
|
|
795
927
|
|
|
@@ -877,13 +1009,13 @@ function MyComponent() {
|
|
|
877
1009
|
- `selection.deselectAll()` - Deselect all rows
|
|
878
1010
|
- `selection.toggleSelectAll()` - Toggle select all
|
|
879
1011
|
- `selection.getSelectionState()` - Get current selection state
|
|
880
|
-
- `selection.getSelectedRows()` - Get selected rows
|
|
1012
|
+
- `selection.getSelectedRows()` - Get selected rows currently loaded in the table
|
|
881
1013
|
- `selection.getSelectedCount()` - Get selected count
|
|
882
1014
|
- `selection.isRowSelected(rowId)` - Check if row is selected
|
|
883
1015
|
|
|
884
1016
|
**Data Management:**
|
|
885
|
-
- `data.refresh()` - Refresh data
|
|
886
|
-
- `data.reload()` - Reload data
|
|
1017
|
+
- `data.refresh(options?)` - Refresh data (`boolean` or `{ resetPagination?, force?, reason? }`)
|
|
1018
|
+
- `data.reload(options?)` - Reload data (`{ force?, reason?, resetPagination? }`)
|
|
887
1019
|
- `data.getAllData()` - Get all data
|
|
888
1020
|
- `data.getRowData(rowId)` - Get specific row data
|
|
889
1021
|
- `data.getRowByIndex(index)` - Get row by index
|
|
@@ -911,9 +1043,9 @@ function MyComponent() {
|
|
|
911
1043
|
- `layout.restoreLayout(layout)` - Restore saved layout
|
|
912
1044
|
|
|
913
1045
|
**Export:**
|
|
914
|
-
- `export.exportCSV(options?)` - Export to CSV
|
|
915
|
-
- `export.exportExcel(options?)` - Export to Excel
|
|
916
|
-
- `export.exportServerData(options)` - Server-side export
|
|
1046
|
+
- `export.exportCSV(options?)` - Export to CSV (`filename`, `chunkSize`, `strictTotalCheck`, `sanitizeCSV`)
|
|
1047
|
+
- `export.exportExcel(options?)` - Export to Excel (`filename`, `chunkSize`, `strictTotalCheck`)
|
|
1048
|
+
- `export.exportServerData(options)` - Server-side export (supports paged data, `blob`, or `fileUrl` responses)
|
|
917
1049
|
- `export.isExporting()` - Check if exporting
|
|
918
1050
|
- `export.cancelExport()` - Cancel export
|
|
919
1051
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu-dropdown.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/droupdown/menu-dropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAU,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACjE,OAAc,EAEV,YAAY,EACZ,SAAS,EAIZ,MAAM,OAAO,CAAC;AAGf,KAAK,aAAa,GAAG;IACjB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,IAAI,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,WAAW,GAAG;IACf,MAAM,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,iBACb,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAAC;IAC5C,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,SAAS,CAAC,GAAG,SAAS,GAAG,GAAG,CAAC;IACnE,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACzE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,OAAO,GAAG,OAAO,IAAI,CAAC;CAC5C;AAED,wBAAgB,YAAY,CAAC,EACzB,QAAQ,EACR,MAAM,EACN,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACX,EAAE,iBAAiB,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"menu-dropdown.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/droupdown/menu-dropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAU,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACjE,OAAc,EAEV,YAAY,EACZ,SAAS,EAIZ,MAAM,OAAO,CAAC;AAGf,KAAK,aAAa,GAAG;IACjB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,IAAI,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,WAAW,GAAG;IACf,MAAM,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,iBACb,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAAC;IAC5C,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,SAAS,CAAC,GAAG,SAAS,GAAG,GAAG,CAAC;IACnE,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACzE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,OAAO,GAAG,OAAO,IAAI,CAAC;CAC5C;AAED,wBAAgB,YAAY,CAAC,EACzB,QAAQ,EACR,MAAM,EACN,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACX,EAAE,iBAAiB,GAAG,YAAY,CAoElC"}
|
|
@@ -51,13 +51,20 @@ function MenuDropdown({ children, anchor, label, component, ...props }) {
|
|
|
51
51
|
setAnchorEl(null);
|
|
52
52
|
}, []);
|
|
53
53
|
const anchorNode = (0, react_1.useMemo)(() => {
|
|
54
|
+
var _a;
|
|
54
55
|
if (anchor) {
|
|
55
56
|
let node = anchor;
|
|
56
57
|
if (typeof anchor === 'function') {
|
|
57
58
|
node = anchor({ isOpen: isOpen });
|
|
58
59
|
}
|
|
60
|
+
const existingOnClick = (_a = node.props) === null || _a === void 0 ? void 0 : _a.onClick;
|
|
59
61
|
return (0, react_1.cloneElement)(node, {
|
|
60
|
-
onClick:
|
|
62
|
+
onClick: (event) => {
|
|
63
|
+
existingOnClick === null || existingOnClick === void 0 ? void 0 : existingOnClick(event);
|
|
64
|
+
if (!event.defaultPrevented) {
|
|
65
|
+
handleClick(event);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
61
68
|
});
|
|
62
69
|
}
|
|
63
70
|
return (0, jsx_runtime_1.jsx)(material_1.Button, { onClick: handleClick, children: label });
|
|
@@ -33,8 +33,8 @@ function FilterValueInput(props) {
|
|
|
33
33
|
}
|
|
34
34
|
// Select type with options
|
|
35
35
|
if (options && options.length > 0) {
|
|
36
|
-
// Multi-select for
|
|
37
|
-
if (operator === 'in') {
|
|
36
|
+
// Multi-select for set operators
|
|
37
|
+
if (operator === 'in' || operator === 'notIn') {
|
|
38
38
|
const currentValue = Array.isArray(filter.value) ? filter.value : [];
|
|
39
39
|
return ((0, jsx_runtime_1.jsxs)(material_1.FormControl, { size: "small", sx: {
|
|
40
40
|
flex: 1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-pagination.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/pagination/data-table-pagination.tsx"],"names":[],"mappings":"AACA,OAAO,EAAwB,oBAAoB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EAAQ,SAAS,
|
|
1
|
+
{"version":3,"file":"data-table-pagination.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/pagination/data-table-pagination.tsx"],"names":[],"mappings":"AACA,OAAO,EAAwB,oBAAoB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EAAQ,SAAS,EAAsB,MAAM,OAAO,CAAC;AAK5D,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CAAC,oBAAoB,EAAE,OAAO,GAAG,aAAa,GAAG,MAAM,GAAG,cAAc,GAAG,qBAAqB,CAAC;IACnJ,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KACpB,CAAC;IAEF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,oBAAoB,CAAC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,eAAO,MAAM,mBAAmB,KAqF9B,CAAC"}
|
|
@@ -10,6 +10,15 @@ const slot_helpers_1 = require("../../utils/slot-helpers");
|
|
|
10
10
|
exports.DataTablePagination = (0, react_1.memo)((props) => {
|
|
11
11
|
const { footerFilter = null, pagination, totalRow, containerSx, paginationProps, footerSx, ...otherProps } = props;
|
|
12
12
|
const { table, tableSize } = (0, data_table_context_1.useDataTableContext)();
|
|
13
|
+
const pageSize = (pagination === null || pagination === void 0 ? void 0 : pagination.pageSize) || 1;
|
|
14
|
+
const maxPageIndex = Math.max(0, Math.ceil(totalRow / pageSize) - 1);
|
|
15
|
+
const safePageIndex = (0, react_1.useMemo)(() => { var _a; return Math.min(Math.max((_a = pagination === null || pagination === void 0 ? void 0 : pagination.pageIndex) !== null && _a !== void 0 ? _a : 0, 0), maxPageIndex); }, [maxPageIndex, pagination === null || pagination === void 0 ? void 0 : pagination.pageIndex]);
|
|
16
|
+
(0, react_1.useEffect)(() => {
|
|
17
|
+
var _a;
|
|
18
|
+
if (((_a = pagination === null || pagination === void 0 ? void 0 : pagination.pageIndex) !== null && _a !== void 0 ? _a : 0) !== safePageIndex) {
|
|
19
|
+
table === null || table === void 0 ? void 0 : table.setPageIndex(safePageIndex);
|
|
20
|
+
}
|
|
21
|
+
}, [pagination === null || pagination === void 0 ? void 0 : pagination.pageIndex, safePageIndex, table]);
|
|
13
22
|
// Extract slot-specific props with enhanced merging
|
|
14
23
|
// const paginationSlotProps = extractSlotProps(slotProps, 'pagination');
|
|
15
24
|
// Merge all props for maximum flexibility
|
|
@@ -28,7 +37,7 @@ exports.DataTablePagination = (0, react_1.memo)((props) => {
|
|
|
28
37
|
size: tableSize === 'small' ? 'small' : 'medium',
|
|
29
38
|
count: totalRow,
|
|
30
39
|
rowsPerPage: pagination === null || pagination === void 0 ? void 0 : pagination.pageSize,
|
|
31
|
-
page:
|
|
40
|
+
page: safePageIndex,
|
|
32
41
|
onPageChange: (_, page) => {
|
|
33
42
|
// Use TanStack Table's native pagination methods
|
|
34
43
|
table.setPageIndex(page);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-export-control.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/table-export-control.tsx"],"names":[],"mappings":"AAEA,OAAO,EAQH,eAAe,EACf,OAAO,
|
|
1
|
+
{"version":3,"file":"table-export-control.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/table-export-control.tsx"],"names":[],"mappings":"AAEA,OAAO,EAQH,eAAe,EACf,OAAO,EAGV,MAAM,eAAe,CAAC;AAOvB,UAAU,uBAAuB;IAE7B,cAAc,CAAC,EAAE,MAAM,CAAC;IAMxB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,GAAE,uBAA4B,OAsMrE"}
|
|
@@ -14,7 +14,7 @@ const icons_1 = require("../../icons");
|
|
|
14
14
|
const slot_helpers_1 = require("../../utils/slot-helpers");
|
|
15
15
|
function TableExportControl(props = {}) {
|
|
16
16
|
const { exportFilename: propsExportFilename, iconButtonProps, tooltipProps, menuSx, menuItemProps, } = props;
|
|
17
|
-
const { apiRef, slots, slotProps, isExporting,
|
|
17
|
+
const { apiRef, slots, slotProps, isExporting, exportPhase, exportProgress, onCancelExport,
|
|
18
18
|
// Export callbacks from context (DataTable props)
|
|
19
19
|
exportFilename: contextExportFilename, } = (0, data_table_context_1.useDataTableContext)();
|
|
20
20
|
// Use props if provided, otherwise fall back to context values
|
|
@@ -45,23 +45,57 @@ function TableExportControl(props = {}) {
|
|
|
45
45
|
console.error('Export failed:', error);
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
|
+
const handleCancelExport = () => {
|
|
49
|
+
var _a;
|
|
50
|
+
if (onCancelExport) {
|
|
51
|
+
onCancelExport();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
(_a = apiRef === null || apiRef === void 0 ? void 0 : apiRef.current) === null || _a === void 0 ? void 0 : _a.export.cancelExport();
|
|
55
|
+
};
|
|
48
56
|
// Merge all props for maximum flexibility
|
|
49
57
|
const mergedIconButtonProps = (0, slot_helpers_1.mergeSlotProps)({
|
|
50
58
|
size: 'small',
|
|
51
|
-
disabled: isExporting,
|
|
52
59
|
sx: { flexShrink: 0 },
|
|
53
60
|
}, exportIconSlotProps, iconButtonProps || {});
|
|
54
61
|
const mergedMenuItemProps = (0, slot_helpers_1.mergeSlotProps)({
|
|
55
62
|
sx: { minWidth: 150 },
|
|
56
63
|
}, menuItemProps || {});
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
const progressPercentage = typeof (exportProgress === null || exportProgress === void 0 ? void 0 : exportProgress.percentage) === 'number'
|
|
65
|
+
? Math.max(0, Math.min(100, exportProgress.percentage))
|
|
66
|
+
: undefined;
|
|
67
|
+
const getPhaseLabel = () => {
|
|
68
|
+
switch (exportPhase) {
|
|
69
|
+
case 'fetching':
|
|
70
|
+
return 'Fetching rows from server...';
|
|
71
|
+
case 'processing':
|
|
72
|
+
return 'Preparing export file...';
|
|
73
|
+
case 'downloading':
|
|
74
|
+
return 'Downloading file...';
|
|
75
|
+
case 'starting':
|
|
76
|
+
return 'Starting export...';
|
|
77
|
+
default:
|
|
78
|
+
return 'Export in progress...';
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
return ((0, jsx_runtime_1.jsx)(menu_dropdown_1.MenuDropdown, { anchor: ((0, jsx_runtime_1.jsx)(material_1.Tooltip, { title: isExporting ? 'Export in progress...' : 'Export data', ...tooltipProps, children: (0, jsx_runtime_1.jsx)(material_1.IconButton, { ...mergedIconButtonProps, children: (0, jsx_runtime_1.jsx)(ExportIconSlot, { ...exportIconSlotProps }) }) })), children: ({ handleClose }) => {
|
|
82
|
+
var _a;
|
|
83
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: {
|
|
84
|
+
minWidth: 200,
|
|
85
|
+
...menuSx,
|
|
86
|
+
}, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle2", sx: { p: 2, pb: 1 }, children: "Export Format" }), (0, jsx_runtime_1.jsxs)(material_1.MenuItem, { onClick: () => {
|
|
87
|
+
handleExport('csv');
|
|
88
|
+
handleClose();
|
|
89
|
+
}, disabled: isExporting, ...mergedMenuItemProps, children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(CsvIconSlot, { ...csvIconSlotProps }) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: "CSV", secondary: "Comma-separated values" })] }), (0, jsx_runtime_1.jsxs)(material_1.MenuItem, { onClick: () => {
|
|
90
|
+
handleExport('excel');
|
|
91
|
+
handleClose();
|
|
92
|
+
}, disabled: isExporting, ...mergedMenuItemProps, children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(ExcelIconSlot, { ...excelIconSlotProps }) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: "Excel", secondary: "Microsoft Excel format" })] }), isExporting && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { px: 2, pb: 1 }, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "caption", color: "text.secondary", sx: { display: 'block', mb: 0.75 }, children: getPhaseLabel() }), (0, jsx_runtime_1.jsx)(material_1.LinearProgress, { variant: progressPercentage !== undefined ? 'determinate' : 'indeterminate', value: progressPercentage !== undefined ? progressPercentage : 0 }), ((exportProgress === null || exportProgress === void 0 ? void 0 : exportProgress.processedRows) !== undefined || (exportProgress === null || exportProgress === void 0 ? void 0 : exportProgress.totalRows) !== undefined) && ((0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "caption", color: "text.secondary", sx: { display: 'block', mt: 0.75 }, children: `${(_a = exportProgress === null || exportProgress === void 0 ? void 0 : exportProgress.processedRows) !== null && _a !== void 0 ? _a : 0}${(exportProgress === null || exportProgress === void 0 ? void 0 : exportProgress.totalRows) !== undefined ? ` / ${exportProgress.totalRows}` : ''}${progressPercentage !== undefined ? ` (${progressPercentage}%)` : ''}` }))] }), (0, jsx_runtime_1.jsx)(material_1.Divider, { sx: { my: 1 } }), (0, jsx_runtime_1.jsx)(material_1.MenuItem, { onClick: () => {
|
|
93
|
+
handleCancelExport();
|
|
94
|
+
handleClose();
|
|
95
|
+
}, ...mergedMenuItemProps, children: (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: "Cancel Export", secondary: "Stop current export job", slotProps: {
|
|
96
|
+
primary: {
|
|
97
|
+
color: 'error.main',
|
|
98
|
+
},
|
|
99
|
+
} }) })] }))] }));
|
|
100
|
+
} }));
|
|
67
101
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Table } from '@tanstack/react-table';
|
|
2
2
|
import { ReactNode, RefObject, ReactElement } from 'react';
|
|
3
3
|
import { ColumnFilterState, TableSize } from '../types';
|
|
4
|
+
import { SelectionState } from '../features';
|
|
4
5
|
import { DataTableApi } from '../types/data-table-api';
|
|
6
|
+
import { ExportPhase, ExportProgressPayload, ServerExportResult } from '../types/export.types';
|
|
5
7
|
/**
|
|
6
8
|
* Context value for the DataTable
|
|
7
9
|
*/
|
|
@@ -17,13 +19,11 @@ interface DataTableContextValue<T = any> {
|
|
|
17
19
|
slotProps?: Record<string, any>;
|
|
18
20
|
isExporting?: boolean;
|
|
19
21
|
exportController?: AbortController | null;
|
|
22
|
+
exportPhase?: ExportPhase | null;
|
|
23
|
+
exportProgress?: ExportProgressPayload;
|
|
20
24
|
onCancelExport?: () => void;
|
|
21
25
|
exportFilename?: string;
|
|
22
|
-
onExportProgress?: (progress:
|
|
23
|
-
processedRows?: number;
|
|
24
|
-
totalRows?: number;
|
|
25
|
-
percentage?: number;
|
|
26
|
-
}) => void;
|
|
26
|
+
onExportProgress?: (progress: ExportProgressPayload) => void;
|
|
27
27
|
onExportComplete?: (result: {
|
|
28
28
|
success: boolean;
|
|
29
29
|
filename: string;
|
|
@@ -33,15 +33,12 @@ interface DataTableContextValue<T = any> {
|
|
|
33
33
|
message: string;
|
|
34
34
|
code: string;
|
|
35
35
|
}) => void;
|
|
36
|
-
onServerExport?: (filters?: Partial<any
|
|
37
|
-
data: any[];
|
|
38
|
-
total: number;
|
|
39
|
-
}>;
|
|
36
|
+
onServerExport?: (filters?: Partial<any>, selection?: SelectionState, signal?: AbortSignal) => Promise<ServerExportResult<any>>;
|
|
40
37
|
}
|
|
41
38
|
interface DataTableProviderProps<T = any> extends DataTableContextValue<T> {
|
|
42
39
|
children: ReactNode;
|
|
43
40
|
}
|
|
44
|
-
export declare function DataTableProvider<T = any>({ children, table, apiRef, dataMode, tableSize, onTableSizeChange, columnFilter, onChangeColumnFilter, slots, slotProps, isExporting, exportController, onCancelExport, exportFilename, onExportProgress, onExportComplete, onExportError, onServerExport, }: DataTableProviderProps<T>): ReactElement;
|
|
41
|
+
export declare function DataTableProvider<T = any>({ children, table, apiRef, dataMode, tableSize, onTableSizeChange, columnFilter, onChangeColumnFilter, slots, slotProps, isExporting, exportController, exportPhase, exportProgress, onCancelExport, exportFilename, onExportProgress, onExportComplete, onExportError, onServerExport, }: DataTableProviderProps<T>): ReactElement;
|
|
45
42
|
export declare function useDataTableContext<T = any>(): DataTableContextValue<T>;
|
|
46
43
|
export {};
|
|
47
44
|
//# sourceMappingURL=data-table-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-context.d.ts","sourceRoot":"","sources":["../../../src/lib/contexts/data-table-context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAc,EAA6B,SAAS,EAAW,SAAS,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAEtG,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"data-table-context.d.ts","sourceRoot":"","sources":["../../../src/lib/contexts/data-table-context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAc,EAA6B,SAAS,EAAW,SAAS,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAEtG,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAG/F;;GAEG;AACH,UAAU,qBAAqB,CAAC,CAAC,GAAG,GAAG;IACnC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3C,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAC9C,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAGhC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACvC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAG5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC7D,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/F,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACnE,cAAc,CAAC,EAAE,CACb,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,EACtB,SAAS,CAAC,EAAE,cAAc,EAC1B,MAAM,CAAC,EAAE,WAAW,KACnB,OAAO,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;CACzC;AAID,UAAU,sBAAsB,CAAC,CAAC,GAAG,GAAG,CAAE,SAAQ,qBAAqB,CAAC,CAAC,CAAC;IACtE,QAAQ,EAAE,SAAS,CAAC;CACvB;AAED,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,GAAG,EAAE,EACvC,QAAQ,EACR,KAAK,EACL,MAAM,EACN,QAAQ,EACR,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,KAAU,EACV,SAAc,EACd,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,cAAc,GACjB,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,YAAY,CAgD1C;AAED,wBAAgB,mBAAmB,CAAC,CAAC,GAAG,GAAG,KAAK,qBAAqB,CAAC,CAAC,CAAC,CAMvE"}
|
|
@@ -38,7 +38,7 @@ exports.useDataTableContext = useDataTableContext;
|
|
|
38
38
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
39
39
|
const react_1 = __importStar(require("react"));
|
|
40
40
|
const DataTableContext = (0, react_1.createContext)(null);
|
|
41
|
-
function DataTableProvider({ children, table, apiRef, dataMode, tableSize, onTableSizeChange, columnFilter, onChangeColumnFilter, slots = {}, slotProps = {}, isExporting, exportController, onCancelExport, exportFilename, onExportProgress, onExportComplete, onExportError, onServerExport, }) {
|
|
41
|
+
function DataTableProvider({ children, table, apiRef, dataMode, tableSize, onTableSizeChange, columnFilter, onChangeColumnFilter, slots = {}, slotProps = {}, isExporting, exportController, exportPhase, exportProgress, onCancelExport, exportFilename, onExportProgress, onExportComplete, onExportError, onServerExport, }) {
|
|
42
42
|
const value = (0, react_1.useMemo)(() => ({
|
|
43
43
|
table,
|
|
44
44
|
apiRef,
|
|
@@ -51,6 +51,8 @@ function DataTableProvider({ children, table, apiRef, dataMode, tableSize, onTab
|
|
|
51
51
|
slotProps,
|
|
52
52
|
isExporting,
|
|
53
53
|
exportController,
|
|
54
|
+
exportPhase,
|
|
55
|
+
exportProgress,
|
|
54
56
|
onCancelExport,
|
|
55
57
|
exportFilename,
|
|
56
58
|
onExportProgress,
|
|
@@ -69,6 +71,8 @@ function DataTableProvider({ children, table, apiRef, dataMode, tableSize, onTab
|
|
|
69
71
|
slotProps,
|
|
70
72
|
isExporting,
|
|
71
73
|
exportController,
|
|
74
|
+
exportPhase,
|
|
75
|
+
exportProgress,
|
|
72
76
|
onCancelExport,
|
|
73
77
|
exportFilename,
|
|
74
78
|
onExportProgress,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/lib/data-table.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/lib/data-table.tsx"],"names":[],"mappings":"AAoFA;;GAEG;AACH,eAAO,MAAM,SAAS,KA6kEpB,CAAC"}
|