UNPKG

@rjsf/utils

Version:
120 lines 4.36 kB
'use client'; import { useCallback, useMemo } from 'react'; import dataURItoBlob from './dataURItoBlob.js'; /** Updated the given `dataUrl` to add the `name` to it * * @param dataURL - The url description string * @param name - The name of the file to add to the dataUrl * @returns - The `dataUrl` updated to include the name */ function addNameToDataURL(dataURL, name) { return dataURL.replace(';base64', `;name=${encodeURIComponent(name)};base64`); } /** Returns a promise that will read the file from the browser and return it as the result of the promise. * * @param file - The `File` information to read * @returns - A promise that resolves to the read file. */ function processFile(file) { const { name, size, type } = file; return new Promise((resolve, reject) => { const reader = new window.FileReader(); reader.onerror = reject; reader.onload = (event) => { var _a; if (typeof ((_a = event.target) === null || _a === void 0 ? void 0 : _a.result) === 'string') { resolve({ dataURL: addNameToDataURL(event.target.result, name), name, size, type, }); } else { resolve({ dataURL: null, name, size, type, }); } }; reader.readAsDataURL(file); }); } /** Reads a list of files from the browser, returning the results of the promises of each individual file read. * * @param files - The list of files to read * @returns - The list of read files */ function processFiles(files) { return Promise.all(Array.from(files).map(processFile)); } /** Extracts the file information from the data URLs * * @param dataURLs - The information about the files * @returns - The list of `FileInfoType` objects extracted from the data urls */ function extractFileInfo(dataURLs) { return dataURLs.reduce((acc, dataURL) => { if (!dataURL) { return acc; } try { const { blob, name } = dataURItoBlob(dataURL); return [ ...acc, { dataURL, name: name, size: blob.size, type: blob.type, }, ]; } catch (_a) { // Invalid dataURI, so just ignore it. return acc; } }, []); } /** Hook which encapsulates the logic needed to read and convert a `value` of `File` or `File[]` into the * `filesInfo: FileInfoType[]` and the two callback implementations needed to change the list or to remove a * `File` from the list. To be used by theme specific `FileWidget` implementations. * * @param value - The current value of the `FileWidget` * @param onChange - The onChange handler for the `FileWidget` * @param [multiple=false] - Flag indicating whether the control supports multiple selections * @returns - The `UseFileWidgetPropsResult` to be used within a `FileWidget` implementation */ export default function useFileWidgetProps(value, onChange, multiple = false) { const values = useMemo(() => { if (multiple && value) { return Array.isArray(value) ? value : [value]; } return []; }, [value, multiple]); const filesInfo = useMemo(() => (Array.isArray(value) ? extractFileInfo(value) : extractFileInfo([value || ''])), [value]); const handleChange = useCallback((files) => { processFiles(files).then((filesInfoEvent) => { const newValue = filesInfoEvent.map((fileInfo) => fileInfo.dataURL || null); if (multiple) { onChange(values.concat(...newValue)); } else { onChange(newValue[0]); } }); }, [values, multiple, onChange]); const handleRemove = useCallback((index) => { if (multiple) { const newValue = values.filter((_, i) => i !== index); onChange(newValue); } else { onChange(undefined); } }, [values, multiple, onChange]); return { filesInfo, handleChange, handleRemove }; } //# sourceMappingURL=useFileWidgetProps.js.map