@navikt/ds-react 8.6.0 → 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 (250) 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 -11
  25. package/cjs/data/token-filter/AutoSuggest.js.map +1 -1
  26. package/cjs/data/token-filter/TokenFilter.d.ts +5 -5
  27. package/cjs/data/token-filter/TokenFilter.js +105 -42
  28. package/cjs/data/token-filter/TokenFilter.js.map +1 -1
  29. package/cjs/data/token-filter/TokenFilter.types.d.ts +51 -33
  30. package/cjs/data/token-filter/helpers/generate-autocomplete-options.d.ts +2 -3
  31. package/cjs/data/token-filter/helpers/generate-autocomplete-options.js +11 -15
  32. package/cjs/data/token-filter/helpers/generate-autocomplete-options.js.map +1 -1
  33. package/cjs/data/token-filter/helpers/operators.d.ts +6 -6
  34. package/cjs/data/token-filter/helpers/operators.js +3 -4
  35. package/cjs/data/token-filter/helpers/operators.js.map +1 -1
  36. package/cjs/data/token-filter/helpers/parse-query-text.d.ts +2 -20
  37. package/cjs/data/token-filter/helpers/parse-query-text.js +1 -1
  38. package/cjs/data/token-filter/helpers/parse-query-text.js.map +1 -1
  39. package/cjs/data/token-filter/helpers/query-builder.d.ts +2 -2
  40. package/cjs/data/token-filter/helpers/query-builder.js.map +1 -1
  41. package/cjs/date/Date.Dialog.d.ts +5 -1
  42. package/cjs/date/Date.Dialog.js +6 -2
  43. package/cjs/date/Date.Dialog.js.map +1 -1
  44. package/cjs/date/datepicker/DatePicker.js +3 -2
  45. package/cjs/date/datepicker/DatePicker.js.map +1 -1
  46. package/cjs/date/datepicker/hooks/useDatepicker.js +5 -2
  47. package/cjs/date/datepicker/hooks/useDatepicker.js.map +1 -1
  48. package/cjs/date/datepicker/hooks/useRangeDatepicker.js +3 -1
  49. package/cjs/date/datepicker/hooks/useRangeDatepicker.js.map +1 -1
  50. package/cjs/date/datepicker/parts/DatePicker.Months.d.ts +2 -1
  51. package/cjs/date/datepicker/parts/DatePicker.Months.js +3 -3
  52. package/cjs/date/datepicker/parts/DatePicker.Months.js.map +1 -1
  53. package/cjs/date/datepicker/parts/DatePicker.RDP.d.ts +5 -1
  54. package/cjs/date/datepicker/parts/DatePicker.RDP.js +2 -2
  55. package/cjs/date/datepicker/parts/DatePicker.RDP.js.map +1 -1
  56. package/cjs/date/monthpicker/MonthPicker.js +3 -2
  57. package/cjs/date/monthpicker/MonthPicker.js.map +1 -1
  58. package/cjs/date/monthpicker/hooks/useMonthPicker.js +3 -1
  59. package/cjs/date/monthpicker/hooks/useMonthPicker.js.map +1 -1
  60. package/cjs/date/monthpicker/parts/MonthPicker.Caption.d.ts +4 -1
  61. package/cjs/date/monthpicker/parts/MonthPicker.Caption.js +3 -2
  62. package/cjs/date/monthpicker/parts/MonthPicker.Caption.js.map +1 -1
  63. package/cjs/dropdown/Toggle.js +5 -12
  64. package/cjs/dropdown/Toggle.js.map +1 -1
  65. package/cjs/form/combobox/Input/Input.js +1 -1
  66. package/cjs/form/combobox/Input/Input.js.map +1 -1
  67. package/cjs/inline-message/root/InlineMessage.js +2 -2
  68. package/cjs/inline-message/root/InlineMessage.js.map +1 -1
  69. package/cjs/provider/Provider.d.ts +2 -2
  70. package/cjs/tooltip/Tooltip.js +1 -3
  71. package/cjs/tooltip/Tooltip.js.map +1 -1
  72. package/cjs/utils/components/HighlightText/HighlightText.d.ts +8 -0
  73. package/cjs/utils/components/HighlightText/HighlightText.js +27 -0
  74. package/cjs/utils/components/HighlightText/HighlightText.js.map +1 -0
  75. package/cjs/utils/components/Listbox/group/ListboxGroup.d.ts +7 -0
  76. package/cjs/utils/components/Listbox/group/ListboxGroup.js +15 -0
  77. package/cjs/utils/components/Listbox/group/ListboxGroup.js.map +1 -0
  78. package/cjs/utils/components/Listbox/input-slot/ListboxInputSlot.d.ts +7 -0
  79. package/cjs/utils/components/Listbox/input-slot/ListboxInputSlot.js +15 -0
  80. package/cjs/utils/components/Listbox/input-slot/ListboxInputSlot.js.map +1 -0
  81. package/cjs/utils/components/Listbox/item/ListboxItem.d.ts +24 -0
  82. package/cjs/utils/components/Listbox/item/ListboxItem.js +33 -0
  83. package/cjs/utils/components/Listbox/item/ListboxItem.js.map +1 -0
  84. package/cjs/utils/components/Listbox/list/ListboxList.d.ts +8 -0
  85. package/cjs/utils/components/Listbox/list/ListboxList.js +32 -0
  86. package/cjs/utils/components/Listbox/list/ListboxList.js.map +1 -0
  87. package/cjs/utils/components/Listbox/root/ListboxRoot.d.ts +20 -0
  88. package/cjs/utils/components/Listbox/root/ListboxRoot.js +84 -0
  89. package/cjs/utils/components/Listbox/root/ListboxRoot.js.map +1 -0
  90. package/cjs/utils/components/Listbox/root/domHelpers.d.ts +3 -0
  91. package/cjs/utils/components/Listbox/root/domHelpers.js +53 -0
  92. package/cjs/utils/components/Listbox/root/domHelpers.js.map +1 -0
  93. package/cjs/utils/components/focus-boundary/FocusBoundary.js +9 -64
  94. package/cjs/utils/components/focus-boundary/FocusBoundary.js.map +1 -1
  95. package/cjs/utils/helpers/focus.d.ts +14 -0
  96. package/cjs/utils/helpers/focus.js +63 -0
  97. package/cjs/utils/helpers/focus.js.map +1 -0
  98. package/cjs/utils/hooks/useDeferredValue.d.ts +1 -0
  99. package/cjs/utils/hooks/useDeferredValue.js +14 -0
  100. package/cjs/utils/hooks/useDeferredValue.js.map +1 -0
  101. package/esm/data/drag-and-drop/item/DataDragAndDropItem.d.ts +27 -0
  102. package/esm/data/drag-and-drop/item/DataDragAndDropItem.js +55 -0
  103. package/esm/data/drag-and-drop/item/DataDragAndDropItem.js.map +1 -0
  104. package/esm/data/drag-and-drop/root/DataDragAndDrop.context.d.ts +5 -0
  105. package/esm/data/drag-and-drop/root/DataDragAndDrop.context.js +3 -0
  106. package/esm/data/drag-and-drop/root/DataDragAndDrop.context.js.map +1 -0
  107. package/esm/data/drag-and-drop/root/DataDragAndDropRoot.d.ts +24 -0
  108. package/esm/data/drag-and-drop/root/DataDragAndDropRoot.js +71 -0
  109. package/esm/data/drag-and-drop/root/DataDragAndDropRoot.js.map +1 -0
  110. package/esm/data/table/helpers/table-keyboard.d.ts +1 -0
  111. package/esm/data/table/helpers/table-keyboard.js +5 -3
  112. package/esm/data/table/helpers/table-keyboard.js.map +1 -1
  113. package/esm/data/table/root/DataTableRoot.context.d.ts +8 -0
  114. package/esm/data/table/root/DataTableRoot.context.js +7 -0
  115. package/esm/data/table/root/DataTableRoot.context.js.map +1 -0
  116. package/esm/data/table/root/DataTableRoot.js +5 -3
  117. package/esm/data/table/root/DataTableRoot.js.map +1 -1
  118. package/esm/data/table/th/DataTableTh.d.ts +18 -2
  119. package/esm/data/table/th/DataTableTh.js +46 -21
  120. package/esm/data/table/th/DataTableTh.js.map +1 -1
  121. package/esm/data/table/tr/DataTableTr.js +9 -2
  122. package/esm/data/table/tr/DataTableTr.js.map +1 -1
  123. package/esm/data/token-filter/AutoSuggest.d.ts +6 -2
  124. package/esm/data/token-filter/AutoSuggest.js +45 -13
  125. package/esm/data/token-filter/AutoSuggest.js.map +1 -1
  126. package/esm/data/token-filter/TokenFilter.d.ts +5 -5
  127. package/esm/data/token-filter/TokenFilter.js +105 -42
  128. package/esm/data/token-filter/TokenFilter.js.map +1 -1
  129. package/esm/data/token-filter/TokenFilter.types.d.ts +51 -33
  130. package/esm/data/token-filter/helpers/generate-autocomplete-options.d.ts +2 -3
  131. package/esm/data/token-filter/helpers/generate-autocomplete-options.js +11 -15
  132. package/esm/data/token-filter/helpers/generate-autocomplete-options.js.map +1 -1
  133. package/esm/data/token-filter/helpers/operators.d.ts +6 -6
  134. package/esm/data/token-filter/helpers/operators.js +3 -4
  135. package/esm/data/token-filter/helpers/operators.js.map +1 -1
  136. package/esm/data/token-filter/helpers/parse-query-text.d.ts +2 -20
  137. package/esm/data/token-filter/helpers/parse-query-text.js +1 -1
  138. package/esm/data/token-filter/helpers/parse-query-text.js.map +1 -1
  139. package/esm/data/token-filter/helpers/query-builder.d.ts +2 -2
  140. package/esm/data/token-filter/helpers/query-builder.js.map +1 -1
  141. package/esm/date/Date.Dialog.d.ts +5 -1
  142. package/esm/date/Date.Dialog.js +6 -2
  143. package/esm/date/Date.Dialog.js.map +1 -1
  144. package/esm/date/datepicker/DatePicker.js +3 -2
  145. package/esm/date/datepicker/DatePicker.js.map +1 -1
  146. package/esm/date/datepicker/hooks/useDatepicker.js +5 -2
  147. package/esm/date/datepicker/hooks/useDatepicker.js.map +1 -1
  148. package/esm/date/datepicker/hooks/useRangeDatepicker.js +3 -1
  149. package/esm/date/datepicker/hooks/useRangeDatepicker.js.map +1 -1
  150. package/esm/date/datepicker/parts/DatePicker.Months.d.ts +2 -1
  151. package/esm/date/datepicker/parts/DatePicker.Months.js +3 -3
  152. package/esm/date/datepicker/parts/DatePicker.Months.js.map +1 -1
  153. package/esm/date/datepicker/parts/DatePicker.RDP.d.ts +5 -1
  154. package/esm/date/datepicker/parts/DatePicker.RDP.js +2 -2
  155. package/esm/date/datepicker/parts/DatePicker.RDP.js.map +1 -1
  156. package/esm/date/monthpicker/MonthPicker.js +3 -2
  157. package/esm/date/monthpicker/MonthPicker.js.map +1 -1
  158. package/esm/date/monthpicker/hooks/useMonthPicker.js +3 -1
  159. package/esm/date/monthpicker/hooks/useMonthPicker.js.map +1 -1
  160. package/esm/date/monthpicker/parts/MonthPicker.Caption.d.ts +4 -1
  161. package/esm/date/monthpicker/parts/MonthPicker.Caption.js +3 -2
  162. package/esm/date/monthpicker/parts/MonthPicker.Caption.js.map +1 -1
  163. package/esm/dropdown/Toggle.js +5 -12
  164. package/esm/dropdown/Toggle.js.map +1 -1
  165. package/esm/form/combobox/Input/Input.js +1 -1
  166. package/esm/form/combobox/Input/Input.js.map +1 -1
  167. package/esm/inline-message/root/InlineMessage.js +3 -3
  168. package/esm/inline-message/root/InlineMessage.js.map +1 -1
  169. package/esm/provider/Provider.d.ts +2 -2
  170. package/esm/tooltip/Tooltip.js +1 -3
  171. package/esm/tooltip/Tooltip.js.map +1 -1
  172. package/esm/utils/components/HighlightText/HighlightText.d.ts +8 -0
  173. package/esm/utils/components/HighlightText/HighlightText.js +21 -0
  174. package/esm/utils/components/HighlightText/HighlightText.js.map +1 -0
  175. package/esm/utils/components/Listbox/group/ListboxGroup.d.ts +7 -0
  176. package/esm/utils/components/Listbox/group/ListboxGroup.js +10 -0
  177. package/esm/utils/components/Listbox/group/ListboxGroup.js.map +1 -0
  178. package/esm/utils/components/Listbox/input-slot/ListboxInputSlot.d.ts +7 -0
  179. package/esm/utils/components/Listbox/input-slot/ListboxInputSlot.js +9 -0
  180. package/esm/utils/components/Listbox/input-slot/ListboxInputSlot.js.map +1 -0
  181. package/esm/utils/components/Listbox/item/ListboxItem.d.ts +24 -0
  182. package/esm/utils/components/Listbox/item/ListboxItem.js +27 -0
  183. package/esm/utils/components/Listbox/item/ListboxItem.js.map +1 -0
  184. package/esm/utils/components/Listbox/list/ListboxList.d.ts +8 -0
  185. package/esm/utils/components/Listbox/list/ListboxList.js +27 -0
  186. package/esm/utils/components/Listbox/list/ListboxList.js.map +1 -0
  187. package/esm/utils/components/Listbox/root/ListboxRoot.d.ts +20 -0
  188. package/esm/utils/components/Listbox/root/ListboxRoot.js +79 -0
  189. package/esm/utils/components/Listbox/root/ListboxRoot.js.map +1 -0
  190. package/esm/utils/components/Listbox/root/domHelpers.d.ts +3 -0
  191. package/esm/utils/components/Listbox/root/domHelpers.js +50 -0
  192. package/esm/utils/components/Listbox/root/domHelpers.js.map +1 -0
  193. package/esm/utils/components/focus-boundary/FocusBoundary.js +8 -63
  194. package/esm/utils/components/focus-boundary/FocusBoundary.js.map +1 -1
  195. package/esm/utils/helpers/focus.d.ts +14 -0
  196. package/esm/utils/helpers/focus.js +60 -0
  197. package/esm/utils/helpers/focus.js.map +1 -0
  198. package/esm/utils/hooks/useDeferredValue.d.ts +1 -0
  199. package/esm/utils/hooks/useDeferredValue.js +7 -0
  200. package/esm/utils/hooks/useDeferredValue.js.map +1 -0
  201. package/package.json +7 -7
  202. package/src/data/drag-and-drop/item/DataDragAndDropItem.tsx +101 -0
  203. package/src/data/drag-and-drop/root/DataDragAndDrop.context.tsx +9 -0
  204. package/src/data/drag-and-drop/root/DataDragAndDropRoot.tsx +98 -0
  205. package/src/data/table/helpers/table-keyboard.ts +7 -3
  206. package/src/data/table/root/DataTableRoot.context.ts +13 -0
  207. package/src/data/table/root/DataTableRoot.tsx +16 -13
  208. package/src/data/table/th/DataTableTh.tsx +110 -54
  209. package/src/data/table/tr/DataTableTr.tsx +13 -2
  210. package/src/data/token-filter/AutoSuggest.tsx +142 -29
  211. package/src/data/token-filter/TokenFilter.tsx +174 -79
  212. package/src/data/token-filter/TokenFilter.types.ts +70 -42
  213. package/src/data/token-filter/helpers/generate-autocomplete-options.test.ts +97 -97
  214. package/src/data/token-filter/helpers/generate-autocomplete-options.ts +31 -38
  215. package/src/data/token-filter/helpers/operators.test.ts +29 -29
  216. package/src/data/token-filter/helpers/operators.ts +16 -16
  217. package/src/data/token-filter/helpers/parse-query-text.test.ts +37 -35
  218. package/src/data/token-filter/helpers/parse-query-text.ts +7 -26
  219. package/src/data/token-filter/helpers/query-builder.ts +2 -2
  220. package/src/date/Date.Dialog.tsx +15 -0
  221. package/src/date/datepicker/DatePicker.tsx +3 -0
  222. package/src/date/datepicker/hooks/useDatepicker.tsx +7 -2
  223. package/src/date/datepicker/hooks/useRangeDatepicker.tsx +5 -1
  224. package/src/date/datepicker/parts/DatePicker.Months.tsx +9 -1
  225. package/src/date/datepicker/parts/DatePicker.RDP.tsx +7 -1
  226. package/src/date/monthpicker/MonthPicker.tsx +3 -1
  227. package/src/date/monthpicker/hooks/useMonthPicker.tsx +5 -1
  228. package/src/date/monthpicker/parts/MonthPicker.Caption.tsx +20 -2
  229. package/src/dropdown/Toggle.tsx +6 -12
  230. package/src/form/combobox/Input/Input.tsx +2 -2
  231. package/src/inline-message/root/InlineMessage.tsx +5 -5
  232. package/src/provider/Provider.tsx +2 -2
  233. package/src/tooltip/Tooltip.tsx +1 -3
  234. package/src/utils/components/HighlightText/HighlightText.tsx +34 -0
  235. package/src/utils/components/Listbox/group/ListboxGroup.tsx +26 -0
  236. package/src/utils/components/Listbox/input-slot/ListboxInputSlot.tsx +22 -0
  237. package/src/utils/components/Listbox/item/ListboxItem.tsx +57 -0
  238. package/src/utils/components/Listbox/list/ListboxList.tsx +38 -0
  239. package/src/utils/components/Listbox/root/ListboxRoot.tsx +104 -0
  240. package/src/utils/components/Listbox/root/domHelpers.ts +59 -0
  241. package/src/utils/components/focus-boundary/FocusBoundary.tsx +8 -78
  242. package/src/utils/helpers/focus.ts +75 -0
  243. package/src/utils/hooks/useDeferredValue.ts +12 -0
  244. package/cjs/data/table/th/DataTableThSortHandle.d.ts +0 -6
  245. package/cjs/data/table/th/DataTableThSortHandle.js +0 -82
  246. package/cjs/data/table/th/DataTableThSortHandle.js.map +0 -1
  247. package/esm/data/table/th/DataTableThSortHandle.d.ts +0 -6
  248. package/esm/data/table/th/DataTableThSortHandle.js +0 -47
  249. package/esm/data/table/th/DataTableThSortHandle.js.map +0 -1
  250. package/src/data/table/th/DataTableThSortHandle.tsx +0 -67
@@ -1,23 +1,27 @@
1
1
  import React, { forwardRef, useState } from "react";
2
- import { Popover } from "../../popover";
2
+ import { Chips } from "../../chips";
3
+ import { HStack } from "../../primitives/stack";
3
4
  import { cl } from "../../utils/helpers";
4
5
  import { AutoSuggest } from "./AutoSuggest";
6
+ import { AutoCompleteOption } from "./AutoSuggest.types";
5
7
  import type {
6
- ParsedOption,
7
- ParsedProperty,
8
- QueryFilterQuery,
9
- QueryFilteringOptions,
10
- QueryFilteringProperties,
8
+ ExternalOptions,
9
+ ExternalPropertyDefinitions,
10
+ ExternalQuery,
11
+ ExternalToken,
12
+ InternalPropertyDefinition,
13
+ InternalPropertyOption,
14
+ OperationT,
11
15
  } from "./TokenFilter.types";
12
16
  import { generateAutoCompleteOptions } from "./helpers/generate-autocomplete-options";
13
17
  import { parseQueryText } from "./helpers/parse-query-text";
14
18
 
15
19
  type TokenFilterProps = {
16
- query: QueryFilterQuery;
17
- onChange: (newQuery: QueryFilterQuery) => void;
20
+ query: ExternalQuery;
21
+ onChange: (newQuery: ExternalQuery) => void;
18
22
  className?: string;
19
- filteringOptions: QueryFilteringOptions;
20
- filteringProperties: QueryFilteringProperties;
23
+ propertyDefinitions: ExternalPropertyDefinitions;
24
+ options: ExternalOptions;
21
25
  };
22
26
 
23
27
  /**
@@ -26,31 +30,76 @@ type TokenFilterProps = {
26
30
  * - Handle token rendering and editing (e.g., show tokens for matched properties/operators/values, allow deleting tokens).
27
31
  */
28
32
  export const TokenFilter = forwardRef<HTMLDivElement, TokenFilterProps>(
29
- ({ query, className, filteringProperties, filteringOptions }, ref) => {
30
- const [inputAnchor, setInputAnchor] = useState<HTMLInputElement | null>(
31
- null,
32
- );
33
-
33
+ ({ query, className, propertyDefinitions, options, onChange }, ref) => {
34
34
  const [filterText, setFilterText] = useState<string>("");
35
- const { properties, options } = derrivedFilterState(
36
- filteringProperties,
37
- filteringOptions,
38
- );
35
+ const [open, setOpen] = useState(false);
39
36
 
40
- const queryState = parseQueryText(filterText, properties);
37
+ const { parsedPropertyDefinitions, parsedPropertyOptions } =
38
+ derrivedFilterState(propertyDefinitions, options);
39
+
40
+ const queryState = parseQueryText(filterText, parsedPropertyDefinitions);
41
41
 
42
42
  const autoCompleteOptions = generateAutoCompleteOptions(
43
43
  queryState,
44
- properties,
45
- options,
44
+ parsedPropertyDefinitions,
45
+ parsedPropertyOptions,
46
46
  );
47
47
 
48
- const handleSelectOption = (value: string) => {
49
- setFilterText(value);
50
- setCustomOpen(false);
48
+ const { addToken, removeToken } = createActionHandlers({
49
+ query,
50
+ onChange,
51
+ });
52
+
53
+ const createToken = (newText: string): boolean => {
54
+ const newQueryState = parseQueryText(newText, parsedPropertyDefinitions);
55
+
56
+ let newToken: ExternalToken | null = null;
57
+
58
+ switch (newQueryState.step) {
59
+ case "property": {
60
+ if (newQueryState.value === "") {
61
+ return false;
62
+ }
63
+ newToken = {
64
+ propertyKey: newQueryState.property.key,
65
+ operator: newQueryState.operator,
66
+ value: newQueryState.value,
67
+ };
68
+ break;
69
+ }
70
+ case "free-text": {
71
+ break;
72
+ }
73
+ case "operator": {
74
+ break;
75
+ }
76
+ }
77
+ if (newToken) {
78
+ addToken(newToken);
79
+ setFilterText("");
80
+ return true;
81
+ }
82
+ return false;
51
83
  };
52
84
 
53
- const [customOpen, setCustomOpen] = useState(false);
85
+ const handleSelectOption = (option: AutoCompleteOption) => {
86
+ const newQueryState = parseQueryText(
87
+ option.value,
88
+ parsedPropertyDefinitions,
89
+ );
90
+
91
+ if (
92
+ (newQueryState.step === "property" && newQueryState.value === "") ||
93
+ newQueryState.step === "operator"
94
+ ) {
95
+ /* Add space after for better formatting */
96
+ /* TODO: Handle this scenario better */
97
+ setFilterText(`${option.value} `);
98
+ return false;
99
+ }
100
+ setFilterText(option.value);
101
+ return createToken(option.value);
102
+ };
54
103
 
55
104
  return (
56
105
  <div
@@ -58,75 +107,121 @@ export const TokenFilter = forwardRef<HTMLDivElement, TokenFilterProps>(
58
107
  className={cl("aksel-property-filter", className)}
59
108
  role="search"
60
109
  >
61
- <input
62
- type="text"
63
- className="aksel-property-filter__input"
64
- placeholder="Type to filter..."
65
- ref={setInputAnchor}
110
+ <AutoSuggest
111
+ onSelect={handleSelectOption}
112
+ options={autoCompleteOptions.options}
66
113
  value={filterText}
67
- onChange={(e) => setFilterText(e.target.value)}
68
- onFocus={() => setCustomOpen(true)}
114
+ onChange={setFilterText}
115
+ open={open}
116
+ setOpen={setOpen}
69
117
  />
70
- <Popover
71
- anchorEl={inputAnchor}
72
- open={customOpen}
73
- onClose={() => {
74
- setFilterText("");
75
- setCustomOpen(false);
76
- }}
77
- >
78
- <AutoSuggest
79
- options={autoCompleteOptions.options}
80
- onSelect={handleSelectOption}
81
- />
82
- </Popover>
83
- {query.tokens.map((token, index) => {
84
- return (
85
- <div key={index} className="aksel-property-filter__token">
86
- <strong>{token.propertyKey}</strong> {token.operator}{" "}
87
- </div>
88
- );
89
- })}
90
- <ul>
91
- {filteringProperties.map((prop) => (
92
- <li key={prop.key}>{prop.propertyLabel}</li>
93
- ))}
94
- </ul>
95
- {/* <pre>{JSON.stringify(queryState, null, 2)}</pre> */}
96
- <pre>{JSON.stringify(autoCompleteOptions, null, 2)}</pre>
118
+ <HStack marginBlock="space-8" gap="space-8">
119
+ {query.tokens.map((token, index) => {
120
+ return (
121
+ <React.Fragment
122
+ key={`${token.propertyKey}-${token.operator}-${token.value}-${index}`}
123
+ >
124
+ <Chips.Removable
125
+ key={index}
126
+ onClick={() => {
127
+ removeToken(index);
128
+ }}
129
+ >
130
+ {`${token.propertyKey} ${token.operator} ${token.value}`}
131
+ </Chips.Removable>
132
+ {index < query.tokens.length - 1 && (
133
+ <span>{query.operation}</span>
134
+ )}
135
+ </React.Fragment>
136
+ );
137
+ })}
138
+ </HStack>
97
139
  </div>
98
140
  );
99
141
  },
100
142
  );
101
143
 
102
144
  function derrivedFilterState(
103
- filteringProperties: QueryFilteringProperties,
104
- filteringOptions: QueryFilteringOptions,
105
- /* query: QueryFilterQuery */
145
+ propertyDefinitions: ExternalPropertyDefinitions,
146
+ propteryOptions: ExternalOptions,
106
147
  ): {
107
- properties: ParsedProperty[];
108
- options: ParsedOption[];
148
+ parsedPropertyDefinitions: InternalPropertyDefinition[];
149
+ parsedPropertyOptions: InternalPropertyOption[];
109
150
  } {
110
- const propertyMap = new Map<string, any>();
151
+ const propertyMap = new Map<string, InternalPropertyDefinition>();
111
152
 
112
- for (const property of filteringProperties) {
153
+ for (const property of propertyDefinitions) {
113
154
  propertyMap.set(property.key, {
114
- propertyKey: property.key,
115
- propertyLabel: property?.propertyLabel ?? "",
116
- groupValuesLabel: property?.groupValuesLabel ?? "",
117
- propertyGroup: property?.group,
155
+ key: property.key,
156
+ label: property?.label ?? "",
157
+ groupLabel: property?.groupLabel ?? "",
158
+ group: property?.group ?? "",
118
159
  operators: property?.operators ?? [],
119
- /* defaultOperator: property?.defaultOperator ?? '=', */
120
160
  externalProperty: property,
121
161
  });
122
162
  }
123
163
 
124
- const internalOptions = filteringOptions.map((option) => ({
125
- property: propertyMap.get(option.propertyKey) ?? null,
126
- value: option.value,
127
- label: option.label ?? option.value ?? "",
128
- tags: option.tags ?? [],
129
- }));
164
+ const internalOptions: InternalPropertyOption[] = [];
165
+
166
+ for (const option of propteryOptions) {
167
+ internalOptions.push({
168
+ property: propertyMap.get(option.propertyKey) ?? null,
169
+ value: option.value,
170
+ label: option.label ?? option.value ?? "",
171
+ tags: option.tags ?? [],
172
+ });
173
+ }
174
+
175
+ return {
176
+ parsedPropertyDefinitions: [...propertyMap.values()],
177
+ parsedPropertyOptions: internalOptions,
178
+ };
179
+ }
180
+
181
+ function createActionHandlers({
182
+ query,
183
+ onChange,
184
+ }: {
185
+ query: ExternalQuery;
186
+ onChange: (newQuery: ExternalQuery) => void;
187
+ }) {
188
+ const handleChange = (newQuery: ExternalQuery) => {
189
+ onChange(newQuery);
190
+ };
191
+
192
+ const addToken = (token: ExternalToken) => {
193
+ handleChange({ ...query, tokens: [...query.tokens, token] });
194
+ };
195
+
196
+ const updateToken = (updateIndex: number, updatedToken: ExternalToken) => {
197
+ handleChange({
198
+ ...query,
199
+ tokens: query.tokens.map((token, index) =>
200
+ index === updateIndex ? updatedToken : token,
201
+ ),
202
+ });
203
+ };
204
+
205
+ const updateOperation = (operation: OperationT) => {
206
+ handleChange({ ...query, operation });
207
+ };
208
+
209
+ const removeToken = (removeIndex: number) => {
210
+ handleChange({
211
+ ...query,
212
+ tokens: query.tokens.filter((_, index) => index !== removeIndex),
213
+ });
214
+ };
215
+
216
+ const removeAllTokens = () => {
217
+ handleChange({ ...query, tokens: [] });
218
+ };
130
219
 
131
- return { properties: [...propertyMap.values()], options: internalOptions };
220
+ return {
221
+ addToken,
222
+ updateToken,
223
+ updateOperation,
224
+ removeToken,
225
+ removeAllTokens,
226
+ };
132
227
  }
@@ -1,4 +1,5 @@
1
- type QueryFilterOperator =
1
+ /* External API */
2
+ type OperatorT =
2
3
  | "<"
3
4
  | "<="
4
5
  | ">"
@@ -11,73 +12,100 @@ type QueryFilterOperator =
11
12
  | "!^"
12
13
  | (string & {});
13
14
 
14
- type QueryFilterOperation = "and" | "or";
15
+ type OperationT = "and" | "or";
15
16
 
16
- type QueryFilterToken = {
17
+ type ExternalToken = {
17
18
  propertyKey: string;
18
- operator: QueryFilterOperator;
19
- value: any;
19
+ operator: OperatorT;
20
+ value: string;
20
21
  };
21
22
 
22
- type QueryFilterQuery = {
23
- tokens: QueryFilterToken[];
24
- operation: QueryFilterOperation;
23
+ type ExternalQuery = {
24
+ tokens: ExternalToken[];
25
+ operation: OperationT;
25
26
  };
26
27
 
27
- type QueryFilteringOption = {
28
+ type ExternalOption = {
28
29
  propertyKey: string;
29
- value: any;
30
+ value: string;
30
31
  label?: string;
31
32
  tags?: string[];
32
33
  disabled?: boolean;
33
34
  };
34
35
 
35
- type QueryFilteringOptions = QueryFilteringOption[];
36
+ type ExternalOptions = ExternalOption[];
36
37
 
37
- type QueryFilteringOptionGroup = {
38
+ type ExternalPropertyGroup = {
38
39
  label: string;
39
- options: QueryFilteringOptions;
40
+ options: ExternalOptions;
40
41
  };
41
42
 
42
- type QueryFilteringScopedOperator =
43
- | string
44
- | { operator: string; tokenType: "single" | "multiple" };
45
-
46
- type QueryFilteringProperty = {
43
+ type ExternalPropertyDefinition = {
47
44
  key: string;
48
- propertyLabel: string;
49
- groupValuesLabel?: string;
45
+ label: string;
46
+ groupLabel?: string;
50
47
  group?: string;
51
- operators?: QueryFilteringScopedOperator[];
48
+ operators?: ExternalPropertyOperator[];
52
49
  };
53
50
 
54
- type QueryFilteringProperties = QueryFilteringProperty[];
51
+ type ExternalPropertyDefinitions = ExternalPropertyDefinition[];
55
52
 
56
- type ParsedProperty = {
57
- propertyKey: string;
58
- propertyLabel: string;
59
- groupValuesLabel: string;
60
- propertyGroup: string;
61
- operators: QueryFilteringScopedOperator[];
62
- externalProperty: QueryFilteringProperty;
53
+ type ExternalPropertyOperator =
54
+ | string
55
+ | { operator: string; type: "single" | "multiple" };
56
+
57
+ export type {
58
+ ExternalOption,
59
+ ExternalOptions,
60
+ ExternalPropertyDefinition,
61
+ ExternalPropertyDefinitions,
62
+ ExternalPropertyGroup,
63
+ ExternalQuery,
64
+ ExternalToken,
65
+ OperationT,
66
+ OperatorT,
67
+ };
68
+
69
+ /* Internal API */
70
+ type InternalPropertyDefinition = {
71
+ key: string;
72
+ label: string;
73
+ groupLabel: string;
74
+ group: string;
75
+ operators: ExternalPropertyOperator[];
76
+ externalProperty: ExternalPropertyDefinition;
63
77
  };
64
78
 
65
- type ParsedOption = {
66
- property: ParsedProperty | null;
67
- value: any;
79
+ type InternalPropertyOption = {
80
+ property: InternalPropertyDefinition | null;
81
+ value: string;
68
82
  label: string;
69
83
  tags: string[];
70
84
  };
71
85
 
86
+ type InternalParsedTextState =
87
+ | {
88
+ /** User has typed property + complete operator + value (e.g., "Status != active") */
89
+ step: "property";
90
+ property: InternalPropertyDefinition;
91
+ operator: OperatorT;
92
+ value: string;
93
+ }
94
+ | {
95
+ /** User is typing the operator after property (e.g., "Status !") */
96
+ step: "operator";
97
+ property: InternalPropertyDefinition;
98
+ operatorPrefix: string;
99
+ }
100
+ | {
101
+ /** No property match; treat as free-text search */
102
+ step: "free-text";
103
+ value: string;
104
+ operator?: OperatorT;
105
+ };
106
+
72
107
  export type {
73
- QueryFilterOperator,
74
- QueryFilterQuery,
75
- QueryFilteringOptions,
76
- QueryFilteringProperty,
77
- QueryFilterOperation,
78
- QueryFilteringProperties,
79
- ParsedProperty,
80
- ParsedOption,
81
- QueryFilteringOption,
82
- QueryFilteringOptionGroup,
108
+ InternalPropertyDefinition,
109
+ InternalPropertyOption,
110
+ InternalParsedTextState,
83
111
  };