Update dependency react-dropzone to v14 (#49243)

* Update dependency react-dropzone to v14

* Changes needed for react-dropzone v13

* feat(FileDropzone): update props to be backward compatible

* refactor(filedropzone): clean up component story

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com>
Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
This commit is contained in:
renovate[bot]
2022-06-21 11:10:00 +02:00
committed by GitHub
co-authored by Renovate Bot Ashley Harrison Levente Balogh Jack Westbrook
parent 62531715b3
commit a0ffb9093c
6 changed files with 81 additions and 32 deletions
+1 -1
View File
@@ -73,7 +73,7 @@
"react-colorful": "5.5.1",
"react-custom-scrollbars-2": "4.5.0",
"react-dom": "17.0.2",
"react-dropzone": "12.0.4",
"react-dropzone": "14.2.1",
"react-highlight-words": "0.18.0",
"react-hook-form": "7.5.3",
"react-inlinesvg": "3.0.0",
@@ -16,15 +16,18 @@ export default {
page: mdx,
},
},
argTypes: {
onLoad: { action: 'onLoad' },
},
} as Meta;
export const Basic: Story<FileDropzoneProps> = (args) => {
return <FileDropzone {...args} />;
const Template: Story<FileDropzoneProps> = (args) => <FileDropzone {...args} />;
export const Basic = Template.bind({});
export const WithCustomFileList = Template.bind({});
WithCustomFileList.args = {
fileListRenderer: (file) => <div>Custom rendered item {file.file.name}</div>,
};
export const WithCustomFileList: Story<FileDropzoneProps> = () => {
return <FileDropzone fileListRenderer={(file) => <div>Custom rendered item {file.file.name}</div>} />;
export const OnlyAcceptingCertainFiles = Template.bind({});
OnlyAcceptingCertainFiles.args = {
options: { accept: { 'application/json': ['.json'] } },
};
@@ -27,18 +27,24 @@ describe('The FileDropzone component', () => {
expect(screen.getByText('Upload file')).toBeInTheDocument();
});
it('should show accepted file type when passed in the options as a string', () => {
it('should show the accepted file type(s) when passed in as a string', () => {
render(<FileDropzone options={{ accept: '.json' }} />);
expect(screen.getByText('Accepted file type: .json')).toBeInTheDocument();
});
it('should show accepted file types when passed in the options as a string array', () => {
it('should show the accepted file type(s) when passed in as a array of strings', () => {
render(<FileDropzone options={{ accept: ['.json', '.txt'] }} />);
expect(screen.getByText('Accepted file types: .json, .txt')).toBeInTheDocument();
});
it('should show the accepted file type(s) when passed in as an `Accept` object', () => {
render(<FileDropzone options={{ accept: { 'text/*': ['.json', '.txt'] } }} />);
expect(screen.getByText('Accepted file types: .json, .txt')).toBeInTheDocument();
});
it('should handle file removal from the list', async () => {
render(<FileDropzone />);
@@ -1,7 +1,7 @@
import { css, cx } from '@emotion/css';
import { uniqueId } from 'lodash';
import { uniqueId, isString } from 'lodash';
import React, { ReactNode, useCallback, useState } from 'react';
import { DropEvent, DropzoneOptions, FileRejection, useDropzone } from 'react-dropzone';
import { DropEvent, DropzoneOptions, FileRejection, useDropzone, Accept } from 'react-dropzone';
import { GrafanaTheme2 } from '@grafana/data';
@@ -10,6 +10,11 @@ import { Icon } from '../Icon/Icon';
import { FileListItem } from './FileListItem';
type BackwardsCompatibleDropzoneOptions = Omit<DropzoneOptions, 'accept'> & {
// For backward compatibility we are still allowing the old `string | string[]` format for adding accepted file types (format changed in v13.0.0)
accept?: string | string[] | Accept;
};
export interface FileDropzoneProps {
/**
* Use the children property to have custom dropzone view.
@@ -25,7 +30,7 @@ export interface FileDropzoneProps {
* maxFiles: 0,
* }
*/
options?: DropzoneOptions;
options?: BackwardsCompatibleDropzoneOptions;
/**
* Use this to change the FileReader's read.
*/
@@ -145,6 +150,7 @@ export function FileDropzone({ options, children, readAs, onLoad, fileListRender
...options,
useFsAccessApi: false,
onDrop,
accept: transformAcceptToNewFormat(options?.accept),
});
const theme = useTheme2();
const styles = getStyles(theme, isDragActive);
@@ -162,13 +168,41 @@ export function FileDropzone({ options, children, readAs, onLoad, fileListRender
{children ?? <FileDropzoneDefaultChildren primaryText={getPrimaryText(files, options)} />}
</div>
{options?.accept && (
<small className={cx(styles.small, styles.acceptMargin)}>{getAcceptedFileTypeText(options)}</small>
<small className={cx(styles.small, styles.acceptMargin)}>{getAcceptedFileTypeText(options.accept)}</small>
)}
{fileList}
</div>
);
}
export function getMimeTypeByExtension(ext: string) {
if (['txt', 'json', 'csv', 'xls', 'yml'].some((e) => ext.match(e))) {
return 'text/plain';
}
return 'application/octet-stream';
}
export function transformAcceptToNewFormat(accept?: string | string[] | Accept): Accept | undefined {
if (isString(accept)) {
return {
[getMimeTypeByExtension(accept)]: [accept],
};
}
if (Array.isArray(accept)) {
return accept.reduce((prev: Record<string, string[]>, current) => {
const mime = getMimeTypeByExtension(current);
prev[mime] = prev[mime] ? [...prev[mime], current] : [current];
return prev;
}, {});
}
return accept;
}
export function FileDropzoneDefaultChildren({
primaryText = 'Upload file',
secondaryText = 'Drag and drop here or browse',
@@ -184,19 +218,25 @@ export function FileDropzoneDefaultChildren({
</div>
);
}
function getPrimaryText(files: DropzoneFile[], options?: DropzoneOptions) {
function getPrimaryText(files: DropzoneFile[], options?: BackwardsCompatibleDropzoneOptions) {
if (options?.multiple === undefined || options?.multiple) {
return 'Upload file';
}
return files.length ? 'Replace file' : 'Upload file';
}
function getAcceptedFileTypeText(options: DropzoneOptions) {
if (Array.isArray(options.accept)) {
return `Accepted file types: ${options.accept.join(', ')}`;
function getAcceptedFileTypeText(accept: string | string[] | Accept) {
if (isString(accept)) {
return `Accepted file type: ${accept}`;
}
return `Accepted file type: ${options.accept}`;
if (Array.isArray(accept)) {
return `Accepted file types: ${accept.join(', ')}`;
}
// react-dropzone has updated the type of the "accept" parameter since v13.0.0:
// https://github.com/react-dropzone/react-dropzone/blob/master/src/index.js#L95
return `Accepted file types: ${Object.values(accept).flat().join(', ')}`;
}
function mapToCustomFile(file: File): DropzoneFile {