@ackplus/react-tanstack-data-table 1.1.16 → 1.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -8
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/lib/components/data-table-view.d.ts +7 -0
- package/dist/lib/components/data-table-view.d.ts.map +1 -0
- package/dist/lib/components/data-table-view.js +151 -0
- package/dist/lib/components/toolbar/column-filter-control.d.ts +3 -2
- package/dist/lib/components/toolbar/column-filter-control.d.ts.map +1 -1
- package/dist/lib/components/toolbar/column-filter-control.js +91 -92
- package/dist/lib/components/toolbar/data-table-toolbar.d.ts.map +1 -1
- package/dist/lib/components/toolbar/data-table-toolbar.js +14 -1
- package/dist/lib/components/toolbar/table-export-control.d.ts.map +1 -1
- package/dist/lib/components/toolbar/table-export-control.js +0 -2
- package/dist/lib/components/toolbar/table-refresh-control.d.ts.map +1 -1
- package/dist/lib/components/toolbar/table-refresh-control.js +3 -1
- package/dist/lib/data-table.d.ts +0 -3
- package/dist/lib/data-table.d.ts.map +1 -1
- package/dist/lib/data-table.js +9 -1638
- package/dist/lib/features/column-filter.feature.d.ts +2 -1
- package/dist/lib/features/column-filter.feature.d.ts.map +1 -1
- package/dist/lib/features/column-filter.feature.js +14 -0
- package/dist/lib/hooks/index.d.ts +3 -0
- package/dist/lib/hooks/index.d.ts.map +1 -0
- package/dist/lib/hooks/index.js +5 -0
- package/dist/lib/hooks/use-data-table-engine.d.ts +104 -0
- package/dist/lib/hooks/use-data-table-engine.d.ts.map +1 -0
- package/dist/lib/hooks/use-data-table-engine.js +964 -0
- package/dist/lib/types/data-table.types.d.ts +0 -1
- package/dist/lib/types/data-table.types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +4 -0
- package/src/lib/components/data-table-view.tsx +386 -0
- package/src/lib/components/toolbar/column-filter-control.tsx +270 -212
- package/src/lib/components/toolbar/data-table-toolbar.tsx +15 -1
- package/src/lib/components/toolbar/table-export-control.tsx +0 -2
- package/src/lib/components/toolbar/table-refresh-control.tsx +11 -7
- package/src/lib/data-table.tsx +17 -2183
- package/src/lib/features/column-filter.feature.ts +15 -1
- package/src/lib/hooks/index.ts +2 -0
- package/src/lib/hooks/use-data-table-engine.ts +1285 -0
- package/src/lib/types/data-table.types.ts +0 -1
package/README.md
CHANGED
|
@@ -131,7 +131,6 @@ function MyDataTable() {
|
|
|
131
131
|
| `initialLoadData` | `boolean` | `true` | Load data on component mount |
|
|
132
132
|
| `onFetchData` | `(filters, meta?) => Promise<{data, total}>` | - | Server-side data fetching with optional refresh metadata (`reason`, `force`) |
|
|
133
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 |
|
|
135
134
|
| `onDataStateChange` | `(state) => void` | - | Called when table state changes |
|
|
136
135
|
| `totalRow` | `number` | `0` | Total rows for server-side pagination |
|
|
137
136
|
|
|
@@ -616,13 +615,6 @@ function ReactQueryTable() {
|
|
|
616
615
|
refetchType: options.force ? 'all' : 'active',
|
|
617
616
|
})
|
|
618
617
|
}
|
|
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
618
|
/>
|
|
627
619
|
);
|
|
628
620
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
* - Loading states and empty data handling
|
|
19
19
|
*/
|
|
20
20
|
export { DataTable } from './lib/data-table';
|
|
21
|
+
export { DataTableView } from './lib/components/data-table-view';
|
|
22
|
+
export type { DataTableViewProps } from './lib/components/data-table-view';
|
|
23
|
+
export { useDataTableEngine } from './lib/hooks';
|
|
24
|
+
export type { EngineResult } from './lib/hooks';
|
|
21
25
|
export * from './lib/components/headers';
|
|
22
26
|
export * from './lib/components/rows';
|
|
23
27
|
export * from './lib/components/filters';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,YAAY,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0CAA0C,CAAC;AAGzD,OAAO,EACH,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,GACnB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAGxE,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AAGnC,cAAc,aAAa,CAAC;AAG5B,YAAY,EACR,MAAM,EACN,SAAS,EACT,GAAG,EACH,KAAK,EACL,MAAM,EACN,IAAI,EACJ,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,GAClB,MAAM,uBAAuB,CAAC;AAG/B,cAAc,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -33,10 +33,14 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
33
33
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
34
34
|
};
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.DataTableToolbar = exports.BulkActionsToolbar = exports.TableSizeControl = exports.TableExportControl = exports.ColumnResetControl = exports.ColumnPinningControl = exports.ColumnVisibilityControl = exports.DataTable = void 0;
|
|
36
|
+
exports.DataTableToolbar = exports.BulkActionsToolbar = exports.TableSizeControl = exports.TableExportControl = exports.ColumnResetControl = exports.ColumnPinningControl = exports.ColumnVisibilityControl = exports.useDataTableEngine = exports.DataTableView = exports.DataTable = void 0;
|
|
37
37
|
// Main components - be specific to avoid conflicts
|
|
38
38
|
var data_table_1 = require("./lib/data-table");
|
|
39
39
|
Object.defineProperty(exports, "DataTable", { enumerable: true, get: function () { return data_table_1.DataTable; } });
|
|
40
|
+
var data_table_view_1 = require("./lib/components/data-table-view");
|
|
41
|
+
Object.defineProperty(exports, "DataTableView", { enumerable: true, get: function () { return data_table_view_1.DataTableView; } });
|
|
42
|
+
var hooks_1 = require("./lib/hooks");
|
|
43
|
+
Object.defineProperty(exports, "useDataTableEngine", { enumerable: true, get: function () { return hooks_1.useDataTableEngine; } });
|
|
40
44
|
// Other component exports
|
|
41
45
|
__exportStar(require("./lib/components/headers"), exports);
|
|
42
46
|
__exportStar(require("./lib/components/rows"), exports);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DataTableProps } from '../types/data-table.types';
|
|
2
|
+
import type { EngineResult } from '../hooks/use-data-table-engine';
|
|
3
|
+
export interface DataTableViewProps<T = any> extends DataTableProps<T> {
|
|
4
|
+
engine: EngineResult<T>;
|
|
5
|
+
}
|
|
6
|
+
export declare function DataTableView<T extends Record<string, any>>({ engine, extraFilter, footerFilter, enableGlobalFilter, enableColumnVisibility, enableColumnFilter, enableExport, enableReset, enableTableSizeControl, enableColumnPinning, enableRefresh, enableBulkActions, bulkActions, enableRowSelection, enableColumnDragging, enableColumnResizing, enableStickyHeaderOrFooter, maxHeight, enableVirtualization, enablePagination, tableProps, enableHover, enableStripes, emptyMessage, skeletonRows, onRowClick, selectOnRowClick, renderSubComponent, slots, slotProps, }: DataTableViewProps<T>): any;
|
|
7
|
+
//# sourceMappingURL=data-table-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-view.d.ts","sourceRoot":"","sources":["../../../src/lib/components/data-table-view.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEnE,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,GAAG,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAClE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;CAC3B;AAED,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EACzD,MAAM,EACN,WAAkB,EAClB,YAAmB,EACnB,kBAAyB,EACzB,sBAA6B,EAC7B,kBAA0B,EAC1B,YAAoB,EACpB,WAAkB,EAClB,sBAA6B,EAC7B,mBAA2B,EAC3B,aAAqB,EACrB,iBAAyB,EACzB,WAAW,EACX,kBAA0B,EAC1B,oBAA4B,EAC5B,oBAA4B,EAC5B,0BAAkC,EAClC,SAAmB,EACnB,oBAA4B,EAC5B,gBAAwB,EACxB,UAAe,EACf,WAAkB,EAClB,aAAqB,EACrB,YAAkC,EAClC,YAAgB,EAChB,UAAU,EACV,gBAAwB,EACxB,kBAAkB,EAClB,KAAU,EACV,SAAc,GACjB,EAAE,kBAAkB,CAAC,CAAC,CAAC,OA+UvB"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DataTableView = DataTableView;
|
|
37
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
38
|
+
/**
|
|
39
|
+
* DataTableView – presentational layer for DataTable.
|
|
40
|
+
* Renders based on engine result; no fetch, export, or API logic.
|
|
41
|
+
*/
|
|
42
|
+
const material_1 = require("@mui/material");
|
|
43
|
+
const react_1 = __importStar(require("react"));
|
|
44
|
+
const slot_helpers_1 = require("../utils/slot-helpers");
|
|
45
|
+
const headers_1 = require("./headers");
|
|
46
|
+
const pagination_1 = require("./pagination");
|
|
47
|
+
const rows_1 = require("./rows");
|
|
48
|
+
const toolbar_1 = require("./toolbar");
|
|
49
|
+
function DataTableView({ engine, extraFilter = null, footerFilter = null, enableGlobalFilter = true, enableColumnVisibility = true, enableColumnFilter = false, enableExport = false, enableReset = true, enableTableSizeControl = true, enableColumnPinning = false, enableRefresh = false, enableBulkActions = false, bulkActions, enableRowSelection = false, enableColumnDragging = false, enableColumnResizing = false, enableStickyHeaderOrFooter = false, maxHeight = '400px', enableVirtualization = false, enablePagination = false, tableProps = {}, enableHover = true, enableStripes = false, emptyMessage = 'No data available', skeletonRows = 5, onRowClick, selectOnRowClick = false, renderSubComponent, slots = {}, slotProps = {}, }) {
|
|
50
|
+
const { table, refs, derived, state, actions, } = engine;
|
|
51
|
+
const { tableContainerRef, apiRef, } = refs;
|
|
52
|
+
const { tableLoading, rows, visibleLeafColumns, useFixedLayout, tableStyle, isSomeRowsSelected, selectedRowCount, tableTotalRow, } = derived;
|
|
53
|
+
const { pagination, selectionState, tableSize, } = state;
|
|
54
|
+
const { handleColumnReorder, renderRowModel, } = actions;
|
|
55
|
+
const rowVirtualizer = renderRowModel.rowVirtualizer;
|
|
56
|
+
const renderTableRows = (0, react_1.useCallback)(() => {
|
|
57
|
+
var _a, _b, _c, _d;
|
|
58
|
+
if (tableLoading) {
|
|
59
|
+
const { component: LoadingRowComponent, props: loadingRowProps } = (0, slot_helpers_1.getSlotComponentWithProps)(slots, slotProps || {}, 'loadingRow', rows_1.LoadingRows, {});
|
|
60
|
+
return ((0, jsx_runtime_1.jsx)(LoadingRowComponent, { rowCount: enablePagination ? Math.min(pagination.pageSize, skeletonRows) : skeletonRows, colSpan: table.getAllColumns().length, slots: slots, slotProps: slotProps, ...loadingRowProps }));
|
|
61
|
+
}
|
|
62
|
+
if (rows.length === 0) {
|
|
63
|
+
const { component: EmptyRowComponent, props: emptyRowProps } = (0, slot_helpers_1.getSlotComponentWithProps)(slots, slotProps || {}, 'emptyRow', rows_1.EmptyDataRow, {});
|
|
64
|
+
return ((0, jsx_runtime_1.jsx)(EmptyRowComponent, { colSpan: table.getAllColumns().length, message: emptyMessage, slots: slots, slotProps: slotProps, ...emptyRowProps }));
|
|
65
|
+
}
|
|
66
|
+
if (enableVirtualization && !enablePagination && rows.length > 0) {
|
|
67
|
+
const virtualItems = rowVirtualizer.getVirtualItems();
|
|
68
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [virtualItems.length > 0 && ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", { colSpan: table.getAllColumns().length, style: {
|
|
69
|
+
height: `${(_b = (_a = virtualItems[0]) === null || _a === void 0 ? void 0 : _a.start) !== null && _b !== void 0 ? _b : 0}px`,
|
|
70
|
+
padding: 0,
|
|
71
|
+
border: 0,
|
|
72
|
+
} }) })), virtualItems.map((virtualRow) => {
|
|
73
|
+
const row = rows[virtualRow.index];
|
|
74
|
+
if (!row)
|
|
75
|
+
return null;
|
|
76
|
+
return ((0, jsx_runtime_1.jsx)(rows_1.DataTableRow, { row: row, enableHover: enableHover, enableStripes: enableStripes, isOdd: virtualRow.index % 2 === 1, renderSubComponent: renderSubComponent, disableStickyHeader: enableStickyHeaderOrFooter, onRowClick: onRowClick, selectOnRowClick: selectOnRowClick, slots: slots, slotProps: slotProps }, row.id));
|
|
77
|
+
}), virtualItems.length > 0 && ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", { colSpan: table.getAllColumns().length, style: {
|
|
78
|
+
height: `${rowVirtualizer.getTotalSize() -
|
|
79
|
+
((_d = (_c = virtualItems[virtualItems.length - 1]) === null || _c === void 0 ? void 0 : _c.end) !== null && _d !== void 0 ? _d : 0)}px`,
|
|
80
|
+
padding: 0,
|
|
81
|
+
border: 0,
|
|
82
|
+
} }) }))] }));
|
|
83
|
+
}
|
|
84
|
+
return rows.map((row, index) => ((0, jsx_runtime_1.jsx)(rows_1.DataTableRow, { row: row, enableHover: enableHover, enableStripes: enableStripes, isOdd: index % 2 === 1, renderSubComponent: renderSubComponent, disableStickyHeader: enableStickyHeaderOrFooter, onRowClick: onRowClick, selectOnRowClick: selectOnRowClick, slots: slots, slotProps: slotProps }, row.id)));
|
|
85
|
+
}, [
|
|
86
|
+
tableLoading,
|
|
87
|
+
rows,
|
|
88
|
+
enableVirtualization,
|
|
89
|
+
enablePagination,
|
|
90
|
+
pagination.pageSize,
|
|
91
|
+
skeletonRows,
|
|
92
|
+
table,
|
|
93
|
+
slotProps,
|
|
94
|
+
emptyMessage,
|
|
95
|
+
rowVirtualizer,
|
|
96
|
+
enableHover,
|
|
97
|
+
enableStripes,
|
|
98
|
+
renderSubComponent,
|
|
99
|
+
enableStickyHeaderOrFooter,
|
|
100
|
+
onRowClick,
|
|
101
|
+
selectOnRowClick,
|
|
102
|
+
slots,
|
|
103
|
+
]);
|
|
104
|
+
const { component: RootComponent, props: rootSlotProps } = (0, slot_helpers_1.getSlotComponentWithProps)(slots, slotProps || {}, 'root', material_1.Box, {});
|
|
105
|
+
const { component: ToolbarComponent, props: toolbarSlotProps } = (0, slot_helpers_1.getSlotComponentWithProps)(slots, slotProps || {}, 'toolbar', toolbar_1.DataTableToolbar, {});
|
|
106
|
+
const { component: BulkActionsComponent, props: bulkActionsSlotProps } = (0, slot_helpers_1.getSlotComponentWithProps)(slots, slotProps || {}, 'bulkActionsToolbar', toolbar_1.BulkActionsToolbar, {});
|
|
107
|
+
const { component: TableContainerComponent, props: tableContainerSlotProps } = (0, slot_helpers_1.getSlotComponentWithProps)(slots, slotProps || {}, 'tableContainer', material_1.TableContainer, {});
|
|
108
|
+
const { component: TableComponent, props: tableComponentSlotProps } = (0, slot_helpers_1.getSlotComponentWithProps)(slots, slotProps || {}, 'table', material_1.Table, {});
|
|
109
|
+
const { component: BodyComponent, props: bodySlotProps } = (0, slot_helpers_1.getSlotComponentWithProps)(slots, slotProps || {}, 'body', material_1.TableBody, {});
|
|
110
|
+
const { component: FooterComponent, props: footerSlotProps } = (0, slot_helpers_1.getSlotComponentWithProps)(slots, slotProps || {}, 'footer', material_1.Box, {});
|
|
111
|
+
const { component: PaginationComponent, props: paginationSlotProps } = (0, slot_helpers_1.getSlotComponentWithProps)(slots, slotProps || {}, 'pagination', pagination_1.DataTablePagination, {});
|
|
112
|
+
return ((0, jsx_runtime_1.jsxs)(RootComponent, { ...rootSlotProps, children: [(enableGlobalFilter || extraFilter) ? ((0, jsx_runtime_1.jsx)(ToolbarComponent, { extraFilter: extraFilter, enableGlobalFilter: enableGlobalFilter, enableColumnVisibility: enableColumnVisibility, enableColumnFilter: enableColumnFilter, enableExport: enableExport, enableReset: enableReset, enableTableSizeControl: enableTableSizeControl, enableColumnPinning: enableColumnPinning, enableRefresh: enableRefresh, ...toolbarSlotProps, refreshButtonProps: {
|
|
113
|
+
loading: tableLoading,
|
|
114
|
+
showSpinnerWhileLoading: false,
|
|
115
|
+
onRefresh: () => { var _a, _b, _c; return (_c = (_b = (_a = apiRef.current) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.refresh) === null || _c === void 0 ? void 0 : _c.call(_b, true); },
|
|
116
|
+
...toolbarSlotProps.refreshButtonProps,
|
|
117
|
+
} })) : null, enableBulkActions && enableRowSelection && isSomeRowsSelected ? ((0, jsx_runtime_1.jsx)(BulkActionsComponent, { selectionState: selectionState, selectedRowCount: selectedRowCount, bulkActions: bulkActions, sx: {
|
|
118
|
+
position: 'relative',
|
|
119
|
+
zIndex: 2,
|
|
120
|
+
...bulkActionsSlotProps.sx,
|
|
121
|
+
}, ...bulkActionsSlotProps })) : null, (0, jsx_runtime_1.jsx)(TableContainerComponent, { component: material_1.Paper, ref: tableContainerRef, sx: {
|
|
122
|
+
width: '100%',
|
|
123
|
+
overflowX: 'auto',
|
|
124
|
+
...(enableStickyHeaderOrFooter && {
|
|
125
|
+
maxHeight,
|
|
126
|
+
overflowY: 'auto',
|
|
127
|
+
}),
|
|
128
|
+
...(enableVirtualization && {
|
|
129
|
+
maxHeight,
|
|
130
|
+
overflowY: 'auto',
|
|
131
|
+
}),
|
|
132
|
+
...tableContainerSlotProps === null || tableContainerSlotProps === void 0 ? void 0 : tableContainerSlotProps.sx,
|
|
133
|
+
}, ...tableContainerSlotProps, children: (0, jsx_runtime_1.jsxs)(TableComponent, { size: tableSize, stickyHeader: enableStickyHeaderOrFooter, style: {
|
|
134
|
+
...tableStyle,
|
|
135
|
+
...tableProps === null || tableProps === void 0 ? void 0 : tableProps.style,
|
|
136
|
+
}, ...(0, slot_helpers_1.mergeSlotProps)(tableProps || {}, tableComponentSlotProps), children: [useFixedLayout ? ((0, jsx_runtime_1.jsx)("colgroup", { children: visibleLeafColumns().map((column) => ((0, jsx_runtime_1.jsx)("col", { style: {
|
|
137
|
+
width: column.getSize(),
|
|
138
|
+
minWidth: column.columnDef.minSize,
|
|
139
|
+
maxWidth: column.columnDef.maxSize,
|
|
140
|
+
} }, column.id))) })) : null, (0, jsx_runtime_1.jsx)(headers_1.TableHeader, { draggable: enableColumnDragging, enableColumnResizing: enableColumnResizing, enableStickyHeader: enableStickyHeaderOrFooter, onColumnReorder: handleColumnReorder, slots: slots, slotProps: slotProps }), (0, jsx_runtime_1.jsx)(BodyComponent, { ...bodySlotProps, children: renderTableRows() })] }) }), enablePagination ? ((0, jsx_runtime_1.jsx)(FooterComponent, { sx: {
|
|
141
|
+
...(enableStickyHeaderOrFooter && {
|
|
142
|
+
position: 'sticky',
|
|
143
|
+
bottom: 0,
|
|
144
|
+
backgroundColor: 'background.paper',
|
|
145
|
+
borderTop: '1px solid',
|
|
146
|
+
borderColor: 'divider',
|
|
147
|
+
zIndex: 1,
|
|
148
|
+
}),
|
|
149
|
+
...footerSlotProps.sx,
|
|
150
|
+
}, ...footerSlotProps, children: (0, jsx_runtime_1.jsx)(PaginationComponent, { footerFilter: footerFilter, pagination: pagination, totalRow: tableTotalRow, ...paginationSlotProps }) })) : null] }));
|
|
151
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IconButtonProps, SxProps } from
|
|
2
|
-
import { ReactElement } from
|
|
1
|
+
import { type IconButtonProps, type SxProps } from "@mui/material";
|
|
2
|
+
import { type ReactElement } from "react";
|
|
3
3
|
export interface ColumnFilterControlProps {
|
|
4
4
|
title?: string;
|
|
5
5
|
titleSx?: SxProps;
|
|
@@ -9,6 +9,7 @@ export interface ColumnFilterControlProps {
|
|
|
9
9
|
clearButtonProps?: any;
|
|
10
10
|
applyButtonProps?: any;
|
|
11
11
|
addButtonProps?: any;
|
|
12
|
+
deleteButtonProps?: any;
|
|
12
13
|
logicSelectProps?: any;
|
|
13
14
|
[key: string]: any;
|
|
14
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-filter-control.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/column-filter-control.tsx"],"names":[],"mappings":"AACA,OAAO,EAYH,eAAe,
|
|
1
|
+
{"version":3,"file":"column-filter-control.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/column-filter-control.tsx"],"names":[],"mappings":"AACA,OAAO,EAYH,KAAK,eAAe,EACpB,KAAK,OAAO,EACf,MAAM,eAAe,CAAC;AACvB,OAAc,EAMV,KAAK,YAAY,EACpB,MAAM,OAAO,CAAC;AAWf,MAAM,WAAW,wBAAwB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,UAAU,CAAC,EAAE,GAAG,CAAC;IAEjB,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,cAAc,CAAC,EAAE,GAAG,CAAC;IACrB,iBAAiB,CAAC,EAAE,GAAG,CAAC;IACxB,gBAAgB,CAAC,EAAE,GAAG,CAAC;IAEvB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAiBD,wBAAgB,mBAAmB,CAAC,KAAK,GAAE,wBAA6B,GAAG,YAAY,CA6WtF"}
|
|
@@ -45,43 +45,49 @@ const column_helpers_1 = require("../../utils/column-helpers");
|
|
|
45
45
|
const slot_helpers_1 = require("../../utils/slot-helpers");
|
|
46
46
|
const filters_1 = require("../filters");
|
|
47
47
|
const filter_value_input_1 = require("../filters/filter-value-input");
|
|
48
|
+
/**
|
|
49
|
+
* Small helper component to sync MenuDropdown open state to parent state
|
|
50
|
+
* WITHOUT calling hooks inside render-prop callback.
|
|
51
|
+
*/
|
|
52
|
+
function OpenStateSync({ open, onChange, }) {
|
|
53
|
+
(0, react_1.useEffect)(() => onChange(open), [open, onChange]);
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
48
56
|
function ColumnFilterControl(props = {}) {
|
|
49
57
|
var _a, _b, _c;
|
|
50
58
|
const { table, slots, slotProps } = (0, data_table_context_1.useDataTableContext)();
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
59
|
+
const iconSlotProps = (0, slot_helpers_1.extractSlotProps)(slotProps, "filterIcon");
|
|
60
|
+
const FilterIconSlot = (0, slot_helpers_1.getSlotComponent)(slots, "filterIcon", icons_material_1.FilterList);
|
|
61
|
+
const [isMenuOpen, setIsMenuOpen] = (0, react_1.useState)(false);
|
|
62
|
+
const didAutoAddRef = (0, react_1.useRef)(false);
|
|
55
63
|
const filterState = ((_a = table === null || table === void 0 ? void 0 : table.getColumnFilterState) === null || _a === void 0 ? void 0 : _a.call(table)) || {
|
|
56
64
|
filters: [],
|
|
57
|
-
logic:
|
|
65
|
+
logic: "AND",
|
|
58
66
|
pendingFilters: [],
|
|
59
|
-
pendingLogic:
|
|
67
|
+
pendingLogic: "AND",
|
|
60
68
|
};
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
const filterLogic = filterState.pendingLogic;
|
|
64
|
-
// Active filters are the actual applied filters
|
|
69
|
+
const filters = filterState.pendingFilters || [];
|
|
70
|
+
const filterLogic = (filterState.pendingLogic || "AND");
|
|
65
71
|
const activeFiltersCount = ((_c = (_b = table === null || table === void 0 ? void 0 : table.getActiveColumnFilters) === null || _b === void 0 ? void 0 : _b.call(table)) === null || _c === void 0 ? void 0 : _c.length) || 0;
|
|
66
72
|
const filterableColumns = (0, react_1.useMemo)(() => {
|
|
67
|
-
return table === null || table === void 0 ? void 0 : table.getAllLeafColumns().filter(column => (0, column_helpers_1.isColumnFilterable)(column));
|
|
73
|
+
return (table === null || table === void 0 ? void 0 : table.getAllLeafColumns().filter((column) => (0, column_helpers_1.isColumnFilterable)(column))) || [];
|
|
68
74
|
}, [table]);
|
|
75
|
+
const getOperatorsForColumn = (0, react_1.useCallback)((columnId) => {
|
|
76
|
+
const column = filterableColumns.find((col) => col.id === columnId);
|
|
77
|
+
const type = (0, column_helpers_1.getColumnType)(column);
|
|
78
|
+
return filters_1.FILTER_OPERATORS[type] || filters_1.FILTER_OPERATORS.text;
|
|
79
|
+
}, [filterableColumns]);
|
|
69
80
|
const addFilter = (0, react_1.useCallback)((columnId, operator) => {
|
|
70
81
|
var _a, _b;
|
|
71
|
-
|
|
72
|
-
// If column specified, get its appropriate default operator
|
|
73
|
-
let defaultOperator = operator || '';
|
|
82
|
+
let defaultOperator = operator || "";
|
|
74
83
|
if (columnId && !operator) {
|
|
75
|
-
const column = filterableColumns
|
|
84
|
+
const column = filterableColumns.find((col) => col.id === columnId);
|
|
76
85
|
const columnType = (0, column_helpers_1.getColumnType)(column);
|
|
77
86
|
const operators = filters_1.FILTER_OPERATORS[columnType] || filters_1.FILTER_OPERATORS.text;
|
|
78
|
-
defaultOperator = ((_a = operators[0]) === null || _a === void 0 ? void 0 : _a.value) ||
|
|
87
|
+
defaultOperator = ((_a = operators[0]) === null || _a === void 0 ? void 0 : _a.value) || "contains";
|
|
79
88
|
}
|
|
80
|
-
(_b = table === null || table === void 0 ? void 0 : table.addPendingColumnFilter) === null || _b === void 0 ? void 0 : _b.call(table, columnId ||
|
|
89
|
+
(_b = table === null || table === void 0 ? void 0 : table.addPendingColumnFilter) === null || _b === void 0 ? void 0 : _b.call(table, columnId || "", defaultOperator, "");
|
|
81
90
|
}, [table, filterableColumns]);
|
|
82
|
-
const handleAddFilter = (0, react_1.useCallback)(() => {
|
|
83
|
-
addFilter();
|
|
84
|
-
}, [addFilter]);
|
|
85
91
|
const updateFilter = (0, react_1.useCallback)((filterId, updates) => {
|
|
86
92
|
var _a;
|
|
87
93
|
(_a = table === null || table === void 0 ? void 0 : table.updatePendingColumnFilter) === null || _a === void 0 ? void 0 : _a.call(table, filterId, updates);
|
|
@@ -91,117 +97,110 @@ function ColumnFilterControl(props = {}) {
|
|
|
91
97
|
(_a = table === null || table === void 0 ? void 0 : table.removePendingColumnFilter) === null || _a === void 0 ? void 0 : _a.call(table, filterId);
|
|
92
98
|
}, [table]);
|
|
93
99
|
const clearAllFilters = (0, react_1.useCallback)((closeDialog) => {
|
|
94
|
-
|
|
95
|
-
// Clear all pending filters
|
|
96
|
-
(_a = table === null || table === void 0 ? void 0 : table.clearAllPendingColumnFilters) === null || _a === void 0 ? void 0 : _a.call(table);
|
|
97
|
-
// Immediately apply the clear (which will clear active filters too)
|
|
100
|
+
// Defer all work to avoid long-running click handler (prevents "[Violation] 'click' handler took Xms")
|
|
98
101
|
setTimeout(() => {
|
|
99
102
|
var _a;
|
|
100
|
-
(_a = table === null || table === void 0 ? void 0 : table.
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
103
|
+
(_a = table === null || table === void 0 ? void 0 : table.resetColumnFilter) === null || _a === void 0 ? void 0 : _a.call(table);
|
|
104
|
+
// Prevent auto-add effect from adding a row when it sees empty state after clear
|
|
105
|
+
didAutoAddRef.current = true;
|
|
106
|
+
closeDialog === null || closeDialog === void 0 ? void 0 : closeDialog();
|
|
105
107
|
}, 0);
|
|
106
108
|
}, [table]);
|
|
107
|
-
// Handle filter logic change (AND/OR)
|
|
108
109
|
const handleLogicChange = (0, react_1.useCallback)((newLogic) => {
|
|
109
110
|
var _a;
|
|
110
111
|
(_a = table === null || table === void 0 ? void 0 : table.setPendingFilterLogic) === null || _a === void 0 ? void 0 : _a.call(table, newLogic);
|
|
111
112
|
}, [table]);
|
|
112
|
-
// Apply all pending filters
|
|
113
113
|
const applyFilters = (0, react_1.useCallback)(() => {
|
|
114
114
|
var _a;
|
|
115
115
|
(_a = table === null || table === void 0 ? void 0 : table.applyPendingColumnFilters) === null || _a === void 0 ? void 0 : _a.call(table);
|
|
116
116
|
}, [table]);
|
|
117
|
-
// Handle apply button click
|
|
118
117
|
const handleApplyFilters = (0, react_1.useCallback)((closeDialog) => {
|
|
119
|
-
|
|
120
|
-
|
|
118
|
+
// Defer so click handler returns immediately (prevents "[Violation] 'click' handler took Xms")
|
|
119
|
+
setTimeout(() => {
|
|
120
|
+
applyFilters();
|
|
121
|
+
closeDialog();
|
|
122
|
+
}, 0);
|
|
121
123
|
}, [applyFilters]);
|
|
122
|
-
const getOperatorsForColumn = (0, react_1.useCallback)((columnId) => {
|
|
123
|
-
const column = filterableColumns === null || filterableColumns === void 0 ? void 0 : filterableColumns.find(col => col.id === columnId);
|
|
124
|
-
const type = (0, column_helpers_1.getColumnType)(column);
|
|
125
|
-
return filters_1.FILTER_OPERATORS[type] || filters_1.FILTER_OPERATORS.text;
|
|
126
|
-
}, [filterableColumns]);
|
|
127
|
-
// Handle column selection change
|
|
128
124
|
const handleColumnChange = (0, react_1.useCallback)((filterId, newColumnId, currentFilter) => {
|
|
129
125
|
var _a;
|
|
130
|
-
const newColumn = filterableColumns
|
|
126
|
+
const newColumn = filterableColumns.find((col) => col.id === newColumnId);
|
|
131
127
|
const columnType = (0, column_helpers_1.getColumnType)(newColumn);
|
|
132
128
|
const operators = filters_1.FILTER_OPERATORS[columnType] || filters_1.FILTER_OPERATORS.text;
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
const newOperator = currentOperatorValid ? currentFilter.operator : ((_a = operators[0]) === null || _a === void 0 ? void 0 : _a.value) || '';
|
|
129
|
+
const currentOperatorValid = operators.some((op) => op.value === currentFilter.operator);
|
|
130
|
+
const newOperator = currentOperatorValid ? currentFilter.operator : ((_a = operators[0]) === null || _a === void 0 ? void 0 : _a.value) || "";
|
|
136
131
|
updateFilter(filterId, {
|
|
137
132
|
columnId: newColumnId,
|
|
138
133
|
operator: newOperator,
|
|
139
|
-
|
|
140
|
-
value: ['isEmpty', 'isNotEmpty'].includes(newOperator) ? '' : currentFilter.value,
|
|
134
|
+
value: ["isEmpty", "isNotEmpty"].includes(newOperator) ? "" : currentFilter.value,
|
|
141
135
|
});
|
|
142
136
|
}, [filterableColumns, updateFilter]);
|
|
143
|
-
// Handle operator selection change
|
|
144
137
|
const handleOperatorChange = (0, react_1.useCallback)((filterId, newOperator, currentFilter) => {
|
|
145
138
|
updateFilter(filterId, {
|
|
146
139
|
operator: newOperator,
|
|
147
|
-
|
|
148
|
-
value: ['isEmpty', 'isNotEmpty'].includes(newOperator) ? '' : currentFilter.value,
|
|
140
|
+
value: ["isEmpty", "isNotEmpty"].includes(newOperator) ? "" : currentFilter.value,
|
|
149
141
|
});
|
|
150
142
|
}, [updateFilter]);
|
|
151
|
-
// Handle filter value change
|
|
152
143
|
const handleFilterValueChange = (0, react_1.useCallback)((filterId, value) => {
|
|
153
144
|
updateFilter(filterId, { value });
|
|
154
145
|
}, [updateFilter]);
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (['isEmpty', 'isNotEmpty'].includes(f.operator))
|
|
165
|
-
return true;
|
|
166
|
-
// For other operators, value is required
|
|
167
|
-
return f.value && f.value.toString().trim() !== '';
|
|
168
|
-
}).length;
|
|
169
|
-
// Check if we need to show "Clear Applied Filters" button
|
|
146
|
+
const pendingReadyCount = (0, react_1.useMemo)(() => {
|
|
147
|
+
return filters.filter((f) => {
|
|
148
|
+
if (!f.columnId || !f.operator)
|
|
149
|
+
return false;
|
|
150
|
+
if (["isEmpty", "isNotEmpty"].includes(f.operator))
|
|
151
|
+
return true;
|
|
152
|
+
return f.value != null && String(f.value).trim() !== "";
|
|
153
|
+
}).length;
|
|
154
|
+
}, [filters]);
|
|
170
155
|
const hasAppliedFilters = activeFiltersCount > 0;
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
//
|
|
156
|
+
const hasPendingChanges = pendingReadyCount > 0 || (filters.length === 0 && hasAppliedFilters);
|
|
157
|
+
// Auto-add only once per open. If menu opened with existing filters, mark as processed so
|
|
158
|
+
// "Clear All" doesn't cause a new row to be auto-added when state becomes empty.
|
|
174
159
|
(0, react_1.useEffect)(() => {
|
|
175
160
|
var _a;
|
|
176
|
-
if (
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
161
|
+
if (!isMenuOpen) {
|
|
162
|
+
didAutoAddRef.current = false;
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (didAutoAddRef.current)
|
|
166
|
+
return;
|
|
167
|
+
if (!filterableColumns.length) {
|
|
168
|
+
didAutoAddRef.current = true;
|
|
169
|
+
return;
|
|
183
170
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
171
|
+
if (filters.length > 0 || activeFiltersCount > 0) {
|
|
172
|
+
// Already have filters this session; mark processed so clear won't re-trigger auto-add
|
|
173
|
+
didAutoAddRef.current = true;
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const firstColumn = filterableColumns[0];
|
|
177
|
+
const columnType = (0, column_helpers_1.getColumnType)(firstColumn);
|
|
178
|
+
const operators = filters_1.FILTER_OPERATORS[columnType] || filters_1.FILTER_OPERATORS.text;
|
|
179
|
+
const defaultOperator = ((_a = operators[0]) === null || _a === void 0 ? void 0 : _a.value) || "contains";
|
|
180
|
+
didAutoAddRef.current = true;
|
|
181
|
+
addFilter(firstColumn.id, defaultOperator);
|
|
182
|
+
}, [isMenuOpen, filterableColumns, filters.length, activeFiltersCount, addFilter]);
|
|
183
|
+
// Merge props but do NOT spread non-icon props onto IconButton
|
|
184
|
+
const mergedProps = (0, slot_helpers_1.mergeSlotProps)({ size: "small", sx: { flexShrink: 0 } }, (slotProps === null || slotProps === void 0 ? void 0 : slotProps.columnFilterControl) || {}, props);
|
|
185
|
+
const { badgeProps, menuSx, title, titleSx, logicSelectProps, clearButtonProps, applyButtonProps, addButtonProps, deleteButtonProps, iconButtonProps, ...iconButtonRestProps } = mergedProps;
|
|
186
|
+
return ((0, jsx_runtime_1.jsx)(menu_dropdown_1.MenuDropdown, { anchor: ({ isOpen }) => ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { display: "inline-flex" }, children: [(0, jsx_runtime_1.jsx)(OpenStateSync, { open: isOpen, onChange: setIsMenuOpen }), (0, jsx_runtime_1.jsx)(material_1.Badge, { badgeContent: activeFiltersCount > 0 ? activeFiltersCount : 0, color: "primary", invisible: activeFiltersCount === 0, ...badgeProps, children: (0, jsx_runtime_1.jsx)(material_1.IconButton, { ...iconButtonRestProps, ...iconButtonProps, children: (0, jsx_runtime_1.jsx)(FilterIconSlot, { ...iconSlotProps }) }) })] })), children: ({ handleClose }) => ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: {
|
|
192
187
|
p: 2,
|
|
193
188
|
minWidth: 400,
|
|
194
189
|
maxWidth: 600,
|
|
195
|
-
...
|
|
196
|
-
}, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle2", sx: {
|
|
190
|
+
...(menuSx || {}),
|
|
191
|
+
}, onClick: (e) => e.stopPropagation(), children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle2", sx: {
|
|
197
192
|
mb: 1,
|
|
198
|
-
...
|
|
199
|
-
}, children:
|
|
200
|
-
const selectedColumn = filterableColumns
|
|
193
|
+
...(titleSx || {}),
|
|
194
|
+
}, children: title || "Column Filters" }), (0, jsx_runtime_1.jsx)(material_1.Divider, { sx: { mb: 2 } }), filters.length > 1 && ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: { mb: 2 }, children: (0, jsx_runtime_1.jsxs)(material_1.FormControl, { size: "small", sx: { minWidth: 120 }, children: [(0, jsx_runtime_1.jsx)(material_1.InputLabel, { children: "Logic" }), (0, jsx_runtime_1.jsxs)(material_1.Select, { value: filterLogic, label: "Logic", onChange: (e) => handleLogicChange(e.target.value), ...logicSelectProps, children: [(0, jsx_runtime_1.jsx)(material_1.MenuItem, { value: "AND", children: "AND" }), (0, jsx_runtime_1.jsx)(material_1.MenuItem, { value: "OR", children: "OR" })] })] }) })), (0, jsx_runtime_1.jsx)(material_1.Stack, { spacing: 2, sx: { mb: 2 }, children: filters.map((filter) => {
|
|
195
|
+
const selectedColumn = filterableColumns.find((col) => col.id === filter.columnId);
|
|
201
196
|
const operators = filter.columnId ? getOperatorsForColumn(filter.columnId) : [];
|
|
202
|
-
const needsValue = ![
|
|
203
|
-
return ((0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 1, alignItems: "center", children: [(0, jsx_runtime_1.jsxs)(material_1.FormControl, { size: "small", sx: { minWidth: 120 }, children: [(0, jsx_runtime_1.jsx)(material_1.InputLabel, { children: "Column" }), (0, jsx_runtime_1.jsx)(material_1.Select, { value: filter.columnId ||
|
|
197
|
+
const needsValue = !["isEmpty", "isNotEmpty"].includes(filter.operator);
|
|
198
|
+
return ((0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 1, alignItems: "center", children: [(0, jsx_runtime_1.jsxs)(material_1.FormControl, { size: "small", sx: { minWidth: 120 }, children: [(0, jsx_runtime_1.jsx)(material_1.InputLabel, { children: "Column" }), (0, jsx_runtime_1.jsx)(material_1.Select, { value: filter.columnId || "", label: "Column", onChange: (e) => handleColumnChange(filter.id, e.target.value, filter), children: filterableColumns.map((column) => ((0, jsx_runtime_1.jsx)(material_1.MenuItem, { value: column.id, children: typeof column.columnDef.header === "string"
|
|
204
199
|
? column.columnDef.header
|
|
205
|
-
: column.id }, column.id))) })] }), (0, jsx_runtime_1.jsxs)(material_1.FormControl, { size: "small", sx: { minWidth: 120 }, children: [(0, jsx_runtime_1.jsx)(material_1.InputLabel, { children: "Operator" }), (0, jsx_runtime_1.jsx)(material_1.Select, { value: filter.operator ||
|
|
206
|
-
}) }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", size: "small", startIcon: (0, jsx_runtime_1.jsx)(icons_1.AddIcon, {}), onClick:
|
|
200
|
+
: column.id }, column.id))) })] }), (0, jsx_runtime_1.jsxs)(material_1.FormControl, { size: "small", sx: { minWidth: 120 }, children: [(0, jsx_runtime_1.jsx)(material_1.InputLabel, { children: "Operator" }), (0, jsx_runtime_1.jsx)(material_1.Select, { value: filter.operator || "", label: "Operator", onChange: (e) => handleOperatorChange(filter.id, e.target.value, filter), disabled: !filter.columnId, children: operators.map((op) => ((0, jsx_runtime_1.jsx)(material_1.MenuItem, { value: op.value, children: op.label }, op.value))) })] }), needsValue && selectedColumn && ((0, jsx_runtime_1.jsx)(filter_value_input_1.FilterValueInput, { filter: filter, column: selectedColumn, onValueChange: (value) => handleFilterValueChange(filter.id, value) })), (0, jsx_runtime_1.jsx)(material_1.IconButton, { size: "small", onClick: () => removeFilter(filter.id), color: "error", ...deleteButtonProps, children: (0, jsx_runtime_1.jsx)(icons_1.DeleteIcon, { fontSize: "small" }) })] }, filter.id));
|
|
201
|
+
}) }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", size: "small", startIcon: (0, jsx_runtime_1.jsx)(icons_1.AddIcon, {}), onClick: () => addFilter(), disabled: filterableColumns.length === 0, sx: { mb: 2 }, ...addButtonProps, children: "Add Filter" }), (0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 1, justifyContent: "flex-end", children: [hasAppliedFilters && ((0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", size: "small", onClick: (e) => {
|
|
202
|
+
e.preventDefault();
|
|
203
|
+
e.stopPropagation();
|
|
204
|
+
clearAllFilters(handleClose);
|
|
205
|
+
}, color: "error", ...clearButtonProps, children: "Clear All" })), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", size: "small", onClick: () => handleApplyFilters(() => handleClose === null || handleClose === void 0 ? void 0 : handleClose()), disabled: !hasPendingChanges, ...applyButtonProps, children: "Apply" })] })] })) }));
|
|
207
206
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-table-toolbar.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/data-table-toolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKH,YAAY,EACZ,OAAO,EACV,MAAM,eAAe,CAAC;AACvB,OAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAavD,MAAM,WAAW,qBAAsB,SAAQ,YAAY;IACvD,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,GAAE,qBAA0B,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"data-table-toolbar.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/data-table-toolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKH,YAAY,EACZ,OAAO,EACV,MAAM,eAAe,CAAC;AACvB,OAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAavD,MAAM,WAAW,qBAAsB,SAAQ,YAAY;IACvD,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,GAAE,qBAA0B,GAAG,YAAY,CAsNhF"}
|
|
@@ -45,7 +45,20 @@ function DataTableToolbar(props = {}) {
|
|
|
45
45
|
table,
|
|
46
46
|
...otherProps,
|
|
47
47
|
}, toolbarSlotProps);
|
|
48
|
-
|
|
48
|
+
// Omit child-slot props so they are not spread onto the Toolbar DOM element (React warning)
|
|
49
|
+
const TOOLBAR_CHILD_SLOT_KEYS = [
|
|
50
|
+
'refreshButtonProps',
|
|
51
|
+
'searchInputProps',
|
|
52
|
+
'tableSizeControlProps',
|
|
53
|
+
'columnFilterProps',
|
|
54
|
+
'columnPinningProps',
|
|
55
|
+
'columnVisibilityProps',
|
|
56
|
+
'resetButtonProps',
|
|
57
|
+
'exportButtonProps',
|
|
58
|
+
];
|
|
59
|
+
const toolbarDomProps = { ...mergedToolbarProps };
|
|
60
|
+
TOOLBAR_CHILD_SLOT_KEYS.forEach((key) => delete toolbarDomProps[key]);
|
|
61
|
+
return ((0, jsx_runtime_1.jsx)(ToolbarSlot, { ...toolbarDomProps, children: (0, jsx_runtime_1.jsxs)(material_1.Box, { sx: {
|
|
49
62
|
width: '100%',
|
|
50
63
|
...containerSx,
|
|
51
64
|
}, children: [(title || subtitle) ? ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { mb: 2 }, children: [title ? ((0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h6", component: "div", sx: titleSx, children: title })) : null, subtitle ? ((0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", sx: subtitleSx, children: subtitle })) : null] })) : null, (0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 2, justifyContent: "space-between", alignItems: "center", children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 0.5, alignItems: "center", sx: {
|
|
@@ -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,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,
|
|
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,OAoMrE"}
|
|
@@ -85,10 +85,8 @@ function TableExportControl(props = {}) {
|
|
|
85
85
|
...menuSx,
|
|
86
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
87
|
handleExport('csv');
|
|
88
|
-
handleClose();
|
|
89
88
|
}, 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
89
|
handleExport('excel');
|
|
91
|
-
handleClose();
|
|
92
90
|
}, 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
91
|
handleCancelExport();
|
|
94
92
|
handleClose();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-refresh-control.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/table-refresh-control.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,YAAY,EAAe,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAuB,eAAe,EAAoB,MAAM,eAAe,CAAC;AAKvF,MAAM,WAAW,wBAAwB;IACrC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,GAAG,CAAC;IAEnB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvC,qCAAqC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,gDAAgD;IAChD,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,GAAE,wBAA6B,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"table-refresh-control.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/table-refresh-control.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,YAAY,EAAe,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAuB,eAAe,EAAoB,MAAM,eAAe,CAAC;AAKvF,MAAM,WAAW,wBAAwB;IACrC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,GAAG,CAAC;IAEnB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvC,qCAAqC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,gDAAgD;IAChD,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,GAAE,wBAA6B,GAAG,YAAY,CAsCtF"}
|
|
@@ -57,5 +57,7 @@ function TableRefreshControl(props = {}) {
|
|
|
57
57
|
disabled: !!props.loading,
|
|
58
58
|
sx: { flexShrink: 0 },
|
|
59
59
|
}, refreshIconSlotProps, props.iconButtonProps || {});
|
|
60
|
-
|
|
60
|
+
// Wrap in span so when IconButton is disabled (loading), the tooltip still
|
|
61
|
+
// receives pointer events and closes on mouse leave (disabled elements don't fire them).
|
|
62
|
+
return ((0, jsx_runtime_1.jsx)(material_1.Tooltip, { title: "Refresh data", ...props.tooltipProps, children: (0, jsx_runtime_1.jsx)("span", { style: { display: 'inline-flex' }, children: (0, jsx_runtime_1.jsx)(material_1.IconButton, { ...mergedIconButtonProps, children: props.loading && props.showSpinnerWhileLoading ? ((0, jsx_runtime_1.jsx)(material_1.CircularProgress, { size: 16 })) : ((0, jsx_runtime_1.jsx)(RefreshIconSlot, { ...refreshIconSlotProps })) }) }) }));
|
|
61
63
|
}
|