Select Git revision
test_configuration.py
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
FileInput.tsx 1.60 KiB
import {
ChangeEvent,
Dispatch,
SetStateAction,
useEffect,
useRef,
InputHTMLAttributes,
useId,
} from "react";
import Typography from "src/components/Typography";
interface Props extends InputHTMLAttributes<HTMLInputElement> {
label: string;
files: File[];
onFilesChange: Dispatch<SetStateAction<File[]>>;
}
/**
* Controlled File Input component
* @param props
* @constructor
*/
const FileInput = (props: Props) => {
const inputRef = useRef<HTMLInputElement>(null);
const inputId = useId();
const { files, onFilesChange, label, ...rest } = props;
/**
* Workaround for not being able to set the value directly on <input type="file">
* Using the https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer
* API to construct a valid file list; not available in IE!
*/
useEffect(() => {
const dataTransfer = new DataTransfer();
files.forEach((file: File) => dataTransfer.items.add(file));
if (inputRef.current) inputRef.current.files = dataTransfer.files;
}, [files]);
const handleChange = (evt: ChangeEvent<HTMLInputElement>) => {
const fileList = evt.currentTarget.files;
if (!fileList) {
onFilesChange([]);
} else {
onFilesChange(Array.from(fileList));
}
};
return (
<div className="flex flex-col">
<label htmlFor={inputId} className="-mt-3.5">
<Typography text={label} variant="paragraph" />
</label>
<input
className="mt-3"
id={inputId}
ref={inputRef}
type="file"
onChange={handleChange}
{...rest}
/>
</div>
);
};
export default FileInput;