@ackplus/react-tanstack-data-table 1.1.19 → 1.1.21
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/dist/lib/hooks/use-data-table-engine.d.ts.map +1 -1
- package/dist/lib/hooks/use-data-table-engine.js +54 -15
- package/dist/lib/types/data-table.types.d.ts +2 -1
- package/dist/lib/types/data-table.types.d.ts.map +1 -1
- package/package.json +3 -4
- package/src/index.ts +0 -75
- package/src/lib/components/data-table-view.tsx +0 -386
- package/src/lib/components/droupdown/menu-dropdown.tsx +0 -103
- package/src/lib/components/filters/filter-value-input.tsx +0 -225
- package/src/lib/components/filters/index.ts +0 -126
- package/src/lib/components/headers/draggable-header.tsx +0 -326
- package/src/lib/components/headers/index.ts +0 -6
- package/src/lib/components/headers/table-header.tsx +0 -175
- package/src/lib/components/index.ts +0 -21
- package/src/lib/components/pagination/data-table-pagination.tsx +0 -111
- package/src/lib/components/pagination/index.ts +0 -5
- package/src/lib/components/rows/data-table-row.tsx +0 -218
- package/src/lib/components/rows/empty-data-row.tsx +0 -69
- package/src/lib/components/rows/index.ts +0 -7
- package/src/lib/components/rows/loading-rows.tsx +0 -164
- package/src/lib/components/toolbar/bulk-actions-toolbar.tsx +0 -125
- package/src/lib/components/toolbar/column-filter-control.tsx +0 -432
- package/src/lib/components/toolbar/column-pinning-control.tsx +0 -275
- package/src/lib/components/toolbar/column-reset-control.tsx +0 -74
- package/src/lib/components/toolbar/column-visibility-control.tsx +0 -105
- package/src/lib/components/toolbar/data-table-toolbar.tsx +0 -257
- package/src/lib/components/toolbar/index.ts +0 -17
- package/src/lib/components/toolbar/table-export-control.tsx +0 -233
- package/src/lib/components/toolbar/table-refresh-control.tsx +0 -62
- package/src/lib/components/toolbar/table-search-control.tsx +0 -155
- package/src/lib/components/toolbar/table-size-control.tsx +0 -102
- package/src/lib/contexts/data-table-context.tsx +0 -126
- package/src/lib/data-table.tsx +0 -29
- package/src/lib/features/README.md +0 -161
- package/src/lib/features/column-filter.feature.ts +0 -493
- package/src/lib/features/index.ts +0 -23
- package/src/lib/features/selection.feature.ts +0 -322
- package/src/lib/hooks/index.ts +0 -2
- package/src/lib/hooks/use-data-table-engine.ts +0 -1516
- package/src/lib/icons/add-icon.tsx +0 -23
- package/src/lib/icons/csv-icon.tsx +0 -15
- package/src/lib/icons/delete-icon.tsx +0 -30
- package/src/lib/icons/excel-icon.tsx +0 -15
- package/src/lib/icons/index.ts +0 -7
- package/src/lib/icons/unpin-icon.tsx +0 -18
- package/src/lib/icons/view-comfortable-icon.tsx +0 -45
- package/src/lib/icons/view-compact-icon.tsx +0 -55
- package/src/lib/types/column.types.ts +0 -63
- package/src/lib/types/data-table-api.ts +0 -191
- package/src/lib/types/data-table.types.ts +0 -192
- package/src/lib/types/export.types.ts +0 -223
- package/src/lib/types/index.ts +0 -24
- package/src/lib/types/slots.types.ts +0 -342
- package/src/lib/types/table.types.ts +0 -88
- package/src/lib/utils/column-helpers.ts +0 -72
- package/src/lib/utils/debounced-fetch.utils.ts +0 -131
- package/src/lib/utils/export-utils.ts +0 -712
- package/src/lib/utils/index.ts +0 -27
- package/src/lib/utils/logger.ts +0 -203
- package/src/lib/utils/slot-helpers.tsx +0 -194
- package/src/lib/utils/special-columns.utils.ts +0 -101
- package/src/lib/utils/styling-helpers.ts +0 -126
- package/src/lib/utils/table-helpers.ts +0 -106
|
@@ -1,493 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Custom Column Filter Feature for TanStack Table
|
|
3
|
-
*
|
|
4
|
-
* This feature adds advanced column filtering capabilities to TanStack Table
|
|
5
|
-
* following the official custom features pattern introduced in v8.14.0
|
|
6
|
-
*/
|
|
7
|
-
import {
|
|
8
|
-
Table,
|
|
9
|
-
TableFeature,
|
|
10
|
-
RowData,
|
|
11
|
-
Updater,
|
|
12
|
-
functionalUpdate,
|
|
13
|
-
makeStateUpdater,
|
|
14
|
-
RowModel,
|
|
15
|
-
Row,
|
|
16
|
-
getFilteredRowModel as getDefaultFilter,
|
|
17
|
-
} from '@tanstack/react-table';
|
|
18
|
-
|
|
19
|
-
// Import from types to avoid circular dependency
|
|
20
|
-
import type { ColumnFilterState } from '../types/table.types';
|
|
21
|
-
import moment from 'moment';
|
|
22
|
-
|
|
23
|
-
// Types for the custom column filter feature
|
|
24
|
-
export interface ColumnFilterRule {
|
|
25
|
-
id: string;
|
|
26
|
-
columnId: string;
|
|
27
|
-
operator: string;
|
|
28
|
-
value: any;
|
|
29
|
-
columnType?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface ColumnFilterOptions {
|
|
33
|
-
enableAdvanceColumnFilter?: boolean;
|
|
34
|
-
onColumnFilterChange?: (updater: Updater<ColumnFilterState>) => void;
|
|
35
|
-
// Add callback for when filters are applied
|
|
36
|
-
onColumnFilterApply?: (state: ColumnFilterState) => void;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Declaration merging to extend TanStack Table types
|
|
40
|
-
declare module '@tanstack/react-table' {
|
|
41
|
-
interface TableState {
|
|
42
|
-
columnFilter: ColumnFilterState;
|
|
43
|
-
}
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
45
|
-
interface TableOptionsResolved<TData extends RowData> {
|
|
46
|
-
enableAdvanceColumnFilter?: boolean;
|
|
47
|
-
onColumnFilterChange?: (updater: Updater<ColumnFilterState>) => void;
|
|
48
|
-
onColumnFilterApply?: (state: ColumnFilterState) => void;
|
|
49
|
-
}
|
|
50
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
51
|
-
interface Table<TData extends RowData> {
|
|
52
|
-
setColumnFilterState: (updater: Updater<ColumnFilterState> | ColumnFilterState) => void;
|
|
53
|
-
|
|
54
|
-
// Pending filter methods (for draft state)
|
|
55
|
-
addPendingColumnFilter: (columnId: string, operator: string, value: any) => void;
|
|
56
|
-
updatePendingColumnFilter: (filterId: string, updates: Partial<ColumnFilterRule>) => void;
|
|
57
|
-
removePendingColumnFilter: (filterId: string) => void;
|
|
58
|
-
clearAllPendingColumnFilters: () => void;
|
|
59
|
-
setPendingFilterLogic: (logic: 'AND' | 'OR') => void;
|
|
60
|
-
|
|
61
|
-
// Apply pending filters to active filters
|
|
62
|
-
applyPendingColumnFilters: () => void;
|
|
63
|
-
resetColumnFilter: () => void;
|
|
64
|
-
|
|
65
|
-
// Legacy methods (for backward compatibility)
|
|
66
|
-
addColumnFilter: (columnId: string, operator: string, value: any) => void;
|
|
67
|
-
updateColumnFilter: (filterId: string, updates: Partial<ColumnFilterRule>) => void;
|
|
68
|
-
removeColumnFilter: (filterId: string) => void;
|
|
69
|
-
clearAllColumnFilters: () => void;
|
|
70
|
-
setFilterLogic: (logic: 'AND' | 'OR') => void;
|
|
71
|
-
|
|
72
|
-
// Getters
|
|
73
|
-
getActiveColumnFilters: () => ColumnFilterRule[];
|
|
74
|
-
getPendingColumnFilters: () => ColumnFilterRule[];
|
|
75
|
-
getColumnFilterState: () => ColumnFilterState;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Table instance methods for custom column filtering
|
|
80
|
-
// export interface ColumnFilterInstance<TData extends RowData> {
|
|
81
|
-
// setColumnFilterState: (updater: Updater<ColumnFilterState>) => void;
|
|
82
|
-
|
|
83
|
-
// // Pending filter methods (for draft state)
|
|
84
|
-
// addPendingColumnFilter: (columnId: string, operator: string, value: any) => void;
|
|
85
|
-
// updatePendingColumnFilter: (filterId: string, updates: Partial<ColumnFilterRule>) => void;
|
|
86
|
-
// removePendingColumnFilter: (filterId: string) => void;
|
|
87
|
-
// clearAllPendingColumnFilters: () => void;
|
|
88
|
-
// setPendingFilterLogic: (logic: 'AND' | 'OR') => void;
|
|
89
|
-
|
|
90
|
-
// // Apply pending filters to active filters
|
|
91
|
-
// applyPendingColumnFilters: () => void;
|
|
92
|
-
|
|
93
|
-
// // Legacy methods (for backward compatibility)
|
|
94
|
-
// addColumnFilter: (columnId: string, operator: string, value: any) => void;
|
|
95
|
-
// updateColumnFilter: (filterId: string, updates: Partial<ColumnFilterRule>) => void;
|
|
96
|
-
// removeColumnFilter: (filterId: string) => void;
|
|
97
|
-
// clearAllColumnFilters: () => void;
|
|
98
|
-
// setFilterLogic: (logic: 'AND' | 'OR') => void;
|
|
99
|
-
|
|
100
|
-
// // Getters
|
|
101
|
-
// getActiveColumnFilters: () => ColumnFilterRule[];
|
|
102
|
-
// getPendingColumnFilters: () => ColumnFilterRule[];
|
|
103
|
-
// getColumnFilterState: () => ColumnFilterState;
|
|
104
|
-
// }
|
|
105
|
-
|
|
106
|
-
// The custom feature implementation
|
|
107
|
-
export const ColumnFilterFeature: TableFeature<any> = {
|
|
108
|
-
// Define the feature's initial state
|
|
109
|
-
getInitialState: (state): { columnFilter: ColumnFilterState } => {
|
|
110
|
-
return {
|
|
111
|
-
columnFilter: {
|
|
112
|
-
filters: [],
|
|
113
|
-
logic: 'AND',
|
|
114
|
-
pendingFilters: [],
|
|
115
|
-
pendingLogic: 'AND',
|
|
116
|
-
},
|
|
117
|
-
...state,
|
|
118
|
-
};
|
|
119
|
-
},
|
|
120
|
-
|
|
121
|
-
// Define the feature's default options
|
|
122
|
-
getDefaultOptions: <TData extends RowData>(
|
|
123
|
-
table: Table<TData>
|
|
124
|
-
): ColumnFilterOptions => {
|
|
125
|
-
return {
|
|
126
|
-
enableAdvanceColumnFilter: true,
|
|
127
|
-
onColumnFilterChange: makeStateUpdater('columnFilter', table),
|
|
128
|
-
onColumnFilterApply: () => {
|
|
129
|
-
// Implementation of onColumnFilterApply
|
|
130
|
-
},
|
|
131
|
-
} as ColumnFilterOptions;
|
|
132
|
-
},
|
|
133
|
-
|
|
134
|
-
// Define the feature's table instance methods
|
|
135
|
-
createTable: <TData extends RowData>(table: Table<TData>): void => {
|
|
136
|
-
table.setColumnFilterState = (updater) => {
|
|
137
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
138
|
-
const safeUpdater: Updater<ColumnFilterState> = (old) => {
|
|
139
|
-
const newState = functionalUpdate(updater, old);
|
|
140
|
-
return newState;
|
|
141
|
-
};
|
|
142
|
-
return table.options.onColumnFilterChange?.(safeUpdater);
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
// === PENDING FILTER METHODS (Draft state) ===
|
|
146
|
-
table.addPendingColumnFilter = (columnId: string, operator: string, value: any) => {
|
|
147
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
148
|
-
table.setColumnFilterState((old) => {
|
|
149
|
-
const newFilter: ColumnFilterRule = {
|
|
150
|
-
id: `filter_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
|
|
151
|
-
columnId,
|
|
152
|
-
operator,
|
|
153
|
-
value,
|
|
154
|
-
};
|
|
155
|
-
return {
|
|
156
|
-
...old,
|
|
157
|
-
pendingFilters: [...old.pendingFilters, newFilter],
|
|
158
|
-
};
|
|
159
|
-
});
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
table.updatePendingColumnFilter = (filterId: string, updates: Partial<ColumnFilterRule>) => {
|
|
163
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
164
|
-
table.setColumnFilterState((old) => {
|
|
165
|
-
const updatedFilters = old.pendingFilters.map((filter) =>
|
|
166
|
-
filter.id === filterId ? { ...filter, ...updates } : filter
|
|
167
|
-
);
|
|
168
|
-
return {
|
|
169
|
-
...old,
|
|
170
|
-
pendingFilters: updatedFilters,
|
|
171
|
-
};
|
|
172
|
-
});
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
table.removePendingColumnFilter = (filterId: string) => {
|
|
176
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
177
|
-
table.setColumnFilterState((old) => ({
|
|
178
|
-
...old,
|
|
179
|
-
pendingFilters: old.pendingFilters.filter((filter) => filter.id !== filterId),
|
|
180
|
-
}));
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
table.clearAllPendingColumnFilters = () => {
|
|
184
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
185
|
-
table.setColumnFilterState((old) => ({
|
|
186
|
-
...old,
|
|
187
|
-
pendingFilters: [],
|
|
188
|
-
}));
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
table.resetColumnFilter = () => {
|
|
192
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
193
|
-
const newState: ColumnFilterState = {
|
|
194
|
-
pendingFilters: [],
|
|
195
|
-
pendingLogic: 'AND',
|
|
196
|
-
filters: [],
|
|
197
|
-
logic: 'AND',
|
|
198
|
-
};
|
|
199
|
-
table.setColumnFilterState(newState);
|
|
200
|
-
// Notify engine so it can reset pagination and refetch (server mode)
|
|
201
|
-
table.options.onColumnFilterApply?.(newState);
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
table.setPendingFilterLogic = (logic: 'AND' | 'OR') => {
|
|
205
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
206
|
-
table.setColumnFilterState((old) => ({
|
|
207
|
-
...old,
|
|
208
|
-
pendingLogic: logic,
|
|
209
|
-
}));
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
// === APPLY PENDING FILTERS ===
|
|
213
|
-
table.applyPendingColumnFilters = () => {
|
|
214
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
215
|
-
table.setColumnFilterState((old) => {
|
|
216
|
-
const newState = {
|
|
217
|
-
...old,
|
|
218
|
-
filters: [...old.pendingFilters],
|
|
219
|
-
logic: old.pendingLogic,
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
// Call the apply callback after state update
|
|
223
|
-
setTimeout(() => {
|
|
224
|
-
table.options.onColumnFilterApply?.(newState);
|
|
225
|
-
}, 0);
|
|
226
|
-
|
|
227
|
-
return newState;
|
|
228
|
-
});
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
// === LEGACY METHODS (for backward compatibility) ===
|
|
232
|
-
table.addColumnFilter = (columnId: string, operator: string, value: any) => {
|
|
233
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
234
|
-
// For backward compatibility, add directly to active filters
|
|
235
|
-
table.setColumnFilterState((old) => {
|
|
236
|
-
const newFilter: ColumnFilterRule = {
|
|
237
|
-
id: `filter_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
|
|
238
|
-
columnId,
|
|
239
|
-
operator,
|
|
240
|
-
value,
|
|
241
|
-
};
|
|
242
|
-
return {
|
|
243
|
-
...old,
|
|
244
|
-
filters: [...old.filters, newFilter],
|
|
245
|
-
};
|
|
246
|
-
});
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
table.updateColumnFilter = (filterId: string, updates: Partial<ColumnFilterRule>) => {
|
|
250
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
251
|
-
table.setColumnFilterState((old) => {
|
|
252
|
-
const updatedFilters = old.filters.map((filter) =>
|
|
253
|
-
filter.id === filterId ? { ...filter, ...updates } : filter
|
|
254
|
-
);
|
|
255
|
-
return {
|
|
256
|
-
...old,
|
|
257
|
-
filters: updatedFilters,
|
|
258
|
-
};
|
|
259
|
-
});
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
table.removeColumnFilter = (filterId: string) => {
|
|
263
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
264
|
-
table.setColumnFilterState((old) => ({
|
|
265
|
-
...old,
|
|
266
|
-
filters: old.filters.filter((filter) => filter.id !== filterId),
|
|
267
|
-
}));
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
table.clearAllColumnFilters = () => {
|
|
271
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
272
|
-
table.setColumnFilterState((old) => ({
|
|
273
|
-
...old,
|
|
274
|
-
filters: [],
|
|
275
|
-
}));
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
table.setFilterLogic = (logic: 'AND' | 'OR') => {
|
|
279
|
-
if (!table.options.enableAdvanceColumnFilter) return;
|
|
280
|
-
table.setColumnFilterState((old) => ({
|
|
281
|
-
...old,
|
|
282
|
-
logic,
|
|
283
|
-
}));
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
// === GETTERS ===
|
|
287
|
-
table.getActiveColumnFilters = () => {
|
|
288
|
-
const state = table.getState().columnFilter;
|
|
289
|
-
return state.filters.filter((f) => f.columnId && f.operator);
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
table.getPendingColumnFilters = () => {
|
|
293
|
-
const state = table.getState().columnFilter;
|
|
294
|
-
return state.pendingFilters.filter((f) => f.columnId && f.operator);
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
table.getColumnFilterState = () => {
|
|
298
|
-
return table.getState().columnFilter;
|
|
299
|
-
};
|
|
300
|
-
},
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Utility function to check if a row matches the custom column filters
|
|
305
|
-
* This can be used for client-side filtering
|
|
306
|
-
*/
|
|
307
|
-
export function matchesCustomColumnFilters(
|
|
308
|
-
row: any,
|
|
309
|
-
filters: ColumnFilterRule[],
|
|
310
|
-
logic: 'AND' | 'OR' = 'AND'
|
|
311
|
-
): boolean {
|
|
312
|
-
if (filters.length === 0) return true;
|
|
313
|
-
|
|
314
|
-
const activeFilters = filters.filter((f) => f.columnId && f.operator);
|
|
315
|
-
if (activeFilters.length === 0) return true;
|
|
316
|
-
|
|
317
|
-
const results = activeFilters.map((filter) => {
|
|
318
|
-
let columnValue;
|
|
319
|
-
let columnType = filter.columnType || 'text';
|
|
320
|
-
try {
|
|
321
|
-
// Try to get the value safely to avoid infinite loops
|
|
322
|
-
const column = row.getAllCells().find((cell: any) => cell.column.id === filter.columnId);
|
|
323
|
-
if (column) {
|
|
324
|
-
columnValue = column.getValue();
|
|
325
|
-
// Try to get type from columnDef if not set
|
|
326
|
-
if (!filter.columnType && column.column.columnDef && column.column.columnDef.type) {
|
|
327
|
-
columnType = column.column.columnDef.type;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
} catch (error) {
|
|
331
|
-
console.warn(`Error getting value for column ${filter.columnId}:`, error);
|
|
332
|
-
columnValue = row.original?.[filter.columnId] || '';
|
|
333
|
-
}
|
|
334
|
-
return evaluateFilterCondition(columnValue, filter.operator, filter.value, columnType);
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
return logic === 'AND' ? results.every(Boolean) : results.some(Boolean);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
export const getCombinedFilteredRowModel = <TData,>() => {
|
|
341
|
-
return (table: Table<TData>) => (): RowModel<TData> => {
|
|
342
|
-
// Respect server/manual filtering: skip client filtering when manualFiltering is enabled
|
|
343
|
-
if (table.options.manualFiltering) {
|
|
344
|
-
return table.getCoreRowModel();
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Run the built-in global + column filters first:
|
|
348
|
-
const baseFilteredModel = getDefaultFilter<TData>()(table)();
|
|
349
|
-
|
|
350
|
-
const { filters, logic } = table.getState().columnFilter ?? {
|
|
351
|
-
filters: [],
|
|
352
|
-
logic: 'AND',
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
if (!filters.length || !table.options.enableAdvanceColumnFilter) {
|
|
356
|
-
return baseFilteredModel;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// Apply custom column filters to pre-filtered rows
|
|
360
|
-
const filteredRows = baseFilteredModel.rows.filter(row =>
|
|
361
|
-
matchesCustomColumnFilters(row, filters, logic)
|
|
362
|
-
);
|
|
363
|
-
|
|
364
|
-
const flatRows: Row<TData>[] = [];
|
|
365
|
-
const rowsById: Record<string, Row<TData>> = {};
|
|
366
|
-
|
|
367
|
-
const addRow = (row: Row<TData>) => {
|
|
368
|
-
flatRows.push(row);
|
|
369
|
-
rowsById[row.id] = row;
|
|
370
|
-
row.subRows?.forEach(addRow);
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
filteredRows.forEach(addRow);
|
|
374
|
-
|
|
375
|
-
return {
|
|
376
|
-
rows: filteredRows,
|
|
377
|
-
flatRows,
|
|
378
|
-
rowsById,
|
|
379
|
-
};
|
|
380
|
-
};
|
|
381
|
-
};
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Evaluate a single filter condition
|
|
385
|
-
*/
|
|
386
|
-
function evaluateFilterCondition(columnValue: any, operator: string, filterValue: any, type: string = 'text'): boolean {
|
|
387
|
-
// --- Date helpers using moment ---
|
|
388
|
-
function toMoment(val: any) {
|
|
389
|
-
if (!val) return null;
|
|
390
|
-
const m = moment(val);
|
|
391
|
-
return m.isValid() ? m : null;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// --- Date type logic ---
|
|
395
|
-
if (type === 'date') {
|
|
396
|
-
if (operator === 'isEmpty') {
|
|
397
|
-
return columnValue === null || columnValue === undefined || columnValue === '';
|
|
398
|
-
}
|
|
399
|
-
if (operator === 'isNotEmpty') {
|
|
400
|
-
return columnValue !== null && columnValue !== undefined && columnValue !== '';
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
const mCol = columnValue ? toMoment(columnValue) : null;
|
|
404
|
-
const mFilter = filterValue ? toMoment(filterValue) : null;
|
|
405
|
-
if (!mCol || !mFilter || !mCol.isValid() || !mFilter.isValid()) return false;
|
|
406
|
-
switch (operator) {
|
|
407
|
-
case 'equals':
|
|
408
|
-
return mCol.isSame(mFilter, 'day');
|
|
409
|
-
case 'notEquals':
|
|
410
|
-
return !mCol.isSame(mFilter, 'day');
|
|
411
|
-
case 'after':
|
|
412
|
-
return mCol.isAfter(mFilter, 'day');
|
|
413
|
-
case 'before':
|
|
414
|
-
return mCol.isBefore(mFilter, 'day');
|
|
415
|
-
default:
|
|
416
|
-
return true;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
// --- Boolean type logic ---
|
|
421
|
-
if (type === 'boolean') {
|
|
422
|
-
switch (operator) {
|
|
423
|
-
case 'is':
|
|
424
|
-
if (filterValue === 'any') return true;
|
|
425
|
-
if (filterValue === 'true') return (columnValue === true || columnValue === 'true' || columnValue === 1 || columnValue === '1' || columnValue === 'Yes' || columnValue === 'yes');
|
|
426
|
-
if (filterValue === 'false') return (columnValue === false || columnValue === 'false' || columnValue === 0 || columnValue === '0' || columnValue === 'No' || columnValue === 'no');
|
|
427
|
-
return false;
|
|
428
|
-
|
|
429
|
-
default:
|
|
430
|
-
return true;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// --- Select type logic (in, notIn, single select) ---
|
|
435
|
-
if (type === 'select') {
|
|
436
|
-
if (operator === 'in' || operator === 'notIn') {
|
|
437
|
-
const values = Array.isArray(filterValue)
|
|
438
|
-
? filterValue
|
|
439
|
-
: [filterValue].filter((value) => value !== undefined && value !== null && value !== '');
|
|
440
|
-
|
|
441
|
-
if (values.length === 0) {
|
|
442
|
-
return operator === 'notIn';
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
if (operator === 'in') return values.includes(columnValue);
|
|
446
|
-
if (operator === 'notIn') return !values.includes(columnValue);
|
|
447
|
-
}
|
|
448
|
-
if (operator === 'equals' || operator === 'notEquals') {
|
|
449
|
-
return operator === 'equals'
|
|
450
|
-
? columnValue === filterValue
|
|
451
|
-
: columnValue !== filterValue;
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// --- Text/Number type logic ---
|
|
456
|
-
if (type === 'number') {
|
|
457
|
-
switch (operator) {
|
|
458
|
-
case 'equals':
|
|
459
|
-
return Number(columnValue) === Number(filterValue);
|
|
460
|
-
case 'notEquals':
|
|
461
|
-
return Number(columnValue) !== Number(filterValue);
|
|
462
|
-
case 'greaterThan':
|
|
463
|
-
return Number(columnValue) > Number(filterValue);
|
|
464
|
-
case 'greaterThanOrEqual':
|
|
465
|
-
return Number(columnValue) >= Number(filterValue);
|
|
466
|
-
case 'lessThan':
|
|
467
|
-
return Number(columnValue) < Number(filterValue);
|
|
468
|
-
case 'lessThanOrEqual':
|
|
469
|
-
return Number(columnValue) <= Number(filterValue);
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
switch (operator) {
|
|
474
|
-
case 'contains':
|
|
475
|
-
return String(columnValue).toLowerCase().includes(String(filterValue).toLowerCase());
|
|
476
|
-
case 'notContains':
|
|
477
|
-
return !String(columnValue).toLowerCase().includes(String(filterValue).toLowerCase());
|
|
478
|
-
case 'startsWith':
|
|
479
|
-
return String(columnValue).toLowerCase().startsWith(String(filterValue).toLowerCase());
|
|
480
|
-
case 'endsWith':
|
|
481
|
-
return String(columnValue).toLowerCase().endsWith(String(filterValue).toLowerCase());
|
|
482
|
-
case 'equals':
|
|
483
|
-
return columnValue === filterValue;
|
|
484
|
-
case 'notEquals':
|
|
485
|
-
return columnValue !== filterValue;
|
|
486
|
-
case 'isEmpty':
|
|
487
|
-
return columnValue === null || columnValue === undefined || columnValue === '';
|
|
488
|
-
case 'isNotEmpty':
|
|
489
|
-
return columnValue !== null && columnValue !== undefined && columnValue !== '';
|
|
490
|
-
default:
|
|
491
|
-
return true;
|
|
492
|
-
}
|
|
493
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Custom TanStack Table Features
|
|
3
|
-
*
|
|
4
|
-
* This module exports custom features that extend TanStack Table functionality
|
|
5
|
-
* following the official custom features pattern introduced in v8.14.0
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export {
|
|
9
|
-
ColumnFilterFeature,
|
|
10
|
-
matchesCustomColumnFilters,
|
|
11
|
-
type ColumnFilterRule,
|
|
12
|
-
type ColumnFilterOptions,
|
|
13
|
-
} from './column-filter.feature';
|
|
14
|
-
|
|
15
|
-
// Export custom selection feature
|
|
16
|
-
export {
|
|
17
|
-
SelectionFeature,
|
|
18
|
-
type SelectionState,
|
|
19
|
-
type SelectMode,
|
|
20
|
-
type SelectionOptions,
|
|
21
|
-
type SelectionTableState,
|
|
22
|
-
type SelectionInstance,
|
|
23
|
-
} from './selection.feature';
|