@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
1 lines • 8.22 kB
Source Map (JSON)
{"version":3,"file":"Upload.mjs","names":["Upload","UploadIcon"],"sources":["../../../src/base-ui/Upload/Upload.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport { Upload as UploadIcon } from 'lucide-react';\nimport type { ChangeEvent, DragEvent, KeyboardEvent, MouseEvent, Ref } from 'react';\nimport { memo, useCallback, useRef, useState } from 'react';\n\nimport Icon from '@/Icon';\n\nimport { filterFilesByAccept } from './helpers';\nimport { styles } from './style';\nimport type { UploadProps } from './type';\n\nconst resolveAcceptedFiles = async (\n files: File[],\n beforeUpload: UploadProps['beforeUpload'],\n): Promise<File[]> => {\n if (!beforeUpload) return files;\n\n const accepted: File[] = [];\n for (const file of files) {\n let result: boolean | void;\n try {\n result = await beforeUpload(file, files);\n } catch {\n result = false;\n }\n if (result !== false) accepted.push(file);\n }\n return accepted;\n};\n\nconst Upload = memo<UploadProps>(\n ({\n accept,\n beforeUpload,\n children,\n className,\n description,\n directory,\n disabled,\n dragger,\n maxCount,\n multiple,\n onChange,\n onFiles,\n openFileDialogOnClick = true,\n ref,\n style,\n title,\n ...rest\n }) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const [isDragOver, setIsDragOver] = useState(false);\n\n const handleFiles = useCallback(\n async (rawFiles: File[]) => {\n const filtered = filterFilesByAccept(rawFiles, accept);\n const accepted = await resolveAcceptedFiles(filtered, beforeUpload);\n const sliced = maxCount ? accepted.slice(0, maxCount) : accepted;\n\n if (sliced.length === 0) return;\n\n onFiles?.(sliced);\n for (const file of sliced) onChange?.({ file, fileList: sliced });\n },\n [accept, beforeUpload, maxCount, onFiles, onChange],\n );\n\n const openDialog = useCallback(() => {\n if (disabled) return;\n inputRef.current?.click();\n }, [disabled]);\n\n const handleInputChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n const files = event.target.files ? [...event.target.files] : [];\n event.target.value = '';\n if (files.length > 0) void handleFiles(files);\n },\n [handleFiles],\n );\n\n const handleClick = useCallback(\n (event: MouseEvent) => {\n if (event.target === inputRef.current) return;\n if (disabled || !openFileDialogOnClick) return;\n openDialog();\n },\n [disabled, openFileDialogOnClick, openDialog],\n );\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (disabled || !openFileDialogOnClick) return;\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n openDialog();\n }\n },\n [disabled, openFileDialogOnClick, openDialog],\n );\n\n const handleDragOver = useCallback((event: DragEvent) => {\n event.preventDefault();\n }, []);\n\n const handleDragEnter = useCallback(\n (event: DragEvent) => {\n event.preventDefault();\n if (!disabled) setIsDragOver(true);\n },\n [disabled],\n );\n\n const handleDragLeave = useCallback((event: DragEvent) => {\n event.preventDefault();\n setIsDragOver(false);\n }, []);\n\n const handleDrop = useCallback(\n (event: DragEvent) => {\n event.preventDefault();\n setIsDragOver(false);\n if (disabled) return;\n const files = event.dataTransfer.files ? [...event.dataTransfer.files] : [];\n if (files.length > 0) void handleFiles(files);\n },\n [disabled, handleFiles],\n );\n\n const directoryProps: Record<string, string> = directory ? { webkitdirectory: '' } : {};\n\n const inputEl = (\n <input\n accept={accept}\n disabled={disabled}\n multiple={multiple}\n ref={inputRef}\n style={{ display: 'none' }}\n type=\"file\"\n onChange={handleInputChange}\n {...directoryProps}\n />\n );\n\n if (dragger) {\n return (\n <div\n aria-disabled={disabled}\n className={cx(styles.dragger, isDragOver && styles.draggerOver, className)}\n ref={ref as Ref<HTMLDivElement>}\n role=\"button\"\n style={style}\n tabIndex={disabled ? -1 : 0}\n onClick={handleClick}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {inputEl}\n {children ?? (\n <>\n <Icon className={styles.draggerIcon} icon={UploadIcon} size={24} />\n <b className={styles.draggerTitle}>\n {title ?? 'Click or drag file to this area to upload'}\n </b>\n {description && <span className={styles.draggerDescription}>{description}</span>}\n </>\n )}\n </div>\n );\n }\n\n return (\n <span\n aria-disabled={disabled}\n className={cx(styles.trigger, className)}\n ref={ref as Ref<HTMLSpanElement>}\n role=\"button\"\n style={style}\n tabIndex={disabled ? -1 : 0}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {inputEl}\n {children}\n </span>\n );\n },\n);\n\nUpload.displayName = 'Upload';\n\nexport default Upload;\n"],"mappings":"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"}