@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
148 lines (147 loc) • 4.34 kB
JavaScript
"use client";
import Icon from "../../Icon/Icon.mjs";
import { filterFilesByAccept } from "./helpers.mjs";
import { styles } from "./style.mjs";
import { memo, useCallback, useRef, useState } from "react";
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
import { cx } from "antd-style";
import { Upload } from "lucide-react";
//#region src/base-ui/Upload/Upload.tsx
const resolveAcceptedFiles = async (files, beforeUpload) => {
if (!beforeUpload) return files;
const accepted = [];
for (const file of files) {
let result;
try {
result = await beforeUpload(file, files);
} catch {
result = false;
}
if (result !== false) accepted.push(file);
}
return accepted;
};
const Upload$1 = memo(({ accept, beforeUpload, children, className, description, directory, disabled, dragger, maxCount, multiple, onChange, onFiles, openFileDialogOnClick = true, ref, style, title, ...rest }) => {
const inputRef = useRef(null);
const [isDragOver, setIsDragOver] = useState(false);
const handleFiles = useCallback(async (rawFiles) => {
const filtered = filterFilesByAccept(rawFiles, accept);
const accepted = await resolveAcceptedFiles(filtered, beforeUpload);
const sliced = maxCount ? accepted.slice(0, maxCount) : accepted;
if (sliced.length === 0) return;
onFiles?.(sliced);
for (const file of sliced) onChange?.({
file,
fileList: sliced
});
}, [
accept,
beforeUpload,
maxCount,
onFiles,
onChange
]);
const openDialog = useCallback(() => {
if (disabled) return;
inputRef.current?.click();
}, [disabled]);
const handleInputChange = useCallback((event) => {
const files = event.target.files ? [...event.target.files] : [];
event.target.value = "";
if (files.length > 0) handleFiles(files);
}, [handleFiles]);
const handleClick = useCallback((event) => {
if (event.target === inputRef.current) return;
if (disabled || !openFileDialogOnClick) return;
openDialog();
}, [
disabled,
openFileDialogOnClick,
openDialog
]);
const handleKeyDown = useCallback((event) => {
if (disabled || !openFileDialogOnClick) return;
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
openDialog();
}
}, [
disabled,
openFileDialogOnClick,
openDialog
]);
const handleDragOver = useCallback((event) => {
event.preventDefault();
}, []);
const handleDragEnter = useCallback((event) => {
event.preventDefault();
if (!disabled) setIsDragOver(true);
}, [disabled]);
const handleDragLeave = useCallback((event) => {
event.preventDefault();
setIsDragOver(false);
}, []);
const handleDrop = useCallback((event) => {
event.preventDefault();
setIsDragOver(false);
if (disabled) return;
const files = event.dataTransfer.files ? [...event.dataTransfer.files] : [];
if (files.length > 0) handleFiles(files);
}, [disabled, handleFiles]);
const inputEl = /* @__PURE__ */ jsx("input", {
accept,
disabled,
multiple,
ref: inputRef,
style: { display: "none" },
type: "file",
onChange: handleInputChange,
...directory ? { webkitdirectory: "" } : {}
});
if (dragger) return /* @__PURE__ */ jsxs("div", {
"aria-disabled": disabled,
className: cx(styles.dragger, isDragOver && styles.draggerOver, className),
ref,
role: "button",
style,
tabIndex: disabled ? -1 : 0,
onClick: handleClick,
onDragEnter: handleDragEnter,
onDragLeave: handleDragLeave,
onDragOver: handleDragOver,
onDrop: handleDrop,
onKeyDown: handleKeyDown,
...rest,
children: [inputEl, children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [
/* @__PURE__ */ jsx(Icon, {
className: styles.draggerIcon,
icon: Upload,
size: 24
}),
/* @__PURE__ */ jsx("b", {
className: styles.draggerTitle,
children: title ?? "Click or drag file to this area to upload"
}),
description && /* @__PURE__ */ jsx("span", {
className: styles.draggerDescription,
children: description
})
] })]
});
return /* @__PURE__ */ jsxs("span", {
"aria-disabled": disabled,
className: cx(styles.trigger, className),
ref,
role: "button",
style,
tabIndex: disabled ? -1 : 0,
onClick: handleClick,
onKeyDown: handleKeyDown,
...rest,
children: [inputEl, children]
});
});
Upload$1.displayName = "Upload";
//#endregion
export { Upload$1 as default };
//# sourceMappingURL=Upload.mjs.map