@tanstack/table-core 9.0.0-beta.46 → 9.0.0-beta.47
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/features/column-filtering/columnFilteringFeature.types.d.cts +43 -3
- package/dist/features/column-filtering/columnFilteringFeature.types.d.ts +43 -3
- package/dist/features/column-filtering/columnFilteringFeature.utils.cjs +18 -9
- package/dist/features/column-filtering/columnFilteringFeature.utils.cjs.map +1 -1
- package/dist/features/column-filtering/columnFilteringFeature.utils.d.cts +6 -2
- package/dist/features/column-filtering/columnFilteringFeature.utils.d.ts +6 -2
- package/dist/features/column-filtering/columnFilteringFeature.utils.js +18 -9
- package/dist/features/column-filtering/columnFilteringFeature.utils.js.map +1 -1
- package/dist/features/column-filtering/createFilteredRowModel.cjs +7 -2
- package/dist/features/column-filtering/createFilteredRowModel.cjs.map +1 -1
- package/dist/features/column-filtering/createFilteredRowModel.d.cts +6 -2
- package/dist/features/column-filtering/createFilteredRowModel.d.ts +6 -2
- package/dist/features/column-filtering/createFilteredRowModel.js +7 -2
- package/dist/features/column-filtering/createFilteredRowModel.js.map +1 -1
- package/dist/features/column-grouping/columnGroupingFeature.types.d.cts +41 -3
- package/dist/features/column-grouping/columnGroupingFeature.types.d.ts +41 -3
- package/dist/features/column-grouping/columnGroupingFeature.utils.cjs +17 -3
- package/dist/features/column-grouping/columnGroupingFeature.utils.cjs.map +1 -1
- package/dist/features/column-grouping/columnGroupingFeature.utils.d.cts +5 -0
- package/dist/features/column-grouping/columnGroupingFeature.utils.d.ts +5 -0
- package/dist/features/column-grouping/columnGroupingFeature.utils.js +17 -3
- package/dist/features/column-grouping/columnGroupingFeature.utils.js.map +1 -1
- package/dist/features/column-grouping/createGroupedRowModel.cjs +6 -3
- package/dist/features/column-grouping/createGroupedRowModel.cjs.map +1 -1
- package/dist/features/column-grouping/createGroupedRowModel.d.cts +6 -3
- package/dist/features/column-grouping/createGroupedRowModel.d.ts +6 -3
- package/dist/features/column-grouping/createGroupedRowModel.js +6 -3
- package/dist/features/column-grouping/createGroupedRowModel.js.map +1 -1
- package/dist/features/global-filtering/globalFilteringFeature.utils.cjs +3 -1
- package/dist/features/global-filtering/globalFilteringFeature.utils.cjs.map +1 -1
- package/dist/features/global-filtering/globalFilteringFeature.utils.d.cts +2 -6
- package/dist/features/global-filtering/globalFilteringFeature.utils.d.ts +2 -6
- package/dist/features/global-filtering/globalFilteringFeature.utils.js +3 -1
- package/dist/features/global-filtering/globalFilteringFeature.utils.js.map +1 -1
- package/dist/features/row-sorting/createSortedRowModel.cjs +6 -2
- package/dist/features/row-sorting/createSortedRowModel.cjs.map +1 -1
- package/dist/features/row-sorting/createSortedRowModel.d.cts +6 -2
- package/dist/features/row-sorting/createSortedRowModel.d.ts +6 -2
- package/dist/features/row-sorting/createSortedRowModel.js +6 -2
- package/dist/features/row-sorting/createSortedRowModel.js.map +1 -1
- package/dist/features/row-sorting/rowSortingFeature.types.d.cts +31 -2
- package/dist/features/row-sorting/rowSortingFeature.types.d.ts +31 -2
- package/dist/features/row-sorting/rowSortingFeature.utils.cjs +19 -4
- package/dist/features/row-sorting/rowSortingFeature.utils.cjs.map +1 -1
- package/dist/features/row-sorting/rowSortingFeature.utils.js +19 -4
- package/dist/features/row-sorting/rowSortingFeature.utils.js.map +1 -1
- package/dist/fns/aggregationFns.cjs +128 -57
- package/dist/fns/aggregationFns.cjs.map +1 -1
- package/dist/fns/aggregationFns.d.cts +72 -18
- package/dist/fns/aggregationFns.d.ts +72 -18
- package/dist/fns/aggregationFns.js +126 -58
- package/dist/fns/aggregationFns.js.map +1 -1
- package/dist/fns/filterFns.cjs +253 -96
- package/dist/fns/filterFns.cjs.map +1 -1
- package/dist/fns/filterFns.d.cts +126 -94
- package/dist/fns/filterFns.d.ts +126 -94
- package/dist/fns/filterFns.js +246 -97
- package/dist/fns/filterFns.js.map +1 -1
- package/dist/fns/sortFns.cjs +68 -21
- package/dist/fns/sortFns.cjs.map +1 -1
- package/dist/fns/sortFns.d.cts +48 -15
- package/dist/fns/sortFns.d.ts +48 -15
- package/dist/fns/sortFns.js +68 -22
- package/dist/fns/sortFns.js.map +1 -1
- package/dist/helpers/tableFeatures.cjs +5 -4
- package/dist/helpers/tableFeatures.cjs.map +1 -1
- package/dist/helpers/tableFeatures.d.cts +5 -4
- package/dist/helpers/tableFeatures.d.ts +5 -4
- package/dist/helpers/tableFeatures.js +5 -4
- package/dist/helpers/tableFeatures.js.map +1 -1
- package/dist/index.cjs +12 -0
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +4 -4
- package/dist/types/TableFeatures.d.cts +15 -7
- package/dist/types/TableFeatures.d.ts +15 -7
- package/dist/types/type-utils.d.cts +8 -1
- package/dist/types/type-utils.d.ts +8 -1
- package/package.json +1 -1
- package/skills/api-not-found/SKILL.md +1 -1
- package/skills/client-vs-server/SKILL.md +1 -1
- package/skills/column-faceting/SKILL.md +11 -5
- package/skills/column-filtering/SKILL.md +8 -3
- package/skills/column-ordering/SKILL.md +1 -1
- package/skills/column-pinning/SKILL.md +1 -1
- package/skills/column-resizing/SKILL.md +1 -1
- package/skills/column-sizing/SKILL.md +1 -1
- package/skills/column-visibility/SKILL.md +1 -1
- package/skills/core/SKILL.md +1 -1
- package/skills/custom-features/SKILL.md +1 -1
- package/skills/expanding/SKILL.md +1 -1
- package/skills/global-filtering/SKILL.md +3 -3
- package/skills/grouping/SKILL.md +8 -3
- package/skills/migrate-v8-to-v9/SKILL.md +7 -7
- package/skills/pagination/SKILL.md +1 -1
- package/skills/row-pinning/SKILL.md +1 -1
- package/skills/row-selection/SKILL.md +1 -1
- package/skills/sorting/SKILL.md +9 -3
- package/skills/table-features/SKILL.md +16 -13
- package/skills/typescript/SKILL.md +1 -1
- package/src/features/column-filtering/columnFilteringFeature.types.ts +60 -0
- package/src/features/column-filtering/columnFilteringFeature.utils.ts +33 -19
- package/src/features/column-filtering/createFilteredRowModel.ts +13 -3
- package/src/features/column-grouping/columnGroupingFeature.types.ts +63 -8
- package/src/features/column-grouping/columnGroupingFeature.utils.ts +43 -9
- package/src/features/column-grouping/createGroupedRowModel.ts +6 -3
- package/src/features/global-filtering/globalFilteringFeature.utils.ts +8 -0
- package/src/features/row-sorting/createSortedRowModel.ts +6 -2
- package/src/features/row-sorting/rowSortingFeature.types.ts +53 -1
- package/src/features/row-sorting/rowSortingFeature.utils.ts +45 -13
- package/src/fns/aggregationFns.ts +204 -146
- package/src/fns/filterFns.ts +361 -283
- package/src/fns/sortFns.ts +95 -78
- package/src/helpers/tableFeatures.ts +5 -4
- package/src/types/TableFeatures.ts +15 -7
- package/src/types/type-utils.ts +8 -0
package/src/fns/filterFns.ts
CHANGED
|
@@ -1,7 +1,72 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CreatedFilterFn,
|
|
3
|
+
ExtractFilterMeta,
|
|
4
|
+
FilterFnDef,
|
|
5
|
+
} from '../features/column-filtering/columnFilteringFeature.types'
|
|
1
6
|
import type { RowData } from '../types/type-utils'
|
|
2
7
|
import type { TableFeatures } from '../types/TableFeatures'
|
|
3
8
|
import type { Row } from '../types/Row'
|
|
4
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Builds a `FilterFn` from a value-level comparator plus optional resolvers.
|
|
12
|
+
*
|
|
13
|
+
* The `filter` comparator receives the row's data value (already passed
|
|
14
|
+
* through `resolveDataValue` when one is defined) and the filter value
|
|
15
|
+
* (already passed through `resolveFilterValue` by the table). Keeping
|
|
16
|
+
* normalization in the resolvers means a variant of an existing filter
|
|
17
|
+
* function only has to swap the resolvers, not re-implement the comparison.
|
|
18
|
+
*
|
|
19
|
+
* The definition is attached to the returned function, so a variant can be
|
|
20
|
+
* created by spreading a built-in filter function and overriding what differs:
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* const normalize = (value: unknown) =>
|
|
24
|
+
* String(value ?? '')
|
|
25
|
+
* .toLowerCase()
|
|
26
|
+
* .normalize('NFD')
|
|
27
|
+
* .replace(/\p{Diacritic}/gu, '')
|
|
28
|
+
*
|
|
29
|
+
* const includesStringIgnoreDiacritics = constructFilterFn({
|
|
30
|
+
* ...filterFn_includesString,
|
|
31
|
+
* resolveFilterValue: normalize,
|
|
32
|
+
* resolveDataValue: normalize,
|
|
33
|
+
* })
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* Note: the table applies `resolveFilterValue` once per filter before any rows
|
|
37
|
+
* are tested. When calling a filter function directly (outside of a table),
|
|
38
|
+
* apply it yourself: `fn(row, columnId, fn.resolveFilterValue?.(value) ?? value)`.
|
|
39
|
+
*/
|
|
40
|
+
export function constructFilterFn<
|
|
41
|
+
TFeatures extends TableFeatures = any,
|
|
42
|
+
TData extends RowData = any,
|
|
43
|
+
>(def: FilterFnDef<TFeatures, TData>): CreatedFilterFn<TFeatures, TData> {
|
|
44
|
+
const filterFn: CreatedFilterFn<TFeatures, TData> = Object.assign(
|
|
45
|
+
<TRowFeatures extends TableFeatures, TRowData extends RowData>(
|
|
46
|
+
row: Row<TRowFeatures, TRowData>,
|
|
47
|
+
columnId: string,
|
|
48
|
+
filterValue: any,
|
|
49
|
+
addMeta?: (meta: ExtractFilterMeta<TRowFeatures>) => void,
|
|
50
|
+
): boolean => {
|
|
51
|
+
const rawValue = row.getValue(columnId)
|
|
52
|
+
const dataValue = filterFn.resolveDataValue
|
|
53
|
+
? filterFn.resolveDataValue(rawValue)
|
|
54
|
+
: rawValue
|
|
55
|
+
// The def's comparator is typed against the factory's TFeatures/TData;
|
|
56
|
+
// the caller's row generics are erased at this boundary.
|
|
57
|
+
return filterFn.filter(
|
|
58
|
+
dataValue,
|
|
59
|
+
filterValue,
|
|
60
|
+
row as any,
|
|
61
|
+
columnId,
|
|
62
|
+
addMeta as any,
|
|
63
|
+
)
|
|
64
|
+
},
|
|
65
|
+
def,
|
|
66
|
+
)
|
|
67
|
+
return filterFn
|
|
68
|
+
}
|
|
69
|
+
|
|
5
70
|
// Basic filters
|
|
6
71
|
|
|
7
72
|
/**
|
|
@@ -9,16 +74,10 @@ import type { Row } from '../types/Row'
|
|
|
9
74
|
*
|
|
10
75
|
* Uses JavaScript `===` comparison and auto-removes empty filter values.
|
|
11
76
|
*/
|
|
12
|
-
export const filterFn_equals =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
filterValue: unknown,
|
|
17
|
-
) => {
|
|
18
|
-
return row.getValue(columnId) === filterValue
|
|
19
|
-
},
|
|
20
|
-
{ autoRemove: (val: any) => testFalsy(val) },
|
|
21
|
-
)
|
|
77
|
+
export const filterFn_equals = constructFilterFn({
|
|
78
|
+
filter: (dataValue, filterValue) => dataValue === filterValue,
|
|
79
|
+
autoRemove: (val: any) => testFalsy(val),
|
|
80
|
+
})
|
|
22
81
|
|
|
23
82
|
/**
|
|
24
83
|
* Keeps rows whose column value is loosely equal to the filter value.
|
|
@@ -26,16 +85,10 @@ export const filterFn_equals = Object.assign(
|
|
|
26
85
|
* Uses JavaScript `==` comparison and auto-removes empty filter values. This is
|
|
27
86
|
* useful for matching string input against numeric row values.
|
|
28
87
|
*/
|
|
29
|
-
export const filterFn_weakEquals =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
filterValue: unknown,
|
|
34
|
-
) => {
|
|
35
|
-
return row.getValue(columnId) == filterValue
|
|
36
|
-
},
|
|
37
|
-
{ autoRemove: (val: any) => testFalsy(val) },
|
|
38
|
-
)
|
|
88
|
+
export const filterFn_weakEquals = constructFilterFn({
|
|
89
|
+
filter: (dataValue, filterValue) => dataValue == filterValue,
|
|
90
|
+
autoRemove: (val: any) => testFalsy(val),
|
|
91
|
+
})
|
|
39
92
|
|
|
40
93
|
// String filters
|
|
41
94
|
|
|
@@ -44,21 +97,12 @@ export const filterFn_weakEquals = Object.assign(
|
|
|
44
97
|
*
|
|
45
98
|
* Matching is case-sensitive and empty filter values are auto-removed.
|
|
46
99
|
*/
|
|
47
|
-
export const filterFn_includesStringSensitive =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return Boolean(
|
|
54
|
-
row.getValue(columnId)?.toString().includes(String(filterValue)),
|
|
55
|
-
)
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
autoRemove: (val: any) => testFalsy(val),
|
|
59
|
-
resolveFilterValue: (val: any) => String(val),
|
|
60
|
-
},
|
|
61
|
-
)
|
|
100
|
+
export const filterFn_includesStringSensitive = constructFilterFn({
|
|
101
|
+
filter: (dataValue, filterValue) => Boolean(dataValue?.includes(filterValue)),
|
|
102
|
+
autoRemove: (val: any) => testFalsy(val),
|
|
103
|
+
resolveFilterValue: (val: any) => String(val),
|
|
104
|
+
resolveDataValue: (val: any) => (val == null ? undefined : String(val)),
|
|
105
|
+
})
|
|
62
106
|
|
|
63
107
|
/**
|
|
64
108
|
* Keeps rows whose stringified column value includes the filter text.
|
|
@@ -66,25 +110,13 @@ export const filterFn_includesStringSensitive = Object.assign(
|
|
|
66
110
|
* Both values are lowercased before comparison, and empty filter values are
|
|
67
111
|
* auto-removed.
|
|
68
112
|
*/
|
|
69
|
-
export const filterFn_includesString =
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
row
|
|
77
|
-
.getValue(columnId)
|
|
78
|
-
?.toString()
|
|
79
|
-
.toLowerCase()
|
|
80
|
-
.includes(String(filterValue).toLowerCase()),
|
|
81
|
-
)
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
autoRemove: (val: any) => testFalsy(val),
|
|
85
|
-
resolveFilterValue: (val: any) => String(val).toLowerCase(),
|
|
86
|
-
},
|
|
87
|
-
)
|
|
113
|
+
export const filterFn_includesString = constructFilterFn({
|
|
114
|
+
filter: (dataValue, filterValue) => Boolean(dataValue?.includes(filterValue)),
|
|
115
|
+
autoRemove: (val: any) => testFalsy(val),
|
|
116
|
+
resolveFilterValue: (val: any) => String(val).toLowerCase(),
|
|
117
|
+
resolveDataValue: (val: any) =>
|
|
118
|
+
val == null ? undefined : String(val).toLowerCase(),
|
|
119
|
+
})
|
|
88
120
|
|
|
89
121
|
/**
|
|
90
122
|
* Keeps rows whose stringified column value equals the filter text.
|
|
@@ -92,41 +124,80 @@ export const filterFn_includesString = Object.assign(
|
|
|
92
124
|
* Both values are lowercased before comparison, and empty filter values are
|
|
93
125
|
* auto-removed.
|
|
94
126
|
*/
|
|
95
|
-
export const filterFn_equalsString =
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
row.getValue(columnId)?.toString().toLowerCase() ===
|
|
103
|
-
String(filterValue).toLowerCase()
|
|
104
|
-
)
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
autoRemove: (val: any) => testFalsy(val),
|
|
108
|
-
resolveFilterValue: (val: any) => String(val).toLowerCase(),
|
|
109
|
-
},
|
|
110
|
-
)
|
|
127
|
+
export const filterFn_equalsString = constructFilterFn({
|
|
128
|
+
filter: (dataValue, filterValue) => dataValue === filterValue,
|
|
129
|
+
autoRemove: (val: any) => testFalsy(val),
|
|
130
|
+
resolveFilterValue: (val: any) => String(val).toLowerCase(),
|
|
131
|
+
resolveDataValue: (val: any) =>
|
|
132
|
+
val == null ? undefined : String(val).toLowerCase(),
|
|
133
|
+
})
|
|
111
134
|
|
|
112
135
|
/**
|
|
113
136
|
* Keeps rows whose stringified column value exactly equals the filter text.
|
|
114
137
|
*
|
|
115
138
|
* Matching is case-sensitive and empty filter values are auto-removed.
|
|
116
139
|
*/
|
|
117
|
-
export const filterFn_equalsStringSensitive =
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
140
|
+
export const filterFn_equalsStringSensitive = constructFilterFn({
|
|
141
|
+
filter: (dataValue, filterValue) => dataValue === filterValue,
|
|
142
|
+
autoRemove: (val: any) => testFalsy(val),
|
|
143
|
+
resolveFilterValue: (val: any) => String(val),
|
|
144
|
+
resolveDataValue: (val: any) => (val == null ? undefined : String(val)),
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Keeps rows whose stringified column value starts with the filter text.
|
|
149
|
+
*
|
|
150
|
+
* Both values are lowercased before comparison, and empty filter values are
|
|
151
|
+
* auto-removed.
|
|
152
|
+
*/
|
|
153
|
+
export const filterFn_startsWith = constructFilterFn({
|
|
154
|
+
filter: (dataValue, filterValue) =>
|
|
155
|
+
Boolean(dataValue?.startsWith(filterValue)),
|
|
156
|
+
autoRemove: (val: any) => testFalsy(val),
|
|
157
|
+
resolveFilterValue: (val: any) => String(val).toLowerCase(),
|
|
158
|
+
resolveDataValue: (val: any) =>
|
|
159
|
+
val == null ? undefined : String(val).toLowerCase(),
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Keeps rows whose stringified column value ends with the filter text.
|
|
164
|
+
*
|
|
165
|
+
* Both values are lowercased before comparison, and empty filter values are
|
|
166
|
+
* auto-removed.
|
|
167
|
+
*/
|
|
168
|
+
export const filterFn_endsWith = constructFilterFn({
|
|
169
|
+
filter: (dataValue, filterValue) => Boolean(dataValue?.endsWith(filterValue)),
|
|
170
|
+
autoRemove: (val: any) => testFalsy(val),
|
|
171
|
+
resolveFilterValue: (val: any) => String(val).toLowerCase(),
|
|
172
|
+
resolveDataValue: (val: any) =>
|
|
173
|
+
val == null ? undefined : String(val).toLowerCase(),
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
// Blank filters
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Keeps rows whose column value is empty.
|
|
180
|
+
*
|
|
181
|
+
* A value is empty when it is nullish or stringifies to whitespace only. The
|
|
182
|
+
* filter value acts as an on/off flag: `false` and blank values are
|
|
183
|
+
* auto-removed.
|
|
184
|
+
*/
|
|
185
|
+
export const filterFn_empty = constructFilterFn({
|
|
186
|
+
filter: (dataValue) => testValueEmpty(dataValue),
|
|
187
|
+
autoRemove: (val: any) => testFalsy(val) || val === false,
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Keeps rows whose column value is not empty.
|
|
192
|
+
*
|
|
193
|
+
* A value is empty when it is nullish or stringifies to whitespace only. The
|
|
194
|
+
* filter value acts as an on/off flag: `false` and blank values are
|
|
195
|
+
* auto-removed.
|
|
196
|
+
*/
|
|
197
|
+
export const filterFn_notEmpty = constructFilterFn({
|
|
198
|
+
filter: (dataValue) => !testValueEmpty(dataValue),
|
|
199
|
+
autoRemove: (val: any) => testFalsy(val) || val === false,
|
|
200
|
+
})
|
|
130
201
|
|
|
131
202
|
// Number filters
|
|
132
203
|
|
|
@@ -136,78 +207,44 @@ export const filterFn_equalsStringSensitive = Object.assign(
|
|
|
136
207
|
* Numeric values are compared numerically when both sides can be coerced to
|
|
137
208
|
* numbers; otherwise normalized strings are compared.
|
|
138
209
|
*/
|
|
139
|
-
export const filterFn_greaterThan =
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
) => {
|
|
145
|
-
const rowValue = row.getValue(columnId)
|
|
146
|
-
const numericRowValue =
|
|
147
|
-
rowValue === null || rowValue === undefined ? 0 : +rowValue
|
|
148
|
-
const numericFilterValue = Number(filterValue)
|
|
149
|
-
|
|
150
|
-
if (!isNaN(numericFilterValue) && !isNaN(numericRowValue)) {
|
|
151
|
-
return numericRowValue > numericFilterValue
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const stringValue = (rowValue ?? '').toString().toLowerCase().trim()
|
|
155
|
-
const stringFilterValue = String(filterValue).toLowerCase().trim()
|
|
156
|
-
return stringValue > stringFilterValue
|
|
157
|
-
},
|
|
158
|
-
{ autoRemove: (val: any) => testFalsy(val) },
|
|
159
|
-
)
|
|
210
|
+
export const filterFn_greaterThan = constructFilterFn({
|
|
211
|
+
filter: (dataValue, filterValue) =>
|
|
212
|
+
compareGreaterThan(dataValue, filterValue),
|
|
213
|
+
autoRemove: (val: any) => testFalsy(val),
|
|
214
|
+
})
|
|
160
215
|
|
|
161
216
|
/**
|
|
162
217
|
* Keeps rows whose value is greater than or equal to the filter value.
|
|
163
218
|
*
|
|
164
|
-
* Delegates to the built-in greater-than and equality comparisons.
|
|
219
|
+
* Delegates to the built-in greater-than and strict-equality comparisons.
|
|
165
220
|
*/
|
|
166
|
-
export const filterFn_greaterThanOrEqualTo =
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
) => {
|
|
172
|
-
return (
|
|
173
|
-
filterFn_greaterThan(row, columnId, filterValue) ||
|
|
174
|
-
filterFn_equals(row, columnId, filterValue)
|
|
175
|
-
)
|
|
176
|
-
},
|
|
177
|
-
{ autoRemove: (val: any) => testFalsy(val) },
|
|
178
|
-
)
|
|
221
|
+
export const filterFn_greaterThanOrEqualTo = constructFilterFn({
|
|
222
|
+
filter: (dataValue, filterValue) =>
|
|
223
|
+
compareGreaterThanOrEqualTo(dataValue, filterValue),
|
|
224
|
+
autoRemove: (val: any) => testFalsy(val),
|
|
225
|
+
})
|
|
179
226
|
|
|
180
227
|
/**
|
|
181
228
|
* Keeps rows whose value is less than the filter value.
|
|
182
229
|
*
|
|
183
230
|
* This is implemented as the inverse of greater-than-or-equal comparison.
|
|
184
231
|
*/
|
|
185
|
-
export const filterFn_lessThan =
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
) => {
|
|
191
|
-
return !filterFn_greaterThanOrEqualTo(row, columnId, filterValue)
|
|
192
|
-
},
|
|
193
|
-
{ autoRemove: (val: any) => testFalsy(val) },
|
|
194
|
-
)
|
|
232
|
+
export const filterFn_lessThan = constructFilterFn({
|
|
233
|
+
filter: (dataValue, filterValue) =>
|
|
234
|
+
!compareGreaterThanOrEqualTo(dataValue, filterValue),
|
|
235
|
+
autoRemove: (val: any) => testFalsy(val),
|
|
236
|
+
})
|
|
195
237
|
|
|
196
238
|
/**
|
|
197
239
|
* Keeps rows whose value is less than or equal to the filter value.
|
|
198
240
|
*
|
|
199
241
|
* This is implemented as the inverse of greater-than comparison.
|
|
200
242
|
*/
|
|
201
|
-
export const filterFn_lessThanOrEqualTo =
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
) => {
|
|
207
|
-
return !filterFn_greaterThan(row, columnId, filterValue)
|
|
208
|
-
},
|
|
209
|
-
{ autoRemove: (val: any) => testFalsy(val) },
|
|
210
|
-
)
|
|
243
|
+
export const filterFn_lessThanOrEqualTo = constructFilterFn({
|
|
244
|
+
filter: (dataValue, filterValue) =>
|
|
245
|
+
!compareGreaterThan(dataValue, filterValue),
|
|
246
|
+
autoRemove: (val: any) => testFalsy(val),
|
|
247
|
+
})
|
|
211
248
|
|
|
212
249
|
// Range filters
|
|
213
250
|
|
|
@@ -216,80 +253,26 @@ export const filterFn_lessThanOrEqualTo = Object.assign(
|
|
|
216
253
|
*
|
|
217
254
|
* Blank range endpoints are treated as open-ended.
|
|
218
255
|
*/
|
|
219
|
-
const filterFn_between =
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (min !== '' && min !== undefined) {
|
|
227
|
-
if (!filterFn_greaterThan(row, columnId, min)) {
|
|
228
|
-
return false
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const max = filterValues[1]
|
|
233
|
-
if (max === '' || max === undefined) {
|
|
234
|
-
return true
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (min !== '' && min !== undefined) {
|
|
238
|
-
const numericMin = Number(min)
|
|
239
|
-
const numericMax = Number(max)
|
|
240
|
-
if (!isNaN(numericMin) && !isNaN(numericMax) && numericMin > numericMax) {
|
|
241
|
-
return true
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
return filterFn_lessThan(row, columnId, max)
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
autoRemove: (val: any) =>
|
|
249
|
-
testFalsy(val) ||
|
|
250
|
-
(Array.isArray(val) && testFalsy(val[0]) && testFalsy(val[1])),
|
|
251
|
-
},
|
|
252
|
-
)
|
|
256
|
+
export const filterFn_between = constructFilterFn({
|
|
257
|
+
filter: (dataValue, filterValues: [unknown, unknown]) =>
|
|
258
|
+
compareBetween(dataValue, filterValues, false),
|
|
259
|
+
autoRemove: (val: any) =>
|
|
260
|
+
testFalsy(val) ||
|
|
261
|
+
(Array.isArray(val) && testFalsy(val[0]) && testFalsy(val[1])),
|
|
262
|
+
})
|
|
253
263
|
|
|
254
264
|
/**
|
|
255
265
|
* Keeps rows whose value falls between an inclusive min/max pair.
|
|
256
266
|
*
|
|
257
267
|
* Blank range endpoints are treated as open-ended.
|
|
258
268
|
*/
|
|
259
|
-
const filterFn_betweenInclusive =
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
if (min !== '' && min !== undefined) {
|
|
267
|
-
if (!filterFn_greaterThanOrEqualTo(row, columnId, min)) {
|
|
268
|
-
return false
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const max = filterValues[1]
|
|
273
|
-
if (max === '' || max === undefined) {
|
|
274
|
-
return true
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
if (min !== '' && min !== undefined) {
|
|
278
|
-
const numericMin = Number(min)
|
|
279
|
-
const numericMax = Number(max)
|
|
280
|
-
if (!isNaN(numericMin) && !isNaN(numericMax) && numericMin > numericMax) {
|
|
281
|
-
return true
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
return filterFn_lessThanOrEqualTo(row, columnId, max)
|
|
286
|
-
},
|
|
287
|
-
{
|
|
288
|
-
autoRemove: (val: any) =>
|
|
289
|
-
testFalsy(val) ||
|
|
290
|
-
(Array.isArray(val) && testFalsy(val[0]) && testFalsy(val[1])),
|
|
291
|
-
},
|
|
292
|
-
)
|
|
269
|
+
export const filterFn_betweenInclusive = constructFilterFn({
|
|
270
|
+
filter: (dataValue, filterValues: [unknown, unknown]) =>
|
|
271
|
+
compareBetween(dataValue, filterValues, true),
|
|
272
|
+
autoRemove: (val: any) =>
|
|
273
|
+
testFalsy(val) ||
|
|
274
|
+
(Array.isArray(val) && testFalsy(val[0]) && testFalsy(val[1])),
|
|
275
|
+
})
|
|
293
276
|
|
|
294
277
|
/**
|
|
295
278
|
* Keeps rows whose numeric value is inside an inclusive `[min, max]` range.
|
|
@@ -297,139 +280,156 @@ const filterFn_betweenInclusive = Object.assign(
|
|
|
297
280
|
* Filter values are normalized so blank endpoints become open-ended and
|
|
298
281
|
* reversed endpoints are swapped.
|
|
299
282
|
*/
|
|
300
|
-
export const filterFn_inNumberRange =
|
|
301
|
-
|
|
302
|
-
row: Row<TFeatures, TData>,
|
|
303
|
-
columnId: string,
|
|
304
|
-
filterValue: [number, number],
|
|
305
|
-
) => {
|
|
283
|
+
export const filterFn_inNumberRange = constructFilterFn({
|
|
284
|
+
filter: (dataValue: number, filterValue: [number, number]) => {
|
|
306
285
|
const [min, max] = filterValue
|
|
286
|
+
return dataValue >= min && dataValue <= max
|
|
287
|
+
},
|
|
288
|
+
resolveFilterValue: (val: [any, any]) => {
|
|
289
|
+
const [unsafeMin, unsafeMax] = val
|
|
290
|
+
|
|
291
|
+
const parsedMin =
|
|
292
|
+
typeof unsafeMin !== 'number' ? parseFloat(unsafeMin) : unsafeMin
|
|
293
|
+
const parsedMax =
|
|
294
|
+
typeof unsafeMax !== 'number' ? parseFloat(unsafeMax) : unsafeMax
|
|
295
|
+
|
|
296
|
+
let min =
|
|
297
|
+
unsafeMin === null || Number.isNaN(parsedMin) ? -Infinity : parsedMin
|
|
298
|
+
let max =
|
|
299
|
+
unsafeMax === null || Number.isNaN(parsedMax) ? Infinity : parsedMax
|
|
300
|
+
|
|
301
|
+
if (min > max) {
|
|
302
|
+
const temp = min
|
|
303
|
+
min = max
|
|
304
|
+
max = temp
|
|
305
|
+
}
|
|
307
306
|
|
|
308
|
-
|
|
309
|
-
return rowValue >= min && rowValue <= max
|
|
307
|
+
return [min, max] as const
|
|
310
308
|
},
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
const parsedMin =
|
|
316
|
-
typeof unsafeMin !== 'number' ? parseFloat(unsafeMin) : unsafeMin
|
|
317
|
-
const parsedMax =
|
|
318
|
-
typeof unsafeMax !== 'number' ? parseFloat(unsafeMax) : unsafeMax
|
|
319
|
-
|
|
320
|
-
let min =
|
|
321
|
-
unsafeMin === null || Number.isNaN(parsedMin) ? -Infinity : parsedMin
|
|
322
|
-
let max =
|
|
323
|
-
unsafeMax === null || Number.isNaN(parsedMax) ? Infinity : parsedMax
|
|
324
|
-
|
|
325
|
-
if (min > max) {
|
|
326
|
-
const temp = min
|
|
327
|
-
min = max
|
|
328
|
-
max = temp
|
|
329
|
-
}
|
|
309
|
+
autoRemove: (val: any) =>
|
|
310
|
+
testFalsy(val) ||
|
|
311
|
+
(Array.isArray(val) && testFalsy(val[0]) && testFalsy(val[1])),
|
|
312
|
+
})
|
|
330
313
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
314
|
+
// Date filters
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Keeps rows whose date value is inside an inclusive `[min, max]` date range.
|
|
318
|
+
*
|
|
319
|
+
* Row values and range endpoints may be `Date` objects, timestamps, or
|
|
320
|
+
* parseable date strings. Blank or invalid endpoints become open-ended and
|
|
321
|
+
* reversed endpoints are swapped. Rows without a valid date never match.
|
|
322
|
+
*/
|
|
323
|
+
export const filterFn_inDateRange = constructFilterFn({
|
|
324
|
+
filter: (dataValue: number, filterValue: [number, number]) => {
|
|
325
|
+
const [min, max] = filterValue
|
|
326
|
+
return dataValue >= min && dataValue <= max
|
|
336
327
|
},
|
|
337
|
-
)
|
|
328
|
+
resolveFilterValue: (val: [any, any]) => {
|
|
329
|
+
const [unsafeMin, unsafeMax] = val
|
|
330
|
+
|
|
331
|
+
const parsedMin = toDateTimestamp(unsafeMin)
|
|
332
|
+
const parsedMax = toDateTimestamp(unsafeMax)
|
|
333
|
+
|
|
334
|
+
let min = Number.isNaN(parsedMin) ? -Infinity : parsedMin
|
|
335
|
+
let max = Number.isNaN(parsedMax) ? Infinity : parsedMax
|
|
336
|
+
|
|
337
|
+
if (min > max) {
|
|
338
|
+
const temp = min
|
|
339
|
+
min = max
|
|
340
|
+
max = temp
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return [min, max] as const
|
|
344
|
+
},
|
|
345
|
+
resolveDataValue: (val: any) => toDateTimestamp(val),
|
|
346
|
+
autoRemove: (val: any) =>
|
|
347
|
+
testFalsy(val) ||
|
|
348
|
+
(Array.isArray(val) && testFalsy(val[0]) && testFalsy(val[1])),
|
|
349
|
+
})
|
|
338
350
|
|
|
339
351
|
// Array filters
|
|
340
352
|
|
|
341
353
|
/**
|
|
342
354
|
* Keeps rows whose scalar column value equals at least one filter value.
|
|
343
355
|
*/
|
|
344
|
-
export const filterFn_arrHas =
|
|
345
|
-
|
|
346
|
-
row: Row<TFeatures, TData>,
|
|
347
|
-
columnId: string,
|
|
348
|
-
filterValue: Array<unknown>,
|
|
349
|
-
) => {
|
|
350
|
-
const value = row.getValue<unknown>(columnId)
|
|
356
|
+
export const filterFn_arrHas = constructFilterFn({
|
|
357
|
+
filter: (dataValue, filterValue: Array<unknown>) => {
|
|
351
358
|
for (let i = 0; i < filterValue.length; i++) {
|
|
352
|
-
if (
|
|
359
|
+
if (dataValue === filterValue[i]) {
|
|
353
360
|
return true
|
|
354
361
|
}
|
|
355
362
|
}
|
|
356
363
|
return false
|
|
357
364
|
},
|
|
358
|
-
|
|
359
|
-
)
|
|
365
|
+
autoRemove: (val: any) => testFalsy(val) || !val?.length,
|
|
366
|
+
})
|
|
360
367
|
|
|
361
368
|
/**
|
|
362
369
|
* Keeps rows whose array or string column value includes at least one filter value.
|
|
363
370
|
*/
|
|
364
|
-
export const filterFn_arrIncludes =
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
columnId: string,
|
|
368
|
-
filterValue: Array<unknown>,
|
|
369
|
-
) => {
|
|
370
|
-
const value = row.getValue<unknown>(columnId)
|
|
371
|
-
if (typeof value !== 'string' && !Array.isArray(value)) {
|
|
371
|
+
export const filterFn_arrIncludes = constructFilterFn({
|
|
372
|
+
filter: (dataValue, filterValue: Array<unknown>) => {
|
|
373
|
+
if (typeof dataValue !== 'string' && !Array.isArray(dataValue)) {
|
|
372
374
|
return false
|
|
373
375
|
}
|
|
374
376
|
|
|
375
377
|
for (let i = 0; i < filterValue.length; i++) {
|
|
376
|
-
if (
|
|
378
|
+
if (dataValue.includes(filterValue[i] as any)) {
|
|
377
379
|
return true
|
|
378
380
|
}
|
|
379
381
|
}
|
|
380
382
|
return false
|
|
381
383
|
},
|
|
382
|
-
|
|
383
|
-
)
|
|
384
|
+
autoRemove: (val: any) => testFalsy(val) || !val?.length,
|
|
385
|
+
})
|
|
384
386
|
|
|
385
387
|
/**
|
|
386
388
|
* Keeps rows whose array column value includes every filter value.
|
|
387
389
|
*/
|
|
388
|
-
export const filterFn_arrIncludesAll =
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
columnId: string,
|
|
392
|
-
filterValue: Array<unknown>,
|
|
393
|
-
) => {
|
|
394
|
-
const value = row.getValue<Array<unknown>>(columnId)
|
|
395
|
-
if (!Array.isArray(value)) return false
|
|
390
|
+
export const filterFn_arrIncludesAll = constructFilterFn({
|
|
391
|
+
filter: (dataValue, filterValue: Array<unknown>) => {
|
|
392
|
+
if (!Array.isArray(dataValue)) return false
|
|
396
393
|
for (let i = 0; i < filterValue.length; i++) {
|
|
397
|
-
if (!
|
|
394
|
+
if (!dataValue.includes(filterValue[i])) {
|
|
398
395
|
return false
|
|
399
396
|
}
|
|
400
397
|
}
|
|
401
398
|
return true
|
|
402
399
|
},
|
|
403
|
-
|
|
404
|
-
)
|
|
400
|
+
autoRemove: (val: any) => testFalsy(val) || !val?.length,
|
|
401
|
+
})
|
|
405
402
|
|
|
406
403
|
/**
|
|
407
404
|
* Keeps rows whose array column value includes at least one filter value.
|
|
408
405
|
*/
|
|
409
|
-
export const filterFn_arrIncludesSome =
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
columnId: string,
|
|
413
|
-
filterValue: Array<unknown>,
|
|
414
|
-
) => {
|
|
415
|
-
const value = row.getValue<Array<unknown>>(columnId)
|
|
416
|
-
if (!Array.isArray(value)) return false
|
|
406
|
+
export const filterFn_arrIncludesSome = constructFilterFn({
|
|
407
|
+
filter: (dataValue, filterValue: Array<unknown>) => {
|
|
408
|
+
if (!Array.isArray(dataValue)) return false
|
|
417
409
|
for (let i = 0; i < filterValue.length; i++) {
|
|
418
|
-
if (
|
|
410
|
+
if (dataValue.includes(filterValue[i])) {
|
|
419
411
|
return true
|
|
420
412
|
}
|
|
421
413
|
}
|
|
422
414
|
return false
|
|
423
415
|
},
|
|
424
|
-
|
|
425
|
-
)
|
|
416
|
+
autoRemove: (val: any) => testFalsy(val) || !val?.length,
|
|
417
|
+
})
|
|
426
418
|
|
|
427
419
|
// Export
|
|
428
420
|
|
|
429
421
|
/**
|
|
430
422
|
* The built-in filter function registry.
|
|
431
423
|
*
|
|
432
|
-
*
|
|
424
|
+
* Registering this full object opts out of tree-shaking: every built-in
|
|
425
|
+
* filter function ends up in your bundle. Prefer importing the `filterFn_*`
|
|
426
|
+
* functions you actually use and registering just those in the `filterFns`
|
|
427
|
+
* slot, or passing them directly to the `filterFn` column option.
|
|
428
|
+
*
|
|
429
|
+
* @deprecated Import individual `filterFn_*` functions instead for a smaller
|
|
430
|
+
* bundle. This export still works and is not going away in v9, but built-in
|
|
431
|
+
* name resolution (including `filterFn: 'auto'`) only finds functions you
|
|
432
|
+
* register yourself.
|
|
433
433
|
*/
|
|
434
434
|
export const filterFns = {
|
|
435
435
|
arrIncludes: filterFn_arrIncludes,
|
|
@@ -438,11 +438,17 @@ export const filterFns = {
|
|
|
438
438
|
arrIncludesSome: filterFn_arrIncludesSome,
|
|
439
439
|
between: filterFn_between,
|
|
440
440
|
betweenInclusive: filterFn_betweenInclusive,
|
|
441
|
+
empty: filterFn_empty,
|
|
442
|
+
endsWith: filterFn_endsWith,
|
|
441
443
|
equals: filterFn_equals,
|
|
442
444
|
equalsString: filterFn_equalsString,
|
|
445
|
+
equalsStringSensitive: filterFn_equalsStringSensitive,
|
|
446
|
+
inDateRange: filterFn_inDateRange,
|
|
443
447
|
inNumberRange: filterFn_inNumberRange,
|
|
444
448
|
includesString: filterFn_includesString,
|
|
445
449
|
includesStringSensitive: filterFn_includesStringSensitive,
|
|
450
|
+
notEmpty: filterFn_notEmpty,
|
|
451
|
+
startsWith: filterFn_startsWith,
|
|
446
452
|
weakEquals: filterFn_weakEquals,
|
|
447
453
|
}
|
|
448
454
|
|
|
@@ -453,3 +459,75 @@ export type BuiltInFilterFn = keyof typeof filterFns
|
|
|
453
459
|
function testFalsy(val: any) {
|
|
454
460
|
return val === undefined || val === null || val === ''
|
|
455
461
|
}
|
|
462
|
+
|
|
463
|
+
function testValueEmpty(dataValue: any) {
|
|
464
|
+
return dataValue == null || String(dataValue).trim() === ''
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function toDateTimestamp(value: any): number {
|
|
468
|
+
if (value instanceof Date) {
|
|
469
|
+
return value.getTime()
|
|
470
|
+
}
|
|
471
|
+
if (typeof value === 'number') {
|
|
472
|
+
return value
|
|
473
|
+
}
|
|
474
|
+
// Guard nullish and blank values explicitly: `new Date(null)` is the epoch,
|
|
475
|
+
// not an invalid date.
|
|
476
|
+
if (value == null || value === '') {
|
|
477
|
+
return NaN
|
|
478
|
+
}
|
|
479
|
+
return new Date(value).getTime()
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function compareGreaterThan(dataValue: any, filterValue: any): boolean {
|
|
483
|
+
const numericDataValue = dataValue == null ? 0 : +dataValue
|
|
484
|
+
const numericFilterValue = Number(filterValue)
|
|
485
|
+
|
|
486
|
+
if (!isNaN(numericFilterValue) && !isNaN(numericDataValue)) {
|
|
487
|
+
return numericDataValue > numericFilterValue
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const stringDataValue = String(dataValue ?? '')
|
|
491
|
+
.toLowerCase()
|
|
492
|
+
.trim()
|
|
493
|
+
const stringFilterValue = String(filterValue).toLowerCase().trim()
|
|
494
|
+
return stringDataValue > stringFilterValue
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function compareGreaterThanOrEqualTo(dataValue: any, filterValue: any) {
|
|
498
|
+
return dataValue === filterValue || compareGreaterThan(dataValue, filterValue)
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
function compareBetween(
|
|
502
|
+
dataValue: any,
|
|
503
|
+
filterValues: [unknown, unknown],
|
|
504
|
+
inclusive: boolean,
|
|
505
|
+
): boolean {
|
|
506
|
+
const min = filterValues[0]
|
|
507
|
+
const hasMin = min !== '' && min !== undefined
|
|
508
|
+
if (hasMin) {
|
|
509
|
+
const passesMin = inclusive
|
|
510
|
+
? compareGreaterThanOrEqualTo(dataValue, min)
|
|
511
|
+
: compareGreaterThan(dataValue, min)
|
|
512
|
+
if (!passesMin) {
|
|
513
|
+
return false
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
const max = filterValues[1]
|
|
518
|
+
if (max === '' || max === undefined) {
|
|
519
|
+
return true
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if (hasMin) {
|
|
523
|
+
const numericMin = Number(min)
|
|
524
|
+
const numericMax = Number(max)
|
|
525
|
+
if (!isNaN(numericMin) && !isNaN(numericMax) && numericMin > numericMax) {
|
|
526
|
+
return true
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
return inclusive
|
|
531
|
+
? !compareGreaterThan(dataValue, max)
|
|
532
|
+
: !compareGreaterThanOrEqualTo(dataValue, max)
|
|
533
|
+
}
|