@geneui/components
Version:
The Gene UI components library designed for BI tools
993 lines (981 loc) • 44.9 kB
JavaScript
import { _ as _extends } from '../_rollupPluginBabelHelpers-e8fb2e5c.js';
import React__default, { useState, useCallback, useEffect, forwardRef, useMemo, useRef } from 'react';
import PropTypes from 'prop-types';
import { c as classnames } from '../index-031ff73c.js';
import { u as uploaderConfig } from '../configs-00612ce0.js';
import { p as getImageDimensions, s as stopEvent, f as fileSizeDisplay, n as noop } from '../index-a0e4e333.js';
import Button from '../Button/index.js';
import ExtendedInput from '../ExtendedInput/index.js';
import { Row, Col } from '../Grid/index.js';
import useKeyDown from '../hooks/useKeyDown.js';
import useImgDownload from '../hooks/useImgDownload.js';
import BusyLoader from '../BusyLoader/index.js';
import Icon from '../Icon/index.js';
import Image from '../Image/index.js';
import { T as Tooltip } from '../index-6d7e99cd.js';
import { s as styleInject } from '../style-inject.es-746bb8ed.js';
import '../dateValidation-67caec66.js';
import '../_commonjsHelpers-24198af3.js';
import 'react-dom';
import '../tslib.es6-f211516f.js';
import '../hooks/useDeviceType.js';
import '../hooks/useWindowSize.js';
import '../hooks/useDebounce.js';
import '../useEllipsisDetection-4d997d5d.js';
import '../SuggestionList/index.js';
import '../hooks/useClickOutside.js';
import '../config-1053d64d.js';
import '../Scrollbar/index.js';
import '../callAfterDelay-7272faca.js';
import '../GeneUIProvider/index.js';
import '../hooks/useWidth.js';
import '../Empty/index.js';
import '../Checkbox/index.js';
import '../checkboxRadioSwitcher-5b69d7bd.js';
import '../guid-8ddf77b3.js';
// Helpers
const typeListReplacer = 'TYPE_LIST';
const maxFileSizeReplacer = 'MAX_FILE_SIZE';
const getFileByUrl = async (url, file, isImageUpload, customHeaders) => {
const res = await fetch(url, {
headers: {
...customHeaders
}
});
const blob = await res.blob();
const blobFile = {
blob,
...file
};
if (isImageUpload) {
blobFile.dimensions = await getImageDimensions(blob);
}
return blobFile;
};
const addDragEventListener = (element, handleDragIn, handleDragOut, handleDrop) => {
element.addEventListener('dragenter', handleDragIn);
element.addEventListener('dragover', handleDragIn);
element.addEventListener('dragleave', handleDragOut);
element.addEventListener('dragend', handleDragOut);
element.addEventListener('drop', handleDrop);
};
const removeDragEventListener = (element, handleDragIn, handleDragOut, handleDrop) => {
element.removeEventListener('dragenter', handleDragIn);
element.removeEventListener('dragover', handleDragIn);
element.removeEventListener('dragleave', handleDragOut);
element.removeEventListener('dragend', handleDragOut);
element.removeEventListener('drop', handleDrop);
};
const toBlobFile = async (file, isImageUpload) => {
const blob = new Blob([file], {
type: file.type
});
const blobFile = {
name: file.name,
blob,
path: URL.createObjectURL(blob)
};
if (isImageUpload) {
const dimensions = await getImageDimensions(blob);
blobFile.dimensions = dimensions;
}
return blobFile;
};
/**
* Checking the file for the size and type of rules
* and return each one of them.
*/
const isValidFile = _ref => {
var _file$name$split$pop;
let {
allTypesAccepted,
isImageUpload,
maxFileSize,
typesList,
file
} = _ref;
const fileType = file && file.name && ((_file$name$split$pop = file.name.split('.').pop()) === null || _file$name$split$pop === void 0 ? void 0 : _file$name$split$pop.toLowerCase());
return {
isValidSize: file.size <= maxFileSize,
isValidType: typesList.length ? typesList.includes(fileType) : allTypesAccepted
};
};
const generateFilesByPage = files => {
if (files && files.length) {
const data = files.map(path => {
const binary = new ArrayBuffer(path.length);
const blob = new Blob([binary], {
type: 'image/jpeg'
});
return {
blob,
path,
name: path.split('/').pop()
};
});
return data;
}
return [];
};
const getLastMod = (url, cb) => {
fetch(url).then(response => {
const headersObj = Object.fromEntries([...response.headers]);
return cb(headersObj['last-modified']);
});
};
var css_248z$3 = "[data-gene-ui-version=\"2.16.5\"] .media-preview-holder{background-color:#000c;color:#fff;display:flex;height:100%;left:0;position:fixed;top:0;width:100%;z-index:500}[data-gene-ui-version=\"2.16.5\"] .media-preview-holder .bc-icon-close{cursor:pointer;position:absolute;right:2.2rem;top:2.2rem}[data-gene-ui-version=\"2.16.5\"] .media-preview{display:flex;flex-direction:column;margin:auto;padding:3rem 0 0;position:relative}[data-gene-ui-version=\"2.16.5\"] .media-preview .mp-title{font:600 1.4rem/1.8rem var(--font-family);left:0;position:absolute;top:0;width:100%}[data-gene-ui-version=\"2.16.5\"] .mp-details{font:600 1.4rem/2rem var(--font-family);margin:.5rem 0 0}[data-gene-ui-version=\"2.16.5\"] .mp-details>li{margin:1rem 0 0}[data-gene-ui-version=\"2.16.5\"] .mp-details span{opacity:.7}[data-gene-ui-version=\"2.16.5\"] .mp-element{height:auto;max-height:calc(100vh - 20rem);max-width:100%;width:auto}";
styleInject(css_248z$3);
function Preview(_ref) {
let {
previewImage: {
name,
path,
blob: {
size
},
dimensions
},
hideName,
onClose
} = _ref;
return /*#__PURE__*/React__default.createElement("div", {
className: "media-preview-holder",
onClick: onClose
}, /*#__PURE__*/React__default.createElement(Icon, {
type: "bc-icon-close"
}), /*#__PURE__*/React__default.createElement("div", {
className: "media-preview",
onClick: stopEvent
}, /*#__PURE__*/React__default.createElement("div", {
className: "mp-title ellipsis-text"
}, !hideName && name), /*#__PURE__*/React__default.createElement("img", {
className: "mp-element",
src: path,
alt: name
}), /*#__PURE__*/React__default.createElement("ul", {
className: "mp-details"
}, /*#__PURE__*/React__default.createElement("li", null, /*#__PURE__*/React__default.createElement("span", null, "Image size:"), " ", fileSizeDisplay(size), ' '), dimensions && /*#__PURE__*/React__default.createElement("li", null, /*#__PURE__*/React__default.createElement("span", null, "Image dimensions: "), dimensions.width, " x ", dimensions.height))));
}
Preview.propTypes = {
previewImage: PropTypes.object.isRequired,
onClose: PropTypes.func.isRequired,
dimensions: PropTypes.object,
name: PropTypes.string,
path: PropTypes.string,
blob: PropTypes.object
};
Preview.defaultProps = {
dimensions: {}
};
var css_248z$2 = "[data-gene-ui-version=\"2.16.5\"] .uploaded-item{align-items:center;border-radius:.4rem;display:flex;height:2.8rem;padding:0 1px 0 .8rem;transition:background .4s,color .4s,border-color .4s;width:100%}html[dir=rtl] .uploaded-item{padding:0 .8rem 0 1px}[data-gene-ui-version=\"2.16.5\"] .uploaded-item:not(.error){cursor:pointer}[data-gene-ui-version=\"2.16.5\"] .uploaded-item>li{align-items:center;display:flex;flex-shrink:0}[data-gene-ui-version=\"2.16.5\"] .uploaded-item>li.ui-title{flex:auto;overflow:hidden}[data-gene-ui-version=\"2.16.5\"] .uploaded-item .ui-preview-holder{position:relative}[data-gene-ui-version=\"2.16.5\"] .uploaded-item .ui-preview-holder small{display:block;font:700 .5rem/.9rem var(--font-family);left:0;position:absolute;text-align:center;text-transform:uppercase;top:.8rem;width:100%}[data-gene-ui-version=\"2.16.5\"] .uploaded-item .ui-title{font:600 1.4rem/normal var(--font-family);padding:0 2rem}[data-gene-ui-version=\"2.16.5\"] .uploaded-item .ui-actions-holder small{display:block;font:600 1rem/1.4rem var(--font-family);opacity:.7;padding-inline-end:.8rem;text-transform:uppercase}[data-gene-ui-version=\"2.16.5\"] .uploaded-item .ui-actions-holder .icon{cursor:pointer;transition:opacity .4s}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-light .ui-actions-holder .icon,[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-minimal .ui-actions-holder .icon{opacity:0}@media (hover:hover){[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-light .ui-actions-holder .icon:hover,[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-minimal .ui-actions-holder .icon:hover{opacity:1}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-light:hover,[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-minimal:hover{background:rgba(var(--background-sc-rgb),.05)}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-light:hover .ui-actions-holder .icon:not(:hover),[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-minimal:hover .ui-actions-holder .icon:not(:hover){opacity:.5}}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-light.error,[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-minimal.error{color:var(--danger)}@media (hover:hover){[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-light.error:hover,[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-minimal.error:hover{background:rgba(var(--danger-rgb),.05)}}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-light.error .ui-actions-holder .icon:not(:hover),[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-minimal.error .ui-actions-holder .icon:not(:hover){opacity:.5}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-detailed{border:1px solid rgba(var(--background-sc-rgb),.08);border-radius:.8rem;height:4.2rem;padding:0 .8rem 0 1.4rem}html[dir=rtl] .uploaded-item.ui-detailed{padding:0 1.4rem 0 .8rem}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-detailed img{border-radius:.4rem;height:2.6rem;object-fit:cover;width:2.6rem}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-detailed .ui-title{font-size:1.2rem;padding:0 1.4rem}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-detailed .ui-actions-holder .icon{opacity:.5}@media (hover:hover){[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-detailed .ui-actions-holder .icon:hover{opacity:1}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-detailed:hover{border-color:rgba(var(--background-sc-rgb),.38)}}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-detailed.error{border-color:rgba(var(--danger-rgb),.5)}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-detailed.error .ui-actions-holder .icon{color:var(--danger)}@media (hover:hover){[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-detailed.error:hover{border-color:var(--danger)}[data-gene-ui-version=\"2.16.5\"] .uploaded-item.ui-detailed.error:hover .ui-actions-holder .icon{opacity:1}}";
styleInject(css_248z$2);
function UploadedItem(_ref) {
let {
notUploadedFileList,
uploadErrorText,
metaDataHeaders,
customHeaders,
appearance,
retryIndex,
onRemove,
showTrash,
onRetry,
isBusy,
index,
file,
showDownloadButton,
showRemoveButton,
showResetButton,
showPreviewButton,
additionalContext,
hideName
} = _ref;
const [previewImage, setPreviewImage] = useState(null);
const [lastModifiedDate, setLastModifiedDate] = useState(null);
const toPreview = useCallback(image => {
if (file.blob.type.search('pdf') > -1) {
const link = document.createElement('a');
link.href = file.path;
link.target = '_blank';
link.click();
} else {
setPreviewImage(image);
}
}, []);
const doClosePreview = useCallback(() => setPreviewImage(null), []);
useKeyDown(doClosePreview, [], {
current: window
}, ['Escape']);
const {
name,
blob: {
size,
type
},
path,
dimensions
} = file;
useEffect(() => {
switch (metaDataHeaders === null || metaDataHeaders === void 0 ? void 0 : metaDataHeaders.type) {
case 'LAST-MODIFIED':
if (metaDataHeaders.formatter) {
getLastMod(path, date => {
date ? setLastModifiedDate(metaDataHeaders.formatter(date)) : setLastModifiedDate(metaDataHeaders.formatter(new Date(Date.now())));
});
} else {
getLastMod(path, date => {
date ? setLastModifiedDate(new Date(date).toLocaleDateString()) : setLastModifiedDate(new Date(Date.now()).toLocaleDateString());
});
}
break;
}
}, [file]);
const uploadedError = notUploadedFileList.find(item => item && item.file === file);
const [image, fileExtension] = type.split('/');
const isImage = image === 'image';
const renderPreview = () => {
switch (appearance) {
case uploaderConfig.uploadedItemsAppearance[0]:
return /*#__PURE__*/React__default.createElement(Icon, {
type: "bc-icon-attachment"
});
case uploaderConfig.uploadedItemsAppearance[1]:
return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Icon, {
type: "bc-icon-file-type"
}), /*#__PURE__*/React__default.createElement("small", null, fileExtension));
case uploaderConfig.uploadedItemsAppearance[2]:
return isImage ? /*#__PURE__*/React__default.createElement("img", {
src: path,
alt: name
}) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Icon, {
type: "bc-icon-file-type"
}), /*#__PURE__*/React__default.createElement("small", null, fileExtension));
}
};
const onDownload = useImgDownload();
return previewImage ? /*#__PURE__*/React__default.createElement(Preview, {
onClose: doClosePreview,
previewImage: previewImage,
hideName: hideName
}) : /*#__PURE__*/React__default.createElement(BusyLoader, {
isBusy: isBusy && retryIndex === index,
loadingText: ""
}, /*#__PURE__*/React__default.createElement(Tooltip, {
title: uploadedError ? uploadErrorText : '',
text: uploadedError && uploadedError.error || ''
}, appearance === uploaderConfig.uploadedItemsAppearance[3] && isImage ? /*#__PURE__*/React__default.createElement(Image, {
src: path,
withBorder: true,
isValid: !uploadedError,
actions: /*#__PURE__*/React__default.createElement(React__default.Fragment, null, uploadedError && showResetButton ? /*#__PURE__*/React__default.createElement(Button, {
icon: "bc-icon-reset",
appearance: "minimal",
"data-index": index,
onClick: onRetry,
type: "button"
}) : showPreviewButton && /*#__PURE__*/React__default.createElement(Button, {
icon: "bc-icon-view",
appearance: "minimal",
onClick: () => toPreview(file),
type: "button"
}), showRemoveButton && /*#__PURE__*/React__default.createElement(Button, {
icon: "bc-icon-trash",
"data-index": index,
onClick: onRemove,
appearance: "minimal",
color: "danger",
type: "button"
}))
}) : /*#__PURE__*/React__default.createElement("ul", {
className: classnames('uploaded-item', "ui-".concat(appearance), {
error: uploadedError
})
}, /*#__PURE__*/React__default.createElement("li", {
className: "ui-preview-holder"
}, renderPreview()), /*#__PURE__*/React__default.createElement("li", {
className: "ui-title"
}, /*#__PURE__*/React__default.createElement("div", {
className: "ellipsis-text"
}, name)), /*#__PURE__*/React__default.createElement("li", {
className: "ui-actions-holder"
}, /*#__PURE__*/React__default.createElement("small", null, lastModifiedDate || fileSizeDisplay(size)), uploadedError && showResetButton && /*#__PURE__*/React__default.createElement(Icon, {
type: "bc-icon-upload-reset",
"data-index": index,
onClick: onRetry
}), showPreviewButton && /*#__PURE__*/React__default.createElement(Icon, {
type: "bc-icon-activate",
appearance: "minimal",
"data-index": index,
onClick: () => toPreview(file)
}), showRemoveButton && /*#__PURE__*/React__default.createElement(Icon, {
type: "bc-icon-trash",
appearance: "minimal",
"data-index": index,
onClick: onRemove
}), showDownloadButton && /*#__PURE__*/React__default.createElement(Icon, {
type: "bc-icon-download",
appearance: "minimal",
"data-index": index,
onClick: () => onDownload(file.path, file.name, customHeaders)
})))));
}
UploadedItem.propTypes = {
file: PropTypes.object,
index: PropTypes.number,
isBusy: PropTypes.bool,
showTrash: PropTypes.bool,
notUploadedFileList: PropTypes.array,
onRemove: PropTypes.func,
onRetry: PropTypes.func,
retryIndex: PropTypes.number,
uploadErrorText: PropTypes.string,
appearance: PropTypes.oneOf(uploaderConfig.uploadedItemsAppearance),
showDownloadButton: PropTypes.bool,
showRemoveButton: PropTypes.bool,
showResetButton: PropTypes.bool,
showPreviewButton: PropTypes.bool
};
UploadedItem.defaultProps = {
appearance: uploaderConfig.uploadedItemsAppearance[0],
isBusy: false,
uploadErrorText: 'Upload Error',
onRetry: noop,
onRemove: noop,
showDownloadButton: true,
showRemoveButton: true,
showResetButton: true,
showPreviewButton: true
};
var css_248z$1 = "[data-gene-ui-version=\"2.16.5\"] .drop-area-holder{max-width:100%;position:relative;transition:opacity .4s}[data-gene-ui-version=\"2.16.5\"] .drop-area-holder.disabled{opacity:.5;pointer-events:none}[data-gene-ui-version=\"2.16.5\"] .drop-area-holder:not(.ua-button){width:100%}[data-gene-ui-version=\"2.16.5\"] .drop-area-holder.ua-input .uploader-chooser-holder{display:grid;grid-template-areas:\"input button\";grid-template-columns:1fr auto;position:relative}[data-gene-ui-version=\"2.16.5\"] .drop-area-holder.ua-input .uploader-chooser-holder .input-holder{grid-area:input}html:not([dir=rtl]) .drop-area-holder.ua-input .uploader-chooser-holder .input-element-back{border-top-right-radius:0}html[dir=rtl] .drop-area-holder.ua-input .uploader-chooser-holder .input-element-back{border-top-left-radius:0}html:not([dir=rtl]) .drop-area-holder.ua-input .uploader-chooser-holder .input-element-back{border-bottom-right-radius:0}html[dir=rtl] .drop-area-holder.ua-input .uploader-chooser-holder .input-element-back{border-bottom-left-radius:0}html:not([dir=rtl]) .drop-area-holder.ua-input .uploader-chooser-holder .input-element-back{border-right:0}html[dir=rtl] .drop-area-holder.ua-input .uploader-chooser-holder .input-element-back{border-left:0}[data-gene-ui-version=\"2.16.5\"] .drop-area-holder.ua-input .uploader-chooser-holder .btn{grid-area:button}html:not([dir=rtl]) .drop-area-holder.ua-input .uploader-chooser-holder .btn{border-top-left-radius:0}html[dir=rtl] .drop-area-holder.ua-input .uploader-chooser-holder .btn{border-top-right-radius:0}html:not([dir=rtl]) .drop-area-holder.ua-input .uploader-chooser-holder .btn{border-bottom-left-radius:0}html[dir=rtl] .drop-area-holder.ua-input .uploader-chooser-holder .btn{border-bottom-right-radius:0}html:not([dir=rtl]) .drop-area-holder.ua-input .uploader-chooser-holder .btn{border-left:0}html[dir=rtl] .drop-area-holder.ua-input .uploader-chooser-holder .btn{border-right:0}[data-gene-ui-version=\"2.16.5\"] .drop-area-holder.ua-input .uploader-chooser-holder.dirty input[type=file]{grid-area:input}[data-gene-ui-version=\"2.16.5\"] .drop-area-holder.ua-box .uploader-chooser-holder{padding:100% 0 0;position:relative}[data-gene-ui-version=\"2.16.5\"] .uploader-chooser-holder{display:block;transition:opacity .4s}[data-gene-ui-version=\"2.16.5\"] .drop-area-holder.active .uploader-chooser-holder{opacity:0}[data-gene-ui-version=\"2.16.5\"] .uploader-chooser-holder input[type=file]{cursor:pointer;height:100%;left:0;opacity:0;position:absolute;top:0;width:100%;z-index:1}[data-gene-ui-version=\"2.16.5\"] .uploader-chooser-holder input[type=file]::-webkit-file-upload-button{visibility:hidden}[data-gene-ui-version=\"2.16.5\"] .drop-here-element{align-items:center;background:rgba(var(--hero-rgb),.1);border:1px dashed var(--hero);border-radius:1rem;color:var(--hero);display:flex;font:600 1.4rem/1.8rem var(--font-family);height:100%;justify-content:center;left:0;padding:0 1rem;pointer-events:none;position:absolute;top:0;transition:opacity .4s;width:100%;z-index:10}[data-gene-ui-version=\"2.16.5\"] .drop-area-holder:not(.active) .drop-here-element{opacity:0}[data-gene-ui-version=\"2.16.5\"] .ua-button .drop-here-element.cr-round,[data-gene-ui-version=\"2.16.5\"] .ua-input .drop-here-element.cr-round{border-radius:3.6rem}[data-gene-ui-version=\"2.16.5\"] .ua-button .drop-here-element.cr-smooth,[data-gene-ui-version=\"2.16.5\"] .ua-input .drop-here-element.cr-smooth{border-radius:.4rem}[data-gene-ui-version=\"2.16.5\"] .ua-cloud .drop-here-element{border-radius:.8rem}[data-gene-ui-version=\"2.16.5\"] .cloud-box-uploader{align-items:center;border:1px dashed rgba(var(--background-sc-rgb),.2);border-radius:.8rem;display:flex;flex-direction:column;font:600 2rem/2.4rem var(--font-family);justify-content:center;min-height:28rem;text-align:center;transition:background .4s,border-color .4s;width:100%}[data-gene-ui-version=\"2.16.5\"] .uploader-chooser-holder:hover .cloud-box-uploader{background:rgba(var(--hero-rgb),.02);border-color:var(--hero)}[data-gene-ui-version=\"2.16.5\"] .s-uploading .cloud-box-uploader{background:rgba(var(--background-sc-rgb),.01)}[data-gene-ui-version=\"2.16.5\"] .cloud-box-uploader.error{background:rgba(var(--danger-rgb),.02);border-color:var(--danger)}[data-gene-ui-version=\"2.16.5\"] .cloud-box-uploader>p{opacity:.8}[data-gene-ui-version=\"2.16.5\"] .cloud-box-uploader>.icon{font-size:9.6rem;margin:1rem 0 .4rem;opacity:.23}[data-gene-ui-version=\"2.16.5\"] .cloud-box-uploader>h5{font:inherit;opacity:.8}[data-gene-ui-version=\"2.16.5\"] .cloud-box-uploader>small{display:block;font:600 1.4rem/1.8rem var(--font-family);margin:1rem 0 1.5rem;opacity:.5}[data-gene-ui-version=\"2.16.5\"] .box-uploader{align-items:center;border:1px dashed rgba(var(--background-sc-rgb),.2);border-radius:1rem;display:flex;flex-direction:column;height:100%;justify-content:center;left:0;position:absolute;text-align:center;top:0;transition:background .4s,border-color .4s;width:100%}[data-gene-ui-version=\"2.16.5\"] .uploader-chooser-holder:hover .box-uploader{background:rgba(var(--hero-rgb),.02);border-color:var(--hero)}[data-gene-ui-version=\"2.16.5\"] .s-uploading .box-uploader{border-style:solid}[data-gene-ui-version=\"2.16.5\"] .box-uploader.error{background:rgba(var(--danger-rgb),.02);border-color:var(--danger)}[data-gene-ui-version=\"2.16.5\"] .box-uploader h5{font:600 1.4rem/normal var(--font-family);margin:1rem 0 0;opacity:.8}[data-gene-ui-version=\"2.16.5\"] .box-uploader .responsive-plus-icon-holder{max-height:6.4rem;max-width:6.4rem;min-height:3.6rem;min-width:3.6rem;opacity:.2;width:23.2456140351%}[data-gene-ui-version=\"2.16.5\"] .responsive-plus-icon{padding:100% 0 0;position:relative}[data-gene-ui-version=\"2.16.5\"] .responsive-plus-icon:after,[data-gene-ui-version=\"2.16.5\"] .responsive-plus-icon:before{background:var(--background-sc);border-radius:1rem;content:\"\";display:block;left:50%;padding:7.5471698113% 0 0;position:absolute;top:50%;width:88.679245283%}[data-gene-ui-version=\"2.16.5\"] .responsive-plus-icon:before{transform:translate(-50%,-50%)}[data-gene-ui-version=\"2.16.5\"] .responsive-plus-icon:after{transform:translate(-50%,-50%) rotate(90deg)}";
styleInject(css_248z$1);
const UploadView = /*#__PURE__*/forwardRef((_ref, ref) => {
let {
immediatelyUploadAfterSelect,
inputCornerRadius,
startUploadLabel,
chooseFileLabel,
dropHereLabel,
cornerRadius,
loadingLabel,
browseLabel,
appearance,
isDisabled,
className,
draggable,
typesList,
onUpload,
multiple,
isValid,
isBusy,
icon,
...restProps
} = _ref;
const handleChange = useCallback(e => {
onUpload && onUpload(e);
e.target.value = '';
}, [onUpload]);
const acceptTypes = useMemo(() => typesList.map(type => ".".concat(type)).toString(), [typesList]);
const dirty = false;
const renderUploadHolder = () => {
const placeholder = isBusy ? loadingLabel : chooseFileLabel;
switch (appearance) {
case uploaderConfig.uploaderAppearance[0]:
return /*#__PURE__*/React__default.createElement(Button, {
appearance: "outline",
cornerRadius: cornerRadius,
color: isValid ? '' : 'danger',
icon: isBusy ? 'bc-icon-loader' : icon
}, placeholder);
case uploaderConfig.uploaderAppearance[1]:
return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(ExtendedInput, {
cornerRadius: inputCornerRadius,
placeholder: placeholder,
inputSize: "big",
writeProtected: true,
colorBorderOnError: true,
isValid: isValid
}), /*#__PURE__*/React__default.createElement(Button, {
cornerRadius: cornerRadius,
size: "big",
icon: isBusy ? 'bc-icon-loader' : '',
color: isValid ? 'confirm' : 'danger'
}, browseLabel));
case uploaderConfig.uploaderAppearance[2]:
return /*#__PURE__*/React__default.createElement("div", {
className: classnames('cloud-box-uploader', {
error: !isValid
})
}, isBusy ? /*#__PURE__*/React__default.createElement("p", null, loadingLabel) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Icon, {
type: icon || 'bc-icon-cloud-upload'
}), /*#__PURE__*/React__default.createElement("h5", null, chooseFileLabel), /*#__PURE__*/React__default.createElement("small", null, "or"), /*#__PURE__*/React__default.createElement(Button, {
cornerRadius: cornerRadius,
color: isValid ? '' : 'danger'
}, browseLabel)));
case uploaderConfig.uploaderAppearance[3]:
return /*#__PURE__*/React__default.createElement("div", {
className: classnames('box-uploader', {
error: !isValid
})
}, /*#__PURE__*/React__default.createElement(BusyLoader, {
isBusy: isBusy,
loadingText: loadingLabel,
className: "p-absolute"
}, /*#__PURE__*/React__default.createElement("div", {
className: "responsive-plus-icon-holder"
}, /*#__PURE__*/React__default.createElement("div", {
className: "responsive-plus-icon"
})), /*#__PURE__*/React__default.createElement("h5", null, chooseFileLabel)));
}
};
return /*#__PURE__*/React__default.createElement("ul", _extends({
className: classnames('drop-area-holder', className, "ua-".concat(appearance), {
active: draggable,
disabled: isDisabled,
'pointer-events-none s-uploading': isBusy
}),
ref: ref
}, restProps), /*#__PURE__*/React__default.createElement("label", {
className: classnames('uploader-chooser-holder', {
dirty
})
}, renderUploadHolder(), /*#__PURE__*/React__default.createElement("input", {
type: "file",
onChange: handleChange,
disabled: isDisabled,
accept: acceptTypes,
title: "",
multiple: multiple
})), !isDisabled && /*#__PURE__*/React__default.createElement("div", {
className: classnames('drop-here-element', "cr-".concat(cornerRadius))
}, /*#__PURE__*/React__default.createElement("p", {
className: "ellipsis-text"
}, dropHereLabel)));
});
UploadView.propTypes = {
appearance: PropTypes.oneOf(uploaderConfig.uploaderAppearance),
immediatelyUploadAfterSelect: PropTypes.bool,
onUpload: PropTypes.func.isRequired,
draggable: PropTypes.bool,
icon: PropTypes.string,
cornerRadius: 'smooth',
inputCornerRadius: ExtendedInput.propTypes.cornerRadius,
isDisabled: PropTypes.bool,
isBusy: PropTypes.bool,
chooseFileLabel: PropTypes.string,
browseLabel: PropTypes.string,
startUploadLabel: PropTypes.string,
dropHereLabel: PropTypes.string,
loadingLabel: PropTypes.string,
className: PropTypes.string,
isValid: PropTypes.bool,
typesList: PropTypes.arrayOf(PropTypes.string)
};
UploadView.defaultProps = {
appearance: uploaderConfig.uploaderAppearance[0],
immediatelyUploadAfterSelect: true,
draggable: false,
cornerRadius: 'smooth',
inputCornerRadius: ExtendedInput.defaultProps.cornerRadius,
isDisabled: false,
isBusy: false,
chooseFileLabel: 'Upload File',
browseLabel: 'Browse',
startUploadLabel: 'Start Upload',
dropHereLabel: 'Drop here',
loadingLabel: 'Uploading...',
typesList: [],
isValid: true,
multiple: false
};
var css_248z = "[data-gene-ui-version=\"2.16.5\"] .uploader-holder{align-items:flex-start;display:flex;flex-direction:column;width:100%}[data-gene-ui-version=\"2.16.5\"] .uploader-holder .grid-child{min-height:2.8rem;position:relative}[data-gene-ui-version=\"2.16.5\"] .uploader-header{align-items:flex-start;display:flex;flex-direction:column;width:100%}[data-gene-ui-version=\"2.16.5\"] .uploader-header:not(.only-child){margin:0 0 1.4rem}[data-gene-ui-version=\"2.16.5\"] .uploader-footer{align-items:flex-start;display:flex;flex-direction:column;width:100%}[data-gene-ui-version=\"2.16.5\"] .ua-cloud>.uploader-footer{align-items:center}[data-gene-ui-version=\"2.16.5\"] .ua-input>.uploader-footer{padding:0 2rem}[data-gene-ui-version=\"2.16.5\"] .uploader-footer .uploader-footer-button{margin:1.8rem 0 0}";
styleInject(css_248z);
const lowGrid = 10;
const highGrid = 20;
function Uploader(_ref) {
let {
immediatelyUploadAfterSelect,
uploadedItemsAppearance,
informationMessage,
uploaderAppearance,
inputCornerRadius,
allTypesAccepted,
startUploadLabel,
noFileChosenText,
chooseFileLabel,
getInitialState,
showLocalErrors,
metaDataHeaders,
showDownloadButton,
showResetButton,
showPreviewButton,
uploadErrorText,
uploadingLabel,
fileChosenText,
fileAppearance,
customHeaders,
isImageUpload,
dropHereLabel,
maxFileCount,
cornerRadius,
deleteAction,
sizeErrorMsg,
typeErrorMsg,
isActiveDrop,
loadingLabel,
browseLabel,
maxFileSize,
isDisabled,
typesList,
showTrash,
className,
draggText,
onChange,
required,
multiple,
isValid,
upload,
icon,
data,
initialData,
images,
initialImages,
additionalContext,
hideName,
...restProps
} = _ref;
const isControlled = useMemo(() => Array.isArray(images), [images]);
const dropRef = useRef(null);
const [fileList, setFileList] = useState(generateFilesByPage(initialImages));
const [deletedFileList, setDeletedFileList] = useState([]);
const [errorMsg, setErrorMsg] = useState('');
const [notUploadedFileList, setNotUploadedFileList] = useState([]);
const [draggable, setDraggable] = useState(false);
const [isBusy, setIsBusy] = useState(false);
const [refreshIndex, setRefreshIndex] = useState(null);
const [valid, setValidation] = useState(true);
useEffect(() => {
isControlled && setFileList(generateFilesByPage(images));
}, [isControlled, images]);
useEffect(() => getInitialState && getInitialState(valid), [getInitialState, valid]);
useEffect(() => setValidation(required ? !!fileList.length : true), [fileList, required]);
useEffect(() => {
if (Array.isArray(data)) {
if (data && data.length > 0) {
setIsBusy(true);
Promise.all([...data.map(file => getFileByUrl(file.path, file, isImageUpload, customHeaders))]).then(res => {
setFileList(res);
}).finally(() => setIsBusy(false));
} else {
setFileList([]);
}
}
}, [data, isImageUpload]);
const startUpload = useCallback((uploadedFiles, deletedFiles) => {
setIsBusy(true);
return new Promise((resolve, reject) => {
upload({
uploadedFiles,
deletedFiles
}).then(resolve).catch(reject).finally(() => setIsBusy(false));
});
}, [upload]);
const fileChangeHandler = useCallback((newList, del) => {
!isControlled && (!multiple || del) && setFileList(prev => maxFileCount >= prev.length ? newList : prev);
!isControlled && multiple && !del && setFileList(prev => maxFileCount > prev.length ? [newList[0], ...prev] : prev);
onChange({
value: newList
});
}, [isControlled, onChange]);
const checkFileValidation = useCallback(file => {
if (file.size) {
const {
isValidSize,
isValidType
} = isValidFile({
allTypesAccepted,
isImageUpload,
maxFileSize,
typesList,
file
});
if (showLocalErrors) {
const msg = isValidSize ? isValidType ? '' : typeErrorMsg.replace(typeListReplacer, typesList.join(', ')) : sizeErrorMsg.replace(maxFileSizeReplacer, maxFileSize);
setErrorMsg(msg);
}
return isValidSize && isValidType;
}
}, [allTypesAccepted, isImageUpload, maxFileSize, typesList, showLocalErrors, typeErrorMsg, sizeErrorMsg]);
const addFile = useCallback(async file => {
if (checkFileValidation(file)) {
const blobFile = await toBlobFile(file, isImageUpload);
const newList = maxFileCount ? [blobFile, ...fileList].slice(0, maxFileCount) : [blobFile, ...fileList];
if (immediatelyUploadAfterSelect && upload) {
startUpload(newList, deletedFileList).catch(error => {
setNotUploadedFileList([{
file: blobFile,
error
}, ...notUploadedFileList]);
}).finally(() => {
fileChangeHandler(newList, false);
});
} else {
fileChangeHandler(newList, false);
}
}
}, [checkFileValidation, isImageUpload, maxFileCount, fileList.length, immediatelyUploadAfterSelect, upload, startUpload, deletedFileList, notUploadedFileList, fileChangeHandler]);
const handleDrop = useCallback(e => {
stopEvent(e, true);
setDraggable(false);
const {
dataTransfer: {
files = []
}
} = e;
if (isActiveDrop && files.length) {
addFile(files[0]);
}
}, [isActiveDrop, addFile]);
const handleDragIn = useCallback(e => {
stopEvent(e, true);
e.dataTransfer.items.length && setDraggable(true);
}, []);
const handleDragOut = useCallback(e => {
stopEvent(e, true);
setDraggable(false);
}, []);
useEffect(() => {
const div = dropRef.current;
if (div && !isBusy) {
addDragEventListener(div, handleDragIn, handleDragOut, handleDrop);
return () => {
removeDragEventListener(div, handleDragIn, handleDragOut, handleDrop);
};
}
}, [handleDrop, dropRef.current, isBusy]);
const onUpload = useCallback(e => {
for (const file in e.target.files) addFile(e.target.files[file]);
e.target.value = null;
}, [addFile]);
const doUpload = useCallback(e => {
stopEvent(e, true);
if (upload && fileList.length) {
setNotUploadedFileList([]);
startUpload(fileList, deletedFileList).then(_ref2 => {
let {
fileErrors
} = _ref2;
fileErrors && setNotUploadedFileList([...fileErrors]);
}).catch(() => setNotUploadedFileList([...fileList]));
}
}, [upload, fileList, startUpload, deletedFileList]);
const deleteItemByIndex = useCallback(e => {
const {
index
} = e.currentTarget.dataset;
const newList = [...fileList];
newList.splice(index, 1);
if (data && data.find(file => file.id === (fileList[index] && fileList[index].id))) {
setDeletedFileList([...deletedFileList, fileList[index]]);
if (isImageUpload) {
deleteAction(fileList[index]);
}
}
fileChangeHandler(newList, true);
}, [fileList, data, fileChangeHandler, deletedFileList, isImageUpload, deleteAction]);
const uploadRefresh = useCallback(e => {
const {
index
} = e.currentTarget.dataset;
const file = fileList[index];
if (file && upload) {
setRefreshIndex(Number(index));
startUpload(file, deletedFileList).then(() => {
const newList = notUploadedFileList.filter(notUploaded => notUploaded.file !== file);
setNotUploadedFileList(newList);
}).finally(() => setRefreshIndex(null));
}
}, [startUpload, notUploadedFileList, fileList, upload, deletedFileList]);
const isBoxApperance = uploaderAppearance === uploaderConfig.uploaderAppearance[3];
const gridGap = isBoxApperance ? highGrid : lowGrid;
const isExistFile = !!fileList.length;
return /*#__PURE__*/React__default.createElement("div", _extends({
className: classnames('uploader-holder', "ua-".concat(uploaderAppearance), className)
}, restProps), !isBoxApperance && /*#__PURE__*/React__default.createElement("div", {
className: classnames('uploader-header', {
'only-child': !isExistFile
})
}, /*#__PURE__*/React__default.createElement(UploadView, {
appearance: uploaderAppearance,
immediatelyUploadAfterSelect: immediatelyUploadAfterSelect,
onUpload: onUpload,
ref: dropRef,
draggable: draggable,
icon: icon,
cornerRadius: cornerRadius,
isDisabled: isDisabled,
isBusy: isBusy,
chooseFileLabel: chooseFileLabel,
browseLabel: browseLabel,
startUploadLabel: startUploadLabel,
dropHereLabel: dropHereLabel,
loadingLabel: loadingLabel,
isValid: isValid,
typesList: typesList,
multiple: multiple
})), (isExistFile || isBoxApperance) && /*#__PURE__*/React__default.createElement(Row, {
padding: gridGap,
gutter: gridGap
}, fileList.map((file, index) => /*#__PURE__*/React__default.createElement(Col, _extends({}, uploaderConfig.gridColumnSize, {
key: index
}), /*#__PURE__*/React__default.createElement(UploadedItem, {
file: file,
index: index,
isBusy: isBusy,
onRetry: uploadRefresh,
retryIndex: refreshIndex,
showRemoveButton: showTrash,
onRemove: deleteItemByIndex,
uploadErrorText: uploadErrorText,
showResetButton: showResetButton,
metaDataHeaders: metaDataHeaders,
appearance: uploadedItemsAppearance,
showPreviewButton: showPreviewButton,
additionalContext: additionalContext,
showDownloadButton: showDownloadButton,
notUploadedFileList: notUploadedFileList,
customHeaders: customHeaders,
hideName: hideName
}))), isBoxApperance && /*#__PURE__*/React__default.createElement(Col, uploaderConfig.gridColumnSize, /*#__PURE__*/React__default.createElement(UploadView, {
appearance: uploadedItemsAppearance
}))), /*#__PURE__*/React__default.createElement("div", {
className: "uploader-footer"
}, (informationMessage || showLocalErrors && errorMsg) && /*#__PURE__*/React__default.createElement("div", {
className: classnames('information-message', {
'color-danger': !!errorMsg
})
}, errorMsg || informationMessage), !immediatelyUploadAfterSelect && isExistFile && uploaderAppearance !== uploaderConfig.uploaderAppearance[1] && /*#__PURE__*/React__default.createElement("div", {
className: "uploader-footer-button"
}, /*#__PURE__*/React__default.createElement(Button, {
onClick: doUpload,
disabled: isDisabled || isBusy,
cornerRadius: cornerRadius
}, startUploadLabel))));
}
Uploader.propTypes = {
/**
* Disable type check
*/
allTypesAccepted: PropTypes.bool,
/**
* Browse label text
*/
browseLabel: PropTypes.string,
/**
* Choose file label text
*/
chooseFileLabel: PropTypes.string,
/**
* Your custom className, for div
*/
className: PropTypes.string,
/**
* Button corner radius
*/
cornerRadius: 'smooth',
/**
* ExtendedInput corner radius
*/
inputCornerRadius: ExtendedInput.propTypes.cornerRadius,
/**
* Default data for loaded items. The data array should have:
* path - URL to file/image,
* name - file/image display name,
* id - unique identifier,
*/
data: PropTypes.arrayOf(PropTypes.shape({
path: PropTypes.string,
name: PropTypes.string,
id: PropTypes.number
})),
/**
* Delete action to process delete default data deleteAction((file: deletedFile) => void)
*/
deleteAction: PropTypes.func,
/**
* Drop here label text
*/
dropHereLabel: PropTypes.string,
/**
* Size error message. If in the string you write MAX_FILE_SIZE it will be replaced maxFileSize prop.
*/
sizeErrorMsg: PropTypes.string,
/**
* Type error message. If in the string you write TYPE_LIST it will be replaced typesList prop.
*/
typeErrorMsg: PropTypes.string,
getInitialState: PropTypes.func,
/**
* Upload holder icon
*/
icon: PropTypes.string,
/**
* Immediate upload after selecting or using the "Start Upload" button.
*/
immediatelyUploadAfterSelect: PropTypes.bool,
/**
* Information message text
*/
informationMessage: PropTypes.string,
/**
* Activation drugover
*/
isActiveDrop: PropTypes.bool,
/**
* Disable uploader
*/
isDisabled: PropTypes.bool,
/**
* Enable image upload mode
*/
isImageUpload: PropTypes.bool,
/**
* Loading label text
*/
loadingLabel: PropTypes.string,
/**
* Max upload file size in bytes
*/
maxFileSize: PropTypes.number,
/**
* File list changes handling onChange((files: fileList) => void);
*/
onChange: PropTypes.func,
/**
* Required file
*/
required: PropTypes.bool,
/**
* Show local validation errors
*/
showLocalErrors: PropTypes.bool,
/**
* Start upload label text
*/
startUploadLabel: PropTypes.string,
/**
* Array of upload item types
*/
typesList: PropTypes.arrayOf(PropTypes.string),
/**
* Upload file function, upload((files: {uploadedFiles, deletedFiles}) => Promise);
*/
upload: PropTypes.func,
/**
* Uploaded items appearance
*/
uploadedItemsAppearance: PropTypes.oneOf(uploaderConfig.uploadedItemsAppearance),
/**
* Uploader appearance
*/
uploaderAppearance: PropTypes.oneOf(uploaderConfig.uploaderAppearance),
/**
* Upload error text showing in tooltip
*/
uploadErrorText: PropTypes.string,
/**
* Maximum upload file count
*/
maxFileCount: PropTypes.number,
/**
* Control Uploader validation.
*/
isValid: PropTypes.bool,
/**
* Show/Hide trash icon
*/
showTrash: PropTypes.bool,
/**
* Show/Hide Reset icon
*/
showResetButton: PropTypes.bool,
/**
* Show/Hide Preview icon
*/
showPreviewButton: PropTypes.bool,
/**
* Show/Hide Download icon
*/
showDownloadButton: PropTypes.bool,
/**
* initialImages - an array of URL strings. Use to specify the initial value of the component.
*
* NOTE: previously, data property could be used to handle the component value. Now, instead
* of using entire image objects, you can use just URL strings with images and initialImages props
*/
initialImages: PropTypes.arrayOf(PropTypes.string),
/**
* images - an array of URL strings; required for a controlled component
*/
images: PropTypes.arrayOf(PropTypes.string),
/**
* change files size with any custom string.
*/
additionalContext: PropTypes.string,
/**
* multi file upload option.
*/
multiple: PropTypes.bool,
/**
* This is for fetch image for example through this prop you can pass token.
* Provide an Object that will spread in Request Headers:{...customHeaders} in second parameter for fetch function.
* For example { 'Content-Type': 'application/json'} it will convert fetch(URL,{headers{'Content-Type': 'application/json'}})
*/
customHeaders: PropTypes.object,
/**
* set true to hide image name from preview mode.
*/
hideName: PropTypes.bool,
/**
* metaDataHeaders is an object where type can be "LAST-MODIFIED" (for future requirement can be added new types) and
* formatter that returns callback function with 'last modified data string' parameter that can be formatted and returned.
* {
* type: "LAST-MODIFIED",
* formatter:(date)=>{return new Date(date).toLocaleDateString()}
* }
*/
metaDataHeaders: PropTypes.shape({
type: PropTypes.string,
formatter: PropTypes.func
})
};
Uploader.defaultProps = {
allTypesAccepted: true,
browseLabel: 'Browse',
chooseFileLabel: 'Upload File',
cornerRadius: 'smooth',
inputCornerRadius: ExtendedInput.defaultProps.cornerRadius,
dropHereLabel: 'Drop here',
sizeErrorMsg: "File must be smaller than ".concat(maxFileSizeReplacer, " bytes."),
typeErrorMsg: "You can only upload ".concat(typeListReplacer, " File."),
immediatelyUploadAfterSelect: true,
isActiveDrop: false,
isDisabled: false,
isImageUpload: false,
loadingLabel: 'Uploading...',
maxFileSize: 5000000,
required: false,
showTrash: true,
showDownloadButton: true,
showResetButton: true,
showPreviewButton: true,
showLocalErrors: false,
startUploadLabel: 'Start Upload',
typesList: [],
uploadedItemsAppearance: uploaderConfig.uploadedItemsAppearance[0],
uploaderAppearance: uploaderConfig.uploaderAppearance[0],
uploadErrorText: 'Upload Error',
onChange: noop,
isValid: true,
hideName: false
};
export { Uploader as default };