UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

331 lines (330 loc) 12.6 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; exports.transformFiles = transformFiles; var _includes = _interopRequireDefault(require("core-js-pure/stable/instance/includes.js")); var _push = _interopRequireDefault(require("core-js-pure/stable/instance/push.js")); var _react = require("react"); var _clsx = require("clsx"); var _index = _interopRequireDefault(require("../../FieldBlock/index.js")); var _index2 = require("../../hooks/index.js"); var _Upload = _interopRequireDefault(require("../../../../components/Upload.js")); var _useUpload = _interopRequireDefault(require("../../../../components/upload/useUpload.js")); var _uploadFileUtils = require("../../../../components/upload/uploadFileUtils.js"); var _utils = require("../../../../components/flex/utils.js"); var _HelpButtonInline = _interopRequireWildcard(require("../../../../components/help-button/HelpButtonInline.js")); var _index3 = require("../../../../shared/index.js"); var _index4 = require("../../utils/index.js"); var _useIterateItemNo = require("../../Iterate/ItemNo/useIterateItemNo.js"); var _withComponentMarkers = _interopRequireDefault(require("../../../../shared/helpers/withComponentMarkers.js")); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function UploadComponent(props) { const sharedTr = (0, _index3.useTranslation)().Upload; const formsTr = (0, _index2.useTranslation)().Upload; const errorMessages = (0, _react.useMemo)(() => ({ 'Field.errorRequired': formsTr.errorRequired }), [formsTr.errorRequired]); const validateRequired = (0, _react.useCallback)((value, { required, isChanged, error }) => { const hasError = value?.some(file => file.errorMessage); if (hasError) { return new _index4.FormError('Upload.errorInvalidFiles'); } const hasFiles = value?.length > 0; if (required && (!isChanged && !hasFiles || !hasFiles)) { return error; } return undefined; }, []); const fromInput = (0, _react.useCallback)(value => { value?.forEach((item, index) => { if (!item) { return; } value[index] = item; value[index]['name'] = item['name'] || item.file?.name; }); return value; }, []); const preparedProps = { errorMessages, validateRequired, fromInput, toInput: transformFiles, ...props }; const { id, className, width: widthProp = 'stretch', value, label, labelDescription, help, htmlAttributes, disabled, handleChange, handleFocus, handleBlur, fileHandler, onValidationError, dataContext, ...rest } = (0, _index2.useFieldProps)(preparedProps, { executeOnChangeRegardlessOfError: true }); const { identifier } = (0, _index2.usePath)({ id, path: props.path, itemPath: props.itemPath }); const { setFieldState, setFieldInternals } = dataContext || {}; const { title = sharedTr.title, text = sharedTr.text, variant = 'default', acceptedFileTypes = ['pdf', 'png', 'jpg', 'jpeg'], filesAmountLimit = 100, fileMaxSize = 5, skeleton, onFileDelete, onFileClick, download, allowDuplicates, disableDragAndDrop, buttonProps } = rest; const { files, setFiles, clearFiles } = (0, _useUpload.default)(id); const filesRef = (0, _react.useRef)(undefined); (0, _react.useMemo)(() => { filesRef.current = files; }, [files]); const labelWithItemNo = (0, _useIterateItemNo.useIterateItemNo)({ label: label !== null && label !== void 0 ? label : title, labelSuffix: props.labelSuffix, required: props.required }); const isPendingOrErrorFile = (0, _react.useCallback)(file => { return Boolean(file?.isLoading || file?.errorMessage); }, []); (0, _react.useEffect)(() => { return () => { clearFiles(); }; }, [clearFiles]); (0, _react.useEffect)(() => { var _filesRef$current; const externalFiles = value !== null && value !== void 0 ? value : []; const localFiles = (_filesRef$current = filesRef.current) !== null && _filesRef$current !== void 0 ? _filesRef$current : []; const mergedExternalFiles = externalFiles.map(externalFile => { if (!externalFile?.isLoading) { return externalFile; } const localResolvedFile = localFiles.find(localFile => (0, _uploadFileUtils.isSameFile)(localFile, externalFile) && !localFile?.isLoading); return localResolvedFile || externalFile; }); const filesToPreserve = localFiles.filter(localFile => { if (!isPendingOrErrorFile(localFile)) { return false; } return !mergedExternalFiles.some(externalFile => (0, _uploadFileUtils.isSameFile)(externalFile, localFile)); }); setFiles([...mergedExternalFiles, ...filesToPreserve]); }, [isPendingOrErrorFile, setFiles, value]); const handleChangeAsync = (0, _react.useCallback)(async files => { const filesArray = files || []; const existingFileIds = filesRef.current?.map(file => file.id) || []; const existingFiles = filesArray.filter(file => (0, _includes.default)(existingFileIds).call(existingFileIds, file.id)); const newFiles = filesArray.filter(file => !(0, _includes.default)(existingFileIds).call(existingFileIds, file.id)); const newValidFiles = newFiles.filter(file => !file.errorMessage); if (newValidFiles.length > 0) { const fieldIdentifier = identifier; setFieldState?.(fieldIdentifier, 'pending'); setFieldInternals?.(fieldIdentifier, { enableAsyncMode: true }); try { const newFilesLoading = newFiles.map(file => ({ ...file, isLoading: !file.errorMessage })); setFiles([...filesRef.current, ...newFilesLoading]); const incomingFiles = await fileHandler(newValidFiles); if (!incomingFiles) { setFiles(existingFiles); handleChange(existingFiles); } else { var _newFilesLoading$filt; const updatedByResponse = new Set(); incomingFiles.forEach(file => { const incomingFileObj = { ...file, isLoading: false }; const foundIndex = newFilesLoading.findIndex(newFile => newFile.isLoading); if (foundIndex >= 0) { newFilesLoading[foundIndex] = incomingFileObj; updatedByResponse.add(foundIndex); } else { (0, _push.default)(newFilesLoading).call(newFilesLoading, incomingFileObj); } }); newFilesLoading.forEach((file, index) => { if (updatedByResponse.has(index)) { return; } const currentFile = filesRef.current?.find(f => (0, _uploadFileUtils.isSameFile)(f, file)); if (currentFile?.isLoading) { newFilesLoading[index] = { ...file, isLoading: true }; } }); const indexOfFirstNewFile = filesRef.current.findIndex(({ id }) => id === newFiles[0].id); const updatedFiles = [...filesRef.current.slice(0, indexOfFirstNewFile), ...((_newFilesLoading$filt = newFilesLoading?.filter(file => file != null)) !== null && _newFilesLoading$filt !== void 0 ? _newFilesLoading$filt : []), ...filesRef.current.slice(indexOfFirstNewFile + newFilesLoading.length)]; setFiles(updatedFiles); handleChange(updatedFiles); } } finally { setFieldState?.(fieldIdentifier, undefined); } } else { handleChange(files); } }, [identifier, fileHandler, onValidationError, handleChange, setFieldInternals, setFieldState, setFiles]); const processValidationErrors = (0, _react.useCallback)((files, existingFiles) => { var _existingFiles$map; if (!files || !onValidationError) { return files; } const existingFileIds = (_existingFiles$map = existingFiles?.map(file => file.id)) !== null && _existingFiles$map !== void 0 ? _existingFiles$map : []; const newFiles = files.filter(file => !(0, _includes.default)(existingFileIds).call(existingFileIds, file.id)); const newInvalidFiles = newFiles.filter(file => file.errorMessage); if (newInvalidFiles.length === 0) { return files; } const processedInvalidFiles = onValidationError(newInvalidFiles) || newInvalidFiles; return files.map(file => { const processedFile = processedInvalidFiles.find(processed => (0, _uploadFileUtils.isSameFile)(processed, file)); return processedFile || file; }); }, [onValidationError]); const changeHandler = (0, _react.useCallback)(({ files }) => { let changeValue = files?.length === 0 ? undefined : files; handleBlur(); if (changeValue) { handleFocus(); } changeValue = processValidationErrors(changeValue, filesRef.current); if (fileHandler) { handleChangeAsync(changeValue); } else { handleChange(changeValue); } }, [handleBlur, handleFocus, fileHandler, processValidationErrors, handleChangeAsync, handleChange]); const width = widthProp; const fieldBlockProps = { id, forId: `${id}-input`, labelSrOnly: true, className: (0, _clsx.clsx)('dnb-forms-field-upload', className), width, help: undefined, ...(0, _utils.pickSpacingProps)(props) }; const usedLabelDescription = labelDescription !== null && labelDescription !== void 0 ? labelDescription : text; return (0, _jsxRuntime.jsx)(_index.default, { ...fieldBlockProps, children: (0, _jsxRuntime.jsxs)(_Upload.default, { id: id, variant: variant, acceptedFileTypes: acceptedFileTypes, filesAmountLimit: filesAmountLimit, download: download, allowDuplicates: allowDuplicates, disableDragAndDrop: disableDragAndDrop, buttonProps: buttonProps, disabled: disabled, fileMaxSize: fileMaxSize, skeleton: skeleton, onChange: changeHandler, onFileDelete: onFileDelete, onFileClick: onFileClick, title: help && labelDescription === false ? (0, _jsxRuntime.jsx)(LabelWithHelpButton, { label: labelWithItemNo, id: id, help: help }) : labelWithItemNo, text: help && (labelDescription !== null && labelDescription !== void 0 ? labelDescription : text) ? (0, _jsxRuntime.jsx)(LabelWithHelpButton, { label: usedLabelDescription, id: id, help: help }) : usedLabelDescription, ...htmlAttributes, children: [help && (0, _jsxRuntime.jsx)(_HelpButtonInline.HelpButtonInlineContent, { contentId: `${id}-help`, help: help, roundedCorner: variant === 'compact' }), props.children] }) }); } function LabelWithHelpButton(props) { const { label, id, help } = props; return (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [label, (0, _jsxRuntime.jsx)(_HelpButtonInline.default, { contentId: `${id}-help`, left: label ? 'x-small' : false, help: help })] }); } var _default = exports.default = UploadComponent; (0, _withComponentMarkers.default)(UploadComponent, { _supportsSpacingProps: true }); function transformFiles(value) { if (Array.isArray(value)) { if (value.length === 0) { return undefined; } value.map(item => { if (item?.file && !(item.file instanceof File)) { var _lastModified, _type; item['file'] = new File([], item['name'] || item?.file['name'], { lastModified: (_lastModified = item.file?.lastModified) !== null && _lastModified !== void 0 ? _lastModified : 0, type: (_type = item.file?.type) !== null && _type !== void 0 ? _type : '' }); } return item; }); } return value; } //# sourceMappingURL=Upload.js.map