@navikt/ds-react 8.5.2 → 8.7.0

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.
Files changed (258) hide show
  1. package/cjs/data/drag-and-drop/item/DataDragAndDropItem.d.ts +27 -0
  2. package/cjs/data/drag-and-drop/item/DataDragAndDropItem.js +91 -0
  3. package/cjs/data/drag-and-drop/item/DataDragAndDropItem.js.map +1 -0
  4. package/cjs/data/drag-and-drop/root/DataDragAndDrop.context.d.ts +5 -0
  5. package/cjs/data/drag-and-drop/root/DataDragAndDrop.context.js +6 -0
  6. package/cjs/data/drag-and-drop/root/DataDragAndDrop.context.js.map +1 -0
  7. package/cjs/data/drag-and-drop/root/DataDragAndDropRoot.d.ts +24 -0
  8. package/cjs/data/drag-and-drop/root/DataDragAndDropRoot.js +111 -0
  9. package/cjs/data/drag-and-drop/root/DataDragAndDropRoot.js.map +1 -0
  10. package/cjs/data/table/helpers/table-keyboard.d.ts +1 -0
  11. package/cjs/data/table/helpers/table-keyboard.js +5 -3
  12. package/cjs/data/table/helpers/table-keyboard.js.map +1 -1
  13. package/cjs/data/table/root/DataTableRoot.context.d.ts +8 -0
  14. package/cjs/data/table/root/DataTableRoot.context.js +11 -0
  15. package/cjs/data/table/root/DataTableRoot.context.js.map +1 -0
  16. package/cjs/data/table/root/DataTableRoot.js +5 -3
  17. package/cjs/data/table/root/DataTableRoot.js.map +1 -1
  18. package/cjs/data/table/th/DataTableTh.d.ts +18 -2
  19. package/cjs/data/table/th/DataTableTh.js +45 -20
  20. package/cjs/data/table/th/DataTableTh.js.map +1 -1
  21. package/cjs/data/table/tr/DataTableTr.js +9 -2
  22. package/cjs/data/table/tr/DataTableTr.js.map +1 -1
  23. package/cjs/data/token-filter/AutoSuggest.d.ts +6 -2
  24. package/cjs/data/token-filter/AutoSuggest.js +46 -14
  25. package/cjs/data/token-filter/AutoSuggest.js.map +1 -1
  26. package/cjs/data/token-filter/AutoSuggest.types.d.ts +0 -1
  27. package/cjs/data/token-filter/TokenFilter.d.ts +10 -5
  28. package/cjs/data/token-filter/TokenFilter.js +110 -48
  29. package/cjs/data/token-filter/TokenFilter.js.map +1 -1
  30. package/cjs/data/token-filter/TokenFilter.types.d.ts +51 -35
  31. package/cjs/data/token-filter/helpers/generate-autocomplete-options.d.ts +3 -6
  32. package/cjs/data/token-filter/helpers/generate-autocomplete-options.js +24 -37
  33. package/cjs/data/token-filter/helpers/generate-autocomplete-options.js.map +1 -1
  34. package/cjs/data/token-filter/helpers/operators.d.ts +6 -6
  35. package/cjs/data/token-filter/helpers/operators.js +3 -4
  36. package/cjs/data/token-filter/helpers/operators.js.map +1 -1
  37. package/cjs/data/token-filter/helpers/parse-query-text.d.ts +2 -20
  38. package/cjs/data/token-filter/helpers/parse-query-text.js +1 -1
  39. package/cjs/data/token-filter/helpers/parse-query-text.js.map +1 -1
  40. package/cjs/data/token-filter/helpers/query-builder.d.ts +2 -2
  41. package/cjs/data/token-filter/helpers/query-builder.js.map +1 -1
  42. package/cjs/date/Date.Dialog.d.ts +5 -1
  43. package/cjs/date/Date.Dialog.js +6 -2
  44. package/cjs/date/Date.Dialog.js.map +1 -1
  45. package/cjs/date/datepicker/DatePicker.js +3 -2
  46. package/cjs/date/datepicker/DatePicker.js.map +1 -1
  47. package/cjs/date/datepicker/hooks/useDatepicker.js +5 -2
  48. package/cjs/date/datepicker/hooks/useDatepicker.js.map +1 -1
  49. package/cjs/date/datepicker/hooks/useRangeDatepicker.js +3 -1
  50. package/cjs/date/datepicker/hooks/useRangeDatepicker.js.map +1 -1
  51. package/cjs/date/datepicker/parts/DatePicker.Months.d.ts +2 -1
  52. package/cjs/date/datepicker/parts/DatePicker.Months.js +3 -3
  53. package/cjs/date/datepicker/parts/DatePicker.Months.js.map +1 -1
  54. package/cjs/date/datepicker/parts/DatePicker.RDP.d.ts +5 -1
  55. package/cjs/date/datepicker/parts/DatePicker.RDP.js +2 -2
  56. package/cjs/date/datepicker/parts/DatePicker.RDP.js.map +1 -1
  57. package/cjs/date/monthpicker/MonthPicker.js +3 -2
  58. package/cjs/date/monthpicker/MonthPicker.js.map +1 -1
  59. package/cjs/date/monthpicker/hooks/useMonthPicker.js +3 -1
  60. package/cjs/date/monthpicker/hooks/useMonthPicker.js.map +1 -1
  61. package/cjs/date/monthpicker/parts/MonthPicker.Caption.d.ts +4 -1
  62. package/cjs/date/monthpicker/parts/MonthPicker.Caption.js +3 -2
  63. package/cjs/date/monthpicker/parts/MonthPicker.Caption.js.map +1 -1
  64. package/cjs/dropdown/Toggle.js +5 -12
  65. package/cjs/dropdown/Toggle.js.map +1 -1
  66. package/cjs/form/combobox/Input/Input.js +1 -1
  67. package/cjs/form/combobox/Input/Input.js.map +1 -1
  68. package/cjs/inline-message/root/InlineMessage.js +2 -2
  69. package/cjs/inline-message/root/InlineMessage.js.map +1 -1
  70. package/cjs/provider/Provider.d.ts +2 -2
  71. package/cjs/toggle-group/useToggleGroup.js +5 -3
  72. package/cjs/toggle-group/useToggleGroup.js.map +1 -1
  73. package/cjs/tooltip/Tooltip.js +1 -3
  74. package/cjs/tooltip/Tooltip.js.map +1 -1
  75. package/cjs/utils/components/HighlightText/HighlightText.d.ts +8 -0
  76. package/cjs/utils/components/HighlightText/HighlightText.js +27 -0
  77. package/cjs/utils/components/HighlightText/HighlightText.js.map +1 -0
  78. package/cjs/utils/components/Listbox/group/ListboxGroup.d.ts +7 -0
  79. package/cjs/utils/components/Listbox/group/ListboxGroup.js +15 -0
  80. package/cjs/utils/components/Listbox/group/ListboxGroup.js.map +1 -0
  81. package/cjs/utils/components/Listbox/input-slot/ListboxInputSlot.d.ts +7 -0
  82. package/cjs/utils/components/Listbox/input-slot/ListboxInputSlot.js +15 -0
  83. package/cjs/utils/components/Listbox/input-slot/ListboxInputSlot.js.map +1 -0
  84. package/cjs/utils/components/Listbox/item/ListboxItem.d.ts +24 -0
  85. package/cjs/utils/components/Listbox/item/ListboxItem.js +33 -0
  86. package/cjs/utils/components/Listbox/item/ListboxItem.js.map +1 -0
  87. package/cjs/utils/components/Listbox/list/ListboxList.d.ts +8 -0
  88. package/cjs/utils/components/Listbox/list/ListboxList.js +32 -0
  89. package/cjs/utils/components/Listbox/list/ListboxList.js.map +1 -0
  90. package/cjs/utils/components/Listbox/root/ListboxRoot.d.ts +20 -0
  91. package/cjs/utils/components/Listbox/root/ListboxRoot.js +84 -0
  92. package/cjs/utils/components/Listbox/root/ListboxRoot.js.map +1 -0
  93. package/cjs/utils/components/Listbox/root/domHelpers.d.ts +3 -0
  94. package/cjs/utils/components/Listbox/root/domHelpers.js +53 -0
  95. package/cjs/utils/components/Listbox/root/domHelpers.js.map +1 -0
  96. package/cjs/utils/components/focus-boundary/FocusBoundary.js +9 -64
  97. package/cjs/utils/components/focus-boundary/FocusBoundary.js.map +1 -1
  98. package/cjs/utils/helpers/focus.d.ts +14 -0
  99. package/cjs/utils/helpers/focus.js +63 -0
  100. package/cjs/utils/helpers/focus.js.map +1 -0
  101. package/cjs/utils/hooks/useDeferredValue.d.ts +1 -0
  102. package/cjs/utils/hooks/useDeferredValue.js +14 -0
  103. package/cjs/utils/hooks/useDeferredValue.js.map +1 -0
  104. package/esm/data/drag-and-drop/item/DataDragAndDropItem.d.ts +27 -0
  105. package/esm/data/drag-and-drop/item/DataDragAndDropItem.js +55 -0
  106. package/esm/data/drag-and-drop/item/DataDragAndDropItem.js.map +1 -0
  107. package/esm/data/drag-and-drop/root/DataDragAndDrop.context.d.ts +5 -0
  108. package/esm/data/drag-and-drop/root/DataDragAndDrop.context.js +3 -0
  109. package/esm/data/drag-and-drop/root/DataDragAndDrop.context.js.map +1 -0
  110. package/esm/data/drag-and-drop/root/DataDragAndDropRoot.d.ts +24 -0
  111. package/esm/data/drag-and-drop/root/DataDragAndDropRoot.js +71 -0
  112. package/esm/data/drag-and-drop/root/DataDragAndDropRoot.js.map +1 -0
  113. package/esm/data/table/helpers/table-keyboard.d.ts +1 -0
  114. package/esm/data/table/helpers/table-keyboard.js +5 -3
  115. package/esm/data/table/helpers/table-keyboard.js.map +1 -1
  116. package/esm/data/table/root/DataTableRoot.context.d.ts +8 -0
  117. package/esm/data/table/root/DataTableRoot.context.js +7 -0
  118. package/esm/data/table/root/DataTableRoot.context.js.map +1 -0
  119. package/esm/data/table/root/DataTableRoot.js +5 -3
  120. package/esm/data/table/root/DataTableRoot.js.map +1 -1
  121. package/esm/data/table/th/DataTableTh.d.ts +18 -2
  122. package/esm/data/table/th/DataTableTh.js +46 -21
  123. package/esm/data/table/th/DataTableTh.js.map +1 -1
  124. package/esm/data/table/tr/DataTableTr.js +9 -2
  125. package/esm/data/table/tr/DataTableTr.js.map +1 -1
  126. package/esm/data/token-filter/AutoSuggest.d.ts +6 -2
  127. package/esm/data/token-filter/AutoSuggest.js +45 -16
  128. package/esm/data/token-filter/AutoSuggest.js.map +1 -1
  129. package/esm/data/token-filter/AutoSuggest.types.d.ts +0 -1
  130. package/esm/data/token-filter/TokenFilter.d.ts +10 -5
  131. package/esm/data/token-filter/TokenFilter.js +110 -48
  132. package/esm/data/token-filter/TokenFilter.js.map +1 -1
  133. package/esm/data/token-filter/TokenFilter.types.d.ts +51 -35
  134. package/esm/data/token-filter/helpers/generate-autocomplete-options.d.ts +3 -6
  135. package/esm/data/token-filter/helpers/generate-autocomplete-options.js +24 -37
  136. package/esm/data/token-filter/helpers/generate-autocomplete-options.js.map +1 -1
  137. package/esm/data/token-filter/helpers/operators.d.ts +6 -6
  138. package/esm/data/token-filter/helpers/operators.js +3 -4
  139. package/esm/data/token-filter/helpers/operators.js.map +1 -1
  140. package/esm/data/token-filter/helpers/parse-query-text.d.ts +2 -20
  141. package/esm/data/token-filter/helpers/parse-query-text.js +1 -1
  142. package/esm/data/token-filter/helpers/parse-query-text.js.map +1 -1
  143. package/esm/data/token-filter/helpers/query-builder.d.ts +2 -2
  144. package/esm/data/token-filter/helpers/query-builder.js.map +1 -1
  145. package/esm/date/Date.Dialog.d.ts +5 -1
  146. package/esm/date/Date.Dialog.js +6 -2
  147. package/esm/date/Date.Dialog.js.map +1 -1
  148. package/esm/date/datepicker/DatePicker.js +3 -2
  149. package/esm/date/datepicker/DatePicker.js.map +1 -1
  150. package/esm/date/datepicker/hooks/useDatepicker.js +5 -2
  151. package/esm/date/datepicker/hooks/useDatepicker.js.map +1 -1
  152. package/esm/date/datepicker/hooks/useRangeDatepicker.js +3 -1
  153. package/esm/date/datepicker/hooks/useRangeDatepicker.js.map +1 -1
  154. package/esm/date/datepicker/parts/DatePicker.Months.d.ts +2 -1
  155. package/esm/date/datepicker/parts/DatePicker.Months.js +3 -3
  156. package/esm/date/datepicker/parts/DatePicker.Months.js.map +1 -1
  157. package/esm/date/datepicker/parts/DatePicker.RDP.d.ts +5 -1
  158. package/esm/date/datepicker/parts/DatePicker.RDP.js +2 -2
  159. package/esm/date/datepicker/parts/DatePicker.RDP.js.map +1 -1
  160. package/esm/date/monthpicker/MonthPicker.js +3 -2
  161. package/esm/date/monthpicker/MonthPicker.js.map +1 -1
  162. package/esm/date/monthpicker/hooks/useMonthPicker.js +3 -1
  163. package/esm/date/monthpicker/hooks/useMonthPicker.js.map +1 -1
  164. package/esm/date/monthpicker/parts/MonthPicker.Caption.d.ts +4 -1
  165. package/esm/date/monthpicker/parts/MonthPicker.Caption.js +3 -2
  166. package/esm/date/monthpicker/parts/MonthPicker.Caption.js.map +1 -1
  167. package/esm/dropdown/Toggle.js +5 -12
  168. package/esm/dropdown/Toggle.js.map +1 -1
  169. package/esm/form/combobox/Input/Input.js +1 -1
  170. package/esm/form/combobox/Input/Input.js.map +1 -1
  171. package/esm/inline-message/root/InlineMessage.js +3 -3
  172. package/esm/inline-message/root/InlineMessage.js.map +1 -1
  173. package/esm/provider/Provider.d.ts +2 -2
  174. package/esm/toggle-group/useToggleGroup.js +6 -4
  175. package/esm/toggle-group/useToggleGroup.js.map +1 -1
  176. package/esm/tooltip/Tooltip.js +1 -3
  177. package/esm/tooltip/Tooltip.js.map +1 -1
  178. package/esm/utils/components/HighlightText/HighlightText.d.ts +8 -0
  179. package/esm/utils/components/HighlightText/HighlightText.js +21 -0
  180. package/esm/utils/components/HighlightText/HighlightText.js.map +1 -0
  181. package/esm/utils/components/Listbox/group/ListboxGroup.d.ts +7 -0
  182. package/esm/utils/components/Listbox/group/ListboxGroup.js +10 -0
  183. package/esm/utils/components/Listbox/group/ListboxGroup.js.map +1 -0
  184. package/esm/utils/components/Listbox/input-slot/ListboxInputSlot.d.ts +7 -0
  185. package/esm/utils/components/Listbox/input-slot/ListboxInputSlot.js +9 -0
  186. package/esm/utils/components/Listbox/input-slot/ListboxInputSlot.js.map +1 -0
  187. package/esm/utils/components/Listbox/item/ListboxItem.d.ts +24 -0
  188. package/esm/utils/components/Listbox/item/ListboxItem.js +27 -0
  189. package/esm/utils/components/Listbox/item/ListboxItem.js.map +1 -0
  190. package/esm/utils/components/Listbox/list/ListboxList.d.ts +8 -0
  191. package/esm/utils/components/Listbox/list/ListboxList.js +27 -0
  192. package/esm/utils/components/Listbox/list/ListboxList.js.map +1 -0
  193. package/esm/utils/components/Listbox/root/ListboxRoot.d.ts +20 -0
  194. package/esm/utils/components/Listbox/root/ListboxRoot.js +79 -0
  195. package/esm/utils/components/Listbox/root/ListboxRoot.js.map +1 -0
  196. package/esm/utils/components/Listbox/root/domHelpers.d.ts +3 -0
  197. package/esm/utils/components/Listbox/root/domHelpers.js +50 -0
  198. package/esm/utils/components/Listbox/root/domHelpers.js.map +1 -0
  199. package/esm/utils/components/focus-boundary/FocusBoundary.js +8 -63
  200. package/esm/utils/components/focus-boundary/FocusBoundary.js.map +1 -1
  201. package/esm/utils/helpers/focus.d.ts +14 -0
  202. package/esm/utils/helpers/focus.js +60 -0
  203. package/esm/utils/helpers/focus.js.map +1 -0
  204. package/esm/utils/hooks/useDeferredValue.d.ts +1 -0
  205. package/esm/utils/hooks/useDeferredValue.js +7 -0
  206. package/esm/utils/hooks/useDeferredValue.js.map +1 -0
  207. package/package.json +7 -7
  208. package/src/data/drag-and-drop/item/DataDragAndDropItem.tsx +101 -0
  209. package/src/data/drag-and-drop/root/DataDragAndDrop.context.tsx +9 -0
  210. package/src/data/drag-and-drop/root/DataDragAndDropRoot.tsx +98 -0
  211. package/src/data/table/helpers/table-keyboard.ts +7 -3
  212. package/src/data/table/root/DataTableRoot.context.ts +13 -0
  213. package/src/data/table/root/DataTableRoot.tsx +16 -13
  214. package/src/data/table/th/DataTableTh.tsx +110 -54
  215. package/src/data/table/tr/DataTableTr.tsx +13 -2
  216. package/src/data/token-filter/AutoSuggest.tsx +142 -35
  217. package/src/data/token-filter/AutoSuggest.types.ts +0 -1
  218. package/src/data/token-filter/TokenFilter.tsx +179 -81
  219. package/src/data/token-filter/TokenFilter.types.ts +70 -44
  220. package/src/data/token-filter/helpers/generate-autocomplete-options.test.ts +97 -157
  221. package/src/data/token-filter/helpers/generate-autocomplete-options.ts +56 -53
  222. package/src/data/token-filter/helpers/operators.test.ts +29 -29
  223. package/src/data/token-filter/helpers/operators.ts +16 -16
  224. package/src/data/token-filter/helpers/parse-query-text.test.ts +37 -35
  225. package/src/data/token-filter/helpers/parse-query-text.ts +7 -26
  226. package/src/data/token-filter/helpers/query-builder.ts +2 -2
  227. package/src/date/Date.Dialog.tsx +15 -0
  228. package/src/date/datepicker/DatePicker.tsx +3 -0
  229. package/src/date/datepicker/hooks/useDatepicker.tsx +7 -2
  230. package/src/date/datepicker/hooks/useRangeDatepicker.tsx +5 -1
  231. package/src/date/datepicker/parts/DatePicker.Months.tsx +9 -1
  232. package/src/date/datepicker/parts/DatePicker.RDP.tsx +7 -1
  233. package/src/date/monthpicker/MonthPicker.tsx +3 -1
  234. package/src/date/monthpicker/hooks/useMonthPicker.tsx +5 -1
  235. package/src/date/monthpicker/parts/MonthPicker.Caption.tsx +20 -2
  236. package/src/dropdown/Toggle.tsx +6 -12
  237. package/src/form/combobox/Input/Input.tsx +2 -2
  238. package/src/inline-message/root/InlineMessage.tsx +5 -5
  239. package/src/provider/Provider.tsx +2 -2
  240. package/src/toggle-group/useToggleGroup.ts +6 -5
  241. package/src/tooltip/Tooltip.tsx +1 -3
  242. package/src/utils/components/HighlightText/HighlightText.tsx +34 -0
  243. package/src/utils/components/Listbox/group/ListboxGroup.tsx +26 -0
  244. package/src/utils/components/Listbox/input-slot/ListboxInputSlot.tsx +22 -0
  245. package/src/utils/components/Listbox/item/ListboxItem.tsx +57 -0
  246. package/src/utils/components/Listbox/list/ListboxList.tsx +38 -0
  247. package/src/utils/components/Listbox/root/ListboxRoot.tsx +104 -0
  248. package/src/utils/components/Listbox/root/domHelpers.ts +59 -0
  249. package/src/utils/components/focus-boundary/FocusBoundary.tsx +8 -78
  250. package/src/utils/helpers/focus.ts +75 -0
  251. package/src/utils/hooks/useDeferredValue.ts +12 -0
  252. package/cjs/data/table/th/DataTableThSortHandle.d.ts +0 -6
  253. package/cjs/data/table/th/DataTableThSortHandle.js +0 -82
  254. package/cjs/data/table/th/DataTableThSortHandle.js.map +0 -1
  255. package/esm/data/table/th/DataTableThSortHandle.d.ts +0 -6
  256. package/esm/data/table/th/DataTableThSortHandle.js +0 -47
  257. package/esm/data/table/th/DataTableThSortHandle.js.map +0 -1
  258. package/src/data/table/th/DataTableThSortHandle.tsx +0 -67
@@ -1,12 +1,12 @@
1
1
  import type { AutoCompleteOption, OptionGroup } from "../AutoSuggest.types";
2
2
  import type {
3
- ParsedOption,
4
- ParsedProperty,
5
- QueryFilterOperator,
3
+ InternalParsedTextState,
4
+ InternalPropertyDefinition,
5
+ InternalPropertyOption,
6
+ OperatorT,
6
7
  } from "../TokenFilter.types";
7
8
  import { createGroups } from "./grouping";
8
9
  import { QUERY_OPERATORS } from "./operators";
9
- import { type ParsedText } from "./parse-query-text";
10
10
  import { OPERATOR_LABELS, buildQueryString } from "./query-builder";
11
11
  import { matchesFilterText } from "./text-matching";
12
12
 
@@ -23,11 +23,16 @@ import { matchesFilterText } from "./text-matching";
23
23
  * Used by the UI to determine cursor position and input replacement.
24
24
  * - options: Grouped suggestions to display (properties, operators, or values).
25
25
  */
26
+ type AutoCompleteResult = {
27
+ value: string;
28
+ options: OptionGroup<AutoCompleteOption>[];
29
+ };
30
+
26
31
  function generateAutoCompleteOptions(
27
- queryState: ParsedText,
28
- filteringProperties: ParsedProperty[] = [],
29
- filteringOptions: ParsedOption[] = [],
30
- ) {
32
+ queryState: InternalParsedTextState,
33
+ filteringProperties: InternalPropertyDefinition[] = [],
34
+ filteringOptions: InternalPropertyOption[] = [],
35
+ ): AutoCompleteResult {
31
36
  /* State: Property and operator are matched, suggest values */
32
37
  if (queryState.step === "property") {
33
38
  const filterText = queryState.value || "";
@@ -51,7 +56,7 @@ function generateAutoCompleteOptions(
51
56
  );
52
57
 
53
58
  const partialQuery = buildQueryString(
54
- queryState.property.propertyLabel,
59
+ queryState.property.label,
55
60
  queryState.operatorPrefix,
56
61
  "",
57
62
  );
@@ -60,9 +65,6 @@ function generateAutoCompleteOptions(
60
65
  * Edge case: User typed an invalid operator prefix that doesn't match any operators.
61
66
  * This can happen when typing characters that don't start any valid operator.
62
67
  * Return empty suggestions gracefully - the UI will show "no results".
63
- *
64
- * TODO: When per-property operator configuration is implemented,
65
- * this could also occur when a property restricts which operators are valid.
66
68
  */
67
69
  if (operators.length === 0) {
68
70
  return {
@@ -105,11 +107,14 @@ function generateAutoCompleteOptions(
105
107
  */
106
108
  return {
107
109
  value: queryState.value,
108
- options: createValueSuggestions(
109
- filteringOptions,
110
- queryState.operator ?? "=",
111
- queryState.value,
112
- ),
110
+ options: [
111
+ ...generatePropertySuggestions(filteringProperties, queryState.value),
112
+ ...createValueSuggestions(
113
+ filteringOptions,
114
+ queryState.operator ?? "=",
115
+ queryState.value,
116
+ ),
117
+ ],
113
118
  };
114
119
  }
115
120
 
@@ -127,8 +132,8 @@ function generateAutoCompleteOptions(
127
132
  * 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.
128
133
  */
129
134
  function getValidOperatorsForProperty(
130
- property: ParsedProperty,
131
- ): QueryFilterOperator[] {
135
+ property: InternalPropertyDefinition,
136
+ ): OperatorT[] {
132
137
  const { operators } = property;
133
138
 
134
139
  /* If no operators configured, return all available operators */
@@ -146,8 +151,8 @@ function getValidOperatorsForProperty(
146
151
 
147
152
  /* Filter to only valid QUERY_OPERATORS to ensure type safety */
148
153
  return operatorStrings.filter((op) =>
149
- QUERY_OPERATORS.includes(op as QueryFilterOperator),
150
- ) as QueryFilterOperator[];
154
+ QUERY_OPERATORS.includes(op as OperatorT),
155
+ ) as OperatorT[];
151
156
  }
152
157
 
153
158
  /**
@@ -155,9 +160,9 @@ function getValidOperatorsForProperty(
155
160
  * If the prefix is empty, all operators are returned.
156
161
  */
157
162
  function filterOperatorsByPrefix(
158
- operators: QueryFilterOperator[],
163
+ operators: OperatorT[],
159
164
  prefix: string,
160
- ): QueryFilterOperator[] {
165
+ ): OperatorT[] {
161
166
  if (!prefix) {
162
167
  return operators;
163
168
  }
@@ -166,10 +171,10 @@ function filterOperatorsByPrefix(
166
171
  }
167
172
 
168
173
  function generatePropertySuggestions(
169
- filteringProperties: ParsedProperty[] = [],
174
+ filteringProperties: InternalPropertyDefinition[] = [],
170
175
  filterText = "",
171
- ): OptionGroup<ParsedProperty>[] {
172
- const filteredProperties: ParsedProperty[] = [];
176
+ ): OptionGroup<AutoCompleteOption>[] {
177
+ const filteredProperties: InternalPropertyDefinition[] = [];
173
178
 
174
179
  for (const property of filteringProperties) {
175
180
  if (!property) {
@@ -178,11 +183,7 @@ function generatePropertySuggestions(
178
183
 
179
184
  if (
180
185
  matchesFilterText(
181
- [
182
- property.propertyLabel,
183
- property.groupValuesLabel,
184
- property.propertyGroup,
185
- ].filter(Boolean),
186
+ [property.label, property.groupLabel, property.group].filter(Boolean),
186
187
  filterText,
187
188
  )
188
189
  ) {
@@ -190,15 +191,23 @@ function generatePropertySuggestions(
190
191
  }
191
192
  }
192
193
 
193
- return createGroups(
194
+ const groups = createGroups(
194
195
  filteredProperties,
195
- (property) => property.propertyGroup,
196
+ (property) => property.group,
196
197
  "Properties",
197
198
  );
199
+
200
+ return groups.map((group) => ({
201
+ label: group.label,
202
+ options: group.options.map((property) => ({
203
+ value: buildQueryString(property.label, "", ""),
204
+ label: property.label,
205
+ })),
206
+ }));
198
207
  }
199
208
 
200
209
  function generateOperatorSuggestions(
201
- property: ParsedProperty,
210
+ property: InternalPropertyDefinition,
202
211
  operatorPrefix = "",
203
212
  ): OptionGroup<AutoCompleteOption>[] {
204
213
  const operators = filterOperatorsByPrefix(
@@ -214,8 +223,8 @@ function generateOperatorSuggestions(
214
223
  {
215
224
  label: "Operators",
216
225
  options: operators.map((operator) => ({
217
- value: buildQueryString(property.propertyLabel, operator, ""),
218
- label: buildQueryString(property.propertyLabel, operator, ""),
226
+ value: buildQueryString(property.label, operator, ""),
227
+ label: buildQueryString(property.label, operator, ""),
219
228
  description: OPERATOR_LABELS[operator] ?? "",
220
229
  })),
221
230
  },
@@ -226,12 +235,15 @@ function generateOperatorSuggestions(
226
235
  * Creates value suggestions for autocomplete.
227
236
  * When scopedProperty is provided, only shows values for that property (single group).
228
237
  * When scopedProperty is omitted, searches across all properties (multiple groups).
238
+ * TODO: This could potentially contain an unlimited number of options if there are many values across properties.
239
+ * May need virtualization/async or other filtering mechanism.
229
240
  */
241
+
230
242
  function createValueSuggestions(
231
- filteringOptions: ParsedOption[] = [],
232
- operator: QueryFilterOperator,
243
+ filteringOptions: InternalPropertyOption[] = [],
244
+ operator: OperatorT,
233
245
  filterText = "",
234
- scopedProperty?: ParsedProperty,
246
+ scopedProperty?: InternalPropertyDefinition,
235
247
  ): OptionGroup<AutoCompleteOption>[] {
236
248
  const groups: Record<string, OptionGroup<AutoCompleteOption>> = {};
237
249
 
@@ -246,14 +258,10 @@ function createValueSuggestions(
246
258
  }
247
259
 
248
260
  /* Build search fields */
249
- const searchFields = [
250
- option.label,
251
- ...(option.tags ?? []),
252
- ...(option.filteringTags ?? []),
253
- ];
261
+ const searchFields = [option.label, ...(option.tags ?? [])];
254
262
 
255
263
  if (!scopedProperty) {
256
- searchFields.push(option.property.propertyLabel);
264
+ searchFields.push(option.property.label);
257
265
  }
258
266
 
259
267
  const matches = matchesFilterText(searchFields.filter(Boolean), filterText);
@@ -262,7 +270,7 @@ function createValueSuggestions(
262
270
  continue;
263
271
  }
264
272
 
265
- const groupLabel = option.property.groupValuesLabel || "Values";
273
+ const groupLabel = option.property.groupLabel || "Values";
266
274
 
267
275
  if (!groups[groupLabel]) {
268
276
  groups[groupLabel] = {
@@ -272,14 +280,9 @@ function createValueSuggestions(
272
280
  }
273
281
 
274
282
  groups[groupLabel].options.push({
275
- value: buildQueryString(
276
- option.property.propertyLabel,
277
- operator,
278
- option.value,
279
- ),
280
- label: option.label,
283
+ value: buildQueryString(option.property.label, operator, option.value),
284
+ label: buildQueryString(option.property.label, operator, option.value),
281
285
  tags: option.tags,
282
- filteringTags: option.filteringTags,
283
286
  });
284
287
  }
285
288
 
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, test } from "vitest";
2
- import type { ParsedProperty } from "../TokenFilter.types";
2
+ import type { InternalPropertyDefinition } from "../TokenFilter.types";
3
3
  import {
4
4
  QUERY_OPERATORS,
5
5
  matchFilteringProperty,
@@ -109,44 +109,44 @@ describe("matchOperator", () => {
109
109
  });
110
110
 
111
111
  describe("matchFilteringProperty", () => {
112
- const properties: ParsedProperty[] = [
112
+ const properties: InternalPropertyDefinition[] = [
113
113
  {
114
- propertyKey: "status",
115
- propertyLabel: "Status",
116
- groupValuesLabel: "",
117
- propertyGroup: "testgroup",
114
+ key: "status",
115
+ label: "Status",
116
+ groupLabel: "",
117
+ group: "testgroup",
118
118
  externalProperty: {} as any,
119
119
  operators: [],
120
120
  },
121
121
  {
122
- propertyKey: "hostname",
123
- propertyLabel: "Hostname",
124
- groupValuesLabel: "",
125
- propertyGroup: "testgroup",
122
+ key: "hostname",
123
+ label: "Hostname",
124
+ groupLabel: "",
125
+ group: "testgroup",
126
126
  externalProperty: {} as any,
127
127
  operators: [],
128
128
  },
129
129
  {
130
- propertyKey: "instance-id",
131
- propertyLabel: "Instance ID",
132
- groupValuesLabel: "",
133
- propertyGroup: "testgroup",
130
+ key: "instance-id",
131
+ label: "Instance ID",
132
+ groupLabel: "",
133
+ group: "testgroup",
134
134
  externalProperty: {} as any,
135
135
  operators: [],
136
136
  },
137
137
  {
138
- propertyKey: "region",
139
- propertyLabel: "Region",
140
- groupValuesLabel: "",
141
- propertyGroup: "testgroup",
138
+ key: "region",
139
+ label: "Region",
140
+ groupLabel: "",
141
+ group: "testgroup",
142
142
  externalProperty: {} as any,
143
143
  operators: [],
144
144
  },
145
145
  {
146
- propertyKey: "availability-zone",
147
- propertyLabel: "Availability Zone",
148
- groupValuesLabel: "",
149
- propertyGroup: "testgroup",
146
+ key: "availability-zone",
147
+ label: "Availability Zone",
148
+ groupLabel: "",
149
+ group: "testgroup",
150
150
  externalProperty: {} as any,
151
151
  operators: [],
152
152
  },
@@ -154,27 +154,27 @@ describe("matchFilteringProperty", () => {
154
154
 
155
155
  test("should match a basic property", () => {
156
156
  const result = matchFilteringProperty(properties, "Status");
157
- expect(result?.propertyKey).toBe("status");
157
+ expect(result?.key).toBe("status");
158
158
  });
159
159
 
160
160
  test("should match property case-insensitively", () => {
161
161
  const result = matchFilteringProperty(properties, "status");
162
- expect(result?.propertyKey).toBe("status");
162
+ expect(result?.key).toBe("status");
163
163
  });
164
164
 
165
165
  test("should match property with mixed casing", () => {
166
166
  const result = matchFilteringProperty(properties, "sTaTuS");
167
- expect(result?.propertyKey).toBe("status");
167
+ expect(result?.key).toBe("status");
168
168
  });
169
169
 
170
170
  test("should use longest matching property when properties overlap", () => {
171
171
  const result = matchFilteringProperty(properties, "Instance ID");
172
- expect(result?.propertyKey).toBe("instance-id");
172
+ expect(result?.key).toBe("instance-id");
173
173
  });
174
174
 
175
175
  test("should prefer longest property: Availability Zone vs Zone", () => {
176
176
  const result = matchFilteringProperty(properties, "Availability Zone");
177
- expect(result?.propertyKey).toBe("availability-zone");
177
+ expect(result?.key).toBe("availability-zone");
178
178
  });
179
179
 
180
180
  test("should return undefined when no property matches", () => {
@@ -189,12 +189,12 @@ describe("matchFilteringProperty", () => {
189
189
 
190
190
  test("should match property from partial input", () => {
191
191
  const result = matchFilteringProperty(properties, "Status=value");
192
- expect(result?.propertyKey).toBe("status");
192
+ expect(result?.key).toBe("status");
193
193
  });
194
194
 
195
195
  test("should match property with spaces in label", () => {
196
196
  const result = matchFilteringProperty(properties, "Instance ID:value");
197
- expect(result?.propertyKey).toBe("instance-id");
197
+ expect(result?.key).toBe("instance-id");
198
198
  });
199
199
  });
200
200
 
@@ -1,11 +1,14 @@
1
- import type { ParsedProperty, QueryFilterOperator } from "../TokenFilter.types";
1
+ import type {
2
+ InternalPropertyDefinition,
3
+ OperatorT,
4
+ } from "../TokenFilter.types";
2
5
 
3
6
  /**
4
7
  * Operators ordered by specificity (longest/most specific first)
5
8
  * This ensures longer operators like ">=" and "<=" are matched
6
9
  * before shorter ones like ">" and "<"
7
10
  */
8
- const Operators: Record<QueryFilterOperator, null> = {
11
+ const Operators: Record<OperatorT, null> = {
9
12
  ">=": null,
10
13
  "<=": null,
11
14
  "!=": null,
@@ -18,16 +21,16 @@ const Operators: Record<QueryFilterOperator, null> = {
18
21
  "<": null,
19
22
  };
20
23
 
21
- const QUERY_OPERATORS: QueryFilterOperator[] = Object.keys(Operators);
24
+ const QUERY_OPERATORS: OperatorT[] = Object.keys(Operators);
22
25
 
23
26
  /**
24
27
  * Match an operator from the input text.
25
28
  * Operators are already sorted by specificity, so no re-sorting needed.
26
29
  */
27
30
  function matchOperator(
28
- allowedOperators: QueryFilterOperator[],
31
+ allowedOperators: OperatorT[],
29
32
  text: string,
30
- ): QueryFilterOperator | undefined {
33
+ ): OperatorT | undefined {
31
34
  return allowedOperators.find((operator) =>
32
35
  text.toLowerCase().startsWith(operator.toLowerCase()),
33
36
  );
@@ -42,18 +45,15 @@ function matchOperator(
42
45
  * Result: { propertyLabel: "Instance ID" }
43
46
  */
44
47
  function matchFilteringProperty(
45
- filteringProperties: ParsedProperty[],
48
+ filteringProperties: InternalPropertyDefinition[],
46
49
  text: string,
47
- ): ParsedProperty | undefined {
50
+ ): InternalPropertyDefinition | undefined {
48
51
  const lowerText = text.toLowerCase();
49
- let bestMatch: ParsedProperty | undefined;
52
+ let bestMatch: InternalPropertyDefinition | undefined;
50
53
 
51
54
  for (const prop of filteringProperties) {
52
- if (lowerText.startsWith(prop.propertyLabel.toLowerCase())) {
53
- if (
54
- !bestMatch ||
55
- prop.propertyLabel.length > bestMatch.propertyLabel.length
56
- ) {
55
+ if (lowerText.startsWith(prop.label.toLowerCase())) {
56
+ if (!bestMatch || prop.label.length > bestMatch.label.length) {
57
57
  bestMatch = prop;
58
58
  }
59
59
  }
@@ -67,7 +67,7 @@ function matchFilteringProperty(
67
67
  * Returns the prefix if valid, null otherwise.
68
68
  */
69
69
  function matchOperatorPrefix(
70
- allowedOperators: QueryFilterOperator[],
70
+ allowedOperators: OperatorT[],
71
71
  filteringText: string,
72
72
  ): string | null {
73
73
  const trimmedText = filteringText.trim();
@@ -84,8 +84,8 @@ function matchOperatorPrefix(
84
84
  }
85
85
 
86
86
  export {
87
- QUERY_OPERATORS,
88
- matchOperator,
89
87
  matchFilteringProperty,
88
+ matchOperator,
90
89
  matchOperatorPrefix,
90
+ QUERY_OPERATORS,
91
91
  };
@@ -1,52 +1,54 @@
1
1
  import { describe, expect, test } from "vitest";
2
2
  import type {
3
- ParsedProperty,
4
- QueryFilteringProperty,
3
+ ExternalPropertyDefinition,
4
+ InternalParsedTextState,
5
+ InternalPropertyDefinition,
5
6
  } from "../TokenFilter.types";
6
7
  import { parseQueryText } from "./parse-query-text";
7
- import type { ParsedText } from "./parse-query-text";
8
8
 
9
- const properties: QueryFilteringProperty[] = [
9
+ const properties: ExternalPropertyDefinition[] = [
10
10
  {
11
- groupValuesLabel: "",
11
+ groupLabel: "",
12
12
  group: "testgroup",
13
13
  key: "status",
14
- propertyLabel: "Status",
14
+ label: "Status",
15
15
  },
16
16
  {
17
- groupValuesLabel: "",
17
+ groupLabel: "",
18
18
  group: "testgroup",
19
19
  key: "hostname",
20
- propertyLabel: "Hostname",
20
+ label: "Hostname",
21
21
  },
22
22
  {
23
- groupValuesLabel: "",
23
+ groupLabel: "",
24
24
  group: "testgroup",
25
25
  key: "instance-id",
26
- propertyLabel: "Instance ID",
26
+ label: "Instance ID",
27
27
  },
28
28
  {
29
- groupValuesLabel: "",
29
+ groupLabel: "",
30
30
  group: "testgroup",
31
31
  key: "region",
32
- propertyLabel: "Region",
32
+ label: "Region",
33
33
  },
34
34
  {
35
- groupValuesLabel: "",
35
+ groupLabel: "",
36
36
  group: "testgroup",
37
37
  key: "availability-zone",
38
- propertyLabel: "Availability Zone",
38
+ label: "Availability Zone",
39
39
  },
40
40
  ];
41
41
 
42
- const parsedProperties: ParsedProperty[] = properties.map((prop) => ({
43
- propertyKey: prop.key,
44
- propertyLabel: prop.propertyLabel,
45
- groupValuesLabel: prop.groupValuesLabel ?? "",
46
- propertyGroup: prop.group ?? "",
47
- externalProperty: prop,
48
- operators: prop.operators ?? [],
49
- }));
42
+ const parsedProperties: InternalPropertyDefinition[] = properties.map(
43
+ (prop) => ({
44
+ key: prop.key,
45
+ label: prop.label,
46
+ groupLabel: prop.groupLabel ?? "",
47
+ group: prop.group ?? "",
48
+ externalProperty: prop,
49
+ operators: prop.operators ?? [],
50
+ }),
51
+ );
50
52
 
51
53
  describe("parseQueryText", () => {
52
54
  describe("value extraction", () => {
@@ -54,7 +56,7 @@ describe("parseQueryText", () => {
54
56
  const result = parseQueryText("Status=active", parsedProperties);
55
57
  expect(result.step).toBe("property");
56
58
  const propertyResult = result as Extract<
57
- ParsedText,
59
+ InternalParsedTextState,
58
60
  { step: "property" }
59
61
  >;
60
62
  expect(propertyResult.value).toBe("active");
@@ -64,7 +66,7 @@ describe("parseQueryText", () => {
64
66
  const result = parseQueryText("Status= active", parsedProperties);
65
67
  expect(result.step).toBe("property");
66
68
  const propertyResult = result as Extract<
67
- ParsedText,
69
+ InternalParsedTextState,
68
70
  { step: "property" }
69
71
  >;
70
72
  expect(propertyResult.value).toBe("active");
@@ -74,7 +76,7 @@ describe("parseQueryText", () => {
74
76
  const result = parseQueryText("Status=", parsedProperties);
75
77
  expect(result.step).toBe("property");
76
78
  const propertyResult = result as Extract<
77
- ParsedText,
79
+ InternalParsedTextState,
78
80
  { step: "property" }
79
81
  >;
80
82
  expect(propertyResult.value).toBe("");
@@ -84,7 +86,7 @@ describe("parseQueryText", () => {
84
86
  const result = parseQueryText("Status= ", parsedProperties);
85
87
  expect(result.step).toBe("property");
86
88
  const propertyResult = result as Extract<
87
- ParsedText,
89
+ InternalParsedTextState,
88
90
  { step: "property" }
89
91
  >;
90
92
  expect(propertyResult.value).toBe("");
@@ -97,7 +99,7 @@ describe("parseQueryText", () => {
97
99
  );
98
100
  expect(result.step).toBe("property");
99
101
  const propertyResult = result as Extract<
100
- ParsedText,
102
+ InternalParsedTextState,
101
103
  { step: "property" }
102
104
  >;
103
105
  expect(propertyResult.value).toBe("active and running");
@@ -107,7 +109,7 @@ describe("parseQueryText", () => {
107
109
  const result = parseQueryText("Instance ID=server-123", parsedProperties);
108
110
  expect(result.step).toBe("property");
109
111
  const propertyResult = result as Extract<
110
- ParsedText,
112
+ InternalParsedTextState,
111
113
  { step: "property" }
112
114
  >;
113
115
  expect(propertyResult.value).toBe("server-123");
@@ -119,7 +121,7 @@ describe("parseQueryText", () => {
119
121
  const result = parseQueryText("Status =value", parsedProperties);
120
122
  expect(result.step).toBe("property");
121
123
  const propertyResult = result as Extract<
122
- ParsedText,
124
+ InternalParsedTextState,
123
125
  { step: "property" }
124
126
  >;
125
127
  expect(propertyResult.operator).toBe("=");
@@ -130,7 +132,7 @@ describe("parseQueryText", () => {
130
132
  const result = parseQueryText("Status >value", parsedProperties);
131
133
  expect(result.step).toBe("property");
132
134
  const propertyResult = result as Extract<
133
- ParsedText,
135
+ InternalParsedTextState,
134
136
  { step: "property" }
135
137
  >;
136
138
  expect(propertyResult.operator).toBe(">");
@@ -141,7 +143,7 @@ describe("parseQueryText", () => {
141
143
  const result = parseQueryText("Status ", parsedProperties);
142
144
  expect(result.step).toBe("operator");
143
145
  const operatorResult = result as Extract<
144
- ParsedText,
146
+ InternalParsedTextState,
145
147
  { step: "operator" }
146
148
  >;
147
149
  expect(operatorResult.operatorPrefix).toBe("");
@@ -163,7 +165,7 @@ describe("parseQueryText", () => {
163
165
  const result = parseQueryText("Status", parsedProperties);
164
166
  expect(result.step).toBe("operator");
165
167
  const operatorResult = result as Extract<
166
- ParsedText,
168
+ InternalParsedTextState,
167
169
  { step: "operator" }
168
170
  >;
169
171
  expect(operatorResult.operatorPrefix).toBe("");
@@ -173,10 +175,10 @@ describe("parseQueryText", () => {
173
175
  const result = parseQueryText("Instance ID:value", parsedProperties);
174
176
  expect(result.step).toBe("property");
175
177
  const propertyResult = result as Extract<
176
- ParsedText,
178
+ InternalParsedTextState,
177
179
  { step: "property" }
178
180
  >;
179
- expect(propertyResult.property.propertyKey).toBe("instance-id");
181
+ expect(propertyResult.property.key).toBe("instance-id");
180
182
  expect(propertyResult.operator).toBe(":");
181
183
  expect(propertyResult.value).toBe("value");
182
184
  });
@@ -187,7 +189,7 @@ describe("parseQueryText", () => {
187
189
  const result = parseQueryText("Random text", parsedProperties);
188
190
  expect(result.step).toBe("free-text");
189
191
  const freeTextResult = result as Extract<
190
- ParsedText,
192
+ InternalParsedTextState,
191
193
  { step: "free-text" }
192
194
  >;
193
195
  expect(freeTextResult.value).toBe("Random text");
@@ -1,4 +1,7 @@
1
- import type { ParsedProperty, QueryFilterOperator } from "../TokenFilter.types";
1
+ import type {
2
+ InternalParsedTextState,
3
+ InternalPropertyDefinition,
4
+ } from "../TokenFilter.types";
2
5
  import {
3
6
  QUERY_OPERATORS,
4
7
  matchFilteringProperty,
@@ -6,35 +9,14 @@ import {
6
9
  matchOperatorPrefix,
7
10
  } from "./operators";
8
11
 
9
- type ParsedText =
10
- | {
11
- /** User has typed property + complete operator + value (e.g., "Status != active") */
12
- step: "property";
13
- property: ParsedProperty;
14
- operator: QueryFilterOperator;
15
- value: string;
16
- }
17
- | {
18
- /** User is typing the operator after property (e.g., "Status !") */
19
- step: "operator";
20
- property: ParsedProperty;
21
- operatorPrefix: string;
22
- }
23
- | {
24
- /** No property match; treat as free-text search */
25
- step: "free-text";
26
- value: string;
27
- operator?: QueryFilterOperator;
28
- };
29
-
30
12
  /**
31
13
  * Parse user input text to extract property, operator, and value components.
32
14
  * Handles partial input (e.g., user typing "Status !" to complete the operator).
33
15
  */
34
16
  function parseQueryText(
35
17
  filteringText: string,
36
- filteringProperties: ParsedProperty[],
37
- ): ParsedText {
18
+ filteringProperties: InternalPropertyDefinition[],
19
+ ): InternalParsedTextState {
38
20
  const property = matchFilteringProperty(filteringProperties, filteringText);
39
21
  if (!property) {
40
22
  const freeTextOperator = matchOperator(QUERY_OPERATORS, filteringText);
@@ -53,7 +35,7 @@ function parseQueryText(
53
35
  }
54
36
 
55
37
  const textWithoutProperty = filteringText
56
- .substring(property.propertyLabel.length)
38
+ .substring(property.label.length)
57
39
  .trimStart();
58
40
 
59
41
  const operator = matchOperator(QUERY_OPERATORS, textWithoutProperty);
@@ -83,4 +65,3 @@ function parseQueryText(
83
65
  }
84
66
 
85
67
  export { parseQueryText };
86
- export type { ParsedText };