@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
JavaScript
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