package.src.components.MultipleFileUpload.MultipleFileUploadStatusItem.tsx Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of react-core Show documentation
Show all versions of react-core Show documentation
This library provides a set of common React components for use with the PatternFly reference implementation.
The newest version!
import * as React from 'react';
import styles from '@patternfly/react-styles/css/components/MultipleFileUpload/multiple-file-upload';
import { css } from '@patternfly/react-styles';
import { Progress } from '../Progress';
import { Button } from '../Button';
import FileIcon from '@patternfly/react-icons/dist/esm/icons/file-icon';
import TimesCircleIcon from '@patternfly/react-icons/dist/esm/icons/times-circle-icon';
/** Automatically reads an uploaded file to render a visual representation of it, including
* its name, size, and read status. This sub-component also allows custom reading of files
* via various callbacks which will override the automatic reading behavior.
*/
export interface MultipleFileUploadStatusItemProps extends React.HTMLProps {
/** Class to add to outer div */
className?: string;
/** Adds accessibility text to the status item deletion button */
buttonAriaLabel?: string;
/** The file object being represented by the status item */
file?: File;
/** A callback for when a selected file starts loading */
onReadStarted?: (fileHandle: File) => void;
/** A callback for when a selected file finishes loading */
onReadFinished?: (fileHandle: File) => void;
/** A callback for when the FileReader successfully reads the file */
onReadSuccess?: (data: string, file: File) => void;
/** A callback for when the FileReader API fails */
onReadFail?: (error: DOMException, onReadFail: File) => void;
/** Clear button was clicked */
onClearClick?: React.MouseEventHandler;
// Props to bypass built in behavior
/** A callback to process file reading in a custom way */
customFileHandler?: (file: File) => void;
/** A custom icon to show in place of the generic file icon */
fileIcon?: React.ReactNode;
/** A custom name to display for the file rather than using built in functionality to auto-fill it */
fileName?: string;
/** A custom file size to display for the file rather than using built in functionality to auto-fill it */
fileSize?: number;
/** A custom value to display for the progress component rather than using built in functionality to auto-fill it */
progressValue?: number;
/** A custom variant to apply to the progress component rather than using built in functionality to auto-fill it */
progressVariant?: 'danger' | 'success' | 'warning';
// Props passed through to the progress component
/** Adds accessible text to the progress bar. Required when title not used and there is not any label associated with the progress bar */
progressAriaLabel?: string;
/** Associates the progress bar with it's label for accessibility purposes. Required when title not used */
progressAriaLabelledBy?: string;
/** Modifies the text announced by assistive technologies when the progress bar updates. */
progressAriaLiveMessage?: string | ((loadPercentage: number) => string);
/** Unique identifier for progress. Generated if not specified. */
progressId?: string;
/** Additional content related to the status item. */
progressHelperText?: React.ReactNode;
}
export const MultipleFileUploadStatusItem: React.FunctionComponent = ({
className,
file,
fileIcon,
onReadStarted = () => {},
onReadFinished = () => {},
onReadSuccess = () => {},
onReadFail = () => {},
onClearClick = () => {},
customFileHandler,
fileName,
fileSize,
progressValue,
progressVariant,
progressAriaLabel,
progressAriaLabelledBy,
progressId,
progressAriaLiveMessage,
buttonAriaLabel = 'Remove from list',
progressHelperText,
...props
}: MultipleFileUploadStatusItemProps) => {
const [loadPercentage, setLoadPercentage] = React.useState(0);
const [loadResult, setLoadResult] = React.useState();
function readFile(file: File) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
reader.onprogress = (data) => {
if (data.lengthComputable) {
setLoadPercentage((data.loaded / data.total) * 100);
}
};
reader.readAsDataURL(file);
});
}
React.useEffect(() => {
if (customFileHandler) {
customFileHandler(file);
} else {
onReadStarted(file);
readFile(file)
.then((data) => {
setLoadResult('success');
setLoadPercentage(100);
onReadFinished(file);
onReadSuccess(data as string, file);
})
.catch((error: DOMException) => {
onReadFinished(file);
onReadFail(error, file);
setLoadResult('danger');
});
}
}, []);
const getHumanReadableFileSize = (size: number) => {
const prefixes = ['', 'K', 'M', 'G', 'T'];
let prefixUnit = 0;
while (size >= 1000) {
prefixUnit += 1;
size = size / 1000;
}
if (prefixUnit >= prefixes.length) {
return 'File size too large';
}
return `${Math.round(size)}${prefixes[prefixUnit]}B`;
};
const value = progressValue || loadPercentage;
const variant = progressVariant || loadResult;
const title = (
{fileName || file?.name || ''}
{fileSize || getHumanReadableFileSize(file?.size || 0)}
);
return (
{fileIcon || }
{progressAriaLiveMessage &&
typeof progressAriaLiveMessage === 'function' &&
progressAriaLiveMessage(+loadPercentage.toFixed(2))}
{progressAriaLiveMessage && typeof progressAriaLiveMessage === 'string' && progressAriaLiveMessage}
{!progressAriaLiveMessage && `Progress value is ${progressValue || Math.floor(loadPercentage)}%.`}
);
};
MultipleFileUploadStatusItem.displayName = 'MultipleFileUploadStatusItem';