@transferwise/components 46.97.5 → 46.98.1

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 (293) hide show
  1. package/build/alert/Alert.js +8 -0
  2. package/build/alert/Alert.js.map +1 -1
  3. package/build/alert/Alert.mjs +8 -0
  4. package/build/alert/Alert.mjs.map +1 -1
  5. package/build/common/closeButton/CloseButton.js +3 -1
  6. package/build/common/closeButton/CloseButton.js.map +1 -1
  7. package/build/common/closeButton/CloseButton.mjs +3 -1
  8. package/build/common/closeButton/CloseButton.mjs.map +1 -1
  9. package/build/dateInput/DateInput.js +4 -4
  10. package/build/dateInput/DateInput.js.map +1 -1
  11. package/build/dateInput/DateInput.mjs +4 -4
  12. package/build/dateInput/DateInput.mjs.map +1 -1
  13. package/build/dateLookup/DateLookup.js +4 -4
  14. package/build/dateLookup/DateLookup.js.map +1 -1
  15. package/build/dateLookup/DateLookup.mjs +4 -4
  16. package/build/dateLookup/DateLookup.mjs.map +1 -1
  17. package/build/dateLookup/dayCalendar/table/DayCalendarTable.js +3 -3
  18. package/build/dateLookup/dayCalendar/table/DayCalendarTable.js.map +1 -1
  19. package/build/dateLookup/dayCalendar/table/DayCalendarTable.mjs +3 -3
  20. package/build/dateLookup/dayCalendar/table/DayCalendarTable.mjs.map +1 -1
  21. package/build/i18n/cs.json +3 -2
  22. package/build/i18n/cs.json.js +3 -2
  23. package/build/i18n/cs.json.js.map +1 -1
  24. package/build/i18n/cs.json.mjs +3 -2
  25. package/build/i18n/cs.json.mjs.map +1 -1
  26. package/build/i18n/de.json +3 -2
  27. package/build/i18n/de.json.js +3 -2
  28. package/build/i18n/de.json.js.map +1 -1
  29. package/build/i18n/de.json.mjs +3 -2
  30. package/build/i18n/de.json.mjs.map +1 -1
  31. package/build/i18n/en.json +3 -2
  32. package/build/i18n/en.json.js +3 -2
  33. package/build/i18n/en.json.js.map +1 -1
  34. package/build/i18n/en.json.mjs +3 -2
  35. package/build/i18n/en.json.mjs.map +1 -1
  36. package/build/i18n/es.json +3 -2
  37. package/build/i18n/es.json.js +3 -2
  38. package/build/i18n/es.json.js.map +1 -1
  39. package/build/i18n/es.json.mjs +3 -2
  40. package/build/i18n/es.json.mjs.map +1 -1
  41. package/build/i18n/fr.json +3 -2
  42. package/build/i18n/fr.json.js +3 -2
  43. package/build/i18n/fr.json.js.map +1 -1
  44. package/build/i18n/fr.json.mjs +3 -2
  45. package/build/i18n/fr.json.mjs.map +1 -1
  46. package/build/i18n/hu.json +3 -2
  47. package/build/i18n/hu.json.js +3 -2
  48. package/build/i18n/hu.json.js.map +1 -1
  49. package/build/i18n/hu.json.mjs +3 -2
  50. package/build/i18n/hu.json.mjs.map +1 -1
  51. package/build/i18n/id.json +3 -2
  52. package/build/i18n/id.json.js +3 -2
  53. package/build/i18n/id.json.js.map +1 -1
  54. package/build/i18n/id.json.mjs +3 -2
  55. package/build/i18n/id.json.mjs.map +1 -1
  56. package/build/i18n/it.json +3 -2
  57. package/build/i18n/it.json.js +3 -2
  58. package/build/i18n/it.json.js.map +1 -1
  59. package/build/i18n/it.json.mjs +3 -2
  60. package/build/i18n/it.json.mjs.map +1 -1
  61. package/build/i18n/ja.json +3 -2
  62. package/build/i18n/ja.json.js +3 -2
  63. package/build/i18n/ja.json.js.map +1 -1
  64. package/build/i18n/ja.json.mjs +3 -2
  65. package/build/i18n/ja.json.mjs.map +1 -1
  66. package/build/i18n/nl.json +6 -5
  67. package/build/i18n/pl.json +3 -2
  68. package/build/i18n/pl.json.js +3 -2
  69. package/build/i18n/pl.json.js.map +1 -1
  70. package/build/i18n/pl.json.mjs +3 -2
  71. package/build/i18n/pl.json.mjs.map +1 -1
  72. package/build/i18n/pt.json +3 -2
  73. package/build/i18n/pt.json.js +3 -2
  74. package/build/i18n/pt.json.js.map +1 -1
  75. package/build/i18n/pt.json.mjs +3 -2
  76. package/build/i18n/pt.json.mjs.map +1 -1
  77. package/build/i18n/ro.json +3 -2
  78. package/build/i18n/ro.json.js +3 -2
  79. package/build/i18n/ro.json.js.map +1 -1
  80. package/build/i18n/ro.json.mjs +3 -2
  81. package/build/i18n/ro.json.mjs.map +1 -1
  82. package/build/i18n/ru.json +3 -2
  83. package/build/i18n/ru.json.js +3 -2
  84. package/build/i18n/ru.json.js.map +1 -1
  85. package/build/i18n/ru.json.mjs +3 -2
  86. package/build/i18n/ru.json.mjs.map +1 -1
  87. package/build/i18n/th.json +3 -2
  88. package/build/i18n/th.json.js +3 -2
  89. package/build/i18n/th.json.js.map +1 -1
  90. package/build/i18n/th.json.mjs +3 -2
  91. package/build/i18n/th.json.mjs.map +1 -1
  92. package/build/i18n/tr.json +3 -2
  93. package/build/i18n/tr.json.js +3 -2
  94. package/build/i18n/tr.json.js.map +1 -1
  95. package/build/i18n/tr.json.mjs +3 -2
  96. package/build/i18n/tr.json.mjs.map +1 -1
  97. package/build/i18n/zh-CN.json +3 -2
  98. package/build/i18n/zh-CN.json.js +3 -2
  99. package/build/i18n/zh-CN.json.js.map +1 -1
  100. package/build/i18n/zh-CN.json.mjs +3 -2
  101. package/build/i18n/zh-CN.json.mjs.map +1 -1
  102. package/build/i18n/zh-HK.json +3 -2
  103. package/build/i18n/zh-HK.json.js +3 -2
  104. package/build/i18n/zh-HK.json.js.map +1 -1
  105. package/build/i18n/zh-HK.json.mjs +3 -2
  106. package/build/i18n/zh-HK.json.mjs.map +1 -1
  107. package/build/image/Image.js +9 -10
  108. package/build/image/Image.js.map +1 -1
  109. package/build/image/Image.mjs +11 -11
  110. package/build/image/Image.mjs.map +1 -1
  111. package/build/index.js +0 -2
  112. package/build/index.js.map +1 -1
  113. package/build/index.mjs +0 -1
  114. package/build/index.mjs.map +1 -1
  115. package/build/main.css +16 -45
  116. package/build/moneyInput/MoneyInput.js +4 -8
  117. package/build/moneyInput/MoneyInput.js.map +1 -1
  118. package/build/moneyInput/MoneyInput.messages.js +3 -0
  119. package/build/moneyInput/MoneyInput.messages.js.map +1 -1
  120. package/build/moneyInput/MoneyInput.messages.mjs +3 -0
  121. package/build/moneyInput/MoneyInput.messages.mjs.map +1 -1
  122. package/build/moneyInput/MoneyInput.mjs +4 -8
  123. package/build/moneyInput/MoneyInput.mjs.map +1 -1
  124. package/build/phoneNumberInput/PhoneNumberInput.js +36 -2
  125. package/build/phoneNumberInput/PhoneNumberInput.js.map +1 -1
  126. package/build/phoneNumberInput/PhoneNumberInput.messages.js +6 -0
  127. package/build/phoneNumberInput/PhoneNumberInput.messages.js.map +1 -1
  128. package/build/phoneNumberInput/PhoneNumberInput.messages.mjs +6 -0
  129. package/build/phoneNumberInput/PhoneNumberInput.messages.mjs.map +1 -1
  130. package/build/phoneNumberInput/PhoneNumberInput.mjs +36 -2
  131. package/build/phoneNumberInput/PhoneNumberInput.mjs.map +1 -1
  132. package/build/snackbar/Snackbar.js +1 -1
  133. package/build/snackbar/Snackbar.js.map +1 -1
  134. package/build/snackbar/Snackbar.mjs +1 -1
  135. package/build/snackbar/Snackbar.mjs.map +1 -1
  136. package/build/styles/circularButton/CircularButton.css +1 -0
  137. package/build/styles/dateInput/DateInput.css +13 -0
  138. package/build/styles/main.css +16 -45
  139. package/build/styles/uploadInput/uploadItem/UploadItem.css +2 -1
  140. package/build/tabs/Tabs.js +3 -3
  141. package/build/tabs/Tabs.js.map +1 -1
  142. package/build/tabs/Tabs.mjs +3 -3
  143. package/build/tabs/Tabs.mjs.map +1 -1
  144. package/build/test-utils/assets/apple-pay-logo.svg +84 -0
  145. package/build/typeahead/Typeahead.js +2 -2
  146. package/build/typeahead/Typeahead.js.map +1 -1
  147. package/build/typeahead/Typeahead.mjs +2 -2
  148. package/build/typeahead/Typeahead.mjs.map +1 -1
  149. package/build/typeahead/typeaheadInput/TypeaheadInput.js +2 -2
  150. package/build/typeahead/typeaheadInput/TypeaheadInput.js.map +1 -1
  151. package/build/typeahead/typeaheadInput/TypeaheadInput.mjs +2 -2
  152. package/build/typeahead/typeaheadInput/TypeaheadInput.mjs.map +1 -1
  153. package/build/types/alert/Alert.d.ts.map +1 -1
  154. package/build/types/common/closeButton/CloseButton.d.ts +2 -0
  155. package/build/types/common/closeButton/CloseButton.d.ts.map +1 -1
  156. package/build/types/image/Image.d.ts +0 -1
  157. package/build/types/image/Image.d.ts.map +1 -1
  158. package/build/types/index.d.ts +0 -2
  159. package/build/types/index.d.ts.map +1 -1
  160. package/build/types/moneyInput/MoneyInput.d.ts.map +1 -1
  161. package/build/types/moneyInput/MoneyInput.messages.d.ts +5 -0
  162. package/build/types/moneyInput/MoneyInput.messages.d.ts.map +1 -1
  163. package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
  164. package/build/types/phoneNumberInput/PhoneNumberInput.messages.d.ts +8 -0
  165. package/build/types/phoneNumberInput/PhoneNumberInput.messages.d.ts.map +1 -1
  166. package/build/types/test-utils/fake-data.d.ts +2 -0
  167. package/build/types/test-utils/fake-data.d.ts.map +1 -1
  168. package/build/types/test-utils/index.d.ts +6 -4
  169. package/build/types/test-utils/index.d.ts.map +1 -1
  170. package/build/types/upload/Upload.d.ts +1 -2
  171. package/build/types/upload/Upload.d.ts.map +1 -1
  172. package/build/types/upload/steps/processingStep/processingStep.d.ts +1 -3
  173. package/build/types/upload/steps/processingStep/processingStep.d.ts.map +1 -1
  174. package/build/types/uploadInput/UploadInput.d.ts.map +1 -1
  175. package/build/types/uploadInput/uploadItem/UploadItem.d.ts +1 -1
  176. package/build/types/uploadInput/uploadItem/UploadItem.d.ts.map +1 -1
  177. package/build/types/withDisplayFormat/WithDisplayFormat.d.ts.map +1 -1
  178. package/build/upload/Upload.js +29 -45
  179. package/build/upload/Upload.js.map +1 -1
  180. package/build/upload/Upload.mjs +29 -45
  181. package/build/upload/Upload.mjs.map +1 -1
  182. package/build/upload/steps/processingStep/processingStep.js +1 -3
  183. package/build/upload/steps/processingStep/processingStep.js.map +1 -1
  184. package/build/upload/steps/processingStep/processingStep.mjs +1 -3
  185. package/build/upload/steps/processingStep/processingStep.mjs.map +1 -1
  186. package/build/upload/steps/uploadImageStep/uploadImageStep.js +1 -1
  187. package/build/upload/steps/uploadImageStep/uploadImageStep.js.map +1 -1
  188. package/build/upload/steps/uploadImageStep/uploadImageStep.mjs +1 -1
  189. package/build/upload/steps/uploadImageStep/uploadImageStep.mjs.map +1 -1
  190. package/build/uploadInput/UploadInput.js +54 -6
  191. package/build/uploadInput/UploadInput.js.map +1 -1
  192. package/build/uploadInput/UploadInput.mjs +54 -6
  193. package/build/uploadInput/UploadInput.mjs.map +1 -1
  194. package/build/uploadInput/uploadItem/UploadItem.js +12 -6
  195. package/build/uploadInput/uploadItem/UploadItem.js.map +1 -1
  196. package/build/uploadInput/uploadItem/UploadItem.mjs +12 -6
  197. package/build/uploadInput/uploadItem/UploadItem.mjs.map +1 -1
  198. package/build/withDisplayFormat/WithDisplayFormat.js +3 -2
  199. package/build/withDisplayFormat/WithDisplayFormat.js.map +1 -1
  200. package/build/withDisplayFormat/WithDisplayFormat.mjs +3 -2
  201. package/build/withDisplayFormat/WithDisplayFormat.mjs.map +1 -1
  202. package/package.json +14 -17
  203. package/src/alert/Alert.spec.tsx +11 -0
  204. package/src/alert/Alert.story.tsx +23 -9
  205. package/src/alert/Alert.tsx +14 -1
  206. package/src/circularButton/CircularButton.css +1 -0
  207. package/src/circularButton/CircularButton.less +1 -0
  208. package/src/circularButton/CircularButton.tests.story.tsx +23 -0
  209. package/src/common/closeButton/CloseButton.spec.tsx +13 -1
  210. package/src/common/closeButton/CloseButton.tsx +3 -0
  211. package/src/dateInput/DateInput.css +13 -0
  212. package/src/dateInput/DateInput.less +20 -0
  213. package/src/dateInput/DateInput.tests.story.tsx +14 -3
  214. package/src/dateInput/DateInput.tsx +4 -4
  215. package/src/i18n/cs.json +3 -2
  216. package/src/i18n/de.json +3 -2
  217. package/src/i18n/en.json +3 -2
  218. package/src/i18n/es.json +3 -2
  219. package/src/i18n/fr.json +3 -2
  220. package/src/i18n/hu.json +3 -2
  221. package/src/i18n/id.json +3 -2
  222. package/src/i18n/it.json +3 -2
  223. package/src/i18n/ja.json +3 -2
  224. package/src/i18n/nl.json +6 -5
  225. package/src/i18n/pl.json +3 -2
  226. package/src/i18n/pt.json +3 -2
  227. package/src/i18n/ro.json +3 -2
  228. package/src/i18n/ru.json +3 -2
  229. package/src/i18n/th.json +3 -2
  230. package/src/i18n/tr.json +3 -2
  231. package/src/i18n/zh-CN.json +3 -2
  232. package/src/i18n/zh-HK.json +3 -2
  233. package/src/image/Image.spec.tsx +3 -3
  234. package/src/image/Image.tsx +10 -12
  235. package/src/index.ts +0 -2
  236. package/src/legacylistItem/LegacyListItem.story.tsx +5 -5
  237. package/src/legacylistItem/LegacyListItem.tests.story.tsx +6 -6
  238. package/src/main.css +16 -45
  239. package/src/main.less +0 -1
  240. package/src/moneyInput/MoneyInput.messages.ts +5 -0
  241. package/src/moneyInput/MoneyInput.spec.tsx +42 -5
  242. package/src/moneyInput/MoneyInput.story.tsx +11 -2
  243. package/src/moneyInput/MoneyInput.tsx +5 -7
  244. package/src/phoneNumberInput/PhoneNumberInput.messages.ts +8 -0
  245. package/src/phoneNumberInput/PhoneNumberInput.spec.tsx +77 -43
  246. package/src/phoneNumberInput/PhoneNumberInput.tsx +34 -2
  247. package/src/promoCard/__snapshots__/PromoCard.spec.tsx.snap +1 -0
  248. package/src/promoCard/__snapshots__/PromoCardGroup.spec.tsx.snap +2 -0
  249. package/src/ssr.spec.tsx +0 -1
  250. package/src/test-utils/assets/apple-pay-logo.svg +84 -0
  251. package/src/test-utils/fake-data.ts +5 -0
  252. package/src/test-utils/jest.setup.ts +0 -4
  253. package/src/typeahead/Typeahead.spec.tsx +182 -0
  254. package/src/typeahead/typeaheadInput/TypeaheadInput.spec.tsx +103 -0
  255. package/src/typeahead/util/highlight.spec.tsx +43 -0
  256. package/src/upload/Upload.spec.tsx +63 -0
  257. package/src/upload/Upload.story.tsx +0 -51
  258. package/src/upload/Upload.tests.story.tsx +93 -0
  259. package/src/upload/Upload.tsx +28 -49
  260. package/src/upload/steps/processingStep/processingStep.tsx +2 -7
  261. package/src/uploadInput/UploadInput.tsx +74 -10
  262. package/src/uploadInput/uploadItem/UploadItem.css +2 -1
  263. package/src/uploadInput/uploadItem/UploadItem.less +1 -1
  264. package/src/uploadInput/uploadItem/UploadItem.tsx +11 -6
  265. package/src/withDisplayFormat/WithDisplayFormat.spec.js +11 -15
  266. package/src/withDisplayFormat/WithDisplayFormat.tsx +3 -2
  267. package/build/selectOption/SelectOption.js +0 -131
  268. package/build/selectOption/SelectOption.js.map +0 -1
  269. package/build/selectOption/SelectOption.messages.js +0 -17
  270. package/build/selectOption/SelectOption.messages.js.map +0 -1
  271. package/build/selectOption/SelectOption.messages.mjs +0 -13
  272. package/build/selectOption/SelectOption.messages.mjs.map +0 -1
  273. package/build/selectOption/SelectOption.mjs +0 -127
  274. package/build/selectOption/SelectOption.mjs.map +0 -1
  275. package/build/styles/selectOption/SelectOption.css +0 -44
  276. package/build/types/selectOption/SelectOption.d.ts +0 -21
  277. package/build/types/selectOption/SelectOption.d.ts.map +0 -1
  278. package/build/types/selectOption/SelectOption.messages.d.ts +0 -12
  279. package/build/types/selectOption/SelectOption.messages.d.ts.map +0 -1
  280. package/build/types/selectOption/index.d.ts +0 -3
  281. package/build/types/selectOption/index.d.ts.map +0 -1
  282. package/src/selectOption/SelectOption.css +0 -44
  283. package/src/selectOption/SelectOption.less +0 -40
  284. package/src/selectOption/SelectOption.messages.ts +0 -12
  285. package/src/selectOption/SelectOption.spec.tsx +0 -83
  286. package/src/selectOption/SelectOption.story.tsx +0 -277
  287. package/src/selectOption/SelectOption.tsx +0 -151
  288. package/src/selectOption/index.ts +0 -2
  289. package/src/typeahead/Typeahead.rtl.spec.tsx +0 -54
  290. package/src/typeahead/Typeahead.spec.js +0 -404
  291. package/src/typeahead/typeaheadInput/TypeaheadInput.spec.js +0 -74
  292. package/src/typeahead/typeaheadOption/TypeaheadOption.spec.js +0 -75
  293. package/src/typeahead/util/highlight.spec.js +0 -34
@@ -1,13 +1,12 @@
1
1
  import Button from '../../../button';
2
2
  import { Status, Typography } from '../../../common';
3
- import ProcessIndicator, { ProcessIndicatorStatus } from '../../../processIndicator';
3
+ import ProcessIndicator from '../../../processIndicator';
4
4
  import Title from '../../../title';
5
5
 
6
6
  export interface ProcessingStepProps {
7
7
  isComplete: boolean;
8
8
  isError: boolean;
9
9
  isSuccess: boolean;
10
- onAnimationCompleted: (status: ProcessIndicatorStatus) => void;
11
10
  onClear: React.MouseEventHandler<HTMLButtonElement>;
12
11
  psButtonText: string;
13
12
  psProcessingText: string;
@@ -18,7 +17,6 @@ export default function ProcessingStep({
18
17
  isComplete,
19
18
  isError,
20
19
  isSuccess,
21
- onAnimationCompleted,
22
20
  onClear,
23
21
  psButtonText,
24
22
  psProcessingText,
@@ -35,10 +33,7 @@ export default function ProcessingStep({
35
33
  return (
36
34
  <div className="droppable-processing-card droppable-card" aria-hidden={isComplete}>
37
35
  <div className="droppable-card-content">
38
- <ProcessIndicator
39
- status={processStatus}
40
- onAnimationCompleted={(status) => onAnimationCompleted(status)}
41
- />
36
+ <ProcessIndicator status={processStatus} />
42
37
  <Title className="m-y-2" type={Typography.TITLE_BODY} aria-live="polite">
43
38
  {psProcessingText}
44
39
  </Title>
@@ -161,6 +161,7 @@ const UploadInput = ({
161
161
  }: UploadInputProps) => {
162
162
  const inputAttributes = useInputAttributes({ nonLabelable: true });
163
163
  const [markedFileForDelete, setMarkedFileForDelete] = useState<UploadedFile | null>(null);
164
+ const [lastAttemptedDeleteId, setLastAttemptedDeleteId] = useState<string | number | null>(null);
164
165
  const [mounted, setMounted] = useState(false);
165
166
  const { formatMessage } = useIntl();
166
167
  const uploadInputRef = useRef<HTMLInputElement | null>(null);
@@ -321,9 +322,13 @@ const UploadInput = ({
321
322
  }
322
323
  }, [onFilesChange, uploadedFiles]); // eslint-disable-line react-hooks/exhaustive-deps
323
324
 
324
- const [nextFocusable, setNextFocusable] = useState<HTMLDivElement | UploadItemRef | null>(
325
- uploadInputRef.current,
326
- );
325
+ type NextFocusable =
326
+ | HTMLDivElement
327
+ | UploadItemRef
328
+ | { ref: HTMLDivElement | UploadItemRef; target: 'button' | 'link' }
329
+ | null;
330
+
331
+ const [nextFocusable, setNextFocusable] = useState<NextFocusable>(uploadInputRef.current);
327
332
 
328
333
  const handleFocus = (fileId: string | number) => {
329
334
  fileRefs = fileRefs.filter((ref) => {
@@ -331,7 +336,15 @@ const UploadInput = ({
331
336
  });
332
337
 
333
338
  const filesCount = fileRefs.length;
334
- let next: HTMLDivElement | UploadItemRef | null = uploadInputRef.current;
339
+ let next: UploadItemRef | HTMLDivElement | null = uploadInputRef.current;
340
+ let focusTarget: 'button' | 'link' = 'button';
341
+
342
+ // If there will be no files left after deletion, focus the upload button
343
+ if (filesCount === 1) {
344
+ next = uploadInputRef.current;
345
+ setNextFocusable(next);
346
+ return;
347
+ }
335
348
 
336
349
  if (filesCount > 1) {
337
350
  const currentFileIndex = fileRefs.findIndex((file) => file?.id === fileId);
@@ -344,15 +357,61 @@ const UploadInput = ({
344
357
  } else {
345
358
  next = fileRefs[currentFileIndex + 1];
346
359
  }
360
+
361
+ // If next is an UploadItemRef, check if it has a URL (succeeded)
362
+ if (next && 'status' in next) {
363
+ // Find the file object for this ref
364
+ const fileObj = uploadedFiles.find((f) => f.id === next?.id);
365
+ if (
366
+ fileObj &&
367
+ (fileObj.status === Status.SUCCEEDED || fileObj.status === Status.DONE) &&
368
+ fileObj.url
369
+ ) {
370
+ focusTarget = 'link';
371
+ }
372
+ }
373
+ setNextFocusable(() => {
374
+ if (next && typeof (next as UploadItemRef).focus === 'function') {
375
+ return { ref: next, target: focusTarget };
376
+ }
377
+ return next;
378
+ });
347
379
  }
348
- setNextFocusable(next);
349
380
  };
350
381
 
351
382
  const handleRefocus = () => {
352
- if (nextFocusable && 'focus' in nextFocusable && typeof nextFocusable.focus === 'function') {
353
- setTimeout(() => {
354
- nextFocusable.focus();
355
- }, 0);
383
+ const focusTarget = nextFocusable;
384
+ if (lastAttemptedDeleteId) {
385
+ setLastAttemptedDeleteId(null);
386
+ return;
387
+ }
388
+ if (focusTarget) {
389
+ // If there are no files left, focus the upload button
390
+ if (
391
+ uploadedFiles.length === 0 &&
392
+ uploadInputRef.current &&
393
+ typeof uploadInputRef.current.focus === 'function'
394
+ ) {
395
+ setTimeout(() => {
396
+ uploadInputRef.current!.focus();
397
+ }, 0);
398
+ } else if (
399
+ typeof focusTarget === 'object' &&
400
+ 'ref' in focusTarget &&
401
+ focusTarget.ref &&
402
+ typeof focusTarget.ref.focus === 'function'
403
+ ) {
404
+ setTimeout(() => {
405
+ if (focusTarget.ref && typeof (focusTarget.ref as UploadItemRef).focus === 'function') {
406
+ // @ts-expect-error: focus may not exist on all possible ref types, but is safe here
407
+ (focusTarget.ref as UploadItemRef).focus(focusTarget.target);
408
+ }
409
+ }, 0);
410
+ } else if (focusTarget && typeof (focusTarget as UploadItemRef).focus === 'function') {
411
+ setTimeout(() => {
412
+ (focusTarget as UploadItemRef).focus();
413
+ }, 0);
414
+ }
356
415
  }
357
416
  };
358
417
 
@@ -391,10 +450,14 @@ const UploadInput = ({
391
450
  onDelete={
392
451
  file.status === Status.FAILED
393
452
  ? async () => {
453
+ setLastAttemptedDeleteId(file.id);
394
454
  await removeFile(file);
395
455
  handleRefocus();
396
456
  }
397
- : () => setMarkedFileForDelete(file)
457
+ : () => {
458
+ setLastAttemptedDeleteId(file.id);
459
+ setMarkedFileForDelete(file);
460
+ }
398
461
  }
399
462
  onDownload={onDownload}
400
463
  onFocus={() => handleFocus(file.id)}
@@ -451,6 +514,7 @@ const UploadInput = ({
451
514
  void removeFile(markedFileForDelete);
452
515
  }
453
516
  setMarkedFileForDelete(null);
517
+ setLastAttemptedDeleteId(null);
454
518
  }}
455
519
  >
456
520
  {deleteConfirm?.confirmText || formatMessage(MESSAGES.deleteModalConfirmButtonText)}
@@ -152,7 +152,8 @@
152
152
  padding-left: var(--size-16);
153
153
  }
154
154
  .np-upload-input__item .np-upload-input-errors > li::before {
155
- content: '•';
155
+ content: '•' ;
156
+ content: '•' / '';
156
157
  position: absolute;
157
158
  display: block;
158
159
  left: 0;
@@ -158,7 +158,7 @@
158
158
  padding-left: var(--size-16);
159
159
 
160
160
  &::before {
161
- content: '•';
161
+ content: '•' / '';
162
162
  position: absolute;
163
163
  display: block;
164
164
  left: 0;
@@ -19,7 +19,7 @@ export type UploadItemProps = React.JSX.IntrinsicAttributes & {
19
19
  singleFileUpload: boolean;
20
20
  canDelete: boolean;
21
21
  onDelete: () => void;
22
- onFocus: () => void;
22
+ onFocus: (target?: 'button' | 'link') => void;
23
23
 
24
24
  /**
25
25
  * Callback to be called when the file link is clicked.
@@ -63,11 +63,15 @@ const UploadItem = forwardRef<UploadItemRef, UploadItemProps>(
63
63
  const buttonRef = useRef<HTMLButtonElement>(null);
64
64
 
65
65
  useImperativeHandle<UploadItemRef, UploadItemRef>(ref, () => ({
66
- focus: (): void => {
67
- if (url) {
68
- linkRef.current?.focus();
69
- } else {
70
- buttonRef.current?.focus();
66
+ focus: (target?: 'button' | 'link'): void => {
67
+ if (target === 'button' && buttonRef.current) {
68
+ buttonRef.current.focus();
69
+ } else if (target === 'link' && linkRef.current) {
70
+ linkRef.current.focus();
71
+ } else if (buttonRef.current) {
72
+ buttonRef.current.focus();
73
+ } else if (linkRef.current) {
74
+ linkRef.current.focus();
71
75
  }
72
76
  },
73
77
  id: file.id,
@@ -199,6 +203,7 @@ const UploadItem = forwardRef<UploadItemRef, UploadItemProps>(
199
203
  tabIndex={0}
200
204
  data-testid={`${file.id}-${TEST_IDS.action}`}
201
205
  onClick={() => onDelete()}
206
+ // @ts-expect-error: handleFocus is not a standard FocusEventHandler, but required for parent logic
202
207
  onFocus={handleFocus}
203
208
  >
204
209
  <Bin size={16} />
@@ -3,7 +3,7 @@ import { userEvent, render, screen, waitFor } from '../test-utils';
3
3
  import { Input } from '../inputs/Input';
4
4
  import WithDisplayFormat from '.';
5
5
 
6
- const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
6
+ const user = userEvent;
7
7
 
8
8
  const setup = (props) =>
9
9
  render(
@@ -22,15 +22,6 @@ describe('InputWithTextFormat (React Testing Library)', () => {
22
22
  onBlur: jest.fn(),
23
23
  };
24
24
 
25
- beforeEach(() => {
26
- jest.useFakeTimers();
27
- });
28
-
29
- afterEach(async () => {
30
- await jest.runOnlyPendingTimersAsync();
31
- jest.useRealTimers();
32
- });
33
-
34
25
  [
35
26
  { value: '123', expectedValue: '12-3', displayPattern: '**-**-**' },
36
27
  { value: '1234', expectedValue: '12-34', displayPattern: '**-**-**' },
@@ -132,18 +123,23 @@ describe('InputWithTextFormat (React Testing Library)', () => {
132
123
  expect(input).toHaveValue('12');
133
124
  });
134
125
 
135
- // @FIXME (maybe) Is this behaviour expected? 🤔
136
- it(`moves to the end, when entered a char in the middle`, async () => {
126
+ it(`cusor preserve position when entered a char in the middle`, async () => {
137
127
  setup(initialProps);
138
128
  const input = screen.getByRole('textbox');
139
129
  await user.type(input, '123');
140
130
  expect(input).toHaveValue('12-3');
141
131
 
142
- await user.type(input, '{arrowLeft}{arrowLeft}{arrowLeft}@');
132
+ await user.keyboard('{arrowleft}{arrowleft}{arrowleft}');
133
+ await user.keyboard('@');
134
+
143
135
  expect(input).toHaveValue('1@-23');
144
136
 
145
- await user.type(input, 'x');
146
- expect(input).toHaveValue('1@-23x');
137
+ await user.keyboard('x');
138
+ expect(input).toHaveValue('1@-x23');
139
+
140
+ await user.keyboard('{arrowright}{backspace}');
141
+
142
+ expect(input).toHaveValue('1@-x3');
147
143
  });
148
144
 
149
145
  it(`supports pasting`, async () => {
@@ -270,7 +270,6 @@ class WithDisplayFormat<T extends TextElementProps> extends React.Component<
270
270
  handleCursorPositioning = (action: string) => {
271
271
  const { displayPattern } = this.props;
272
272
  const { triggerEvent, selectionStart, selectionEnd, pastedLength } = this.state;
273
- const target = triggerEvent?.currentTarget;
274
273
 
275
274
  const cursorPosition = getCursorPositionAfterKeystroke(
276
275
  action,
@@ -281,7 +280,9 @@ class WithDisplayFormat<T extends TextElementProps> extends React.Component<
281
280
  );
282
281
 
283
282
  setTimeout(() => {
284
- target?.setSelectionRange(cursorPosition, cursorPosition);
283
+ if (triggerEvent) {
284
+ (triggerEvent.target as HTMLTextElement).setSelectionRange(cursorPosition, cursorPosition);
285
+ }
285
286
  this.setState({ selectionStart: cursorPosition, selectionEnd: cursorPosition });
286
287
  }, 0);
287
288
  };
@@ -1,131 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var React = require('react');
6
- var clsx = require('clsx');
7
- var Option = require('../common/Option/Option.js');
8
- require('../common/theme.js');
9
- require('../common/direction.js');
10
- require('../common/propsValues/control.js');
11
- var breakpoint = require('../common/propsValues/breakpoint.js');
12
- require('../common/propsValues/size.js');
13
- require('../common/propsValues/typography.js');
14
- require('../common/propsValues/width.js');
15
- require('../common/propsValues/type.js');
16
- require('../common/propsValues/dateMode.js');
17
- require('../common/propsValues/monthFormat.js');
18
- var position = require('../common/propsValues/position.js');
19
- require('../common/propsValues/layouts.js');
20
- require('../common/propsValues/status.js');
21
- require('../common/propsValues/sentiment.js');
22
- require('../common/propsValues/profileType.js');
23
- require('../common/propsValues/variant.js');
24
- require('../common/propsValues/scroll.js');
25
- require('../common/propsValues/markdownNodeType.js');
26
- require('../common/fileType.js');
27
- var icons = require('@transferwise/icons');
28
- var reactIntl = require('react-intl');
29
- require('../common/closeButton/CloseButton.messages.js');
30
- var jsxRuntime = require('react/jsx-runtime');
31
- var Section = require('../section/Section.js');
32
- var Header = require('../header/Header.js');
33
- var NavigationOption = require('../navigationOption/NavigationOption.js');
34
- var NavigationOptionsList = require('../navigationOptionsList/NavigationOptionsList.js');
35
- var contexts = require('../inputs/contexts.js');
36
- var SelectOption_messages = require('./SelectOption.messages.js');
37
- var ResponsivePanel = require('../common/responsivePanel/ResponsivePanel.js');
38
- var useScreenSize = require('../common/hooks/useScreenSize.js');
39
-
40
- function SelectOption({
41
- selected = undefined,
42
- options,
43
- onChange,
44
- placeholder,
45
- disabled,
46
- ...props
47
- }) {
48
- const intl = reactIntl.useIntl();
49
- const rootRef = React.useRef(null);
50
- const [showOptions, setShowOptions] = React.useState(false);
51
- const hasSelected = selected !== undefined;
52
- const isLargeScreen = useScreenSize.useScreenSize(breakpoint.Breakpoint.SMALL);
53
- const inputAttributes = contexts.useInputAttributes();
54
- const ariaLabelledBy = props['aria-labelledby'] ?? inputAttributes?.['aria-labelledby'];
55
- function handleOnClick(showOptionsStatus) {
56
- return () => {
57
- setShowOptions(showOptionsStatus);
58
- };
59
- }
60
- function handleOnChange(data) {
61
- return () => {
62
- setShowOptions(false);
63
- onChange(data);
64
- };
65
- }
66
- function getOptions(isLargeScreen = false) {
67
- return /*#__PURE__*/jsxRuntime.jsx("div", {
68
- className: clsx.clsx({
69
- 'np-select-option-list': isLargeScreen
70
- }),
71
- children: options.map((optionsSection, index) => /*#__PURE__*/jsxRuntime.jsxs(Section.default, {
72
- className: clsx.clsx({
73
- 'p-x-2 p-y-1': isLargeScreen
74
- }),
75
- children: [optionsSection.title && /*#__PURE__*/jsxRuntime.jsx(Header.Header, {
76
- title: optionsSection.title
77
- }), /*#__PURE__*/jsxRuntime.jsx(NavigationOptionsList.default, {
78
- children: optionsSection.options.map((option, index) => {
79
- return /*#__PURE__*/jsxRuntime.jsx(NavigationOption.default, {
80
- isContainerAligned: !isLargeScreen,
81
- showMediaCircle: true,
82
- showMediaAtAllSizes: true,
83
- onClick: handleOnChange(option),
84
- ...option
85
- }, index);
86
- })
87
- })]
88
- }, index))
89
- });
90
- }
91
- return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
92
- children: [/*#__PURE__*/jsxRuntime.jsx(Option.default, {
93
- ref: rootRef,
94
- as: "div",
95
- showMediaAtAllSizes: true,
96
- disabled: disabled,
97
- decision: false,
98
- media: hasSelected ? selected.media : placeholder.media ?? /*#__PURE__*/jsxRuntime.jsx(icons.Plus, {
99
- size: 24
100
- }),
101
- title: (hasSelected ? selected : placeholder).title,
102
- content: (hasSelected ? selected : placeholder).content,
103
- className: clsx.clsx('np-select-option', 'clickable', hasSelected ? 'np-select-option-selected' : 'np-select-option-placeholder', props.className),
104
- button: /*#__PURE__*/jsxRuntime.jsx("button", {
105
- ...inputAttributes,
106
- type: "button",
107
- disabled: disabled,
108
- "aria-labelledby": ariaLabelledBy,
109
- "aria-haspopup": "dialog",
110
- "aria-expanded": showOptions,
111
- className: hasSelected ? 'btn-unstyled' : 'np-action-btn',
112
- "aria-label": hasSelected ? undefined : props['aria-label'],
113
- onClick: handleOnClick(true),
114
- children: hasSelected ? /*#__PURE__*/jsxRuntime.jsx(icons.ChevronDown, {
115
- title: intl.formatMessage(SelectOption_messages.default.selectedActionLabel)
116
- }) : placeholder.actionLabel || intl.formatMessage(SelectOption_messages.default.actionLabel)
117
- })
118
- }), /*#__PURE__*/jsxRuntime.jsx(ResponsivePanel.default, {
119
- anchorWidth: true,
120
- altAxis: true,
121
- anchorRef: rootRef,
122
- open: showOptions,
123
- position: position.Position.BOTTOM,
124
- onClose: handleOnClick(false),
125
- children: getOptions(isLargeScreen)
126
- })]
127
- });
128
- }
129
-
130
- exports.default = SelectOption;
131
- //# sourceMappingURL=SelectOption.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SelectOption.js","sources":["../../src/selectOption/SelectOption.tsx"],"sourcesContent":["import { useRef, useState } from 'react';\nimport { ActionButtonProps } from '../actionButton';\nimport { clsx } from 'clsx';\nimport Option from '../common/Option';\nimport type { OptionProps } from '../common/Option/Option';\nimport { Breakpoint, Position } from '../common';\nimport Section from '../section';\nimport Header from '../header';\nimport { HeaderProps } from '../header/Header';\nimport NavigationOption from '../navigationOption';\nimport NavigationOptionsList from '../navigationOptionsList';\nimport { useInputAttributes } from '../inputs/contexts';\nimport messages from './SelectOption.messages';\nimport { useIntl } from 'react-intl';\nimport ResponsivePanel from '../common/responsivePanel';\nimport { useScreenSize } from '../common/hooks/useScreenSize';\nimport { ChevronDown, Plus } from '@transferwise/icons';\n\nexport type SelectOptiopsSection<T = unknown> = {\n title?: HeaderProps['title'];\n options: SelectOptionValue<T>[];\n};\n\nexport type SelectOptionValue<T = unknown> = Pick<\n OptionProps,\n 'media' | 'title' | 'content' | 'disabled'\n> & {\n value?: T;\n};\n\nexport type SelectOptionPlaceholder = Pick<OptionProps, 'media' | 'title' | 'content'> & {\n actionLabel?: ActionButtonProps['children'];\n};\n\nexport type SelectOptionProps<T = unknown> = {\n onChange: (selected: SelectOptionValue<T>) => void;\n selected?: SelectOptionValue<T>;\n options: SelectOptiopsSection<T>[];\n placeholder: SelectOptionPlaceholder;\n} & Omit<\n OptionProps,\n 'as' | 'title' | 'media' | 'content' | 'onClick' | 'onChange' | 'showMediaAtAllSizes' | 'decision'\n>;\n\nexport default function SelectOption<T>({\n selected = undefined,\n options,\n onChange,\n placeholder,\n disabled,\n ...props\n}: SelectOptionProps<T>) {\n const intl = useIntl();\n const rootRef = useRef(null);\n const [showOptions, setShowOptions] = useState(false);\n\n const hasSelected = selected !== undefined;\n const isLargeScreen = useScreenSize(Breakpoint.SMALL);\n\n const inputAttributes = useInputAttributes();\n const ariaLabelledBy = props['aria-labelledby'] ?? inputAttributes?.['aria-labelledby'];\n\n function handleOnClick(showOptionsStatus: boolean) {\n return () => {\n setShowOptions(showOptionsStatus);\n };\n }\n\n function handleOnChange(data: SelectOptionValue<T>) {\n return () => {\n setShowOptions(false);\n onChange(data);\n };\n }\n\n function getOptions(isLargeScreen = false) {\n return (\n <div className={clsx({ 'np-select-option-list': isLargeScreen })}>\n {options.map((optionsSection, index) => (\n <Section key={index} className={clsx({ 'p-x-2 p-y-1': isLargeScreen })}>\n {optionsSection.title && <Header title={optionsSection.title} />}\n <NavigationOptionsList>\n {optionsSection.options.map((option, index) => {\n return (\n <NavigationOption\n key={index}\n isContainerAligned={!isLargeScreen}\n showMediaCircle\n showMediaAtAllSizes\n onClick={handleOnChange(option)}\n {...option}\n />\n );\n })}\n </NavigationOptionsList>\n </Section>\n ))}\n </div>\n );\n }\n\n return (\n <>\n <Option\n ref={rootRef}\n as=\"div\"\n showMediaAtAllSizes\n disabled={disabled}\n decision={false}\n media={hasSelected ? selected.media : (placeholder.media ?? <Plus size={24} />)}\n title={(hasSelected ? selected : placeholder).title}\n content={(hasSelected ? selected : placeholder).content}\n className={clsx(\n 'np-select-option',\n 'clickable',\n hasSelected ? 'np-select-option-selected' : 'np-select-option-placeholder',\n props.className,\n )}\n button={\n <button\n {...inputAttributes}\n type=\"button\"\n disabled={disabled}\n aria-labelledby={ariaLabelledBy}\n aria-haspopup=\"dialog\"\n aria-expanded={showOptions}\n className={hasSelected ? 'btn-unstyled' : 'np-action-btn'}\n aria-label={hasSelected ? undefined : props['aria-label']}\n onClick={handleOnClick(true)}\n >\n {hasSelected ? (\n <ChevronDown title={intl.formatMessage(messages.selectedActionLabel)} />\n ) : (\n placeholder.actionLabel || intl.formatMessage(messages.actionLabel)\n )}\n </button>\n }\n />\n <ResponsivePanel\n anchorWidth\n altAxis\n anchorRef={rootRef}\n open={showOptions}\n position={Position.BOTTOM}\n onClose={handleOnClick(false)}\n >\n {getOptions(isLargeScreen)}\n </ResponsivePanel>\n </>\n );\n}\n"],"names":["SelectOption","selected","undefined","options","onChange","placeholder","disabled","props","intl","useIntl","rootRef","useRef","showOptions","setShowOptions","useState","hasSelected","isLargeScreen","useScreenSize","Breakpoint","SMALL","inputAttributes","useInputAttributes","ariaLabelledBy","handleOnClick","showOptionsStatus","handleOnChange","data","getOptions","_jsx","className","clsx","children","map","optionsSection","index","_jsxs","Section","title","Header","NavigationOptionsList","option","NavigationOption","isContainerAligned","showMediaCircle","showMediaAtAllSizes","onClick","_Fragment","Option","ref","as","decision","media","Plus","size","content","button","type","ChevronDown","formatMessage","messages","selectedActionLabel","actionLabel","ResponsivePanel","anchorWidth","altAxis","anchorRef","open","position","Position","BOTTOM","onClose"],"mappings":"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"}
@@ -1,17 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var reactIntl = require('react-intl');
6
-
7
- var messages = reactIntl.defineMessages({
8
- actionLabel: {
9
- id: "neptune.SelectOption.action.label"
10
- },
11
- selectedActionLabel: {
12
- id: "neptune.SelectOption.selected.action.label"
13
- }
14
- });
15
-
16
- exports.default = messages;
17
- //# sourceMappingURL=SelectOption.messages.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SelectOption.messages.js","sources":["../../src/selectOption/SelectOption.messages.ts"],"sourcesContent":["import { defineMessages } from 'react-intl';\n\nexport default defineMessages({\n actionLabel: {\n id: 'neptune.SelectOption.action.label',\n defaultMessage: 'Choose',\n },\n selectedActionLabel: {\n id: 'neptune.SelectOption.selected.action.label',\n defaultMessage: 'Change chosen option',\n },\n});\n"],"names":["defineMessages","actionLabel","id","selectedActionLabel"],"mappings":";;;;;;AAEA,eAAeA,wBAAc,CAAC;AAC5BC,EAAAA,WAAW,EAAE;IACXC,EAAE,EAAA;GAEH;AACDC,EAAAA,mBAAmB,EAAE;IACnBD,EAAE,EAAA;AAEH;AACF,CAAA,CAAC;;;;"}
@@ -1,13 +0,0 @@
1
- import { defineMessages } from 'react-intl';
2
-
3
- var messages = defineMessages({
4
- actionLabel: {
5
- id: "neptune.SelectOption.action.label"
6
- },
7
- selectedActionLabel: {
8
- id: "neptune.SelectOption.selected.action.label"
9
- }
10
- });
11
-
12
- export { messages as default };
13
- //# sourceMappingURL=SelectOption.messages.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SelectOption.messages.mjs","sources":["../../src/selectOption/SelectOption.messages.ts"],"sourcesContent":["import { defineMessages } from 'react-intl';\n\nexport default defineMessages({\n actionLabel: {\n id: 'neptune.SelectOption.action.label',\n defaultMessage: 'Choose',\n },\n selectedActionLabel: {\n id: 'neptune.SelectOption.selected.action.label',\n defaultMessage: 'Change chosen option',\n },\n});\n"],"names":["defineMessages","actionLabel","id","selectedActionLabel"],"mappings":";;AAEA,eAAeA,cAAc,CAAC;AAC5BC,EAAAA,WAAW,EAAE;IACXC,EAAE,EAAA;GAEH;AACDC,EAAAA,mBAAmB,EAAE;IACnBD,EAAE,EAAA;AAEH;AACF,CAAA,CAAC;;;;"}
@@ -1,127 +0,0 @@
1
- import { useRef, useState } from 'react';
2
- import { clsx } from 'clsx';
3
- import Option from '../common/Option/Option.mjs';
4
- import '../common/theme.mjs';
5
- import '../common/direction.mjs';
6
- import '../common/propsValues/control.mjs';
7
- import { Breakpoint } from '../common/propsValues/breakpoint.mjs';
8
- import '../common/propsValues/size.mjs';
9
- import '../common/propsValues/typography.mjs';
10
- import '../common/propsValues/width.mjs';
11
- import '../common/propsValues/type.mjs';
12
- import '../common/propsValues/dateMode.mjs';
13
- import '../common/propsValues/monthFormat.mjs';
14
- import { Position } from '../common/propsValues/position.mjs';
15
- import '../common/propsValues/layouts.mjs';
16
- import '../common/propsValues/status.mjs';
17
- import '../common/propsValues/sentiment.mjs';
18
- import '../common/propsValues/profileType.mjs';
19
- import '../common/propsValues/variant.mjs';
20
- import '../common/propsValues/scroll.mjs';
21
- import '../common/propsValues/markdownNodeType.mjs';
22
- import '../common/fileType.mjs';
23
- import { ChevronDown, Plus } from '@transferwise/icons';
24
- import { useIntl } from 'react-intl';
25
- import '../common/closeButton/CloseButton.messages.mjs';
26
- import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
27
- import Section from '../section/Section.mjs';
28
- import { Header } from '../header/Header.mjs';
29
- import NavigationOption from '../navigationOption/NavigationOption.mjs';
30
- import NavigationOptionList from '../navigationOptionsList/NavigationOptionsList.mjs';
31
- import { useInputAttributes } from '../inputs/contexts.mjs';
32
- import messages from './SelectOption.messages.mjs';
33
- import ResponsivePanel from '../common/responsivePanel/ResponsivePanel.mjs';
34
- import { useScreenSize } from '../common/hooks/useScreenSize.mjs';
35
-
36
- function SelectOption({
37
- selected = undefined,
38
- options,
39
- onChange,
40
- placeholder,
41
- disabled,
42
- ...props
43
- }) {
44
- const intl = useIntl();
45
- const rootRef = useRef(null);
46
- const [showOptions, setShowOptions] = useState(false);
47
- const hasSelected = selected !== undefined;
48
- const isLargeScreen = useScreenSize(Breakpoint.SMALL);
49
- const inputAttributes = useInputAttributes();
50
- const ariaLabelledBy = props['aria-labelledby'] ?? inputAttributes?.['aria-labelledby'];
51
- function handleOnClick(showOptionsStatus) {
52
- return () => {
53
- setShowOptions(showOptionsStatus);
54
- };
55
- }
56
- function handleOnChange(data) {
57
- return () => {
58
- setShowOptions(false);
59
- onChange(data);
60
- };
61
- }
62
- function getOptions(isLargeScreen = false) {
63
- return /*#__PURE__*/jsx("div", {
64
- className: clsx({
65
- 'np-select-option-list': isLargeScreen
66
- }),
67
- children: options.map((optionsSection, index) => /*#__PURE__*/jsxs(Section, {
68
- className: clsx({
69
- 'p-x-2 p-y-1': isLargeScreen
70
- }),
71
- children: [optionsSection.title && /*#__PURE__*/jsx(Header, {
72
- title: optionsSection.title
73
- }), /*#__PURE__*/jsx(NavigationOptionList, {
74
- children: optionsSection.options.map((option, index) => {
75
- return /*#__PURE__*/jsx(NavigationOption, {
76
- isContainerAligned: !isLargeScreen,
77
- showMediaCircle: true,
78
- showMediaAtAllSizes: true,
79
- onClick: handleOnChange(option),
80
- ...option
81
- }, index);
82
- })
83
- })]
84
- }, index))
85
- });
86
- }
87
- return /*#__PURE__*/jsxs(Fragment, {
88
- children: [/*#__PURE__*/jsx(Option, {
89
- ref: rootRef,
90
- as: "div",
91
- showMediaAtAllSizes: true,
92
- disabled: disabled,
93
- decision: false,
94
- media: hasSelected ? selected.media : placeholder.media ?? /*#__PURE__*/jsx(Plus, {
95
- size: 24
96
- }),
97
- title: (hasSelected ? selected : placeholder).title,
98
- content: (hasSelected ? selected : placeholder).content,
99
- className: clsx('np-select-option', 'clickable', hasSelected ? 'np-select-option-selected' : 'np-select-option-placeholder', props.className),
100
- button: /*#__PURE__*/jsx("button", {
101
- ...inputAttributes,
102
- type: "button",
103
- disabled: disabled,
104
- "aria-labelledby": ariaLabelledBy,
105
- "aria-haspopup": "dialog",
106
- "aria-expanded": showOptions,
107
- className: hasSelected ? 'btn-unstyled' : 'np-action-btn',
108
- "aria-label": hasSelected ? undefined : props['aria-label'],
109
- onClick: handleOnClick(true),
110
- children: hasSelected ? /*#__PURE__*/jsx(ChevronDown, {
111
- title: intl.formatMessage(messages.selectedActionLabel)
112
- }) : placeholder.actionLabel || intl.formatMessage(messages.actionLabel)
113
- })
114
- }), /*#__PURE__*/jsx(ResponsivePanel, {
115
- anchorWidth: true,
116
- altAxis: true,
117
- anchorRef: rootRef,
118
- open: showOptions,
119
- position: Position.BOTTOM,
120
- onClose: handleOnClick(false),
121
- children: getOptions(isLargeScreen)
122
- })]
123
- });
124
- }
125
-
126
- export { SelectOption as default };
127
- //# sourceMappingURL=SelectOption.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SelectOption.mjs","sources":["../../src/selectOption/SelectOption.tsx"],"sourcesContent":["import { useRef, useState } from 'react';\nimport { ActionButtonProps } from '../actionButton';\nimport { clsx } from 'clsx';\nimport Option from '../common/Option';\nimport type { OptionProps } from '../common/Option/Option';\nimport { Breakpoint, Position } from '../common';\nimport Section from '../section';\nimport Header from '../header';\nimport { HeaderProps } from '../header/Header';\nimport NavigationOption from '../navigationOption';\nimport NavigationOptionsList from '../navigationOptionsList';\nimport { useInputAttributes } from '../inputs/contexts';\nimport messages from './SelectOption.messages';\nimport { useIntl } from 'react-intl';\nimport ResponsivePanel from '../common/responsivePanel';\nimport { useScreenSize } from '../common/hooks/useScreenSize';\nimport { ChevronDown, Plus } from '@transferwise/icons';\n\nexport type SelectOptiopsSection<T = unknown> = {\n title?: HeaderProps['title'];\n options: SelectOptionValue<T>[];\n};\n\nexport type SelectOptionValue<T = unknown> = Pick<\n OptionProps,\n 'media' | 'title' | 'content' | 'disabled'\n> & {\n value?: T;\n};\n\nexport type SelectOptionPlaceholder = Pick<OptionProps, 'media' | 'title' | 'content'> & {\n actionLabel?: ActionButtonProps['children'];\n};\n\nexport type SelectOptionProps<T = unknown> = {\n onChange: (selected: SelectOptionValue<T>) => void;\n selected?: SelectOptionValue<T>;\n options: SelectOptiopsSection<T>[];\n placeholder: SelectOptionPlaceholder;\n} & Omit<\n OptionProps,\n 'as' | 'title' | 'media' | 'content' | 'onClick' | 'onChange' | 'showMediaAtAllSizes' | 'decision'\n>;\n\nexport default function SelectOption<T>({\n selected = undefined,\n options,\n onChange,\n placeholder,\n disabled,\n ...props\n}: SelectOptionProps<T>) {\n const intl = useIntl();\n const rootRef = useRef(null);\n const [showOptions, setShowOptions] = useState(false);\n\n const hasSelected = selected !== undefined;\n const isLargeScreen = useScreenSize(Breakpoint.SMALL);\n\n const inputAttributes = useInputAttributes();\n const ariaLabelledBy = props['aria-labelledby'] ?? inputAttributes?.['aria-labelledby'];\n\n function handleOnClick(showOptionsStatus: boolean) {\n return () => {\n setShowOptions(showOptionsStatus);\n };\n }\n\n function handleOnChange(data: SelectOptionValue<T>) {\n return () => {\n setShowOptions(false);\n onChange(data);\n };\n }\n\n function getOptions(isLargeScreen = false) {\n return (\n <div className={clsx({ 'np-select-option-list': isLargeScreen })}>\n {options.map((optionsSection, index) => (\n <Section key={index} className={clsx({ 'p-x-2 p-y-1': isLargeScreen })}>\n {optionsSection.title && <Header title={optionsSection.title} />}\n <NavigationOptionsList>\n {optionsSection.options.map((option, index) => {\n return (\n <NavigationOption\n key={index}\n isContainerAligned={!isLargeScreen}\n showMediaCircle\n showMediaAtAllSizes\n onClick={handleOnChange(option)}\n {...option}\n />\n );\n })}\n </NavigationOptionsList>\n </Section>\n ))}\n </div>\n );\n }\n\n return (\n <>\n <Option\n ref={rootRef}\n as=\"div\"\n showMediaAtAllSizes\n disabled={disabled}\n decision={false}\n media={hasSelected ? selected.media : (placeholder.media ?? <Plus size={24} />)}\n title={(hasSelected ? selected : placeholder).title}\n content={(hasSelected ? selected : placeholder).content}\n className={clsx(\n 'np-select-option',\n 'clickable',\n hasSelected ? 'np-select-option-selected' : 'np-select-option-placeholder',\n props.className,\n )}\n button={\n <button\n {...inputAttributes}\n type=\"button\"\n disabled={disabled}\n aria-labelledby={ariaLabelledBy}\n aria-haspopup=\"dialog\"\n aria-expanded={showOptions}\n className={hasSelected ? 'btn-unstyled' : 'np-action-btn'}\n aria-label={hasSelected ? undefined : props['aria-label']}\n onClick={handleOnClick(true)}\n >\n {hasSelected ? (\n <ChevronDown title={intl.formatMessage(messages.selectedActionLabel)} />\n ) : (\n placeholder.actionLabel || intl.formatMessage(messages.actionLabel)\n )}\n </button>\n }\n />\n <ResponsivePanel\n anchorWidth\n altAxis\n anchorRef={rootRef}\n open={showOptions}\n position={Position.BOTTOM}\n onClose={handleOnClick(false)}\n >\n {getOptions(isLargeScreen)}\n </ResponsivePanel>\n </>\n );\n}\n"],"names":["SelectOption","selected","undefined","options","onChange","placeholder","disabled","props","intl","useIntl","rootRef","useRef","showOptions","setShowOptions","useState","hasSelected","isLargeScreen","useScreenSize","Breakpoint","SMALL","inputAttributes","useInputAttributes","ariaLabelledBy","handleOnClick","showOptionsStatus","handleOnChange","data","getOptions","_jsx","className","clsx","children","map","optionsSection","index","_jsxs","Section","title","Header","NavigationOptionsList","option","NavigationOption","isContainerAligned","showMediaCircle","showMediaAtAllSizes","onClick","_Fragment","Option","ref","as","decision","media","Plus","size","content","button","type","ChevronDown","formatMessage","messages","selectedActionLabel","actionLabel","ResponsivePanel","anchorWidth","altAxis","anchorRef","open","position","Position","BOTTOM","onClose"],"mappings":"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"}