diff --git a/playbook/app/pb_kits/playbook/pb_file_upload/_file_upload.tsx b/playbook/app/pb_kits/playbook/pb_file_upload/_file_upload.tsx index 72d3e55179..a181e8787f 100644 --- a/playbook/app/pb_kits/playbook/pb_file_upload/_file_upload.tsx +++ b/playbook/app/pb_kits/playbook/pb_file_upload/_file_upload.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useCallback, useRef } from 'react' -import { useDropzone, DropzoneInputProps, DropzoneRootProps } from 'react-dropzone' +import { useDropzone, DropzoneInputProps, DropzoneRootProps, FileRejection } from 'react-dropzone' import classnames from 'classnames' import { buildCss, buildDataProps, noop, buildHtmlProps } from '../utilities/props' @@ -9,8 +9,10 @@ import type { Callback } from '../types' import Body from '../pb_body/_body' import Card from '../pb_card/_card' +import { isEmpty } from '../utilities/object' + type FileUploadProps = { - accept?: string[], + accept?: Record, className?: string, customMessage?: string, dark?: boolean, @@ -19,7 +21,7 @@ type FileUploadProps = { acceptedFilesDescription?: string, maxSize?: number, onFilesAccepted: Callback, - onFilesRejected: (error: string, files: File[]) => void, + onFilesRejected: (error: string, files: readonly FileRejection[]) => void, } const getFormattedFileSize = (fileSize: number): string => { @@ -28,7 +30,7 @@ const getFormattedFileSize = (fileSize: number): string => { const FileUpload = (props: FileUploadProps): React.ReactElement => { const { - accept = null, + accept = {}, acceptedFilesDescription = '', className, customMessage, @@ -48,30 +50,37 @@ const FileUpload = (props: FileUploadProps): React.ReactElement => { getRootProps: () => DropzoneRootProps & any; getInputProps: () => DropzoneInputProps & any; isDragActive: boolean; - rejectedFiles: File[]; + fileRejections: readonly FileRejection[]; } - const { getRootProps, getInputProps, isDragActive, rejectedFiles }: DropZoneProps = useDropzone({ + const { getRootProps, getInputProps, isDragActive, fileRejections }: DropZoneProps = useDropzone({ accept, maxSize, onDrop, }) - const prevRejected = useRef(null); + const prevRejected = useRef(null); - const maxFileSizeText = `Max file size is ${getFormattedFileSize(maxSize)}.` + let maxFileSizeText = '' + if (maxSize !== undefined) { + maxFileSizeText = `Max file size is ${getFormattedFileSize(maxSize)}.` + } useEffect(() => { - if (rejectedFiles === prevRejected.current) return - const isFileTooLarge = maxSize && rejectedFiles.length > 0 && rejectedFiles[0].size > maxSize; + if (fileRejections === prevRejected.current) return + const isFileTooLarge = maxSize && fileRejections.length > 0 && fileRejections[0].file.size > maxSize; if (isFileTooLarge) { - onFilesRejected(`File size is too large! ${maxFileSizeText}`, rejectedFiles) + onFilesRejected(`File size is too large! ${maxFileSizeText}`, fileRejections) } - prevRejected.current = rejectedFiles - }, [maxFileSizeText, maxSize, onFilesRejected, rejectedFiles]) + prevRejected.current = fileRejections + }, [maxFileSizeText, maxSize, onFilesRejected, fileRejections]) const acceptedFileTypes = () => { - return accept.map((fileType) => { + if (!accept) { + return [] + } + + return Object.keys(accept).map((fileType) => { if (fileType.startsWith('image/')) { return fileType.replace('image/', ' ') } else { @@ -86,7 +95,7 @@ const FileUpload = (props: FileUploadProps): React.ReactElement => { const getDescription = () => { return customMessage ? customMessage - : `Choose a file or drag it here.${accept === null ? '' : ` The accepted file types are: ${acceptedFilesDescription || acceptedFileTypes()}.`}${maxSize ? ` ${maxFileSizeText}` : ''}`; + : `Choose a file or drag it here.${isEmpty(accept) ? '' : ` The accepted file types are: ${acceptedFilesDescription || acceptedFileTypes()}.`}${maxSize ? ` ${maxFileSizeText}` : ''}`; } return ( diff --git a/playbook/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_accept.jsx b/playbook/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_accept.jsx index 25d0568ad0..1e06264198 100644 --- a/playbook/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_accept.jsx +++ b/playbook/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_accept.jsx @@ -28,7 +28,9 @@ const FileUploadAccept = (props) => { {...props} /> diff --git a/playbook/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_custom_description.jsx b/playbook/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_custom_description.jsx index dbd91dd597..856baecf28 100644 --- a/playbook/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_custom_description.jsx +++ b/playbook/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_custom_description.jsx @@ -25,7 +25,10 @@ const FileUploadCustomDescription = (props) => { {...props} /> ( const RejectedFilesList = ({ files }) => ( {files.map((file) => ( - {`${file.name} (file too large)`} + {`${file.file.name} (file too large)`} ))} ) diff --git a/playbook/package.json b/playbook/package.json index 82f12ac7bf..ab29ec76af 100644 --- a/playbook/package.json +++ b/playbook/package.json @@ -80,7 +80,7 @@ "react": "^17.0.2", "react-animate-height": "^2.0.23", "react-dom": "^17.0.2", - "react-dropzone": "^10.2.2", + "react-dropzone": "^14.3.5", "react-highlight-words": "^0.20.0", "react-joyride": "^2.8.2", "react-modal": "^3.16.1", diff --git a/yarn.lock b/yarn.lock index 697638d6f8..25ce375090 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4543,10 +4543,10 @@ atob@^2.1.2: resolved "https://npm.powerapp.cloud/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -attr-accept@^2.0.0: - version "2.2.2" - resolved "https://npm.powerapp.cloud/attr-accept/-/attr-accept-2.2.2.tgz#646613809660110749e92f2c10833b70968d929b" - integrity sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg== +attr-accept@^2.2.4: + version "2.2.5" + resolved "https://npm.powerapp.cloud/attr-accept/-/attr-accept-2.2.5.tgz#d7061d958e6d4f97bf8665c68b75851a0713ab5e" + integrity sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ== autoprefixer@^10.4.13: version "10.4.19" @@ -6577,12 +6577,12 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -file-selector@^0.1.12: - version "0.1.19" - resolved "https://npm.powerapp.cloud/file-selector/-/file-selector-0.1.19.tgz#8ecc9d069a6f544f2e4a096b64a8052e70ec8abf" - integrity sha512-kCWw3+Aai8Uox+5tHCNgMFaUdgidxvMnLWO6fM5sZ0hA2wlHP5/DHGF0ECe84BiB95qdJbKNEJhWKVDvMN+JDQ== +file-selector@^2.1.0: + version "2.1.2" + resolved "https://npm.powerapp.cloud/file-selector/-/file-selector-2.1.2.tgz#fe7c7ee9e550952dfbc863d73b14dc740d7de8b4" + integrity sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig== dependencies: - tslib "^2.0.1" + tslib "^2.7.0" filemanager-webpack-plugin@4.0.0: version "4.0.0" @@ -10040,14 +10040,14 @@ react-dom@^17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" -react-dropzone@^10.2.2: - version "10.2.2" - resolved "https://npm.powerapp.cloud/react-dropzone/-/react-dropzone-10.2.2.tgz#67b4db7459589a42c3b891a82eaf9ade7650b815" - integrity sha512-U5EKckXVt6IrEyhMMsgmHQiWTGLudhajPPG77KFSvgsMqNEHSyGpqWvOMc5+DhEah/vH4E1n+J5weBNLd5VtyA== +react-dropzone@^14.3.5: + version "14.3.5" + resolved "https://npm.powerapp.cloud/react-dropzone/-/react-dropzone-14.3.5.tgz#1a8bd312c8a353ec78ef402842ccb3589c225add" + integrity sha512-9nDUaEEpqZLOz5v5SUcFA0CjM4vq8YbqO0WRls+EYT7+DvxUdzDPKNCPLqGfj3YL9MsniCLCD4RFA6M95V6KMQ== dependencies: - attr-accept "^2.0.0" - file-selector "^0.1.12" - prop-types "^15.7.2" + attr-accept "^2.2.4" + file-selector "^2.1.0" + prop-types "^15.8.1" react-fast-compare@^3.0.1: version "3.2.0" @@ -11526,6 +11526,11 @@ tslib@^2.6.2: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== +tslib@^2.7.0: + version "2.8.1" + resolved "https://npm.powerapp.cloud/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tsutils@^3.21.0: version "3.21.0" resolved "https://npm.powerapp.cloud/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"