diff --git a/bun.lock b/bun.lock index 5d472fd5..0b6e38d2 100644 --- a/bun.lock +++ b/bun.lock @@ -21,8 +21,8 @@ }, "devDependencies": { "@testing-library/jest-dom": "^6.0.0", - "@testing-library/react": "^14.0.0", - "@testing-library/user-event": "^14.4.3", + "@testing-library/react": "^16.3.2", + "@testing-library/user-event": "^14.6.1", "@types/bun": "^1.3.14", "@types/node": "^25", "@types/react": "^19", @@ -247,7 +247,7 @@ "@testing-library/jest-dom": ["@testing-library/jest-dom@6.9.1", "", { "dependencies": { "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", "css.escape": "^1.5.1", "dom-accessibility-api": "^0.6.3", "picocolors": "^1.1.1", "redent": "^3.0.0" } }, "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA=="], - "@testing-library/react": ["@testing-library/react@14.3.1", "", { "dependencies": { "@babel/runtime": "^7.12.5", "@testing-library/dom": "^9.0.0", "@types/react-dom": "^18.0.0" }, "peerDependencies": { "react": "^18.0.0", "react-dom": "^18.0.0" } }, "sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ=="], + "@testing-library/react": ["@testing-library/react@16.3.2", "", { "dependencies": { "@babel/runtime": "^7.12.5" }, "peerDependencies": { "@testing-library/dom": "^10.0.0", "@types/react": "^18.0.0 || ^19.0.0", "@types/react-dom": "^18.0.0 || ^19.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g=="], "@testing-library/user-event": ["@testing-library/user-event@14.6.1", "", { "peerDependencies": { "@testing-library/dom": ">=7.21.4" } }, "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw=="], @@ -1093,8 +1093,6 @@ "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="], - "@testing-library/react/@types/react-dom": ["@types/react-dom@18.3.7", "", { "peerDependencies": { "@types/react": "^18.0.0" } }, "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ=="], - "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], "@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], diff --git a/src/components/FileUpload.tsx b/src/components/FileUpload.tsx index f94c17ef..acbccadd 100644 --- a/src/components/FileUpload.tsx +++ b/src/components/FileUpload.tsx @@ -9,6 +9,7 @@ import { MAX_FILE_SIZE, WARNING_FILE_SIZE } from "@/lib/types"; interface Props { onFileSelect: (file: File | null) => void; + onMultipleFileSelect?: (files: FileList | null) => void; currentFile: File | null; fileError: string; duration: number; @@ -16,6 +17,7 @@ interface Props { export default function FileUpload({ onFileSelect, + onMultipleFileSelect, currentFile, fileError, duration, @@ -114,44 +116,60 @@ export default function FileUpload({ // ── Drop zone (inner) handler ───────────────────────── const handleDrop = (e: React.DragEvent) => { - e.preventDefault(); - setDragging(false); - const file = e.dataTransfer.files?.[0]; - if (file) handleFile(file); - }; + e.preventDefault(); + setDragging(false); + + const files = e.dataTransfer.files; + + if (!files?.length) return; + + if (files.length === 1 && files[0]) { + handleFile(files[0]); + } + + onMultipleFileSelect?.(files); +}; // ── File info (shown after upload) ─────────────────── - const FileInfo = () => ( -
+ {currentFile?.name} +
+ + {currentFile && ( + + {currentFile.name.includes(".") + ? currentFile.name.split(".").pop() + : "VIDEO"} + + )}- {currentFile?.name} -
- {currentFile && ( - - {currentFile.name.includes(".") - ? currentFile.name.split(".").pop() - : "VIDEO"} - - )} -{formatBytes(currentFile?.size ?? 0)}
-- {duration > 0 - ? `Duration: ${formatDuration(duration)}` - : "Loading duration..."} -
-{formatBytes(currentFile?.size ?? 0)}
+ ++ {duration > 0 + ? `Duration: ${formatDuration(duration)}` + : "Loading duration..."} +
- Supports: MP4, MOV, AVI, MKV, WebM, and most video formats -
- - {fileError && ( -{fileError}
- )} - - { - const f = e.target.files?.[0]; - if (f) handleFile(f); - }} - /> -+ Supports: MP4, MOV, AVI, MKV, WebM, and most video formats +
+ +{fileError && ( ++ {fileError} +
+)} + + { + onMultipleFileSelect?.(e.target.files) + }} + /> ++
Supports: MP4, MOV, AVI, MKV, WebM, and most video formats up to 2GB
{fileError && ({fileError}
)} -