diff --git a/.changeset/eight-elephants-grin.md b/.changeset/eight-elephants-grin.md new file mode 100644 index 00000000000..39df29e9593 --- /dev/null +++ b/.changeset/eight-elephants-grin.md @@ -0,0 +1,5 @@ +--- +"@razorpay/blade": patch +--- + +feat(FileUpload): add `onReupload` prop to use in case of error state diff --git a/packages/blade/src/components/FileUpload/FileUpload.web.tsx b/packages/blade/src/components/FileUpload/FileUpload.web.tsx index 8e1d96d711c..d76eb2e3c87 100644 --- a/packages/blade/src/components/FileUpload/FileUpload.web.tsx +++ b/packages/blade/src/components/FileUpload/FileUpload.web.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback, useMemo, forwardRef } from 'react'; +import { useState, useCallback, useMemo, useRef, forwardRef } from 'react'; import type { FileUploadProps, BladeFile, BladeFileList } from './types'; import { StyledFileUploadWrapper } from './StyledFileUploadWrapper'; import { @@ -24,6 +24,7 @@ import type { BladeElementRef } from '~utils/types'; import { getHintType } from '~components/Input/BaseInput/BaseInput'; import { makeAccessible } from '~utils/makeAccessible'; import { formHintLeftLabelMarginLeft } from '~components/Input/BaseInput/baseInputTokens'; +import { useMergeRefs } from '~utils/useMergeRefs'; const _FileUpload: React.ForwardRefRenderFunction = ( { @@ -33,6 +34,7 @@ const _FileUpload: React.ForwardRefRenderFunction { + const inputRef = useRef(null); + const mergedRef = useMergeRefs(ref, inputRef); const { platform } = useTheme(); const [selectedFiles, setSelectedFiles] = useState(fileList ?? []); const [errorMessage, setErrorMessage] = useState(errorText); @@ -262,7 +266,7 @@ const _FileUpload: React.ForwardRefRenderFunction setIsActive(false), ...accessibilityProps, }} - ref={ref} + ref={mergedRef} /> { + const newFiles = selectedFiles.filter(({ id }) => id !== selectedFiles[0].id); + setSelectedFiles(newFiles); + inputRef.current?.click(); + + // TODO - Remove this in the next major release + // Fallback to onRemove if onReupload isn't provided to avoid breaking changes in the API + if (onReupload) { + onReupload({ file: selectedFiles[0] }); + } else { + onRemove?.({ file: selectedFiles[0] }); + } + setIsActive(false); + }} onDismiss={() => { const newFiles = selectedFiles.filter(({ id }) => id !== selectedFiles[0].id); setSelectedFiles(newFiles); @@ -353,6 +371,19 @@ const _FileUpload: React.ForwardRefRenderFunction { + const newFiles = selectedFiles.filter(({ id }) => id !== file.id); + setSelectedFiles(newFiles); + inputRef.current?.click(); + // TODO - Remove this in the next major release + // Fallback to onRemove if onReupload isn't provided to avoid breaking changes in the API + if (onReupload) { + onReupload({ file: selectedFiles[0] }); + } else { + onRemove?.({ file: selectedFiles[0] }); + } + setIsActive(false); + }} onDismiss={() => { const newFiles = selectedFiles.filter(({ id }) => id !== file.id); setSelectedFiles(newFiles); diff --git a/packages/blade/src/components/FileUpload/FileUploadItem.tsx b/packages/blade/src/components/FileUpload/FileUploadItem.tsx index e6d0dda0916..b3854a47728 100644 --- a/packages/blade/src/components/FileUpload/FileUploadItem.tsx +++ b/packages/blade/src/components/FileUpload/FileUploadItem.tsx @@ -2,19 +2,21 @@ import { memo } from 'react'; import { StyledFileUploadItemWrapper } from './StyledFileUploadItemWrapper'; import type { FileUploadItemProps } from './types'; import { FileUploadItemIcon } from './FileUploadItemIcon'; -import { TrashIcon, EyeIcon, CloseIcon, CheckCircleIcon } from '~components/Icons'; +import { TrashIcon, EyeIcon, CloseIcon, CheckCircleIcon, RefreshIcon } from '~components/Icons'; import { BaseBox } from '~components/Box/BaseBox'; import { Text } from '~components/Typography'; import { Divider } from '~components/Divider'; import { IconButton } from '~components/Button/IconButton'; import { ProgressBar } from '~components/ProgressBar'; import isUndefined from '~utils/lodashButBetter/isUndefined'; +import { BaseLink } from '~components/Link/BaseLink'; const FileUploadItem = memo( ({ file, onPreview, onRemove, + onReupload, onDismiss, size: containerSize, }: FileUploadItemProps): React.ReactElement => { @@ -73,7 +75,7 @@ const FileUploadItem = memo( } ${isUploading && uploadPercent ? `(${uploadPercent}%)` : ''}`} - {status === 'error' || status === 'uploading' ? ( + {status === 'uploading' ? ( onDismiss?.({ file })} /> + ) : status === 'error' ? ( + + { + onReupload?.({ file }); + }} + > + Re-upload + + ) : ( {onPreview ? ( diff --git a/packages/blade/src/components/FileUpload/StyledFileUploadItemWrapper.tsx b/packages/blade/src/components/FileUpload/StyledFileUploadItemWrapper.tsx index 7008c064d6f..c4c5a4379d2 100644 --- a/packages/blade/src/components/FileUpload/StyledFileUploadItemWrapper.tsx +++ b/packages/blade/src/components/FileUpload/StyledFileUploadItemWrapper.tsx @@ -23,7 +23,7 @@ const StyledFileUploadItemWrapper = styled(BaseBox) void; + /** + * Callback function triggered when a file upload is retried + */ + onReupload?: ({ file }: { file: File }) => void; /** * Callback function triggered when a file upload is dismissed */ @@ -146,7 +150,7 @@ type FileUploadProps = (FileUploadPropsWithA11yLabel | FileUploadPropsWithLabel) type FileUploadItemProps = Pick< FileUploadProps, - 'onPreview' | 'onRemove' | 'onDismiss' | 'size' + 'onPreview' | 'onRemove' | 'onDismiss' | 'onReupload' | 'size' > & { file: BladeFile; };