UNPKG

@veracity/vui

Version:

Veracity UI is a React component library crafted for use within Veracity applications and pages. Based on Styled Components and @xstyled.

110 lines (108 loc) 3.74 kB
import { cs } from "../utils/styles.js"; import { omitThemingProps, useStyleConfig } from "../core/theme.js"; import styled from "../core/styled.js"; import vui from "../core/vui.js"; import { Icon } from "../icon/icon.js"; import { T } from "../t/t.js"; import { useRef } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; //#region src/dragAndDrop/dragAndDrop.tsx const defaultIcon = "falCloudUpload"; const defaultText = "Click or drag files to this area"; const inputType = "file"; const DragAndDropBase = styled.labelBox` display: flex; min-width: 0; transition-duration: normal; justify-content: center; `; /** Prepares uploading files by selecting or dragging. */ const DragAndDrop = vui((props, ref) => { const { accept, className, icon = defaultIcon, selectFolderOnClick, selectFolderOnDrop, onFilesAdded, multiple = true, text = defaultText, children, disabled, ...rest } = omitThemingProps(props); const fileInputRef = useRef(null); const styles = useStyleConfig("DragAndDrop", props); const processFiles = (files) => Array.from(files).map((file) => file); const handleFileInput = (e) => { e.preventDefault(); if (disabled) return void 0; const files = processFiles(e?.currentTarget?.files); if (files?.length) { onFilesAdded?.(files); e.currentTarget.type = ""; e.currentTarget.type = inputType; } }; const getFilesWebkitDataTransferItems = (dataTransferItems) => { const traverseFileTreePromise = (item, path = "") => new Promise((resolve) => { if (item.isFile) item.file((file) => { file.filepath = path + file.name; files.push(file); resolve([file]); }); else if (item.isDirectory) { const dirEntry = item; dirEntry.createReader().readEntries((entries) => { const entriesPromises = entries.map((entry) => traverseFileTreePromise(entry, path + dirEntry.name + "/")); resolve(Promise.all(entriesPromises).then((entries) => [].concat(...entries))); }); } }); const files = []; return new Promise((resolve, reject) => { const entriesPromises = []; for (let i = 0; i < dataTransferItems.length; i++) { const item = dataTransferItems[i].webkitGetAsEntry(); if (item) entriesPromises.push(traverseFileTreePromise(item)); } Promise.all(entriesPromises).then(() => resolve(files)).catch(reject); }); }; const handleDrop = (e) => { e.preventDefault(); if (disabled) return void 0; if (selectFolderOnDrop) { const items = e.dataTransfer.items; getFilesWebkitDataTransferItems(items).then((files) => files?.length && onFilesAdded?.(files)); return; } const files = e.dataTransfer?.files ? processFiles(e.dataTransfer.files) : []; if (files?.length) onFilesAdded?.(files); }; return /* @__PURE__ */ jsxs(DragAndDropBase, { className: cs("vui-drag-and-drop", className), cursor: disabled ? "not-allowed" : "pointer", onDragEnter: (e) => e.preventDefault(), onDragOver: (e) => e.preventDefault(), onDrop: (e) => handleDrop(e), opacity: disabled ? .5 : 1, p: 5, pointerEvents: disabled ? "none" : "auto", ref, ...styles, ...rest, children: [children || /* @__PURE__ */ jsxs(T, { display: "flex", children: [/* @__PURE__ */ jsx(Icon, { mr: 1, name: icon }), text] }), /* @__PURE__ */ jsx("input", { accept, className: "vui-drag-and-drop-hidden-input", multiple, onChange: handleFileInput, ref: fileInputRef, style: { display: "none" }, type: inputType, ...selectFolderOnClick && { webkitdirectory: "true", directory: "true" } })] }); }); DragAndDrop.displayName = "DragAndDrop"; //#endregion export { DragAndDrop, DragAndDrop as default }; globalThis.__vuiVersion__ = "5.3.1" //# sourceMappingURL=dragAndDrop.js.map