@transferwise/components 46.130.2 → 46.130.3

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 (236) hide show
  1. package/build/dateInput/DateInput.js +12 -5
  2. package/build/dateInput/DateInput.js.map +1 -1
  3. package/build/dateInput/DateInput.mjs +11 -4
  4. package/build/dateInput/DateInput.mjs.map +1 -1
  5. package/build/expressiveMoneyInput/currencySelector/CurrencySelector.js +16 -8
  6. package/build/expressiveMoneyInput/currencySelector/CurrencySelector.js.map +1 -1
  7. package/build/expressiveMoneyInput/currencySelector/CurrencySelector.mjs +14 -6
  8. package/build/expressiveMoneyInput/currencySelector/CurrencySelector.mjs.map +1 -1
  9. package/build/index.js +12 -7
  10. package/build/index.js.map +1 -1
  11. package/build/index.mjs +9 -3
  12. package/build/index.mjs.map +1 -1
  13. package/build/inputs/{_BottomSheet.js → SelectInput/BottomSheet/SelectInputBottomSheet.js} +7 -7
  14. package/build/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.js.map +1 -0
  15. package/build/inputs/{_BottomSheet.mjs → SelectInput/BottomSheet/SelectInputBottomSheet.mjs} +7 -7
  16. package/build/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.mjs.map +1 -0
  17. package/build/inputs/{_ButtonInput.js → SelectInput/ButtonInput/SelectInputButtonInput.js} +5 -5
  18. package/build/inputs/SelectInput/ButtonInput/SelectInputButtonInput.js.map +1 -0
  19. package/build/inputs/{_ButtonInput.mjs → SelectInput/ButtonInput/SelectInputButtonInput.mjs} +5 -5
  20. package/build/inputs/SelectInput/ButtonInput/SelectInputButtonInput.mjs.map +1 -0
  21. package/build/inputs/SelectInput/ClearButton/SelectInputClearButton.js +26 -0
  22. package/build/inputs/SelectInput/ClearButton/SelectInputClearButton.js.map +1 -0
  23. package/build/inputs/SelectInput/ClearButton/SelectInputClearButton.mjs +24 -0
  24. package/build/inputs/SelectInput/ClearButton/SelectInputClearButton.mjs.map +1 -0
  25. package/build/inputs/SelectInput/DefaultRenderTrigger/SelectInputDefaultRenderTrigger.js +59 -0
  26. package/build/inputs/SelectInput/DefaultRenderTrigger/SelectInputDefaultRenderTrigger.js.map +1 -0
  27. package/build/inputs/SelectInput/DefaultRenderTrigger/SelectInputDefaultRenderTrigger.mjs +56 -0
  28. package/build/inputs/SelectInput/DefaultRenderTrigger/SelectInputDefaultRenderTrigger.mjs.map +1 -0
  29. package/build/inputs/SelectInput/ItemView/GroupItemView/SelectInputGroupItemView.js +50 -0
  30. package/build/inputs/SelectInput/ItemView/GroupItemView/SelectInputGroupItemView.js.map +1 -0
  31. package/build/inputs/SelectInput/ItemView/GroupItemView/SelectInputGroupItemView.mjs +48 -0
  32. package/build/inputs/SelectInput/ItemView/GroupItemView/SelectInputGroupItemView.mjs.map +1 -0
  33. package/build/inputs/SelectInput/ItemView/SelectInputItemView.js +47 -0
  34. package/build/inputs/SelectInput/ItemView/SelectInputItemView.js.map +1 -0
  35. package/build/inputs/SelectInput/ItemView/SelectInputItemView.mjs +45 -0
  36. package/build/inputs/SelectInput/ItemView/SelectInputItemView.mjs.map +1 -0
  37. package/build/inputs/SelectInput/Option/SelectInputOption.js +42 -0
  38. package/build/inputs/SelectInput/Option/SelectInputOption.js.map +1 -0
  39. package/build/inputs/SelectInput/Option/SelectInputOption.mjs +40 -0
  40. package/build/inputs/SelectInput/Option/SelectInputOption.mjs.map +1 -0
  41. package/build/inputs/SelectInput/OptionContent/SelectInputOptionContent.js +40 -0
  42. package/build/inputs/SelectInput/OptionContent/SelectInputOptionContent.js.map +1 -0
  43. package/build/inputs/SelectInput/OptionContent/SelectInputOptionContent.mjs +38 -0
  44. package/build/inputs/SelectInput/OptionContent/SelectInputOptionContent.mjs.map +1 -0
  45. package/build/inputs/SelectInput/Options/OptionsContainer/SelectInputOptionsContainer.js +48 -0
  46. package/build/inputs/SelectInput/Options/OptionsContainer/SelectInputOptionsContainer.js.map +1 -0
  47. package/build/inputs/SelectInput/Options/OptionsContainer/SelectInputOptionsContainer.mjs +46 -0
  48. package/build/inputs/SelectInput/Options/OptionsContainer/SelectInputOptionsContainer.mjs.map +1 -0
  49. package/build/inputs/SelectInput/Options/SelectInputOptions.js +300 -0
  50. package/build/inputs/SelectInput/Options/SelectInputOptions.js.map +1 -0
  51. package/build/inputs/SelectInput/Options/SelectInputOptions.mjs +298 -0
  52. package/build/inputs/SelectInput/Options/SelectInputOptions.mjs.map +1 -0
  53. package/build/inputs/{_Popover.js → SelectInput/Popover/SelectInputPopover.js} +7 -7
  54. package/build/inputs/SelectInput/Popover/SelectInputPopover.js.map +1 -0
  55. package/build/inputs/{_Popover.mjs → SelectInput/Popover/SelectInputPopover.mjs} +7 -7
  56. package/build/inputs/SelectInput/Popover/SelectInputPopover.mjs.map +1 -0
  57. package/build/inputs/SelectInput/SelectInput.contexts.js +29 -0
  58. package/build/inputs/SelectInput/SelectInput.contexts.js.map +1 -0
  59. package/build/inputs/SelectInput/SelectInput.contexts.mjs +24 -0
  60. package/build/inputs/SelectInput/SelectInput.contexts.mjs.map +1 -0
  61. package/build/inputs/SelectInput/SelectInput.js +222 -0
  62. package/build/inputs/SelectInput/SelectInput.js.map +1 -0
  63. package/build/inputs/SelectInput/SelectInput.messages.js.map +1 -0
  64. package/build/inputs/SelectInput/SelectInput.messages.mjs.map +1 -0
  65. package/build/inputs/SelectInput/SelectInput.mjs +216 -0
  66. package/build/inputs/SelectInput/SelectInput.mjs.map +1 -0
  67. package/build/inputs/SelectInput/SelectInput.utils.js +164 -0
  68. package/build/inputs/SelectInput/SelectInput.utils.js.map +1 -0
  69. package/build/inputs/SelectInput/SelectInput.utils.mjs +154 -0
  70. package/build/inputs/SelectInput/SelectInput.utils.mjs.map +1 -0
  71. package/build/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.js +42 -0
  72. package/build/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.js.map +1 -0
  73. package/build/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.mjs +36 -0
  74. package/build/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.mjs.map +1 -0
  75. package/build/main.css +90 -90
  76. package/build/moneyInput/MoneyInput.js +9 -2
  77. package/build/moneyInput/MoneyInput.js.map +1 -1
  78. package/build/moneyInput/MoneyInput.mjs +8 -1
  79. package/build/moneyInput/MoneyInput.mjs.map +1 -1
  80. package/build/phoneNumberInput/PhoneNumberInput.js +10 -3
  81. package/build/phoneNumberInput/PhoneNumberInput.js.map +1 -1
  82. package/build/phoneNumberInput/PhoneNumberInput.mjs +9 -2
  83. package/build/phoneNumberInput/PhoneNumberInput.mjs.map +1 -1
  84. package/build/styles/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.css +96 -0
  85. package/build/styles/inputs/SelectInput/ButtonInput/SelectInputButtonInput.css +16 -0
  86. package/build/styles/inputs/SelectInput/ClearButton/SelectInputClearButton.css +46 -0
  87. package/build/styles/inputs/SelectInput/ItemView/SelectInputItemView.css +16 -0
  88. package/build/styles/inputs/SelectInput/Option/SelectInputOption.css +33 -0
  89. package/build/styles/inputs/SelectInput/OptionContent/SelectInputOptionContent.css +37 -0
  90. package/build/styles/inputs/SelectInput/Options/SelectInputOptions.css +81 -0
  91. package/build/styles/inputs/SelectInput/Popover/SelectInputPopover.css +46 -0
  92. package/build/styles/main.css +90 -90
  93. package/build/types/index.d.ts +1 -1
  94. package/build/types/index.d.ts.map +1 -1
  95. package/build/types/inputs/{_BottomSheet.d.ts → SelectInput/BottomSheet/SelectInputBottomSheet.d.ts} +3 -3
  96. package/build/types/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.d.ts.map +1 -0
  97. package/build/types/inputs/SelectInput/BottomSheet/index.d.ts +3 -0
  98. package/build/types/inputs/SelectInput/BottomSheet/index.d.ts.map +1 -0
  99. package/build/types/inputs/SelectInput/ButtonInput/SelectInputButtonInput.d.ts +5 -0
  100. package/build/types/inputs/SelectInput/ButtonInput/SelectInputButtonInput.d.ts.map +1 -0
  101. package/build/types/inputs/SelectInput/ButtonInput/index.d.ts +3 -0
  102. package/build/types/inputs/SelectInput/ButtonInput/index.d.ts.map +1 -0
  103. package/build/types/inputs/SelectInput/ClearButton/SelectInputClearButton.d.ts +7 -0
  104. package/build/types/inputs/SelectInput/ClearButton/SelectInputClearButton.d.ts.map +1 -0
  105. package/build/types/inputs/SelectInput/ClearButton/index.d.ts +3 -0
  106. package/build/types/inputs/SelectInput/ClearButton/index.d.ts.map +1 -0
  107. package/build/types/inputs/SelectInput/DefaultRenderTrigger/SelectInputDefaultRenderTrigger.d.ts +16 -0
  108. package/build/types/inputs/SelectInput/DefaultRenderTrigger/SelectInputDefaultRenderTrigger.d.ts.map +1 -0
  109. package/build/types/inputs/SelectInput/DefaultRenderTrigger/index.d.ts +2 -0
  110. package/build/types/inputs/SelectInput/DefaultRenderTrigger/index.d.ts.map +1 -0
  111. package/build/types/inputs/SelectInput/ItemView/GroupItemView/SelectInputGroupItemView.d.ts +9 -0
  112. package/build/types/inputs/SelectInput/ItemView/GroupItemView/SelectInputGroupItemView.d.ts.map +1 -0
  113. package/build/types/inputs/SelectInput/ItemView/GroupItemView/index.d.ts +3 -0
  114. package/build/types/inputs/SelectInput/ItemView/GroupItemView/index.d.ts.map +1 -0
  115. package/build/types/inputs/SelectInput/ItemView/SelectInputItemView.d.ts +11 -0
  116. package/build/types/inputs/SelectInput/ItemView/SelectInputItemView.d.ts.map +1 -0
  117. package/build/types/inputs/SelectInput/ItemView/index.d.ts +4 -0
  118. package/build/types/inputs/SelectInput/ItemView/index.d.ts.map +1 -0
  119. package/build/types/inputs/SelectInput/Option/SelectInputOption.d.ts +11 -0
  120. package/build/types/inputs/SelectInput/Option/SelectInputOption.d.ts.map +1 -0
  121. package/build/types/inputs/SelectInput/Option/index.d.ts +3 -0
  122. package/build/types/inputs/SelectInput/Option/index.d.ts.map +1 -0
  123. package/build/types/inputs/SelectInput/OptionContent/SelectInputOptionContent.d.ts +13 -0
  124. package/build/types/inputs/SelectInput/OptionContent/SelectInputOptionContent.d.ts.map +1 -0
  125. package/build/types/inputs/SelectInput/OptionContent/index.d.ts +3 -0
  126. package/build/types/inputs/SelectInput/OptionContent/index.d.ts.map +1 -0
  127. package/build/types/inputs/SelectInput/Options/OptionsContainer/SelectInputOptionsContainer.d.ts +9 -0
  128. package/build/types/inputs/SelectInput/Options/OptionsContainer/SelectInputOptionsContainer.d.ts.map +1 -0
  129. package/build/types/inputs/SelectInput/Options/OptionsContainer/index.d.ts +3 -0
  130. package/build/types/inputs/SelectInput/Options/OptionsContainer/index.d.ts.map +1 -0
  131. package/build/types/inputs/SelectInput/Options/SelectInputOptions.d.ts +21 -0
  132. package/build/types/inputs/SelectInput/Options/SelectInputOptions.d.ts.map +1 -0
  133. package/build/types/inputs/SelectInput/Options/index.d.ts +4 -0
  134. package/build/types/inputs/SelectInput/Options/index.d.ts.map +1 -0
  135. package/build/types/inputs/{_Popover.d.ts → SelectInput/Popover/SelectInputPopover.d.ts} +3 -3
  136. package/build/types/inputs/SelectInput/Popover/SelectInputPopover.d.ts.map +1 -0
  137. package/build/types/inputs/SelectInput/Popover/index.d.ts +3 -0
  138. package/build/types/inputs/SelectInput/Popover/index.d.ts.map +1 -0
  139. package/build/types/inputs/SelectInput/SelectInput.contexts.d.ts +33 -0
  140. package/build/types/inputs/SelectInput/SelectInput.contexts.d.ts.map +1 -0
  141. package/build/types/inputs/SelectInput/SelectInput.d.ts +10 -0
  142. package/build/types/inputs/SelectInput/SelectInput.d.ts.map +1 -0
  143. package/build/types/inputs/SelectInput/SelectInput.messages.d.ts.map +1 -0
  144. package/build/types/inputs/{SelectInput.d.ts → SelectInput/SelectInput.types.d.ts} +12 -38
  145. package/build/types/inputs/SelectInput/SelectInput.types.d.ts.map +1 -0
  146. package/build/types/inputs/SelectInput/SelectInput.utils.d.ts +60 -0
  147. package/build/types/inputs/SelectInput/SelectInput.utils.d.ts.map +1 -0
  148. package/build/types/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.d.ts +12 -0
  149. package/build/types/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.d.ts.map +1 -0
  150. package/build/types/inputs/SelectInput/TriggerButton/index.d.ts +3 -0
  151. package/build/types/inputs/SelectInput/TriggerButton/index.d.ts.map +1 -0
  152. package/build/types/inputs/SelectInput/components.d.ts +10 -0
  153. package/build/types/inputs/SelectInput/components.d.ts.map +1 -0
  154. package/build/types/inputs/SelectInput/index.d.ts +10 -0
  155. package/build/types/inputs/SelectInput/index.d.ts.map +1 -0
  156. package/package.json +1 -1
  157. package/src/index.ts +0 -1
  158. package/src/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.css +96 -0
  159. package/src/inputs/{_BottomSheet.tsx → SelectInput/BottomSheet/SelectInputBottomSheet.tsx} +7 -7
  160. package/src/inputs/SelectInput/BottomSheet/index.ts +2 -0
  161. package/src/inputs/SelectInput/ButtonInput/SelectInputButtonInput.css +16 -0
  162. package/src/inputs/{_ButtonInput.tsx → SelectInput/ButtonInput/SelectInputButtonInput.tsx} +5 -5
  163. package/src/inputs/SelectInput/ButtonInput/index.ts +2 -0
  164. package/src/inputs/SelectInput/ClearButton/SelectInputClearButton.css +46 -0
  165. package/src/inputs/SelectInput/ClearButton/SelectInputClearButton.less +39 -0
  166. package/src/inputs/SelectInput/ClearButton/SelectInputClearButton.tsx +27 -0
  167. package/src/inputs/SelectInput/ClearButton/index.ts +2 -0
  168. package/src/inputs/SelectInput/DefaultRenderTrigger/SelectInputDefaultRenderTrigger.tsx +74 -0
  169. package/src/inputs/SelectInput/DefaultRenderTrigger/index.ts +5 -0
  170. package/src/inputs/SelectInput/ItemView/GroupItemView/SelectInputGroupItemView.tsx +61 -0
  171. package/src/inputs/SelectInput/ItemView/GroupItemView/index.ts +2 -0
  172. package/src/inputs/SelectInput/ItemView/SelectInputItemView.css +16 -0
  173. package/src/inputs/SelectInput/ItemView/SelectInputItemView.less +17 -0
  174. package/src/inputs/SelectInput/ItemView/SelectInputItemView.tsx +48 -0
  175. package/src/inputs/SelectInput/ItemView/index.ts +3 -0
  176. package/src/inputs/SelectInput/Option/SelectInputOption.css +33 -0
  177. package/src/inputs/SelectInput/Option/SelectInputOption.less +32 -0
  178. package/src/inputs/SelectInput/Option/SelectInputOption.tsx +57 -0
  179. package/src/inputs/SelectInput/Option/index.ts +2 -0
  180. package/src/inputs/SelectInput/OptionContent/SelectInputOptionContent.css +37 -0
  181. package/src/inputs/SelectInput/OptionContent/SelectInputOptionContent.less +38 -0
  182. package/src/inputs/SelectInput/OptionContent/SelectInputOptionContent.tsx +72 -0
  183. package/src/inputs/SelectInput/OptionContent/index.ts +2 -0
  184. package/src/inputs/SelectInput/Options/OptionsContainer/SelectInputOptionsContainer.tsx +59 -0
  185. package/src/inputs/SelectInput/Options/OptionsContainer/index.ts +2 -0
  186. package/src/inputs/SelectInput/Options/SelectInputOptions.css +81 -0
  187. package/src/inputs/SelectInput/Options/SelectInputOptions.less +77 -0
  188. package/src/inputs/SelectInput/Options/SelectInputOptions.tsx +411 -0
  189. package/src/inputs/SelectInput/Options/index.ts +3 -0
  190. package/src/inputs/SelectInput/Popover/SelectInputPopover.css +46 -0
  191. package/src/inputs/{_Popover.tsx → SelectInput/Popover/SelectInputPopover.tsx} +7 -7
  192. package/src/inputs/SelectInput/Popover/index.ts +2 -0
  193. package/src/inputs/SelectInput/SelectInput.contexts.tsx +40 -0
  194. package/src/inputs/SelectInput/SelectInput.less +22 -0
  195. package/src/inputs/{SelectInput.test.tsx → SelectInput/SelectInput.test.tsx} +9 -11
  196. package/src/inputs/SelectInput/SelectInput.tsx +257 -0
  197. package/src/inputs/SelectInput/SelectInput.types.ts +113 -0
  198. package/src/inputs/SelectInput/SelectInput.utils.ts +205 -0
  199. package/src/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.tsx +36 -0
  200. package/src/inputs/SelectInput/TriggerButton/index.ts +5 -0
  201. package/src/inputs/{SelectInput.docs.mdx → SelectInput/_stories/SelectInput.docs.mdx} +0 -1
  202. package/src/inputs/{SelectInput.story.tsx → SelectInput/_stories/SelectInput.story.tsx} +11 -8
  203. package/src/inputs/{SelectInput.test.story.tsx → SelectInput/_stories/SelectInput.test.story.tsx} +6 -10
  204. package/src/inputs/SelectInput/components.ts +10 -0
  205. package/src/inputs/SelectInput/index.ts +12 -0
  206. package/src/main.css +90 -90
  207. package/src/main.less +1 -1
  208. package/build/inputs/SelectInput.js +0 -890
  209. package/build/inputs/SelectInput.js.map +0 -1
  210. package/build/inputs/SelectInput.messages.js.map +0 -1
  211. package/build/inputs/SelectInput.messages.mjs.map +0 -1
  212. package/build/inputs/SelectInput.mjs +0 -881
  213. package/build/inputs/SelectInput.mjs.map +0 -1
  214. package/build/inputs/_BottomSheet.js.map +0 -1
  215. package/build/inputs/_BottomSheet.mjs.map +0 -1
  216. package/build/inputs/_ButtonInput.js.map +0 -1
  217. package/build/inputs/_ButtonInput.mjs.map +0 -1
  218. package/build/inputs/_Popover.js.map +0 -1
  219. package/build/inputs/_Popover.mjs.map +0 -1
  220. package/build/types/inputs/SelectInput.d.ts.map +0 -1
  221. package/build/types/inputs/SelectInput.messages.d.ts.map +0 -1
  222. package/build/types/inputs/_BottomSheet.d.ts.map +0 -1
  223. package/build/types/inputs/_ButtonInput.d.ts +0 -5
  224. package/build/types/inputs/_ButtonInput.d.ts.map +0 -1
  225. package/build/types/inputs/_Popover.d.ts.map +0 -1
  226. package/src/inputs/SelectInput.less +0 -219
  227. package/src/inputs/SelectInput.tsx +0 -1269
  228. package/build/inputs/{SelectInput.messages.js → SelectInput/SelectInput.messages.js} +0 -0
  229. package/build/inputs/{SelectInput.messages.mjs → SelectInput/SelectInput.messages.mjs} +0 -0
  230. package/build/styles/inputs/{SelectInput.css → SelectInput/SelectInput.css} +90 -90
  231. package/build/types/inputs/{SelectInput.messages.d.ts → SelectInput/SelectInput.messages.d.ts} +0 -0
  232. package/src/inputs/{_BottomSheet.less → SelectInput/BottomSheet/SelectInputBottomSheet.less} +0 -0
  233. package/src/inputs/{_ButtonInput.less → SelectInput/ButtonInput/SelectInputButtonInput.less} +0 -0
  234. package/src/inputs/{_Popover.less → SelectInput/Popover/SelectInputPopover.less} +0 -0
  235. package/src/inputs/{SelectInput.css → SelectInput/SelectInput.css} +90 -90
  236. /package/src/inputs/{SelectInput.messages.ts → SelectInput/SelectInput.messages.ts} +0 -0
@@ -1,881 +0,0 @@
1
- import { Listbox, ListboxOptions, ListboxButton, ListboxOption } from '@headlessui/react';
2
- import { CrossCircle, ChevronDown, Cross, Check } from '@transferwise/icons';
3
- import { clsx } from 'clsx';
4
- import mergeProps from 'merge-props';
5
- import { useState, useRef, useEffect, useDeferredValue, useContext, useMemo, useId, createContext, forwardRef } from 'react';
6
- import { useIntl } from 'react-intl';
7
- import { Virtualizer } from 'virtua';
8
- import { useEffectEvent } from '../common/hooks/useEffectEvent.mjs';
9
- import { useScreenSize } from '../common/hooks/useScreenSize.mjs';
10
- import { PolymorphicWithOverrides } from '../common/polymorphicWithOverrides/PolymorphicWithOverrides.mjs';
11
- import { Breakpoint } from '../common/propsValues/breakpoint.mjs';
12
- import messages$1 from '../dateLookup/dateTrigger/DateTrigger.messages.mjs';
13
- import { BottomSheet } from './_BottomSheet.mjs';
14
- import { ButtonInput } from './_ButtonInput.mjs';
15
- import { Popover } from './_Popover.mjs';
16
- import { useInputAttributes } from './contexts.mjs';
17
- import { InputGroup } from './InputGroup.mjs';
18
- import { SearchInput } from './SearchInput.mjs';
19
- import messages from './SelectInput.messages.mjs';
20
- import Header from '../header/Header.mjs';
21
- import Section from '../section/Section.mjs';
22
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
23
-
24
- const MAX_ITEMS_WITHOUT_VIRTUALIZATION = 50;
25
- function searchableString(value) {
26
- return value.trim().replace(/\s+/gu, ' ')
27
- // NFD converts an Å to A + ̊ (and other special characters)
28
- .normalize('NFD')
29
- // and then this replaces the ̊ with nothing (and other special characters)
30
- .replace(/[\u0300-\u036f]/g, '').toLowerCase();
31
- }
32
- function inferSearchableStrings(value) {
33
- if (typeof value === 'string') {
34
- return [searchableString(value)];
35
- }
36
- if (typeof value === 'object' && value != null) {
37
- return Object.values(value).filter(innerValue => typeof innerValue === 'string').map(innerValue => searchableString(innerValue));
38
- }
39
- return [];
40
- }
41
- function dedupeSelectInputOptionItem(item, existingValues, compareValues) {
42
- const isDuplicate = compareValues ? Array.from(existingValues).some(existingValue => compareValues(item.value, existingValue)) : existingValues.has(item.value);
43
- if (!isDuplicate) {
44
- existingValues.add(item.value);
45
- return item;
46
- }
47
- return {
48
- ...item,
49
- value: undefined
50
- };
51
- }
52
- /**
53
- * Sets the `value` of duplicate option items to `undefined`, hiding them when
54
- * rendered. Indexes are kept intact within groups to preserve the active item
55
- * between filter changes when possible.
56
- */
57
- function dedupeSelectInputItems(items, compareValues) {
58
- const existingValues = new Set();
59
- return items.map(item => {
60
- switch (item.type) {
61
- case 'option':
62
- {
63
- return dedupeSelectInputOptionItem(item, existingValues, compareValues);
64
- }
65
- case 'group':
66
- {
67
- return {
68
- ...item,
69
- options: item.options.map(option => dedupeSelectInputOptionItem(option, existingValues, compareValues))
70
- };
71
- }
72
- }
73
- return item;
74
- });
75
- }
76
- function selectInputOptionItemIncludesNeedle(item, needle) {
77
- return inferSearchableStrings(item.filterMatchers ?? item.value).some(haystack => haystack.includes(needle));
78
- }
79
- function filterSelectInputItems(items, predicate) {
80
- return items.filter(item => {
81
- switch (item.type) {
82
- case 'option':
83
- {
84
- return predicate(item);
85
- }
86
- case 'group':
87
- {
88
- return item.options.some(option => predicate(option));
89
- }
90
- }
91
- return false;
92
- });
93
- }
94
- /**
95
- * Flattens and sorts filtered options using the provided comparator.
96
- * Extracts all options from groups, filters out undefined values (deduplicated items),
97
- * sorts them, and returns as a flat list of option items.
98
- */
99
- function sortSelectInputItems(items, compareFn, searchQuery) {
100
- const flattenedOption = items.flatMap(item => {
101
- if (item.type === 'option') {
102
- return item.value !== undefined ? [item] : [];
103
- }
104
- if (item.type === 'group') {
105
- return item.options.filter(option => option.value !== undefined);
106
- }
107
- return [];
108
- });
109
- // eslint-disable-next-line functional/immutable-data
110
- return flattenedOption.sort((a, b) => compareFn(a, b, searchQuery));
111
- }
112
- /**
113
- * A prebuilt sort function for `sortFilteredOptions` that sorts options by relevance to the search query.
114
- * Prioritizes: exact matches > starts with > contains > alphabetical.
115
- *
116
- * @param getLabel - Function to extract the label string from the option value. Defaults to using `title` property.
117
- *
118
- * @example
119
- * ```tsx
120
- * <SelectInput
121
- * filterable
122
- * sortFilteredOptions={sortByRelevance((value) => value.name)}
123
- * // ...
124
- * />
125
- * ```
126
- */
127
- function sortByRelevance(getLabel = value => value.title) {
128
- return (a, b, searchQuery) => {
129
- const normalizedQuery = searchQuery.toLowerCase();
130
- const labelA = getLabel(a.value).toLowerCase();
131
- const labelB = getLabel(b.value).toLowerCase();
132
- // Prioritize exact matches
133
- const aExactMatch = labelA === normalizedQuery;
134
- const bExactMatch = labelB === normalizedQuery;
135
- if (aExactMatch && !bExactMatch) return -1;
136
- if (!aExactMatch && bExactMatch) return 1;
137
- // Then prioritize options where label starts with the search query
138
- const aStartsWith = labelA.startsWith(normalizedQuery);
139
- const bStartsWith = labelB.startsWith(normalizedQuery);
140
- if (aStartsWith && !bStartsWith) return -1;
141
- if (!aStartsWith && bStartsWith) return 1;
142
- // Then prioritize options where label contains the search query
143
- const aContains = labelA.includes(normalizedQuery);
144
- const bContains = labelB.includes(normalizedQuery);
145
- if (aContains && !bContains) return -1;
146
- if (!aContains && bContains) return 1;
147
- // Finally sort alphabetically
148
- return labelA.localeCompare(labelB);
149
- };
150
- }
151
- const defaultRenderTrigger = ({
152
- content,
153
- placeholderShown,
154
- clear,
155
- disabled,
156
- size,
157
- className
158
- }) => /*#__PURE__*/jsx(InputGroup, {
159
- addonEnd: {
160
- content: /*#__PURE__*/jsxs("span", {
161
- className: clsx('np-select-input-addon-container', disabled && 'disabled'),
162
- children: [clear != null && !placeholderShown ? /*#__PURE__*/jsxs(Fragment, {
163
- children: [/*#__PURE__*/jsx(SelectInputClearButton, {
164
- onClick: event => {
165
- event.preventDefault();
166
- clear();
167
- }
168
- }), /*#__PURE__*/jsx("span", {
169
- className: "np-select-input-addon-separator"
170
- })]
171
- }) : null, /*#__PURE__*/jsx("span", {
172
- className: "np-select-input-addon",
173
- children: /*#__PURE__*/jsx(ChevronDown, {
174
- size: 16
175
- })
176
- })]
177
- }),
178
- initialContentWidth: 24 + 4,
179
- padding: 'sm'
180
- },
181
- disabled: disabled,
182
- className: className,
183
- children: /*#__PURE__*/jsx(SelectInputTriggerButton, {
184
- as: ButtonInput,
185
- size: size,
186
- children: /*#__PURE__*/jsx("span", {
187
- className: clsx('np-select-input-content', placeholderShown && 'np-select-input-placeholder'),
188
- children: content
189
- })
190
- })
191
- });
192
- function SelectInputClearButton({
193
- className,
194
- onClick
195
- }) {
196
- const intl = useIntl();
197
- return /*#__PURE__*/jsx("button", {
198
- type: "button",
199
- "aria-label": intl.formatMessage(messages$1.ariaLabel),
200
- className: clsx(className, 'np-select-input-addon np-select-input-addon--interactive'),
201
- onClick: onClick,
202
- children: /*#__PURE__*/jsx(Cross, {
203
- size: 16
204
- })
205
- });
206
- }
207
- const noop = () => {};
208
- function SelectInput({
209
- id: idProp,
210
- parentId,
211
- name,
212
- multiple,
213
- placeholder,
214
- autocomplete,
215
- items,
216
- defaultValue,
217
- value: controlledValue,
218
- compareValues,
219
- renderValue = String,
220
- renderFooter,
221
- renderTrigger = defaultRenderTrigger,
222
- filterable,
223
- filterPlaceholder,
224
- sortFilteredOptions,
225
- disabled,
226
- size = 'md',
227
- className,
228
- UNSAFE_triggerButtonProps,
229
- triggerRef: externalTriggerRef,
230
- onFilterChange = noop,
231
- onChange,
232
- onOpen,
233
- onClose,
234
- onClear
235
- }) {
236
- const inputAttributes = useInputAttributes({
237
- nonLabelable: true
238
- });
239
- const id = idProp ?? inputAttributes.id;
240
- const [open, setOpen] = useState(false);
241
- const initialized = useRef(false);
242
- const handleClose = useEffectEvent(onClose ?? (() => {}));
243
- const handleOpen = useEffectEvent(onOpen ?? (() => {}));
244
- useEffect(() => {
245
- if (initialized.current) {
246
- if (open) {
247
- handleOpen?.();
248
- } else {
249
- handleClose?.();
250
- }
251
- } else {
252
- initialized.current = true;
253
- }
254
- }, [handleClose, handleOpen, open]);
255
- const [filterQuery, _setFilterQuery] = useState('');
256
- const deferredFilterQuery = useDeferredValue(filterQuery);
257
- const setFilterQuery = useEffectEvent(query => {
258
- _setFilterQuery(query);
259
- if (query !== filterQuery) {
260
- onFilterChange({
261
- query,
262
- queryNormalized: query ? searchableString(query) : null
263
- });
264
- }
265
- });
266
- const internalTriggerRef = useRef(null);
267
- const screenSm = useScreenSize(Breakpoint.SMALL);
268
- const OptionsOverlay = screenSm ? Popover : BottomSheet;
269
- const searchInputRef = useRef(null);
270
- const listboxRef = useRef(null);
271
- const controllerRef = filterable ? searchInputRef : listboxRef;
272
- /**
273
- * Attempts to resolve the `listbox` label
274
- * @see https://storybook.wise.design/?path=/docs/forms-selectinput-accessibility--docs#labelling
275
- */
276
- const getListBoxLabelProps = () => {
277
- if (UNSAFE_triggerButtonProps?.['aria-label']) {
278
- return {
279
- listBoxLabel: UNSAFE_triggerButtonProps['aria-label']
280
- };
281
- }
282
- if (UNSAFE_triggerButtonProps?.['aria-labelledby']) {
283
- return {
284
- listBoxLabelledBy: UNSAFE_triggerButtonProps['aria-labelledby']
285
- };
286
- }
287
- if (inputAttributes['aria-labelledby']) {
288
- return {
289
- listBoxLabelledBy: inputAttributes['aria-labelledby']
290
- };
291
- }
292
- return {};
293
- };
294
- return /*#__PURE__*/jsx(Listbox, {
295
- name: name,
296
- multiple: multiple,
297
- defaultValue: defaultValue,
298
- value: controlledValue,
299
- by: compareValues,
300
- disabled: disabled,
301
- onChange: value => {
302
- if (!multiple) {
303
- setOpen(false);
304
- }
305
- onChange?.(value);
306
- },
307
- children: ({
308
- disabled: uiDisabled,
309
- value
310
- }) => {
311
- const placeholderShown = multiple && Array.isArray(value) ? value.length === 0 : value == null;
312
- return /*#__PURE__*/jsx(OptionsOverlay, {
313
- placement: "bottom-start",
314
- open: open,
315
- renderTrigger: ({
316
- ref,
317
- getInteractionProps
318
- }) => /*#__PURE__*/jsx(SelectInputTriggerButtonPropsContext.Provider, {
319
- // eslint-disable-next-line react/jsx-no-constructed-context-values
320
- value: {
321
- ref: node => {
322
- ref(node);
323
- if (externalTriggerRef) {
324
- // eslint-disable-next-line no-param-reassign
325
- externalTriggerRef.current = node;
326
- } else {
327
- internalTriggerRef.current = node;
328
- }
329
- },
330
- ...inputAttributes,
331
- ...UNSAFE_triggerButtonProps,
332
- id,
333
- ...mergeProps({
334
- onClick: () => {
335
- setOpen(prev => !prev);
336
- },
337
- onKeyDown: event => {
338
- if (event.key === ' ' || event.key === 'Enter' || event.key === 'ArrowDown' || event.key === 'ArrowUp') {
339
- setOpen(prev => !prev);
340
- }
341
- }
342
- }, getInteractionProps())
343
- },
344
- children: renderTrigger({
345
- content: !placeholderShown ? /*#__PURE__*/jsx(SelectInputOptionContentWithinTriggerContext.Provider, {
346
- value: true,
347
- children: multiple && Array.isArray(value) ? value.map(option => renderValue(option, true)).filter(node => node != null).join(', ') : renderValue(value, true)
348
- }) : placeholder,
349
- placeholderShown,
350
- clear: onClear != null ? () => {
351
- onClear();
352
- (externalTriggerRef?.current ?? internalTriggerRef.current)?.focus({
353
- preventScroll: true
354
- });
355
- } : undefined,
356
- disabled: uiDisabled,
357
- size,
358
- className
359
- })
360
- }),
361
- initialFocusRef: controllerRef,
362
- size: filterable ? 'lg' : 'md',
363
- padding: "none",
364
- onClose: () => {
365
- setOpen(false);
366
- },
367
- onCloseEnd: () => {
368
- setFilterQuery('');
369
- },
370
- children: /*#__PURE__*/jsx(SelectInputOptions, {
371
- id: id ? `${id}Search` : undefined,
372
- parentId: parentId,
373
- items: items,
374
- compareValues: compareValues,
375
- renderValue: renderValue,
376
- renderFooter: renderFooter,
377
- filterable: filterable,
378
- filterPlaceholder: filterPlaceholder,
379
- sortFilteredOptions: sortFilteredOptions,
380
- searchInputRef: searchInputRef,
381
- listboxRef: listboxRef,
382
- filterQuery: deferredFilterQuery,
383
- autocomplete: autocomplete,
384
- name: name,
385
- onFilterChange: setFilterQuery,
386
- onAutocompleteSelect: matchedValue => {
387
- onChange?.(matchedValue);
388
- if (!multiple) {
389
- setOpen(false);
390
- }
391
- },
392
- ...getListBoxLabelProps()
393
- })
394
- });
395
- }
396
- });
397
- }
398
- SelectInput.sortByRelevance = sortByRelevance;
399
- const SelectInputTriggerButtonPropsContext = /*#__PURE__*/createContext({});
400
- function SelectInputTriggerButton({
401
- as = 'button',
402
- ...restProps
403
- }) {
404
- const {
405
- ref,
406
- onClick,
407
- onKeyDown,
408
- ...interactionProps
409
- } = useContext(SelectInputTriggerButtonPropsContext);
410
- return /*#__PURE__*/jsx(ListboxButton, {
411
- ref: ref,
412
- as: PolymorphicWithOverrides,
413
- role: "combobox",
414
- __overrides: {
415
- as,
416
- ...interactionProps
417
- },
418
- ...mergeProps({
419
- onClick,
420
- onKeyDown
421
- }, restProps)
422
- });
423
- }
424
- const SelectInputOptionsContainer = /*#__PURE__*/forwardRef(function SelectInputOptionsContainer({
425
- 'aria-orientation': ariaOrientation,
426
- 'aria-activedescendant': ariaActiveDescendant,
427
- role,
428
- tabIndex,
429
- onAriaActiveDescendantChange,
430
- onKeyDown,
431
- ...restProps
432
- }, ref) {
433
- const handleAriaActiveDescendantChange = useEffectEvent(onAriaActiveDescendantChange);
434
- useEffect(() => {
435
- handleAriaActiveDescendantChange(ariaActiveDescendant);
436
- }, [ariaActiveDescendant, handleAriaActiveDescendantChange]);
437
- return /*#__PURE__*/jsx("div", {
438
- ref: ref,
439
- role: "none",
440
- onKeyDown: event => {
441
- // Prevent confirmation close without an active item
442
- if (event.key === 'Enter' && ariaActiveDescendant == null) {
443
- return;
444
- }
445
- // Required to make ListBox focusable
446
- if (event.key === 'Tab') {
447
- return;
448
- }
449
- // Prevent absorbing Escape early
450
- if (event.key === 'Escape') {
451
- onKeyDown?.({
452
- ...event,
453
- preventDefault: () => {},
454
- stopPropagation: () => {}
455
- });
456
- return;
457
- }
458
- onKeyDown?.(event);
459
- },
460
- ...restProps
461
- });
462
- });
463
- function SelectInputOptions({
464
- id,
465
- parentId,
466
- items,
467
- compareValues: compareValuesProp,
468
- renderValue = String,
469
- renderFooter,
470
- filterable = false,
471
- filterPlaceholder,
472
- sortFilteredOptions,
473
- searchInputRef,
474
- listboxRef,
475
- filterQuery,
476
- onFilterChange,
477
- listBoxLabel,
478
- listBoxLabelledBy,
479
- autocomplete,
480
- name,
481
- onAutocompleteSelect
482
- }) {
483
- const intl = useIntl();
484
- const virtualiserHandlerRef = useRef(null);
485
- const controllerRef = filterable ? searchInputRef : listboxRef;
486
- const [initialRender, setInitialRender] = useState(true);
487
- const needle = useMemo(() => {
488
- if (filterable) {
489
- return filterQuery ? searchableString(filterQuery) : null;
490
- }
491
- return undefined;
492
- }, [filterQuery, filterable]);
493
- useEffect(() => {
494
- if (needle) {
495
- // Ensure having an active option while filtering.
496
- // Without `requestAnimationFrame` upon which React depends for scheduling
497
- // updates, the active status would only show for a split second and then
498
- // disappear inadvertently.
499
- requestAnimationFrame(() => {
500
- if (controllerRef.current != null && !controllerRef.current.hasAttribute('aria-activedescendant')) {
501
- // Activate first option via synthetic key press
502
- controllerRef.current.dispatchEvent(new KeyboardEvent('keydown', {
503
- key: 'Home',
504
- bubbles: true
505
- }));
506
- }
507
- });
508
- }
509
- }, [controllerRef, needle]);
510
- const compareValues = useMemo(() => {
511
- if (!compareValuesProp) {
512
- return undefined;
513
- }
514
- if (typeof compareValuesProp === 'function') {
515
- return (a, b) => compareValuesProp(a, b);
516
- }
517
- const key = compareValuesProp;
518
- return (a, b) => {
519
- if (typeof a === 'object' && a != null && typeof b === 'object' && b != null) {
520
- return a[key] === b[key];
521
- }
522
- return a === b;
523
- };
524
- }, [compareValuesProp]);
525
- const filteredItems = useMemo(() => {
526
- if (needle == null) {
527
- return items;
528
- }
529
- const dedupedItems = dedupeSelectInputItems(items, compareValues);
530
- if (sortFilteredOptions) {
531
- // When sorting, filter out non-matching items completely to avoid ghost items
532
- const filtered = dedupedItems.map(item => {
533
- if (item.type === 'option') {
534
- return selectInputOptionItemIncludesNeedle(item, needle) ? item : {
535
- ...item,
536
- value: undefined
537
- };
538
- }
539
- if (item.type === 'group') {
540
- return {
541
- ...item,
542
- options: item.options.map(option => selectInputOptionItemIncludesNeedle(option, needle) ? option : {
543
- ...option,
544
- value: undefined
545
- })
546
- };
547
- }
548
- return item;
549
- });
550
- return sortSelectInputItems(filtered, sortFilteredOptions, filterQuery);
551
- }
552
- return filterSelectInputItems(dedupedItems, item => selectInputOptionItemIncludesNeedle(item, needle));
553
- // eslint-disable-next-line react-hooks/exhaustive-deps
554
- }, [needle, items, compareValues]);
555
- const resultsEmpty = needle != null && filteredItems.length === 0;
556
- const virtualized = filteredItems.length > MAX_ITEMS_WITHOUT_VIRTUALIZATION;
557
- // Items shown once shall be kept mounted until the needle changes, otherwise
558
- // the scroll position may jump around inadvertently. Pattern adopted from:
559
- // https://inokawa.github.io/virtua/?path=/story/advanced-keep-offscreen-items--append-only
560
- const [mountedIndexes, setMountedIndexes] = useState([]);
561
- const prevNeedleRef = useRef(needle);
562
- useEffect(() => {
563
- const needleChanged = prevNeedleRef.current !== needle;
564
- prevNeedleRef.current = needle;
565
- if (needleChanged) {
566
- // Reset mounted indexes when search changes to avoid stale scroll positions
567
- setMountedIndexes([]);
568
- return;
569
- }
570
- // Ensure the 'End' key works as intended by keeping the last item mounted.
571
- // Skipped on needle change to prevent auto-scrolling on search.
572
- if (filteredItems.length > 0) {
573
- setMountedIndexes(prevMountedIndexes => {
574
- const indexes = new Set(prevMountedIndexes);
575
- indexes.add(filteredItems.length - 1);
576
- return [...indexes]; // Sorting is redundant by nature here
577
- });
578
- }
579
- }, [needle, filteredItems.length]);
580
- const listboxContainerRef = useRef(null);
581
- useEffect(() => {
582
- if (listboxContainerRef.current != null) {
583
- listboxContainerRef.current.style.setProperty('--initial-height', `${listboxContainerRef.current.offsetHeight}px`);
584
- }
585
- }, []);
586
- useEffect(() => {
587
- setInitialRender(false);
588
- }, []);
589
- const showStatus = resultsEmpty;
590
- const statusId = useId();
591
- const listboxId = useId();
592
- const getItemNode = index => {
593
- const item = filteredItems[index];
594
- return /*#__PURE__*/jsx(SelectInputItemView, {
595
- item: item,
596
- renderValue: renderValue,
597
- needle: needle
598
- }, index);
599
- };
600
- const findMatchingItem = autocompleteValue => {
601
- const flatOptions = items.flatMap(item => item.type === 'group' ? item.options : item.type === 'option' ? [item] : []).filter(item => item.type === 'option' && item.value != null);
602
- const exactMatch = flatOptions.find(option => String(option.value) === autocompleteValue || option.filterMatchers?.some(matcher => matcher === autocompleteValue));
603
- if (exactMatch) {
604
- return exactMatch.value;
605
- }
606
- const fuzzyMatch = flatOptions.find(option => option.filterMatchers?.some(matcher => matcher.toLowerCase().includes(autocompleteValue.toLowerCase())));
607
- return fuzzyMatch ? fuzzyMatch.value : null;
608
- };
609
- return /*#__PURE__*/jsxs(ListboxOptions, {
610
- modal: true,
611
- as: SelectInputOptionsContainer,
612
- static: true,
613
- className: "np-select-input-options-container",
614
- onAriaActiveDescendantChange: value => {
615
- if (controllerRef.current != null) {
616
- if (!initialRender && value != null) {
617
- controllerRef.current.setAttribute('aria-activedescendant', value);
618
- } else {
619
- controllerRef.current.removeAttribute('aria-activedescendant');
620
- }
621
- }
622
- },
623
- children: [filterable ? /*#__PURE__*/jsx("div", {
624
- className: "np-select-input-query-container",
625
- children: /*#__PURE__*/jsx(SearchInput, {
626
- ref: searchInputRef,
627
- id: id,
628
- name: name,
629
- autoComplete: autocomplete,
630
- role: "combobox",
631
- shape: "rectangle",
632
- placeholder: filterPlaceholder,
633
- "aria-label": filterPlaceholder,
634
- defaultValue: filterQuery,
635
- "aria-autocomplete": "list",
636
- "aria-expanded": true,
637
- "aria-controls": listboxId,
638
- "aria-describedby": showStatus ? statusId : undefined,
639
- onKeyDown: event => {
640
- // Prevent interfering with the matcher of Headless UI
641
- // https://mathiasbynens.be/notes/javascript-unicode#regex
642
- if (/^.$/u.test(event.key)) {
643
- event.stopPropagation();
644
- }
645
- },
646
- onChange: event => {
647
- // Free up resources and ensure not to go out of bounds when the
648
- // resulting item count is less than before
649
- const inputValue = event.currentTarget.value;
650
- // Free up resources and ensure not to go out of bounds
651
- setMountedIndexes([]);
652
- onFilterChange(inputValue);
653
- },
654
- onInput: event => {
655
- const inputValue = event.currentTarget.value;
656
- const inputElement = event.currentTarget;
657
- if (autocomplete && onAutocompleteSelect && inputValue) {
658
- setTimeout(() => {
659
- if (inputElement.value === inputValue && inputValue.length > 2) {
660
- const matchedValue = findMatchingItem(inputValue);
661
- if (matchedValue !== null) {
662
- onAutocompleteSelect(matchedValue);
663
- }
664
- }
665
- }, 50);
666
- }
667
- }
668
- })
669
- }) : null, /*#__PURE__*/jsxs("section", {
670
- ref: listboxContainerRef,
671
- tabIndex: -1,
672
- className: clsx('np-select-input-listbox-container', virtualized && 'np-select-input-listbox-container--virtualized', needle == null &&
673
- // Groups aren't shown when filtering
674
- items.some(item => item.type === 'group') && 'np-select-input-listbox-container--has-group'),
675
- "data-wds-parent": parentId ?? undefined,
676
- children: [resultsEmpty ? /*#__PURE__*/jsxs("div", {
677
- id: statusId,
678
- className: "np-select-input-options-status",
679
- children: [/*#__PURE__*/jsx(CrossCircle, {
680
- size: 16,
681
- className: "np-select-input-options-status-icon"
682
- }), intl.formatMessage(messages.noResultsFound)]
683
- }) : null, /*#__PURE__*/jsx("div", {
684
- ref: listboxRef,
685
- id: listboxId,
686
- role: "listbox",
687
- "aria-orientation": "vertical",
688
- "aria-label": listBoxLabel,
689
- "aria-labelledby": listBoxLabelledBy,
690
- tabIndex: 0,
691
- className: "np-select-input-listbox",
692
- children: !virtualized ? filteredItems.map((_, index) => getItemNode(index)) : /*#__PURE__*/jsx(Virtualizer, {
693
- ref: virtualiserHandlerRef,
694
- data: filteredItems,
695
- keepMounted: mountedIndexes,
696
- scrollRef: listboxRef // `VList` doesn't expose this
697
- ,
698
- onScroll: async () => {
699
- if (!virtualiserHandlerRef.current) return;
700
- const startIndex = virtualiserHandlerRef.current.findItemIndex(virtualiserHandlerRef.current.scrollOffset);
701
- const endIndex = virtualiserHandlerRef.current.findItemIndex(virtualiserHandlerRef.current.scrollOffset + virtualiserHandlerRef.current.viewportSize);
702
- setMountedIndexes(prevMountedIndexes => {
703
- const indexes = new Set(prevMountedIndexes);
704
- for (let index = startIndex; index <= endIndex; index += 1) {
705
- indexes.add(index);
706
- }
707
- return [...indexes].sort((a, b) => a - b);
708
- });
709
- },
710
- children: (item, index) =>
711
- /*#__PURE__*/
712
- // The position of each item can't be inferred by browsers when
713
- // virtualizing, as some of the items may not be in the DOM
714
- jsx(SelectInputItemsCountContext.Provider, {
715
- value: filteredItems.length,
716
- children: /*#__PURE__*/jsx(SelectInputItemPositionContext.Provider, {
717
- value: index + 1,
718
- children: getItemNode(index)
719
- })
720
- })
721
- })
722
- }), renderFooter != null ? /*#__PURE__*/jsx("footer", {
723
- className: "np-select-input-footer",
724
- children: /*#__PURE__*/jsx("div", {
725
- role: "none",
726
- onKeyDown: event => {
727
- // Prevent interfering with Headless UI
728
- if (event.key !== 'Escape') {
729
- event.stopPropagation();
730
- }
731
- },
732
- children: renderFooter({
733
- resultsEmpty,
734
- queryNormalized: needle
735
- })
736
- })
737
- }) : null]
738
- })]
739
- });
740
- }
741
- function SelectInputItemView({
742
- item,
743
- renderValue,
744
- needle
745
- }) {
746
- switch (item.type) {
747
- case 'option':
748
- {
749
- if (item.value != null && (needle == null || selectInputOptionItemIncludesNeedle(item, needle))) {
750
- return /*#__PURE__*/jsx(SelectInputOption, {
751
- value: item.value,
752
- disabled: item.disabled,
753
- children: renderValue(item.value, false)
754
- });
755
- }
756
- break;
757
- }
758
- case 'group':
759
- {
760
- return /*#__PURE__*/jsx(SelectInputGroupItemView, {
761
- item: item,
762
- renderValue: renderValue,
763
- needle: needle
764
- });
765
- }
766
- case 'separator':
767
- {
768
- if (needle == null) {
769
- return /*#__PURE__*/jsx("hr", {
770
- className: "np-select-input-separator-item"
771
- });
772
- }
773
- break;
774
- }
775
- }
776
- return null;
777
- }
778
- function SelectInputGroupItemView({
779
- item,
780
- renderValue,
781
- needle
782
- }) {
783
- const headerId = useId();
784
- const header = /*#__PURE__*/jsx(Header, {
785
- as: "header",
786
- role: "none",
787
- id: headerId,
788
- title: item.label
789
- // @ts-expect-error when we migrate ActionButton to new Button this should be sorted
790
- ,
791
- action: item.action && {
792
- text: item.action.label,
793
- onClick: item.action.onClick
794
- },
795
- className: "np-select-input-group-item-header p-x-1"
796
- });
797
- return (
798
- /*#__PURE__*/
799
- // An empty container may be rendered when no options match `needle`
800
- // However, pre-filtering would result in worse performance overall
801
- jsxs(Section, {
802
- as: "section",
803
- role: "group",
804
- "aria-labelledby": headerId,
805
- className: clsx('m-y-0', needle === null && 'np-select-input-group-item--without-needle'),
806
- children: [needle == null ? header : null, item.options.map((option, index) => /*#__PURE__*/jsx(SelectInputItemView
807
- // eslint-disable-next-line react/no-array-index-key
808
- , {
809
- item: option,
810
- renderValue: renderValue,
811
- needle: needle
812
- }, index))]
813
- })
814
- );
815
- }
816
- const SelectInputItemsCountContext = /*#__PURE__*/createContext(undefined);
817
- const SelectInputItemPositionContext = /*#__PURE__*/createContext(undefined);
818
- function SelectInputOption({
819
- value,
820
- disabled,
821
- children
822
- }) {
823
- const itemsCount = useContext(SelectInputItemsCountContext);
824
- const itemPosition = useContext(SelectInputItemPositionContext);
825
- return /*#__PURE__*/jsx(ListboxOption, {
826
- as: "div",
827
- value: value,
828
- "aria-setsize": itemsCount,
829
- "aria-posinset": itemPosition,
830
- disabled: disabled,
831
- className: ({
832
- active,
833
- disabled: uiDisabled
834
- }) => clsx('np-select-input-option-container np-text-body-large', active && 'np-select-input-option-container--active', uiDisabled && 'np-select-input-option-container--disabled'),
835
- children: ({
836
- selected
837
- }) => /*#__PURE__*/jsxs(Fragment, {
838
- children: [/*#__PURE__*/jsx("div", {
839
- className: "np-select-input-option",
840
- children: children
841
- }), /*#__PURE__*/jsx(Check, {
842
- size: 16,
843
- className: clsx('np-select-input-option-check', !selected && 'np-select-input-option-check--not-selected')
844
- })]
845
- })
846
- });
847
- }
848
- const SelectInputOptionContentWithinTriggerContext = /*#__PURE__*/createContext(false);
849
- function SelectInputOptionContent({
850
- title,
851
- note,
852
- description,
853
- icon
854
- }) {
855
- const withinTrigger = useContext(SelectInputOptionContentWithinTriggerContext);
856
- return /*#__PURE__*/jsxs("div", {
857
- className: clsx('np-select-input-option-content-container', (note || description) && 'np-text-body-large'),
858
- children: [icon ? /*#__PURE__*/jsx("div", {
859
- className: clsx('np-select-input-option-content-icon', !withinTrigger && 'np-select-input-option-content-icon--not-within-trigger'),
860
- children: icon
861
- }) : null, /*#__PURE__*/jsxs("div", {
862
- className: "np-select-input-option-content-text",
863
- children: [/*#__PURE__*/jsxs("div", {
864
- className: clsx('np-select-input-option-content-text-line-1', withinTrigger && 'np-select-input-option-content-text-within-trigger'),
865
- children: [/*#__PURE__*/jsx("div", {
866
- className: "d-inline",
867
- children: title
868
- }), note ? /*#__PURE__*/jsx("span", {
869
- className: "np-select-input-option-content-text-secondary np-text-body-default",
870
- children: note
871
- }) : null]
872
- }), description ? /*#__PURE__*/jsx("div", {
873
- className: clsx('np-select-input-option-content-text-secondary np-text-body-default', withinTrigger && 'np-select-input-option-content-text-within-trigger np-select-input-option-description-in-trigger'),
874
- children: description
875
- }) : null]
876
- })]
877
- });
878
- }
879
-
880
- export { SelectInput, SelectInputOptionContent, SelectInputTriggerButton, sortByRelevance };
881
- //# sourceMappingURL=SelectInput.mjs.map