@ackplus/react-tanstack-data-table 1.0.35 → 1.1.1
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/LICENSE +21 -0
- package/{src → dist}/index.d.ts +21 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/{src → dist}/lib/components/droupdown/menu-dropdown.d.ts +2 -1
- package/dist/lib/components/droupdown/menu-dropdown.d.ts.map +1 -0
- package/{src → dist}/lib/components/droupdown/menu-dropdown.js +38 -7
- package/{src → dist}/lib/components/filters/filter-value-input.d.ts +3 -1
- package/dist/lib/components/filters/filter-value-input.d.ts.map +1 -0
- package/dist/lib/components/filters/filter-value-input.js +83 -0
- package/{src → dist}/lib/components/filters/index.d.ts +1 -0
- package/dist/lib/components/filters/index.d.ts.map +1 -0
- package/dist/lib/components/filters/index.js +142 -0
- package/{src → dist}/lib/components/headers/draggable-header.d.ts +2 -2
- package/dist/lib/components/headers/draggable-header.d.ts.map +1 -0
- package/{src → dist}/lib/components/headers/draggable-header.js +81 -17
- package/dist/lib/components/headers/index.d.ts +6 -0
- package/dist/lib/components/headers/index.d.ts.map +1 -0
- package/dist/lib/components/headers/index.js +21 -0
- package/{src → dist}/lib/components/headers/table-header.d.ts +15 -1
- package/dist/lib/components/headers/table-header.d.ts.map +1 -0
- package/{src → dist}/lib/components/headers/table-header.js +50 -17
- package/{src → dist}/lib/components/index.d.ts +6 -1
- package/dist/lib/components/index.d.ts.map +1 -0
- package/dist/lib/components/index.js +32 -0
- package/{src → dist}/lib/components/pagination/data-table-pagination.d.ts +2 -1
- package/dist/lib/components/pagination/data-table-pagination.d.ts.map +1 -0
- package/{src → dist}/lib/components/pagination/data-table-pagination.js +20 -6
- package/dist/lib/components/pagination/index.d.ts +5 -0
- package/dist/lib/components/pagination/index.d.ts.map +1 -0
- package/dist/lib/components/pagination/index.js +20 -0
- package/{src → dist}/lib/components/rows/data-table-row.d.ts +15 -2
- package/dist/lib/components/rows/data-table-row.d.ts.map +1 -0
- package/{src → dist}/lib/components/rows/data-table-row.js +58 -25
- package/{src → dist}/lib/components/rows/empty-data-row.d.ts +3 -3
- package/dist/lib/components/rows/empty-data-row.d.ts.map +1 -0
- package/{src → dist}/lib/components/rows/empty-data-row.js +12 -4
- package/dist/lib/components/rows/index.d.ts +7 -0
- package/dist/lib/components/rows/index.d.ts.map +1 -0
- package/dist/lib/components/rows/index.js +22 -0
- package/{src → dist}/lib/components/rows/loading-rows.d.ts +3 -1
- package/dist/lib/components/rows/loading-rows.d.ts.map +1 -0
- package/{src → dist}/lib/components/rows/loading-rows.js +27 -19
- package/{src → dist}/lib/components/toolbar/bulk-actions-toolbar.d.ts +4 -3
- package/dist/lib/components/toolbar/bulk-actions-toolbar.d.ts.map +1 -0
- package/dist/lib/components/toolbar/bulk-actions-toolbar.js +49 -0
- package/{src → dist}/lib/components/toolbar/column-filter-control.d.ts +3 -1
- package/dist/lib/components/toolbar/column-filter-control.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/column-filter-control.js +73 -4
- package/{src → dist}/lib/components/toolbar/column-pinning-control.d.ts +2 -1
- package/dist/lib/components/toolbar/column-pinning-control.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/column-pinning-control.js +70 -6
- package/{src → dist}/lib/components/toolbar/column-reset-control.d.ts +3 -1
- package/dist/lib/components/toolbar/column-reset-control.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/column-reset-control.js +9 -2
- package/{src → dist}/lib/components/toolbar/column-visibility-control.d.ts +2 -1
- package/dist/lib/components/toolbar/column-visibility-control.d.ts.map +1 -0
- package/dist/lib/components/toolbar/column-visibility-control.js +77 -0
- package/{src → dist}/lib/components/toolbar/data-table-toolbar.d.ts +3 -2
- package/dist/lib/components/toolbar/data-table-toolbar.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/data-table-toolbar.js +17 -4
- package/{src → dist}/lib/components/toolbar/index.d.ts +4 -0
- package/dist/lib/components/toolbar/index.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/index.js +6 -0
- package/dist/lib/components/toolbar/table-export-control.d.ts +12 -0
- package/dist/lib/components/toolbar/table-export-control.d.ts.map +1 -0
- package/dist/lib/components/toolbar/table-export-control.js +67 -0
- package/{src → dist}/lib/components/toolbar/table-search-control.d.ts +3 -1
- package/dist/lib/components/toolbar/table-search-control.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/table-search-control.js +45 -2
- package/{src → dist}/lib/components/toolbar/table-size-control.d.ts +3 -1
- package/dist/lib/components/toolbar/table-size-control.d.ts.map +1 -0
- package/{src → dist}/lib/components/toolbar/table-size-control.js +20 -8
- package/{src → dist}/lib/contexts/data-table-context.d.ts +6 -2
- package/dist/lib/contexts/data-table-context.d.ts.map +1 -0
- package/{src → dist}/lib/contexts/data-table-context.js +34 -1
- package/dist/lib/data-table.d.ts +5 -0
- package/dist/lib/data-table.d.ts.map +1 -0
- package/{src/lib/components/table → dist/lib}/data-table.js +427 -143
- package/dist/lib/features/column-filter.feature.d.ts +55 -0
- package/dist/lib/features/column-filter.feature.d.ts.map +1 -0
- package/{src → dist}/lib/features/column-filter.feature.js +116 -18
- package/dist/lib/features/index.d.ts +9 -0
- package/dist/lib/features/index.d.ts.map +1 -0
- package/{src → dist}/lib/features/index.js +7 -0
- package/{src → dist}/lib/features/selection.feature.d.ts +8 -1
- package/dist/lib/features/selection.feature.d.ts.map +1 -0
- package/{src → dist}/lib/features/selection.feature.js +76 -15
- package/dist/lib/icons/add-icon.d.ts +4 -0
- package/dist/lib/icons/add-icon.d.ts.map +1 -0
- package/dist/lib/icons/add-icon.js +12 -0
- package/dist/lib/icons/csv-icon.d.ts +4 -0
- package/dist/lib/icons/csv-icon.d.ts.map +1 -0
- package/dist/lib/icons/csv-icon.js +12 -0
- package/dist/lib/icons/delete-icon.d.ts +4 -0
- package/dist/lib/icons/delete-icon.d.ts.map +1 -0
- package/dist/lib/icons/delete-icon.js +12 -0
- package/dist/lib/icons/excel-icon.d.ts +4 -0
- package/dist/lib/icons/excel-icon.d.ts.map +1 -0
- package/dist/lib/icons/excel-icon.js +12 -0
- package/dist/lib/icons/index.d.ts +8 -0
- package/dist/lib/icons/index.d.ts.map +1 -0
- package/dist/lib/icons/unpin-icon.d.ts +4 -0
- package/dist/lib/icons/unpin-icon.d.ts.map +1 -0
- package/dist/lib/icons/unpin-icon.js +12 -0
- package/{src → dist}/lib/icons/view-comfortable-icon.d.ts +3 -1
- package/dist/lib/icons/view-comfortable-icon.d.ts.map +1 -0
- package/dist/lib/icons/view-comfortable-icon.js +12 -0
- package/dist/lib/icons/view-compact-icon.d.ts +4 -0
- package/dist/lib/icons/view-compact-icon.d.ts.map +1 -0
- package/dist/lib/icons/view-compact-icon.js +12 -0
- package/{src → dist}/lib/types/column.types.d.ts +10 -1
- package/dist/lib/types/column.types.d.ts.map +1 -0
- package/{src → dist}/lib/types/data-table-api.d.ts +2 -1
- package/dist/lib/types/data-table-api.d.ts.map +1 -0
- package/{src/lib/components/table → dist/lib/types}/data-table.types.d.ts +10 -10
- package/dist/lib/types/data-table.types.d.ts.map +1 -0
- package/{src → dist}/lib/types/export.types.d.ts +38 -0
- package/dist/lib/types/export.types.d.ts.map +1 -0
- package/dist/lib/types/export.types.js +6 -0
- package/{src → dist}/lib/types/index.d.ts +5 -0
- package/dist/lib/types/index.d.ts.map +1 -0
- package/dist/lib/types/index.js +30 -0
- package/{src → dist}/lib/types/slots.types.d.ts +50 -3
- package/dist/lib/types/slots.types.d.ts.map +1 -0
- package/{src → dist}/lib/types/table.types.d.ts +14 -0
- package/dist/lib/types/table.types.d.ts.map +1 -0
- package/{src → dist}/lib/utils/column-helpers.d.ts +10 -0
- package/dist/lib/utils/column-helpers.d.ts.map +1 -0
- package/{src → dist}/lib/utils/column-helpers.js +20 -4
- package/{src → dist}/lib/utils/debounced-fetch.utils.d.ts +3 -5
- package/dist/lib/utils/debounced-fetch.utils.d.ts.map +1 -0
- package/{src → dist}/lib/utils/debounced-fetch.utils.js +12 -6
- package/{src → dist}/lib/utils/export-utils.d.ts +13 -0
- package/dist/lib/utils/export-utils.d.ts.map +1 -0
- package/dist/lib/utils/export-utils.js +252 -0
- package/{src → dist}/lib/utils/index.d.ts +4 -0
- package/dist/lib/utils/index.d.ts.map +1 -0
- package/dist/lib/utils/index.js +35 -0
- package/{src → dist}/lib/utils/logger.d.ts +43 -0
- package/dist/lib/utils/logger.d.ts.map +1 -0
- package/{src → dist}/lib/utils/logger.js +22 -2
- package/{src → dist}/lib/utils/slot-helpers.d.ts +39 -1
- package/dist/lib/utils/slot-helpers.d.ts.map +1 -0
- package/{src → dist}/lib/utils/slot-helpers.js +55 -6
- package/{src → dist}/lib/utils/special-columns.utils.d.ts +10 -0
- package/dist/lib/utils/special-columns.utils.d.ts.map +1 -0
- package/{src → dist}/lib/utils/special-columns.utils.js +41 -5
- package/{src → dist}/lib/utils/styling-helpers.d.ts +20 -0
- package/dist/lib/utils/styling-helpers.d.ts.map +1 -0
- package/dist/lib/utils/styling-helpers.js +108 -0
- package/{src → dist}/lib/utils/table-helpers.d.ts +25 -0
- package/dist/lib/utils/table-helpers.d.ts.map +1 -0
- package/{src → dist}/lib/utils/table-helpers.js +24 -0
- package/package.json +36 -11
- package/src/index.ts +71 -0
- package/src/lib/components/droupdown/menu-dropdown.tsx +97 -0
- package/src/lib/components/filters/filter-value-input.tsx +225 -0
- package/src/lib/components/filters/{index.js → index.ts} +3 -6
- package/src/lib/components/headers/draggable-header.tsx +326 -0
- package/src/lib/components/headers/{index.d.ts → index.ts} +4 -0
- package/src/lib/components/headers/table-header.tsx +173 -0
- package/src/lib/components/index.ts +21 -0
- package/src/lib/components/pagination/data-table-pagination.tsx +99 -0
- package/src/lib/components/pagination/index.ts +5 -0
- package/src/lib/components/rows/data-table-row.tsx +208 -0
- package/src/lib/components/rows/empty-data-row.tsx +69 -0
- package/src/lib/components/rows/{index.d.ts → index.ts} +4 -0
- package/src/lib/components/rows/loading-rows.tsx +160 -0
- package/src/lib/components/toolbar/bulk-actions-toolbar.tsx +125 -0
- package/src/lib/components/toolbar/column-filter-control.tsx +374 -0
- package/src/lib/components/toolbar/column-pinning-control.tsx +275 -0
- package/src/lib/components/toolbar/column-reset-control.tsx +74 -0
- package/src/lib/components/toolbar/column-visibility-control.tsx +105 -0
- package/src/lib/components/toolbar/data-table-toolbar.tsx +229 -0
- package/src/lib/components/toolbar/index.ts +17 -0
- package/src/lib/components/toolbar/table-export-control.tsx +179 -0
- package/src/lib/components/toolbar/table-search-control.tsx +155 -0
- package/src/lib/components/toolbar/table-size-control.tsx +102 -0
- package/src/lib/contexts/data-table-context.tsx +112 -0
- package/src/lib/data-table.tsx +1911 -0
- package/src/lib/features/README.md +161 -0
- package/src/lib/features/column-filter.feature.ts +456 -0
- package/src/lib/features/index.ts +23 -0
- package/src/lib/features/selection.feature.ts +318 -0
- package/src/lib/icons/add-icon.tsx +23 -0
- package/src/lib/icons/csv-icon.tsx +15 -0
- package/src/lib/icons/delete-icon.tsx +30 -0
- package/src/lib/icons/excel-icon.tsx +15 -0
- package/src/lib/icons/unpin-icon.tsx +18 -0
- package/src/lib/icons/view-comfortable-icon.tsx +45 -0
- package/src/lib/icons/view-compact-icon.tsx +55 -0
- package/src/lib/types/column.types.ts +44 -0
- package/src/lib/types/data-table-api.ts +169 -0
- package/src/lib/types/data-table.types.ts +139 -0
- package/src/lib/types/export.types.ts +154 -0
- package/src/lib/types/index.ts +22 -0
- package/src/lib/types/slots.types.ts +332 -0
- package/src/lib/types/table.types.ts +90 -0
- package/src/lib/utils/column-helpers.ts +72 -0
- package/src/lib/utils/debounced-fetch.utils.ts +54 -0
- package/src/lib/utils/export-utils.ts +285 -0
- package/src/lib/utils/index.ts +27 -0
- package/src/lib/utils/logger.ts +203 -0
- package/src/lib/utils/slot-helpers.tsx +194 -0
- package/src/lib/utils/special-columns.utils.ts +94 -0
- package/src/lib/utils/styling-helpers.ts +126 -0
- package/src/lib/utils/table-helpers.ts +106 -0
- package/src/index.js +0 -27
- package/src/lib/components/filters/filter-value-input.js +0 -41
- package/src/lib/components/headers/index.js +0 -5
- package/src/lib/components/index.js +0 -10
- package/src/lib/components/pagination/index.d.ts +0 -1
- package/src/lib/components/pagination/index.js +0 -4
- package/src/lib/components/rows/index.js +0 -6
- package/src/lib/components/table/data-table.d.ts +0 -4
- package/src/lib/components/table/index.d.ts +0 -2
- package/src/lib/components/table/index.js +0 -5
- package/src/lib/components/toolbar/bulk-actions-toolbar.js +0 -30
- package/src/lib/components/toolbar/column-visibility-control.js +0 -31
- package/src/lib/components/toolbar/table-export-control.d.ts +0 -31
- package/src/lib/components/toolbar/table-export-control.js +0 -56
- package/src/lib/examples/advanced-features-example.d.ts +0 -1
- package/src/lib/examples/advanced-features-example.js +0 -269
- package/src/lib/examples/bulk-actions-test.d.ts +0 -1
- package/src/lib/examples/bulk-actions-test.js +0 -44
- package/src/lib/examples/custom-column-filter-example.d.ts +0 -1
- package/src/lib/examples/custom-column-filter-example.js +0 -60
- package/src/lib/examples/index.d.ts +0 -8
- package/src/lib/examples/index.js +0 -19
- package/src/lib/examples/selection-test-example.d.ts +0 -1
- package/src/lib/examples/selection-test-example.js +0 -101
- package/src/lib/examples/server-side-fetching-example.d.ts +0 -1
- package/src/lib/examples/server-side-fetching-example.js +0 -245
- package/src/lib/examples/server-side-test.d.ts +0 -1
- package/src/lib/examples/server-side-test.js +0 -9
- package/src/lib/examples/simple-local-example.d.ts +0 -1
- package/src/lib/examples/simple-local-example.js +0 -95
- package/src/lib/examples/simple-slots-example.d.ts +0 -1
- package/src/lib/examples/simple-slots-example.js +0 -115
- package/src/lib/features/column-filter.feature.d.ts +0 -45
- package/src/lib/features/index.d.ts +0 -2
- package/src/lib/hooks/index.d.ts +0 -1
- package/src/lib/hooks/index.js +0 -4
- package/src/lib/hooks/use-data-table-api.d.ts +0 -46
- package/src/lib/hooks/use-data-table-api.js +0 -690
- package/src/lib/icons/add-icon.d.ts +0 -2
- package/src/lib/icons/add-icon.js +0 -8
- package/src/lib/icons/csv-icon.d.ts +0 -2
- package/src/lib/icons/csv-icon.js +0 -8
- package/src/lib/icons/delete-icon.d.ts +0 -2
- package/src/lib/icons/delete-icon.js +0 -8
- package/src/lib/icons/excel-icon.d.ts +0 -2
- package/src/lib/icons/excel-icon.js +0 -8
- package/src/lib/icons/unpin-icon.d.ts +0 -2
- package/src/lib/icons/unpin-icon.js +0 -8
- package/src/lib/icons/view-comfortable-icon.js +0 -8
- package/src/lib/icons/view-compact-icon.d.ts +0 -2
- package/src/lib/icons/view-compact-icon.js +0 -8
- package/src/lib/types/export.types.js +0 -2
- package/src/lib/types/index.js +0 -8
- package/src/lib/utils/export-utils.js +0 -175
- package/src/lib/utils/index.js +0 -11
- package/src/lib/utils/styling-helpers.js +0 -70
- package/tsconfig.tsbuildinfo +0 -1
- /package/{src → dist}/lib/icons/index.js +0 -0
- /package/{src → dist}/lib/types/column.types.js +0 -0
- /package/{src → dist}/lib/types/data-table-api.js +0 -0
- /package/{src/lib/components/table → dist/lib/types}/data-table.types.js +0 -0
- /package/{src → dist}/lib/types/slots.types.js +0 -0
- /package/{src → dist}/lib/types/table.types.js +0 -0
- /package/src/lib/icons/{index.d.ts → index.ts} +0 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Custom TanStack Table Features
|
|
2
|
+
|
|
3
|
+
This directory contains custom features that extend TanStack Table functionality following the official custom features pattern introduced in v8.14.0.
|
|
4
|
+
|
|
5
|
+
## Custom Column Filter Feature
|
|
6
|
+
|
|
7
|
+
The Custom Column Filter Feature adds advanced column filtering capabilities to TanStack Table, providing a more sophisticated filtering UI with AND/OR logic and multiple operators.
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
- **Multiple Filter Conditions**: Add multiple filter rules for different columns
|
|
12
|
+
- **Logic Operators**: Choose between AND/OR logic for combining filters
|
|
13
|
+
- **Various Operators**: Support for equals, contains, greater than, less than, empty checks, etc.
|
|
14
|
+
- **Type-Aware Filtering**: Different operators available based on column type
|
|
15
|
+
- **Integrated State Management**: Filters are managed within TanStack Table's state system
|
|
16
|
+
|
|
17
|
+
### Usage
|
|
18
|
+
|
|
19
|
+
#### 1. Import the Feature
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { CustomColumnFilterFeature } from '@your-package/features';
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
#### 2. Add to Table Options
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
const table = useReactTable({
|
|
29
|
+
_features: [CustomColumnFilterFeature], // Add the custom feature
|
|
30
|
+
data,
|
|
31
|
+
columns,
|
|
32
|
+
// ... other options
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### 3. Use the Feature Methods
|
|
37
|
+
|
|
38
|
+
The feature adds several methods to your table instance:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// Add a new filter
|
|
42
|
+
table.addColumnFilter('columnId', 'contains', 'search value');
|
|
43
|
+
|
|
44
|
+
// Update an existing filter
|
|
45
|
+
table.updateColumnFilter('filterId', { value: 'new value' });
|
|
46
|
+
|
|
47
|
+
// Remove a filter
|
|
48
|
+
table.removeColumnFilter('filterId');
|
|
49
|
+
|
|
50
|
+
// Clear all filters
|
|
51
|
+
table.clearAllColumnFilters();
|
|
52
|
+
|
|
53
|
+
// Get active filters
|
|
54
|
+
const activeFilters = table.getActiveColumnFilters();
|
|
55
|
+
|
|
56
|
+
// Set filter logic (AND/OR)
|
|
57
|
+
table.setFilterLogic('OR');
|
|
58
|
+
|
|
59
|
+
// Get current filter state
|
|
60
|
+
const filterState = table.getColumnFilterState();
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### 4. Handle State Changes
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const table = useReactTable({
|
|
67
|
+
_features: [CustomColumnFilterFeature],
|
|
68
|
+
// ... other options
|
|
69
|
+
onCustomColumnFilterChange: (updater) => {
|
|
70
|
+
// Handle filter state changes
|
|
71
|
+
const newState = typeof updater === 'function'
|
|
72
|
+
? updater(currentState)
|
|
73
|
+
: updater;
|
|
74
|
+
|
|
75
|
+
// Update your local state or trigger server requests
|
|
76
|
+
handleFilterChange(newState);
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Available Filter Operators
|
|
82
|
+
|
|
83
|
+
| Operator | Description | Types |
|
|
84
|
+
|----------|-------------|-------|
|
|
85
|
+
| `equals` | Exact match | All |
|
|
86
|
+
| `notEquals` | Not equal to | All |
|
|
87
|
+
| `contains` | Contains substring | Text |
|
|
88
|
+
| `notContains` | Does not contain | Text |
|
|
89
|
+
| `startsWith` | Starts with | Text |
|
|
90
|
+
| `endsWith` | Ends with | Text |
|
|
91
|
+
| `isEmpty` | Is empty/null | All |
|
|
92
|
+
| `isNotEmpty` | Is not empty/null | All |
|
|
93
|
+
| `greaterThan` | Greater than | Number, Date |
|
|
94
|
+
| `greaterThanOrEqual` | Greater than or equal | Number, Date |
|
|
95
|
+
| `lessThan` | Less than | Number, Date |
|
|
96
|
+
| `lessThanOrEqual` | Less than or equal | Number, Date |
|
|
97
|
+
| `between` | Between two values | Number, Date |
|
|
98
|
+
| `in` | In array of values | All |
|
|
99
|
+
| `notIn` | Not in array of values | All |
|
|
100
|
+
|
|
101
|
+
### Client-Side Filtering
|
|
102
|
+
|
|
103
|
+
For client-side filtering, you can use the provided utility function:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import { matchesCustomColumnFilters } from '@your-package/features';
|
|
107
|
+
|
|
108
|
+
const filteredRows = rows.filter(row =>
|
|
109
|
+
matchesCustomColumnFilters(row, filters, logic)
|
|
110
|
+
);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Server-Side Filtering
|
|
114
|
+
|
|
115
|
+
For server-side filtering, listen to filter changes and send the filter state to your backend:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
const handleFilterChange = (filterState) => {
|
|
119
|
+
// Send to server
|
|
120
|
+
fetchData({
|
|
121
|
+
filters: filterState.filters,
|
|
122
|
+
logic: filterState.logic,
|
|
123
|
+
// ... other params
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### TypeScript Integration
|
|
129
|
+
|
|
130
|
+
The feature includes full TypeScript support with declaration merging that extends TanStack Table's types:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
// These types are automatically available after importing the feature
|
|
134
|
+
interface CustomColumnFilterState {
|
|
135
|
+
filters: ColumnFilterRule[];
|
|
136
|
+
logic: 'AND' | 'OR';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
interface ColumnFilterRule {
|
|
140
|
+
id: string;
|
|
141
|
+
columnId: string;
|
|
142
|
+
operator: string;
|
|
143
|
+
value: any;
|
|
144
|
+
columnType?: string;
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Example
|
|
149
|
+
|
|
150
|
+
See `custom-column-filter-example.tsx` for a complete working example.
|
|
151
|
+
|
|
152
|
+
## Creating Additional Custom Features
|
|
153
|
+
|
|
154
|
+
To create additional custom features, follow the TanStack Table custom features pattern:
|
|
155
|
+
|
|
156
|
+
1. Define TypeScript types
|
|
157
|
+
2. Use declaration merging to extend TanStack Table types
|
|
158
|
+
3. Create the feature object with `getInitialState`, `getDefaultOptions`, and `createTable`
|
|
159
|
+
4. Add the feature to your table's `_features` array
|
|
160
|
+
|
|
161
|
+
Refer to the TanStack Table documentation for more details on creating custom features.
|
|
@@ -0,0 +1,456 @@
|
|
|
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>) => 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
|
+
|
|
64
|
+
// Legacy methods (for backward compatibility)
|
|
65
|
+
addColumnFilter: (columnId: string, operator: string, value: any) => void;
|
|
66
|
+
updateColumnFilter: (filterId: string, updates: Partial<ColumnFilterRule>) => void;
|
|
67
|
+
removeColumnFilter: (filterId: string) => void;
|
|
68
|
+
clearAllColumnFilters: () => void;
|
|
69
|
+
setFilterLogic: (logic: 'AND' | 'OR') => void;
|
|
70
|
+
|
|
71
|
+
// Getters
|
|
72
|
+
getActiveColumnFilters: () => ColumnFilterRule[];
|
|
73
|
+
getPendingColumnFilters: () => ColumnFilterRule[];
|
|
74
|
+
getColumnFilterState: () => ColumnFilterState;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Table instance methods for custom column filtering
|
|
79
|
+
// export interface ColumnFilterInstance<TData extends RowData> {
|
|
80
|
+
// setColumnFilterState: (updater: Updater<ColumnFilterState>) => void;
|
|
81
|
+
|
|
82
|
+
// // Pending filter methods (for draft state)
|
|
83
|
+
// addPendingColumnFilter: (columnId: string, operator: string, value: any) => void;
|
|
84
|
+
// updatePendingColumnFilter: (filterId: string, updates: Partial<ColumnFilterRule>) => void;
|
|
85
|
+
// removePendingColumnFilter: (filterId: string) => void;
|
|
86
|
+
// clearAllPendingColumnFilters: () => void;
|
|
87
|
+
// setPendingFilterLogic: (logic: 'AND' | 'OR') => void;
|
|
88
|
+
|
|
89
|
+
// // Apply pending filters to active filters
|
|
90
|
+
// applyPendingColumnFilters: () => void;
|
|
91
|
+
|
|
92
|
+
// // Legacy methods (for backward compatibility)
|
|
93
|
+
// addColumnFilter: (columnId: string, operator: string, value: any) => void;
|
|
94
|
+
// updateColumnFilter: (filterId: string, updates: Partial<ColumnFilterRule>) => void;
|
|
95
|
+
// removeColumnFilter: (filterId: string) => void;
|
|
96
|
+
// clearAllColumnFilters: () => void;
|
|
97
|
+
// setFilterLogic: (logic: 'AND' | 'OR') => void;
|
|
98
|
+
|
|
99
|
+
// // Getters
|
|
100
|
+
// getActiveColumnFilters: () => ColumnFilterRule[];
|
|
101
|
+
// getPendingColumnFilters: () => ColumnFilterRule[];
|
|
102
|
+
// getColumnFilterState: () => ColumnFilterState;
|
|
103
|
+
// }
|
|
104
|
+
|
|
105
|
+
// The custom feature implementation
|
|
106
|
+
export const ColumnFilterFeature: TableFeature<any> = {
|
|
107
|
+
// Define the feature's initial state
|
|
108
|
+
getInitialState: (state): { columnFilter: ColumnFilterState } => {
|
|
109
|
+
return {
|
|
110
|
+
columnFilter: {
|
|
111
|
+
filters: [],
|
|
112
|
+
logic: 'AND',
|
|
113
|
+
pendingFilters: [],
|
|
114
|
+
pendingLogic: 'AND',
|
|
115
|
+
},
|
|
116
|
+
...state,
|
|
117
|
+
};
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
// Define the feature's default options
|
|
121
|
+
getDefaultOptions: <TData extends RowData>(
|
|
122
|
+
table: Table<TData>
|
|
123
|
+
): ColumnFilterOptions => {
|
|
124
|
+
return {
|
|
125
|
+
enableAdvanceColumnFilter: true,
|
|
126
|
+
onColumnFilterChange: makeStateUpdater('columnFilter', table),
|
|
127
|
+
onColumnFilterApply: () => {
|
|
128
|
+
// Implementation of onColumnFilterApply
|
|
129
|
+
},
|
|
130
|
+
} as ColumnFilterOptions;
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
// Define the feature's table instance methods
|
|
134
|
+
createTable: <TData extends RowData>(table: Table<TData>): void => {
|
|
135
|
+
table.setColumnFilterState = (updater) => {
|
|
136
|
+
if (!table.options.enableAdvanceColumnFilter) return;
|
|
137
|
+
const safeUpdater: Updater<ColumnFilterState> = (old) => {
|
|
138
|
+
const newState = functionalUpdate(updater, old);
|
|
139
|
+
return newState;
|
|
140
|
+
};
|
|
141
|
+
return table.options.onColumnFilterChange?.(safeUpdater);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// === PENDING FILTER METHODS (Draft state) ===
|
|
145
|
+
table.addPendingColumnFilter = (columnId: string, operator: string, value: any) => {
|
|
146
|
+
if (!table.options.enableAdvanceColumnFilter) return;
|
|
147
|
+
table.setColumnFilterState((old) => {
|
|
148
|
+
const newFilter: ColumnFilterRule = {
|
|
149
|
+
id: `filter_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
|
|
150
|
+
columnId,
|
|
151
|
+
operator,
|
|
152
|
+
value,
|
|
153
|
+
};
|
|
154
|
+
return {
|
|
155
|
+
...old,
|
|
156
|
+
pendingFilters: [...old.pendingFilters, newFilter],
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
table.updatePendingColumnFilter = (filterId: string, updates: Partial<ColumnFilterRule>) => {
|
|
162
|
+
if (!table.options.enableAdvanceColumnFilter) return;
|
|
163
|
+
table.setColumnFilterState((old) => {
|
|
164
|
+
const updatedFilters = old.pendingFilters.map((filter) =>
|
|
165
|
+
filter.id === filterId ? { ...filter, ...updates } : filter
|
|
166
|
+
);
|
|
167
|
+
return {
|
|
168
|
+
...old,
|
|
169
|
+
pendingFilters: updatedFilters,
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
table.removePendingColumnFilter = (filterId: string) => {
|
|
175
|
+
if (!table.options.enableAdvanceColumnFilter) return;
|
|
176
|
+
table.setColumnFilterState((old) => ({
|
|
177
|
+
...old,
|
|
178
|
+
pendingFilters: old.pendingFilters.filter((filter) => filter.id !== filterId),
|
|
179
|
+
}));
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
table.clearAllPendingColumnFilters = () => {
|
|
183
|
+
if (!table.options.enableAdvanceColumnFilter) return;
|
|
184
|
+
table.setColumnFilterState((old) => ({
|
|
185
|
+
...old,
|
|
186
|
+
pendingFilters: [],
|
|
187
|
+
}));
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
table.setPendingFilterLogic = (logic: 'AND' | 'OR') => {
|
|
191
|
+
if (!table.options.enableAdvanceColumnFilter) return;
|
|
192
|
+
table.setColumnFilterState((old) => ({
|
|
193
|
+
...old,
|
|
194
|
+
pendingLogic: logic,
|
|
195
|
+
}));
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// === APPLY PENDING FILTERS ===
|
|
199
|
+
table.applyPendingColumnFilters = () => {
|
|
200
|
+
if (!table.options.enableAdvanceColumnFilter) return;
|
|
201
|
+
table.setColumnFilterState((old) => {
|
|
202
|
+
const newState = {
|
|
203
|
+
...old,
|
|
204
|
+
filters: [...old.pendingFilters],
|
|
205
|
+
logic: old.pendingLogic,
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// Call the apply callback after state update
|
|
209
|
+
setTimeout(() => {
|
|
210
|
+
table.options.onColumnFilterApply?.(newState);
|
|
211
|
+
}, 0);
|
|
212
|
+
|
|
213
|
+
return newState;
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// === LEGACY METHODS (for backward compatibility) ===
|
|
218
|
+
table.addColumnFilter = (columnId: string, operator: string, value: any) => {
|
|
219
|
+
if (!table.options.enableAdvanceColumnFilter) return;
|
|
220
|
+
// For backward compatibility, add directly to active filters
|
|
221
|
+
table.setColumnFilterState((old) => {
|
|
222
|
+
const newFilter: ColumnFilterRule = {
|
|
223
|
+
id: `filter_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
|
|
224
|
+
columnId,
|
|
225
|
+
operator,
|
|
226
|
+
value,
|
|
227
|
+
};
|
|
228
|
+
return {
|
|
229
|
+
...old,
|
|
230
|
+
filters: [...old.filters, newFilter],
|
|
231
|
+
};
|
|
232
|
+
});
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
table.updateColumnFilter = (filterId: string, updates: Partial<ColumnFilterRule>) => {
|
|
236
|
+
if (!table.options.enableAdvanceColumnFilter) return;
|
|
237
|
+
table.setColumnFilterState((old) => {
|
|
238
|
+
const updatedFilters = old.filters.map((filter) =>
|
|
239
|
+
filter.id === filterId ? { ...filter, ...updates } : filter
|
|
240
|
+
);
|
|
241
|
+
return {
|
|
242
|
+
...old,
|
|
243
|
+
filters: updatedFilters,
|
|
244
|
+
};
|
|
245
|
+
});
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
table.removeColumnFilter = (filterId: string) => {
|
|
249
|
+
if (!table.options.enableAdvanceColumnFilter) return;
|
|
250
|
+
table.setColumnFilterState((old) => ({
|
|
251
|
+
...old,
|
|
252
|
+
filters: old.filters.filter((filter) => filter.id !== filterId),
|
|
253
|
+
}));
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
table.clearAllColumnFilters = () => {
|
|
257
|
+
if (!table.options.enableAdvanceColumnFilter) return;
|
|
258
|
+
table.setColumnFilterState((old) => ({
|
|
259
|
+
...old,
|
|
260
|
+
filters: [],
|
|
261
|
+
}));
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
table.setFilterLogic = (logic: 'AND' | 'OR') => {
|
|
265
|
+
if (!table.options.enableAdvanceColumnFilter) return;
|
|
266
|
+
table.setColumnFilterState((old) => ({
|
|
267
|
+
...old,
|
|
268
|
+
logic,
|
|
269
|
+
}));
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// === GETTERS ===
|
|
273
|
+
table.getActiveColumnFilters = () => {
|
|
274
|
+
const state = table.getState().columnFilter;
|
|
275
|
+
return state.filters.filter((f) => f.columnId && f.operator);
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
table.getPendingColumnFilters = () => {
|
|
279
|
+
const state = table.getState().columnFilter;
|
|
280
|
+
return state.pendingFilters.filter((f) => f.columnId && f.operator);
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
table.getColumnFilterState = () => {
|
|
284
|
+
return table.getState().columnFilter;
|
|
285
|
+
};
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Utility function to check if a row matches the custom column filters
|
|
291
|
+
* This can be used for client-side filtering
|
|
292
|
+
*/
|
|
293
|
+
export function matchesCustomColumnFilters(
|
|
294
|
+
row: any,
|
|
295
|
+
filters: ColumnFilterRule[],
|
|
296
|
+
logic: 'AND' | 'OR' = 'AND'
|
|
297
|
+
): boolean {
|
|
298
|
+
if (filters.length === 0) return true;
|
|
299
|
+
|
|
300
|
+
const activeFilters = filters.filter((f) => f.columnId && f.operator);
|
|
301
|
+
if (activeFilters.length === 0) return true;
|
|
302
|
+
|
|
303
|
+
const results = activeFilters.map((filter) => {
|
|
304
|
+
let columnValue;
|
|
305
|
+
let columnType = filter.columnType || 'text';
|
|
306
|
+
try {
|
|
307
|
+
// Try to get the value safely to avoid infinite loops
|
|
308
|
+
const column = row.getAllCells().find((cell: any) => cell.column.id === filter.columnId);
|
|
309
|
+
if (column) {
|
|
310
|
+
columnValue = column.getValue();
|
|
311
|
+
// Try to get type from columnDef if not set
|
|
312
|
+
if (!filter.columnType && column.column.columnDef && column.column.columnDef.type) {
|
|
313
|
+
columnType = column.column.columnDef.type;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
} catch (error) {
|
|
317
|
+
console.warn(`Error getting value for column ${filter.columnId}:`, error);
|
|
318
|
+
columnValue = row.original?.[filter.columnId] || '';
|
|
319
|
+
}
|
|
320
|
+
return evaluateFilterCondition(columnValue, filter.operator, filter.value, columnType);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
return logic === 'AND' ? results.every(Boolean) : results.some(Boolean);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export const getCombinedFilteredRowModel = <TData,>() => {
|
|
327
|
+
return (table: Table<TData>) => (): RowModel<TData> => {
|
|
328
|
+
// Respect server/manual filtering: skip client filtering when manualFiltering is enabled
|
|
329
|
+
if (table.options.manualFiltering) {
|
|
330
|
+
return table.getCoreRowModel();
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Run the built-in global + column filters first:
|
|
334
|
+
const baseFilteredModel = getDefaultFilter<TData>()(table)();
|
|
335
|
+
|
|
336
|
+
const { filters, logic } = table.getState().columnFilter ?? {
|
|
337
|
+
filters: [],
|
|
338
|
+
logic: 'AND',
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
if (!filters.length || !table.options.enableAdvanceColumnFilter) return baseFilteredModel;
|
|
342
|
+
|
|
343
|
+
// Apply custom column filters to pre-filtered rows
|
|
344
|
+
const filteredRows = baseFilteredModel.rows.filter(row =>
|
|
345
|
+
matchesCustomColumnFilters(row, filters, logic)
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
const flatRows: Row<TData>[] = [];
|
|
349
|
+
const rowsById: Record<string, Row<TData>> = {};
|
|
350
|
+
|
|
351
|
+
const addRow = (row: Row<TData>) => {
|
|
352
|
+
flatRows.push(row);
|
|
353
|
+
rowsById[row.id] = row;
|
|
354
|
+
row.subRows?.forEach(addRow);
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
filteredRows.forEach(addRow);
|
|
358
|
+
|
|
359
|
+
return {
|
|
360
|
+
rows: filteredRows,
|
|
361
|
+
flatRows,
|
|
362
|
+
rowsById,
|
|
363
|
+
};
|
|
364
|
+
};
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Evaluate a single filter condition
|
|
369
|
+
*/
|
|
370
|
+
function evaluateFilterCondition(columnValue: any, operator: string, filterValue: any, type: string = 'text'): boolean {
|
|
371
|
+
// --- Date helpers using moment ---
|
|
372
|
+
function toMoment(val: any) {
|
|
373
|
+
if (!val) return null;
|
|
374
|
+
const m = moment(val);
|
|
375
|
+
return m.isValid() ? m : null;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// --- Date type logic ---
|
|
379
|
+
if (type === 'date') {
|
|
380
|
+
const mCol = toMoment(columnValue);
|
|
381
|
+
const mFilter = toMoment(filterValue);
|
|
382
|
+
if (!mCol || !mFilter) return false;
|
|
383
|
+
switch (operator) {
|
|
384
|
+
case 'equals':
|
|
385
|
+
return mCol.isSame(mFilter, 'day');
|
|
386
|
+
case 'notEquals':
|
|
387
|
+
return !mCol.isSame(mFilter, 'day');
|
|
388
|
+
case 'after':
|
|
389
|
+
return mCol.isAfter(mFilter, 'day');
|
|
390
|
+
case 'before':
|
|
391
|
+
return mCol.isBefore(mFilter, 'day');
|
|
392
|
+
case 'isEmpty':
|
|
393
|
+
return !columnValue;
|
|
394
|
+
case 'isNotEmpty':
|
|
395
|
+
return !!columnValue;
|
|
396
|
+
default:
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// --- Boolean type logic ---
|
|
402
|
+
if (type === 'boolean') {
|
|
403
|
+
switch (operator) {
|
|
404
|
+
case 'is':
|
|
405
|
+
if (filterValue === 'any') return true;
|
|
406
|
+
if (filterValue === 'true') return (columnValue === true || columnValue === 'true' || columnValue === 1 || columnValue === '1' || columnValue === 'Yes' || columnValue === 'yes');
|
|
407
|
+
if (filterValue === 'false') return (columnValue === false || columnValue === 'false' || columnValue === 0 || columnValue === '0' || columnValue === 'No' || columnValue === 'no');
|
|
408
|
+
return false;
|
|
409
|
+
|
|
410
|
+
default:
|
|
411
|
+
return true;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// --- Select type logic (in, notIn, single select) ---
|
|
416
|
+
if (type === 'select') {
|
|
417
|
+
if (operator === 'in' || operator === 'notIn') {
|
|
418
|
+
if (Array.isArray(filterValue)) {
|
|
419
|
+
if (operator === 'in') return filterValue.includes(columnValue);
|
|
420
|
+
if (operator === 'notIn') return !filterValue.includes(columnValue);
|
|
421
|
+
}
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
if (operator === 'equals' || operator === 'notEquals') {
|
|
425
|
+
return operator === 'equals'
|
|
426
|
+
? columnValue === filterValue
|
|
427
|
+
: columnValue !== filterValue;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// --- Text/Number type logic ---
|
|
432
|
+
switch (operator) {
|
|
433
|
+
case 'contains':
|
|
434
|
+
return String(columnValue).toLowerCase().includes(String(filterValue).toLowerCase());
|
|
435
|
+
case 'notContains':
|
|
436
|
+
return !String(columnValue).toLowerCase().includes(String(filterValue).toLowerCase());
|
|
437
|
+
case 'startsWith':
|
|
438
|
+
return String(columnValue).toLowerCase().startsWith(String(filterValue).toLowerCase());
|
|
439
|
+
case 'endsWith':
|
|
440
|
+
return String(columnValue).toLowerCase().endsWith(String(filterValue).toLowerCase());
|
|
441
|
+
case 'isEmpty':
|
|
442
|
+
return columnValue === null || columnValue === undefined || columnValue === '';
|
|
443
|
+
case 'isNotEmpty':
|
|
444
|
+
return columnValue !== null && columnValue !== undefined && columnValue !== '';
|
|
445
|
+
case 'greaterThan':
|
|
446
|
+
return Number(columnValue) > Number(filterValue);
|
|
447
|
+
case 'greaterThanOrEqual':
|
|
448
|
+
return Number(columnValue) >= Number(filterValue);
|
|
449
|
+
case 'lessThan':
|
|
450
|
+
return Number(columnValue) < Number(filterValue);
|
|
451
|
+
case 'lessThanOrEqual':
|
|
452
|
+
return Number(columnValue) <= Number(filterValue);
|
|
453
|
+
default:
|
|
454
|
+
return true;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
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';
|