@navikt/ds-react 8.5.0 → 8.5.2
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/cjs/data/table/helpers/table-grid-nav.d.ts +9 -15
- package/cjs/data/table/helpers/table-grid-nav.js +18 -25
- package/cjs/data/table/helpers/table-grid-nav.js.map +1 -1
- package/cjs/data/table/helpers/table-keyboard.d.ts +1 -1
- package/cjs/data/table/helpers/table-keyboard.js +1 -6
- package/cjs/data/table/helpers/table-keyboard.js.map +1 -1
- package/cjs/data/table/root/DataTableRoot.d.ts +41 -4
- package/cjs/data/table/root/DataTableRoot.js +10 -6
- package/cjs/data/table/root/DataTableRoot.js.map +1 -1
- package/cjs/data/table/root/useTableKeyboardNav.d.ts +1 -1
- package/cjs/data/table/root/useTableKeyboardNav.js +32 -19
- package/cjs/data/table/root/useTableKeyboardNav.js.map +1 -1
- package/cjs/data/table/td/DataTableTd.d.ts +5 -4
- package/cjs/data/table/td/DataTableTd.js +2 -2
- package/cjs/data/table/td/DataTableTd.js.map +1 -1
- package/cjs/data/token-filter/AutoSuggest.d.ts +9 -0
- package/cjs/data/token-filter/AutoSuggest.js +56 -0
- package/cjs/data/token-filter/AutoSuggest.js.map +1 -0
- package/cjs/data/token-filter/AutoSuggest.types.d.ts +12 -0
- package/cjs/data/token-filter/AutoSuggest.types.js +3 -0
- package/cjs/data/token-filter/AutoSuggest.types.js.map +1 -0
- package/cjs/data/token-filter/TokenFilter.d.ts +11 -0
- package/cjs/data/token-filter/TokenFilter.js +102 -0
- package/cjs/data/token-filter/TokenFilter.js.map +1 -0
- package/cjs/data/token-filter/TokenFilter.types.d.ts +52 -0
- package/cjs/data/token-filter/TokenFilter.types.js +3 -0
- package/cjs/data/token-filter/TokenFilter.types.js.map +1 -0
- package/cjs/data/token-filter/helpers/generate-autocomplete-options.d.ts +24 -0
- package/cjs/data/token-filter/helpers/generate-autocomplete-options.js +197 -0
- package/cjs/data/token-filter/helpers/generate-autocomplete-options.js.map +1 -0
- package/cjs/data/token-filter/helpers/grouping.d.ts +28 -0
- package/cjs/data/token-filter/helpers/grouping.js +61 -0
- package/cjs/data/token-filter/helpers/grouping.js.map +1 -0
- package/cjs/data/token-filter/helpers/operators.d.ts +22 -0
- package/cjs/data/token-filter/helpers/operators.js +66 -0
- package/cjs/data/token-filter/helpers/operators.js.map +1 -0
- package/cjs/data/token-filter/helpers/parse-query-text.d.ts +25 -0
- package/cjs/data/token-filter/helpers/parse-query-text.js +46 -0
- package/cjs/data/token-filter/helpers/parse-query-text.js.map +1 -0
- package/cjs/data/token-filter/helpers/query-builder.d.ts +20 -0
- package/cjs/data/token-filter/helpers/query-builder.js +38 -0
- package/cjs/data/token-filter/helpers/query-builder.js.map +1 -0
- package/cjs/data/token-filter/helpers/text-matching.d.ts +16 -0
- package/cjs/data/token-filter/helpers/text-matching.js +47 -0
- package/cjs/data/token-filter/helpers/text-matching.js.map +1 -0
- package/cjs/form/combobox/Input/InputController.js +1 -1
- package/cjs/form/combobox/Input/InputController.js.map +1 -1
- package/cjs/form/file-upload/dropzone/FileUploadDropzone.js +1 -1
- package/cjs/form/file-upload/dropzone/FileUploadDropzone.js.map +1 -1
- package/cjs/tooltip/Tooltip.js +1 -1
- package/cjs/tooltip/Tooltip.js.map +1 -1
- package/cjs/utils/i18n/locales/nb.d.ts +75 -154
- package/cjs/utils/i18n/locales/nb.js +75 -154
- package/cjs/utils/i18n/locales/nb.js.map +1 -1
- package/esm/data/table/helpers/table-grid-nav.d.ts +9 -15
- package/esm/data/table/helpers/table-grid-nav.js +18 -25
- package/esm/data/table/helpers/table-grid-nav.js.map +1 -1
- package/esm/data/table/helpers/table-keyboard.d.ts +1 -1
- package/esm/data/table/helpers/table-keyboard.js +1 -6
- package/esm/data/table/helpers/table-keyboard.js.map +1 -1
- package/esm/data/table/root/DataTableRoot.d.ts +41 -4
- package/esm/data/table/root/DataTableRoot.js +10 -6
- package/esm/data/table/root/DataTableRoot.js.map +1 -1
- package/esm/data/table/root/useTableKeyboardNav.d.ts +1 -1
- package/esm/data/table/root/useTableKeyboardNav.js +32 -19
- package/esm/data/table/root/useTableKeyboardNav.js.map +1 -1
- package/esm/data/table/td/DataTableTd.d.ts +5 -4
- package/esm/data/table/td/DataTableTd.js +2 -2
- package/esm/data/table/td/DataTableTd.js.map +1 -1
- package/esm/data/token-filter/AutoSuggest.d.ts +9 -0
- package/esm/data/token-filter/AutoSuggest.js +20 -0
- package/esm/data/token-filter/AutoSuggest.js.map +1 -0
- package/esm/data/token-filter/AutoSuggest.types.d.ts +12 -0
- package/esm/data/token-filter/AutoSuggest.types.js +2 -0
- package/esm/data/token-filter/AutoSuggest.types.js.map +1 -0
- package/esm/data/token-filter/TokenFilter.d.ts +11 -0
- package/esm/data/token-filter/TokenFilter.js +66 -0
- package/esm/data/token-filter/TokenFilter.js.map +1 -0
- package/esm/data/token-filter/TokenFilter.types.d.ts +52 -0
- package/esm/data/token-filter/TokenFilter.types.js +2 -0
- package/esm/data/token-filter/TokenFilter.types.js.map +1 -0
- package/esm/data/token-filter/helpers/generate-autocomplete-options.d.ts +24 -0
- package/esm/data/token-filter/helpers/generate-autocomplete-options.js +195 -0
- package/esm/data/token-filter/helpers/generate-autocomplete-options.js.map +1 -0
- package/esm/data/token-filter/helpers/grouping.d.ts +28 -0
- package/esm/data/token-filter/helpers/grouping.js +59 -0
- package/esm/data/token-filter/helpers/grouping.js.map +1 -0
- package/esm/data/token-filter/helpers/operators.d.ts +22 -0
- package/esm/data/token-filter/helpers/operators.js +60 -0
- package/esm/data/token-filter/helpers/operators.js.map +1 -0
- package/esm/data/token-filter/helpers/parse-query-text.d.ts +25 -0
- package/esm/data/token-filter/helpers/parse-query-text.js +44 -0
- package/esm/data/token-filter/helpers/parse-query-text.js.map +1 -0
- package/esm/data/token-filter/helpers/query-builder.d.ts +20 -0
- package/esm/data/token-filter/helpers/query-builder.js +34 -0
- package/esm/data/token-filter/helpers/query-builder.js.map +1 -0
- package/esm/data/token-filter/helpers/text-matching.d.ts +16 -0
- package/esm/data/token-filter/helpers/text-matching.js +45 -0
- package/esm/data/token-filter/helpers/text-matching.js.map +1 -0
- package/esm/form/combobox/Input/InputController.js +1 -1
- package/esm/form/combobox/Input/InputController.js.map +1 -1
- package/esm/form/file-upload/dropzone/FileUploadDropzone.js +1 -1
- package/esm/form/file-upload/dropzone/FileUploadDropzone.js.map +1 -1
- package/esm/tooltip/Tooltip.js +2 -2
- package/esm/tooltip/Tooltip.js.map +1 -1
- package/esm/utils/i18n/locales/nb.d.ts +75 -154
- package/esm/utils/i18n/locales/nb.js +75 -154
- package/esm/utils/i18n/locales/nb.js.map +1 -1
- package/package.json +3 -3
- package/src/data/table/helpers/table-grid-nav.test.ts +659 -0
- package/src/data/table/helpers/table-grid-nav.ts +19 -38
- package/src/data/table/helpers/table-keyboard.ts +1 -10
- package/src/data/table/root/DataTableRoot.tsx +50 -10
- package/src/data/table/root/useTableKeyboardNav.ts +35 -23
- package/src/data/table/td/DataTableTd.tsx +13 -6
- package/src/data/token-filter/AutoSuggest.tsx +55 -0
- package/src/data/token-filter/AutoSuggest.types.ts +14 -0
- package/src/data/token-filter/TokenFilter.tsx +129 -0
- package/src/data/token-filter/TokenFilter.types.ts +85 -0
- package/src/data/token-filter/helpers/generate-autocomplete-options.test.ts +896 -0
- package/src/data/token-filter/helpers/generate-autocomplete-options.ts +289 -0
- package/src/data/token-filter/helpers/grouping.test.ts +206 -0
- package/src/data/token-filter/helpers/grouping.ts +73 -0
- package/src/data/token-filter/helpers/operators.test.ts +281 -0
- package/src/data/token-filter/helpers/operators.ts +91 -0
- package/src/data/token-filter/helpers/parse-query-text.test.ts +201 -0
- package/src/data/token-filter/helpers/parse-query-text.ts +86 -0
- package/src/data/token-filter/helpers/query-builder.test.ts +126 -0
- package/src/data/token-filter/helpers/query-builder.ts +41 -0
- package/src/data/token-filter/helpers/text-matching.test.ts +125 -0
- package/src/data/token-filter/helpers/text-matching.ts +58 -0
- package/src/form/combobox/Input/InputController.tsx +0 -1
- package/src/form/file-upload/dropzone/FileUploadDropzone.tsx +0 -1
- package/src/tooltip/Tooltip.tsx +3 -3
- package/src/utils/i18n/locales/nb.ts +4 -83
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { createGroups } from "./grouping.js";
|
|
2
|
+
import { QUERY_OPERATORS } from "./operators.js";
|
|
3
|
+
import { OPERATOR_LABELS, buildQueryString } from "./query-builder.js";
|
|
4
|
+
import { matchesFilterText } from "./text-matching.js";
|
|
5
|
+
/**
|
|
6
|
+
* Generates "options" to be used as autosuggest-ottion based on the current query state.
|
|
7
|
+
*
|
|
8
|
+
* The query parser recognizes three states:
|
|
9
|
+
* - "property": User has selected/matched a property and operator ("Status = active")
|
|
10
|
+
* - "operator": User has matched a property but is typing the operator ("Status" or "Status !")
|
|
11
|
+
* - "free-text": User is typing freely without a property match (e.g., "act" or "!: test")
|
|
12
|
+
*
|
|
13
|
+
* @returns
|
|
14
|
+
* - value: The canonical query string representation for the current state.
|
|
15
|
+
* Used by the UI to determine cursor position and input replacement.
|
|
16
|
+
* - options: Grouped suggestions to display (properties, operators, or values).
|
|
17
|
+
*/
|
|
18
|
+
function generateAutoCompleteOptions(queryState, filteringProperties = [], filteringOptions = []) {
|
|
19
|
+
var _a;
|
|
20
|
+
/* State: Property and operator are matched, suggest values */
|
|
21
|
+
if (queryState.step === "property") {
|
|
22
|
+
const filterText = queryState.value || "";
|
|
23
|
+
return {
|
|
24
|
+
value: queryState.value,
|
|
25
|
+
options: createValueSuggestions(filteringOptions, queryState.operator, filterText, queryState.property),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/* State: Property matched, but operator is incomplete */
|
|
29
|
+
if (queryState.step === "operator") {
|
|
30
|
+
const operators = filterOperatorsByPrefix(getValidOperatorsForProperty(queryState.property), queryState.operatorPrefix);
|
|
31
|
+
const partialQuery = buildQueryString(queryState.property.propertyLabel, queryState.operatorPrefix, "");
|
|
32
|
+
/**
|
|
33
|
+
* Edge case: User typed an invalid operator prefix that doesn't match any operators.
|
|
34
|
+
* This can happen when typing characters that don't start any valid operator.
|
|
35
|
+
* Return empty suggestions gracefully - the UI will show "no results".
|
|
36
|
+
*
|
|
37
|
+
* TODO: When per-property operator configuration is implemented,
|
|
38
|
+
* this could also occur when a property restricts which operators are valid.
|
|
39
|
+
*/
|
|
40
|
+
if (operators.length === 0) {
|
|
41
|
+
return {
|
|
42
|
+
value: partialQuery,
|
|
43
|
+
options: [],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
value: partialQuery,
|
|
48
|
+
options: generateOperatorSuggestions(queryState.property, queryState.operatorPrefix),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/*
|
|
52
|
+
* Edge case: Input starts with operator but has no value yet (user typed just "!=")
|
|
53
|
+
* Wait for value before showing suggestions
|
|
54
|
+
*/
|
|
55
|
+
if (!queryState.value && queryState.operator) {
|
|
56
|
+
return {
|
|
57
|
+
value: "",
|
|
58
|
+
options: [],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/* Empty input: Show all properties */
|
|
62
|
+
if (!queryState.value) {
|
|
63
|
+
return {
|
|
64
|
+
value: "",
|
|
65
|
+
options: generatePropertySuggestions(filteringProperties),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/*
|
|
69
|
+
* Free-text search: Show matching values across all properties
|
|
70
|
+
* Use the detected operator if input started with one (e.g., "!= test"), otherwise default to "="
|
|
71
|
+
*/
|
|
72
|
+
return {
|
|
73
|
+
value: queryState.value,
|
|
74
|
+
options: createValueSuggestions(filteringOptions, (_a = queryState.operator) !== null && _a !== void 0 ? _a : "=", queryState.value),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Returns the valid operators for a given property.
|
|
79
|
+
* Extracts operators from the property's custom operator configuration.
|
|
80
|
+
* If none are configured, falls back to all available operators.
|
|
81
|
+
*
|
|
82
|
+
* The QueryFilteringScopedOperator can be a simple string (e.g., "=")
|
|
83
|
+
* or an object with operator and tokenType (e.g., { operator: ":", tokenType: "single" }).
|
|
84
|
+
* This function normalizes both formats and returns just the operator strings.
|
|
85
|
+
*
|
|
86
|
+
* @returns Array of valid operators for the property
|
|
87
|
+
*
|
|
88
|
+
* TODO: We omit passing the tokenType for now since it's not currently used in the UI. But will be needed for single/multi-selection.
|
|
89
|
+
*/
|
|
90
|
+
function getValidOperatorsForProperty(property) {
|
|
91
|
+
const { operators } = property;
|
|
92
|
+
/* If no operators configured, return all available operators */
|
|
93
|
+
if (!operators || operators.length === 0) {
|
|
94
|
+
return QUERY_OPERATORS;
|
|
95
|
+
}
|
|
96
|
+
/*
|
|
97
|
+
* Extract operator strings from QueryFilteringScopedOperator format
|
|
98
|
+
* Handle both simple strings and objects with operator property
|
|
99
|
+
*/
|
|
100
|
+
const operatorStrings = operators.map((op) => typeof op === "string" ? op : op.operator);
|
|
101
|
+
/* Filter to only valid QUERY_OPERATORS to ensure type safety */
|
|
102
|
+
return operatorStrings.filter((op) => QUERY_OPERATORS.includes(op));
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Filters the list of operators based on the provided prefix.
|
|
106
|
+
* If the prefix is empty, all operators are returned.
|
|
107
|
+
*/
|
|
108
|
+
function filterOperatorsByPrefix(operators, prefix) {
|
|
109
|
+
if (!prefix) {
|
|
110
|
+
return operators;
|
|
111
|
+
}
|
|
112
|
+
return operators.filter((operator) => operator.startsWith(prefix));
|
|
113
|
+
}
|
|
114
|
+
function generatePropertySuggestions(filteringProperties = [], filterText = "") {
|
|
115
|
+
const filteredProperties = [];
|
|
116
|
+
for (const property of filteringProperties) {
|
|
117
|
+
if (!property) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (matchesFilterText([
|
|
121
|
+
property.propertyLabel,
|
|
122
|
+
property.groupValuesLabel,
|
|
123
|
+
property.propertyGroup,
|
|
124
|
+
].filter(Boolean), filterText)) {
|
|
125
|
+
filteredProperties.push(property);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return createGroups(filteredProperties, (property) => property.propertyGroup, "Properties");
|
|
129
|
+
}
|
|
130
|
+
function generateOperatorSuggestions(property, operatorPrefix = "") {
|
|
131
|
+
const operators = filterOperatorsByPrefix(getValidOperatorsForProperty(property), operatorPrefix);
|
|
132
|
+
if (operators.length === 0) {
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
return [
|
|
136
|
+
{
|
|
137
|
+
label: "Operators",
|
|
138
|
+
options: operators.map((operator) => {
|
|
139
|
+
var _a;
|
|
140
|
+
return ({
|
|
141
|
+
value: buildQueryString(property.propertyLabel, operator, ""),
|
|
142
|
+
label: buildQueryString(property.propertyLabel, operator, ""),
|
|
143
|
+
description: (_a = OPERATOR_LABELS[operator]) !== null && _a !== void 0 ? _a : "",
|
|
144
|
+
});
|
|
145
|
+
}),
|
|
146
|
+
},
|
|
147
|
+
];
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Creates value suggestions for autocomplete.
|
|
151
|
+
* When scopedProperty is provided, only shows values for that property (single group).
|
|
152
|
+
* When scopedProperty is omitted, searches across all properties (multiple groups).
|
|
153
|
+
*/
|
|
154
|
+
function createValueSuggestions(filteringOptions = [], operator, filterText = "", scopedProperty) {
|
|
155
|
+
var _a, _b;
|
|
156
|
+
const groups = {};
|
|
157
|
+
for (const option of filteringOptions) {
|
|
158
|
+
if (!(option === null || option === void 0 ? void 0 : option.property)) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
/* If scoped to a property, filter to only that property's options */
|
|
162
|
+
if (scopedProperty && option.property !== scopedProperty) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
/* Build search fields */
|
|
166
|
+
const searchFields = [
|
|
167
|
+
option.label,
|
|
168
|
+
...((_a = option.tags) !== null && _a !== void 0 ? _a : []),
|
|
169
|
+
...((_b = option.filteringTags) !== null && _b !== void 0 ? _b : []),
|
|
170
|
+
];
|
|
171
|
+
if (!scopedProperty) {
|
|
172
|
+
searchFields.push(option.property.propertyLabel);
|
|
173
|
+
}
|
|
174
|
+
const matches = matchesFilterText(searchFields.filter(Boolean), filterText);
|
|
175
|
+
if (!matches) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
const groupLabel = option.property.groupValuesLabel || "Values";
|
|
179
|
+
if (!groups[groupLabel]) {
|
|
180
|
+
groups[groupLabel] = {
|
|
181
|
+
label: groupLabel,
|
|
182
|
+
options: [],
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
groups[groupLabel].options.push({
|
|
186
|
+
value: buildQueryString(option.property.propertyLabel, operator, option.value),
|
|
187
|
+
label: option.label,
|
|
188
|
+
tags: option.tags,
|
|
189
|
+
filteringTags: option.filteringTags,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return Object.values(groups).filter((group) => group.options.length > 0);
|
|
193
|
+
}
|
|
194
|
+
export { generateAutoCompleteOptions };
|
|
195
|
+
//# sourceMappingURL=generate-autocomplete-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-autocomplete-options.js","sourceRoot":"","sources":["../../../../src/data/token-filter/helpers/generate-autocomplete-options.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { OptionGroup } from "../AutoSuggest.types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Groups items into labeled groups with support for a default group.
|
|
4
|
+
* Empty or whitespace-only group labels are treated as belonging to the default group.
|
|
5
|
+
*
|
|
6
|
+
* @returns Array of groups with non-empty options
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const properties = [
|
|
10
|
+
* { name: "Status", group: "Metadata" },
|
|
11
|
+
* { name: "Region", group: "Location" },
|
|
12
|
+
* { name: "Type", group: "" },
|
|
13
|
+
* ];
|
|
14
|
+
* const groups = createGroups(
|
|
15
|
+
* properties,
|
|
16
|
+
* (p) => p.group,
|
|
17
|
+
* "Properties"
|
|
18
|
+
* );
|
|
19
|
+
*
|
|
20
|
+
* Returns:
|
|
21
|
+
* [
|
|
22
|
+
* { label: "Metadata", options: [{ name: "Status", group: "Metadata" }] },
|
|
23
|
+
* { label: "Location", options: [{ name: "Region", group: "Location" }] },
|
|
24
|
+
* { label: "Properties", options: [{ name: "Type", group: "" }] }
|
|
25
|
+
* ]
|
|
26
|
+
*/
|
|
27
|
+
declare function createGroups<T>(items: T[], getGroupLabel: (item: T) => string | undefined | null, defaultGroupLabel?: string): OptionGroup<T>[];
|
|
28
|
+
export { createGroups };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Groups items into labeled groups with support for a default group.
|
|
3
|
+
* Empty or whitespace-only group labels are treated as belonging to the default group.
|
|
4
|
+
*
|
|
5
|
+
* @returns Array of groups with non-empty options
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const properties = [
|
|
9
|
+
* { name: "Status", group: "Metadata" },
|
|
10
|
+
* { name: "Region", group: "Location" },
|
|
11
|
+
* { name: "Type", group: "" },
|
|
12
|
+
* ];
|
|
13
|
+
* const groups = createGroups(
|
|
14
|
+
* properties,
|
|
15
|
+
* (p) => p.group,
|
|
16
|
+
* "Properties"
|
|
17
|
+
* );
|
|
18
|
+
*
|
|
19
|
+
* Returns:
|
|
20
|
+
* [
|
|
21
|
+
* { label: "Metadata", options: [{ name: "Status", group: "Metadata" }] },
|
|
22
|
+
* { label: "Location", options: [{ name: "Region", group: "Location" }] },
|
|
23
|
+
* { label: "Properties", options: [{ name: "Type", group: "" }] }
|
|
24
|
+
* ]
|
|
25
|
+
*/
|
|
26
|
+
function createGroups(items, getGroupLabel, defaultGroupLabel = "Default") {
|
|
27
|
+
const defaultGroup = {
|
|
28
|
+
label: defaultGroupLabel,
|
|
29
|
+
options: [],
|
|
30
|
+
};
|
|
31
|
+
const customGroups = {};
|
|
32
|
+
for (const item of items) {
|
|
33
|
+
if (!item) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const rawLabel = getGroupLabel(item);
|
|
37
|
+
const groupLabel = rawLabel === null || rawLabel === void 0 ? void 0 : rawLabel.trim();
|
|
38
|
+
/* Empty string after trim or falsy values go to default group */
|
|
39
|
+
if (!groupLabel) {
|
|
40
|
+
defaultGroup.options.push(item);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (!customGroups[groupLabel]) {
|
|
44
|
+
customGroups[groupLabel] = {
|
|
45
|
+
label: groupLabel,
|
|
46
|
+
options: [],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
customGroups[groupLabel].options.push(item);
|
|
50
|
+
}
|
|
51
|
+
/* Custom groups first, then default group if it has items */
|
|
52
|
+
const groups = [...Object.values(customGroups)];
|
|
53
|
+
if (defaultGroup.options.length > 0) {
|
|
54
|
+
groups.push(defaultGroup);
|
|
55
|
+
}
|
|
56
|
+
return groups;
|
|
57
|
+
}
|
|
58
|
+
export { createGroups };
|
|
59
|
+
//# sourceMappingURL=grouping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grouping.js","sourceRoot":"","sources":["../../../../src/data/token-filter/helpers/grouping.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,SAAS,YAAY,CACnB,KAAU,EACV,aAAqD,EACrD,iBAAiB,GAAG,SAAS;IAE7B,MAAM,YAAY,GAAmB;QACnC,KAAK,EAAE,iBAAiB;QACxB,OAAO,EAAE,EAAE;KACZ,CAAC;IACF,MAAM,YAAY,GAAmC,EAAE,CAAC;IAExD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,UAAU,GAAG,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,EAAE,CAAC;QAEpC,iEAAiE;QACjE,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,SAAS;QACX,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,YAAY,CAAC,UAAU,CAAC,GAAG;gBACzB,KAAK,EAAE,UAAU;gBACjB,OAAO,EAAE,EAAE;aACZ,CAAC;QACJ,CAAC;QAED,YAAY,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IAED,6DAA6D;IAC7D,MAAM,MAAM,GAAqB,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAElE,IAAI,YAAY,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ParsedProperty, QueryFilterOperator } from "../TokenFilter.types.js";
|
|
2
|
+
declare const QUERY_OPERATORS: QueryFilterOperator[];
|
|
3
|
+
/**
|
|
4
|
+
* Match an operator from the input text.
|
|
5
|
+
* Operators are already sorted by specificity, so no re-sorting needed.
|
|
6
|
+
*/
|
|
7
|
+
declare function matchOperator(allowedOperators: QueryFilterOperator[], text: string): QueryFilterOperator | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Match a property from the input text by longest property label.
|
|
10
|
+
*
|
|
11
|
+
* properties: [{ propertyLabel: "Instance" }, { propertyLabel: "Instance ID" }]
|
|
12
|
+
* text = "Instance ID:"
|
|
13
|
+
*
|
|
14
|
+
* Result: { propertyLabel: "Instance ID" }
|
|
15
|
+
*/
|
|
16
|
+
declare function matchFilteringProperty(filteringProperties: ParsedProperty[], text: string): ParsedProperty | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Check if the input text is a valid prefix of any allowed operator.
|
|
19
|
+
* Returns the prefix if valid, null otherwise.
|
|
20
|
+
*/
|
|
21
|
+
declare function matchOperatorPrefix(allowedOperators: QueryFilterOperator[], filteringText: string): string | null;
|
|
22
|
+
export { QUERY_OPERATORS, matchOperator, matchFilteringProperty, matchOperatorPrefix, };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operators ordered by specificity (longest/most specific first)
|
|
3
|
+
* This ensures longer operators like ">=" and "<=" are matched
|
|
4
|
+
* before shorter ones like ">" and "<"
|
|
5
|
+
*/
|
|
6
|
+
const Operators = {
|
|
7
|
+
">=": null,
|
|
8
|
+
"<=": null,
|
|
9
|
+
"!=": null,
|
|
10
|
+
"!:": null,
|
|
11
|
+
"!^": null,
|
|
12
|
+
"=": null,
|
|
13
|
+
":": null,
|
|
14
|
+
"^": null,
|
|
15
|
+
">": null,
|
|
16
|
+
"<": null,
|
|
17
|
+
};
|
|
18
|
+
const QUERY_OPERATORS = Object.keys(Operators);
|
|
19
|
+
/**
|
|
20
|
+
* Match an operator from the input text.
|
|
21
|
+
* Operators are already sorted by specificity, so no re-sorting needed.
|
|
22
|
+
*/
|
|
23
|
+
function matchOperator(allowedOperators, text) {
|
|
24
|
+
return allowedOperators.find((operator) => text.toLowerCase().startsWith(operator.toLowerCase()));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Match a property from the input text by longest property label.
|
|
28
|
+
*
|
|
29
|
+
* properties: [{ propertyLabel: "Instance" }, { propertyLabel: "Instance ID" }]
|
|
30
|
+
* text = "Instance ID:"
|
|
31
|
+
*
|
|
32
|
+
* Result: { propertyLabel: "Instance ID" }
|
|
33
|
+
*/
|
|
34
|
+
function matchFilteringProperty(filteringProperties, text) {
|
|
35
|
+
const lowerText = text.toLowerCase();
|
|
36
|
+
let bestMatch;
|
|
37
|
+
for (const prop of filteringProperties) {
|
|
38
|
+
if (lowerText.startsWith(prop.propertyLabel.toLowerCase())) {
|
|
39
|
+
if (!bestMatch ||
|
|
40
|
+
prop.propertyLabel.length > bestMatch.propertyLabel.length) {
|
|
41
|
+
bestMatch = prop;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return bestMatch;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check if the input text is a valid prefix of any allowed operator.
|
|
49
|
+
* Returns the prefix if valid, null otherwise.
|
|
50
|
+
*/
|
|
51
|
+
function matchOperatorPrefix(allowedOperators, filteringText) {
|
|
52
|
+
const trimmedText = filteringText.trim();
|
|
53
|
+
if (trimmedText.length === 0) {
|
|
54
|
+
return "";
|
|
55
|
+
}
|
|
56
|
+
const isValidPrefix = allowedOperators.some((operator) => operator.toLowerCase().startsWith(trimmedText.toLowerCase()));
|
|
57
|
+
return isValidPrefix ? trimmedText : null;
|
|
58
|
+
}
|
|
59
|
+
export { QUERY_OPERATORS, matchOperator, matchFilteringProperty, matchOperatorPrefix, };
|
|
60
|
+
//# sourceMappingURL=operators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operators.js","sourceRoot":"","sources":["../../../../src/data/token-filter/helpers/operators.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,SAAS,GAAsC;IACnD,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,IAAI;CACV,CAAC;AAEF,MAAM,eAAe,GAA0B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAEtE;;;GAGG;AACH,SAAS,aAAa,CACpB,gBAAuC,EACvC,IAAY;IAEZ,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CACxC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CACtD,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,sBAAsB,CAC7B,mBAAqC,EACrC,IAAY;IAEZ,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,SAAqC,CAAC;IAE1C,KAAK,MAAM,IAAI,IAAI,mBAAmB,EAAE,CAAC;QACvC,IAAI,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAC3D,IACE,CAAC,SAAS;gBACV,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC,MAAM,EAC1D,CAAC;gBACD,SAAS,GAAG,IAAI,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,SAAS,mBAAmB,CAC1B,gBAAuC,EACvC,aAAqB;IAErB,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC;IAEzC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,aAAa,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CACvD,QAAQ,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAC7D,CAAC;IAEF,OAAO,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5C,CAAC;AAED,OAAO,EACL,eAAe,EACf,aAAa,EACb,sBAAsB,EACtB,mBAAmB,GACpB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ParsedProperty, QueryFilterOperator } from "../TokenFilter.types.js";
|
|
2
|
+
type ParsedText = {
|
|
3
|
+
/** User has typed property + complete operator + value (e.g., "Status != active") */
|
|
4
|
+
step: "property";
|
|
5
|
+
property: ParsedProperty;
|
|
6
|
+
operator: QueryFilterOperator;
|
|
7
|
+
value: string;
|
|
8
|
+
} | {
|
|
9
|
+
/** User is typing the operator after property (e.g., "Status !") */
|
|
10
|
+
step: "operator";
|
|
11
|
+
property: ParsedProperty;
|
|
12
|
+
operatorPrefix: string;
|
|
13
|
+
} | {
|
|
14
|
+
/** No property match; treat as free-text search */
|
|
15
|
+
step: "free-text";
|
|
16
|
+
value: string;
|
|
17
|
+
operator?: QueryFilterOperator;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Parse user input text to extract property, operator, and value components.
|
|
21
|
+
* Handles partial input (e.g., user typing "Status !" to complete the operator).
|
|
22
|
+
*/
|
|
23
|
+
declare function parseQueryText(filteringText: string, filteringProperties: ParsedProperty[]): ParsedText;
|
|
24
|
+
export { parseQueryText };
|
|
25
|
+
export type { ParsedText };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { QUERY_OPERATORS, matchFilteringProperty, matchOperator, matchOperatorPrefix, } from "./operators.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parse user input text to extract property, operator, and value components.
|
|
4
|
+
* Handles partial input (e.g., user typing "Status !" to complete the operator).
|
|
5
|
+
*/
|
|
6
|
+
function parseQueryText(filteringText, filteringProperties) {
|
|
7
|
+
const property = matchFilteringProperty(filteringProperties, filteringText);
|
|
8
|
+
if (!property) {
|
|
9
|
+
const freeTextOperator = matchOperator(QUERY_OPERATORS, filteringText);
|
|
10
|
+
if (freeTextOperator) {
|
|
11
|
+
return {
|
|
12
|
+
step: "free-text",
|
|
13
|
+
operator: freeTextOperator,
|
|
14
|
+
value: filteringText.substring(freeTextOperator.length).trimStart(),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
step: "free-text",
|
|
19
|
+
value: filteringText,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const textWithoutProperty = filteringText
|
|
23
|
+
.substring(property.propertyLabel.length)
|
|
24
|
+
.trimStart();
|
|
25
|
+
const operator = matchOperator(QUERY_OPERATORS, textWithoutProperty);
|
|
26
|
+
if (operator) {
|
|
27
|
+
return {
|
|
28
|
+
step: "property",
|
|
29
|
+
property,
|
|
30
|
+
operator,
|
|
31
|
+
value: textWithoutProperty.substring(operator.length).trimStart(),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const operatorPrefix = matchOperatorPrefix(QUERY_OPERATORS, textWithoutProperty);
|
|
35
|
+
if (operatorPrefix !== null) {
|
|
36
|
+
return { step: "operator", property, operatorPrefix };
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
step: "free-text",
|
|
40
|
+
value: filteringText,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export { parseQueryText };
|
|
44
|
+
//# sourceMappingURL=parse-query-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-query-text.js","sourceRoot":"","sources":["../../../../src/data/token-filter/helpers/parse-query-text.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAuBrB;;;GAGG;AACH,SAAS,cAAc,CACrB,aAAqB,EACrB,mBAAqC;IAErC,MAAM,QAAQ,GAAG,sBAAsB,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;IAC5E,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,gBAAgB,GAAG,aAAa,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;QACvE,IAAI,gBAAgB,EAAE,CAAC;YACrB,OAAO;gBACL,IAAI,EAAE,WAAW;gBACjB,QAAQ,EAAE,gBAAgB;gBAC1B,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE;aACpE,CAAC;QACJ,CAAC;QAED,OAAO;YACL,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,aAAa;SACrB,CAAC;IACJ,CAAC;IAED,MAAM,mBAAmB,GAAG,aAAa;SACtC,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC;SACxC,SAAS,EAAE,CAAC;IAEf,MAAM,QAAQ,GAAG,aAAa,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;IAErE,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,QAAQ;YACR,QAAQ;YACR,KAAK,EAAE,mBAAmB,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE;SAClE,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAAG,mBAAmB,CACxC,eAAe,EACf,mBAAmB,CACpB,CAAC;IAEF,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;QAC5B,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;IACxD,CAAC;IAED,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,aAAa;KACrB,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { QueryFilterOperator } from "../TokenFilter.types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Human-readable labels for query filter operators.
|
|
4
|
+
* Used for displaying operator descriptions in autocomplete suggestions.
|
|
5
|
+
* TODO: Support i18n
|
|
6
|
+
*/
|
|
7
|
+
declare const OPERATOR_LABELS: Record<QueryFilterOperator, string>;
|
|
8
|
+
/**
|
|
9
|
+
* Builds a query string from property label, operator, and value.
|
|
10
|
+
* Only includes non-empty parts, joined by spaces.
|
|
11
|
+
* @returns Space-joined query string
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* buildQueryString("Status", "=", "active") // "Status = active"
|
|
15
|
+
* buildQueryString("Status", "=", "") // "Status ="
|
|
16
|
+
* buildQueryString("Status", "", "") // "Status"
|
|
17
|
+
* buildQueryString("", "", "") // ""
|
|
18
|
+
*/
|
|
19
|
+
declare function buildQueryString(propertyLabel: string, operator: string, value: string): string;
|
|
20
|
+
export { buildQueryString, OPERATOR_LABELS };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-readable labels for query filter operators.
|
|
3
|
+
* Used for displaying operator descriptions in autocomplete suggestions.
|
|
4
|
+
* TODO: Support i18n
|
|
5
|
+
*/
|
|
6
|
+
const OPERATOR_LABELS = {
|
|
7
|
+
":": "contains",
|
|
8
|
+
"!:": "does not contain",
|
|
9
|
+
"=": "is",
|
|
10
|
+
"!=": "is not",
|
|
11
|
+
"^": "starts with",
|
|
12
|
+
"!^": "does not start with",
|
|
13
|
+
">=": "is greater than or equal to",
|
|
14
|
+
"<=": "is less than or equal to",
|
|
15
|
+
">": "is greater than",
|
|
16
|
+
"<": "is less than",
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Builds a query string from property label, operator, and value.
|
|
20
|
+
* Only includes non-empty parts, joined by spaces.
|
|
21
|
+
* @returns Space-joined query string
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* buildQueryString("Status", "=", "active") // "Status = active"
|
|
25
|
+
* buildQueryString("Status", "=", "") // "Status ="
|
|
26
|
+
* buildQueryString("Status", "", "") // "Status"
|
|
27
|
+
* buildQueryString("", "", "") // ""
|
|
28
|
+
*/
|
|
29
|
+
function buildQueryString(propertyLabel, operator, value) {
|
|
30
|
+
const parts = [propertyLabel, operator, value].filter(Boolean);
|
|
31
|
+
return parts.join(" ");
|
|
32
|
+
}
|
|
33
|
+
export { buildQueryString, OPERATOR_LABELS };
|
|
34
|
+
//# sourceMappingURL=query-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-builder.js","sourceRoot":"","sources":["../../../../src/data/token-filter/helpers/query-builder.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,eAAe,GAAwC;IAC3D,GAAG,EAAE,UAAU;IACf,IAAI,EAAE,kBAAkB;IACxB,GAAG,EAAE,IAAI;IACT,IAAI,EAAE,QAAQ;IACd,GAAG,EAAE,aAAa;IAClB,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,6BAA6B;IACnC,IAAI,EAAE,0BAA0B;IAChC,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,cAAc;CACpB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,SAAS,gBAAgB,CACvB,aAAqB,EACrB,QAAgB,EAChB,KAAa;IAEb,MAAM,KAAK,GAAG,CAAC,aAAa,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC/D,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if search field values match the given filter text.
|
|
3
|
+
*
|
|
4
|
+
* @param searchFieldValues - Array of strings to search within (e.g., labels, tags, descriptions)
|
|
5
|
+
* @param filterText - The search text to match against
|
|
6
|
+
* @returns true if all space-separated parts of filterText are found in at least one searchFieldValue
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* matchesFilterText(['Hello World', 'foo'], 'hello') // true
|
|
10
|
+
* matchesFilterText(['Hello World', 'foo'], 'hello bar') // false
|
|
11
|
+
* matchesFilterText(['Hello World', 'bar'], 'hello bar') // true
|
|
12
|
+
* matchesFilterText([], 'test') // false
|
|
13
|
+
* matchesFilterText(['test'], '') // true (empty filter matches all)
|
|
14
|
+
*/
|
|
15
|
+
declare function matchesFilterText(searchFieldValues: string[], filterText: string): boolean;
|
|
16
|
+
export { matchesFilterText };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if search field values match the given filter text.
|
|
3
|
+
*
|
|
4
|
+
* @param searchFieldValues - Array of strings to search within (e.g., labels, tags, descriptions)
|
|
5
|
+
* @param filterText - The search text to match against
|
|
6
|
+
* @returns true if all space-separated parts of filterText are found in at least one searchFieldValue
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* matchesFilterText(['Hello World', 'foo'], 'hello') // true
|
|
10
|
+
* matchesFilterText(['Hello World', 'foo'], 'hello bar') // false
|
|
11
|
+
* matchesFilterText(['Hello World', 'bar'], 'hello bar') // true
|
|
12
|
+
* matchesFilterText([], 'test') // false
|
|
13
|
+
* matchesFilterText(['test'], '') // true (empty filter matches all)
|
|
14
|
+
*/
|
|
15
|
+
function matchesFilterText(searchFieldValues, filterText) {
|
|
16
|
+
/* Guard against null/undefined inputs */
|
|
17
|
+
if (!searchFieldValues || !Array.isArray(searchFieldValues)) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
if (filterText === null || filterText === undefined) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
const normalizedFilter = filterText.trim().toLowerCase();
|
|
24
|
+
/* Empty filter matches everything */
|
|
25
|
+
if (!normalizedFilter) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
/* Split filter into parts ("nord land" -> ["nord", "land"]) */
|
|
29
|
+
const parts = normalizedFilter.split(/\s+/).filter(Boolean);
|
|
30
|
+
if (parts.length === 0) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
/* Normalize and filter out nullish values */
|
|
34
|
+
const normalizedFields = searchFieldValues
|
|
35
|
+
.map((value) => value === null || value === void 0 ? void 0 : value.toLowerCase())
|
|
36
|
+
.filter(Boolean);
|
|
37
|
+
/* If no valid fields to search, no match */
|
|
38
|
+
if (normalizedFields.length === 0) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
/* Every part of the filter must be found in at least one field */
|
|
42
|
+
return parts.every((part) => normalizedFields.some((field) => field.includes(part)));
|
|
43
|
+
}
|
|
44
|
+
export { matchesFilterText };
|
|
45
|
+
//# sourceMappingURL=text-matching.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-matching.js","sourceRoot":"","sources":["../../../../src/data/token-filter/helpers/text-matching.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,SAAS,iBAAiB,CACxB,iBAA2B,EAC3B,UAAkB;IAElB,yCAAyC;IACzC,IAAI,CAAC,iBAAiB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC5D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,gBAAgB,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEzD,qCAAqC;IACrC,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,+DAA+D;IAC/D,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAE5D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6CAA6C;IAC7C,MAAM,gBAAgB,GAAG,iBAAiB;SACvC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,WAAW,EAAE,CAAC;SACpC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEnB,4CAA4C;IAC5C,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,kEAAkE;IAClE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAC1B,gBAAgB,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CACvD,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
2
1
|
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
2
|
var t = {};
|
|
4
3
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -10,6 +9,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
9
|
}
|
|
11
10
|
return t;
|
|
12
11
|
};
|
|
12
|
+
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
13
13
|
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
14
14
|
import React, { forwardRef } from "react";
|
|
15
15
|
import { Floating } from "../../../utils/components/floating/Floating.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputController.js","sourceRoot":"","sources":["../../../../src/form/combobox/Input/InputController.tsx"],"names":[],"mappings":"AAAA,0DAA0D
|
|
1
|
+
{"version":3,"file":"InputController.js","sourceRoot":"","sources":["../../../../src/form/combobox/Input/InputController.tsx"],"names":[],"mappings":";;;;;;;;;;;AAAA,0DAA0D;AAC1D,4DAA4D;AAC5D,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,6CAA6C,CAAC;AACvE,OAAO,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,eAAe,MAAM,oCAAoC,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AAEtF,OAAO,KAAK,MAAM,SAAS,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAElD,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAcvC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IACf,MAAM;IACJ,sHAAsH;IACtH,WAAW;IACX,sHAAsH;IACtH,gBAAgB,EAChB,gBAAgB,GAAG,IAAI,EACvB,cAAc,EACd,yBAAyB,GAAG,IAAI,KAG9B,KAAK,EADJ,IAAI,UACL,KAAK,EAVH,sGAUL,CAAQ,CAAC;IAEV,MAAM,EACJ,UAAU,EACV,UAAU,EACV,IAAI,GAAG,QAAQ,EACf,QAAQ,EACR,mBAAmB,EACnB,QAAQ,EACR,YAAY,GACb,GAAG,eAAe,EAAE,CAAC;IAEtB,MAAM,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,GAAG,yBAAyB,EAAE,CAAC;IAC5E,MAAM,EAAE,eAAe,EAAE,GAAG,yBAAyB,EAAE,CAAC;IAExD,MAAM,cAAc,GAAG,YAAY,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAEnD,OAAO,CACL,oBAAC,QAAQ,CAAC,MAAM,IAAC,OAAO,QAAC,GAAG,EAAE,YAAY;QAExC,6BACE,SAAS,EAAE,EAAE,CAAC,uDAAuD,EAAE;gBACrE,oDAAoD,EAClD,iBAAiB,KAAK,SAAS;aAClC,CAAC,EACF,OAAO,EAAE,GAAG,EAAE;gBACZ,IAAI,UAAU,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC;oBACpC,OAAO;gBACT,CAAC;gBAED,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBACvB,UAAU,EAAE,CAAC;YACf,CAAC;YAEA,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAC5B,oBAAC,KAAK,kBACJ,EAAE,EAAE,UAAU,CAAC,EAAE,EACjB,GAAG,EAAE,cAAc,EACnB,cAAc,EAAE,cAAc,EAC9B,QAAQ,EAAE,QAAQ,IACd,IAAI,EACR,CACH,CAAC,CAAC,CAAC,CACF,oBAAC,eAAe,IAAC,eAAe,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI;gBAC3D,oBAAC,KAAK,kBACJ,EAAE,EAAE,UAAU,CAAC,EAAE,EACjB,GAAG,EAAE,cAAc,EACnB,cAAc,EAAE,cAAc,EAC9B,yBAAyB,EAAE,yBAAyB,EACpD,QAAQ,EAAE,QAAQ,IACd,IAAI,EACR,CACc,CACnB;YACA,gBAAgB,IAAI,oBAAC,gBAAgB,IAAC,GAAG,EAAE,mBAAmB,GAAI,CAC/D,CACU,CACnB,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
2
1
|
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
2
|
var t = {};
|
|
4
3
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -10,6 +9,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
9
|
}
|
|
11
10
|
return t;
|
|
12
11
|
};
|
|
12
|
+
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
13
13
|
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
14
14
|
import React, { forwardRef } from "react";
|
|
15
15
|
import { CircleSlashIcon, CloudUpIcon } from "@navikt/aksel-icons";
|