@transferwise/components 0.0.0-experimental-e9426b6 → 0.0.0-experimental-0397551

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 (182) hide show
  1. package/build/dateInput/DateInput.js +3 -6
  2. package/build/dateInput/DateInput.js.map +1 -1
  3. package/build/dateInput/DateInput.mjs +2 -5
  4. package/build/dateInput/DateInput.mjs.map +1 -1
  5. package/build/expressiveMoneyInput/currencySelector/CurrencySelector.js +3 -5
  6. package/build/expressiveMoneyInput/currencySelector/CurrencySelector.js.map +1 -1
  7. package/build/expressiveMoneyInput/currencySelector/CurrencySelector.mjs +1 -3
  8. package/build/expressiveMoneyInput/currencySelector/CurrencySelector.mjs.map +1 -1
  9. package/build/index.js +3 -5
  10. package/build/index.js.map +1 -1
  11. package/build/index.mjs +1 -3
  12. package/build/index.mjs.map +1 -1
  13. package/build/inputs/SelectInput.js +821 -0
  14. package/build/inputs/SelectInput.js.map +1 -0
  15. package/build/inputs/SelectInput.messages.js.map +1 -0
  16. package/build/inputs/SelectInput.messages.mjs.map +1 -0
  17. package/build/inputs/SelectInput.mjs +813 -0
  18. package/build/inputs/SelectInput.mjs.map +1 -0
  19. package/build/main.css +47 -47
  20. package/build/moneyInput/MoneyInput.js +2 -5
  21. package/build/moneyInput/MoneyInput.js.map +1 -1
  22. package/build/moneyInput/MoneyInput.mjs +1 -4
  23. package/build/moneyInput/MoneyInput.mjs.map +1 -1
  24. package/build/phoneNumberInput/PhoneNumberInput.js +2 -5
  25. package/build/phoneNumberInput/PhoneNumberInput.js.map +1 -1
  26. package/build/phoneNumberInput/PhoneNumberInput.mjs +1 -4
  27. package/build/phoneNumberInput/PhoneNumberInput.mjs.map +1 -1
  28. package/build/styles/main.css +47 -47
  29. package/build/types/inputs/{SelectInput/SelectInput.types.d.ts → SelectInput.d.ts} +7 -4
  30. package/build/types/inputs/SelectInput.d.ts.map +1 -0
  31. package/build/types/inputs/SelectInput.messages.d.ts.map +1 -0
  32. package/package.json +1 -1
  33. package/src/actionButton/ActionButton.story.tsx +3 -0
  34. package/src/checkbox/Checkbox.story.tsx +3 -0
  35. package/src/circularButton/CircularButton.story.tsx +3 -0
  36. package/src/common/bottomSheet/BottomSheet.story.tsx +12 -0
  37. package/src/common/circle/Circle.story.tsx +3 -0
  38. package/src/criticalBanner/CriticalCommsBanner.story.tsx +3 -0
  39. package/src/dateInput/DateInput.test.story.tsx +6 -0
  40. package/src/dateLookup/DateLookup.story.tsx +3 -0
  41. package/src/info/Info.story.tsx +6 -0
  42. package/src/inputs/{SelectInput/SelectInput.docs.mdx → SelectInput.docs.mdx} +1 -0
  43. package/src/inputs/SelectInput.less +219 -0
  44. package/src/inputs/{SelectInput/SelectInput.story.tsx → SelectInput.story.tsx} +7 -7
  45. package/src/inputs/SelectInput.tsx +1190 -0
  46. package/src/main.css +47 -47
  47. package/src/main.less +1 -1
  48. package/src/modal/Modal.story.tsx +15 -0
  49. package/src/snackbar/Snackbar.test.story.tsx +9 -0
  50. package/build/inputs/SelectInput/SelectInput.helpers.js +0 -115
  51. package/build/inputs/SelectInput/SelectInput.helpers.js.map +0 -1
  52. package/build/inputs/SelectInput/SelectInput.helpers.mjs +0 -109
  53. package/build/inputs/SelectInput/SelectInput.helpers.mjs.map +0 -1
  54. package/build/inputs/SelectInput/SelectInput.js +0 -216
  55. package/build/inputs/SelectInput/SelectInput.js.map +0 -1
  56. package/build/inputs/SelectInput/SelectInput.messages.js.map +0 -1
  57. package/build/inputs/SelectInput/SelectInput.messages.mjs.map +0 -1
  58. package/build/inputs/SelectInput/SelectInput.mjs +0 -210
  59. package/build/inputs/SelectInput/SelectInput.mjs.map +0 -1
  60. package/build/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.js +0 -26
  61. package/build/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.js.map +0 -1
  62. package/build/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.mjs +0 -24
  63. package/build/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.mjs.map +0 -1
  64. package/build/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.js +0 -54
  65. package/build/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.js.map +0 -1
  66. package/build/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.mjs +0 -52
  67. package/build/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.mjs.map +0 -1
  68. package/build/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.js +0 -50
  69. package/build/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.js.map +0 -1
  70. package/build/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.mjs +0 -48
  71. package/build/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.mjs.map +0 -1
  72. package/build/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.js +0 -47
  73. package/build/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.js.map +0 -1
  74. package/build/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.mjs +0 -45
  75. package/build/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.mjs.map +0 -1
  76. package/build/inputs/SelectInput/components/SelectInputOption/SelectInputOption.js +0 -45
  77. package/build/inputs/SelectInput/components/SelectInputOption/SelectInputOption.js.map +0 -1
  78. package/build/inputs/SelectInput/components/SelectInputOption/SelectInputOption.mjs +0 -41
  79. package/build/inputs/SelectInput/components/SelectInputOption/SelectInputOption.mjs.map +0 -1
  80. package/build/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.js +0 -41
  81. package/build/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.js.map +0 -1
  82. package/build/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.mjs +0 -38
  83. package/build/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.mjs.map +0 -1
  84. package/build/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.js +0 -270
  85. package/build/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.js.map +0 -1
  86. package/build/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.mjs +0 -268
  87. package/build/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.mjs.map +0 -1
  88. package/build/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.js +0 -48
  89. package/build/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.js.map +0 -1
  90. package/build/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.mjs +0 -46
  91. package/build/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.mjs.map +0 -1
  92. package/build/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.js +0 -41
  93. package/build/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.js.map +0 -1
  94. package/build/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.mjs +0 -34
  95. package/build/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.mjs.map +0 -1
  96. package/build/styles/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.css +0 -17
  97. package/build/styles/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.css +0 -16
  98. package/build/styles/inputs/SelectInput/components/SelectInputOption/SelectInputOption.css +0 -33
  99. package/build/styles/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.css +0 -37
  100. package/build/types/inputs/SelectInput/SelectInput.d.ts +0 -3
  101. package/build/types/inputs/SelectInput/SelectInput.d.ts.map +0 -1
  102. package/build/types/inputs/SelectInput/SelectInput.helpers.d.ts +0 -28
  103. package/build/types/inputs/SelectInput/SelectInput.helpers.d.ts.map +0 -1
  104. package/build/types/inputs/SelectInput/SelectInput.messages.d.ts.map +0 -1
  105. package/build/types/inputs/SelectInput/SelectInput.types.d.ts.map +0 -1
  106. package/build/types/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.d.ts +0 -5
  107. package/build/types/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.d.ts.map +0 -1
  108. package/build/types/inputs/SelectInput/components/SelectInputClearButton/index.d.ts +0 -2
  109. package/build/types/inputs/SelectInput/components/SelectInputClearButton/index.d.ts.map +0 -1
  110. package/build/types/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.d.ts +0 -9
  111. package/build/types/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.d.ts.map +0 -1
  112. package/build/types/inputs/SelectInput/components/SelectInputDefaultTrigger/index.d.ts +0 -2
  113. package/build/types/inputs/SelectInput/components/SelectInputDefaultTrigger/index.d.ts.map +0 -1
  114. package/build/types/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.d.ts +0 -9
  115. package/build/types/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.d.ts.map +0 -1
  116. package/build/types/inputs/SelectInput/components/SelectInputGroupItemView/index.d.ts +0 -2
  117. package/build/types/inputs/SelectInput/components/SelectInputGroupItemView/index.d.ts.map +0 -1
  118. package/build/types/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.d.ts +0 -8
  119. package/build/types/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.d.ts.map +0 -1
  120. package/build/types/inputs/SelectInput/components/SelectInputItemView/index.d.ts +0 -2
  121. package/build/types/inputs/SelectInput/components/SelectInputItemView/index.d.ts.map +0 -1
  122. package/build/types/inputs/SelectInput/components/SelectInputOption/SelectInputOption.d.ts +0 -10
  123. package/build/types/inputs/SelectInput/components/SelectInputOption/SelectInputOption.d.ts.map +0 -1
  124. package/build/types/inputs/SelectInput/components/SelectInputOption/index.d.ts +0 -2
  125. package/build/types/inputs/SelectInput/components/SelectInputOption/index.d.ts.map +0 -1
  126. package/build/types/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.d.ts +0 -9
  127. package/build/types/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.d.ts.map +0 -1
  128. package/build/types/inputs/SelectInput/components/SelectInputOptionContent/index.d.ts +0 -3
  129. package/build/types/inputs/SelectInput/components/SelectInputOptionContent/index.d.ts.map +0 -1
  130. package/build/types/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.d.ts +0 -15
  131. package/build/types/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.d.ts.map +0 -1
  132. package/build/types/inputs/SelectInput/components/SelectInputOptions/index.d.ts +0 -2
  133. package/build/types/inputs/SelectInput/components/SelectInputOptions/index.d.ts.map +0 -1
  134. package/build/types/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.d.ts +0 -6
  135. package/build/types/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.d.ts.map +0 -1
  136. package/build/types/inputs/SelectInput/components/SelectInputOptionsContainer/index.d.ts +0 -2
  137. package/build/types/inputs/SelectInput/components/SelectInputOptionsContainer/index.d.ts.map +0 -1
  138. package/build/types/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.d.ts +0 -15
  139. package/build/types/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.d.ts.map +0 -1
  140. package/build/types/inputs/SelectInput/components/SelectInputTriggerButton/index.d.ts +0 -3
  141. package/build/types/inputs/SelectInput/components/SelectInputTriggerButton/index.d.ts.map +0 -1
  142. package/build/types/inputs/SelectInput/index.d.ts +0 -5
  143. package/build/types/inputs/SelectInput/index.d.ts.map +0 -1
  144. package/src/inputs/SelectInput/SelectInput.helpers.ts +0 -152
  145. package/src/inputs/SelectInput/SelectInput.less +0 -42
  146. package/src/inputs/SelectInput/SelectInput.test.tsx +0 -606
  147. package/src/inputs/SelectInput/SelectInput.tsx +0 -247
  148. package/src/inputs/SelectInput/SelectInput.types.ts +0 -114
  149. package/src/inputs/SelectInput/components/SelectInputClearButton/SelectInputClearButton.tsx +0 -25
  150. package/src/inputs/SelectInput/components/SelectInputClearButton/index.ts +0 -1
  151. package/src/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.css +0 -17
  152. package/src/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.less +0 -15
  153. package/src/inputs/SelectInput/components/SelectInputDefaultTrigger/SelectInputDefaultTrigger.tsx +0 -56
  154. package/src/inputs/SelectInput/components/SelectInputDefaultTrigger/index.ts +0 -1
  155. package/src/inputs/SelectInput/components/SelectInputGroupItemView/SelectInputGroupItemView.tsx +0 -64
  156. package/src/inputs/SelectInput/components/SelectInputGroupItemView/index.ts +0 -1
  157. package/src/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.css +0 -16
  158. package/src/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.less +0 -17
  159. package/src/inputs/SelectInput/components/SelectInputItemView/SelectInputItemView.tsx +0 -55
  160. package/src/inputs/SelectInput/components/SelectInputItemView/index.ts +0 -1
  161. package/src/inputs/SelectInput/components/SelectInputOption/SelectInputOption.css +0 -33
  162. package/src/inputs/SelectInput/components/SelectInputOption/SelectInputOption.less +0 -32
  163. package/src/inputs/SelectInput/components/SelectInputOption/SelectInputOption.tsx +0 -51
  164. package/src/inputs/SelectInput/components/SelectInputOption/index.ts +0 -5
  165. package/src/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.css +0 -37
  166. package/src/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.less +0 -38
  167. package/src/inputs/SelectInput/components/SelectInputOptionContent/SelectInputOptionContent.tsx +0 -67
  168. package/src/inputs/SelectInput/components/SelectInputOptionContent/index.ts +0 -5
  169. package/src/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.less +0 -75
  170. package/src/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.tsx +0 -369
  171. package/src/inputs/SelectInput/components/SelectInputOptions/index.ts +0 -1
  172. package/src/inputs/SelectInput/components/SelectInputOptionsContainer/SelectInputOptionsContainer.tsx +0 -56
  173. package/src/inputs/SelectInput/components/SelectInputOptionsContainer/index.ts +0 -1
  174. package/src/inputs/SelectInput/components/SelectInputTriggerButton/SelectInputTriggerButton.tsx +0 -39
  175. package/src/inputs/SelectInput/components/SelectInputTriggerButton/index.ts +0 -5
  176. package/src/inputs/SelectInput/index.ts +0 -13
  177. package/build/inputs/{SelectInput/SelectInput.messages.js → SelectInput.messages.js} +0 -0
  178. package/build/inputs/{SelectInput/SelectInput.messages.mjs → SelectInput.messages.mjs} +0 -0
  179. package/{src/inputs/SelectInput → build/styles/inputs}/SelectInput.css +47 -47
  180. package/build/types/inputs/{SelectInput/SelectInput.messages.d.ts → SelectInput.messages.d.ts} +0 -0
  181. package/{build/styles/inputs/SelectInput → src/inputs}/SelectInput.css +47 -47
  182. /package/src/inputs/{SelectInput/SelectInput.messages.ts → SelectInput.messages.ts} +0 -0
@@ -1,270 +0,0 @@
1
- 'use strict';
2
-
3
- var react = require('@headlessui/react');
4
- var icons = require('@transferwise/icons');
5
- var clsx = require('clsx');
6
- var React = require('react');
7
- var reactIntl = require('react-intl');
8
- var virtua = require('virtua');
9
- var SearchInput = require('../../../SearchInput.js');
10
- var SelectInput_messages = require('../../SelectInput.messages.js');
11
- var SelectInput_helpers = require('../../SelectInput.helpers.js');
12
- var SelectInputOptionsContainer = require('../SelectInputOptionsContainer/SelectInputOptionsContainer.js');
13
- var SelectInputItemView = require('../SelectInputItemView/SelectInputItemView.js');
14
- var SelectInputOption = require('../SelectInputOption/SelectInputOption.js');
15
- var jsxRuntime = require('react/jsx-runtime');
16
-
17
- const MAX_ITEMS_WITHOUT_VIRTUALIZATION = 50;
18
- function SelectInputOptions({
19
- id,
20
- parentId,
21
- items,
22
- compareValues: compareValuesProp,
23
- renderValue = String,
24
- renderFooter,
25
- filterable = false,
26
- filterPlaceholder,
27
- sortFilteredOptions,
28
- searchInputRef,
29
- listboxRef,
30
- filterQuery,
31
- onFilterChange,
32
- listBoxLabel,
33
- listBoxLabelledBy,
34
- autocomplete,
35
- name,
36
- onAutocompleteSelect
37
- }) {
38
- const intl = reactIntl.useIntl();
39
- const virtualiserHandlerRef = React.useRef(null);
40
- const controllerRef = filterable ? searchInputRef : listboxRef;
41
- const [initialRender, setInitialRender] = React.useState(true);
42
- const needle = React.useMemo(() => {
43
- if (filterable) {
44
- return filterQuery ? SelectInput_helpers.searchableString(filterQuery) : null;
45
- }
46
- return undefined;
47
- }, [filterQuery, filterable]);
48
- React.useEffect(() => {
49
- if (needle) {
50
- // Ensure having an active option while filtering.
51
- // Without `requestAnimationFrame` upon which React depends for scheduling
52
- // updates, the active status would only show for a split second and then
53
- // disappear inadvertently.
54
- requestAnimationFrame(() => {
55
- if (controllerRef.current != null && !controllerRef.current.hasAttribute('aria-activedescendant')) {
56
- // Activate first option via synthetic key press
57
- controllerRef.current.dispatchEvent(new KeyboardEvent('keydown', {
58
- key: 'Home',
59
- bubbles: true
60
- }));
61
- }
62
- });
63
- }
64
- }, [controllerRef, needle]);
65
- const compareValues = React.useMemo(() => {
66
- if (!compareValuesProp) {
67
- return undefined;
68
- }
69
- if (typeof compareValuesProp === 'function') {
70
- return (a, b) => compareValuesProp(a, b);
71
- }
72
- const key = compareValuesProp;
73
- return (a, b) => {
74
- if (typeof a === 'object' && a != null && typeof b === 'object' && b != null) {
75
- return a[key] === b[key];
76
- }
77
- return a === b;
78
- };
79
- }, [compareValuesProp]);
80
- const filteredItems = React.useMemo(() => {
81
- if (needle == null) {
82
- return items;
83
- }
84
- const filtered = SelectInput_helpers.filterSelectInputItems(SelectInput_helpers.dedupeSelectInputItems(items, compareValues), item => SelectInput_helpers.selectInputOptionItemIncludesNeedle(item, needle));
85
- if (sortFilteredOptions) {
86
- return SelectInput_helpers.sortSelectInputItems(filtered, sortFilteredOptions, filterQuery);
87
- }
88
- return filtered;
89
- // eslint-disable-next-line react-hooks/exhaustive-deps
90
- }, [needle, items, compareValues]);
91
- const resultsEmpty = needle != null && filteredItems.length === 0;
92
- const virtualized = filteredItems.length > MAX_ITEMS_WITHOUT_VIRTUALIZATION;
93
- // Items shown once shall be kept mounted until the needle changes, otherwise
94
- // the scroll position may jump around inadvertently. Pattern adopted from:
95
- // https://inokawa.github.io/virtua/?path=/story/advanced-keep-offscreen-items--append-only
96
- const [mountedIndexes, setMountedIndexes] = React.useState([]);
97
- React.useEffect(() => {
98
- // Ensure the 'End' key works as intended by keeping the last item mounted
99
- setMountedIndexes(prevMountedIndexes => {
100
- const indexes = new Set(prevMountedIndexes);
101
- indexes.add(filteredItems.length - 1);
102
- return [...indexes]; // Sorting is redundant by nature here
103
- });
104
- }, [needle,
105
- // Needed as `filteredItems.length` may be equal between two updates
106
- filteredItems.length]);
107
- const listboxContainerRef = React.useRef(null);
108
- React.useEffect(() => {
109
- if (listboxContainerRef.current != null) {
110
- listboxContainerRef.current.style.setProperty('--initial-height', `${listboxContainerRef.current.offsetHeight}px`);
111
- }
112
- }, []);
113
- React.useEffect(() => {
114
- setInitialRender(false);
115
- }, []);
116
- const showStatus = resultsEmpty;
117
- const statusId = React.useId();
118
- const listboxId = React.useId();
119
- const getItemNode = index => {
120
- const item = filteredItems[index];
121
- return /*#__PURE__*/jsxRuntime.jsx(SelectInputItemView.SelectInputItemView, {
122
- item: item,
123
- renderValue: renderValue,
124
- needle: needle
125
- }, index);
126
- };
127
- const findMatchingItem = autocompleteValue => {
128
- const flatOptions = items.flatMap(item => item.type === 'group' ? item.options : item.type === 'option' ? [item] : []).filter(item => item.type === 'option' && item.value != null);
129
- const exactMatch = flatOptions.find(option => String(option.value) === autocompleteValue || option.filterMatchers?.some(matcher => matcher === autocompleteValue));
130
- if (exactMatch) {
131
- return exactMatch.value;
132
- }
133
- const fuzzyMatch = flatOptions.find(option => option.filterMatchers?.some(matcher => matcher.toLowerCase().includes(autocompleteValue.toLowerCase())));
134
- return fuzzyMatch ? fuzzyMatch.value : null;
135
- };
136
- return /*#__PURE__*/jsxRuntime.jsxs(react.ListboxOptions, {
137
- modal: true,
138
- as: SelectInputOptionsContainer.SelectInputOptionsContainer,
139
- static: true,
140
- className: "np-select-input-options-container",
141
- onAriaActiveDescendantChange: value => {
142
- if (controllerRef.current != null) {
143
- if (!initialRender && value != null) {
144
- controllerRef.current.setAttribute('aria-activedescendant', value);
145
- } else {
146
- controllerRef.current.removeAttribute('aria-activedescendant');
147
- }
148
- }
149
- },
150
- children: [filterable ? /*#__PURE__*/jsxRuntime.jsx("div", {
151
- className: "np-select-input-query-container",
152
- children: /*#__PURE__*/jsxRuntime.jsx(SearchInput.SearchInput, {
153
- ref: searchInputRef,
154
- id: id,
155
- name: name,
156
- autoComplete: autocomplete,
157
- role: "combobox",
158
- shape: "rectangle",
159
- placeholder: filterPlaceholder,
160
- "aria-label": filterPlaceholder,
161
- defaultValue: filterQuery,
162
- "aria-autocomplete": "list",
163
- "aria-expanded": true,
164
- "aria-controls": listboxId,
165
- "aria-describedby": showStatus ? statusId : undefined,
166
- onKeyDown: event => {
167
- // Prevent interfering with the matcher of Headless UI
168
- // https://mathiasbynens.be/notes/javascript-unicode#regex
169
- if (/^.$/u.test(event.key)) {
170
- event.stopPropagation();
171
- }
172
- },
173
- onChange: event => {
174
- // Free up resources and ensure not to go out of bounds when the
175
- // resulting item count is less than before
176
- const inputValue = event.currentTarget.value;
177
- // Free up resources and ensure not to go out of bounds
178
- setMountedIndexes([]);
179
- onFilterChange(inputValue);
180
- },
181
- onInput: event => {
182
- const inputValue = event.currentTarget.value;
183
- const inputElement = event.currentTarget;
184
- if (autocomplete && onAutocompleteSelect && inputValue) {
185
- setTimeout(() => {
186
- if (inputElement.value === inputValue && inputValue.length > 2) {
187
- const matchedValue = findMatchingItem(inputValue);
188
- if (matchedValue !== null) {
189
- onAutocompleteSelect(matchedValue);
190
- }
191
- }
192
- }, 50);
193
- }
194
- }
195
- })
196
- }) : null, /*#__PURE__*/jsxRuntime.jsxs("section", {
197
- ref: listboxContainerRef,
198
- tabIndex: -1,
199
- className: clsx.clsx('np-select-input-listbox-container', virtualized && 'np-select-input-listbox-container--virtualized', needle == null &&
200
- // Groups aren't shown when filtering
201
- items.some(item => item.type === 'group') && 'np-select-input-listbox-container--has-group'),
202
- "data-wds-parent": parentId ?? undefined,
203
- children: [resultsEmpty ? /*#__PURE__*/jsxRuntime.jsxs("div", {
204
- id: statusId,
205
- className: "np-select-input-options-status",
206
- children: [/*#__PURE__*/jsxRuntime.jsx(icons.CrossCircle, {
207
- size: 16,
208
- className: "np-select-input-options-status-icon"
209
- }), intl.formatMessage(SelectInput_messages.default.noResultsFound)]
210
- }) : null, /*#__PURE__*/jsxRuntime.jsx("div", {
211
- ref: listboxRef,
212
- id: listboxId,
213
- role: "listbox",
214
- "aria-orientation": "vertical",
215
- "aria-label": listBoxLabel,
216
- "aria-labelledby": listBoxLabelledBy,
217
- tabIndex: 0,
218
- className: "np-select-input-listbox",
219
- children: !virtualized ? filteredItems.map((_, index) => getItemNode(index)) : /*#__PURE__*/jsxRuntime.jsx(virtua.Virtualizer, {
220
- ref: virtualiserHandlerRef,
221
- data: filteredItems,
222
- keepMounted: mountedIndexes,
223
- scrollRef: listboxRef // `VList` doesn't expose this
224
- ,
225
- onScroll: async () => {
226
- if (!virtualiserHandlerRef.current) return;
227
- const startIndex = virtualiserHandlerRef.current.findItemIndex(virtualiserHandlerRef.current.scrollOffset);
228
- const endIndex = virtualiserHandlerRef.current.findItemIndex(virtualiserHandlerRef.current.scrollOffset + virtualiserHandlerRef.current.viewportSize);
229
- setMountedIndexes(prevMountedIndexes => {
230
- const indexes = new Set(prevMountedIndexes);
231
- for (let index = startIndex; index <= endIndex; index += 1) {
232
- indexes.add(index);
233
- }
234
- return [...indexes].sort((a, b) => a - b);
235
- });
236
- },
237
- children: (item, index) =>
238
- /*#__PURE__*/
239
- // The position of each item can't be inferred by browsers when
240
- // virtualizing, as some of the items may not be in the DOM
241
- jsxRuntime.jsx(SelectInputOption.SelectInputItemsCountContext.Provider, {
242
- value: filteredItems.length,
243
- children: /*#__PURE__*/jsxRuntime.jsx(SelectInputOption.SelectInputItemPositionContext.Provider, {
244
- value: index + 1,
245
- children: getItemNode(index)
246
- })
247
- })
248
- }, needle)
249
- }), renderFooter != null ? /*#__PURE__*/jsxRuntime.jsx("footer", {
250
- className: "np-select-input-footer",
251
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
252
- role: "none",
253
- onKeyDown: event => {
254
- // Prevent interfering with Headless UI
255
- if (event.key !== 'Escape') {
256
- event.stopPropagation();
257
- }
258
- },
259
- children: renderFooter({
260
- resultsEmpty,
261
- queryNormalized: needle
262
- })
263
- })
264
- }) : null]
265
- })]
266
- });
267
- }
268
-
269
- exports.SelectInputOptions = SelectInputOptions;
270
- //# sourceMappingURL=SelectInputOptions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SelectInputOptions.js","sources":["../../../../../src/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.tsx"],"sourcesContent":["import { ListboxOptions } from '@headlessui/react';\nimport { CrossCircle } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport { useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { useIntl } from 'react-intl';\nimport { Virtualizer, type VirtualizerHandle } from 'virtua';\n\nimport { SearchInput } from '../../../SearchInput';\nimport messages from '../../SelectInput.messages';\nimport { SelectInputProps, SelectInputOptionItem, SelectInputItem } from '../../SelectInput.types';\nimport {\n searchableString,\n dedupeSelectInputItems,\n filterSelectInputItems,\n selectInputOptionItemIncludesNeedle,\n sortSelectInputItems,\n} from '../../SelectInput.helpers';\n\nimport { SelectInputOptionsContainer } from '../SelectInputOptionsContainer';\nimport { SelectInputItemView } from '../SelectInputItemView';\nimport { SelectInputItemsCountContext, SelectInputItemPositionContext } from '../SelectInputOption';\n\nconst MAX_ITEMS_WITHOUT_VIRTUALIZATION = 50;\n\ninterface SelectInputOptionsProps<T = string> extends Pick<\n SelectInputProps<T>,\n | 'items'\n | 'renderValue'\n | 'renderFooter'\n | 'filterable'\n | 'filterPlaceholder'\n | 'id'\n | 'parentId'\n | 'compareValues'\n | 'sortFilteredOptions'\n> {\n searchInputRef: React.MutableRefObject<HTMLInputElement | null>;\n listboxRef: React.MutableRefObject<HTMLDivElement | null>;\n filterQuery: string;\n onFilterChange: (query: string) => void;\n listBoxLabel?: string;\n listBoxLabelledBy?: string;\n autocomplete?: string;\n name?: string;\n onAutocompleteSelect?: (value: T) => void;\n}\n\nexport function SelectInputOptions<T = string>({\n id,\n parentId,\n items,\n compareValues: compareValuesProp,\n renderValue = String,\n renderFooter,\n filterable = false,\n filterPlaceholder,\n sortFilteredOptions,\n searchInputRef,\n listboxRef,\n filterQuery,\n onFilterChange,\n listBoxLabel,\n listBoxLabelledBy,\n autocomplete,\n name,\n onAutocompleteSelect,\n}: SelectInputOptionsProps<T>) {\n const intl = useIntl();\n const virtualiserHandlerRef = useRef<VirtualizerHandle>(null);\n const controllerRef = filterable ? searchInputRef : listboxRef;\n const [initialRender, setInitialRender] = useState(true);\n\n const needle = useMemo(() => {\n if (filterable) {\n return filterQuery ? searchableString(filterQuery) : null;\n }\n return undefined;\n }, [filterQuery, filterable]);\n\n useEffect(() => {\n if (needle) {\n // Ensure having an active option while filtering.\n // Without `requestAnimationFrame` upon which React depends for scheduling\n // updates, the active status would only show for a split second and then\n // disappear inadvertently.\n requestAnimationFrame(() => {\n if (\n controllerRef.current != null &&\n !controllerRef.current.hasAttribute('aria-activedescendant')\n ) {\n // Activate first option via synthetic key press\n controllerRef.current.dispatchEvent(\n new KeyboardEvent('keydown', { key: 'Home', bubbles: true }),\n );\n }\n });\n }\n }, [controllerRef, needle]);\n\n const compareValues = useMemo(() => {\n if (!compareValuesProp) {\n return undefined;\n }\n\n if (typeof compareValuesProp === 'function') {\n return (a: NonNullable<T>, b: NonNullable<T>) => compareValuesProp(a, b);\n }\n\n const key = compareValuesProp;\n return (a: NonNullable<T>, b: NonNullable<T>) => {\n if (typeof a === 'object' && a != null && typeof b === 'object' && b != null) {\n return (a as Record<string, unknown>)[key] === (b as Record<string, unknown>)[key];\n }\n return a === b;\n };\n }, [compareValuesProp]);\n\n const filteredItems: readonly SelectInputItem<NonNullable<T> | undefined>[] = useMemo(() => {\n if (needle == null) {\n return items;\n }\n\n const filtered = filterSelectInputItems(dedupeSelectInputItems(items, compareValues), (item) =>\n selectInputOptionItemIncludesNeedle(item, needle),\n );\n\n if (sortFilteredOptions) {\n return sortSelectInputItems(filtered, sortFilteredOptions, filterQuery);\n }\n\n return filtered;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [needle, items, compareValues]);\n const resultsEmpty = needle != null && filteredItems.length === 0;\n\n const virtualized = filteredItems.length > MAX_ITEMS_WITHOUT_VIRTUALIZATION;\n\n // Items shown once shall be kept mounted until the needle changes, otherwise\n // the scroll position may jump around inadvertently. Pattern adopted from:\n // https://inokawa.github.io/virtua/?path=/story/advanced-keep-offscreen-items--append-only\n const [mountedIndexes, setMountedIndexes] = useState<number[]>([]);\n useEffect(() => {\n // Ensure the 'End' key works as intended by keeping the last item mounted\n setMountedIndexes((prevMountedIndexes) => {\n const indexes = new Set(prevMountedIndexes);\n indexes.add(filteredItems.length - 1);\n return [...indexes]; // Sorting is redundant by nature here\n });\n }, [\n needle, // Needed as `filteredItems.length` may be equal between two updates\n filteredItems.length,\n ]);\n\n const listboxContainerRef = useRef<HTMLDivElement>(null);\n useEffect(() => {\n if (listboxContainerRef.current != null) {\n listboxContainerRef.current.style.setProperty(\n '--initial-height',\n `${listboxContainerRef.current.offsetHeight}px`,\n );\n }\n }, []);\n\n useEffect(() => {\n setInitialRender(false);\n }, []);\n\n const showStatus = resultsEmpty;\n const statusId = useId();\n const listboxId = useId();\n\n const getItemNode = (index: number) => {\n const item = filteredItems[index];\n return (\n <SelectInputItemView key={index} item={item} renderValue={renderValue} needle={needle} />\n );\n };\n\n const findMatchingItem = (autocompleteValue: string): T | null => {\n const flatOptions = items\n .flatMap((item) =>\n item.type === 'group' ? item.options : item.type === 'option' ? [item] : [],\n )\n .filter(\n (item): item is SelectInputOptionItem<NonNullable<T>> =>\n item.type === 'option' && item.value != null,\n );\n\n const exactMatch = flatOptions.find(\n (option) =>\n String(option.value) === autocompleteValue ||\n option.filterMatchers?.some((matcher) => matcher === autocompleteValue),\n );\n\n if (exactMatch) {\n return exactMatch.value;\n }\n\n const fuzzyMatch = flatOptions.find((option) =>\n option.filterMatchers?.some((matcher) =>\n matcher.toLowerCase().includes(autocompleteValue.toLowerCase()),\n ),\n );\n\n return fuzzyMatch ? fuzzyMatch.value : null;\n };\n\n return (\n <ListboxOptions\n modal\n as={SelectInputOptionsContainer}\n static\n className=\"np-select-input-options-container\"\n onAriaActiveDescendantChange={(value: React.AriaAttributes['aria-activedescendant']) => {\n if (controllerRef.current != null) {\n if (!initialRender && value != null) {\n controllerRef.current.setAttribute('aria-activedescendant', value);\n } else {\n controllerRef.current.removeAttribute('aria-activedescendant');\n }\n }\n }}\n >\n {filterable ? (\n <div className=\"np-select-input-query-container\">\n <SearchInput\n ref={searchInputRef}\n id={id}\n name={name}\n autoComplete={autocomplete}\n role=\"combobox\"\n shape=\"rectangle\"\n placeholder={filterPlaceholder}\n aria-label={filterPlaceholder}\n defaultValue={filterQuery}\n aria-autocomplete=\"list\"\n aria-expanded\n aria-controls={listboxId}\n aria-describedby={showStatus ? statusId : undefined}\n onKeyDown={(event) => {\n // Prevent interfering with the matcher of Headless UI\n // https://mathiasbynens.be/notes/javascript-unicode#regex\n if (/^.$/u.test(event.key)) {\n event.stopPropagation();\n }\n }}\n onChange={(event) => {\n // Free up resources and ensure not to go out of bounds when the\n // resulting item count is less than before\n const inputValue = event.currentTarget.value;\n\n // Free up resources and ensure not to go out of bounds\n setMountedIndexes([]);\n onFilterChange(inputValue);\n }}\n onInput={(event) => {\n const inputValue = event.currentTarget.value;\n const inputElement = event.currentTarget;\n\n if (autocomplete && onAutocompleteSelect && inputValue) {\n setTimeout(() => {\n if (inputElement.value === inputValue && inputValue.length > 2) {\n const matchedValue = findMatchingItem(inputValue);\n if (matchedValue !== null) {\n onAutocompleteSelect(matchedValue);\n }\n }\n }, 50);\n }\n }}\n />\n </div>\n ) : null}\n\n <section\n ref={listboxContainerRef}\n tabIndex={-1}\n className={clsx(\n 'np-select-input-listbox-container',\n virtualized && 'np-select-input-listbox-container--virtualized',\n needle == null && // Groups aren't shown when filtering\n items.some((item) => item.type === 'group') &&\n 'np-select-input-listbox-container--has-group',\n )}\n data-wds-parent={parentId ?? undefined}\n >\n {resultsEmpty ? (\n <div id={statusId} className=\"np-select-input-options-status\">\n <CrossCircle size={16} className=\"np-select-input-options-status-icon\" />\n {intl.formatMessage(messages.noResultsFound)}\n </div>\n ) : null}\n\n <div\n ref={listboxRef}\n id={listboxId}\n role=\"listbox\"\n aria-orientation=\"vertical\"\n aria-label={listBoxLabel}\n aria-labelledby={listBoxLabelledBy}\n tabIndex={0}\n className=\"np-select-input-listbox\"\n >\n {!virtualized ? (\n filteredItems.map((_, index) => getItemNode(index))\n ) : (\n <Virtualizer\n ref={virtualiserHandlerRef}\n key={needle}\n data={filteredItems}\n keepMounted={mountedIndexes}\n scrollRef={listboxRef} // `VList` doesn't expose this\n onScroll={async () => {\n if (!virtualiserHandlerRef.current) return;\n\n const startIndex = virtualiserHandlerRef.current.findItemIndex(\n virtualiserHandlerRef.current.scrollOffset,\n );\n const endIndex = virtualiserHandlerRef.current.findItemIndex(\n virtualiserHandlerRef.current.scrollOffset +\n virtualiserHandlerRef.current.viewportSize,\n );\n\n setMountedIndexes((prevMountedIndexes) => {\n const indexes = new Set(prevMountedIndexes);\n\n for (let index = startIndex; index <= endIndex; index += 1) {\n indexes.add(index);\n }\n\n return [...indexes].sort((a, b) => a - b);\n });\n }}\n >\n {(item, index) => (\n // The position of each item can't be inferred by browsers when\n // virtualizing, as some of the items may not be in the DOM\n <SelectInputItemsCountContext.Provider value={filteredItems.length}>\n <SelectInputItemPositionContext.Provider value={index + 1}>\n {getItemNode(index)}\n </SelectInputItemPositionContext.Provider>\n </SelectInputItemsCountContext.Provider>\n )}\n </Virtualizer>\n )}\n </div>\n\n {renderFooter != null ? (\n <footer className=\"np-select-input-footer\">\n <div\n role=\"none\"\n onKeyDown={(event) => {\n // Prevent interfering with Headless UI\n if (event.key !== 'Escape') {\n event.stopPropagation();\n }\n }}\n >\n {renderFooter({\n resultsEmpty,\n queryNormalized: needle,\n })}\n </div>\n </footer>\n ) : null}\n </section>\n </ListboxOptions>\n );\n}\n"],"names":["MAX_ITEMS_WITHOUT_VIRTUALIZATION","SelectInputOptions","id","parentId","items","compareValues","compareValuesProp","renderValue","String","renderFooter","filterable","filterPlaceholder","sortFilteredOptions","searchInputRef","listboxRef","filterQuery","onFilterChange","listBoxLabel","listBoxLabelledBy","autocomplete","name","onAutocompleteSelect","intl","useIntl","virtualiserHandlerRef","useRef","controllerRef","initialRender","setInitialRender","useState","needle","useMemo","searchableString","undefined","useEffect","requestAnimationFrame","current","hasAttribute","dispatchEvent","KeyboardEvent","key","bubbles","a","b","filteredItems","filtered","filterSelectInputItems","dedupeSelectInputItems","item","selectInputOptionItemIncludesNeedle","sortSelectInputItems","resultsEmpty","length","virtualized","mountedIndexes","setMountedIndexes","prevMountedIndexes","indexes","Set","add","listboxContainerRef","style","setProperty","offsetHeight","showStatus","statusId","useId","listboxId","getItemNode","index","_jsx","SelectInputItemView","findMatchingItem","autocompleteValue","flatOptions","flatMap","type","options","filter","value","exactMatch","find","option","filterMatchers","some","matcher","fuzzyMatch","toLowerCase","includes","_jsxs","ListboxOptions","modal","as","SelectInputOptionsContainer","static","className","onAriaActiveDescendantChange","setAttribute","removeAttribute","children","SearchInput","ref","autoComplete","role","shape","placeholder","defaultValue","onKeyDown","event","test","stopPropagation","onChange","inputValue","currentTarget","onInput","inputElement","setTimeout","matchedValue","tabIndex","clsx","CrossCircle","size","formatMessage","messages","noResultsFound","map","_","Virtualizer","data","keepMounted","scrollRef","onScroll","startIndex","findItemIndex","scrollOffset","endIndex","viewportSize","sort","SelectInputItemsCountContext","Provider","SelectInputItemPositionContext","queryNormalized"],"mappings":"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"}
@@ -1,268 +0,0 @@
1
- import { ListboxOptions } from '@headlessui/react';
2
- import { CrossCircle } from '@transferwise/icons';
3
- import { clsx } from 'clsx';
4
- import { useRef, useState, useMemo, useEffect, useId } from 'react';
5
- import { useIntl } from 'react-intl';
6
- import { Virtualizer } from 'virtua';
7
- import { SearchInput } from '../../../SearchInput.mjs';
8
- import messages from '../../SelectInput.messages.mjs';
9
- import { searchableString, filterSelectInputItems, dedupeSelectInputItems, sortSelectInputItems, selectInputOptionItemIncludesNeedle } from '../../SelectInput.helpers.mjs';
10
- import { SelectInputOptionsContainer } from '../SelectInputOptionsContainer/SelectInputOptionsContainer.mjs';
11
- import { SelectInputItemView } from '../SelectInputItemView/SelectInputItemView.mjs';
12
- import { SelectInputItemsCountContext, SelectInputItemPositionContext } from '../SelectInputOption/SelectInputOption.mjs';
13
- import { jsxs, jsx } from 'react/jsx-runtime';
14
-
15
- const MAX_ITEMS_WITHOUT_VIRTUALIZATION = 50;
16
- function SelectInputOptions({
17
- id,
18
- parentId,
19
- items,
20
- compareValues: compareValuesProp,
21
- renderValue = String,
22
- renderFooter,
23
- filterable = false,
24
- filterPlaceholder,
25
- sortFilteredOptions,
26
- searchInputRef,
27
- listboxRef,
28
- filterQuery,
29
- onFilterChange,
30
- listBoxLabel,
31
- listBoxLabelledBy,
32
- autocomplete,
33
- name,
34
- onAutocompleteSelect
35
- }) {
36
- const intl = useIntl();
37
- const virtualiserHandlerRef = useRef(null);
38
- const controllerRef = filterable ? searchInputRef : listboxRef;
39
- const [initialRender, setInitialRender] = useState(true);
40
- const needle = useMemo(() => {
41
- if (filterable) {
42
- return filterQuery ? searchableString(filterQuery) : null;
43
- }
44
- return undefined;
45
- }, [filterQuery, filterable]);
46
- useEffect(() => {
47
- if (needle) {
48
- // Ensure having an active option while filtering.
49
- // Without `requestAnimationFrame` upon which React depends for scheduling
50
- // updates, the active status would only show for a split second and then
51
- // disappear inadvertently.
52
- requestAnimationFrame(() => {
53
- if (controllerRef.current != null && !controllerRef.current.hasAttribute('aria-activedescendant')) {
54
- // Activate first option via synthetic key press
55
- controllerRef.current.dispatchEvent(new KeyboardEvent('keydown', {
56
- key: 'Home',
57
- bubbles: true
58
- }));
59
- }
60
- });
61
- }
62
- }, [controllerRef, needle]);
63
- const compareValues = useMemo(() => {
64
- if (!compareValuesProp) {
65
- return undefined;
66
- }
67
- if (typeof compareValuesProp === 'function') {
68
- return (a, b) => compareValuesProp(a, b);
69
- }
70
- const key = compareValuesProp;
71
- return (a, b) => {
72
- if (typeof a === 'object' && a != null && typeof b === 'object' && b != null) {
73
- return a[key] === b[key];
74
- }
75
- return a === b;
76
- };
77
- }, [compareValuesProp]);
78
- const filteredItems = useMemo(() => {
79
- if (needle == null) {
80
- return items;
81
- }
82
- const filtered = filterSelectInputItems(dedupeSelectInputItems(items, compareValues), item => selectInputOptionItemIncludesNeedle(item, needle));
83
- if (sortFilteredOptions) {
84
- return sortSelectInputItems(filtered, sortFilteredOptions, filterQuery);
85
- }
86
- return filtered;
87
- // eslint-disable-next-line react-hooks/exhaustive-deps
88
- }, [needle, items, compareValues]);
89
- const resultsEmpty = needle != null && filteredItems.length === 0;
90
- const virtualized = filteredItems.length > MAX_ITEMS_WITHOUT_VIRTUALIZATION;
91
- // Items shown once shall be kept mounted until the needle changes, otherwise
92
- // the scroll position may jump around inadvertently. Pattern adopted from:
93
- // https://inokawa.github.io/virtua/?path=/story/advanced-keep-offscreen-items--append-only
94
- const [mountedIndexes, setMountedIndexes] = useState([]);
95
- useEffect(() => {
96
- // Ensure the 'End' key works as intended by keeping the last item mounted
97
- setMountedIndexes(prevMountedIndexes => {
98
- const indexes = new Set(prevMountedIndexes);
99
- indexes.add(filteredItems.length - 1);
100
- return [...indexes]; // Sorting is redundant by nature here
101
- });
102
- }, [needle,
103
- // Needed as `filteredItems.length` may be equal between two updates
104
- filteredItems.length]);
105
- const listboxContainerRef = useRef(null);
106
- useEffect(() => {
107
- if (listboxContainerRef.current != null) {
108
- listboxContainerRef.current.style.setProperty('--initial-height', `${listboxContainerRef.current.offsetHeight}px`);
109
- }
110
- }, []);
111
- useEffect(() => {
112
- setInitialRender(false);
113
- }, []);
114
- const showStatus = resultsEmpty;
115
- const statusId = useId();
116
- const listboxId = useId();
117
- const getItemNode = index => {
118
- const item = filteredItems[index];
119
- return /*#__PURE__*/jsx(SelectInputItemView, {
120
- item: item,
121
- renderValue: renderValue,
122
- needle: needle
123
- }, index);
124
- };
125
- const findMatchingItem = autocompleteValue => {
126
- const flatOptions = items.flatMap(item => item.type === 'group' ? item.options : item.type === 'option' ? [item] : []).filter(item => item.type === 'option' && item.value != null);
127
- const exactMatch = flatOptions.find(option => String(option.value) === autocompleteValue || option.filterMatchers?.some(matcher => matcher === autocompleteValue));
128
- if (exactMatch) {
129
- return exactMatch.value;
130
- }
131
- const fuzzyMatch = flatOptions.find(option => option.filterMatchers?.some(matcher => matcher.toLowerCase().includes(autocompleteValue.toLowerCase())));
132
- return fuzzyMatch ? fuzzyMatch.value : null;
133
- };
134
- return /*#__PURE__*/jsxs(ListboxOptions, {
135
- modal: true,
136
- as: SelectInputOptionsContainer,
137
- static: true,
138
- className: "np-select-input-options-container",
139
- onAriaActiveDescendantChange: value => {
140
- if (controllerRef.current != null) {
141
- if (!initialRender && value != null) {
142
- controllerRef.current.setAttribute('aria-activedescendant', value);
143
- } else {
144
- controllerRef.current.removeAttribute('aria-activedescendant');
145
- }
146
- }
147
- },
148
- children: [filterable ? /*#__PURE__*/jsx("div", {
149
- className: "np-select-input-query-container",
150
- children: /*#__PURE__*/jsx(SearchInput, {
151
- ref: searchInputRef,
152
- id: id,
153
- name: name,
154
- autoComplete: autocomplete,
155
- role: "combobox",
156
- shape: "rectangle",
157
- placeholder: filterPlaceholder,
158
- "aria-label": filterPlaceholder,
159
- defaultValue: filterQuery,
160
- "aria-autocomplete": "list",
161
- "aria-expanded": true,
162
- "aria-controls": listboxId,
163
- "aria-describedby": showStatus ? statusId : undefined,
164
- onKeyDown: event => {
165
- // Prevent interfering with the matcher of Headless UI
166
- // https://mathiasbynens.be/notes/javascript-unicode#regex
167
- if (/^.$/u.test(event.key)) {
168
- event.stopPropagation();
169
- }
170
- },
171
- onChange: event => {
172
- // Free up resources and ensure not to go out of bounds when the
173
- // resulting item count is less than before
174
- const inputValue = event.currentTarget.value;
175
- // Free up resources and ensure not to go out of bounds
176
- setMountedIndexes([]);
177
- onFilterChange(inputValue);
178
- },
179
- onInput: event => {
180
- const inputValue = event.currentTarget.value;
181
- const inputElement = event.currentTarget;
182
- if (autocomplete && onAutocompleteSelect && inputValue) {
183
- setTimeout(() => {
184
- if (inputElement.value === inputValue && inputValue.length > 2) {
185
- const matchedValue = findMatchingItem(inputValue);
186
- if (matchedValue !== null) {
187
- onAutocompleteSelect(matchedValue);
188
- }
189
- }
190
- }, 50);
191
- }
192
- }
193
- })
194
- }) : null, /*#__PURE__*/jsxs("section", {
195
- ref: listboxContainerRef,
196
- tabIndex: -1,
197
- className: clsx('np-select-input-listbox-container', virtualized && 'np-select-input-listbox-container--virtualized', needle == null &&
198
- // Groups aren't shown when filtering
199
- items.some(item => item.type === 'group') && 'np-select-input-listbox-container--has-group'),
200
- "data-wds-parent": parentId ?? undefined,
201
- children: [resultsEmpty ? /*#__PURE__*/jsxs("div", {
202
- id: statusId,
203
- className: "np-select-input-options-status",
204
- children: [/*#__PURE__*/jsx(CrossCircle, {
205
- size: 16,
206
- className: "np-select-input-options-status-icon"
207
- }), intl.formatMessage(messages.noResultsFound)]
208
- }) : null, /*#__PURE__*/jsx("div", {
209
- ref: listboxRef,
210
- id: listboxId,
211
- role: "listbox",
212
- "aria-orientation": "vertical",
213
- "aria-label": listBoxLabel,
214
- "aria-labelledby": listBoxLabelledBy,
215
- tabIndex: 0,
216
- className: "np-select-input-listbox",
217
- children: !virtualized ? filteredItems.map((_, index) => getItemNode(index)) : /*#__PURE__*/jsx(Virtualizer, {
218
- ref: virtualiserHandlerRef,
219
- data: filteredItems,
220
- keepMounted: mountedIndexes,
221
- scrollRef: listboxRef // `VList` doesn't expose this
222
- ,
223
- onScroll: async () => {
224
- if (!virtualiserHandlerRef.current) return;
225
- const startIndex = virtualiserHandlerRef.current.findItemIndex(virtualiserHandlerRef.current.scrollOffset);
226
- const endIndex = virtualiserHandlerRef.current.findItemIndex(virtualiserHandlerRef.current.scrollOffset + virtualiserHandlerRef.current.viewportSize);
227
- setMountedIndexes(prevMountedIndexes => {
228
- const indexes = new Set(prevMountedIndexes);
229
- for (let index = startIndex; index <= endIndex; index += 1) {
230
- indexes.add(index);
231
- }
232
- return [...indexes].sort((a, b) => a - b);
233
- });
234
- },
235
- children: (item, index) =>
236
- /*#__PURE__*/
237
- // The position of each item can't be inferred by browsers when
238
- // virtualizing, as some of the items may not be in the DOM
239
- jsx(SelectInputItemsCountContext.Provider, {
240
- value: filteredItems.length,
241
- children: /*#__PURE__*/jsx(SelectInputItemPositionContext.Provider, {
242
- value: index + 1,
243
- children: getItemNode(index)
244
- })
245
- })
246
- }, needle)
247
- }), renderFooter != null ? /*#__PURE__*/jsx("footer", {
248
- className: "np-select-input-footer",
249
- children: /*#__PURE__*/jsx("div", {
250
- role: "none",
251
- onKeyDown: event => {
252
- // Prevent interfering with Headless UI
253
- if (event.key !== 'Escape') {
254
- event.stopPropagation();
255
- }
256
- },
257
- children: renderFooter({
258
- resultsEmpty,
259
- queryNormalized: needle
260
- })
261
- })
262
- }) : null]
263
- })]
264
- });
265
- }
266
-
267
- export { SelectInputOptions };
268
- //# sourceMappingURL=SelectInputOptions.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SelectInputOptions.mjs","sources":["../../../../../src/inputs/SelectInput/components/SelectInputOptions/SelectInputOptions.tsx"],"sourcesContent":["import { ListboxOptions } from '@headlessui/react';\nimport { CrossCircle } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport { useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { useIntl } from 'react-intl';\nimport { Virtualizer, type VirtualizerHandle } from 'virtua';\n\nimport { SearchInput } from '../../../SearchInput';\nimport messages from '../../SelectInput.messages';\nimport { SelectInputProps, SelectInputOptionItem, SelectInputItem } from '../../SelectInput.types';\nimport {\n searchableString,\n dedupeSelectInputItems,\n filterSelectInputItems,\n selectInputOptionItemIncludesNeedle,\n sortSelectInputItems,\n} from '../../SelectInput.helpers';\n\nimport { SelectInputOptionsContainer } from '../SelectInputOptionsContainer';\nimport { SelectInputItemView } from '../SelectInputItemView';\nimport { SelectInputItemsCountContext, SelectInputItemPositionContext } from '../SelectInputOption';\n\nconst MAX_ITEMS_WITHOUT_VIRTUALIZATION = 50;\n\ninterface SelectInputOptionsProps<T = string> extends Pick<\n SelectInputProps<T>,\n | 'items'\n | 'renderValue'\n | 'renderFooter'\n | 'filterable'\n | 'filterPlaceholder'\n | 'id'\n | 'parentId'\n | 'compareValues'\n | 'sortFilteredOptions'\n> {\n searchInputRef: React.MutableRefObject<HTMLInputElement | null>;\n listboxRef: React.MutableRefObject<HTMLDivElement | null>;\n filterQuery: string;\n onFilterChange: (query: string) => void;\n listBoxLabel?: string;\n listBoxLabelledBy?: string;\n autocomplete?: string;\n name?: string;\n onAutocompleteSelect?: (value: T) => void;\n}\n\nexport function SelectInputOptions<T = string>({\n id,\n parentId,\n items,\n compareValues: compareValuesProp,\n renderValue = String,\n renderFooter,\n filterable = false,\n filterPlaceholder,\n sortFilteredOptions,\n searchInputRef,\n listboxRef,\n filterQuery,\n onFilterChange,\n listBoxLabel,\n listBoxLabelledBy,\n autocomplete,\n name,\n onAutocompleteSelect,\n}: SelectInputOptionsProps<T>) {\n const intl = useIntl();\n const virtualiserHandlerRef = useRef<VirtualizerHandle>(null);\n const controllerRef = filterable ? searchInputRef : listboxRef;\n const [initialRender, setInitialRender] = useState(true);\n\n const needle = useMemo(() => {\n if (filterable) {\n return filterQuery ? searchableString(filterQuery) : null;\n }\n return undefined;\n }, [filterQuery, filterable]);\n\n useEffect(() => {\n if (needle) {\n // Ensure having an active option while filtering.\n // Without `requestAnimationFrame` upon which React depends for scheduling\n // updates, the active status would only show for a split second and then\n // disappear inadvertently.\n requestAnimationFrame(() => {\n if (\n controllerRef.current != null &&\n !controllerRef.current.hasAttribute('aria-activedescendant')\n ) {\n // Activate first option via synthetic key press\n controllerRef.current.dispatchEvent(\n new KeyboardEvent('keydown', { key: 'Home', bubbles: true }),\n );\n }\n });\n }\n }, [controllerRef, needle]);\n\n const compareValues = useMemo(() => {\n if (!compareValuesProp) {\n return undefined;\n }\n\n if (typeof compareValuesProp === 'function') {\n return (a: NonNullable<T>, b: NonNullable<T>) => compareValuesProp(a, b);\n }\n\n const key = compareValuesProp;\n return (a: NonNullable<T>, b: NonNullable<T>) => {\n if (typeof a === 'object' && a != null && typeof b === 'object' && b != null) {\n return (a as Record<string, unknown>)[key] === (b as Record<string, unknown>)[key];\n }\n return a === b;\n };\n }, [compareValuesProp]);\n\n const filteredItems: readonly SelectInputItem<NonNullable<T> | undefined>[] = useMemo(() => {\n if (needle == null) {\n return items;\n }\n\n const filtered = filterSelectInputItems(dedupeSelectInputItems(items, compareValues), (item) =>\n selectInputOptionItemIncludesNeedle(item, needle),\n );\n\n if (sortFilteredOptions) {\n return sortSelectInputItems(filtered, sortFilteredOptions, filterQuery);\n }\n\n return filtered;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [needle, items, compareValues]);\n const resultsEmpty = needle != null && filteredItems.length === 0;\n\n const virtualized = filteredItems.length > MAX_ITEMS_WITHOUT_VIRTUALIZATION;\n\n // Items shown once shall be kept mounted until the needle changes, otherwise\n // the scroll position may jump around inadvertently. Pattern adopted from:\n // https://inokawa.github.io/virtua/?path=/story/advanced-keep-offscreen-items--append-only\n const [mountedIndexes, setMountedIndexes] = useState<number[]>([]);\n useEffect(() => {\n // Ensure the 'End' key works as intended by keeping the last item mounted\n setMountedIndexes((prevMountedIndexes) => {\n const indexes = new Set(prevMountedIndexes);\n indexes.add(filteredItems.length - 1);\n return [...indexes]; // Sorting is redundant by nature here\n });\n }, [\n needle, // Needed as `filteredItems.length` may be equal between two updates\n filteredItems.length,\n ]);\n\n const listboxContainerRef = useRef<HTMLDivElement>(null);\n useEffect(() => {\n if (listboxContainerRef.current != null) {\n listboxContainerRef.current.style.setProperty(\n '--initial-height',\n `${listboxContainerRef.current.offsetHeight}px`,\n );\n }\n }, []);\n\n useEffect(() => {\n setInitialRender(false);\n }, []);\n\n const showStatus = resultsEmpty;\n const statusId = useId();\n const listboxId = useId();\n\n const getItemNode = (index: number) => {\n const item = filteredItems[index];\n return (\n <SelectInputItemView key={index} item={item} renderValue={renderValue} needle={needle} />\n );\n };\n\n const findMatchingItem = (autocompleteValue: string): T | null => {\n const flatOptions = items\n .flatMap((item) =>\n item.type === 'group' ? item.options : item.type === 'option' ? [item] : [],\n )\n .filter(\n (item): item is SelectInputOptionItem<NonNullable<T>> =>\n item.type === 'option' && item.value != null,\n );\n\n const exactMatch = flatOptions.find(\n (option) =>\n String(option.value) === autocompleteValue ||\n option.filterMatchers?.some((matcher) => matcher === autocompleteValue),\n );\n\n if (exactMatch) {\n return exactMatch.value;\n }\n\n const fuzzyMatch = flatOptions.find((option) =>\n option.filterMatchers?.some((matcher) =>\n matcher.toLowerCase().includes(autocompleteValue.toLowerCase()),\n ),\n );\n\n return fuzzyMatch ? fuzzyMatch.value : null;\n };\n\n return (\n <ListboxOptions\n modal\n as={SelectInputOptionsContainer}\n static\n className=\"np-select-input-options-container\"\n onAriaActiveDescendantChange={(value: React.AriaAttributes['aria-activedescendant']) => {\n if (controllerRef.current != null) {\n if (!initialRender && value != null) {\n controllerRef.current.setAttribute('aria-activedescendant', value);\n } else {\n controllerRef.current.removeAttribute('aria-activedescendant');\n }\n }\n }}\n >\n {filterable ? (\n <div className=\"np-select-input-query-container\">\n <SearchInput\n ref={searchInputRef}\n id={id}\n name={name}\n autoComplete={autocomplete}\n role=\"combobox\"\n shape=\"rectangle\"\n placeholder={filterPlaceholder}\n aria-label={filterPlaceholder}\n defaultValue={filterQuery}\n aria-autocomplete=\"list\"\n aria-expanded\n aria-controls={listboxId}\n aria-describedby={showStatus ? statusId : undefined}\n onKeyDown={(event) => {\n // Prevent interfering with the matcher of Headless UI\n // https://mathiasbynens.be/notes/javascript-unicode#regex\n if (/^.$/u.test(event.key)) {\n event.stopPropagation();\n }\n }}\n onChange={(event) => {\n // Free up resources and ensure not to go out of bounds when the\n // resulting item count is less than before\n const inputValue = event.currentTarget.value;\n\n // Free up resources and ensure not to go out of bounds\n setMountedIndexes([]);\n onFilterChange(inputValue);\n }}\n onInput={(event) => {\n const inputValue = event.currentTarget.value;\n const inputElement = event.currentTarget;\n\n if (autocomplete && onAutocompleteSelect && inputValue) {\n setTimeout(() => {\n if (inputElement.value === inputValue && inputValue.length > 2) {\n const matchedValue = findMatchingItem(inputValue);\n if (matchedValue !== null) {\n onAutocompleteSelect(matchedValue);\n }\n }\n }, 50);\n }\n }}\n />\n </div>\n ) : null}\n\n <section\n ref={listboxContainerRef}\n tabIndex={-1}\n className={clsx(\n 'np-select-input-listbox-container',\n virtualized && 'np-select-input-listbox-container--virtualized',\n needle == null && // Groups aren't shown when filtering\n items.some((item) => item.type === 'group') &&\n 'np-select-input-listbox-container--has-group',\n )}\n data-wds-parent={parentId ?? undefined}\n >\n {resultsEmpty ? (\n <div id={statusId} className=\"np-select-input-options-status\">\n <CrossCircle size={16} className=\"np-select-input-options-status-icon\" />\n {intl.formatMessage(messages.noResultsFound)}\n </div>\n ) : null}\n\n <div\n ref={listboxRef}\n id={listboxId}\n role=\"listbox\"\n aria-orientation=\"vertical\"\n aria-label={listBoxLabel}\n aria-labelledby={listBoxLabelledBy}\n tabIndex={0}\n className=\"np-select-input-listbox\"\n >\n {!virtualized ? (\n filteredItems.map((_, index) => getItemNode(index))\n ) : (\n <Virtualizer\n ref={virtualiserHandlerRef}\n key={needle}\n data={filteredItems}\n keepMounted={mountedIndexes}\n scrollRef={listboxRef} // `VList` doesn't expose this\n onScroll={async () => {\n if (!virtualiserHandlerRef.current) return;\n\n const startIndex = virtualiserHandlerRef.current.findItemIndex(\n virtualiserHandlerRef.current.scrollOffset,\n );\n const endIndex = virtualiserHandlerRef.current.findItemIndex(\n virtualiserHandlerRef.current.scrollOffset +\n virtualiserHandlerRef.current.viewportSize,\n );\n\n setMountedIndexes((prevMountedIndexes) => {\n const indexes = new Set(prevMountedIndexes);\n\n for (let index = startIndex; index <= endIndex; index += 1) {\n indexes.add(index);\n }\n\n return [...indexes].sort((a, b) => a - b);\n });\n }}\n >\n {(item, index) => (\n // The position of each item can't be inferred by browsers when\n // virtualizing, as some of the items may not be in the DOM\n <SelectInputItemsCountContext.Provider value={filteredItems.length}>\n <SelectInputItemPositionContext.Provider value={index + 1}>\n {getItemNode(index)}\n </SelectInputItemPositionContext.Provider>\n </SelectInputItemsCountContext.Provider>\n )}\n </Virtualizer>\n )}\n </div>\n\n {renderFooter != null ? (\n <footer className=\"np-select-input-footer\">\n <div\n role=\"none\"\n onKeyDown={(event) => {\n // Prevent interfering with Headless UI\n if (event.key !== 'Escape') {\n event.stopPropagation();\n }\n }}\n >\n {renderFooter({\n resultsEmpty,\n queryNormalized: needle,\n })}\n </div>\n </footer>\n ) : null}\n </section>\n </ListboxOptions>\n );\n}\n"],"names":["MAX_ITEMS_WITHOUT_VIRTUALIZATION","SelectInputOptions","id","parentId","items","compareValues","compareValuesProp","renderValue","String","renderFooter","filterable","filterPlaceholder","sortFilteredOptions","searchInputRef","listboxRef","filterQuery","onFilterChange","listBoxLabel","listBoxLabelledBy","autocomplete","name","onAutocompleteSelect","intl","useIntl","virtualiserHandlerRef","useRef","controllerRef","initialRender","setInitialRender","useState","needle","useMemo","searchableString","undefined","useEffect","requestAnimationFrame","current","hasAttribute","dispatchEvent","KeyboardEvent","key","bubbles","a","b","filteredItems","filtered","filterSelectInputItems","dedupeSelectInputItems","item","selectInputOptionItemIncludesNeedle","sortSelectInputItems","resultsEmpty","length","virtualized","mountedIndexes","setMountedIndexes","prevMountedIndexes","indexes","Set","add","listboxContainerRef","style","setProperty","offsetHeight","showStatus","statusId","useId","listboxId","getItemNode","index","_jsx","SelectInputItemView","findMatchingItem","autocompleteValue","flatOptions","flatMap","type","options","filter","value","exactMatch","find","option","filterMatchers","some","matcher","fuzzyMatch","toLowerCase","includes","_jsxs","ListboxOptions","modal","as","SelectInputOptionsContainer","static","className","onAriaActiveDescendantChange","setAttribute","removeAttribute","children","SearchInput","ref","autoComplete","role","shape","placeholder","defaultValue","onKeyDown","event","test","stopPropagation","onChange","inputValue","currentTarget","onInput","inputElement","setTimeout","matchedValue","tabIndex","clsx","CrossCircle","size","formatMessage","messages","noResultsFound","map","_","Virtualizer","data","keepMounted","scrollRef","onScroll","startIndex","findItemIndex","scrollOffset","endIndex","viewportSize","sort","SelectInputItemsCountContext","Provider","SelectInputItemPositionContext","queryNormalized"],"mappings":"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"}