@transferwise/components 46.74.0 → 46.74.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.
- package/build/dimmer/Dimmer.js +3 -1
- package/build/dimmer/Dimmer.js.map +1 -1
- package/build/dimmer/Dimmer.mjs +3 -1
- package/build/dimmer/Dimmer.mjs.map +1 -1
- package/build/drawer/Drawer.js +2 -0
- package/build/drawer/Drawer.js.map +1 -1
- package/build/drawer/Drawer.mjs +2 -0
- package/build/drawer/Drawer.mjs.map +1 -1
- package/build/modal/Modal.js +3 -0
- package/build/modal/Modal.js.map +1 -1
- package/build/modal/Modal.mjs +3 -0
- package/build/modal/Modal.mjs.map +1 -1
- package/build/types/dimmer/Dimmer.d.ts +2 -1
- package/build/types/dimmer/Dimmer.d.ts.map +1 -1
- package/build/types/drawer/Drawer.d.ts +2 -1
- package/build/types/drawer/Drawer.d.ts.map +1 -1
- package/build/types/modal/Modal.d.ts +2 -1
- package/build/types/modal/Modal.d.ts.map +1 -1
- package/build/types/uploadInput/UploadInput.d.ts +9 -0
- package/build/types/uploadInput/UploadInput.d.ts.map +1 -1
- package/build/types/uploadInput/uploadItem/UploadItem.d.ts +16 -1
- package/build/types/uploadInput/uploadItem/UploadItem.d.ts.map +1 -1
- package/build/types/uploadInput/uploadItem/UploadItemLink.d.ts.map +1 -1
- package/build/uploadInput/UploadInput.js +71 -66
- package/build/uploadInput/UploadInput.js.map +1 -1
- package/build/uploadInput/UploadInput.mjs +72 -67
- package/build/uploadInput/UploadInput.mjs.map +1 -1
- package/build/uploadInput/uploadItem/UploadItem.js +13 -4
- package/build/uploadInput/uploadItem/UploadItem.js.map +1 -1
- package/build/uploadInput/uploadItem/UploadItem.mjs +13 -4
- package/build/uploadInput/uploadItem/UploadItem.mjs.map +1 -1
- package/build/uploadInput/uploadItem/UploadItemLink.js +1 -0
- package/build/uploadInput/uploadItem/UploadItemLink.js.map +1 -1
- package/build/uploadInput/uploadItem/UploadItemLink.mjs +1 -0
- package/build/uploadInput/uploadItem/UploadItemLink.mjs.map +1 -1
- package/package.json +2 -2
- package/src/dimmer/Dimmer.spec.js +8 -0
- package/src/dimmer/Dimmer.tsx +4 -0
- package/src/drawer/Drawer.spec.js +25 -6
- package/src/drawer/Drawer.tsx +3 -1
- package/src/modal/Modal.spec.js +19 -1
- package/src/modal/Modal.tsx +4 -0
- package/src/uploadInput/UploadInput.spec.tsx +121 -9
- package/src/uploadInput/UploadInput.tests.story.tsx +207 -140
- package/src/uploadInput/UploadInput.tsx +110 -77
- package/src/uploadInput/uploadItem/UploadItem.spec.tsx +1 -0
- package/src/uploadInput/uploadItem/UploadItem.tsx +30 -6
- package/src/uploadInput/uploadItem/UploadItemLink.tsx +9 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UploadItem.mjs","sources":["../../../src/uploadInput/uploadItem/UploadItem.tsx"],"sourcesContent":["import { Bin, CheckCircleFill, CrossCircleFill } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport { forwardRef, useImperativeHandle, useRef } from 'react';\nimport { useIntl } from 'react-intl';\n\nimport Body from '../../body';\nimport { Size, Status, Typography, Sentiment } from '../../common';\nimport ProcessIndicator from '../../processIndicator/ProcessIndicator';\nimport StatusIcon from '../../statusIcon/StatusIcon';\nimport { UploadedFile, UploadError } from '../types';\n\nimport MESSAGES from './UploadItem.messages';\nimport { UploadItemLink } from './UploadItemLink';\n\nexport type UploadItemProps = React.JSX.IntrinsicAttributes & {\n file: UploadedFile;\n /**\n * Is this Item part of a multiple- or single-file UploadInput\n */\n singleFileUpload: boolean;\n canDelete: boolean;\n onDelete: () => void;\n\n /**\n * Callback to be called when the file link is clicked.\n * When provided, you need to manually trigger actions to load/download the file.\n *\n * @param file\n */\n onDownload?: (file: UploadedFile) => void;\n ref?: React.Ref<UploadItemRef>;\n};\n\ninterface UploadItemRef {\n focus: () => void;\n}\n\nexport enum TEST_IDS {\n uploadItem = 'uploadItem',\n mediaBody = 'mediaBody',\n}\n\nconst UploadItem = forwardRef<UploadItemRef, UploadItemProps>(\n ({ file, canDelete, onDelete, onDownload, singleFileUpload }, ref) => {\n const { formatMessage } = useIntl();\n const { status, filename, error, errors, url } = file;\n const linkRef = useRef<HTMLAnchorElement>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n useImperativeHandle<UploadItemRef, UploadItemRef>(ref, () => ({\n focus: (): void => {\n if (url) {\n linkRef.current?.focus();\n } else {\n buttonRef.current?.focus();\n }\n },\n }));\n\n const isSucceeded = [Status.SUCCEEDED, undefined].includes(status) && !!url;\n\n /**\n * We're temporarily reverting to the regular icon components,\n * until the StatusIcon receives 24px sizing. Some misalignment\n * to be expected.\n */\n const getIcon = () => {\n if (error || errors?.length || status === Status.FAILED) {\n return <CrossCircleFill size={24} className=\"emphasis--negative\" />;\n }\n\n let processIndicator: React.ReactNode;\n\n switch (status) {\n case Status.PROCESSING:\n case Status.PENDING:\n processIndicator = (\n <ProcessIndicator size={Size.EXTRA_SMALL} status={Status.PROCESSING} />\n );\n break;\n case Status.SUCCEEDED:\n case Status.DONE:\n default:\n processIndicator = <CheckCircleFill size={24} className=\"emphasis--positive\" />;\n }\n\n return processIndicator;\n };\n\n const getErrorMessage = (error?: UploadError) =>\n typeof error === 'object' ? error.message : error || formatMessage(MESSAGES.uploadingFailed);\n\n const getMultipleErrors = (errors?: UploadError[]) => {\n if (!errors?.length) {\n return null;\n }\n\n if (errors?.length === 1) {\n return getErrorMessage(errors[0]);\n }\n\n return (\n <ul className=\"np-upload-input-errors m-b-0\">\n {errors.map((error, index) => {\n // eslint-disable-next-line react/no-array-index-key\n return <li key={index}>{getErrorMessage(error)}</li>;\n })}\n </ul>\n );\n };\n\n const getDescription = () => {\n if (error || errors?.length || status === Status.FAILED) {\n return (\n <Body type={Typography.BODY_DEFAULT_BOLD} className=\"np-upload-input__text text-negative\">\n {errors?.length ? getMultipleErrors(errors) : getErrorMessage(error)}\n </Body>\n );\n }\n\n switch (status) {\n case Status.PENDING:\n return (\n <Body type={Typography.BODY_DEFAULT} className=\"np-upload-input__text\">\n {formatMessage(MESSAGES.uploading)}\n </Body>\n );\n case Status.PROCESSING:\n return <Body className=\"np-upload-input__text\">{formatMessage(MESSAGES.deleting)}</Body>;\n case Status.SUCCEEDED:\n case Status.DONE:\n default:\n return (\n <Body type={Typography.BODY_DEFAULT_BOLD} className=\"np-upload-input__text\">\n {formatMessage(MESSAGES.uploaded)}\n </Body>\n );\n }\n };\n\n const getTitle = () => {\n return filename || formatMessage(MESSAGES.uploadedFile);\n };\n\n const onDownloadFile = (event: React.MouseEvent): void => {\n if (onDownload) {\n event.preventDefault();\n onDownload(file);\n }\n };\n\n return (\n <div\n className={clsx('np-upload-input__item', { 'is-interactive': isSucceeded && url })}\n data-testid={TEST_IDS.uploadItem}\n >\n <UploadItemLink\n ref={linkRef}\n url={isSucceeded ? url : undefined}\n singleFileUpload={singleFileUpload}\n onDownload={onDownloadFile}\n >\n <span className=\"np-upload-input__icon\">{getIcon()}</span>\n <div className=\"np-upload-input__item-content\" data-testid={TEST_IDS.mediaBody}>\n <Body type={Typography.BODY_LARGE} className=\"np-upload-input__title text-word-break\">\n {getTitle()}\n </Body>\n {getDescription()}\n </div>\n </UploadItemLink>\n {canDelete && (\n <div className=\"np-upload-input__item-action\">\n <button\n ref={buttonRef}\n aria-label={formatMessage(MESSAGES.removeFile, { filename })}\n className=\"np-upload-input__item-button\"\n type=\"button\"\n onClick={() => onDelete()}\n >\n <Bin size={16} />\n </button>\n </div>\n )}\n </div>\n );\n },\n);\n\nUploadItem.displayName = 'UploadItem';\n\nexport default UploadItem;\n"],"names":["TEST_IDS","UploadItem","forwardRef","file","canDelete","onDelete","onDownload","singleFileUpload","ref","formatMessage","useIntl","status","filename","error","errors","url","linkRef","useRef","buttonRef","useImperativeHandle","focus","current","isSucceeded","Status","SUCCEEDED","undefined","includes","getIcon","length","FAILED","_jsx","CrossCircleFill","size","className","processIndicator","PROCESSING","PENDING","ProcessIndicator","Size","EXTRA_SMALL","DONE","CheckCircleFill","getErrorMessage","message","MESSAGES","uploadingFailed","getMultipleErrors","children","map","index","getDescription","Body","type","Typography","BODY_DEFAULT_BOLD","BODY_DEFAULT","uploading","deleting","uploaded","getTitle","uploadedFile","onDownloadFile","event","preventDefault","_jsxs","clsx","uploadItem","UploadItemLink","mediaBody","BODY_LARGE","removeFile","onClick","Bin","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UploadItem.mjs","sources":["../../../src/uploadInput/uploadItem/UploadItem.tsx"],"sourcesContent":["import { Bin, CheckCircleFill, CrossCircleFill } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport { forwardRef, useImperativeHandle, useRef } from 'react';\nimport { useIntl } from 'react-intl';\n\nimport Body from '../../body';\nimport { Size, Status, Typography } from '../../common';\nimport ProcessIndicator from '../../processIndicator/ProcessIndicator';\nimport { UploadedFile, UploadError } from '../types';\n\nimport MESSAGES from './UploadItem.messages';\nimport { UploadItemLink } from './UploadItemLink';\n\nexport type UploadItemProps = React.JSX.IntrinsicAttributes & {\n file: UploadedFile;\n /**\n * Is this Item part of a multiple- or single-file UploadInput\n */\n singleFileUpload: boolean;\n canDelete: boolean;\n onDelete: () => void;\n onFocus: () => void;\n\n /**\n * Callback to be called when the file link is clicked.\n * When provided, you need to manually trigger actions to load/download the file.\n *\n * @param file\n */\n onDownload?: (file: UploadedFile) => void;\n ref?: React.Ref<UploadItemRef>;\n};\ninterface UploadItemRef {\n /**\n * A method to set focus on the upload item.\n * @returns {void}\n */\n focus: () => void;\n\n /**\n * A required unique identifier for the upload item.\n */\n id: string | number;\n\n /**\n * An optional status of the upload item.\n */\n status?: string;\n}\n\nexport enum TEST_IDS {\n uploadItem = 'uploadItem',\n mediaBody = 'mediaBody',\n link = 'link',\n action = 'action',\n}\n\nconst UploadItem = forwardRef<UploadItemRef, UploadItemProps>(\n ({ file, canDelete, onDelete, onDownload, singleFileUpload, onFocus: handleFocus }, ref) => {\n const { formatMessage } = useIntl();\n const { status, filename, error, errors, url } = file;\n const linkRef = useRef<HTMLAnchorElement>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n useImperativeHandle<UploadItemRef, UploadItemRef>(ref, () => ({\n focus: (): void => {\n if (url) {\n linkRef.current?.focus();\n } else {\n buttonRef.current?.focus();\n }\n },\n id: file.id,\n status: file.status,\n }));\n\n const isSucceeded = [Status.SUCCEEDED, undefined].includes(status) && !!url;\n\n /**\n * We're temporarily reverting to the regular icon components,\n * until the StatusIcon receives 24px sizing. Some misalignment\n * to be expected.\n */\n const getIcon = () => {\n if (error || errors?.length || status === Status.FAILED) {\n return <CrossCircleFill size={24} className=\"emphasis--negative\" />;\n }\n\n let processIndicator: React.ReactNode;\n\n switch (status) {\n case Status.PROCESSING:\n case Status.PENDING:\n processIndicator = (\n <ProcessIndicator size={Size.EXTRA_SMALL} status={Status.PROCESSING} />\n );\n break;\n case Status.SUCCEEDED:\n case Status.DONE:\n default:\n processIndicator = <CheckCircleFill size={24} className=\"emphasis--positive\" />;\n }\n\n return processIndicator;\n };\n\n const getErrorMessage = (error?: UploadError) =>\n typeof error === 'object' ? error.message : error || formatMessage(MESSAGES.uploadingFailed);\n\n const getMultipleErrors = (errors?: UploadError[]) => {\n if (!errors?.length) {\n return null;\n }\n\n if (errors?.length === 1) {\n return getErrorMessage(errors[0]);\n }\n\n return (\n <ul className=\"np-upload-input-errors m-b-0\">\n {errors.map((error, index) => {\n // eslint-disable-next-line react/no-array-index-key\n return <li key={index}>{getErrorMessage(error)}</li>;\n })}\n </ul>\n );\n };\n\n const getDescription = () => {\n if (error || errors?.length || status === Status.FAILED) {\n return (\n <Body type={Typography.BODY_DEFAULT_BOLD} className=\"np-upload-input__text text-negative\">\n {errors?.length ? getMultipleErrors(errors) : getErrorMessage(error)}\n </Body>\n );\n }\n\n switch (status) {\n case Status.PENDING:\n return (\n <Body type={Typography.BODY_DEFAULT} className=\"np-upload-input__text\">\n {formatMessage(MESSAGES.uploading)}\n </Body>\n );\n case Status.PROCESSING:\n return <Body className=\"np-upload-input__text\">{formatMessage(MESSAGES.deleting)}</Body>;\n case Status.SUCCEEDED:\n case Status.DONE:\n default:\n return (\n <Body type={Typography.BODY_DEFAULT_BOLD} className=\"np-upload-input__text\">\n {formatMessage(MESSAGES.uploaded)}\n </Body>\n );\n }\n };\n\n const getTitle = () => {\n return filename || formatMessage(MESSAGES.uploadedFile);\n };\n\n const onDownloadFile = (event: React.MouseEvent): void => {\n if (onDownload) {\n event.preventDefault();\n onDownload(file);\n }\n };\n\n return (\n <div\n className={clsx('np-upload-input__item', { 'is-interactive': isSucceeded && url })}\n data-testid={`${file.id}-${TEST_IDS.uploadItem}`}\n >\n <UploadItemLink\n ref={linkRef}\n url={isSucceeded ? url : undefined}\n singleFileUpload={singleFileUpload}\n data-testid={`${file.id}-${TEST_IDS.link}`}\n onDownload={onDownloadFile}\n >\n <span className=\"np-upload-input__icon\">{getIcon()}</span>\n <div\n className=\"np-upload-input__item-content\"\n data-testid={`${file.id}-${TEST_IDS.mediaBody}`}\n >\n <Body type={Typography.BODY_LARGE} className=\"np-upload-input__title text-word-break\">\n {getTitle()}\n </Body>\n {getDescription()}\n </div>\n </UploadItemLink>\n {canDelete && (\n <div className=\"np-upload-input__item-action\">\n <button\n ref={buttonRef}\n aria-label={formatMessage(MESSAGES.removeFile, { filename })}\n className=\"np-upload-input__item-button\"\n type=\"button\"\n tabIndex={0}\n data-testid={`${file.id}-${TEST_IDS.action}`}\n onClick={() => onDelete()}\n onFocus={handleFocus}\n >\n <Bin size={16} />\n </button>\n </div>\n )}\n </div>\n );\n },\n);\n\nUploadItem.displayName = 'UploadItem';\n\nexport default UploadItem;\n"],"names":["TEST_IDS","UploadItem","forwardRef","file","canDelete","onDelete","onDownload","singleFileUpload","onFocus","handleFocus","ref","formatMessage","useIntl","status","filename","error","errors","url","linkRef","useRef","buttonRef","useImperativeHandle","focus","current","id","isSucceeded","Status","SUCCEEDED","undefined","includes","getIcon","length","FAILED","_jsx","CrossCircleFill","size","className","processIndicator","PROCESSING","PENDING","ProcessIndicator","Size","EXTRA_SMALL","DONE","CheckCircleFill","getErrorMessage","message","MESSAGES","uploadingFailed","getMultipleErrors","children","map","index","getDescription","Body","type","Typography","BODY_DEFAULT_BOLD","BODY_DEFAULT","uploading","deleting","uploaded","getTitle","uploadedFile","onDownloadFile","event","preventDefault","_jsxs","clsx","uploadItem","UploadItemLink","link","mediaBody","BODY_LARGE","removeFile","tabIndex","action","onClick","Bin","displayName"],"mappings":"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"}
|
|
@@ -23,6 +23,7 @@ const UploadItemLink = /*#__PURE__*/React.forwardRef(({
|
|
|
23
23
|
target: "_blank",
|
|
24
24
|
rel: "noopener noreferrer",
|
|
25
25
|
className: clsx.clsx('np-upload-input__item-link', singleFileUpload ? 'np-upload-input__item-link--single-file' : ''),
|
|
26
|
+
tabIndex: 0,
|
|
26
27
|
onClick: onDownload,
|
|
27
28
|
children: children
|
|
28
29
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UploadItemLink.js","sources":["../../../src/uploadInput/uploadItem/UploadItemLink.tsx"],"sourcesContent":["import { PropsWithChildren, MouseEvent, forwardRef } from 'react';\nimport { clsx } from 'clsx';\n\ntype UploadItemLinkProps = PropsWithChildren<{\n url?: string;\n onDownload?: (event: MouseEvent) => void;\n singleFileUpload: boolean;\n}>;\n\nexport const UploadItemLink = forwardRef<HTMLAnchorElement | HTMLDivElement, UploadItemLinkProps>(\n ({ children, url, onDownload, singleFileUpload }, ref) => {\n if (!url) {\n return <div
|
|
1
|
+
{"version":3,"file":"UploadItemLink.js","sources":["../../../src/uploadInput/uploadItem/UploadItemLink.tsx"],"sourcesContent":["import { PropsWithChildren, MouseEvent, forwardRef } from 'react';\nimport { clsx } from 'clsx';\n\ntype UploadItemLinkProps = PropsWithChildren<{\n url?: string;\n onDownload?: (event: MouseEvent) => void;\n singleFileUpload: boolean;\n}>;\n\nexport const UploadItemLink = forwardRef<HTMLAnchorElement | HTMLDivElement, UploadItemLinkProps>(\n ({ children, url, onDownload, singleFileUpload }, ref) => {\n if (!url) {\n return (\n <div\n ref={ref as React.RefObject<HTMLDivElement>}\n className={clsx('np-upload-input__item-container')}\n >\n {children}\n </div>\n );\n }\n\n return (\n <a\n ref={ref as React.RefObject<HTMLAnchorElement>}\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={clsx(\n 'np-upload-input__item-link',\n singleFileUpload ? 'np-upload-input__item-link--single-file' : '',\n )}\n tabIndex={0}\n onClick={onDownload}\n >\n {children}\n </a>\n );\n },\n);\n"],"names":["UploadItemLink","forwardRef","children","url","onDownload","singleFileUpload","ref","_jsx","className","clsx","href","target","rel","tabIndex","onClick"],"mappings":";;;;;;AASaA,MAAAA,cAAc,gBAAGC,gBAAU,CACtC,CAAC;EAAEC,QAAQ;EAAEC,GAAG;EAAEC,UAAU;AAAEC,EAAAA,gBAAAA;CAAkB,EAAEC,GAAG,KAAI;EACvD,IAAI,CAACH,GAAG,EAAE;AACR,IAAA,oBACEI,cAAA,CAAA,KAAA,EAAA;AACED,MAAAA,GAAG,EAAEA,GAAuC;AAC5CE,MAAAA,SAAS,EAAEC,SAAI,CAAC,iCAAiC,CAAE;AAAAP,MAAAA,QAAA,EAElDA,QAAAA;AAAQ,KACN,CAAC,CAAA;AAEV,GAAA;AAEA,EAAA,oBACEK,cAAA,CAAA,GAAA,EAAA;AACED,IAAAA,GAAG,EAAEA,GAA0C;AAC/CI,IAAAA,IAAI,EAAEP,GAAI;AACVQ,IAAAA,MAAM,EAAC,QAAQ;AACfC,IAAAA,GAAG,EAAC,qBAAqB;IACzBJ,SAAS,EAAEC,SAAI,CACb,4BAA4B,EAC5BJ,gBAAgB,GAAG,yCAAyC,GAAG,EAAE,CACjE;AACFQ,IAAAA,QAAQ,EAAE,CAAE;AACZC,IAAAA,OAAO,EAAEV,UAAW;AAAAF,IAAAA,QAAA,EAEnBA,QAAAA;AAAQ,GACR,CAAC,CAAA;AAER,CAAC;;;;"}
|
|
@@ -21,6 +21,7 @@ const UploadItemLink = /*#__PURE__*/forwardRef(({
|
|
|
21
21
|
target: "_blank",
|
|
22
22
|
rel: "noopener noreferrer",
|
|
23
23
|
className: clsx('np-upload-input__item-link', singleFileUpload ? 'np-upload-input__item-link--single-file' : ''),
|
|
24
|
+
tabIndex: 0,
|
|
24
25
|
onClick: onDownload,
|
|
25
26
|
children: children
|
|
26
27
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UploadItemLink.mjs","sources":["../../../src/uploadInput/uploadItem/UploadItemLink.tsx"],"sourcesContent":["import { PropsWithChildren, MouseEvent, forwardRef } from 'react';\nimport { clsx } from 'clsx';\n\ntype UploadItemLinkProps = PropsWithChildren<{\n url?: string;\n onDownload?: (event: MouseEvent) => void;\n singleFileUpload: boolean;\n}>;\n\nexport const UploadItemLink = forwardRef<HTMLAnchorElement | HTMLDivElement, UploadItemLinkProps>(\n ({ children, url, onDownload, singleFileUpload }, ref) => {\n if (!url) {\n return <div
|
|
1
|
+
{"version":3,"file":"UploadItemLink.mjs","sources":["../../../src/uploadInput/uploadItem/UploadItemLink.tsx"],"sourcesContent":["import { PropsWithChildren, MouseEvent, forwardRef } from 'react';\nimport { clsx } from 'clsx';\n\ntype UploadItemLinkProps = PropsWithChildren<{\n url?: string;\n onDownload?: (event: MouseEvent) => void;\n singleFileUpload: boolean;\n}>;\n\nexport const UploadItemLink = forwardRef<HTMLAnchorElement | HTMLDivElement, UploadItemLinkProps>(\n ({ children, url, onDownload, singleFileUpload }, ref) => {\n if (!url) {\n return (\n <div\n ref={ref as React.RefObject<HTMLDivElement>}\n className={clsx('np-upload-input__item-container')}\n >\n {children}\n </div>\n );\n }\n\n return (\n <a\n ref={ref as React.RefObject<HTMLAnchorElement>}\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={clsx(\n 'np-upload-input__item-link',\n singleFileUpload ? 'np-upload-input__item-link--single-file' : '',\n )}\n tabIndex={0}\n onClick={onDownload}\n >\n {children}\n </a>\n );\n },\n);\n"],"names":["UploadItemLink","forwardRef","children","url","onDownload","singleFileUpload","ref","_jsx","className","clsx","href","target","rel","tabIndex","onClick"],"mappings":";;;;AASaA,MAAAA,cAAc,gBAAGC,UAAU,CACtC,CAAC;EAAEC,QAAQ;EAAEC,GAAG;EAAEC,UAAU;AAAEC,EAAAA,gBAAAA;CAAkB,EAAEC,GAAG,KAAI;EACvD,IAAI,CAACH,GAAG,EAAE;AACR,IAAA,oBACEI,GAAA,CAAA,KAAA,EAAA;AACED,MAAAA,GAAG,EAAEA,GAAuC;AAC5CE,MAAAA,SAAS,EAAEC,IAAI,CAAC,iCAAiC,CAAE;AAAAP,MAAAA,QAAA,EAElDA,QAAAA;AAAQ,KACN,CAAC,CAAA;AAEV,GAAA;AAEA,EAAA,oBACEK,GAAA,CAAA,GAAA,EAAA;AACED,IAAAA,GAAG,EAAEA,GAA0C;AAC/CI,IAAAA,IAAI,EAAEP,GAAI;AACVQ,IAAAA,MAAM,EAAC,QAAQ;AACfC,IAAAA,GAAG,EAAC,qBAAqB;IACzBJ,SAAS,EAAEC,IAAI,CACb,4BAA4B,EAC5BJ,gBAAgB,GAAG,yCAAyC,GAAG,EAAE,CACjE;AACFQ,IAAAA,QAAQ,EAAE,CAAE;AACZC,IAAAA,OAAO,EAAEV,UAAW;AAAAF,IAAAA,QAAA,EAEnBA,QAAAA;AAAQ,GACR,CAAC,CAAA;AAER,CAAC;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@transferwise/components",
|
|
3
|
-
"version": "46.74.
|
|
3
|
+
"version": "46.74.1",
|
|
4
4
|
"description": "Neptune React components",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -91,8 +91,8 @@
|
|
|
91
91
|
"rollup": "^4.18.1",
|
|
92
92
|
"rollup-preserve-directives": "^1.1.1",
|
|
93
93
|
"storybook": "^8.2.2",
|
|
94
|
-
"@transferwise/less-config": "3.1.0",
|
|
95
94
|
"@transferwise/neptune-css": "14.19.1",
|
|
95
|
+
"@transferwise/less-config": "3.1.0",
|
|
96
96
|
"@wise/components-theming": "1.6.1"
|
|
97
97
|
},
|
|
98
98
|
"peerDependencies": {
|
|
@@ -15,6 +15,7 @@ describe('Dimmer', () => {
|
|
|
15
15
|
children: <div />,
|
|
16
16
|
className: undefined,
|
|
17
17
|
onClose: undefined,
|
|
18
|
+
onExited: jest.fn(),
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
beforeEach(() => {
|
|
@@ -76,4 +77,11 @@ describe('Dimmer', () => {
|
|
|
76
77
|
exit: 'dimmer--exit dimmer--exit-fade',
|
|
77
78
|
});
|
|
78
79
|
});
|
|
80
|
+
|
|
81
|
+
it('calls onExited when the exit animation is finished', () => {
|
|
82
|
+
component.setProps({ fadeContentOnExit: true });
|
|
83
|
+
const transition = component.find('CSSTransition');
|
|
84
|
+
transition.prop('onExited')();
|
|
85
|
+
expect(props.onExited).toHaveBeenCalled();
|
|
86
|
+
});
|
|
79
87
|
});
|
package/src/dimmer/Dimmer.tsx
CHANGED
|
@@ -31,6 +31,7 @@ export type DimmerProps = CommonProps & {
|
|
|
31
31
|
scrollable?: boolean;
|
|
32
32
|
transparent?: boolean;
|
|
33
33
|
onClose?: (event: KeyboardEvent | MouseEvent) => void;
|
|
34
|
+
onExited?: () => void;
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
export const handleTouchMove = (event: Event) => {
|
|
@@ -56,6 +57,7 @@ const Dimmer = ({
|
|
|
56
57
|
scrollable = false,
|
|
57
58
|
transparent = false,
|
|
58
59
|
onClose,
|
|
60
|
+
onExited: handleExited,
|
|
59
61
|
}: DimmerProps) => {
|
|
60
62
|
const [hasNotExited, setHasNotExited] = useState(false);
|
|
61
63
|
const dimmerReference = useRef<HTMLDivElement>(null);
|
|
@@ -101,6 +103,8 @@ const Dimmer = ({
|
|
|
101
103
|
if (dimmerReference.current) {
|
|
102
104
|
dimmerManager.remove(dimmerReference.current);
|
|
103
105
|
}
|
|
106
|
+
|
|
107
|
+
handleExited?.();
|
|
104
108
|
};
|
|
105
109
|
|
|
106
110
|
useEffect(() => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mount } from 'enzyme';
|
|
2
2
|
|
|
3
3
|
import { mockMatchMedia } from '../test-utils';
|
|
4
4
|
import Title from '../title/Title';
|
|
@@ -12,7 +12,7 @@ jest.useFakeTimers();
|
|
|
12
12
|
jest.mock(
|
|
13
13
|
'../dimmer',
|
|
14
14
|
() =>
|
|
15
|
-
function ({ open, children }) {
|
|
15
|
+
function Dimmer({ open, children }) {
|
|
16
16
|
return open ? <div className="dimmer">{children}</div> : null;
|
|
17
17
|
},
|
|
18
18
|
);
|
|
@@ -20,7 +20,7 @@ jest.mock(
|
|
|
20
20
|
jest.mock(
|
|
21
21
|
'../slidingPanel',
|
|
22
22
|
() =>
|
|
23
|
-
function ({ open, children }) {
|
|
23
|
+
function SlidingPanel({ open, children }) {
|
|
24
24
|
return open ? <div className="sliding-panel">{children}</div> : null;
|
|
25
25
|
},
|
|
26
26
|
);
|
|
@@ -29,10 +29,10 @@ const defaultLocale = 'en-GB';
|
|
|
29
29
|
|
|
30
30
|
jest.mock('react-intl', () => ({
|
|
31
31
|
injectIntl: (Component) =>
|
|
32
|
-
function (props) {
|
|
32
|
+
function InjectedComponent(props) {
|
|
33
33
|
return <Component {...props} intl={{ locale: defaultLocale }} />;
|
|
34
34
|
},
|
|
35
|
-
useIntl: () => ({ locale: defaultLocale, formatMessage: (id) =>
|
|
35
|
+
useIntl: () => ({ locale: defaultLocale, formatMessage: (id) => String(id) }),
|
|
36
36
|
defineMessages: (translations) => translations,
|
|
37
37
|
}));
|
|
38
38
|
|
|
@@ -48,11 +48,12 @@ describe('Drawer', () => {
|
|
|
48
48
|
};
|
|
49
49
|
|
|
50
50
|
beforeEach(() => {
|
|
51
|
-
component =
|
|
51
|
+
component = mount(<Drawer {...props} />);
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
afterEach(() => {
|
|
55
55
|
jest.clearAllMocks();
|
|
56
|
+
component.unmount();
|
|
56
57
|
});
|
|
57
58
|
|
|
58
59
|
it('renders drawer header if title is provided', () => {
|
|
@@ -79,4 +80,22 @@ describe('Drawer', () => {
|
|
|
79
80
|
component.setProps({ footerContent: 'SomeContent' });
|
|
80
81
|
expect(component.find('.np-drawer-footer')).toHaveLength(1);
|
|
81
82
|
});
|
|
83
|
+
|
|
84
|
+
it('passes onUnmount to Dimmer onExited prop', () => {
|
|
85
|
+
const onUnmount = jest.fn();
|
|
86
|
+
component.setProps({ onUnmount });
|
|
87
|
+
component.setProps({ open: true });
|
|
88
|
+
expect(component.find('Dimmer').prop('onExited')).toBe(onUnmount);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('calls onUnmount when the component unmounts', () => {
|
|
92
|
+
const onUnmount = jest.fn();
|
|
93
|
+
component.setProps({ onUnmount });
|
|
94
|
+
component.setProps({ open: true });
|
|
95
|
+
expect(onUnmount).not.toHaveBeenCalled();
|
|
96
|
+
jest.runAllTimers();
|
|
97
|
+
component.setProps({ open: false });
|
|
98
|
+
component.find('Dimmer').prop('onExited')();
|
|
99
|
+
expect(onUnmount).toHaveBeenCalledTimes(1);
|
|
100
|
+
});
|
|
82
101
|
});
|
package/src/drawer/Drawer.tsx
CHANGED
|
@@ -24,6 +24,7 @@ export type DrawerProps = {
|
|
|
24
24
|
position?: `${Position.LEFT | Position.RIGHT | Position.BOTTOM}`;
|
|
25
25
|
/** The action to perform on close click. */
|
|
26
26
|
onClose?: (event: KeyboardEvent | React.MouseEvent) => void;
|
|
27
|
+
onUnmount?: () => void;
|
|
27
28
|
} & Pick<HTMLAttributes<HTMLDivElement>, 'role' | 'aria-labelledby'>;
|
|
28
29
|
|
|
29
30
|
export default function Drawer({
|
|
@@ -32,6 +33,7 @@ export default function Drawer({
|
|
|
32
33
|
footerContent,
|
|
33
34
|
headerTitle,
|
|
34
35
|
onClose,
|
|
36
|
+
onUnmount,
|
|
35
37
|
open = false,
|
|
36
38
|
position = 'right',
|
|
37
39
|
role = 'dialog',
|
|
@@ -48,7 +50,7 @@ export default function Drawer({
|
|
|
48
50
|
const overlayId = useContext(OverlayIdContext);
|
|
49
51
|
|
|
50
52
|
return (
|
|
51
|
-
<Dimmer open={open} onClose={onClose}>
|
|
53
|
+
<Dimmer open={open} onClose={onClose} onExited={onUnmount}>
|
|
52
54
|
<SlidingPanel open={open} position={isMobile ? Position.BOTTOM : position}>
|
|
53
55
|
<div
|
|
54
56
|
id={overlayId}
|
package/src/modal/Modal.spec.js
CHANGED
|
@@ -16,7 +16,7 @@ jest.mock('react-intl', () => ({
|
|
|
16
16
|
function (props) {
|
|
17
17
|
return <Component {...props} intl={{ locale: defaultLocale }} />;
|
|
18
18
|
},
|
|
19
|
-
useIntl: () => ({ locale: defaultLocale, formatMessage: (id) =>
|
|
19
|
+
useIntl: () => ({ locale: defaultLocale, formatMessage: (id) => String(id) }),
|
|
20
20
|
defineMessages: (translations) => translations,
|
|
21
21
|
}));
|
|
22
22
|
|
|
@@ -161,6 +161,24 @@ describe('Modal', () => {
|
|
|
161
161
|
expect(onClose).toHaveBeenCalledTimes(1);
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
+
it('passes onUnmount to Dimmer onExited prop', () => {
|
|
165
|
+
const onUnmount = jest.fn();
|
|
166
|
+
component.setProps({ onUnmount });
|
|
167
|
+
component.setProps({ open: true });
|
|
168
|
+
expect(component.find('Dimmer').prop('onExited')).toBe(onUnmount);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('calls onUnmount when the component unmounts', () => {
|
|
172
|
+
const onUnmount = jest.fn();
|
|
173
|
+
component.setProps({ onUnmount });
|
|
174
|
+
component.setProps({ open: true });
|
|
175
|
+
expect(onUnmount).not.toHaveBeenCalled();
|
|
176
|
+
jest.runAllTimers();
|
|
177
|
+
component.setProps({ open: false });
|
|
178
|
+
component.find('Dimmer').prop('onExited')();
|
|
179
|
+
expect(onUnmount).toHaveBeenCalledTimes(1);
|
|
180
|
+
});
|
|
181
|
+
|
|
164
182
|
const clickCloseButton = () => {
|
|
165
183
|
component.find('.close').simulate('click');
|
|
166
184
|
};
|
package/src/modal/Modal.tsx
CHANGED
|
@@ -32,6 +32,7 @@ export type ModalProps = CommonProps & {
|
|
|
32
32
|
footer?: ReactNode;
|
|
33
33
|
size?: SizeSmall | SizeMedium | SizeLarge | SizeExtraLarge;
|
|
34
34
|
onClose: () => void;
|
|
35
|
+
onUnmount?: () => void;
|
|
35
36
|
open: boolean;
|
|
36
37
|
scroll?: ScrollContent | ScrollViewport;
|
|
37
38
|
position?: PositionTop | PositionCenter;
|
|
@@ -43,6 +44,7 @@ const Modal = ({
|
|
|
43
44
|
body,
|
|
44
45
|
footer = null,
|
|
45
46
|
onClose,
|
|
47
|
+
onUnmount,
|
|
46
48
|
className,
|
|
47
49
|
open,
|
|
48
50
|
size = Size.MEDIUM,
|
|
@@ -71,6 +73,7 @@ const Modal = ({
|
|
|
71
73
|
footerContent={footer}
|
|
72
74
|
position={Position.BOTTOM}
|
|
73
75
|
onClose={onClose}
|
|
76
|
+
onUnmount={onUnmount}
|
|
74
77
|
>
|
|
75
78
|
{body}
|
|
76
79
|
</Drawer>
|
|
@@ -81,6 +84,7 @@ const Modal = ({
|
|
|
81
84
|
contentPosition={position}
|
|
82
85
|
disableClickToClose={disableDimmerClickToClose}
|
|
83
86
|
onClose={onClose}
|
|
87
|
+
onExited={onUnmount}
|
|
84
88
|
>
|
|
85
89
|
<CSSTransition
|
|
86
90
|
nodeRef={contentReference}
|
|
@@ -1,17 +1,31 @@
|
|
|
1
|
-
import { within } from '@testing-library/react';
|
|
1
|
+
import { Matcher, within } from '@testing-library/react';
|
|
2
2
|
import { userEvent } from '@testing-library/user-event';
|
|
3
3
|
import { act } from 'react';
|
|
4
4
|
|
|
5
5
|
import { Status } from '../common';
|
|
6
6
|
import { Field } from '../field/Field';
|
|
7
|
-
import { mockMatchMedia, render, screen, waitFor
|
|
7
|
+
import { mockMatchMedia, render, screen, waitFor } from '../test-utils';
|
|
8
8
|
|
|
9
9
|
import UploadInput, { UploadInputProps } from './UploadInput';
|
|
10
10
|
import { TEST_IDS as UPLOAD_BUTTON_TEST_IDS } from './uploadButton/UploadButton';
|
|
11
|
-
import { TEST_IDS as UPLOAD_ITEM_TEST_IDS } from './uploadItem/UploadItem';
|
|
12
11
|
|
|
13
12
|
const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTimeAsync });
|
|
14
13
|
|
|
14
|
+
const deleteFileAndWaitForFocus = async (fileToDeleteTestId: Matcher, nextFocusTestId: Matcher) => {
|
|
15
|
+
const fileToDelete = screen.getByTestId(fileToDeleteTestId);
|
|
16
|
+
|
|
17
|
+
await user.click(within(fileToDelete).getByLabelText('Remove file', { exact: false }));
|
|
18
|
+
|
|
19
|
+
const removeButton = screen.queryByText('Remove');
|
|
20
|
+
if (removeButton) {
|
|
21
|
+
await user.click(removeButton);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
await waitFor(() => {
|
|
25
|
+
expect(screen.getByTestId(nextFocusTestId)).toHaveFocus();
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
|
|
15
29
|
mockMatchMedia();
|
|
16
30
|
|
|
17
31
|
describe('UploadInput', () => {
|
|
@@ -139,15 +153,21 @@ describe('UploadInput', () => {
|
|
|
139
153
|
onFilesChange,
|
|
140
154
|
});
|
|
141
155
|
|
|
142
|
-
const fileToDelete = screen.
|
|
143
|
-
within(fileToDelete).getByLabelText('Remove file', { exact: false }).click();
|
|
156
|
+
const fileToDelete = screen.getByTestId('1-uploadItem');
|
|
144
157
|
await act(async () => {
|
|
158
|
+
within(fileToDelete).getByLabelText('Remove file', { exact: false }).click();
|
|
145
159
|
await jest.runOnlyPendingTimersAsync();
|
|
146
160
|
});
|
|
147
161
|
|
|
148
|
-
|
|
162
|
+
await act(async () => {
|
|
163
|
+
screen.getByText('Remove').click();
|
|
164
|
+
await jest.runOnlyPendingTimersAsync();
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
await waitFor(() => {
|
|
168
|
+
expect(screen.queryByTestId('1-uploadItem')).not.toBeInTheDocument();
|
|
169
|
+
});
|
|
149
170
|
|
|
150
|
-
await waitForElementToBeRemoved(fileToDelete);
|
|
151
171
|
expect(props.onDeleteFile).toHaveBeenCalledWith(files[0].id);
|
|
152
172
|
|
|
153
173
|
expect(onFilesChange).toHaveBeenCalledTimes(2);
|
|
@@ -190,9 +210,9 @@ describe('UploadInput', () => {
|
|
|
190
210
|
onFilesChange,
|
|
191
211
|
});
|
|
192
212
|
|
|
193
|
-
const fileToDelete = screen.
|
|
194
|
-
within(fileToDelete).getByLabelText('Remove file', { exact: false }).click();
|
|
213
|
+
const fileToDelete = screen.getByTestId('1-uploadItem');
|
|
195
214
|
await act(async () => {
|
|
215
|
+
within(fileToDelete).getByLabelText('Remove file', { exact: false }).click();
|
|
196
216
|
await jest.runOnlyPendingTimersAsync();
|
|
197
217
|
});
|
|
198
218
|
|
|
@@ -212,6 +232,98 @@ describe('UploadInput', () => {
|
|
|
212
232
|
|
|
213
233
|
expect(screen.queryByLabelText('Remove file ', { exact: false })).not.toBeInTheDocument();
|
|
214
234
|
});
|
|
235
|
+
|
|
236
|
+
it('should focus the next item after a file is deleted', async () => {
|
|
237
|
+
const files = [
|
|
238
|
+
{ id: 1, filename: 'Sales-2024-invoice.pdf', status: Status.DONE },
|
|
239
|
+
{ id: 2, filename: 'CoWork-0317-invoice.pdf', status: Status.DONE },
|
|
240
|
+
{ id: 3, filename: 'purchase-receipt.pdf', status: Status.DONE },
|
|
241
|
+
];
|
|
242
|
+
|
|
243
|
+
renderComponent({ ...props, files, multiple: true, onFilesChange });
|
|
244
|
+
|
|
245
|
+
// Delete the first file and expect focus to move to the next one
|
|
246
|
+
await deleteFileAndWaitForFocus('1-uploadItem', '2-action');
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('should focus the previous item after the last file is deleted', async () => {
|
|
250
|
+
const files = [
|
|
251
|
+
{
|
|
252
|
+
id: 1,
|
|
253
|
+
filename: 'Sales-2024-invoice.pdf',
|
|
254
|
+
status: Status.DONE,
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
id: 2,
|
|
258
|
+
filename: 'CoWork-0317-invoice.pdf',
|
|
259
|
+
status: Status.DONE,
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
id: 3,
|
|
263
|
+
filename: 'purchase-receipt.pdf',
|
|
264
|
+
status: Status.DONE,
|
|
265
|
+
},
|
|
266
|
+
];
|
|
267
|
+
|
|
268
|
+
renderComponent({
|
|
269
|
+
...props,
|
|
270
|
+
files,
|
|
271
|
+
multiple: true,
|
|
272
|
+
onFilesChange,
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
await deleteFileAndWaitForFocus('3-uploadItem', '2-action');
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('should focus the upload input after the only file is deleted', async () => {
|
|
279
|
+
const singleFile = [
|
|
280
|
+
{
|
|
281
|
+
id: 3,
|
|
282
|
+
filename: 'purchase-receipt.pdf',
|
|
283
|
+
status: Status.DONE,
|
|
284
|
+
},
|
|
285
|
+
];
|
|
286
|
+
|
|
287
|
+
renderComponent({
|
|
288
|
+
...props,
|
|
289
|
+
files: singleFile,
|
|
290
|
+
multiple: true,
|
|
291
|
+
onFilesChange,
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
await deleteFileAndWaitForFocus('3-uploadItem', 'uploadInput');
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it('should focus on the next item or upload input after each file is deleted in sequence', async () => {
|
|
298
|
+
const filesWithFailed = [
|
|
299
|
+
{
|
|
300
|
+
id: 1,
|
|
301
|
+
filename: 'Sales-2024-invoice.pdf',
|
|
302
|
+
status: Status.DONE,
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
id: 2,
|
|
306
|
+
filename: 'CoWork-0317-invoice.pdf',
|
|
307
|
+
status: Status.FAILED,
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
id: 3,
|
|
311
|
+
filename: 'purchase-receipt.pdf',
|
|
312
|
+
status: Status.DONE,
|
|
313
|
+
},
|
|
314
|
+
];
|
|
315
|
+
|
|
316
|
+
renderComponent({
|
|
317
|
+
...props,
|
|
318
|
+
files: filesWithFailed,
|
|
319
|
+
multiple: true,
|
|
320
|
+
onFilesChange,
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
await deleteFileAndWaitForFocus('3-uploadItem', '2-action');
|
|
324
|
+
await deleteFileAndWaitForFocus('1-uploadItem', '2-action');
|
|
325
|
+
await deleteFileAndWaitForFocus('2-uploadItem', 'uploadInput');
|
|
326
|
+
});
|
|
215
327
|
});
|
|
216
328
|
|
|
217
329
|
describe('Max File Upload limit', () => {
|