@navikt/ds-react 6.2.0 → 6.3.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 (271) hide show
  1. package/cjs/form/combobox/ComboboxProvider.js +5 -1
  2. package/cjs/form/combobox/ComboboxProvider.js.map +1 -1
  3. package/cjs/form/combobox/FilteredOptions/FilteredOptions.js +14 -12
  4. package/cjs/form/combobox/FilteredOptions/FilteredOptions.js.map +1 -1
  5. package/cjs/form/combobox/FilteredOptions/filtered-options-util.d.ts +3 -3
  6. package/cjs/form/combobox/FilteredOptions/filtered-options-util.js +1 -3
  7. package/cjs/form/combobox/FilteredOptions/filtered-options-util.js.map +1 -1
  8. package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.d.ts +8 -5
  9. package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js +8 -13
  10. package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
  11. package/cjs/form/combobox/Input/Input.js +9 -7
  12. package/cjs/form/combobox/Input/Input.js.map +1 -1
  13. package/cjs/form/combobox/SelectedOptions/SelectedOptions.d.ts +2 -1
  14. package/cjs/form/combobox/SelectedOptions/SelectedOptions.js +3 -3
  15. package/cjs/form/combobox/SelectedOptions/SelectedOptions.js.map +1 -1
  16. package/cjs/form/combobox/SelectedOptions/selectedOptionsContext.d.ts +10 -7
  17. package/cjs/form/combobox/SelectedOptions/selectedOptionsContext.js +6 -8
  18. package/cjs/form/combobox/SelectedOptions/selectedOptionsContext.js.map +1 -1
  19. package/cjs/form/combobox/combobox-utils.d.ts +10 -0
  20. package/cjs/form/combobox/combobox-utils.js +27 -0
  21. package/cjs/form/combobox/combobox-utils.js.map +1 -0
  22. package/cjs/form/combobox/customOptionsContext.d.ts +5 -4
  23. package/cjs/form/combobox/customOptionsContext.js +1 -1
  24. package/cjs/form/combobox/customOptionsContext.js.map +1 -1
  25. package/cjs/form/combobox/types.d.ts +22 -11
  26. package/cjs/form/file-upload/FileUpload.context.d.ts +8 -0
  27. package/cjs/form/file-upload/FileUpload.context.js +7 -0
  28. package/cjs/form/file-upload/FileUpload.context.js.map +1 -0
  29. package/cjs/form/file-upload/FileUpload.d.ts +118 -0
  30. package/cjs/form/file-upload/FileUpload.js +73 -0
  31. package/cjs/form/file-upload/FileUpload.js.map +1 -0
  32. package/cjs/form/file-upload/FileUpload.types.d.ts +55 -0
  33. package/cjs/form/file-upload/FileUpload.types.js +8 -0
  34. package/cjs/form/file-upload/FileUpload.types.js.map +1 -0
  35. package/cjs/form/file-upload/i18n/get.d.ts +2 -0
  36. package/cjs/form/file-upload/i18n/get.js +38 -0
  37. package/cjs/form/file-upload/i18n/get.js.map +1 -0
  38. package/cjs/form/file-upload/i18n/i18n.context.d.ts +11 -0
  39. package/cjs/form/file-upload/i18n/i18n.context.js +39 -0
  40. package/cjs/form/file-upload/i18n/i18n.context.js.map +1 -0
  41. package/cjs/form/file-upload/i18n/i18n.types.d.ts +13 -0
  42. package/cjs/form/file-upload/i18n/i18n.types.js +3 -0
  43. package/cjs/form/file-upload/i18n/i18n.types.js.map +1 -0
  44. package/cjs/form/file-upload/i18n/locales/nb.json +20 -0
  45. package/cjs/form/file-upload/i18n/merge.d.ts +2 -0
  46. package/cjs/form/file-upload/i18n/merge.js +29 -0
  47. package/cjs/form/file-upload/i18n/merge.js.map +1 -0
  48. package/cjs/form/file-upload/index.d.ts +7 -0
  49. package/cjs/form/file-upload/index.js +16 -0
  50. package/cjs/form/file-upload/index.js.map +1 -0
  51. package/cjs/form/file-upload/parts/Trigger.d.ts +7 -0
  52. package/cjs/form/file-upload/parts/Trigger.js +43 -0
  53. package/cjs/form/file-upload/parts/Trigger.js.map +1 -0
  54. package/cjs/form/file-upload/parts/dropzone/Dropzone.d.ts +4 -0
  55. package/cjs/form/file-upload/parts/dropzone/Dropzone.js +106 -0
  56. package/cjs/form/file-upload/parts/dropzone/Dropzone.js.map +1 -0
  57. package/cjs/form/file-upload/parts/dropzone/dropzone.types.d.ts +18 -0
  58. package/cjs/form/file-upload/parts/dropzone/dropzone.types.js +3 -0
  59. package/cjs/form/file-upload/parts/dropzone/dropzone.types.js.map +1 -0
  60. package/cjs/form/file-upload/parts/dropzone/useDropzone.d.ts +13 -0
  61. package/cjs/form/file-upload/parts/dropzone/useDropzone.js +34 -0
  62. package/cjs/form/file-upload/parts/dropzone/useDropzone.js.map +1 -0
  63. package/cjs/form/file-upload/parts/item/Item.d.ts +55 -0
  64. package/cjs/form/file-upload/parts/item/Item.js +79 -0
  65. package/cjs/form/file-upload/parts/item/Item.js.map +1 -0
  66. package/cjs/form/file-upload/parts/item/Item.types.d.ts +5 -0
  67. package/cjs/form/file-upload/parts/item/Item.types.js +3 -0
  68. package/cjs/form/file-upload/parts/item/Item.types.js.map +1 -0
  69. package/cjs/form/file-upload/parts/item/ItemButton.d.ts +12 -0
  70. package/cjs/form/file-upload/parts/item/ItemButton.js +22 -0
  71. package/cjs/form/file-upload/parts/item/ItemButton.js.map +1 -0
  72. package/cjs/form/file-upload/parts/item/ItemIcon.d.ts +9 -0
  73. package/cjs/form/file-upload/parts/item/ItemIcon.js +51 -0
  74. package/cjs/form/file-upload/parts/item/ItemIcon.js.map +1 -0
  75. package/cjs/form/file-upload/parts/item/ItemName.d.ts +9 -0
  76. package/cjs/form/file-upload/parts/item/ItemName.js +32 -0
  77. package/cjs/form/file-upload/parts/item/ItemName.js.map +1 -0
  78. package/cjs/form/file-upload/parts/item/utils/download-file.d.ts +1 -0
  79. package/cjs/form/file-upload/parts/item/utils/download-file.js +13 -0
  80. package/cjs/form/file-upload/parts/item/utils/download-file.js.map +1 -0
  81. package/cjs/form/file-upload/parts/item/utils/file-type-checker.d.ts +2 -0
  82. package/cjs/form/file-upload/parts/item/utils/file-type-checker.js +6 -0
  83. package/cjs/form/file-upload/parts/item/utils/file-type-checker.js.map +1 -0
  84. package/cjs/form/file-upload/parts/item/utils/format-file-size.d.ts +2 -0
  85. package/cjs/form/file-upload/parts/item/utils/format-file-size.js +24 -0
  86. package/cjs/form/file-upload/parts/item/utils/format-file-size.js.map +1 -0
  87. package/cjs/form/file-upload/useFileUpload.d.ts +12 -0
  88. package/cjs/form/file-upload/useFileUpload.js +33 -0
  89. package/cjs/form/file-upload/useFileUpload.js.map +1 -0
  90. package/cjs/form/file-upload/utils/is-accepted-file-type.d.ts +1 -0
  91. package/cjs/form/file-upload/utils/is-accepted-file-type.js +26 -0
  92. package/cjs/form/file-upload/utils/is-accepted-file-type.js.map +1 -0
  93. package/cjs/form/file-upload/utils/is-accepted-size.d.ts +1 -0
  94. package/cjs/form/file-upload/utils/is-accepted-size.js +11 -0
  95. package/cjs/form/file-upload/utils/is-accepted-size.js.map +1 -0
  96. package/cjs/form/file-upload/utils/validate-files.d.ts +8 -0
  97. package/cjs/form/file-upload/utils/validate-files.js +48 -0
  98. package/cjs/form/file-upload/utils/validate-files.js.map +1 -0
  99. package/cjs/index.d.ts +1 -0
  100. package/cjs/index.js +3 -1
  101. package/cjs/index.js.map +1 -1
  102. package/cjs/loader/Loader.d.ts +0 -7
  103. package/cjs/loader/Loader.js.map +1 -1
  104. package/cjs/table/DataCell.d.ts +1 -3
  105. package/cjs/table/DataCell.js.map +1 -1
  106. package/cjs/util/create-context.d.ts +1 -0
  107. package/cjs/util/create-context.js.map +1 -1
  108. package/cjs/util/hooks/useEventListener.d.ts +1 -1
  109. package/cjs/util/hooks/useMergeRefs.d.ts +1 -1
  110. package/esm/form/combobox/ComboboxProvider.js +5 -1
  111. package/esm/form/combobox/ComboboxProvider.js.map +1 -1
  112. package/esm/form/combobox/FilteredOptions/FilteredOptions.js +14 -12
  113. package/esm/form/combobox/FilteredOptions/FilteredOptions.js.map +1 -1
  114. package/esm/form/combobox/FilteredOptions/filtered-options-util.d.ts +3 -3
  115. package/esm/form/combobox/FilteredOptions/filtered-options-util.js +1 -3
  116. package/esm/form/combobox/FilteredOptions/filtered-options-util.js.map +1 -1
  117. package/esm/form/combobox/FilteredOptions/filteredOptionsContext.d.ts +8 -5
  118. package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js +8 -13
  119. package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
  120. package/esm/form/combobox/Input/Input.js +9 -7
  121. package/esm/form/combobox/Input/Input.js.map +1 -1
  122. package/esm/form/combobox/SelectedOptions/SelectedOptions.d.ts +2 -1
  123. package/esm/form/combobox/SelectedOptions/SelectedOptions.js +3 -3
  124. package/esm/form/combobox/SelectedOptions/SelectedOptions.js.map +1 -1
  125. package/esm/form/combobox/SelectedOptions/selectedOptionsContext.d.ts +10 -7
  126. package/esm/form/combobox/SelectedOptions/selectedOptionsContext.js +6 -8
  127. package/esm/form/combobox/SelectedOptions/selectedOptionsContext.js.map +1 -1
  128. package/esm/form/combobox/combobox-utils.d.ts +10 -0
  129. package/esm/form/combobox/combobox-utils.js +22 -0
  130. package/esm/form/combobox/combobox-utils.js.map +1 -0
  131. package/esm/form/combobox/customOptionsContext.d.ts +5 -4
  132. package/esm/form/combobox/customOptionsContext.js +1 -1
  133. package/esm/form/combobox/customOptionsContext.js.map +1 -1
  134. package/esm/form/combobox/types.d.ts +22 -11
  135. package/esm/form/file-upload/FileUpload.context.d.ts +8 -0
  136. package/esm/form/file-upload/FileUpload.context.js +3 -0
  137. package/esm/form/file-upload/FileUpload.context.js.map +1 -0
  138. package/esm/form/file-upload/FileUpload.d.ts +118 -0
  139. package/esm/form/file-upload/FileUpload.js +44 -0
  140. package/esm/form/file-upload/FileUpload.js.map +1 -0
  141. package/esm/form/file-upload/FileUpload.types.d.ts +55 -0
  142. package/esm/form/file-upload/FileUpload.types.js +5 -0
  143. package/esm/form/file-upload/FileUpload.types.js.map +1 -0
  144. package/esm/form/file-upload/i18n/get.d.ts +2 -0
  145. package/esm/form/file-upload/i18n/get.js +34 -0
  146. package/esm/form/file-upload/i18n/get.js.map +1 -0
  147. package/esm/form/file-upload/i18n/i18n.context.d.ts +11 -0
  148. package/esm/form/file-upload/i18n/i18n.context.js +32 -0
  149. package/esm/form/file-upload/i18n/i18n.context.js.map +1 -0
  150. package/esm/form/file-upload/i18n/i18n.types.d.ts +13 -0
  151. package/esm/form/file-upload/i18n/i18n.types.js +2 -0
  152. package/esm/form/file-upload/i18n/i18n.types.js.map +1 -0
  153. package/esm/form/file-upload/i18n/locales/nb.json +20 -0
  154. package/esm/form/file-upload/i18n/merge.d.ts +2 -0
  155. package/esm/form/file-upload/i18n/merge.js +25 -0
  156. package/esm/form/file-upload/i18n/merge.js.map +1 -0
  157. package/esm/form/file-upload/index.d.ts +7 -0
  158. package/esm/form/file-upload/index.js +6 -0
  159. package/esm/form/file-upload/index.js.map +1 -0
  160. package/esm/form/file-upload/parts/Trigger.d.ts +7 -0
  161. package/esm/form/file-upload/parts/Trigger.js +18 -0
  162. package/esm/form/file-upload/parts/Trigger.js.map +1 -0
  163. package/esm/form/file-upload/parts/dropzone/Dropzone.d.ts +4 -0
  164. package/esm/form/file-upload/parts/dropzone/Dropzone.js +78 -0
  165. package/esm/form/file-upload/parts/dropzone/Dropzone.js.map +1 -0
  166. package/esm/form/file-upload/parts/dropzone/dropzone.types.d.ts +18 -0
  167. package/esm/form/file-upload/parts/dropzone/dropzone.types.js +2 -0
  168. package/esm/form/file-upload/parts/dropzone/dropzone.types.js.map +1 -0
  169. package/esm/form/file-upload/parts/dropzone/useDropzone.d.ts +13 -0
  170. package/esm/form/file-upload/parts/dropzone/useDropzone.js +30 -0
  171. package/esm/form/file-upload/parts/dropzone/useDropzone.js.map +1 -0
  172. package/esm/form/file-upload/parts/item/Item.d.ts +55 -0
  173. package/esm/form/file-upload/parts/item/Item.js +50 -0
  174. package/esm/form/file-upload/parts/item/Item.js.map +1 -0
  175. package/esm/form/file-upload/parts/item/Item.types.d.ts +5 -0
  176. package/esm/form/file-upload/parts/item/Item.types.js +2 -0
  177. package/esm/form/file-upload/parts/item/Item.types.js.map +1 -0
  178. package/esm/form/file-upload/parts/item/ItemButton.d.ts +12 -0
  179. package/esm/form/file-upload/parts/item/ItemButton.js +17 -0
  180. package/esm/form/file-upload/parts/item/ItemButton.js.map +1 -0
  181. package/esm/form/file-upload/parts/item/ItemIcon.d.ts +9 -0
  182. package/esm/form/file-upload/parts/item/ItemIcon.js +46 -0
  183. package/esm/form/file-upload/parts/item/ItemIcon.js.map +1 -0
  184. package/esm/form/file-upload/parts/item/ItemName.d.ts +9 -0
  185. package/esm/form/file-upload/parts/item/ItemName.js +27 -0
  186. package/esm/form/file-upload/parts/item/ItemName.js.map +1 -0
  187. package/esm/form/file-upload/parts/item/utils/download-file.d.ts +1 -0
  188. package/esm/form/file-upload/parts/item/utils/download-file.js +9 -0
  189. package/esm/form/file-upload/parts/item/utils/download-file.js.map +1 -0
  190. package/esm/form/file-upload/parts/item/utils/file-type-checker.d.ts +2 -0
  191. package/esm/form/file-upload/parts/item/utils/file-type-checker.js +2 -0
  192. package/esm/form/file-upload/parts/item/utils/file-type-checker.js.map +1 -0
  193. package/esm/form/file-upload/parts/item/utils/format-file-size.d.ts +2 -0
  194. package/esm/form/file-upload/parts/item/utils/format-file-size.js +20 -0
  195. package/esm/form/file-upload/parts/item/utils/format-file-size.js.map +1 -0
  196. package/esm/form/file-upload/useFileUpload.d.ts +12 -0
  197. package/esm/form/file-upload/useFileUpload.js +29 -0
  198. package/esm/form/file-upload/useFileUpload.js.map +1 -0
  199. package/esm/form/file-upload/utils/is-accepted-file-type.d.ts +1 -0
  200. package/esm/form/file-upload/utils/is-accepted-file-type.js +22 -0
  201. package/esm/form/file-upload/utils/is-accepted-file-type.js.map +1 -0
  202. package/esm/form/file-upload/utils/is-accepted-size.d.ts +1 -0
  203. package/esm/form/file-upload/utils/is-accepted-size.js +7 -0
  204. package/esm/form/file-upload/utils/is-accepted-size.js.map +1 -0
  205. package/esm/form/file-upload/utils/validate-files.d.ts +8 -0
  206. package/esm/form/file-upload/utils/validate-files.js +44 -0
  207. package/esm/form/file-upload/utils/validate-files.js.map +1 -0
  208. package/esm/index.d.ts +1 -0
  209. package/esm/index.js +1 -0
  210. package/esm/index.js.map +1 -1
  211. package/esm/loader/Loader.d.ts +0 -7
  212. package/esm/loader/Loader.js.map +1 -1
  213. package/esm/table/DataCell.d.ts +1 -3
  214. package/esm/table/DataCell.js.map +1 -1
  215. package/esm/util/create-context.d.ts +1 -0
  216. package/esm/util/create-context.js.map +1 -1
  217. package/esm/util/hooks/useEventListener.d.ts +1 -1
  218. package/esm/util/hooks/useMergeRefs.d.ts +1 -1
  219. package/package.json +13 -3
  220. package/src/form/combobox/ComboboxProvider.tsx +7 -3
  221. package/src/form/combobox/FilteredOptions/FilteredOptions.tsx +22 -15
  222. package/src/form/combobox/FilteredOptions/filtered-options-util.ts +5 -10
  223. package/src/form/combobox/FilteredOptions/filteredOptionsContext.tsx +19 -29
  224. package/src/form/combobox/Input/Input.tsx +14 -8
  225. package/src/form/combobox/SelectedOptions/SelectedOptions.tsx +8 -5
  226. package/src/form/combobox/SelectedOptions/selectedOptionsContext.tsx +24 -25
  227. package/src/form/combobox/combobox-utils.test.ts +67 -0
  228. package/src/form/combobox/combobox-utils.ts +32 -0
  229. package/src/form/combobox/combobox.stories.tsx +67 -32
  230. package/src/form/combobox/combobox.test.tsx +32 -1
  231. package/src/form/combobox/customOptionsContext.tsx +9 -8
  232. package/src/form/combobox/types.ts +23 -11
  233. package/src/form/file-upload/FileUpload.context.tsx +9 -0
  234. package/src/form/file-upload/FileUpload.tsx +142 -0
  235. package/src/form/file-upload/FileUpload.types.ts +57 -0
  236. package/src/form/file-upload/file-upload-dropzone.stories.tsx +123 -0
  237. package/src/form/file-upload/file-upload-item.stories.tsx +136 -0
  238. package/src/form/file-upload/file-upload.stories.tsx +236 -0
  239. package/src/form/file-upload/i18n/get.ts +48 -0
  240. package/src/form/file-upload/i18n/i18n.context.test.tsx +92 -0
  241. package/src/form/file-upload/i18n/i18n.context.ts +67 -0
  242. package/src/form/file-upload/i18n/i18n.types.ts +20 -0
  243. package/src/form/file-upload/i18n/locales/nb.json +20 -0
  244. package/src/form/file-upload/i18n/merge.ts +35 -0
  245. package/src/form/file-upload/index.ts +21 -0
  246. package/src/form/file-upload/parts/Trigger.tsx +48 -0
  247. package/src/form/file-upload/parts/dropzone/Dropzone.tsx +180 -0
  248. package/src/form/file-upload/parts/dropzone/dropzone.types.ts +22 -0
  249. package/src/form/file-upload/parts/dropzone/useDropzone.ts +43 -0
  250. package/src/form/file-upload/parts/item/Item.tsx +165 -0
  251. package/src/form/file-upload/parts/item/Item.types.ts +6 -0
  252. package/src/form/file-upload/parts/item/ItemButton.tsx +52 -0
  253. package/src/form/file-upload/parts/item/ItemIcon.tsx +74 -0
  254. package/src/form/file-upload/parts/item/ItemName.tsx +58 -0
  255. package/src/form/file-upload/parts/item/utils/download-file.ts +9 -0
  256. package/src/form/file-upload/parts/item/utils/file-type-checker.ts +4 -0
  257. package/src/form/file-upload/parts/item/utils/format-file-size.test.ts +76 -0
  258. package/src/form/file-upload/parts/item/utils/format-file-size.ts +25 -0
  259. package/src/form/file-upload/useFileUpload.ts +54 -0
  260. package/src/form/file-upload/utils/is-accepted-file-type.test.ts +69 -0
  261. package/src/form/file-upload/utils/is-accepted-file-type.ts +25 -0
  262. package/src/form/file-upload/utils/is-accepted-size.test.ts +26 -0
  263. package/src/form/file-upload/utils/is-accepted-size.ts +7 -0
  264. package/src/form/file-upload/utils/validate-files.test.ts +132 -0
  265. package/src/form/file-upload/utils/validate-files.ts +62 -0
  266. package/src/index.ts +14 -0
  267. package/src/internal-header/header.stories.tsx +8 -5
  268. package/src/loader/Loader.tsx +0 -7
  269. package/src/table/DataCell.tsx +1 -6
  270. package/src/util/create-context.tsx +1 -0
  271. package/src/util/hooks/useMergeRefs.ts +1 -1
@@ -43,17 +43,17 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
43
43
 
44
44
  const onEnter = useCallback(
45
45
  (event: React.KeyboardEvent) => {
46
- const isTextInSelectedOptions = (text: string) => {
47
- return selectedOptions.find(
48
- (item) => item.toLocaleLowerCase() === text.toLocaleLowerCase(),
46
+ const isTextInSelectedOptions = (text: string) =>
47
+ selectedOptions.some(
48
+ (option) =>
49
+ option.label.toLocaleLowerCase() === text.toLocaleLowerCase(),
49
50
  );
50
- };
51
51
 
52
52
  if (currentOption) {
53
53
  event.preventDefault();
54
54
  // Selecting a value from the dropdown / FilteredOptions
55
55
  toggleOption(currentOption, event);
56
- if (!isMultiSelect && !isTextInSelectedOptions(currentOption)) {
56
+ if (!isMultiSelect && !isTextInSelectedOptions(currentOption.label)) {
57
57
  toggleIsListOpen(false);
58
58
  }
59
59
  } else if (shouldAutocomplete && isTextInSelectedOptions(value)) {
@@ -64,11 +64,15 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
64
64
  event.preventDefault();
65
65
  // Autocompleting or adding a new value
66
66
  const selectedValue =
67
- allowNewValues && isValueNew ? value : filteredOptions[0];
67
+ allowNewValues && isValueNew
68
+ ? { label: value, value }
69
+ : filteredOptions[0];
68
70
  toggleOption(selectedValue, event);
69
71
  if (
70
72
  !isMultiSelect &&
71
- !isTextInSelectedOptions(filteredOptions[0] || selectedValue)
73
+ !isTextInSelectedOptions(
74
+ filteredOptions[0].label || selectedValue.label,
75
+ )
72
76
  ) {
73
77
  toggleIsListOpen(false);
74
78
  }
@@ -120,7 +124,9 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
120
124
  if (value === "") {
121
125
  const lastSelectedOption =
122
126
  selectedOptions[selectedOptions.length - 1];
123
- removeSelectedOption(lastSelectedOption);
127
+ if (lastSelectedOption) {
128
+ removeSelectedOption(lastSelectedOption);
129
+ }
124
130
  }
125
131
  } else if (e.key === "ArrowDown") {
126
132
  // Check that cursor position is at the end of the input field,
@@ -1,15 +1,16 @@
1
1
  import React from "react";
2
2
  import { Chips } from "../../../chips";
3
3
  import { useInputContext } from "../Input/inputContext";
4
+ import { ComboboxOption } from "../types";
4
5
  import { useSelectedOptionsContext } from "./selectedOptionsContext";
5
6
 
6
7
  interface SelectedOptionsProps {
7
- selectedOptions?: string[];
8
+ selectedOptions?: ComboboxOption[];
8
9
  size?: "medium" | "small";
9
10
  children: React.ReactNode;
10
11
  }
11
12
 
12
- const Option = ({ option }: { option: string }) => {
13
+ const Option = ({ option }: { option: ComboboxOption }) => {
13
14
  const { isMultiSelect, removeSelectedOption } = useSelectedOptionsContext();
14
15
  const { focusInput } = useInputContext();
15
16
 
@@ -21,11 +22,13 @@ const Option = ({ option }: { option: string }) => {
21
22
 
22
23
  if (!isMultiSelect) {
23
24
  return (
24
- <div className="navds-combobox__selected-options--no-bg">{option}</div>
25
+ <div className="navds-combobox__selected-options--no-bg">
26
+ {option.label}
27
+ </div>
25
28
  );
26
29
  }
27
30
 
28
- return <Chips.Removable onClick={onClick}>{option}</Chips.Removable>;
31
+ return <Chips.Removable onClick={onClick}>{option.label}</Chips.Removable>;
29
32
  };
30
33
 
31
34
  const SelectedOptions: React.FC<SelectedOptionsProps> = ({
@@ -37,7 +40,7 @@ const SelectedOptions: React.FC<SelectedOptionsProps> = ({
37
40
  <Chips className="navds-combobox__selected-options" size={size}>
38
41
  {selectedOptions.length
39
42
  ? selectedOptions.map((option, i) => (
40
- <Option key={option + i} option={option} />
43
+ <Option key={option.label + i} option={option} />
41
44
  ))
42
45
  : []}
43
46
  {children}
@@ -7,19 +7,20 @@ import React, {
7
7
  } from "react";
8
8
  import { usePrevious } from "../../../util/hooks";
9
9
  import { useInputContext } from "../Input/inputContext";
10
+ import { isInList } from "../combobox-utils";
10
11
  import { useCustomOptionsContext } from "../customOptionsContext";
11
- import { ComboboxProps, MaxSelected } from "../types";
12
+ import { ComboboxOption, ComboboxProps, MaxSelected } from "../types";
12
13
 
13
14
  type SelectedOptionsContextType = {
14
- addSelectedOption: (option: string) => void;
15
+ addSelectedOption: (option: ComboboxOption) => void;
15
16
  isMultiSelect?: boolean;
16
- removeSelectedOption: (option: string) => void;
17
- prevSelectedOptions?: string[];
18
- selectedOptions: string[];
17
+ removeSelectedOption: (option: ComboboxOption) => void;
18
+ prevSelectedOptions?: ComboboxOption[];
19
+ selectedOptions: ComboboxOption[];
19
20
  maxSelected?: MaxSelected & { isLimitReached: boolean };
20
21
  setSelectedOptions: (any) => void;
21
22
  toggleOption: (
22
- option: string,
23
+ option: ComboboxOption,
23
24
  event: React.KeyboardEvent | React.PointerEvent,
24
25
  ) => void;
25
26
  };
@@ -35,13 +36,8 @@ export const SelectedOptionsProvider = ({
35
36
  children: any;
36
37
  value: Pick<
37
38
  ComboboxProps,
38
- | "allowNewValues"
39
- | "isMultiSelect"
40
- | "options"
41
- | "selectedOptions"
42
- | "onToggleSelected"
43
- | "maxSelected"
44
- >;
39
+ "allowNewValues" | "isMultiSelect" | "onToggleSelected" | "maxSelected"
40
+ > & { options: ComboboxOption[]; selectedOptions?: ComboboxOption[] };
45
41
  }) => {
46
42
  const { clearInput, focusInput } = useInputContext();
47
43
  const {
@@ -58,7 +54,9 @@ export const SelectedOptionsProvider = ({
58
54
  options,
59
55
  maxSelected,
60
56
  } = value;
61
- const [internalSelectedOptions, setSelectedOptions] = useState<string[]>([]);
57
+ const [internalSelectedOptions, setSelectedOptions] = useState<
58
+ ComboboxOption[]
59
+ >([]);
62
60
  const selectedOptions = useMemo(
63
61
  () =>
64
62
  externalSelectedOptions ?? [...customOptions, ...internalSelectedOptions],
@@ -66,10 +64,8 @@ export const SelectedOptionsProvider = ({
66
64
  );
67
65
 
68
66
  const addSelectedOption = useCallback(
69
- (option: string) => {
70
- const isCustomOption = !options
71
- .map((opt) => opt.toLowerCase())
72
- .includes(option?.toLowerCase?.());
67
+ (option: ComboboxOption) => {
68
+ const isCustomOption = !isInList(option, options);
73
69
  if (isCustomOption) {
74
70
  allowNewValues && addCustomOption(option);
75
71
  !isMultiSelect && setSelectedOptions([]);
@@ -82,7 +78,7 @@ export const SelectedOptionsProvider = ({
82
78
  setSelectedOptions([option]);
83
79
  setCustomOptions([]);
84
80
  }
85
- onToggleSelected?.(option, true, isCustomOption);
81
+ onToggleSelected?.(option.value, true, isCustomOption);
86
82
  },
87
83
  [
88
84
  addCustomOption,
@@ -95,8 +91,8 @@ export const SelectedOptionsProvider = ({
95
91
  );
96
92
 
97
93
  const removeSelectedOption = useCallback(
98
- (option: string) => {
99
- const isCustomOption = customOptions.includes(option);
94
+ (option: ComboboxOption) => {
95
+ const isCustomOption = isInList(option, customOptions);
100
96
  if (isCustomOption) {
101
97
  removeCustomOption(option);
102
98
  } else {
@@ -106,14 +102,17 @@ export const SelectedOptionsProvider = ({
106
102
  ),
107
103
  );
108
104
  }
109
- onToggleSelected?.(option, false, isCustomOption);
105
+ onToggleSelected?.(option.value, false, isCustomOption);
110
106
  },
111
107
  [customOptions, onToggleSelected, removeCustomOption],
112
108
  );
113
109
 
114
110
  const toggleOption = useCallback(
115
- (option: string, event: React.KeyboardEvent | React.PointerEvent) => {
116
- if (selectedOptions.includes(option)) {
111
+ (
112
+ option: ComboboxOption,
113
+ event: React.KeyboardEvent | React.PointerEvent,
114
+ ) => {
115
+ if (isInList(option.value, selectedOptions)) {
117
116
  removeSelectedOption(option);
118
117
  } else {
119
118
  addSelectedOption(option);
@@ -130,7 +129,7 @@ export const SelectedOptionsProvider = ({
130
129
  ],
131
130
  );
132
131
 
133
- const prevSelectedOptions = usePrevious<string[]>(selectedOptions);
132
+ const prevSelectedOptions = usePrevious<ComboboxOption[]>(selectedOptions);
134
133
 
135
134
  const isLimitReached =
136
135
  !!maxSelected?.limit && selectedOptions.length >= maxSelected.limit;
@@ -0,0 +1,67 @@
1
+ import {
2
+ isInList,
3
+ mapToComboboxOptionArray,
4
+ toComboboxOption,
5
+ } from "./combobox-utils";
6
+
7
+ const list = [
8
+ { label: "Hjelpemidler", value: "HJE" },
9
+ { label: "Oppfølging", value: "OPP" },
10
+ { label: "Sykepenger", value: "SYK" },
11
+ { label: "Sykemelding", value: "SYM" },
12
+ ];
13
+
14
+ describe("isInList", () => {
15
+ test("finds a string value in a list of ComboboxOptions", () => {
16
+ expect(isInList("Oppfølging", list)).toBe(true);
17
+ expect(isInList("SYM", list)).toBe(true);
18
+ expect(isInList("Arbeidsavklaringspenger", list)).toBe(false);
19
+ expect(isInList("AAP", list)).toBe(false);
20
+ });
21
+
22
+ test("finds a ComboboxOption in a list of ComboboxOptions", () => {
23
+ expect(isInList({ label: "Oppfølging", value: "OPP" }, list)).toBe(true);
24
+ expect(isInList({ label: "Sykemelding", value: "SYM" }, list)).toBe(true);
25
+ expect(
26
+ isInList({ label: "Arbeidsavklaringspenger", value: "AAP" }, list),
27
+ ).toBe(false);
28
+ expect(
29
+ isInList({ label: "Arbeidsavklaringspenger", value: "AAP" }, list),
30
+ ).toBe(false);
31
+ });
32
+
33
+ test("returns false for ComboboxOptions which do not match both label and value", () => {
34
+ expect(isInList({ label: "Oppfølging", value: "SYM" }, list)).toBe(false);
35
+ expect(isInList({ label: "Sykemelding", value: "OPP" }, list)).toBe(false);
36
+ });
37
+ });
38
+
39
+ describe("mapToComboboxOptionArray", () => {
40
+ test("maps an array of strings to an array of ComboboxOptions", () => {
41
+ const stringArray = ["Hjelpemidler", "Oppfølging", "Sykepenger"];
42
+ const comboboxOptions = [
43
+ { label: "Hjelpemidler", value: "Hjelpemidler" },
44
+ { label: "Oppfølging", value: "Oppfølging" },
45
+ { label: "Sykepenger", value: "Sykepenger" },
46
+ ];
47
+ expect(mapToComboboxOptionArray(stringArray)).toEqual(comboboxOptions);
48
+ });
49
+
50
+ test("does not change an array of ComboboxOptions", () => {
51
+ const comboboxOptions = [
52
+ { label: "Hjelpemidler", value: "Hjelpemidler" },
53
+ { label: "Oppfølging", value: "Oppfølging" },
54
+ { label: "Sykepenger", value: "Sykepenger" },
55
+ ];
56
+ expect(mapToComboboxOptionArray(comboboxOptions)).toEqual(comboboxOptions);
57
+ });
58
+ });
59
+
60
+ describe("toComboboxOption", () => {
61
+ test("creates a ComboboxOption from a string", () => {
62
+ expect(toComboboxOption("Hjelpemidler")).toEqual({
63
+ label: "Hjelpemidler",
64
+ value: "Hjelpemidler",
65
+ });
66
+ });
67
+ });
@@ -0,0 +1,32 @@
1
+ import { ComboboxOption } from "./types";
2
+
3
+ /**
4
+ *
5
+ * @param option ComboboxOption will be compared by both label and value, while a string option is checked if it matches either the label or value in the list.
6
+ * @param list
7
+ */
8
+ const isInList = (option: ComboboxOption | string, list: ComboboxOption[]) => {
9
+ if (typeof option === "string") {
10
+ return list.some(
11
+ (listItem) => listItem.label === option || listItem.value === option,
12
+ );
13
+ } else {
14
+ return list.some(
15
+ (listItem) =>
16
+ listItem.label === option.label && listItem.value === option.value,
17
+ );
18
+ }
19
+ };
20
+
21
+ const toComboboxOption = (value: string): ComboboxOption => ({
22
+ label: value,
23
+ value,
24
+ });
25
+
26
+ const mapToComboboxOptionArray = (options?: string[] | ComboboxOption[]) => {
27
+ return options?.map((option: string | ComboboxOption) =>
28
+ typeof option === "string" ? toComboboxOption(option) : option,
29
+ );
30
+ };
31
+
32
+ export { isInList, mapToComboboxOptionArray, toComboboxOption };
@@ -1,6 +1,6 @@
1
1
  import { Meta, StoryFn, StoryObj } from "@storybook/react";
2
2
  import { expect, fn, userEvent, within } from "@storybook/test";
3
- import React, { useId, useMemo, useRef, useState } from "react";
3
+ import React, { useMemo, useRef, useState } from "react";
4
4
  import { Chips } from "../../chips";
5
5
  import { TextField } from "../textfield";
6
6
  import { ComboboxProps, UNSAFE_Combobox } from "./index";
@@ -30,10 +30,10 @@ const options = [
30
30
  "grape fruit",
31
31
  ];
32
32
 
33
- export const Default: StoryFunction = (props) => {
34
- const id = useId();
35
- return <UNSAFE_Combobox {...props} id={id} />;
36
- };
33
+ export const Default: StoryFunction = (props) => (
34
+ <UNSAFE_Combobox {...props} id="combobox" />
35
+ );
36
+
37
37
  Default.args = {
38
38
  options,
39
39
  label: "Hva er dine favorittfrukter?",
@@ -57,10 +57,9 @@ Default.argTypes = {
57
57
  };
58
58
 
59
59
  export const MultiSelect: StoryFunction = (props) => {
60
- const id = useId();
61
60
  return (
62
61
  <UNSAFE_Combobox
63
- id={id}
62
+ id="combobox-with-multiselect"
64
63
  label="Komboboks - velg flere"
65
64
  options={props.options}
66
65
  isMultiSelect={props.isMultiSelect}
@@ -75,11 +74,55 @@ MultiSelect.args = {
75
74
  size: "medium",
76
75
  };
77
76
 
77
+ export const MultiSelectWithComplexOptions: StoryFunction = (props) => {
78
+ const [selectedOptions, setSelectedOptions] = useState<string[]>([]);
79
+ return (
80
+ <>
81
+ <UNSAFE_Combobox
82
+ {...props}
83
+ options={props.options.map((option) => ({
84
+ ...option,
85
+ label: `${option.label} [${option.value}]`,
86
+ }))}
87
+ id="combobox-with-complex-options"
88
+ label="Velg temakoder"
89
+ allowNewValues
90
+ onToggleSelected={(value, isSelected) =>
91
+ isSelected
92
+ ? setSelectedOptions([...selectedOptions, value])
93
+ : setSelectedOptions(selectedOptions.filter((o) => o !== value))
94
+ }
95
+ selectedOptions={selectedOptions}
96
+ />
97
+ </>
98
+ );
99
+ };
100
+
101
+ MultiSelectWithComplexOptions.args = {
102
+ options: [
103
+ { label: "Hjelpemidler", value: "HJE" },
104
+ { label: "Oppfølging", value: "OPP" },
105
+ { label: "Sykepenger", value: "SYK" },
106
+ { label: "Sykemelding", value: "SYM" },
107
+ { label: "Foreldre- og svangerskapspenger", value: "FOR" },
108
+ { label: "Arbeidsavklaringspenger", value: "AAP" },
109
+ { label: "Uføretrygd", value: "UFO" },
110
+ { label: "Pensjon", value: "PEN" },
111
+ { label: "Barnetrygd", value: "BAR" },
112
+ { label: "Kontantstøtte", value: "KON" },
113
+ { label: "Bostøtte", value: "BOS" },
114
+ { label: "Barnebidrag", value: "BBI" },
115
+ { label: "Bidragsforskudd", value: "BIF" },
116
+ { label: "Grunn- og hjelpestønad", value: "GRU" },
117
+ ],
118
+ isMultiSelect: true,
119
+ size: "medium",
120
+ };
121
+
78
122
  export const WithAddNewOptions: StoryFunction = (props) => {
79
- const id = useId();
80
123
  return (
81
124
  <UNSAFE_Combobox
82
- id={id}
125
+ id="combobox-with-add-new-options"
83
126
  label="Komboboks med mulighet for å legge til nye verdier"
84
127
  options={props.options}
85
128
  allowNewValues={props.allowNewValues}
@@ -95,10 +138,9 @@ WithAddNewOptions.args = {
95
138
  };
96
139
 
97
140
  export const MultiSelectWithAddNewOptions: StoryFunction = (props) => {
98
- const id = useId();
99
141
  return (
100
142
  <UNSAFE_Combobox
101
- id={id}
143
+ id="combobox-with-multiselect-and-add-new-options"
102
144
  isMultiSelect={props.isMultiSelect}
103
145
  label="Multiselect komboboks med mulighet for å legge til nye verdier"
104
146
  options={props.options}
@@ -120,7 +162,6 @@ export const MultiSelectWithExternalChips: StoryFn<{
120
162
  }> = (props) => {
121
163
  const [selectedOptions, setSelectedOptions] = useState<string[]>([]);
122
164
  const [value, setValue] = useState("");
123
- const id = useId();
124
165
 
125
166
  const toggleSelected = (option: string) =>
126
167
  selectedOptions.includes(option)
@@ -142,6 +183,7 @@ export const MultiSelectWithExternalChips: StoryFn<{
142
183
  </Chips>
143
184
  )}
144
185
  <UNSAFE_Combobox
186
+ id="combobox-with-external-chips"
145
187
  options={props.options}
146
188
  selectedOptions={selectedOptions}
147
189
  onToggleSelected={(option) => toggleSelected(option)}
@@ -154,7 +196,6 @@ export const MultiSelectWithExternalChips: StoryFn<{
154
196
  }
155
197
  label="Komboboks"
156
198
  size="medium"
157
- id={id}
158
199
  shouldShowSelectedOptions={false}
159
200
  />
160
201
  </>
@@ -166,19 +207,16 @@ MultiSelectWithExternalChips.args = {
166
207
  options,
167
208
  };
168
209
 
169
- export const Loading: StoryFunction = (props) => {
170
- const id = useId();
171
- return (
172
- <UNSAFE_Combobox
173
- id={id}
174
- label="Komboboks (laster)"
175
- options={[]}
176
- selectedOptions={[]}
177
- isListOpen={props.isListOpen}
178
- isLoading={props.isLoading}
179
- />
180
- );
181
- };
210
+ export const Loading: StoryFunction = (props) => (
211
+ <UNSAFE_Combobox
212
+ id="combobox-with-loading-indicator"
213
+ label="Komboboks (laster)"
214
+ options={[]}
215
+ selectedOptions={[]}
216
+ isListOpen={props.isListOpen}
217
+ isLoading={props.isLoading}
218
+ />
219
+ );
182
220
 
183
221
  Loading.args = {
184
222
  isLoading: true,
@@ -186,11 +224,10 @@ Loading.args = {
186
224
  };
187
225
 
188
226
  export const ComboboxWithNoHits: StoryFunction = (props) => {
189
- const id = useId();
190
227
  const [value, setValue] = useState(props.value);
191
228
  return (
192
229
  <UNSAFE_Combobox
193
- id={id}
230
+ id="combobox-with-no-hits"
194
231
  label="Komboboks (uten søketreff)"
195
232
  options={props.options}
196
233
  value={value}
@@ -210,7 +247,6 @@ export const Controlled: StoryFn<{
210
247
  options: string[];
211
248
  initialSelectedOptions: string[];
212
249
  }> = (props) => {
213
- const id = useId();
214
250
  const [value, setValue] = useState(props.value);
215
251
  const [selectedOptions, setSelectedOptions] = useState(
216
252
  props.initialSelectedOptions,
@@ -238,7 +274,7 @@ export const Controlled: StoryFn<{
238
274
  <br />
239
275
  <UNSAFE_Combobox
240
276
  label="Hva er dine favorittfrukter?"
241
- id={id}
277
+ id="combobox-controlled"
242
278
  filteredOptions={filteredOptions}
243
279
  isMultiSelect
244
280
  options={props.options}
@@ -292,7 +328,6 @@ export const ComboboxSizes = () => (
292
328
  );
293
329
 
294
330
  export const MaxSelectedOptions: StoryFunction = () => {
295
- const id = useId();
296
331
  const [value, setValue] = useState<string | undefined>("");
297
332
  const [selectedOptions, setSelectedOptions] = useState([
298
333
  options[0],
@@ -301,7 +336,7 @@ export const MaxSelectedOptions: StoryFunction = () => {
301
336
  const comboboxRef = useRef<HTMLInputElement>(null);
302
337
  return (
303
338
  <UNSAFE_Combobox
304
- id={id}
339
+ id="combobox-with-max-selected-options"
305
340
  label="Komboboks med begrenset antall valg"
306
341
  options={options}
307
342
  maxSelected={{ limit: 2 }}
@@ -3,7 +3,7 @@ import { render, screen } from "@testing-library/react";
3
3
  import userEvent from "@testing-library/user-event";
4
4
  import React, { useId } from "react";
5
5
  import { act } from "react-dom/test-utils";
6
- import { describe, expect, test } from "vitest";
6
+ import { describe, expect, test, vi } from "vitest";
7
7
  import { UNSAFE_Combobox } from "./index";
8
8
 
9
9
  const options = [
@@ -123,4 +123,35 @@ describe("Combobox state-handling", () => {
123
123
  await screen.findByRole("option", { name: "banana" }),
124
124
  ).toBeInTheDocument();
125
125
  });
126
+
127
+ test("Should handle complex options with label and value", async () => {
128
+ const onToggleSelected = vi.fn();
129
+ render(
130
+ <App
131
+ options={[
132
+ { label: "Hjelpemidler [HJE]", value: "HJE" },
133
+ { label: "Oppfølging [OPP]", value: "OPP" },
134
+ { label: "Sykepenger [SYK]", value: "SYK" },
135
+ { label: "Sykemelding [SYM]", value: "SYM" },
136
+ ]}
137
+ onToggleSelected={onToggleSelected}
138
+ />,
139
+ );
140
+
141
+ expect(screen.getByRole("combobox")).toBeInTheDocument();
142
+ const bananaOption = screen.getByRole("option", {
143
+ name: "Hjelpemidler [HJE]",
144
+ selected: false,
145
+ });
146
+ await act(async () => {
147
+ await userEvent.click(bananaOption);
148
+ });
149
+ expect(onToggleSelected).toHaveBeenCalledWith("HJE", true, false);
150
+ expect(
151
+ screen.getByRole("option", {
152
+ name: "Hjelpemidler [HJE]",
153
+ selected: true,
154
+ }),
155
+ ).toBeInTheDocument();
156
+ });
126
157
  });
@@ -1,11 +1,12 @@
1
1
  import React, { createContext, useCallback, useContext, useState } from "react";
2
2
  import { useInputContext } from "./Input/inputContext";
3
+ import { ComboboxOption } from "./types";
3
4
 
4
5
  type CustomOptionsContextType = {
5
- customOptions: string[];
6
- removeCustomOption: (option: string) => void;
7
- addCustomOption: (option: string) => void;
8
- setCustomOptions: React.Dispatch<React.SetStateAction<string[]>>;
6
+ customOptions: ComboboxOption[];
7
+ removeCustomOption: (option: ComboboxOption) => void;
8
+ addCustomOption: (option: ComboboxOption) => void;
9
+ setCustomOptions: React.Dispatch<React.SetStateAction<ComboboxOption[]>>;
9
10
  };
10
11
 
11
12
  const CustomOptionsContext = createContext<CustomOptionsContextType>(
@@ -19,14 +20,14 @@ export const CustomOptionsProvider = ({
19
20
  children: any;
20
21
  value: { isMultiSelect?: boolean };
21
22
  }) => {
22
- const [customOptions, setCustomOptions] = useState<string[]>([]);
23
+ const [customOptions, setCustomOptions] = useState<ComboboxOption[]>([]);
23
24
  const { focusInput } = useInputContext();
24
25
  const { isMultiSelect } = value;
25
26
 
26
27
  const removeCustomOption = useCallback(
27
- (option: string) => {
28
+ (option: ComboboxOption) => {
28
29
  setCustomOptions((prevCustomOptions) =>
29
- prevCustomOptions.filter((o) => o !== option),
30
+ prevCustomOptions.filter((o) => o.label !== option.label),
30
31
  );
31
32
  focusInput();
32
33
  },
@@ -34,7 +35,7 @@ export const CustomOptionsProvider = ({
34
35
  );
35
36
 
36
37
  const addCustomOption = useCallback(
37
- (option: string) => {
38
+ (option: ComboboxOption) => {
38
39
  if (isMultiSelect) {
39
40
  setCustomOptions((prevOptions) => [...prevOptions, option]);
40
41
  } else {
@@ -1,6 +1,21 @@
1
1
  import React, { ChangeEvent, InputHTMLAttributes } from "react";
2
2
  import { FormFieldProps } from "../useFormField";
3
3
 
4
+ /**
5
+ * A more complex version of options for the Combobox.
6
+ * Used for separating the label and the value of the option.
7
+ */
8
+ export type ComboboxOption = {
9
+ /**
10
+ * The label to display in the dropdown list
11
+ */
12
+ label: string;
13
+ /**
14
+ * The programmatic value of the option, for use internally. Will be returned from onToggleSelected.
15
+ */
16
+ value: string;
17
+ };
18
+
4
19
  export type MaxSelected = {
5
20
  /**
6
21
  * The limit for maximum selected options
@@ -20,9 +35,9 @@ export interface ComboboxProps
20
35
  */
21
36
  label: React.ReactNode;
22
37
  /**
23
- * List of options to use for autocompletion.
38
+ * List of options
24
39
  */
25
- options: string[];
40
+ options: string[] | ComboboxOption[];
26
41
  /**
27
42
  * If enabled, adds an option to add the value of the input as an option whenever there are no options matching the value.
28
43
  */
@@ -42,7 +57,7 @@ export interface ComboboxProps
42
57
  * If provided, this overrides the internal search logic in the component.
43
58
  * Useful for e.g. searching on a server or when overriding the search algorithm to search for synonyms or similar.
44
59
  */
45
- filteredOptions?: string[];
60
+ filteredOptions?: string[] | ComboboxOption[];
46
61
  /**
47
62
  * Optionally hide the label visually.
48
63
  * Not recommended, but can be considered for e.g. search fields in the top menu.
@@ -75,7 +90,6 @@ export interface ComboboxProps
75
90
  * Callback function triggered whenever the value of the input field is triggered.
76
91
  *
77
92
  * @param event
78
- * @returns
79
93
  */
80
94
  onChange?: (
81
95
  event: ChangeEvent<HTMLInputElement> | null,
@@ -85,19 +99,17 @@ export interface ComboboxProps
85
99
  * Callback function triggered whenever the input field is cleared.
86
100
  *
87
101
  * @param event
88
- * @returns
89
102
  */
90
103
  onClear?: (event: React.PointerEvent | React.KeyboardEvent) => void;
91
104
  /**
92
105
  * Callback function triggered whenever an option is selected or de-selected.
93
106
  *
94
- * @param option The selected option.
95
- * @param isSelected Whether the option has been selected or unselected.
96
- * @param isCustomOption Whether the option comes from user input, instead of from the list.
97
- * @returns
107
+ * @param option The option value
108
+ * @param isSelected Whether the option has been selected or unselected
109
+ * @param isCustomOption Whether the option comes from user input, instead of from the list
98
110
  */
99
111
  onToggleSelected?: (
100
- option: string,
112
+ option: ComboboxOption["value"],
101
113
  isSelected: boolean,
102
114
  isCustomOption: boolean,
103
115
  ) => void;
@@ -107,7 +119,7 @@ export interface ComboboxProps
107
119
  * Use this prop when controlling the selected state outside for the component,
108
120
  * e.g. for a filter, where options can be toggled elsewhere/programmatically.
109
121
  */
110
- selectedOptions?: string[];
122
+ selectedOptions?: string[] | ComboboxOption[];
111
123
  /**
112
124
  * Options for the maximum number of selected options.
113
125
  */