@ackplus/react-tanstack-data-table 1.0.19-beta-0.8 → 1.0.19-beta-0.10
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 +2 -2
- package/package.json +3 -3
- package/src/index.d.ts +1 -0
- package/src/index.js +3 -1
- package/src/lib/components/table/data-table.js +15 -7
- package/src/lib/components/toolbar/table-export-control.js +18 -6
- package/src/lib/examples/index.d.ts +1 -0
- package/src/lib/examples/index.js +3 -1
- package/src/lib/examples/server-side-fetching-example.d.ts +1 -0
- package/src/lib/examples/server-side-fetching-example.js +241 -0
- package/src/lib/examples/server-side-test.d.ts +1 -0
- package/src/lib/examples/server-side-test.js +9 -0
- package/src/lib/features/custom-selection.feature.js +2 -2
- package/src/lib/utils/export-utils.js +15 -9
package/README.md
CHANGED
|
@@ -573,10 +573,10 @@ If you find this package helpful and want to support its development, consider m
|
|
|
573
573
|
|
|
574
574
|
<div align="center">
|
|
575
575
|
|
|
576
|
-
[](https://www.paypal.com/paypalme/
|
|
576
|
+
[](https://www.paypal.com/paypalme/ckhandla94)
|
|
577
577
|
[](https://razorpay.me/@ackplus)
|
|
578
578
|
|
|
579
|
-
**[💳 PayPal](https://www.paypal.com/paypalme/
|
|
579
|
+
**[💳 PayPal](https://www.paypal.com/paypalme/ckhandla94)** • **[💳 Razorpay](https://razorpay.me/@ackplus)**
|
|
580
580
|
|
|
581
581
|
</div>
|
|
582
582
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ackplus/react-tanstack-data-table",
|
|
3
3
|
"type": "commonjs",
|
|
4
|
-
"version": "1.0.19-beta-0.
|
|
4
|
+
"version": "1.0.19-beta-0.10",
|
|
5
5
|
"description": "A powerful React data table component built with MUI and TanStack Table",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"react",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"bugs": {
|
|
27
27
|
"url": "https://github.com/ack-solutions/react-tanstack-data-table/issues"
|
|
28
28
|
},
|
|
29
|
-
"main": "./index.js",
|
|
30
|
-
"types": "./index.d.ts",
|
|
29
|
+
"main": "./src/index.js",
|
|
30
|
+
"types": "./src/index.d.ts",
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"@emotion/react": ">=11.0.0",
|
|
33
33
|
"@emotion/styled": ">=11.0.0",
|
package/src/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * from './lib/hooks';
|
|
|
14
14
|
export * from './lib/types';
|
|
15
15
|
export type { Column, ColumnDef, Row, Table, Header, Cell, SortingState, ColumnFiltersState, VisibilityState, ColumnOrderState, ColumnPinningState, PaginationState, } from '@tanstack/react-table';
|
|
16
16
|
export * from './lib/features';
|
|
17
|
+
export { ServerSideTest } from './lib/examples/server-side-test';
|
|
17
18
|
export { CustomColumnFilterExample } from './lib/examples/custom-column-filter-example';
|
|
18
19
|
export { SimpleLocalExample } from './lib/examples/simple-local-example';
|
|
19
20
|
export { AdvancedFeaturesExample } from './lib/examples/advanced-features-example';
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AdvancedFeaturesExample = exports.SimpleLocalExample = exports.CustomColumnFilterExample = exports.DataTableToolbar = exports.BulkActionsToolbar = exports.TableSizeControl = exports.TableExportControl = exports.ColumnResetControl = exports.ColumnPinningControl = exports.ColumnVisibilityControl = exports.DataTable = void 0;
|
|
3
|
+
exports.AdvancedFeaturesExample = exports.SimpleLocalExample = exports.CustomColumnFilterExample = exports.ServerSideTest = exports.DataTableToolbar = exports.BulkActionsToolbar = exports.TableSizeControl = exports.TableExportControl = exports.ColumnResetControl = exports.ColumnPinningControl = exports.ColumnVisibilityControl = exports.DataTable = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
var table_1 = require("./lib/components/table");
|
|
6
6
|
Object.defineProperty(exports, "DataTable", { enumerable: true, get: function () { return table_1.DataTable; } });
|
|
@@ -23,6 +23,8 @@ tslib_1.__exportStar(require("./lib/utils/table-helpers"), exports);
|
|
|
23
23
|
tslib_1.__exportStar(require("./lib/hooks"), exports);
|
|
24
24
|
tslib_1.__exportStar(require("./lib/types"), exports);
|
|
25
25
|
tslib_1.__exportStar(require("./lib/features"), exports);
|
|
26
|
+
var server_side_test_1 = require("./lib/examples/server-side-test");
|
|
27
|
+
Object.defineProperty(exports, "ServerSideTest", { enumerable: true, get: function () { return server_side_test_1.ServerSideTest; } });
|
|
26
28
|
var custom_column_filter_example_1 = require("./lib/examples/custom-column-filter-example");
|
|
27
29
|
Object.defineProperty(exports, "CustomColumnFilterExample", { enumerable: true, get: function () { return custom_column_filter_example_1.CustomColumnFilterExample; } });
|
|
28
30
|
var simple_local_example_1 = require("./lib/examples/simple-local-example");
|
|
@@ -181,17 +181,23 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
181
181
|
onDataStateChange,
|
|
182
182
|
]);
|
|
183
183
|
const handleColumnOrderChange = (0, react_1.useCallback)((updatedColumnOrder) => {
|
|
184
|
-
|
|
184
|
+
const newColumnOrder = typeof updatedColumnOrder === 'function'
|
|
185
|
+
? updatedColumnOrder(columnOrder)
|
|
186
|
+
: updatedColumnOrder;
|
|
187
|
+
setColumnOrder(newColumnOrder);
|
|
185
188
|
if (onColumnDragEnd) {
|
|
186
|
-
onColumnDragEnd(
|
|
189
|
+
onColumnDragEnd(newColumnOrder);
|
|
187
190
|
}
|
|
188
|
-
}, [onColumnDragEnd]);
|
|
191
|
+
}, [onColumnDragEnd, columnOrder]);
|
|
189
192
|
const handleColumnPinningChange = (0, react_1.useCallback)((updatedColumnPinning) => {
|
|
190
|
-
|
|
193
|
+
const newColumnPinning = typeof updatedColumnPinning === 'function'
|
|
194
|
+
? updatedColumnPinning(columnPinning)
|
|
195
|
+
: updatedColumnPinning;
|
|
196
|
+
setColumnPinning(newColumnPinning);
|
|
191
197
|
if (onColumnPinningChange) {
|
|
192
|
-
onColumnPinningChange(
|
|
198
|
+
onColumnPinningChange(newColumnPinning);
|
|
193
199
|
}
|
|
194
|
-
}, [onColumnPinningChange]);
|
|
200
|
+
}, [onColumnPinningChange, columnPinning]);
|
|
195
201
|
const handlePaginationChange = (0, react_1.useCallback)((updater) => {
|
|
196
202
|
setPagination(updater);
|
|
197
203
|
const newPagination = typeof updater === 'function' ? updater(pagination) : updater;
|
|
@@ -472,7 +478,9 @@ exports.DataTable = (0, react_1.forwardRef)(function DataTable({ initialState, c
|
|
|
472
478
|
const BodySlot = (0, slot_helpers_1.getSlotComponent)(slots, 'body', material_1.TableBody);
|
|
473
479
|
const FooterSlot = (0, slot_helpers_1.getSlotComponent)(slots, 'footer', material_1.Box);
|
|
474
480
|
const PaginationSlot = (0, slot_helpers_1.getSlotComponent)(slots, 'pagination', pagination_1.DataTablePagination);
|
|
475
|
-
return ((0, jsx_runtime_1.jsx)(data_table_context_1.DataTableProvider, { table: table,
|
|
481
|
+
return ((0, jsx_runtime_1.jsx)(data_table_context_1.DataTableProvider, { table: table, apiRef: internalApiRef, dataMode: dataMode, tableSize: tableSize, onTableSizeChange: (size) => {
|
|
482
|
+
setTableSize(size);
|
|
483
|
+
}, customColumnsFilter: customColumnsFilter, onChangeCustomColumnsFilter: handleColumnFilterStateChange, slots: slots, slotProps: slotProps, isExporting: isExporting, exportController: exportController, onCancelExport: handleCancelExport, exportFilename: exportFilename, onExportProgress: onExportProgress, onExportComplete: onExportComplete, onExportError: onExportError, onServerExport: onServerExport, children: (0, jsx_runtime_1.jsxs)(RootSlot, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.root, { children: [(enableGlobalFilter || extraFilter) ? ((0, jsx_runtime_1.jsx)(ToolbarSlot, Object.assign({ extraFilter: extraFilter, enableGlobalFilter: enableGlobalFilter, enableColumnVisibility: enableColumnVisibility, enableColumnFilter: enableColumnFilter, enableExport: enableExport, enableReset: enableReset, enableTableSizeControl: enableTableSizeControl, enableColumnPinning: enableColumnPinning }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.toolbar))) : null, enableBulkActions && enableRowSelection && isSomeRowsSelected ? ((0, jsx_runtime_1.jsx)(BulkActionsSlot, Object.assign({ selectionState: selectionState, selectedRowCount: selectedRowCount, bulkActions: bulkActions, sx: {
|
|
476
484
|
position: 'relative',
|
|
477
485
|
zIndex: 2,
|
|
478
486
|
} }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.bulkActionsToolbar))) : null, (0, jsx_runtime_1.jsx)(TableContainerSlot, Object.assign({ component: material_1.Paper, ref: tableContainerRef, sx: Object.assign(Object.assign(Object.assign({ width: '100%', overflowX: 'auto' }, (enableStickyHeaderOrFooter && {
|
|
@@ -23,6 +23,7 @@ function TableExportControl({ exportFilename: propsExportFilename, onServerExpor
|
|
|
23
23
|
const handleExport = (format) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
24
24
|
var _a, _b;
|
|
25
25
|
try {
|
|
26
|
+
console.log('handleExport', dataMode, onServerExport);
|
|
26
27
|
if (dataMode === 'server' && onServerExport) {
|
|
27
28
|
const currentState = table.getState();
|
|
28
29
|
const currentFilters = {
|
|
@@ -60,12 +61,23 @@ function TableExportControl({ exportFilename: propsExportFilename, onServerExpor
|
|
|
60
61
|
});
|
|
61
62
|
}
|
|
62
63
|
});
|
|
63
|
-
const selectedRowCount =
|
|
64
|
+
const selectedRowCount = table.getSelectedCount ? table.getSelectedCount() : 0;
|
|
65
|
+
const hasSelection = table.getIsSomeRowsSelected ? table.getIsSomeRowsSelected() : false;
|
|
66
|
+
const visibleColumns = table.getVisibleLeafColumns().filter(col => col.getIsVisible());
|
|
67
|
+
const exportableColumns = visibleColumns.filter(col => {
|
|
68
|
+
const columnDef = col.columnDef;
|
|
69
|
+
return columnDef.hideInExport !== true;
|
|
70
|
+
});
|
|
71
|
+
const hiddenFromExportColumns = visibleColumns.filter(col => {
|
|
72
|
+
const columnDef = col.columnDef;
|
|
73
|
+
return columnDef.hideInExport === true;
|
|
74
|
+
});
|
|
64
75
|
const summary = {
|
|
65
76
|
filteredRows: table.getFilteredRowModel().rows.length,
|
|
66
|
-
totalColumns:
|
|
77
|
+
totalColumns: exportableColumns.length,
|
|
78
|
+
hiddenColumns: hiddenFromExportColumns.length,
|
|
67
79
|
selectedRows: selectedRowCount,
|
|
68
|
-
hasSelection:
|
|
80
|
+
hasSelection: hasSelection,
|
|
69
81
|
};
|
|
70
82
|
return ((0, jsx_runtime_1.jsx)(menu_dropdown_1.MenuDropdown, { anchor: ((0, jsx_runtime_1.jsx)(material_1.Tooltip, { title: "Export data", children: (0, jsx_runtime_1.jsx)(material_1.IconButton, { size: "small", disabled: isExporting, sx: {
|
|
71
83
|
flexShrink: 0,
|
|
@@ -78,9 +90,9 @@ function TableExportControl({ exportFilename: propsExportFilename, onServerExpor
|
|
|
78
90
|
p: 1,
|
|
79
91
|
bgcolor: 'grey.50',
|
|
80
92
|
borderRadius: 1,
|
|
81
|
-
}, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle2", gutterBottom: true, children: "Export Summary" }), (0, jsx_runtime_1.
|
|
82
|
-
|
|
83
|
-
|
|
93
|
+
}, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle2", gutterBottom: true, children: "Export Summary" }), (0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "body2", color: "text.secondary", children: [summary.hasSelection
|
|
94
|
+
? `${summary.selectedRows} selected • ${summary.totalColumns} exportable columns`
|
|
95
|
+
: `${summary.filteredRows} filtered • ${summary.totalColumns} exportable columns`, summary.hiddenColumns > 0 && ((0, jsx_runtime_1.jsxs)("span", { style: { color: 'orange' }, children: [' ', "\u2022 ", summary.hiddenColumns, " hidden from export"] }))] }), summary.hasSelection ? ((0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "caption", color: "primary.main", sx: { fontWeight: 'medium' }, children: "Will export selected rows only" })) : null] }), isExporting ? ((0, jsx_runtime_1.jsxs)(material_1.MenuItem, { onClick: () => {
|
|
84
96
|
onCancelExport === null || onCancelExport === void 0 ? void 0 : onCancelExport();
|
|
85
97
|
handleClose();
|
|
86
98
|
}, children: [(0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(ExportIconSlot, Object.assign({ fontSize: "small", color: "warning" }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.exportIcon)) }), (0, jsx_runtime_1.jsx)(material_1.ListItemText, { primary: "Cancel Export", secondary: "Stop current export" })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(material_1.MenuItem, { onClick: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -3,3 +3,4 @@ export { SelectionTestExample } from './selection-test-example';
|
|
|
3
3
|
export { AdvancedFeaturesExample } from './advanced-features-example';
|
|
4
4
|
export { SimpleLocalExample } from './simple-local-example';
|
|
5
5
|
export { BulkActionsTest } from './bulk-actions-test';
|
|
6
|
+
export { ServerSideFetchingExample } from './server-side-fetching-example';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BulkActionsTest = exports.SimpleLocalExample = exports.AdvancedFeaturesExample = exports.SelectionTestExample = exports.CustomColumnFilterExample = void 0;
|
|
3
|
+
exports.ServerSideFetchingExample = exports.BulkActionsTest = exports.SimpleLocalExample = exports.AdvancedFeaturesExample = exports.SelectionTestExample = exports.CustomColumnFilterExample = void 0;
|
|
4
4
|
var custom_column_filter_example_1 = require("./custom-column-filter-example");
|
|
5
5
|
Object.defineProperty(exports, "CustomColumnFilterExample", { enumerable: true, get: function () { return custom_column_filter_example_1.CustomColumnFilterExample; } });
|
|
6
6
|
var selection_test_example_1 = require("./selection-test-example");
|
|
@@ -11,3 +11,5 @@ var simple_local_example_1 = require("./simple-local-example");
|
|
|
11
11
|
Object.defineProperty(exports, "SimpleLocalExample", { enumerable: true, get: function () { return simple_local_example_1.SimpleLocalExample; } });
|
|
12
12
|
var bulk_actions_test_1 = require("./bulk-actions-test");
|
|
13
13
|
Object.defineProperty(exports, "BulkActionsTest", { enumerable: true, get: function () { return bulk_actions_test_1.BulkActionsTest; } });
|
|
14
|
+
var server_side_fetching_example_1 = require("./server-side-fetching-example");
|
|
15
|
+
Object.defineProperty(exports, "ServerSideFetchingExample", { enumerable: true, get: function () { return server_side_fetching_example_1.ServerSideFetchingExample; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ServerSideFetchingExample(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ServerSideFetchingExample = ServerSideFetchingExample;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const material_1 = require("@mui/material");
|
|
8
|
+
const data_table_1 = require("../components/table/data-table");
|
|
9
|
+
const MOCK_EMPLOYEES = Array.from({ length: 1000 }, (_, index) => {
|
|
10
|
+
const departments = ['Engineering', 'Marketing', 'Sales', 'HR', 'Finance', 'Operations'];
|
|
11
|
+
const roles = ['Manager', 'Senior', 'Junior', 'Lead', 'Director', 'Specialist'];
|
|
12
|
+
const firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry'];
|
|
13
|
+
const lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis', 'Rodriguez', 'Martinez'];
|
|
14
|
+
const firstName = firstNames[Math.floor(Math.random() * firstNames.length)];
|
|
15
|
+
const lastName = lastNames[Math.floor(Math.random() * lastNames.length)];
|
|
16
|
+
return {
|
|
17
|
+
id: index + 1,
|
|
18
|
+
name: `${firstName} ${lastName}`,
|
|
19
|
+
email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@company.com`,
|
|
20
|
+
department: departments[Math.floor(Math.random() * departments.length)],
|
|
21
|
+
role: roles[Math.floor(Math.random() * roles.length)],
|
|
22
|
+
salary: Math.floor(Math.random() * 80000) + 40000,
|
|
23
|
+
isActive: Math.random() > 0.15,
|
|
24
|
+
joinDate: new Date(2020 + Math.floor(Math.random() * 4), Math.floor(Math.random() * 12), Math.floor(Math.random() * 28) + 1).toISOString().split('T')[0],
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
function ServerSideFetchingExample() {
|
|
28
|
+
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
29
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
30
|
+
const [selectionInfo, setSelectionInfo] = (0, react_1.useState)(null);
|
|
31
|
+
const [lastFetchParams, setLastFetchParams] = (0, react_1.useState)(null);
|
|
32
|
+
const [fetchCount, setFetchCount] = (0, react_1.useState)(0);
|
|
33
|
+
const apiRef = (0, react_1.useRef)(null);
|
|
34
|
+
const handleFetchData = (0, react_1.useCallback)((filters) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
var _a, _b, _c;
|
|
36
|
+
console.log('🔄 Fetching data with filters:', filters);
|
|
37
|
+
setLoading(true);
|
|
38
|
+
setError(null);
|
|
39
|
+
setLastFetchParams(filters);
|
|
40
|
+
setFetchCount(prev => prev + 1);
|
|
41
|
+
try {
|
|
42
|
+
yield new Promise(resolve => setTimeout(resolve, 300 + Math.random() * 500));
|
|
43
|
+
let filteredData = [...MOCK_EMPLOYEES];
|
|
44
|
+
if (filters.globalFilter) {
|
|
45
|
+
const searchTerm = filters.globalFilter.toLowerCase();
|
|
46
|
+
filteredData = filteredData.filter(employee => employee.name.toLowerCase().includes(searchTerm) ||
|
|
47
|
+
employee.email.toLowerCase().includes(searchTerm) ||
|
|
48
|
+
employee.department.toLowerCase().includes(searchTerm) ||
|
|
49
|
+
employee.role.toLowerCase().includes(searchTerm));
|
|
50
|
+
}
|
|
51
|
+
if ((_b = (_a = filters.customColumnsFilter) === null || _a === void 0 ? void 0 : _a.filters) === null || _b === void 0 ? void 0 : _b.length) {
|
|
52
|
+
filteredData = filteredData.filter(employee => {
|
|
53
|
+
return filters.customColumnsFilter.filters.every((filter) => {
|
|
54
|
+
const value = employee[filter.columnId];
|
|
55
|
+
const filterValue = filter.value;
|
|
56
|
+
switch (filter.operator) {
|
|
57
|
+
case 'equals':
|
|
58
|
+
return value === filterValue;
|
|
59
|
+
case 'contains':
|
|
60
|
+
return String(value).toLowerCase().includes(String(filterValue).toLowerCase());
|
|
61
|
+
case 'startsWith':
|
|
62
|
+
return String(value).toLowerCase().startsWith(String(filterValue).toLowerCase());
|
|
63
|
+
case 'endsWith':
|
|
64
|
+
return String(value).toLowerCase().endsWith(String(filterValue).toLowerCase());
|
|
65
|
+
case 'greaterThan':
|
|
66
|
+
return Number(value) > Number(filterValue);
|
|
67
|
+
case 'lessThan':
|
|
68
|
+
return Number(value) < Number(filterValue);
|
|
69
|
+
default:
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if ((_c = filters.sorting) === null || _c === void 0 ? void 0 : _c.length) {
|
|
76
|
+
filteredData.sort((a, b) => {
|
|
77
|
+
for (const sort of filters.sorting) {
|
|
78
|
+
const aValue = a[sort.id];
|
|
79
|
+
const bValue = b[sort.id];
|
|
80
|
+
let comparison = 0;
|
|
81
|
+
if (aValue < bValue)
|
|
82
|
+
comparison = -1;
|
|
83
|
+
else if (aValue > bValue)
|
|
84
|
+
comparison = 1;
|
|
85
|
+
if (comparison !== 0) {
|
|
86
|
+
return sort.desc ? -comparison : comparison;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return 0;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const total = filteredData.length;
|
|
93
|
+
let pageData = filteredData;
|
|
94
|
+
if (filters.pagination) {
|
|
95
|
+
const { pageIndex = 0, pageSize = 10 } = filters.pagination;
|
|
96
|
+
const start = pageIndex * pageSize;
|
|
97
|
+
const end = start + pageSize;
|
|
98
|
+
pageData = filteredData.slice(start, end);
|
|
99
|
+
}
|
|
100
|
+
console.log('✅ Data fetched successfully:', {
|
|
101
|
+
total,
|
|
102
|
+
pageSize: pageData.length,
|
|
103
|
+
filters: filters.pagination
|
|
104
|
+
});
|
|
105
|
+
return {
|
|
106
|
+
data: pageData,
|
|
107
|
+
total: total,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
console.error('❌ Error fetching data:', err);
|
|
112
|
+
setError('Failed to fetch data. Please try again.');
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
setLoading(false);
|
|
117
|
+
}
|
|
118
|
+
}), []);
|
|
119
|
+
const handleSelectionChange = (0, react_1.useCallback)((selection) => {
|
|
120
|
+
console.log('🔄 Selection changed:', selection);
|
|
121
|
+
setSelectionInfo(selection);
|
|
122
|
+
}, []);
|
|
123
|
+
const handleServerExport = (0, react_1.useCallback)((filters, selection) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
console.log('📤 Exporting data with filters:', filters);
|
|
125
|
+
console.log('📤 Export selection:', selection);
|
|
126
|
+
yield new Promise(resolve => setTimeout(resolve, 1000));
|
|
127
|
+
let exportData = [...MOCK_EMPLOYEES];
|
|
128
|
+
if (filters === null || filters === void 0 ? void 0 : filters.globalFilter) {
|
|
129
|
+
const searchTerm = filters.globalFilter.toLowerCase();
|
|
130
|
+
exportData = exportData.filter(employee => employee.name.toLowerCase().includes(searchTerm) ||
|
|
131
|
+
employee.email.toLowerCase().includes(searchTerm) ||
|
|
132
|
+
employee.department.toLowerCase().includes(searchTerm) ||
|
|
133
|
+
employee.role.toLowerCase().includes(searchTerm));
|
|
134
|
+
}
|
|
135
|
+
if (selection.type === 'include' && selection.ids.length > 0) {
|
|
136
|
+
exportData = exportData.filter(employee => selection.ids.includes(employee.id.toString()));
|
|
137
|
+
}
|
|
138
|
+
else if (selection.type === 'exclude' && selection.ids.length > 0) {
|
|
139
|
+
exportData = exportData.filter(employee => !selection.ids.includes(employee.id.toString()));
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
data: exportData,
|
|
143
|
+
total: exportData.length,
|
|
144
|
+
};
|
|
145
|
+
}), []);
|
|
146
|
+
const columns = [
|
|
147
|
+
{
|
|
148
|
+
id: 'name',
|
|
149
|
+
accessorKey: 'name',
|
|
150
|
+
header: 'Name',
|
|
151
|
+
size: 200,
|
|
152
|
+
enableGlobalFilter: true,
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: 'email',
|
|
156
|
+
accessorKey: 'email',
|
|
157
|
+
header: 'Email',
|
|
158
|
+
size: 250,
|
|
159
|
+
enableGlobalFilter: true,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
id: 'department',
|
|
163
|
+
accessorKey: 'department',
|
|
164
|
+
header: 'Department',
|
|
165
|
+
size: 150,
|
|
166
|
+
enableGlobalFilter: true,
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: 'role',
|
|
170
|
+
accessorKey: 'role',
|
|
171
|
+
header: 'Role',
|
|
172
|
+
size: 120,
|
|
173
|
+
enableGlobalFilter: true,
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
id: 'salary',
|
|
177
|
+
accessorKey: 'salary',
|
|
178
|
+
header: 'Salary',
|
|
179
|
+
size: 120,
|
|
180
|
+
accessorFn: (row) => `$${row.salary.toLocaleString()}`,
|
|
181
|
+
hideInExport: true,
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
id: 'isActive',
|
|
185
|
+
accessorKey: 'isActive',
|
|
186
|
+
header: 'Status',
|
|
187
|
+
size: 100,
|
|
188
|
+
accessorFn: (row) => row.isActive ? 'Active' : 'Inactive',
|
|
189
|
+
cell: ({ getValue }) => ((0, jsx_runtime_1.jsx)(material_1.Chip, { label: getValue() ? 'Active' : 'Inactive', color: getValue() ? 'success' : 'default', size: "small" })),
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
id: 'joinDate',
|
|
193
|
+
accessorKey: 'joinDate',
|
|
194
|
+
header: 'Join Date',
|
|
195
|
+
size: 120,
|
|
196
|
+
accessorFn: (row) => new Date(row.joinDate).toLocaleDateString(),
|
|
197
|
+
},
|
|
198
|
+
];
|
|
199
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { p: 3 }, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h4", gutterBottom: true, children: "Server-Side Data Fetching Example" }), (0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body1", color: "text.secondary", paragraph: true, children: "Demonstrates server-side data fetching with proper API ref state management and page-based selection. The Salary column has `hideInExport: true` so it will be excluded from exports." }), (0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 2, sx: { mb: 3 }, children: [(0, jsx_runtime_1.jsx)(material_1.Card, { variant: "outlined", children: (0, jsx_runtime_1.jsxs)(material_1.CardContent, { sx: { pb: 2 }, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h6", color: "primary", children: fetchCount }), (0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", children: "API Calls Made" })] }) }), (0, jsx_runtime_1.jsx)(material_1.Card, { variant: "outlined", children: (0, jsx_runtime_1.jsxs)(material_1.CardContent, { sx: { pb: 2 }, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h6", color: "secondary", children: (selectionInfo === null || selectionInfo === void 0 ? void 0 : selectionInfo.ids.length) || 0 }), (0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", children: "Selected Items" })] }) }), (0, jsx_runtime_1.jsx)(material_1.Card, { variant: "outlined", children: (0, jsx_runtime_1.jsxs)(material_1.CardContent, { sx: { pb: 2 }, children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", alignItems: "center", spacing: 1, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h6", color: loading ? 'warning.main' : 'success.main', children: loading ? 'Loading...' : 'Ready' }), loading && (0, jsx_runtime_1.jsx)(material_1.CircularProgress, { size: 16 })] }), (0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", children: "Server Status" })] }) })] }), error && ((0, jsx_runtime_1.jsx)(material_1.Alert, { severity: "error", sx: { mb: 3 }, children: error })), (0, jsx_runtime_1.jsx)(material_1.Card, { sx: { mb: 3 }, children: (0, jsx_runtime_1.jsxs)(material_1.CardContent, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h6", gutterBottom: true, children: "API Controls (via apiRef)" }), (0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 2, flexWrap: "wrap", children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", size: "small", onClick: () => {
|
|
200
|
+
var _a;
|
|
201
|
+
const state = (_a = apiRef.current) === null || _a === void 0 ? void 0 : _a.selection.getSelectionState();
|
|
202
|
+
console.log('Current Selection State:', state);
|
|
203
|
+
alert(`Selection: ${JSON.stringify(state, null, 2)}`);
|
|
204
|
+
}, children: "Get Selection State" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", size: "small", onClick: () => {
|
|
205
|
+
var _a;
|
|
206
|
+
const count = (_a = apiRef.current) === null || _a === void 0 ? void 0 : _a.selection.getSelectedCount();
|
|
207
|
+
console.log('Selected Count:', count);
|
|
208
|
+
alert(`Selected Count: ${count}`);
|
|
209
|
+
}, children: "Get Selected Count" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", size: "small", onClick: () => {
|
|
210
|
+
var _a;
|
|
211
|
+
(_a = apiRef.current) === null || _a === void 0 ? void 0 : _a.selection.selectAll();
|
|
212
|
+
console.log('Selected all rows on current page');
|
|
213
|
+
}, children: "Select All (Page)" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", size: "small", onClick: () => {
|
|
214
|
+
var _a;
|
|
215
|
+
(_a = apiRef.current) === null || _a === void 0 ? void 0 : _a.selection.deselectAll();
|
|
216
|
+
console.log('Deselected all rows');
|
|
217
|
+
}, children: "Deselect All" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", size: "small", onClick: () => {
|
|
218
|
+
var _a;
|
|
219
|
+
(_a = apiRef.current) === null || _a === void 0 ? void 0 : _a.data.refresh();
|
|
220
|
+
console.log('Refreshed data');
|
|
221
|
+
}, children: "Refresh Data" })] })] }) }), selectionInfo && ((0, jsx_runtime_1.jsx)(material_1.Card, { sx: { mb: 3 }, children: (0, jsx_runtime_1.jsxs)(material_1.CardContent, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h6", gutterBottom: true, children: "Current Selection Info" }), (0, jsx_runtime_1.jsx)(material_1.Paper, { sx: { p: 2, bgcolor: 'grey.50' }, children: (0, jsx_runtime_1.jsxs)(material_1.Stack, { spacing: 1, children: [(0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "body2", children: [(0, jsx_runtime_1.jsx)("strong", { children: "Selection Type:" }), " ", selectionInfo.type] }), (0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "body2", children: [(0, jsx_runtime_1.jsx)("strong", { children: "Selected IDs:" }), " [", selectionInfo.ids.join(', '), "]"] }), (0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "body2", children: [(0, jsx_runtime_1.jsx)("strong", { children: "Count:" }), " ", selectionInfo.ids.length] })] }) })] }) })), (0, jsx_runtime_1.jsx)(material_1.Card, { sx: { mb: 3 }, children: (0, jsx_runtime_1.jsxs)(material_1.CardContent, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h6", gutterBottom: true, children: "Export & Column Configuration" }), (0, jsx_runtime_1.jsx)(material_1.Alert, { severity: "info", sx: { mb: 2 }, children: (0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "body2", children: [(0, jsx_runtime_1.jsx)("strong", { children: "hideInExport Demo:" }), " The Salary column has `hideInExport: true` so it will be excluded from CSV/Excel exports. Try exporting to see the difference!"] }) }), (0, jsx_runtime_1.jsxs)(material_1.Stack, { spacing: 1, children: [(0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "body2", children: [(0, jsx_runtime_1.jsx)("strong", { children: "Exportable columns:" }), " Name, Email, Department, Role, Status, Join Date"] }), (0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "body2", color: "warning.main", children: [(0, jsx_runtime_1.jsx)("strong", { children: "Hidden from export:" }), " Salary (contains sensitive data)"] })] })] }) }), lastFetchParams && ((0, jsx_runtime_1.jsx)(material_1.Card, { sx: { mb: 3 }, children: (0, jsx_runtime_1.jsxs)(material_1.CardContent, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h6", gutterBottom: true, children: "Last Fetch Parameters" }), (0, jsx_runtime_1.jsx)(material_1.Paper, { sx: { p: 2, bgcolor: 'grey.50' }, children: (0, jsx_runtime_1.jsx)("pre", { style: { fontSize: '12px', margin: 0, overflow: 'auto' }, children: JSON.stringify(lastFetchParams, null, 2) }) })] }) })), (0, jsx_runtime_1.jsx)(material_1.Divider, { sx: { mb: 3 } }), (0, jsx_runtime_1.jsx)(data_table_1.DataTable, { ref: apiRef, columns: columns, dataMode: "server", initialLoadData: true, onFetchData: handleFetchData, loading: loading, enableRowSelection: true, enableMultiRowSelection: true, selectMode: "page", onSelectionChange: handleSelectionChange, enableBulkActions: true, bulkActions: (selectionState) => ((0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 1, children: [(0, jsx_runtime_1.jsxs)(material_1.Button, { variant: "contained", size: "small", color: "error", onClick: () => {
|
|
222
|
+
console.log('Bulk delete action triggered');
|
|
223
|
+
console.log('Selection state:', selectionState);
|
|
224
|
+
alert(`Would delete ${selectionState.ids.length} items`);
|
|
225
|
+
}, children: ["Delete Selected (", selectionState.ids.length, ")"] }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", size: "small", onClick: () => {
|
|
226
|
+
console.log('Bulk update action triggered');
|
|
227
|
+
console.log('Selection state:', selectionState);
|
|
228
|
+
alert(`Would update ${selectionState.ids.length} items`);
|
|
229
|
+
}, children: "Update Selected" })] })), enableGlobalFilter: true, enableColumnFilter: true, enableSorting: true, enablePagination: true, initialState: {
|
|
230
|
+
pagination: {
|
|
231
|
+
pageIndex: 0,
|
|
232
|
+
pageSize: 10,
|
|
233
|
+
},
|
|
234
|
+
}, enableExport: true, exportFilename: "employees", onServerExport: handleServerExport, onExportProgress: (progress) => {
|
|
235
|
+
console.log('Export progress:', progress);
|
|
236
|
+
}, onExportComplete: (result) => {
|
|
237
|
+
console.log('Export completed:', result);
|
|
238
|
+
}, onExportError: (error) => {
|
|
239
|
+
console.error('Export error:', error);
|
|
240
|
+
}, enableHover: true, enableStripes: true, tableSize: "medium", enableColumnVisibility: true, enableTableSizeControl: true, enableReset: true, emptyMessage: "No employees found matching your criteria", skeletonRows: 10 })] }));
|
|
241
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ServerSideTest(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ServerSideTest = ServerSideTest;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const material_1 = require("@mui/material");
|
|
6
|
+
const server_side_fetching_example_1 = require("./server-side-fetching-example");
|
|
7
|
+
function ServerSideTest() {
|
|
8
|
+
return ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: { p: 2 }, children: (0, jsx_runtime_1.jsxs)(material_1.Paper, { sx: { p: 3 }, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h5", gutterBottom: true, children: "Server-Side Data Fetching Test" }), (0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", paragraph: true, children: "This example demonstrates how to use the DataTable component with server-side data fetching. The onFetchData callback handles all server operations including filtering, sorting, and pagination." }), (0, jsx_runtime_1.jsx)(server_side_fetching_example_1.ServerSideFetchingExample, {})] }) }));
|
|
9
|
+
}
|
|
@@ -116,7 +116,7 @@ exports.CustomSelectionFeature = {
|
|
|
116
116
|
const selectMode = table.options.selectMode || 'page';
|
|
117
117
|
if (selectMode === 'all' && state.type === 'exclude') {
|
|
118
118
|
const totalCount = table.getRowCount();
|
|
119
|
-
return state.ids.length < totalCount;
|
|
119
|
+
return state.ids.length < totalCount && totalCount > 0;
|
|
120
120
|
}
|
|
121
121
|
else {
|
|
122
122
|
return state.ids.length > 0;
|
|
@@ -134,7 +134,7 @@ exports.CustomSelectionFeature = {
|
|
|
134
134
|
const selectMode = table.options.selectMode || 'page';
|
|
135
135
|
if (selectMode === 'all' && state.type === 'exclude') {
|
|
136
136
|
const totalCount = table.getRowCount();
|
|
137
|
-
return totalCount - state.ids.length;
|
|
137
|
+
return Math.max(0, totalCount - state.ids.length);
|
|
138
138
|
}
|
|
139
139
|
else {
|
|
140
140
|
return state.ids.length;
|
|
@@ -19,9 +19,11 @@ function exportClientData(table, options) {
|
|
|
19
19
|
});
|
|
20
20
|
const rowData = {};
|
|
21
21
|
row.getVisibleCells().forEach(cell => {
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
const columnDef = cell.column.columnDef;
|
|
23
|
+
if (columnDef.hideInExport === true) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const header = typeof columnDef.header === 'string' ? columnDef.header : cell.column.id;
|
|
25
27
|
rowData[header] = cell.getValue() || '';
|
|
26
28
|
});
|
|
27
29
|
return rowData;
|
|
@@ -55,7 +57,10 @@ function exportServerData(table, options) {
|
|
|
55
57
|
if (!data || !Array.isArray(data)) {
|
|
56
58
|
throw new Error('Invalid data received from server');
|
|
57
59
|
}
|
|
58
|
-
const visibleColumns = table.getVisibleLeafColumns().filter(col =>
|
|
60
|
+
const visibleColumns = table.getVisibleLeafColumns().filter(col => {
|
|
61
|
+
const columnDef = col.columnDef;
|
|
62
|
+
return col.getIsVisible() && columnDef.hideInExport !== true;
|
|
63
|
+
});
|
|
59
64
|
const exportData = data.map((rowData, index) => {
|
|
60
65
|
onProgress === null || onProgress === void 0 ? void 0 : onProgress({
|
|
61
66
|
processedRows: index + 1,
|
|
@@ -64,14 +69,15 @@ function exportServerData(table, options) {
|
|
|
64
69
|
});
|
|
65
70
|
const exportRow = {};
|
|
66
71
|
visibleColumns.forEach(column => {
|
|
72
|
+
var _a;
|
|
67
73
|
const columnId = column.id;
|
|
68
|
-
const
|
|
69
|
-
|
|
74
|
+
const columnDef = column.columnDef;
|
|
75
|
+
const header = typeof columnDef.header === 'string'
|
|
76
|
+
? columnDef.header
|
|
70
77
|
: columnId;
|
|
71
78
|
let value = rowData[columnId];
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
value = columnDef.accessorFn(rowData);
|
|
79
|
+
if (column.accessorFn && typeof column.accessorFn === 'function') {
|
|
80
|
+
value = ((_a = (column.accessorFn(rowData, index) || '')) === null || _a === void 0 ? void 0 : _a.toString()) || '';
|
|
75
81
|
}
|
|
76
82
|
if (value === null || value === undefined) {
|
|
77
83
|
value = '';
|