UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

331 lines (330 loc) 14 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; exports.transformFiles = transformFiles; var _push = _interopRequireDefault(require("core-js-pure/stable/instance/push.js")); var _react = _interopRequireWildcard(require("react")); var _classnames = _interopRequireDefault(require("classnames")); var _index = _interopRequireDefault(require("../../FieldBlock/index.js")); var _index2 = require("../../hooks/index.js"); var _Upload = _interopRequireDefault(require("../../../../components/Upload.js")); var _useUpload = _interopRequireWildcard(require("../../../../components/upload/useUpload.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"); 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 _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } 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 === null || value === void 0 ? void 0 : value.some(file => file.errorMessage); if (hasError) { return new _index4.FormError('Upload.errorInvalidFiles'); } const hasFiles = (value === null || value === void 0 ? void 0 : value.length) > 0; if (required && (!isChanged && !hasFiles || !hasFiles)) { return error; } return undefined; }, []); const fromInput = (0, _react.useCallback)(value => { value === null || value === void 0 || value.forEach((item, index) => { var _item$file; if (!item) { return; } value[index] = item; value[index]['name'] = item['name'] || ((_item$file = item.file) === null || _item$file === void 0 ? void 0 : _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 = 'normal', 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 labelWithItemNo = (0, _useIterateItemNo.useIterateItemNo)({ label: label !== null && label !== void 0 ? label : title, labelSuffix: props.labelSuffix, required: props.required }); const filesRef = (0, _react.useRef)(); (0, _react.useMemo)(() => { filesRef.current = files; }, [files]); const isSameUploadFile = (0, _react.useCallback)((fileA, fileB) => { if (!fileA || !fileB) { return false; } if (fileA.id && fileB.id && fileA.id === fileB.id) { return true; } return (0, _useUpload.isFileEqual)(fileA.file, fileB.file); }, []); const isPendingOrErrorFile = (0, _react.useCallback)(file => { return Boolean((file === null || file === void 0 ? void 0 : file.isLoading) || (file === null || file === void 0 ? void 0 : 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 !== null && externalFile !== void 0 && externalFile.isLoading)) { return externalFile; } const localResolvedFile = localFiles.find(localFile => isSameUploadFile(localFile, externalFile) && !(localFile !== null && localFile !== void 0 && localFile.isLoading)); return localResolvedFile || externalFile; }); const filesToPreserve = localFiles.filter(localFile => { if (!isPendingOrErrorFile(localFile)) { return false; } return !mergedExternalFiles.some(externalFile => isSameUploadFile(externalFile, localFile)); }); setFiles([...mergedExternalFiles, ...filesToPreserve]); }, [isPendingOrErrorFile, isSameUploadFile, setFiles, value]); const handleChangeAsync = (0, _react.useCallback)(async files => { var _filesRef$current2; const filesArray = files || []; const existingFileIds = ((_filesRef$current2 = filesRef.current) === null || _filesRef$current2 === void 0 ? void 0 : _filesRef$current2.map(file => file.id)) || []; const existingFiles = filesArray.filter(file => existingFileIds.includes(file.id)); const newFiles = filesArray.filter(file => !existingFileIds.includes(file.id)); const newValidFiles = newFiles.filter(file => !file.errorMessage); if (newValidFiles.length > 0) { const fieldIdentifier = identifier; setFieldState === null || setFieldState === void 0 || setFieldState(fieldIdentifier, 'pending'); setFieldInternals === null || setFieldInternals === void 0 || 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) => { var _filesRef$current3; if (updatedByResponse.has(index)) { return; } const currentFile = (_filesRef$current3 = filesRef.current) === null || _filesRef$current3 === void 0 ? void 0 : _filesRef$current3.find(f => f.id && f.id === file.id || f.file && f.file === file.file); if (currentFile !== null && currentFile !== void 0 && 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 === null || newFilesLoading === void 0 ? void 0 : newFilesLoading.filter(file => file != null)) !== null && _newFilesLoading$filt !== void 0 ? _newFilesLoading$filt : []), ...filesRef.current.slice(indexOfFirstNewFile + newFilesLoading.length)]; setFiles(updatedFiles); handleChange(updatedFiles); } } finally { setFieldState === null || setFieldState === void 0 || 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 === null || existingFiles === void 0 ? void 0 : existingFiles.map(file => file.id)) !== null && _existingFiles$map !== void 0 ? _existingFiles$map : []; const newFiles = files.filter(file => !existingFileIds.includes(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 => processed.id === file.id || processed.file && processed.file === file.file); return processedFile || file; }); }, [onValidationError]); const changeHandler = (0, _react.useCallback)(({ files }) => { let changeValue = (files === null || files === void 0 ? void 0 : 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, _classnames.default)('dnb-forms-field-upload', className), width, help: undefined, ...(0, _utils.pickSpacingProps)(props) }; const usedLabelDescription = labelDescription !== null && labelDescription !== void 0 ? labelDescription : text; return _react.default.createElement(_index.default, fieldBlockProps, _react.default.createElement(_Upload.default, _extends({ 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 ? _react.default.createElement(LabelWithHelpButton, { label: labelWithItemNo, id: id, help: help }) : labelWithItemNo, text: help && (labelDescription !== null && labelDescription !== void 0 ? labelDescription : text) ? _react.default.createElement(LabelWithHelpButton, { label: usedLabelDescription, id: id, help: help }) : usedLabelDescription }, htmlAttributes), help && _react.default.createElement(_HelpButtonInline.HelpButtonInlineContent, { contentId: `${id}-help`, help: help, roundedCorner: variant === 'compact' }), props.children)); } function LabelWithHelpButton(props) { const { label, id, help } = props; return _react.default.createElement(_react.default.Fragment, null, label, _react.default.createElement(_HelpButtonInline.default, { contentId: `${id}-help`, left: label ? 'x-small' : false, help: help })); } var _default = exports.default = UploadComponent; UploadComponent._supportsSpacingProps = true; function transformFiles(value) { if (Array.isArray(value)) { if (value.length === 0) { return undefined; } value.map(item => { if (item !== null && item !== void 0 && item.file && !(item.file instanceof File)) { var _lastModified, _item$file2, _type, _item$file3; item['file'] = new File([], item['name'] || (item === null || item === void 0 ? void 0 : item.file['name']), { lastModified: (_lastModified = (_item$file2 = item.file) === null || _item$file2 === void 0 ? void 0 : _item$file2.lastModified) !== null && _lastModified !== void 0 ? _lastModified : 0, type: (_type = (_item$file3 = item.file) === null || _item$file3 === void 0 ? void 0 : _item$file3.type) !== null && _type !== void 0 ? _type : '' }); } return item; }); } return value; } //# sourceMappingURL=Upload.js.map