diff --git a/packages/web/categories/blob/react/package.json b/packages/web/categories/blob/react/package.json index 8465488..d5552e3 100644 --- a/packages/web/categories/blob/react/package.json +++ b/packages/web/categories/blob/react/package.json @@ -13,7 +13,8 @@ "pridepack" ], "dependencies": { - "@tesseract-design/web-base-blob": "link:../../../base/blob" + "@tesseract-design/web-base-blob": "link:../../../base/blob", + "@tesseract-design/web-base-button": "link:../../../base/button" }, "devDependencies": { "@testing-library/jest-dom": "^5.16.5", diff --git a/packages/web/categories/blob/react/src/components/FileSelectBox/index.tsx b/packages/web/categories/blob/react/src/components/FileSelectBox/index.tsx index 8ac3cbf..cc01151 100644 --- a/packages/web/categories/blob/react/src/components/FileSelectBox/index.tsx +++ b/packages/web/categories/blob/react/src/components/FileSelectBox/index.tsx @@ -1,4 +1,9 @@ import * as React from 'react'; +import * as ButtonBase from '@tesseract-design/web-base-button'; + +interface FileWithPreview extends File { + previewUrl?: string; +} export interface FileButtonProps extends Omit, 'size' | 'type' | 'style' | 'label' | 'list'> { /** @@ -33,6 +38,9 @@ export const FileSelectBox = React.forwardRef block = false, enhanced = false, hiddenLabel = false, + multiple = false, + onChange, + disabled = false, className: _className, placeholder: _placeholder, as: _as, @@ -40,44 +48,250 @@ export const FileSelectBox = React.forwardRef }: FileButtonProps, forwardedRef, ) => { + const [isEnhanced, setIsEnhanced] = React.useState(false); + const [selectedFiles, setSelectedFiles] = React.useState([] as Partial[]); const defaultRef = React.useRef(null); const ref = forwardedRef ?? defaultRef; + const handleAddFile = async (fileList: FileList) => { + const files = Array.from(fileList); + const fileResult = await Promise.all( + files.map((f) => new Promise>((resolve, reject) => { + if (f.type.startsWith('image/')) { + const reader = new FileReader(); + reader.addEventListener('error', () => { + reject(); + }); + + reader.addEventListener('load', (loadEvent) => { + const target = loadEvent.target as FileReader; + resolve({ + ...f, + name: f.name, + type: f.type, + size: f.size, + lastModified: f.lastModified, + previewUrl: target.result as string, + }); + }); + + reader.readAsDataURL(f); + return; + } + + resolve(f); + })) + ); + + setSelectedFiles(fileResult); + } + + const addFile: React.ChangeEventHandler = async (e) => { + if (!enhanced) { + onChange?.(e); + return; + } + + const currentTarget = e.currentTarget; + const fileList = currentTarget.files as FileList; + await handleAddFile(fileList); + onChange?.(e); + }; + + const deleteFiles: React.MouseEventHandler = () => { + if (typeof ref === 'object' && ref.current) { + ref.current.value = ''; + setSelectedFiles([]); + } + }; + + const cancelEvent = (e: React.DragEvent) => { + e.stopPropagation(); + e.preventDefault(); + } + + const handleDropZone: React.DragEventHandler = async (e) => { + cancelEvent(e); + const { dataTransfer } = e; + if (typeof ref === 'object' && ref.current) { + const { files } = dataTransfer; + ref.current.files = files; + await handleAddFile(files); + ref.current.dispatchEvent(new Event('change')); + } + } + + React.useEffect(() => { + setIsEnhanced(enhanced); + }, [enhanced]); + return ( -
-