diff --git a/README.md b/README.md index 63d96de..12f1eda 100644 --- a/README.md +++ b/README.md @@ -56,13 +56,13 @@ Before you begin, make sure you have the following software installed: Using npm: ``` -npm install @canopassoftware/vue-file-upload +npm install @canopassoftware/react-file-upload ``` Using yarn: ``` -yarn add @canopassoftware/vue-file-upload +yarn add @canopassoftware/react-file-upload ``` --- @@ -192,16 +192,26 @@ To manage and preview files with this library, follow these steps: ```js // using CommonJS -const { SingleFileUpload, MultipleFileUpload } = require("@canopassoftware/vue-file-upload"); +const { SingleFileUpload, MultipleFileUpload } = require("@canopassoftware/react-file-upload"); OR // using esModules -import { SingleFileUpload, MultipleFileUpload } from "@canopassoftware/vue-file-upload"; +import { SingleFileUpload, MultipleFileUpload } from "@canopassoftware/react-file-upload"; ``` ### Creating custom UI with file preview - You can customize file uploading UI in inner part of component. +- The `file` containing `file` object with following keys, we will use this object to show preview. + + ```js + file = file: { + previewType: 'video', // type of the preview. like, file is image or video + previewUrl: 'data:image/jpeg;base64,/9j/D1AAAACRsdW1pAAAD...', // URL of the file preview + previewName: 'a152148640581.62d918f12a0b4.mp4', // preview file name + isDragging: false // you will get it `true` when you dragging the file on design + } + ``` ### Single File Upload Management @@ -210,7 +220,7 @@ import { SingleFileUpload, MultipleFileUpload } from "@canopassoftware/vue-file- import Image from "next/image"; import React, { useState } from "react"; -import { SingleFileUpload } from '@canopassoftware/vue-file-upload'; +import { SingleFileUpload } from '@canopassoftware/react-file-upload'; export default function App() { const [previewFileData, setPreviewFileData] = useState( @@ -222,6 +232,7 @@ export default function App() { } ); + // callback function const handleFileUploading = async (file: any) => { await new Promise((resolve) => setTimeout(resolve, 2000)); setPreviewFileData({ @@ -242,12 +253,66 @@ export default function App() { uploadBtn={"Save"} progressBtn={"Saving..."} > + ); } ``` +### Multiple File Upload Management + +```js +"use client"; + +import Image from "next/image"; +import React from "react"; +import MultipleFileUpload from "@canopassoftware/react-file-upload"; +import { StaticImageData } from "next/image"; + +export default function App() { + const uploadedFiles = [] as Array<{ + fileType: string; + fileUrl: string | StaticImageData; + fileName: string; + }>; + + // callback function + const handleFilesUploading = async (files: any) => { + const uploadedFiles = []; + + for (var i = 0; i < files.length; i++) { + uploadedFiles.push({ + fileType: "image", + fileUrl: images[i], + fileName: files[i].name, + }); + } + + await new Promise((resolve) => setTimeout(resolve, 5000)); + return uploadedFiles; + }; +``` + +```html +return ( +
+ + {(file: any) => ( + + )} + +
+ ); +} +``` + ## Contributing We welcome contributions from the community. To contribute to this project, please follow these guidelines: diff --git a/package-lock.json b/package-lock.json index cfec222..cb78834 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,8 +15,8 @@ }, "devDependencies": { "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", + "@types/react": "^18.2.37", + "@types/react-dom": "^18.2.15", "autoprefixer": "^10", "eslint": "^8", "eslint-config-next": "14.0.0", @@ -85,9 +85,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -108,9 +108,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", - "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", + "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -402,24 +402,24 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", - "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/prop-types": { - "version": "15.7.9", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", - "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==", + "version": "15.7.10", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.10.tgz", + "integrity": "sha512-mxSnDQxPqsZxmeShFH+uwQ4kO4gcJcGahjjMFeLbKE95IAZiiZyiEepGZjtXJ7hN/yfu0bu9xN2ajcU0JcxX6A==", "dev": true }, "node_modules/@types/react": { - "version": "18.2.33", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", - "integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", + "version": "18.2.37", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.37.tgz", + "integrity": "sha512-RGAYMi2bhRgEXT3f4B92WTohopH6bIXw05FuGlmJEnv/omEn190+QYEIYxIAuIBdKgboYYdVved2p1AxZVQnaw==", "dev": true, "dependencies": { "@types/prop-types": "*", @@ -428,30 +428,30 @@ } }, "node_modules/@types/react-dom": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz", - "integrity": "sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==", + "version": "18.2.15", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.15.tgz", + "integrity": "sha512-HWMdW+7r7MR5+PZqJF6YFNSCtjz1T0dsvo/f1BV6HkV+6erD/nA7wd9NM00KVG83zf2nJ7uATPO9ttdIPvi3gg==", "dev": true, "dependencies": { "@types/react": "*" } }, "node_modules/@types/scheduler": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz", - "integrity": "sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.6.tgz", + "integrity": "sha512-Vlktnchmkylvc9SnwwwozTv04L/e1NykF5vgoQ0XTmI8DD+wxfjQuHuvHS3p0r2jz2x2ghPs2h1FVeDirIteWA==", "dev": true }, "node_modules/@typescript-eslint/parser": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.0.tgz", - "integrity": "sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.10.0.tgz", + "integrity": "sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/typescript-estree": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/scope-manager": "6.10.0", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/typescript-estree": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4" }, "engines": { @@ -471,13 +471,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz", - "integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz", + "integrity": "sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0" + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -488,9 +488,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", - "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.10.0.tgz", + "integrity": "sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -501,13 +501,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz", - "integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz", + "integrity": "sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/types": "6.10.0", + "@typescript-eslint/visitor-keys": "6.10.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -528,12 +528,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", - "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz", + "integrity": "sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/types": "6.10.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -781,9 +781,9 @@ } }, "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", "dev": true }, "node_modules/asynciterator.prototype": { @@ -845,9 +845,9 @@ } }, "node_modules/axe-core": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.8.2.tgz", - "integrity": "sha512-/dlp0fxyM3R8YW7MFzaHWXrf4zzbr0vaYb23VBFCl83R7nWNPg/yaQw2Dc8jzCMmDVLhSdzH8MjrsuIUuvX+6g==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", + "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", "dev": true, "engines": { "node": ">=4" @@ -973,9 +973,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001558", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001558.tgz", - "integrity": "sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ==", + "version": "1.0.30001561", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001561.tgz", + "integrity": "sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==", "funding": [ { "type": "opencollective", @@ -1220,9 +1220,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.569", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz", - "integrity": "sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==", + "version": "1.4.579", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.579.tgz", + "integrity": "sha512-bJKvA+awBIzYR0xRced7PrQuRIwGQPpo6ZLP62GAShahU9fWpsNN2IP6BSP1BLDDSbxvBVRGAMWlvVVq3npmLA==", "dev": true }, "node_modules/emoji-regex": { @@ -1381,15 +1381,15 @@ } }, "node_modules/eslint": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", - "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", + "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.52.0", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.53.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -1594,27 +1594,27 @@ } }, "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", - "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", + "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", "dev": true, "dependencies": { - "@babel/runtime": "^7.20.7", - "aria-query": "^5.1.3", - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.6.2", - "axobject-query": "^3.1.1", + "@babel/runtime": "^7.23.2", + "aria-query": "^5.3.0", + "array-includes": "^3.1.7", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "=4.7.0", + "axobject-query": "^3.2.1", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.3", - "language-tags": "=1.0.5", + "es-iterator-helpers": "^1.0.15", + "hasown": "^2.0.0", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "semver": "^6.3.0" + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7" }, "engines": { "node": ">=4.0" @@ -1623,15 +1623,6 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-plugin-react": { "version": "7.33.2", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", @@ -1806,9 +1797,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -2143,15 +2134,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -2650,9 +2632,9 @@ } }, "node_modules/jiti": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.20.0.tgz", - "integrity": "sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", "dev": true, "bin": { "jiti": "bin/jiti.js" @@ -2736,12 +2718,15 @@ "dev": true }, "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", "dev": true, "dependencies": { - "language-subtag-registry": "~0.3.2" + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" } }, "node_modules/levn": { @@ -2877,9 +2862,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -3393,9 +3378,9 @@ } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.6.tgz", - "integrity": "sha512-2Xgb+GQlkPAUCFi3sV+NOYcSI5XgduvDBL2Zt/hwJudeKXkyvRS65c38SB0yb9UB40+1rL83I6m0RtlOQ8eHdg==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.7.tgz", + "integrity": "sha512-4v6uESAgwCni6YF6DwJlRaDjg9Z+al5zM4JfngcazMy4WEf/XkPS5TEQjbD+DZ5iNuG6RrKQLa/HuX2SYzC3kQ==", "dev": true, "engines": { "node": ">=14.21.3" @@ -3476,9 +3461,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -4428,9 +4413,9 @@ "dev": true }, "node_modules/yaml": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", - "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "dev": true, "engines": { "node": ">= 14" diff --git a/package.json b/package.json index e07146e..ed4eb92 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,8 @@ }, "devDependencies": { "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", + "@types/react": "^18.2.37", + "@types/react-dom": "^18.2.15", "autoprefixer": "^10", "eslint": "^8", "eslint-config-next": "14.0.0", diff --git a/src/app/page.tsx b/src/app/page.tsx index bceb54c..702ca2d 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,98 +1,103 @@ "use client"; import Image from "next/image"; -import React, { useState } from "react"; -import SingleFileUpload from "../components/singleFile"; +import React from "react"; +import MultipleFileUpload from "../components/multipleFileUpload"; import img from "../assets/images/example-img.jpg"; import { StaticImageData } from "next/image"; export default function App() { - const [previewFileData, setPreviewFileData] = useState( - {} as { - previewType: string; - previewUrl: string | StaticImageData | ArrayBuffer | null; - previewName: string; - isDragging: boolean; + const uploadedFiles = [] as Array<{ + fileType: string; + fileUrl: string | StaticImageData; + fileName: string; + }>; + + const handleFilesUploading = async (files: any) => { + const uploadedFiles = []; + + for (var i = 0; i < files.length; i++) { + uploadedFiles.push({ + fileType: "image", + fileUrl: img, + fileName: files[i].name, + }); } - ); - const handleFileUploading = async (file: any) => { - await new Promise((resolve) => setTimeout(resolve, 2000)); - setPreviewFileData({ - previewType: "image", - previewUrl: img, - previewName: file.name, - isDragging: false, - }); + await new Promise((resolve) => setTimeout(resolve, 5000)); + return uploadedFiles; }; return ( -
- + -
-
- {!previewFileData || !previewFileData.previewUrl ? ( -
); } diff --git a/src/assets/images/long-square-view.gif b/src/assets/images/long-square-view.gif deleted file mode 100644 index e45e980..0000000 Binary files a/src/assets/images/long-square-view.gif and /dev/null differ diff --git a/src/assets/images/multiple-file-uploading.gif b/src/assets/images/multiple-file-uploading.gif deleted file mode 100644 index abeb6bd..0000000 Binary files a/src/assets/images/multiple-file-uploading.gif and /dev/null differ diff --git a/src/assets/images/round-view.gif b/src/assets/images/round-view.gif deleted file mode 100644 index ded6d23..0000000 Binary files a/src/assets/images/round-view.gif and /dev/null differ diff --git a/src/assets/images/single-file-uploading.gif b/src/assets/images/single-file-uploading.gif deleted file mode 100644 index 475a1f3..0000000 Binary files a/src/assets/images/single-file-uploading.gif and /dev/null differ diff --git a/src/assets/images/square-view.gif b/src/assets/images/square-view.gif deleted file mode 100644 index fe5b2c4..0000000 Binary files a/src/assets/images/square-view.gif and /dev/null differ diff --git a/src/components/multipleFileUpload.tsx b/src/components/multipleFileUpload.tsx new file mode 100644 index 0000000..fc9066f --- /dev/null +++ b/src/components/multipleFileUpload.tsx @@ -0,0 +1,371 @@ +"use client"; + +import React, { useState, useRef } from "react"; +import pdfPreviewImg from "../assets/images/pdf-icon.png"; +import textPreviewImg from "../assets/images/text-icon.png"; +import audioPreviewImg from "../assets/images/music-icon.png"; +import apkPreviewImg from "../assets/images/apk-icon.png"; +import zipPreviewImg from "../assets/images/zip-icon.png"; +import sqlPreviewImg from "../assets/images/sql-icon.png"; +import filePreviewImg from "../assets/images/file-icon.png"; +import { StaticImageData } from "next/image"; + +export default function SingleFileUpload({ + accept = "", + uploadedFiles = [] as Array<{ + fileType: string; + fileUrl: string | StaticImageData; + fileName: string; + }>, + callback = {} as any, + uploadBtn = "Upload", + progressBtn = "Uploading...", + pdfPreview = pdfPreviewImg, + textPreview = textPreviewImg, + audioPreview = audioPreviewImg, + apkPreview = apkPreviewImg, + zipPreview = zipPreviewImg, + sqlPreview = sqlPreviewImg, + filePreview = filePreviewImg, + children = (file: { + previewType: string; + previewUrl: string; + previewName: string; + isDragging: boolean; + }) => React.ReactNode, +}) { + const defaultPreview = [] as Array<{ + previewType: string; + previewUrl: string | StaticImageData | ArrayBuffer | null; + previewName: string; + isDragging: boolean; + }>; + + const defaultFiles = [] as Array<{ + fileType: string; + fileUrl: string | StaticImageData; + fileName: string; + }>; + + if (uploadedFiles) { + for (var i = 0; i < uploadedFiles.length; i++) { + const obj = { + previewType: uploadedFiles[i].fileType, + previewUrl: uploadedFiles[i].fileUrl, + previewName: uploadedFiles[i].fileName, + isDragging: false, + }; + + defaultPreview.push(obj); + defaultFiles.push(uploadedFiles[i]); + } + } + + const [filesPreview, setFilesPreview] = useState(defaultPreview); + const [isUploading, setIsUploading] = useState(false); + const [files, setFiles] = useState(defaultFiles); + + let inputRefs = useRef([]); + const selectFile = (index: number) => { + if (isUploading) { + return; + } + if (inputRefs.current[index]) { + (inputRefs.current[index] as HTMLInputElement).click(); + } + }; + + const inputsRef = useRef(null); + const selectFiles = () => { + if (isUploading) { + return; + } + if (inputsRef.current) { + (inputsRef.current as HTMLInputElement).click(); + } + }; + + const add = ( + previewType: any, + previewUrl: string | StaticImageData | ArrayBuffer | null, + previewName: string, + isDragging: boolean, + file: any + ) => { + // add file + setFiles((files) => { + return [...files, file]; + }); + // add file preview + setFilesPreview((filesPreview) => { + return [ + ...filesPreview, + { + previewType: previewType, + previewUrl: previewUrl, + previewName: previewName, + isDragging: isDragging, + }, + ]; + }); + }; + + const update = ( + previewType: any, + previewUrl: string | StaticImageData | ArrayBuffer | null, + previewName: string, + isDragging: boolean, + file: any, + index: number + ) => { + // update file + setFiles((files) => { + const newFiles = [...files]; + newFiles[index] = file; + return newFiles; + }); + // update file preview + setFilesPreview((filesPreview) => { + const newFiles = [...filesPreview]; + newFiles[index].previewType = previewType; + newFiles[index].previewUrl = previewUrl; + newFiles[index].previewName = previewName; + newFiles[index].isDragging = isDragging; + return newFiles; + }); + }; + + const handleFileChange = (event: any, index: number, action: string) => { + const files = event.target.files; + for (var i = 0; i < files.length; i++) { + try { + previewFile(files[i], index + i, action); + } catch (error) { + console.error("error : ", error); + } + } + }; + + const previewFile = (file: any, index: number, action: string) => { + var obj = { + previewType: "image", + previewUrl: "" as string | StaticImageData | ArrayBuffer | null, + previewName: file.name, + isDragging: false, + }; + + const reader = new FileReader(); + reader.onload = () => { + if (file.type.startsWith("image/")) { + obj.previewUrl = reader.result; + } else if (file.type === "text/plain") { + obj.previewUrl = textPreview; + } else if (file.type === "application/pdf") { + obj.previewUrl = pdfPreview; + } else if (file.type.startsWith("video/")) { + obj.previewType = "video"; + obj.previewUrl = URL.createObjectURL(file); + } else if (file.type.startsWith("audio/")) { + obj.previewUrl = audioPreview; + } else if (file.type === "application/vnd.android.package-archive") { + obj.previewUrl = apkPreview; + } else if (file.type === "application/zip") { + obj.previewUrl = zipPreview; + } else if (file.type === "application/sql") { + obj.previewUrl = sqlPreview; + } else { + obj.previewUrl = filePreview; + } + obj.previewName = file.name; + + if (action == "reset") { + update( + obj.previewType, + obj.previewUrl, + obj.previewName, + obj.isDragging, + file, + index + ); + } else { + add( + obj.previewType, + obj.previewUrl, + obj.previewName, + obj.isDragging, + file + ); + } + }; + reader.onerror = (error) => { + console.error(`Error while reading file ${file.name}: ${error}`); + }; + reader.readAsDataURL(file); + }; + + const uploadingFunction = async () => { + if (isUploading) { + return; + } + setIsUploading(true); + + const gotFiles = await callback(files); + + setFilesPreview([]); + setFiles([]); + + if (gotFiles) { + for (var i = 0; i < gotFiles.length; i++) { + const obj = { + previewType: gotFiles[i].fileType, + previewUrl: gotFiles[i].fileUrl, + previewName: gotFiles[i].fileName, + isDragging: false, + }; + + setFilesPreview((filesPreview) => { + return [...filesPreview, obj]; + }); + + const file = gotFiles[i]; + + setFiles((files) => { + return [...files, file]; + }); + } + } + + setIsUploading(false); + }; + + const handleDragOver = (event: any, index: number, action: string) => { + if (isUploading) { + return; + } + event.preventDefault(); + if (action == "reset") { + filesPreview[index].isDragging = true; + } + }; + + const handleDragLeave = (event: any, index: number, action: string) => { + event.preventDefault(); + if (action == "reset") { + filesPreview[index].isDragging = false; + } + }; + + const handleDrop = (event: any, index: number, action: string) => { + if (isUploading) { + return; + } + event.preventDefault(); + if (action == "reset") { + filesPreview[index].isDragging = false; + } + const files = event.dataTransfer.files; + for (var i = 0; i < files.length; i++) { + try { + if (accept ? accept.split(", ").includes(files[i].type) : true) { + previewFile(files[i], index + i, action); + } + } catch (error) { + console.error("error : ", error); + } + } + }; + + const removeImg = (index: any) => { + if (isUploading) { + return; + } + // remove file + setFiles((files) => { + const newFiles = [...files]; + newFiles.splice(index, 1); + return newFiles; + }); + // remove file preview + setFilesPreview((filesPreview) => { + const newFiles = [...filesPreview]; + newFiles.splice(index, 1); + return newFiles; + }); + }; + + return ( +
+ {filesPreview.map((item: any, index: any) => ( +
+
selectFile(index)} + onDragOver={(event) => handleDragOver(event, index, "reset")} + onDragLeave={(event) => handleDragLeave(event, index, "reset")} + onDrop={(event) => handleDrop(event, index, "reset")} + > + {children(item)} + { + inputRefs.current[index] = element; + }} + className="hidden" + onChange={(event) => handleFileChange(event, index, "reset")} + /> +
+ +
+ ))} +
+
+ handleDragOver(event, filesPreview.length, "add") + } + onDragLeave={(event) => + handleDragLeave(event, filesPreview.length, "add") + } + onDrop={(event) => handleDrop(event, filesPreview.length, "add")} + > + {children({})} + + handleFileChange(event, filesPreview.length, "add") + } + multiple + /> +
+
+ +
+
+
+ ); +} diff --git a/src/components/singleFile.tsx b/src/components/singleFileUpload.tsx similarity index 100% rename from src/components/singleFile.tsx rename to src/components/singleFileUpload.tsx