@transferwise/components 0.0.0-experimental-2242f8a → 0.0.0-experimental-5759f4d

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 (255) hide show
  1. package/build/button/Button.js +1 -0
  2. package/build/button/Button.js.map +1 -1
  3. package/build/button/Button.mjs +1 -0
  4. package/build/button/Button.mjs.map +1 -1
  5. package/build/common/RadioButton/RadioButton.js +5 -2
  6. package/build/common/RadioButton/RadioButton.js.map +1 -1
  7. package/build/common/RadioButton/RadioButton.mjs +5 -2
  8. package/build/common/RadioButton/RadioButton.mjs.map +1 -1
  9. package/build/i18n/en.json +2 -0
  10. package/build/i18n/en.json.js +2 -0
  11. package/build/i18n/en.json.js.map +1 -1
  12. package/build/i18n/en.json.mjs +2 -0
  13. package/build/i18n/en.json.mjs.map +1 -1
  14. package/build/iconButton/IconButton.js.map +1 -1
  15. package/build/iconButton/IconButton.mjs.map +1 -1
  16. package/build/image/Image.js.map +1 -1
  17. package/build/image/Image.mjs.map +1 -1
  18. package/build/index.js +2 -0
  19. package/build/index.js.map +1 -1
  20. package/build/index.mjs +1 -0
  21. package/build/index.mjs.map +1 -1
  22. package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.js +56 -0
  23. package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.js.map +1 -0
  24. package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.mjs +54 -0
  25. package/build/listItem/AdditionalInfo/ListItemAdditionalInfo.mjs.map +1 -0
  26. package/build/listItem/AvatarLayout/ListItemAvatarLayout.js +21 -0
  27. package/build/listItem/AvatarLayout/ListItemAvatarLayout.js.map +1 -0
  28. package/build/listItem/AvatarLayout/ListItemAvatarLayout.mjs +19 -0
  29. package/build/listItem/AvatarLayout/ListItemAvatarLayout.mjs.map +1 -0
  30. package/build/listItem/AvatarView/ListItemAvatarView.js +21 -0
  31. package/build/listItem/AvatarView/ListItemAvatarView.js.map +1 -0
  32. package/build/listItem/AvatarView/ListItemAvatarView.mjs +19 -0
  33. package/build/listItem/AvatarView/ListItemAvatarView.mjs.map +1 -0
  34. package/build/listItem/Button/ListItemButton.js +43 -0
  35. package/build/listItem/Button/ListItemButton.js.map +1 -0
  36. package/build/listItem/Button/ListItemButton.mjs +41 -0
  37. package/build/listItem/Button/ListItemButton.mjs.map +1 -0
  38. package/build/listItem/Checkbox/ListItemCheckbox.js +30 -0
  39. package/build/listItem/Checkbox/ListItemCheckbox.js.map +1 -0
  40. package/build/listItem/Checkbox/ListItemCheckbox.mjs +28 -0
  41. package/build/listItem/Checkbox/ListItemCheckbox.mjs.map +1 -0
  42. package/build/listItem/IconButton/ListItemIconButton.js +42 -0
  43. package/build/listItem/IconButton/ListItemIconButton.js.map +1 -0
  44. package/build/listItem/IconButton/ListItemIconButton.mjs +40 -0
  45. package/build/listItem/IconButton/ListItemIconButton.mjs.map +1 -0
  46. package/build/listItem/Image/ListItemImage.js +27 -0
  47. package/build/listItem/Image/ListItemImage.js.map +1 -0
  48. package/build/listItem/Image/ListItemImage.mjs +25 -0
  49. package/build/listItem/Image/ListItemImage.mjs.map +1 -0
  50. package/build/listItem/ListItem.js +302 -0
  51. package/build/listItem/ListItem.js.map +1 -0
  52. package/build/listItem/ListItem.mjs +297 -0
  53. package/build/listItem/ListItem.mjs.map +1 -0
  54. package/build/listItem/ListItemContext.js +8 -0
  55. package/build/listItem/ListItemContext.js.map +1 -0
  56. package/build/listItem/ListItemContext.mjs +6 -0
  57. package/build/listItem/ListItemContext.mjs.map +1 -0
  58. package/build/listItem/Navigation/ListItemNavigation.js +45 -0
  59. package/build/listItem/Navigation/ListItemNavigation.js.map +1 -0
  60. package/build/listItem/Navigation/ListItemNavigation.mjs +43 -0
  61. package/build/listItem/Navigation/ListItemNavigation.mjs.map +1 -0
  62. package/build/listItem/Prompt/ListItemPrompt.js +59 -0
  63. package/build/listItem/Prompt/ListItemPrompt.js.map +1 -0
  64. package/build/listItem/Prompt/ListItemPrompt.mjs +54 -0
  65. package/build/listItem/Prompt/ListItemPrompt.mjs.map +1 -0
  66. package/build/listItem/Radio/ListItemRadio.js +30 -0
  67. package/build/listItem/Radio/ListItemRadio.js.map +1 -0
  68. package/build/listItem/Radio/ListItemRadio.mjs +28 -0
  69. package/build/listItem/Radio/ListItemRadio.mjs.map +1 -0
  70. package/build/listItem/Switch/ListItemSwitch.js +30 -0
  71. package/build/listItem/Switch/ListItemSwitch.js.map +1 -0
  72. package/build/listItem/Switch/ListItemSwitch.mjs +28 -0
  73. package/build/listItem/Switch/ListItemSwitch.mjs.map +1 -0
  74. package/build/listItem/useListItemControl.js +22 -0
  75. package/build/listItem/useListItemControl.js.map +1 -0
  76. package/build/listItem/useListItemControl.mjs +20 -0
  77. package/build/listItem/useListItemControl.mjs.map +1 -0
  78. package/build/main.css +657 -0
  79. package/build/styles/listItem/ListItem.css +657 -0
  80. package/build/styles/listItem/ListItem.grid.css +362 -0
  81. package/build/styles/main.css +657 -0
  82. package/build/switch/Switch.js +2 -0
  83. package/build/switch/Switch.js.map +1 -1
  84. package/build/switch/Switch.mjs +2 -0
  85. package/build/switch/Switch.mjs.map +1 -1
  86. package/build/types/button/Button.d.ts.map +1 -1
  87. package/build/types/button/Button.types.d.ts +1 -1
  88. package/build/types/button/Button.types.d.ts.map +1 -1
  89. package/build/types/button/index.d.ts +1 -1
  90. package/build/types/button/index.d.ts.map +1 -1
  91. package/build/types/common/RadioButton/RadioButton.d.ts +3 -1
  92. package/build/types/common/RadioButton/RadioButton.d.ts.map +1 -1
  93. package/build/types/iconButton/IconButton.d.ts +2 -2
  94. package/build/types/iconButton/IconButton.d.ts.map +1 -1
  95. package/build/types/image/Image.d.ts +3 -0
  96. package/build/types/image/Image.d.ts.map +1 -1
  97. package/build/types/image/index.d.ts +1 -0
  98. package/build/types/image/index.d.ts.map +1 -1
  99. package/build/types/index.d.ts +2 -0
  100. package/build/types/index.d.ts.map +1 -1
  101. package/build/types/listItem/AdditionalInfo/ListItemAdditionalInfo.d.ts +15 -0
  102. package/build/types/listItem/AdditionalInfo/ListItemAdditionalInfo.d.ts.map +1 -0
  103. package/build/types/listItem/AdditionalInfo/index.d.ts +3 -0
  104. package/build/types/listItem/AdditionalInfo/index.d.ts.map +1 -0
  105. package/build/types/listItem/AvatarLayout/ListItemAvatarLayout.d.ts +18 -0
  106. package/build/types/listItem/AvatarLayout/ListItemAvatarLayout.d.ts.map +1 -0
  107. package/build/types/listItem/AvatarLayout/index.d.ts +3 -0
  108. package/build/types/listItem/AvatarLayout/index.d.ts.map +1 -0
  109. package/build/types/listItem/AvatarView/ListItemAvatarView.d.ts +16 -0
  110. package/build/types/listItem/AvatarView/ListItemAvatarView.d.ts.map +1 -0
  111. package/build/types/listItem/AvatarView/index.d.ts +3 -0
  112. package/build/types/listItem/AvatarView/index.d.ts.map +1 -0
  113. package/build/types/listItem/Button/ListItemButton.d.ts +20 -0
  114. package/build/types/listItem/Button/ListItemButton.d.ts.map +1 -0
  115. package/build/types/listItem/Button/index.d.ts +3 -0
  116. package/build/types/listItem/Button/index.d.ts.map +1 -0
  117. package/build/types/listItem/Checkbox/ListItemCheckbox.d.ts +14 -0
  118. package/build/types/listItem/Checkbox/ListItemCheckbox.d.ts.map +1 -0
  119. package/build/types/listItem/Checkbox/index.d.ts +3 -0
  120. package/build/types/listItem/Checkbox/index.d.ts.map +1 -0
  121. package/build/types/listItem/IconButton/ListItemIconButton.d.ts +18 -0
  122. package/build/types/listItem/IconButton/ListItemIconButton.d.ts.map +1 -0
  123. package/build/types/listItem/IconButton/index.d.ts +3 -0
  124. package/build/types/listItem/IconButton/index.d.ts.map +1 -0
  125. package/build/types/listItem/Image/ListItemImage.d.ts +25 -0
  126. package/build/types/listItem/Image/ListItemImage.d.ts.map +1 -0
  127. package/build/types/listItem/Image/index.d.ts +3 -0
  128. package/build/types/listItem/Image/index.d.ts.map +1 -0
  129. package/build/types/listItem/ListItem.d.ts +113 -0
  130. package/build/types/listItem/ListItem.d.ts.map +1 -0
  131. package/build/types/listItem/ListItemContext.d.ts +18 -0
  132. package/build/types/listItem/ListItemContext.d.ts.map +1 -0
  133. package/build/types/listItem/Navigation/ListItemNavigation.d.ts +15 -0
  134. package/build/types/listItem/Navigation/ListItemNavigation.d.ts.map +1 -0
  135. package/build/types/listItem/Navigation/index.d.ts +3 -0
  136. package/build/types/listItem/Navigation/index.d.ts.map +1 -0
  137. package/build/types/listItem/Prompt/ListItemPrompt.d.ts +16 -0
  138. package/build/types/listItem/Prompt/ListItemPrompt.d.ts.map +1 -0
  139. package/build/types/listItem/Prompt/index.d.ts +3 -0
  140. package/build/types/listItem/Prompt/index.d.ts.map +1 -0
  141. package/build/types/listItem/Radio/ListItemRadio.d.ts +14 -0
  142. package/build/types/listItem/Radio/ListItemRadio.d.ts.map +1 -0
  143. package/build/types/listItem/Radio/index.d.ts +3 -0
  144. package/build/types/listItem/Radio/index.d.ts.map +1 -0
  145. package/build/types/listItem/Switch/ListItemSwitch.d.ts +14 -0
  146. package/build/types/listItem/Switch/ListItemSwitch.d.ts.map +1 -0
  147. package/build/types/listItem/Switch/index.d.ts +3 -0
  148. package/build/types/listItem/Switch/index.d.ts.map +1 -0
  149. package/build/types/listItem/_stories/subcomponents.d.ts +18 -0
  150. package/build/types/listItem/_stories/subcomponents.d.ts.map +1 -0
  151. package/build/types/listItem/index.d.ts +14 -0
  152. package/build/types/listItem/index.d.ts.map +1 -0
  153. package/build/types/listItem/useListItemControl.d.ts +5 -0
  154. package/build/types/listItem/useListItemControl.d.ts.map +1 -0
  155. package/build/types/switch/Switch.d.ts +2 -0
  156. package/build/types/switch/Switch.d.ts.map +1 -1
  157. package/build/types/test-utils/index.d.ts +4 -0
  158. package/build/types/test-utils/index.d.ts.map +1 -1
  159. package/build/types/upload/Upload.d.ts +6 -2
  160. package/build/types/upload/Upload.d.ts.map +1 -1
  161. package/build/types/upload/Upload.messages.d.ts +8 -0
  162. package/build/types/upload/Upload.messages.d.ts.map +1 -1
  163. package/build/types/uploadInput/UploadInput.d.ts +1 -1
  164. package/build/types/uploadInput/uploadButton/UploadButton.d.ts +4 -2
  165. package/build/types/uploadInput/uploadButton/UploadButton.d.ts.map +1 -1
  166. package/build/upload/Upload.js +16 -9
  167. package/build/upload/Upload.js.map +1 -1
  168. package/build/upload/Upload.messages.js +6 -0
  169. package/build/upload/Upload.messages.js.map +1 -1
  170. package/build/upload/Upload.messages.mjs +6 -0
  171. package/build/upload/Upload.messages.mjs.map +1 -1
  172. package/build/upload/Upload.mjs +16 -9
  173. package/build/upload/Upload.mjs.map +1 -1
  174. package/build/uploadInput/UploadInput.js +1 -1
  175. package/build/uploadInput/UploadInput.js.map +1 -1
  176. package/build/uploadInput/UploadInput.mjs +1 -1
  177. package/build/uploadInput/UploadInput.mjs.map +1 -1
  178. package/build/uploadInput/uploadButton/UploadButton.js +7 -4
  179. package/build/uploadInput/uploadButton/UploadButton.js.map +1 -1
  180. package/build/uploadInput/uploadButton/UploadButton.mjs +7 -4
  181. package/build/uploadInput/uploadButton/UploadButton.mjs.map +1 -1
  182. package/package.json +1 -1
  183. package/src/button/Button.spec.tsx +18 -0
  184. package/src/button/Button.tsx +5 -1
  185. package/src/button/Button.types.ts +1 -1
  186. package/src/button/index.ts +1 -1
  187. package/src/checkboxButton/CheckboxButton.story.tsx +4 -4
  188. package/src/common/RadioButton/RadioButton.tsx +6 -1
  189. package/src/i18n/en.json +2 -0
  190. package/src/iconButton/IconButton.story.tsx +1 -1
  191. package/src/iconButton/IconButton.tsx +1 -1
  192. package/src/image/Image.tsx +3 -0
  193. package/src/image/index.ts +1 -0
  194. package/src/index.ts +2 -0
  195. package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.story.tsx +145 -0
  196. package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.tsx +36 -0
  197. package/src/listItem/AdditionalInfo/index.ts +2 -0
  198. package/src/listItem/AvatarLayout/ListItemAvatarLayout.story.tsx +118 -0
  199. package/src/listItem/AvatarLayout/ListItemAvatarLayout.tsx +24 -0
  200. package/src/listItem/AvatarLayout/index.ts +2 -0
  201. package/src/listItem/AvatarView/ListItemAvatarView.story.tsx +318 -0
  202. package/src/listItem/AvatarView/ListItemAvatarView.tsx +24 -0
  203. package/src/listItem/AvatarView/index.ts +2 -0
  204. package/src/listItem/Button/ListItemButton.spec.tsx +93 -0
  205. package/src/listItem/Button/ListItemButton.story.tsx +408 -0
  206. package/src/listItem/Button/ListItemButton.tsx +56 -0
  207. package/src/listItem/Button/index.ts +2 -0
  208. package/src/listItem/Checkbox/ListItemCheckbox.story.tsx +107 -0
  209. package/src/listItem/Checkbox/ListItemCheckbox.tsx +33 -0
  210. package/src/listItem/Checkbox/index.ts +2 -0
  211. package/src/listItem/IconButton/ListItemIconButton.story.tsx +236 -0
  212. package/src/listItem/IconButton/ListItemIconButton.tsx +56 -0
  213. package/src/listItem/IconButton/index.ts +2 -0
  214. package/src/listItem/Image/ListItemImage.story.tsx +39 -0
  215. package/src/listItem/Image/ListItemImage.tsx +40 -0
  216. package/src/listItem/Image/index.ts +2 -0
  217. package/src/listItem/ListItem.css +657 -0
  218. package/src/listItem/ListItem.grid.css +362 -0
  219. package/src/listItem/ListItem.grid.less +612 -0
  220. package/src/listItem/ListItem.less +312 -0
  221. package/src/listItem/ListItem.spec.tsx +97 -0
  222. package/src/listItem/ListItem.tsx +428 -0
  223. package/src/listItem/ListItemContext.tsx +22 -0
  224. package/src/listItem/Navigation/ListItemNavigation.story.tsx +106 -0
  225. package/src/listItem/Navigation/ListItemNavigation.tsx +40 -0
  226. package/src/listItem/Navigation/index.ts +2 -0
  227. package/src/listItem/Prompt/ListItemPrompt.spec.tsx +49 -0
  228. package/src/listItem/Prompt/ListItemPrompt.story.tsx +199 -0
  229. package/src/listItem/Prompt/ListItemPrompt.tsx +32 -0
  230. package/src/listItem/Prompt/index.ts +2 -0
  231. package/src/listItem/Radio/ListItemRadio.story.tsx +98 -0
  232. package/src/listItem/Radio/ListItemRadio.tsx +33 -0
  233. package/src/listItem/Radio/index.ts +2 -0
  234. package/src/listItem/Switch/ListItemSwitch.story.tsx +69 -0
  235. package/src/listItem/Switch/ListItemSwitch.tsx +33 -0
  236. package/src/listItem/Switch/index.ts +2 -0
  237. package/src/listItem/_stories/ListItem.focus.test.story.tsx +250 -0
  238. package/src/listItem/_stories/ListItem.layout.test.story.tsx +169 -0
  239. package/src/listItem/_stories/ListItem.story.tsx +670 -0
  240. package/src/listItem/_stories/ListItem.variants.test.story.tsx +266 -0
  241. package/src/listItem/_stories/subcomponents.tsx +139 -0
  242. package/src/listItem/index.ts +14 -0
  243. package/src/listItem/useListItemControl.tsx +18 -0
  244. package/src/main.css +657 -0
  245. package/src/main.less +1 -0
  246. package/src/switch/Switch.tsx +4 -0
  247. package/src/upload/Upload.messages.ts +8 -0
  248. package/src/upload/Upload.spec.tsx +6 -0
  249. package/src/upload/Upload.story.tsx +118 -3
  250. package/src/upload/Upload.tests.story.tsx +5 -3
  251. package/src/upload/Upload.tsx +24 -15
  252. package/src/uploadInput/UploadInput.tests.story.tsx +7 -0
  253. package/src/uploadInput/UploadInput.tsx +2 -2
  254. package/src/uploadInput/uploadButton/UploadButton.spec.tsx +6 -0
  255. package/src/uploadInput/uploadButton/UploadButton.tsx +12 -6
@@ -1 +1 @@
1
- {"version":3,"file":"UploadButton.js","sources":["../../../src/uploadInput/uploadButton/UploadButton.tsx"],"sourcesContent":["import { PlusCircle as PlusIcon, Upload as UploadIcon } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport {\n ChangeEvent,\n DragEvent,\n useRef,\n useState,\n forwardRef,\n useImperativeHandle,\n ForwardedRef,\n} from 'react';\nimport { useIntl } from 'react-intl';\n\nimport Body from '../../body';\nimport { FileType, Typography } from '../../common';\n\nimport MESSAGES from './UploadButton.messages';\nimport { DEFAULT_SIZE_LIMIT, imageFileTypes } from './defaults';\nimport getAllowedFileTypes from './getAllowedFileTypes';\n\ntype AllowedFileTypes = string | readonly string[] | readonly FileType[];\nexport type UploadButtonProps = {\n /**\n * Disable the upload button if your app is not yet ready to accept uploads\n */\n disabled?: boolean;\n\n /**\n * Should be true, if the UploadInput has at least 1\n * file (valid or invalid) listed.\n */\n withEntries?: boolean;\n\n /**\n * Allow multiple file uploads\n */\n multiple?: boolean;\n\n /**\n * List of allowed filetypes, eg. '*' | '.zip,application/zip' | ['.jpg,.jpeg,image/jpeg', '.png,image/png'] (default: image files + PDF)\n */\n fileTypes?: AllowedFileTypes;\n\n /**\n * Size limit in KBs 1000 KB = 1 MB (default: 5000 KB)\n */\n sizeLimit?: number;\n\n /**\n * Description for the upload button\n */\n description?: string | undefined;\n\n /**\n * Maximum number of files allowed, if provided, shows error below file item\n */\n maxFiles?: number;\n\n /**\n * Called when some files were successfully selected\n *\n * @param files\n */\n onChange: (files: FileList) => void;\n\n /**\n * Id for the upload input\n */\n id?: string;\n\n /**\n * Title for the upload button\n */\n uploadButtonTitle?: string;\n};\n\nexport enum TEST_IDS {\n uploadInput = 'uploadInput',\n mediaBody = 'mediaBody',\n}\n\nconst onDragOver = (event: DragEvent): void => {\n event.preventDefault();\n};\n\nconst DEFAULT_FILE_INPUT_ID = 'np-upload-button';\nconst UploadButton = forwardRef<HTMLInputElement | null, UploadButtonProps>(\n (\n {\n disabled,\n withEntries,\n multiple,\n description,\n fileTypes = imageFileTypes,\n sizeLimit = DEFAULT_SIZE_LIMIT,\n maxFiles,\n onChange,\n id = DEFAULT_FILE_INPUT_ID,\n uploadButtonTitle,\n },\n ref: ForwardedRef<HTMLInputElement | null>,\n ) => {\n const { formatMessage } = useIntl();\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n useImperativeHandle(ref, () => {\n if (!inputRef.current) {\n throw new Error('inputRef.current is null');\n }\n return inputRef.current;\n }, []);\n\n const [isDropping, setIsDropping] = useState(false);\n\n const dragCounter = useRef(0);\n\n const reset = (): void => {\n dragCounter.current = 0;\n setIsDropping(false);\n };\n\n const onDragLeave = (event: DragEvent): void => {\n event.preventDefault();\n dragCounter.current -= 1;\n if (dragCounter.current === 0) {\n setIsDropping(false);\n }\n };\n\n const onDragEnter = (event: DragEvent): void => {\n event.preventDefault();\n dragCounter.current += 1;\n if (dragCounter.current === 1) {\n setIsDropping(true);\n }\n };\n\n const onDrop = (event: DragEvent): void => {\n event.preventDefault();\n reset();\n if (event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files[0]) {\n onChange(event.dataTransfer.files);\n }\n };\n\n const filesSelected = (event: ChangeEvent<HTMLInputElement>): void => {\n const { files } = event.target;\n\n if (files) {\n onChange(files);\n\n if (inputRef.current) {\n inputRef.current.value = '';\n }\n }\n };\n\n const getFileTypesDescription = (): string => {\n if (fileTypes === '*') {\n return fileTypes;\n }\n\n return getAllowedFileTypes(Array.isArray(fileTypes) ? fileTypes : [fileTypes]).join(', ');\n };\n\n function getDescription() {\n if (description) {\n return description;\n }\n\n const fileTypesDescription = getFileTypesDescription();\n\n const derivedFileDescription =\n fileTypesDescription === '*' ? formatMessage(MESSAGES.allFileTypes) : fileTypesDescription;\n\n return formatMessage(MESSAGES.instructions, {\n fileTypes: derivedFileDescription,\n size: Math.round(sizeLimit / 1000),\n });\n }\n\n function getAcceptedTypes(): Pick<React.ComponentPropsWithoutRef<'input'>, 'accept'> {\n const areAllFilesAllowed = getFileTypesDescription() === '*';\n\n if (areAllFilesAllowed) {\n return {}; // file input by default allows all files\n }\n\n if (Array.isArray(fileTypes)) {\n return { accept: fileTypes.join(',') };\n }\n\n return { accept: fileTypes as string };\n }\n\n function renderDescription() {\n return (\n <Body className=\"np-upload-input__text\">\n {getDescription()}\n {maxFiles && (\n <>\n <br />\n {formatMessage(MESSAGES.maximumFiles, { maxFiles })}\n </>\n )}\n </Body>\n );\n }\n\n function renderButtonTitle() {\n if (uploadButtonTitle) {\n return uploadButtonTitle;\n }\n return formatMessage(multiple ? MESSAGES.uploadFiles : MESSAGES.uploadFile);\n }\n\n return (\n <label\n className={clsx(\n 'np-upload-input__upload-button',\n `np-upload-input__upload-button--${disabled ? 'disabled' : 'enabled'}`,\n `np-upload-input__upload-button--${withEntries ? 'with-entries' : 'without-entries'}`,\n {\n 'is-dropping': isDropping,\n },\n )}\n htmlFor={id}\n {...(!disabled && { onDragEnter, onDragLeave, onDrop, onDragOver })}\n >\n <span className=\"np-upload-input__icon\">\n <UploadIcon size={24} className=\"text-link\" />\n </span>\n <div className=\"np-upload-input__item-content\" data-testid={TEST_IDS.mediaBody}>\n <Body type={Typography.BODY_LARGE_BOLD} className=\"np-upload-input__title\">\n {renderButtonTitle()}\n </Body>\n {renderDescription()}\n </div>\n <input\n className=\"np-upload-input__upload-button-input sr-only\"\n type=\"file\"\n id={id}\n {...getAcceptedTypes()}\n {...(multiple && { multiple: true })}\n ref={inputRef}\n disabled={disabled}\n name=\"file-upload\"\n data-testid={TEST_IDS.uploadInput}\n onChange={filesSelected}\n />\n {isDropping && (\n <div\n className={clsx(\n 'np-upload-input__drop-file-overlay',\n 'droppable-card',\n 'droppable-dropping-card',\n 'droppable-card-content',\n )}\n >\n <PlusIcon className=\"m-x-1\" size={24} />\n <div>{formatMessage(MESSAGES.dropFile)}</div>\n </div>\n )}\n </label>\n );\n },\n);\n\nUploadButton.displayName = 'UploadButton';\n\nexport default UploadButton;\n"],"names":["TEST_IDS","onDragOver","event","preventDefault","DEFAULT_FILE_INPUT_ID","UploadButton","forwardRef","disabled","withEntries","multiple","description","fileTypes","imageFileTypes","sizeLimit","DEFAULT_SIZE_LIMIT","maxFiles","onChange","id","uploadButtonTitle","ref","formatMessage","useIntl","inputRef","useRef","useImperativeHandle","current","Error","isDropping","setIsDropping","useState","dragCounter","reset","onDragLeave","onDragEnter","onDrop","dataTransfer","files","filesSelected","target","value","getFileTypesDescription","getAllowedFileTypes","Array","isArray","join","getDescription","fileTypesDescription","derivedFileDescription","MESSAGES","allFileTypes","instructions","size","Math","round","getAcceptedTypes","areAllFilesAllowed","accept","renderDescription","_jsxs","Body","className","children","_Fragment","_jsx","maximumFiles","renderButtonTitle","uploadFiles","uploadFile","clsx","htmlFor","UploadIcon","mediaBody","type","Typography","BODY_LARGE_BOLD","name","uploadInput","PlusIcon","dropFile","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"UploadButton.js","sources":["../../../src/uploadInput/uploadButton/UploadButton.tsx"],"sourcesContent":["import { PlusCircle as PlusIcon, Upload as UploadIcon } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport {\n ChangeEvent,\n DragEvent,\n useRef,\n useState,\n forwardRef,\n useImperativeHandle,\n ForwardedRef,\n} from 'react';\nimport { useIntl } from 'react-intl';\n\nimport Body from '../../body';\nimport { FileType, Typography } from '../../common';\n\nimport MESSAGES from './UploadButton.messages';\nimport { DEFAULT_SIZE_LIMIT, imageFileTypes } from './defaults';\nimport getAllowedFileTypes from './getAllowedFileTypes';\n\ntype AllowedFileTypes = string | readonly string[] | readonly FileType[];\nexport type UploadButtonProps = {\n /**\n * Disable the upload button if your app is not yet ready to accept uploads\n */\n disabled?: boolean;\n\n /**\n * Should be true, if the UploadInput has at least 1\n * file (valid or invalid) listed.\n */\n withEntries?: boolean;\n\n /**\n * Allow multiple file uploads\n */\n multiple?: boolean;\n\n /**\n * List of allowed filetypes, eg. '*' | '.zip,application/zip' | ['.jpg,.jpeg,image/jpeg', '.png,image/png'] (default: image files + PDF)\n */\n fileTypes?: AllowedFileTypes;\n\n /**\n * Size limit in KBs (1000 KB = 1 MB).\n * If set to `null`, no size limit will be applied.\n * @default 5000\n */\n sizeLimit?: number | null;\n\n /**\n * Description for the upload button\n */\n description?: string | undefined;\n\n /**\n * Maximum number of files allowed, if provided, shows error below file item\n */\n maxFiles?: number;\n\n /**\n * Called when some files were successfully selected\n *\n * @param files\n */\n onChange: (files: FileList) => void;\n\n /**\n * Id for the upload input\n */\n id?: string;\n\n /**\n * Title for the upload button\n */\n uploadButtonTitle?: string;\n};\n\nexport enum TEST_IDS {\n uploadInput = 'uploadInput',\n mediaBody = 'mediaBody',\n}\n\nconst onDragOver = (event: DragEvent): void => {\n event.preventDefault();\n};\n\nconst DEFAULT_FILE_INPUT_ID = 'np-upload-button';\nconst UploadButton = forwardRef<HTMLInputElement | null, UploadButtonProps>(\n (\n {\n disabled,\n withEntries,\n multiple,\n description,\n fileTypes = imageFileTypes,\n sizeLimit = DEFAULT_SIZE_LIMIT,\n maxFiles,\n onChange,\n id = DEFAULT_FILE_INPUT_ID,\n uploadButtonTitle,\n },\n ref: ForwardedRef<HTMLInputElement | null>,\n ) => {\n const { formatMessage } = useIntl();\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n useImperativeHandle(ref, () => {\n if (!inputRef.current) {\n throw new Error('inputRef.current is null');\n }\n return inputRef.current;\n }, []);\n\n const [isDropping, setIsDropping] = useState(false);\n\n const dragCounter = useRef(0);\n\n const reset = (): void => {\n dragCounter.current = 0;\n setIsDropping(false);\n };\n\n const onDragLeave = (event: DragEvent): void => {\n event.preventDefault();\n dragCounter.current -= 1;\n if (dragCounter.current === 0) {\n setIsDropping(false);\n }\n };\n\n const onDragEnter = (event: DragEvent): void => {\n event.preventDefault();\n dragCounter.current += 1;\n if (dragCounter.current === 1) {\n setIsDropping(true);\n }\n };\n\n const onDrop = (event: DragEvent): void => {\n event.preventDefault();\n reset();\n if (event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files[0]) {\n onChange(event.dataTransfer.files);\n }\n };\n\n const filesSelected = (event: ChangeEvent<HTMLInputElement>): void => {\n const { files } = event.target;\n\n if (files) {\n onChange(files);\n\n if (inputRef.current) {\n inputRef.current.value = '';\n }\n }\n };\n\n const getFileTypesDescription = (): string => {\n if (fileTypes === '*') {\n return fileTypes;\n }\n\n return getAllowedFileTypes(Array.isArray(fileTypes) ? fileTypes : [fileTypes]).join(', ');\n };\n\n function getDescription() {\n if (description) {\n return description;\n }\n\n const fileTypesDescription = getFileTypesDescription();\n\n const derivedFileDescription =\n fileTypesDescription === '*' ? formatMessage(MESSAGES.allFileTypes) : fileTypesDescription;\n\n if (typeof sizeLimit === 'number') {\n return formatMessage(MESSAGES.instructions, {\n fileTypes: derivedFileDescription,\n size: Math.round(sizeLimit / 1000),\n });\n }\n\n return derivedFileDescription;\n }\n\n function getAcceptedTypes(): Pick<React.ComponentPropsWithoutRef<'input'>, 'accept'> {\n const areAllFilesAllowed = getFileTypesDescription() === '*';\n\n if (areAllFilesAllowed) {\n return {}; // file input by default allows all files\n }\n\n if (Array.isArray(fileTypes)) {\n return { accept: fileTypes.join(',') };\n }\n\n return { accept: fileTypes as string };\n }\n\n function renderDescription() {\n return (\n <Body className=\"np-upload-input__text\">\n {getDescription()}\n {maxFiles && (\n <>\n <br />\n {formatMessage(MESSAGES.maximumFiles, { maxFiles })}\n </>\n )}\n </Body>\n );\n }\n\n function renderButtonTitle() {\n if (uploadButtonTitle) {\n return uploadButtonTitle;\n }\n return formatMessage(multiple ? MESSAGES.uploadFiles : MESSAGES.uploadFile);\n }\n\n return (\n <label\n className={clsx(\n 'np-upload-input__upload-button',\n `np-upload-input__upload-button--${disabled ? 'disabled' : 'enabled'}`,\n `np-upload-input__upload-button--${withEntries ? 'with-entries' : 'without-entries'}`,\n {\n 'is-dropping': isDropping,\n },\n )}\n htmlFor={id}\n {...(!disabled && { onDragEnter, onDragLeave, onDrop, onDragOver })}\n >\n <span className=\"np-upload-input__icon\">\n <UploadIcon size={24} className=\"text-link\" />\n </span>\n <div className=\"np-upload-input__item-content\" data-testid={TEST_IDS.mediaBody}>\n <Body type={Typography.BODY_LARGE_BOLD} className=\"np-upload-input__title\">\n {renderButtonTitle()}\n </Body>\n {renderDescription()}\n </div>\n <input\n className=\"np-upload-input__upload-button-input sr-only\"\n type=\"file\"\n id={id}\n {...getAcceptedTypes()}\n {...(multiple && { multiple: true })}\n ref={inputRef}\n disabled={disabled}\n name=\"file-upload\"\n data-testid={TEST_IDS.uploadInput}\n onChange={filesSelected}\n />\n {isDropping && (\n <div\n className={clsx(\n 'np-upload-input__drop-file-overlay',\n 'droppable-card',\n 'droppable-dropping-card',\n 'droppable-card-content',\n )}\n >\n <PlusIcon className=\"m-x-1\" size={24} />\n <div>{formatMessage(MESSAGES.dropFile)}</div>\n </div>\n )}\n </label>\n );\n },\n);\n\nUploadButton.displayName = 'UploadButton';\n\nexport default UploadButton;\n"],"names":["TEST_IDS","onDragOver","event","preventDefault","DEFAULT_FILE_INPUT_ID","UploadButton","forwardRef","disabled","withEntries","multiple","description","fileTypes","imageFileTypes","sizeLimit","DEFAULT_SIZE_LIMIT","maxFiles","onChange","id","uploadButtonTitle","ref","formatMessage","useIntl","inputRef","useRef","useImperativeHandle","current","Error","isDropping","setIsDropping","useState","dragCounter","reset","onDragLeave","onDragEnter","onDrop","dataTransfer","files","filesSelected","target","value","getFileTypesDescription","getAllowedFileTypes","Array","isArray","join","getDescription","fileTypesDescription","derivedFileDescription","MESSAGES","allFileTypes","instructions","size","Math","round","getAcceptedTypes","areAllFilesAllowed","accept","renderDescription","_jsxs","Body","className","children","_Fragment","_jsx","maximumFiles","renderButtonTitle","uploadFiles","uploadFile","clsx","htmlFor","UploadIcon","mediaBody","type","Typography","BODY_LARGE_BOLD","name","uploadInput","PlusIcon","dropFile","displayName"],"mappings":"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"}
@@ -109,10 +109,13 @@ const UploadButton = /*#__PURE__*/forwardRef(({
109
109
  }
110
110
  const fileTypesDescription = getFileTypesDescription();
111
111
  const derivedFileDescription = fileTypesDescription === '*' ? formatMessage(MESSAGES.allFileTypes) : fileTypesDescription;
112
- return formatMessage(MESSAGES.instructions, {
113
- fileTypes: derivedFileDescription,
114
- size: Math.round(sizeLimit / 1000)
115
- });
112
+ if (typeof sizeLimit === 'number') {
113
+ return formatMessage(MESSAGES.instructions, {
114
+ fileTypes: derivedFileDescription,
115
+ size: Math.round(sizeLimit / 1000)
116
+ });
117
+ }
118
+ return derivedFileDescription;
116
119
  }
117
120
  function getAcceptedTypes() {
118
121
  const areAllFilesAllowed = getFileTypesDescription() === '*';
@@ -1 +1 @@
1
- {"version":3,"file":"UploadButton.mjs","sources":["../../../src/uploadInput/uploadButton/UploadButton.tsx"],"sourcesContent":["import { PlusCircle as PlusIcon, Upload as UploadIcon } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport {\n ChangeEvent,\n DragEvent,\n useRef,\n useState,\n forwardRef,\n useImperativeHandle,\n ForwardedRef,\n} from 'react';\nimport { useIntl } from 'react-intl';\n\nimport Body from '../../body';\nimport { FileType, Typography } from '../../common';\n\nimport MESSAGES from './UploadButton.messages';\nimport { DEFAULT_SIZE_LIMIT, imageFileTypes } from './defaults';\nimport getAllowedFileTypes from './getAllowedFileTypes';\n\ntype AllowedFileTypes = string | readonly string[] | readonly FileType[];\nexport type UploadButtonProps = {\n /**\n * Disable the upload button if your app is not yet ready to accept uploads\n */\n disabled?: boolean;\n\n /**\n * Should be true, if the UploadInput has at least 1\n * file (valid or invalid) listed.\n */\n withEntries?: boolean;\n\n /**\n * Allow multiple file uploads\n */\n multiple?: boolean;\n\n /**\n * List of allowed filetypes, eg. '*' | '.zip,application/zip' | ['.jpg,.jpeg,image/jpeg', '.png,image/png'] (default: image files + PDF)\n */\n fileTypes?: AllowedFileTypes;\n\n /**\n * Size limit in KBs 1000 KB = 1 MB (default: 5000 KB)\n */\n sizeLimit?: number;\n\n /**\n * Description for the upload button\n */\n description?: string | undefined;\n\n /**\n * Maximum number of files allowed, if provided, shows error below file item\n */\n maxFiles?: number;\n\n /**\n * Called when some files were successfully selected\n *\n * @param files\n */\n onChange: (files: FileList) => void;\n\n /**\n * Id for the upload input\n */\n id?: string;\n\n /**\n * Title for the upload button\n */\n uploadButtonTitle?: string;\n};\n\nexport enum TEST_IDS {\n uploadInput = 'uploadInput',\n mediaBody = 'mediaBody',\n}\n\nconst onDragOver = (event: DragEvent): void => {\n event.preventDefault();\n};\n\nconst DEFAULT_FILE_INPUT_ID = 'np-upload-button';\nconst UploadButton = forwardRef<HTMLInputElement | null, UploadButtonProps>(\n (\n {\n disabled,\n withEntries,\n multiple,\n description,\n fileTypes = imageFileTypes,\n sizeLimit = DEFAULT_SIZE_LIMIT,\n maxFiles,\n onChange,\n id = DEFAULT_FILE_INPUT_ID,\n uploadButtonTitle,\n },\n ref: ForwardedRef<HTMLInputElement | null>,\n ) => {\n const { formatMessage } = useIntl();\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n useImperativeHandle(ref, () => {\n if (!inputRef.current) {\n throw new Error('inputRef.current is null');\n }\n return inputRef.current;\n }, []);\n\n const [isDropping, setIsDropping] = useState(false);\n\n const dragCounter = useRef(0);\n\n const reset = (): void => {\n dragCounter.current = 0;\n setIsDropping(false);\n };\n\n const onDragLeave = (event: DragEvent): void => {\n event.preventDefault();\n dragCounter.current -= 1;\n if (dragCounter.current === 0) {\n setIsDropping(false);\n }\n };\n\n const onDragEnter = (event: DragEvent): void => {\n event.preventDefault();\n dragCounter.current += 1;\n if (dragCounter.current === 1) {\n setIsDropping(true);\n }\n };\n\n const onDrop = (event: DragEvent): void => {\n event.preventDefault();\n reset();\n if (event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files[0]) {\n onChange(event.dataTransfer.files);\n }\n };\n\n const filesSelected = (event: ChangeEvent<HTMLInputElement>): void => {\n const { files } = event.target;\n\n if (files) {\n onChange(files);\n\n if (inputRef.current) {\n inputRef.current.value = '';\n }\n }\n };\n\n const getFileTypesDescription = (): string => {\n if (fileTypes === '*') {\n return fileTypes;\n }\n\n return getAllowedFileTypes(Array.isArray(fileTypes) ? fileTypes : [fileTypes]).join(', ');\n };\n\n function getDescription() {\n if (description) {\n return description;\n }\n\n const fileTypesDescription = getFileTypesDescription();\n\n const derivedFileDescription =\n fileTypesDescription === '*' ? formatMessage(MESSAGES.allFileTypes) : fileTypesDescription;\n\n return formatMessage(MESSAGES.instructions, {\n fileTypes: derivedFileDescription,\n size: Math.round(sizeLimit / 1000),\n });\n }\n\n function getAcceptedTypes(): Pick<React.ComponentPropsWithoutRef<'input'>, 'accept'> {\n const areAllFilesAllowed = getFileTypesDescription() === '*';\n\n if (areAllFilesAllowed) {\n return {}; // file input by default allows all files\n }\n\n if (Array.isArray(fileTypes)) {\n return { accept: fileTypes.join(',') };\n }\n\n return { accept: fileTypes as string };\n }\n\n function renderDescription() {\n return (\n <Body className=\"np-upload-input__text\">\n {getDescription()}\n {maxFiles && (\n <>\n <br />\n {formatMessage(MESSAGES.maximumFiles, { maxFiles })}\n </>\n )}\n </Body>\n );\n }\n\n function renderButtonTitle() {\n if (uploadButtonTitle) {\n return uploadButtonTitle;\n }\n return formatMessage(multiple ? MESSAGES.uploadFiles : MESSAGES.uploadFile);\n }\n\n return (\n <label\n className={clsx(\n 'np-upload-input__upload-button',\n `np-upload-input__upload-button--${disabled ? 'disabled' : 'enabled'}`,\n `np-upload-input__upload-button--${withEntries ? 'with-entries' : 'without-entries'}`,\n {\n 'is-dropping': isDropping,\n },\n )}\n htmlFor={id}\n {...(!disabled && { onDragEnter, onDragLeave, onDrop, onDragOver })}\n >\n <span className=\"np-upload-input__icon\">\n <UploadIcon size={24} className=\"text-link\" />\n </span>\n <div className=\"np-upload-input__item-content\" data-testid={TEST_IDS.mediaBody}>\n <Body type={Typography.BODY_LARGE_BOLD} className=\"np-upload-input__title\">\n {renderButtonTitle()}\n </Body>\n {renderDescription()}\n </div>\n <input\n className=\"np-upload-input__upload-button-input sr-only\"\n type=\"file\"\n id={id}\n {...getAcceptedTypes()}\n {...(multiple && { multiple: true })}\n ref={inputRef}\n disabled={disabled}\n name=\"file-upload\"\n data-testid={TEST_IDS.uploadInput}\n onChange={filesSelected}\n />\n {isDropping && (\n <div\n className={clsx(\n 'np-upload-input__drop-file-overlay',\n 'droppable-card',\n 'droppable-dropping-card',\n 'droppable-card-content',\n )}\n >\n <PlusIcon className=\"m-x-1\" size={24} />\n <div>{formatMessage(MESSAGES.dropFile)}</div>\n </div>\n )}\n </label>\n );\n },\n);\n\nUploadButton.displayName = 'UploadButton';\n\nexport default UploadButton;\n"],"names":["TEST_IDS","onDragOver","event","preventDefault","DEFAULT_FILE_INPUT_ID","UploadButton","forwardRef","disabled","withEntries","multiple","description","fileTypes","imageFileTypes","sizeLimit","DEFAULT_SIZE_LIMIT","maxFiles","onChange","id","uploadButtonTitle","ref","formatMessage","useIntl","inputRef","useRef","useImperativeHandle","current","Error","isDropping","setIsDropping","useState","dragCounter","reset","onDragLeave","onDragEnter","onDrop","dataTransfer","files","filesSelected","target","value","getFileTypesDescription","getAllowedFileTypes","Array","isArray","join","getDescription","fileTypesDescription","derivedFileDescription","MESSAGES","allFileTypes","instructions","size","Math","round","getAcceptedTypes","areAllFilesAllowed","accept","renderDescription","_jsxs","Body","className","children","_Fragment","_jsx","maximumFiles","renderButtonTitle","uploadFiles","uploadFile","clsx","htmlFor","UploadIcon","mediaBody","type","Typography","BODY_LARGE_BOLD","name","uploadInput","PlusIcon","dropFile","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"UploadButton.mjs","sources":["../../../src/uploadInput/uploadButton/UploadButton.tsx"],"sourcesContent":["import { PlusCircle as PlusIcon, Upload as UploadIcon } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport {\n ChangeEvent,\n DragEvent,\n useRef,\n useState,\n forwardRef,\n useImperativeHandle,\n ForwardedRef,\n} from 'react';\nimport { useIntl } from 'react-intl';\n\nimport Body from '../../body';\nimport { FileType, Typography } from '../../common';\n\nimport MESSAGES from './UploadButton.messages';\nimport { DEFAULT_SIZE_LIMIT, imageFileTypes } from './defaults';\nimport getAllowedFileTypes from './getAllowedFileTypes';\n\ntype AllowedFileTypes = string | readonly string[] | readonly FileType[];\nexport type UploadButtonProps = {\n /**\n * Disable the upload button if your app is not yet ready to accept uploads\n */\n disabled?: boolean;\n\n /**\n * Should be true, if the UploadInput has at least 1\n * file (valid or invalid) listed.\n */\n withEntries?: boolean;\n\n /**\n * Allow multiple file uploads\n */\n multiple?: boolean;\n\n /**\n * List of allowed filetypes, eg. '*' | '.zip,application/zip' | ['.jpg,.jpeg,image/jpeg', '.png,image/png'] (default: image files + PDF)\n */\n fileTypes?: AllowedFileTypes;\n\n /**\n * Size limit in KBs (1000 KB = 1 MB).\n * If set to `null`, no size limit will be applied.\n * @default 5000\n */\n sizeLimit?: number | null;\n\n /**\n * Description for the upload button\n */\n description?: string | undefined;\n\n /**\n * Maximum number of files allowed, if provided, shows error below file item\n */\n maxFiles?: number;\n\n /**\n * Called when some files were successfully selected\n *\n * @param files\n */\n onChange: (files: FileList) => void;\n\n /**\n * Id for the upload input\n */\n id?: string;\n\n /**\n * Title for the upload button\n */\n uploadButtonTitle?: string;\n};\n\nexport enum TEST_IDS {\n uploadInput = 'uploadInput',\n mediaBody = 'mediaBody',\n}\n\nconst onDragOver = (event: DragEvent): void => {\n event.preventDefault();\n};\n\nconst DEFAULT_FILE_INPUT_ID = 'np-upload-button';\nconst UploadButton = forwardRef<HTMLInputElement | null, UploadButtonProps>(\n (\n {\n disabled,\n withEntries,\n multiple,\n description,\n fileTypes = imageFileTypes,\n sizeLimit = DEFAULT_SIZE_LIMIT,\n maxFiles,\n onChange,\n id = DEFAULT_FILE_INPUT_ID,\n uploadButtonTitle,\n },\n ref: ForwardedRef<HTMLInputElement | null>,\n ) => {\n const { formatMessage } = useIntl();\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n useImperativeHandle(ref, () => {\n if (!inputRef.current) {\n throw new Error('inputRef.current is null');\n }\n return inputRef.current;\n }, []);\n\n const [isDropping, setIsDropping] = useState(false);\n\n const dragCounter = useRef(0);\n\n const reset = (): void => {\n dragCounter.current = 0;\n setIsDropping(false);\n };\n\n const onDragLeave = (event: DragEvent): void => {\n event.preventDefault();\n dragCounter.current -= 1;\n if (dragCounter.current === 0) {\n setIsDropping(false);\n }\n };\n\n const onDragEnter = (event: DragEvent): void => {\n event.preventDefault();\n dragCounter.current += 1;\n if (dragCounter.current === 1) {\n setIsDropping(true);\n }\n };\n\n const onDrop = (event: DragEvent): void => {\n event.preventDefault();\n reset();\n if (event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files[0]) {\n onChange(event.dataTransfer.files);\n }\n };\n\n const filesSelected = (event: ChangeEvent<HTMLInputElement>): void => {\n const { files } = event.target;\n\n if (files) {\n onChange(files);\n\n if (inputRef.current) {\n inputRef.current.value = '';\n }\n }\n };\n\n const getFileTypesDescription = (): string => {\n if (fileTypes === '*') {\n return fileTypes;\n }\n\n return getAllowedFileTypes(Array.isArray(fileTypes) ? fileTypes : [fileTypes]).join(', ');\n };\n\n function getDescription() {\n if (description) {\n return description;\n }\n\n const fileTypesDescription = getFileTypesDescription();\n\n const derivedFileDescription =\n fileTypesDescription === '*' ? formatMessage(MESSAGES.allFileTypes) : fileTypesDescription;\n\n if (typeof sizeLimit === 'number') {\n return formatMessage(MESSAGES.instructions, {\n fileTypes: derivedFileDescription,\n size: Math.round(sizeLimit / 1000),\n });\n }\n\n return derivedFileDescription;\n }\n\n function getAcceptedTypes(): Pick<React.ComponentPropsWithoutRef<'input'>, 'accept'> {\n const areAllFilesAllowed = getFileTypesDescription() === '*';\n\n if (areAllFilesAllowed) {\n return {}; // file input by default allows all files\n }\n\n if (Array.isArray(fileTypes)) {\n return { accept: fileTypes.join(',') };\n }\n\n return { accept: fileTypes as string };\n }\n\n function renderDescription() {\n return (\n <Body className=\"np-upload-input__text\">\n {getDescription()}\n {maxFiles && (\n <>\n <br />\n {formatMessage(MESSAGES.maximumFiles, { maxFiles })}\n </>\n )}\n </Body>\n );\n }\n\n function renderButtonTitle() {\n if (uploadButtonTitle) {\n return uploadButtonTitle;\n }\n return formatMessage(multiple ? MESSAGES.uploadFiles : MESSAGES.uploadFile);\n }\n\n return (\n <label\n className={clsx(\n 'np-upload-input__upload-button',\n `np-upload-input__upload-button--${disabled ? 'disabled' : 'enabled'}`,\n `np-upload-input__upload-button--${withEntries ? 'with-entries' : 'without-entries'}`,\n {\n 'is-dropping': isDropping,\n },\n )}\n htmlFor={id}\n {...(!disabled && { onDragEnter, onDragLeave, onDrop, onDragOver })}\n >\n <span className=\"np-upload-input__icon\">\n <UploadIcon size={24} className=\"text-link\" />\n </span>\n <div className=\"np-upload-input__item-content\" data-testid={TEST_IDS.mediaBody}>\n <Body type={Typography.BODY_LARGE_BOLD} className=\"np-upload-input__title\">\n {renderButtonTitle()}\n </Body>\n {renderDescription()}\n </div>\n <input\n className=\"np-upload-input__upload-button-input sr-only\"\n type=\"file\"\n id={id}\n {...getAcceptedTypes()}\n {...(multiple && { multiple: true })}\n ref={inputRef}\n disabled={disabled}\n name=\"file-upload\"\n data-testid={TEST_IDS.uploadInput}\n onChange={filesSelected}\n />\n {isDropping && (\n <div\n className={clsx(\n 'np-upload-input__drop-file-overlay',\n 'droppable-card',\n 'droppable-dropping-card',\n 'droppable-card-content',\n )}\n >\n <PlusIcon className=\"m-x-1\" size={24} />\n <div>{formatMessage(MESSAGES.dropFile)}</div>\n </div>\n )}\n </label>\n );\n },\n);\n\nUploadButton.displayName = 'UploadButton';\n\nexport default UploadButton;\n"],"names":["TEST_IDS","onDragOver","event","preventDefault","DEFAULT_FILE_INPUT_ID","UploadButton","forwardRef","disabled","withEntries","multiple","description","fileTypes","imageFileTypes","sizeLimit","DEFAULT_SIZE_LIMIT","maxFiles","onChange","id","uploadButtonTitle","ref","formatMessage","useIntl","inputRef","useRef","useImperativeHandle","current","Error","isDropping","setIsDropping","useState","dragCounter","reset","onDragLeave","onDragEnter","onDrop","dataTransfer","files","filesSelected","target","value","getFileTypesDescription","getAllowedFileTypes","Array","isArray","join","getDescription","fileTypesDescription","derivedFileDescription","MESSAGES","allFileTypes","instructions","size","Math","round","getAcceptedTypes","areAllFilesAllowed","accept","renderDescription","_jsxs","Body","className","children","_Fragment","_jsx","maximumFiles","renderButtonTitle","uploadFiles","uploadFile","clsx","htmlFor","UploadIcon","mediaBody","type","Typography","BODY_LARGE_BOLD","name","uploadInput","PlusIcon","dropFile","displayName"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transferwise/components",
3
- "version": "0.0.0-experimental-2242f8a",
3
+ "version": "0.0.0-experimental-5759f4d",
4
4
  "description": "Neptune React components",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -202,6 +202,24 @@ describe('Button', () => {
202
202
  expect(button).not.toHaveAttribute('href');
203
203
  });
204
204
  });
205
+
206
+ describe('content id', () => {
207
+ it('should not set id for content by default', () => {
208
+ const { container } = render(<Button v2>clickMe</Button>);
209
+
210
+ expect(container.querySelector('[id$="_content"]')).not.toBeInTheDocument();
211
+ });
212
+
213
+ it('should set id for content by default if `id` is passed as a button prop', () => {
214
+ const { container } = render(
215
+ <Button v2 id="myId">
216
+ clickMe
217
+ </Button>,
218
+ );
219
+
220
+ expect(container.querySelector('#myId_content')).toBeInTheDocument();
221
+ });
222
+ });
205
223
  });
206
224
  });
207
225
  });
@@ -62,7 +62,11 @@ const Button = forwardRef<ButtonReferenceType, NewButtonProps>(
62
62
  data-testid="button-loader-indicator"
63
63
  />
64
64
  )}
65
- <span className="wds-Button-label" aria-hidden={loading}>
65
+ <span
66
+ className="wds-Button-label"
67
+ id={props.id ? `${props.id}_content` : undefined}
68
+ aria-hidden={loading}
69
+ >
66
70
  {size === 'lg' ? (
67
71
  <span className="wds-Button-labelText">{children}</span>
68
72
  ) : (
@@ -5,7 +5,7 @@ export type ButtonSentiment = 'default' | 'negative';
5
5
  export type ButtonPriority = 'primary' | 'secondary' | 'secondary-neutral' | 'tertiary';
6
6
  export type ButtonSize = 'sm' | 'md' | 'lg';
7
7
  export type ButtonReferenceType = HTMLButtonElement | HTMLAnchorElement;
8
- type ButtonAddonIcon = {
8
+ export type ButtonAddonIcon = {
9
9
  type: 'icon';
10
10
  value: ReactNode;
11
11
  };
@@ -1,5 +1,5 @@
1
1
  export { default } from './Button.resolver';
2
- export type { ButtonProps as NewButtonProps } from './Button.types';
2
+ export type { ButtonProps as NewButtonProps, ButtonAddonIcon } from './Button.types';
3
3
 
4
4
  // export legacy button props for backwards compatibility with legacy Button interface
5
5
  // delete this when migration to new Button is done (or aleast no more deep imports, use following query)
@@ -35,14 +35,14 @@ export const Indeterminate: Story = {
35
35
  indeterminate: true,
36
36
  },
37
37
  render: (args) => {
38
- const [indeterminate, setIndeterminate] = useState(true);
38
+ const [checked, setChecked] = useState<boolean | undefined>(undefined);
39
39
 
40
40
  return (
41
41
  <CheckboxButton
42
42
  {...args}
43
- checked
44
- indeterminate={indeterminate}
45
- onChange={() => setIndeterminate(!indeterminate)}
43
+ checked={false}
44
+ indeterminate={args.indeterminate}
45
+ onChange={() => setChecked(!checked)}
46
46
  />
47
47
  );
48
48
  },
@@ -8,6 +8,8 @@ export interface RadioButtonProps<T extends string | number = string> {
8
8
  disabled?: boolean;
9
9
  value?: T;
10
10
  readOnly?: boolean;
11
+ className?: string;
12
+ 'aria-describedby'?: string;
11
13
  }
12
14
 
13
15
  export default function RadioButton<T extends string | number = ''>({
@@ -18,17 +20,20 @@ export default function RadioButton<T extends string | number = ''>({
18
20
  onChange,
19
21
  disabled,
20
22
  readOnly,
23
+ className,
24
+ 'aria-describedby': ariaDescribedBy,
21
25
  }: RadioButtonProps<T>) {
22
26
  return (
23
27
  <>
24
28
  <input
25
29
  type="radio"
26
- className="sr-only"
30
+ className={clsx('sr-only', className)}
27
31
  id={id}
28
32
  value={value}
29
33
  name={name}
30
34
  checked={checked}
31
35
  disabled={disabled || readOnly}
36
+ aria-describedby={ariaDescribedBy}
32
37
  onChange={() => {
33
38
  if (!checked) {
34
39
  onChange?.(value);
package/src/i18n/en.json CHANGED
@@ -45,6 +45,7 @@
45
45
  "neptune.Upload.csFailureText": "Upload failed. Please, try again",
46
46
  "neptune.Upload.csSuccessText": "Upload complete!",
47
47
  "neptune.Upload.csTooLargeMessage": "Please provide a file smaller than {maxSize}MB",
48
+ "neptune.Upload.csTooLargeNoLimitMessage": "Please provide a smaller file",
48
49
  "neptune.Upload.csWrongTypeMessage": "File type not supported. Please try again with a different file",
49
50
  "neptune.Upload.psButtonText": "Cancel",
50
51
  "neptune.Upload.psProcessingText": "Uploading...",
@@ -52,6 +53,7 @@
52
53
  "neptune.Upload.usButtonText": "Or select a file",
53
54
  "neptune.Upload.usDropMessage": "Drop file to start upload",
54
55
  "neptune.Upload.usPlaceholder": "Drag and drop a file less than {maxSize}MB",
56
+ "neptune.Upload.usPlaceholderNoLimit": "Drag and drop a file",
55
57
  "neptune.UploadButton.allFileTypes": "All file types",
56
58
  "neptune.UploadButton.dropFiles": "Drop file to start upload",
57
59
  "neptune.UploadButton.instructions": "{fileTypes}, less than {size}MB",
@@ -91,7 +91,7 @@ export const Basic: Story = {
91
91
  gridTemplate: `auto auto / repeat(6, min-content)`,
92
92
  }}
93
93
  >
94
- {['Primary', 'Secondary', 'Tertiary', 'Text', 'Neg primary', 'Neg secondary'].map(
94
+ {['Primary', 'Secondary', 'Tertiary', 'Minimal', 'Neg primary', 'Neg secondary'].map(
95
95
  (variant) => (
96
96
  <Body type="body-default-bold">{variant}</Body>
97
97
  ),
@@ -12,7 +12,7 @@ export type Props = {
12
12
  Pick<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick' | 'disabled'> &
13
13
  Pick<
14
14
  HTMLAttributes<HTMLDivElement>,
15
- 'className' | 'role' | 'children' | 'aria-label' | 'tabIndex'
15
+ 'id' | 'className' | 'role' | 'children' | 'aria-label' | 'tabIndex'
16
16
  >;
17
17
 
18
18
  const IconButton = forwardRef(function IconButton(
@@ -10,6 +10,9 @@ export interface ImageProps {
10
10
  onLoad?: () => void;
11
11
  onError?: () => void;
12
12
  className?: string;
13
+ /**
14
+ * Specifies the [loading behavior of the image](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img#loading).
15
+ */
13
16
  loading?: 'lazy' | 'eager';
14
17
  stretch?: boolean;
15
18
  role?: string;
@@ -1 +1,2 @@
1
+ export type { ImageProps } from './Image';
1
2
  export { default } from './Image';
package/src/index.ts CHANGED
@@ -108,6 +108,7 @@ export type {
108
108
  TableCellStatus,
109
109
  TableCellType,
110
110
  } from './table';
111
+ export type { ListItemProps, ListItemAdditionalInfoProps, ListItemCheckboxProps } from './listItem';
111
112
 
112
113
  /**
113
114
  * Components
@@ -209,6 +210,7 @@ export { default as Typeahead } from './typeahead';
209
210
  export { default as Upload } from './upload';
210
211
  export { default as UploadInput } from './uploadInput';
211
212
  export { default as Table } from './table';
213
+ export { default as ListItem } from './listItem';
212
214
 
213
215
  /**
214
216
  * Hooks
@@ -0,0 +1,145 @@
1
+ import { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { action } from 'storybook/actions';
3
+ import { lorem20 } from '../../test-utils';
4
+ import { ListItem } from '../ListItem';
5
+ import {
6
+ SB_LIST_ITEM_CONTROLS as CONTROLS,
7
+ SB_LIST_ITEM_MEDIA as MEDIA,
8
+ } from '../_stories/subcomponents';
9
+ import type { ListItemAdditionalInfoProps } from './ListItemAdditionalInfo';
10
+
11
+ /**
12
+ * Use additional information to add extra details that help make the information clearer for users. Use additional information only after you've used the subtitle.
13
+ *
14
+ * Refer to the [design documentation](https://wise.design/components/list-item#content:~:text=StatusIcon.iconLabel.error-,Additional%20information,-Use%20additional%20information) for more details.
15
+ */
16
+ export default {
17
+ component: ListItem.AdditionalInfo,
18
+ title: 'Content/ListItem/ListItem.AdditionalInfo',
19
+ parameters: {
20
+ docs: {
21
+ toc: true,
22
+ },
23
+ },
24
+ args: {
25
+ action: {
26
+ label: 'Details about the subject.',
27
+ href: 'https://wise.com',
28
+ target: '_blank',
29
+ },
30
+ children: lorem20,
31
+ },
32
+ argTypes: {
33
+ children: {
34
+ table: {
35
+ type: { summary: 'ReactNode' },
36
+ },
37
+ },
38
+ },
39
+ } satisfies Meta<ListItemAdditionalInfoProps>;
40
+
41
+ type Story = StoryObj<ListItemAdditionalInfoProps>;
42
+
43
+ export const Playground: Story = {
44
+ tags: ['!autodocs'],
45
+ render: (args: ListItemAdditionalInfoProps) => {
46
+ return (
47
+ <ListItem
48
+ title="List item title"
49
+ subtitle="Subtitle goes here"
50
+ media={MEDIA.avatarSingle}
51
+ control={CONTROLS.partialButton}
52
+ additionalInfo={<ListItem.AdditionalInfo {...args} />}
53
+ />
54
+ );
55
+ },
56
+ };
57
+
58
+ /**
59
+ * Fully interactive ListItems do not allow for any nested links or inline buttons as that would fail accessibility compliance.
60
+ *
61
+ * Non-interactive or partially-interactive ListItems allow appending a single link or inline button via `action` prop. The restriction has been introduced to ensure that the ListItem remains accessible and adheres to the vendors' best practices for mobile platforms.
62
+ */
63
+ export const Interactivity: Story = {
64
+ args: {
65
+ action: {
66
+ label: 'Details about the subject.',
67
+ href: 'https://wise.com',
68
+ target: '_blank',
69
+ },
70
+ },
71
+ render: (args: ListItemAdditionalInfoProps) => {
72
+ return (
73
+ <ol className="list-unstyled">
74
+ <ListItem
75
+ title="Fully interactive ListItem"
76
+ subtitle="Subtitle goes here"
77
+ media={MEDIA.avatarSingle}
78
+ control={CONTROLS.button}
79
+ additionalInfo={<ListItem.AdditionalInfo {...args} action={undefined} />}
80
+ />
81
+
82
+ <ListItem
83
+ title="Partially interactive ListItem"
84
+ subtitle="Subtitle goes here"
85
+ media={MEDIA.avatarSingle}
86
+ control={CONTROLS.partialButton}
87
+ additionalInfo={<ListItem.AdditionalInfo {...args} />}
88
+ />
89
+
90
+ <ListItem
91
+ title="Non-interactive ListItem"
92
+ subtitle="Subtitle goes here"
93
+ media={MEDIA.avatarSingle}
94
+ additionalInfo={<ListItem.AdditionalInfo {...args} />}
95
+ />
96
+ </ol>
97
+ );
98
+ },
99
+ };
100
+
101
+ /**
102
+ * Interactive `ListItem.AdditionalInfo` allows for 2 types of actions: a link or a button.
103
+ */
104
+ export const Actions: Story = {
105
+ render: (args: ListItemAdditionalInfoProps) => {
106
+ return (
107
+ <ol className="list-unstyled">
108
+ <ListItem
109
+ title="Partially interactive ListItem"
110
+ subtitle="Subtitle goes here"
111
+ media={MEDIA.avatarSingle}
112
+ control={CONTROLS.partialButton}
113
+ additionalInfo={
114
+ <ListItem.AdditionalInfo
115
+ {...args}
116
+ action={{
117
+ label: 'I am a link.',
118
+ href: 'https://wise.com',
119
+ target: '_blank',
120
+ }}
121
+ />
122
+ }
123
+ />
124
+
125
+ <ListItem
126
+ title="Partially interactive ListItem"
127
+ subtitle="Subtitle goes here"
128
+ media={MEDIA.avatarSingle}
129
+ control={CONTROLS.partialButton}
130
+ additionalInfo={
131
+ <ListItem.AdditionalInfo
132
+ {...args}
133
+ action={{
134
+ label: 'I am a button.',
135
+ onClick: () => {
136
+ action('Button clicked')();
137
+ },
138
+ }}
139
+ />
140
+ }
141
+ />
142
+ </ol>
143
+ );
144
+ },
145
+ };
@@ -0,0 +1,36 @@
1
+ import { PropsWithChildren, useContext } from 'react';
2
+ import { ListItemContext, type ListItemContextData } from '../ListItemContext';
3
+ import Body from '../../body';
4
+ import Link, { LinkProps } from '../../link';
5
+ import { Typography } from '../../common';
6
+
7
+ export type ListItemAdditionalInfoProps = PropsWithChildren<{
8
+ /**
9
+ * Props object to be passed to the [Link](https://storybook.wise.design/?path=/docs/typography-link--docs) component.
10
+ */
11
+ action?: { label: string } & Pick<LinkProps, 'href' | 'onClick' | 'target'>;
12
+ }>;
13
+
14
+ export const AdditionalInfo = function ({ children, action }: ListItemAdditionalInfoProps) {
15
+ const { ids } = useContext<ListItemContextData>(ListItemContext);
16
+
17
+ return (
18
+ <Body
19
+ type={Typography.BODY_DEFAULT}
20
+ id={ids.additionalInfo}
21
+ className="wds-list-item-additional-info"
22
+ >
23
+ {children}
24
+ {action ? (
25
+ <>
26
+ {' '}
27
+ <Link href={action.href} target={action.target} onClick={action.onClick}>
28
+ {action.label}
29
+ </Link>
30
+ </>
31
+ ) : null}
32
+ </Body>
33
+ );
34
+ };
35
+
36
+ AdditionalInfo.displayName = 'ListItem.AdditionalInfo';
@@ -0,0 +1,2 @@
1
+ export type { ListItemAdditionalInfoProps } from './ListItemAdditionalInfo';
2
+ export { AdditionalInfo } from './ListItemAdditionalInfo';