{"_id":"@alekpr/react-image-crop-uploader","_rev":"9-6188a039660efb948f2dc288f4333bb6","name":"@alekpr/react-image-crop-uploader","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@alekpr/react-image-crop-uploader","version":"1.0.0","keywords":["react","image","upload","crop","cropping","modal","ui"],"author":{"name":"Your Name"},"license":"MIT","_id":"@alekpr/react-image-crop-uploader@1.0.0","maintainers":[{"name":"alekpr","email":"alek.pr@gmail.com"}],"homepage":"https://github.com/alekpr/react-image-crop-uploader#readme","bugs":{"url":"https://github.com/alekpr/react-image-crop-uploader/issues"},"dist":{"shasum":"66362839fa34fd60d9849b355fa2ddf1358e8cc7","tarball":"https://registry.npmjs.org/@alekpr/react-image-crop-uploader/-/react-image-crop-uploader-1.0.0.tgz","fileCount":36,"integrity":"sha512-8JQmnlrXfDAGZ5moLB6HVb2UWfFG5hMFDl/QiQmK7nPaKBqYT3WR2qIFqzgAIxShHHBQvNJUYuVdRoWUBdkZog==","signatures":[{"sig":"MEYCIQCy+yn8rHqDvFGTYEGGxW8EgU3x9nt0GHIlw0Rx18OaZAIhAPTctc8VBT0B2T455RoBh7SlQHx3fV/laU+3yBad7buf","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":102431},"main":"./dist/index.cjs.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs.js"}},"gitHead":"b4073aa225b6235295634ca25e86b861a62203ba","scripts":{"dev":"vite","lint":"eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0","test":"jest","build":"tsc && vite build","prepare":"husky","preview":"vite preview","lint:fix":"eslint src --ext ts,tsx --fix","storybook":"storybook dev -p 6006","test:watch":"jest --watch","test:coverage":"jest --coverage","build-storybook":"storybook build"},"_npmUser":{"name":"alekpr","email":"alek.pr@gmail.com"},"repository":{"url":"git+https://github.com/alekpr/react-image-crop-uploader.git","type":"git"},"_npmVersion":"10.9.2","description":"A comprehensive React image upload component with modal-based cropping capabilities","directories":{},"_nodeVersion":"22.14.0","dependencies":{"react-easy-crop":"^5.5.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","vite":"^6.0.9","husky":"^9.1.7","jsdom":"^25.0.1","eslint":"^9.18.0","postcss":"^8.5.6","ts-jest":"^29.2.5","ts-node":"^10.9.2","storybook":"^8.6.14","typescript":"^5.7.3","@types/jest":"^29.5.14","lint-staged":"^16.1.4","@types/react":"^18.3.18","vite-plugin-dts":"^4.5.0","@types/react-dom":"^18.3.5","@vitejs/plugin-react":"^4.3.4","@storybook/react-vite":"^8.6.14","@storybook/addon-links":"^8.6.14","@testing-library/react":"^16.3.0","jest-environment-jsdom":"^30.0.5","@testing-library/jest-dom":"^6.6.4","@typescript-eslint/parser":"^8.21.0","eslint-plugin-react-hooks":"^5.1.0","@storybook/addon-essentials":"^8.6.14","@storybook/addon-onboarding":"^8.6.14","eslint-plugin-react-refresh":"^0.4.16","@storybook/addon-interactions":"^8.6.14","@typescript-eslint/eslint-plugin":"^8.21.0"},"peerDependencies":{"react":"^17.0.0 || ^18.0.0","react-dom":"^17.0.0 || ^18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react-image-crop-uploader_1.0.0_1754290816062_0.5653396844926026","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@alekpr/react-image-crop-uploader","version":"1.0.1","keywords":["react","image","upload","crop","cropping","modal","ui"],"author":{"name":"alekpr","email":"alek.pr@gmail.com"},"license":"MIT","_id":"@alekpr/react-image-crop-uploader@1.0.1","maintainers":[{"name":"alekpr","email":"alek.pr@gmail.com"}],"homepage":"https://github.com/alekpr/react-image-crop-uploader#readme","bugs":{"url":"https://github.com/alekpr/react-image-crop-uploader/issues"},"dist":{"shasum":"1d07e4d9305405d5202e53b92b35d28a1843aca3","tarball":"https://registry.npmjs.org/@alekpr/react-image-crop-uploader/-/react-image-crop-uploader-1.0.1.tgz","fileCount":36,"integrity":"sha512-x2YwrBxAC/j1PxH09wN+BFjxnI4CPh5S/Srv1LEIfKUDUnaI4U+B9rHO/sqkxVVWApDZowVUwgclz3FFgtcCYg==","signatures":[{"sig":"MEYCIQDbMi8JBgciuZ1MiDK3rTDI4t9CzeHtyyDaXpSlrONrtwIhAPc7ndHItVaui9nt0ihoQ0Jnak/YS9UMw6fDFVC35elH","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":103290},"main":"./dist/index.cjs.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs.js"}},"gitHead":"8a6b591d4cd69c4a920c683cfdd6a7b004ecb372","scripts":{"dev":"vite","lint":"eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0","test":"jest","build":"tsc && vite build","prepare":"husky","preview":"vite preview","lint:fix":"eslint src --ext ts,tsx --fix","storybook":"storybook dev -p 6006","test:watch":"jest --watch","test:coverage":"jest --coverage","build-storybook":"storybook build"},"_npmUser":{"name":"alekpr","email":"alek.pr@gmail.com"},"repository":{"url":"git+https://github.com/alekpr/react-image-crop-uploader.git","type":"git"},"_npmVersion":"10.9.2","description":"A comprehensive React image upload component with modal-based cropping capabilities","directories":{},"_nodeVersion":"22.14.0","dependencies":{"react-easy-crop":"^5.5.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","vite":"^6.0.9","husky":"^9.1.7","jsdom":"^25.0.1","eslint":"^9.18.0","postcss":"^8.5.6","ts-jest":"^29.2.5","ts-node":"^10.9.2","storybook":"^8.6.14","typescript":"^5.7.3","@types/jest":"^29.5.14","lint-staged":"^16.1.4","@types/react":"^18.3.18","vite-plugin-dts":"^4.5.0","@types/react-dom":"^18.3.5","@vitejs/plugin-react":"^4.3.4","@storybook/react-vite":"^8.6.14","@storybook/addon-links":"^8.6.14","@testing-library/react":"^16.3.0","jest-environment-jsdom":"^30.0.5","@testing-library/jest-dom":"^6.6.4","@typescript-eslint/parser":"^8.21.0","eslint-plugin-react-hooks":"^5.1.0","@storybook/addon-essentials":"^8.6.14","@storybook/addon-onboarding":"^8.6.14","eslint-plugin-react-refresh":"^0.4.16","@storybook/addon-interactions":"^8.6.14","@typescript-eslint/eslint-plugin":"^8.21.0"},"peerDependencies":{"react":"^17.0.0 || ^18.0.0","react-dom":"^17.0.0 || ^18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react-image-crop-uploader_1.0.1_1754291514262_0.5262934938421637","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@alekpr/react-image-crop-uploader","version":"1.0.2","keywords":["react","image","upload","crop","cropping","modal","ui"],"author":{"name":"alekpr","email":"alek.pr@gmail.com"},"license":"MIT","_id":"@alekpr/react-image-crop-uploader@1.0.2","maintainers":[{"name":"alekpr","email":"alek.pr@gmail.com"}],"homepage":"https://github.com/alekpr/react-image-crop-uploader#readme","bugs":{"url":"https://github.com/alekpr/react-image-crop-uploader/issues"},"dist":{"shasum":"a025381b3054961ab62125bb3e951185b61c065d","tarball":"https://registry.npmjs.org/@alekpr/react-image-crop-uploader/-/react-image-crop-uploader-1.0.2.tgz","fileCount":36,"integrity":"sha512-d0WvvgowKh5IXD2F/VxOlfRYbPbHwmLv8AIWN0bDI9T5Zt8/hYiWkdXgopFDCnxxfjFp+65pbAf/ZLOPn9eibg==","signatures":[{"sig":"MEUCIQCeo9PmW0xvTaB9n7ROWia7TRBOQ/PsZC/iQu3jRYa41QIgcFlGQF651xDSdULxGpJYJrjR1vE588QHLPBjyvVLqO8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":103554},"main":"./dist/index.cjs.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs.js"},"./style.css":"./dist/react-image-crop-uploader.css","./dist/react-image-crop-uploader.css":"./dist/react-image-crop-uploader.css"},"gitHead":"c8c5f51638cdd3b905536f175f8fbb35752bd107","scripts":{"dev":"vite","lint":"eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0","test":"jest","build":"tsc && vite build","prepare":"husky","preview":"vite preview","lint:fix":"eslint src --ext ts,tsx --fix","storybook":"storybook dev -p 6006","test:watch":"jest --watch","test:coverage":"jest --coverage","build-storybook":"storybook build"},"_npmUser":{"name":"alekpr","email":"alek.pr@gmail.com"},"repository":{"url":"git+https://github.com/alekpr/react-image-crop-uploader.git","type":"git"},"_npmVersion":"10.9.2","description":"A comprehensive React image upload component with modal-based cropping capabilities","directories":{},"_nodeVersion":"22.14.0","dependencies":{"react-easy-crop":"^5.5.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","vite":"^6.0.9","husky":"^9.1.7","jsdom":"^25.0.1","eslint":"^9.18.0","postcss":"^8.5.6","ts-jest":"^29.2.5","ts-node":"^10.9.2","storybook":"^8.6.14","typescript":"^5.7.3","@types/jest":"^29.5.14","lint-staged":"^16.1.4","@types/react":"^18.3.18","vite-plugin-dts":"^4.5.0","@types/react-dom":"^18.3.5","@vitejs/plugin-react":"^4.3.4","@storybook/react-vite":"^8.6.14","@storybook/addon-links":"^8.6.14","@testing-library/react":"^16.3.0","jest-environment-jsdom":"^30.0.5","@testing-library/jest-dom":"^6.6.4","@typescript-eslint/parser":"^8.21.0","eslint-plugin-react-hooks":"^5.1.0","@storybook/addon-essentials":"^8.6.14","@storybook/addon-onboarding":"^8.6.14","eslint-plugin-react-refresh":"^0.4.16","@storybook/addon-interactions":"^8.6.14","@typescript-eslint/eslint-plugin":"^8.21.0"},"peerDependencies":{"react":"^17.0.0 || ^18.0.0","react-dom":"^17.0.0 || ^18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react-image-crop-uploader_1.0.2_1754300322284_0.6435732121204243","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@alekpr/react-image-crop-uploader","version":"1.0.3","keywords":["react","image","upload","crop","cropping","modal","ui"],"author":{"name":"alekpr","email":"alek.pr@gmail.com"},"license":"MIT","_id":"@alekpr/react-image-crop-uploader@1.0.3","maintainers":[{"name":"alekpr","email":"alek.pr@gmail.com"}],"homepage":"https://github.com/alekpr/react-image-crop-uploader#readme","bugs":{"url":"https://github.com/alekpr/react-image-crop-uploader/issues"},"dist":{"shasum":"8fb409615e130a47311deed259ad3cf4760f83fc","tarball":"https://registry.npmjs.org/@alekpr/react-image-crop-uploader/-/react-image-crop-uploader-1.0.3.tgz","fileCount":36,"integrity":"sha512-w5UGTQCJM6yZgYFGmokR5yT25/Cjo8JdH3SFgE/wbvlKzDITB/ZcLxfWNwI+ZmVlSKfQJheiInhs6S8KJD2c2Q==","signatures":[{"sig":"MEQCIH9hyk85wiUEFxK9wMlrjTbKEuUabQIF4SxADtDkkTjJAiBPZJky9oNaC+n/MI+yNSHdthCjka1RR8gVf9OYpGg4/Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":106982},"main":"./dist/index.cjs.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs.js"},"./style.css":"./dist/react-image-crop-uploader.css","./dist/react-image-crop-uploader.css":"./dist/react-image-crop-uploader.css"},"gitHead":"08e44f3ec5991b95c1bd8cb3f18669e7397c7a46","scripts":{"dev":"vite","lint":"eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0","test":"jest","build":"tsc && vite build","prepare":"husky","preview":"vite preview","lint:fix":"eslint src --ext ts,tsx --fix","storybook":"storybook dev -p 6006","test:watch":"jest --watch","test:coverage":"jest --coverage","build-storybook":"storybook build"},"_npmUser":{"name":"alekpr","email":"alek.pr@gmail.com"},"repository":{"url":"git+https://github.com/alekpr/react-image-crop-uploader.git","type":"git"},"_npmVersion":"10.9.2","description":"A comprehensive React image upload component with modal-based cropping capabilities","directories":{},"_nodeVersion":"22.14.0","dependencies":{"react-easy-crop":"^5.5.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","vite":"^6.0.9","husky":"^9.1.7","jsdom":"^25.0.1","eslint":"^9.18.0","postcss":"^8.5.6","ts-jest":"^29.2.5","ts-node":"^10.9.2","storybook":"^8.6.14","typescript":"^5.7.3","@types/jest":"^29.5.14","lint-staged":"^16.1.4","@types/react":"^18.3.18","vite-plugin-dts":"^4.5.0","@types/react-dom":"^18.3.5","@vitejs/plugin-react":"^4.3.4","@storybook/react-vite":"^8.6.14","@storybook/addon-links":"^8.6.14","@testing-library/react":"^16.3.0","jest-environment-jsdom":"^30.0.5","@testing-library/jest-dom":"^6.6.4","@typescript-eslint/parser":"^8.21.0","eslint-plugin-react-hooks":"^5.1.0","@storybook/addon-essentials":"^8.6.14","@storybook/addon-onboarding":"^8.6.14","eslint-plugin-react-refresh":"^0.4.16","@storybook/addon-interactions":"^8.6.14","@typescript-eslint/eslint-plugin":"^8.21.0"},"peerDependencies":{"react":"^17.0.0 || ^18.0.0","react-dom":"^17.0.0 || ^18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react-image-crop-uploader_1.0.3_1754320051239_0.033393575784227636","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@alekpr/react-image-crop-uploader","version":"1.0.4","keywords":["react","image","upload","crop","cropping","modal","ui"],"author":{"name":"alekpr","email":"alek.pr@gmail.com"},"license":"MIT","_id":"@alekpr/react-image-crop-uploader@1.0.4","maintainers":[{"name":"alekpr","email":"alek.pr@gmail.com"}],"homepage":"https://github.com/alekpr/react-image-crop-uploader#readme","bugs":{"url":"https://github.com/alekpr/react-image-crop-uploader/issues"},"dist":{"shasum":"6e460e52e1f2d5fbe16b54f8f4ea4179914b02c5","tarball":"https://registry.npmjs.org/@alekpr/react-image-crop-uploader/-/react-image-crop-uploader-1.0.4.tgz","fileCount":37,"integrity":"sha512-QxWErRO7XHDYsStjKV3CG7s+DCO3zZLvPvoih0OqJcUd75WRY7RgcWlryrFHleRNqs8jFk9GR5v7tZywMRB+Gw==","signatures":[{"sig":"MEYCIQCH833Lxpcf9LugS+BSq/nRKgp2HekRQQq2m2RsZT9VrgIhAJuRjY8bbi4cA0+9dwE21bhjxtHKz/dNJ1xXVL2s+IFZ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":108454},"main":"./dist/index.cjs.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs.js"},"./style.css":"./dist/react-image-crop-uploader.css","./dist/react-image-crop-uploader.css":"./dist/react-image-crop-uploader.css"},"gitHead":"5915c3fad1de38586340c972e2af446779ce8b03","scripts":{"dev":"vite","lint":"eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0","test":"jest","build":"tsc && vite build","prepare":"husky","preview":"vite preview","lint:fix":"eslint src --ext ts,tsx --fix","storybook":"storybook dev -p 6006","test:watch":"jest --watch","test:coverage":"jest --coverage","build-storybook":"storybook build"},"_npmUser":{"name":"alekpr","email":"alek.pr@gmail.com"},"repository":{"url":"git+https://github.com/alekpr/react-image-crop-uploader.git","type":"git"},"_npmVersion":"10.9.2","description":"A comprehensive React image upload component with modal-based cropping capabilities","directories":{},"_nodeVersion":"22.14.0","dependencies":{"react-easy-crop":"^5.5.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","vite":"^6.0.9","husky":"^9.1.7","jsdom":"^25.0.1","eslint":"^9.18.0","postcss":"^8.5.6","ts-jest":"^29.2.5","ts-node":"^10.9.2","storybook":"^8.6.14","typescript":"^5.7.3","@types/jest":"^29.5.14","lint-staged":"^16.1.4","@types/react":"^18.3.18","vite-plugin-dts":"^4.5.0","@types/react-dom":"^18.3.5","@vitejs/plugin-react":"^4.3.4","@storybook/react-vite":"^8.6.14","@storybook/addon-links":"^8.6.14","@testing-library/react":"^16.3.0","jest-environment-jsdom":"^30.0.5","@testing-library/jest-dom":"^6.6.4","@typescript-eslint/parser":"^8.21.0","eslint-plugin-react-hooks":"^5.1.0","@storybook/addon-essentials":"^8.6.14","@storybook/addon-onboarding":"^8.6.14","eslint-plugin-react-refresh":"^0.4.16","@storybook/addon-interactions":"^8.6.14","@typescript-eslint/eslint-plugin":"^8.21.0"},"peerDependencies":{"react":"^17.0.0 || ^18.0.0","react-dom":"^17.0.0 || ^18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react-image-crop-uploader_1.0.4_1754322173568_0.15756119253161383","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@alekpr/react-image-crop-uploader","version":"1.0.5","keywords":["react","image","upload","crop","cropping","modal","ui"],"author":{"name":"alekpr","email":"alek.pr@gmail.com"},"license":"MIT","_id":"@alekpr/react-image-crop-uploader@1.0.5","maintainers":[{"name":"alekpr","email":"alek.pr@gmail.com"}],"homepage":"https://github.com/alekpr/react-image-crop-uploader#readme","bugs":{"url":"https://github.com/alekpr/react-image-crop-uploader/issues"},"dist":{"shasum":"f6409eb23954b3fd8bd277e2fcae5a3c4ec0c683","tarball":"https://registry.npmjs.org/@alekpr/react-image-crop-uploader/-/react-image-crop-uploader-1.0.5.tgz","fileCount":37,"integrity":"sha512-vXE5SKnVap/VEZrelODo0Ls+1lms+ch1C/wUOW/ER2Iw7N/YtYp94gEIb7v8x8SdogUOcaq5j9TkBEBDLWNMxw==","signatures":[{"sig":"MEUCIDpkGvQPtv7qrt37eT2txC0N1KnSI3dcR5+WrLxdg9lXAiEAhr6fEoaDXwinGMlga7AUAR85W6omAvN7MG0S0L456tY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":111204},"main":"./dist/index.cjs.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs.js"},"./style.css":"./dist/react-image-crop-uploader.css","./dist/react-image-crop-uploader.css":"./dist/react-image-crop-uploader.css"},"gitHead":"b98ee4fedae53d280e340f12e0413603aad32664","scripts":{"dev":"vite","lint":"eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0","test":"jest","build":"tsc && vite build","prepare":"husky","preview":"vite preview","lint:fix":"eslint src --ext ts,tsx --fix","storybook":"storybook dev -p 6006","test:watch":"jest --watch","test:coverage":"jest --coverage","build-storybook":"storybook build"},"_npmUser":{"name":"alekpr","email":"alek.pr@gmail.com"},"repository":{"url":"git+https://github.com/alekpr/react-image-crop-uploader.git","type":"git"},"_npmVersion":"10.9.2","description":"A comprehensive React image upload component with modal-based cropping capabilities","directories":{},"_nodeVersion":"22.14.0","dependencies":{"react-easy-crop":"^5.5.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","vite":"^6.0.9","husky":"^9.1.7","jsdom":"^25.0.1","eslint":"^9.18.0","postcss":"^8.5.6","ts-jest":"^29.2.5","ts-node":"^10.9.2","storybook":"^8.6.14","typescript":"^5.7.3","@types/jest":"^29.5.14","lint-staged":"^16.1.4","@types/react":"^18.3.18","vite-plugin-dts":"^4.5.0","@types/react-dom":"^18.3.5","@vitejs/plugin-react":"^4.3.4","@storybook/react-vite":"^8.6.14","@storybook/addon-links":"^8.6.14","@testing-library/react":"^16.3.0","jest-environment-jsdom":"^30.0.5","@testing-library/jest-dom":"^6.6.4","@typescript-eslint/parser":"^8.21.0","eslint-plugin-react-hooks":"^5.1.0","@storybook/addon-essentials":"^8.6.14","@storybook/addon-onboarding":"^8.6.14","eslint-plugin-react-refresh":"^0.4.16","@storybook/addon-interactions":"^8.6.14","@typescript-eslint/eslint-plugin":"^8.21.0"},"peerDependencies":{"react":"^17.0.0 || ^18.0.0","react-dom":"^17.0.0 || ^18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react-image-crop-uploader_1.0.5_1754323223364_0.04958626551087275","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"@alekpr/react-image-crop-uploader","version":"1.0.6","keywords":["react","image","upload","crop","cropping","modal","ui"],"author":{"name":"alekpr","email":"alek.pr@gmail.com"},"license":"MIT","_id":"@alekpr/react-image-crop-uploader@1.0.6","maintainers":[{"name":"alekpr","email":"alek.pr@gmail.com"}],"homepage":"https://github.com/alekpr/react-image-crop-uploader#readme","bugs":{"url":"https://github.com/alekpr/react-image-crop-uploader/issues"},"dist":{"shasum":"8f0c573cf809d3a7a6efe7f568417ec87e5bf482","tarball":"https://registry.npmjs.org/@alekpr/react-image-crop-uploader/-/react-image-crop-uploader-1.0.6.tgz","fileCount":38,"integrity":"sha512-P2g7zSvAWrDf9Hl/pGdkKm32CX5ypt2nkgMQNtWN1o+jOECiQVd1uAiepeNO/b3NpT00BCCtKiIcD2dUFflwxg==","signatures":[{"sig":"MEYCIQChDBC0nrLbrkta5xK1XLU8a0GGbVW0mdIDrzCb03SIDwIhALPXwPUYExgJ7iU9954eZtptI5WQMQ9I4TN8SIFvHoF1","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":112666},"main":"./dist/index.cjs.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs.js"},"./style.css":"./dist/react-image-crop-uploader.css","./dist/react-image-crop-uploader.css":"./dist/react-image-crop-uploader.css"},"gitHead":"b80ed634f347173aacc8350d4b7830c4bc92dde8","scripts":{"dev":"vite","lint":"eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0","test":"jest","build":"tsc && vite build","prepare":"husky","preview":"vite preview","lint:fix":"eslint src --ext ts,tsx --fix","storybook":"storybook dev -p 6006","test:watch":"jest --watch","test:coverage":"jest --coverage","build-storybook":"storybook build"},"_npmUser":{"name":"alekpr","email":"alek.pr@gmail.com"},"repository":{"url":"git+https://github.com/alekpr/react-image-crop-uploader.git","type":"git"},"_npmVersion":"10.9.2","description":"A comprehensive React image upload component with modal-based cropping capabilities","directories":{},"_nodeVersion":"22.14.0","dependencies":{"react-easy-crop":"^5.5.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","vite":"^6.0.9","husky":"^9.1.7","jsdom":"^25.0.1","eslint":"^9.18.0","postcss":"^8.5.6","ts-jest":"^29.2.5","ts-node":"^10.9.2","storybook":"^8.6.14","typescript":"^5.7.3","@types/jest":"^29.5.14","lint-staged":"^16.1.4","@types/react":"^18.3.18","vite-plugin-dts":"^4.5.0","@types/react-dom":"^18.3.5","@vitejs/plugin-react":"^4.3.4","@storybook/react-vite":"^8.6.14","@storybook/addon-links":"^8.6.14","@testing-library/react":"^16.3.0","jest-environment-jsdom":"^30.0.5","@testing-library/jest-dom":"^6.6.4","@typescript-eslint/parser":"^8.21.0","eslint-plugin-react-hooks":"^5.1.0","@storybook/addon-essentials":"^8.6.14","@storybook/addon-onboarding":"^8.6.14","eslint-plugin-react-refresh":"^0.4.16","@storybook/addon-interactions":"^8.6.14","@typescript-eslint/eslint-plugin":"^8.21.0"},"peerDependencies":{"react":"^17.0.0 || ^18.0.0","react-dom":"^17.0.0 || ^18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react-image-crop-uploader_1.0.6_1754324521479_0.15548489717030645","host":"s3://npm-registry-packages-npm-production"}},"1.0.7":{"name":"@alekpr/react-image-crop-uploader","version":"1.0.7","keywords":["react","image","upload","crop","cropping","modal","ui"],"author":{"name":"alekpr","email":"alek.pr@gmail.com"},"license":"MIT","_id":"@alekpr/react-image-crop-uploader@1.0.7","maintainers":[{"name":"alekpr","email":"alek.pr@gmail.com"}],"homepage":"https://github.com/alekpr/react-image-crop-uploader#readme","bugs":{"url":"https://github.com/alekpr/react-image-crop-uploader/issues"},"dist":{"shasum":"c201162564a58ee20514242ac39a1d6bc4634b72","tarball":"https://registry.npmjs.org/@alekpr/react-image-crop-uploader/-/react-image-crop-uploader-1.0.7.tgz","fileCount":38,"integrity":"sha512-EzZ4sU13n2dQEfx3hQi5VjRDViiog+k+hSMBeAdh6c8t3YNkm0yrD7/yD7JLzJm7nWATqB6s0Rf8KDtH/pTj0g==","signatures":[{"sig":"MEQCIHGHJAennGzLkW8XAkFde0rMyc4pcK+uuco/DPE6r5KOAiB08gT0UEabov0BwGVn5TKUP573W4K7BlK+jjr/+aifrQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":112867},"main":"./dist/index.cjs.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs.js"},"./style.css":"./dist/react-image-crop-uploader.css","./dist/react-image-crop-uploader.css":"./dist/react-image-crop-uploader.css"},"gitHead":"e21775ee37f5d2bb41e977148408588cbfd6fdbf","scripts":{"dev":"vite","lint":"eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0","test":"jest","build":"tsc && vite build","prepare":"husky","preview":"vite preview","lint:fix":"eslint src --ext ts,tsx --fix","storybook":"storybook dev -p 6006","test:watch":"jest --watch","test:coverage":"jest --coverage","build-storybook":"storybook build"},"_npmUser":{"name":"alekpr","email":"alek.pr@gmail.com"},"repository":{"url":"git+https://github.com/alekpr/react-image-crop-uploader.git","type":"git"},"_npmVersion":"10.9.2","description":"A comprehensive React image upload component with modal-based cropping capabilities","directories":{},"_nodeVersion":"22.14.0","dependencies":{"react-easy-crop":"^5.5.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","vite":"^6.0.9","husky":"^9.1.7","jsdom":"^25.0.1","eslint":"^9.18.0","postcss":"^8.5.6","ts-jest":"^29.2.5","ts-node":"^10.9.2","storybook":"^8.6.14","typescript":"^5.7.3","@types/jest":"^29.5.14","lint-staged":"^16.1.4","@types/react":"^18.3.18","vite-plugin-dts":"^4.5.0","@types/react-dom":"^18.3.5","@vitejs/plugin-react":"^4.3.4","@storybook/react-vite":"^8.6.14","@storybook/addon-links":"^8.6.14","@testing-library/react":"^16.3.0","jest-environment-jsdom":"^30.0.5","@testing-library/jest-dom":"^6.6.4","@typescript-eslint/parser":"^8.21.0","eslint-plugin-react-hooks":"^5.1.0","@storybook/addon-essentials":"^8.6.14","@storybook/addon-onboarding":"^8.6.14","eslint-plugin-react-refresh":"^0.4.16","@storybook/addon-interactions":"^8.6.14","@typescript-eslint/eslint-plugin":"^8.21.0"},"peerDependencies":{"react":"^17.0.0 || ^18.0.0","react-dom":"^17.0.0 || ^18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react-image-crop-uploader_1.0.7_1754325327812_0.9346869259395012","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@alekpr/react-image-crop-uploader","version":"1.1.0","description":"A comprehensive React image upload component with modal-based cropping capabilities and selective upload support","author":{"name":"alekpr","email":"alek.pr@gmail.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/alekpr/react-image-crop-uploader.git"},"bugs":{"url":"https://github.com/alekpr/react-image-crop-uploader/issues"},"keywords":["react","image","upload","crop","cropping","modal","ui"],"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs.js"},"./dist/react-image-crop-uploader.css":"./dist/react-image-crop-uploader.css","./style.css":"./dist/react-image-crop-uploader.css"},"main":"./dist/index.cjs.js","module":"./dist/index.es.js","types":"./dist/index.d.ts","scripts":{"dev":"vite","build":"tsc && vite build","preview":"vite preview","test":"jest","test:watch":"jest --watch","test:coverage":"jest --coverage","lint":"eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0","lint:fix":"eslint src --ext ts,tsx --fix","storybook":"storybook dev -p 6006","build-storybook":"storybook build","prepare":"husky"},"peerDependencies":{"react":"^17.0.0 || ^18.0.0","react-dom":"^17.0.0 || ^18.0.0"},"devDependencies":{"@storybook/addon-essentials":"^8.6.14","@storybook/addon-interactions":"^8.6.14","@storybook/addon-links":"^8.6.14","@storybook/addon-onboarding":"^8.6.14","@storybook/react-vite":"^8.6.14","@testing-library/jest-dom":"^6.6.4","@testing-library/react":"^16.3.0","@types/jest":"^29.5.14","@types/react":"^18.3.18","@types/react-dom":"^18.3.5","@typescript-eslint/eslint-plugin":"^8.21.0","@typescript-eslint/parser":"^8.21.0","@vitejs/plugin-react":"^4.3.4","eslint":"^9.18.0","eslint-plugin-react-hooks":"^5.1.0","eslint-plugin-react-refresh":"^0.4.16","husky":"^9.1.7","jest":"^29.7.0","jest-environment-jsdom":"^30.0.5","jsdom":"^25.0.1","lint-staged":"^16.1.4","postcss":"^8.5.6","storybook":"^8.6.14","ts-jest":"^29.2.5","ts-node":"^10.9.2","typescript":"^5.7.3","vite":"^6.0.9","vite-plugin-dts":"^4.5.0"},"dependencies":{"react-easy-crop":"^5.5.0"},"_id":"@alekpr/react-image-crop-uploader@1.1.0","gitHead":"e21775ee37f5d2bb41e977148408588cbfd6fdbf","homepage":"https://github.com/alekpr/react-image-crop-uploader#readme","_nodeVersion":"22.14.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-eWjAHyEJSy8fxGktwfd1l2j3NrXk6N1tJVnHShk5P+9IT1pMAVP1g5v+VWxfzUcNIrmRgjpoFjl2Gwr70n8O4w==","shasum":"89373d6bb78e5e7d4fa6f9366a13e8d456d7f69e","tarball":"https://registry.npmjs.org/@alekpr/react-image-crop-uploader/-/react-image-crop-uploader-1.1.0.tgz","fileCount":39,"unpackedSize":128460,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEJoHjv0R8BYavmyV2gm6tyBJCSB52S0+kjQX6eP0tEHAiEAkETiLz9m00agh/t3wvYq0NRMGMjGtogSKf7WtzoMuMY="}]},"_npmUser":{"name":"alekpr","email":"alek.pr@gmail.com"},"directories":{},"maintainers":[{"name":"alekpr","email":"alek.pr@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/react-image-crop-uploader_1.1.0_1754369180265_0.7346275943059768"},"_hasShrinkwrap":false}},"time":{"created":"2025-08-04T07:00:15.958Z","modified":"2025-08-05T04:46:20.663Z","1.0.0":"2025-08-04T07:00:16.270Z","1.0.1":"2025-08-04T07:11:54.444Z","1.0.2":"2025-08-04T09:38:42.488Z","1.0.3":"2025-08-04T15:07:31.415Z","1.0.4":"2025-08-04T15:42:53.742Z","1.0.5":"2025-08-04T16:00:23.578Z","1.0.6":"2025-08-04T16:22:01.663Z","1.0.7":"2025-08-04T16:35:28.006Z","1.1.0":"2025-08-05T04:46:20.447Z"},"bugs":{"url":"https://github.com/alekpr/react-image-crop-uploader/issues"},"author":{"name":"alekpr","email":"alek.pr@gmail.com"},"license":"MIT","homepage":"https://github.com/alekpr/react-image-crop-uploader#readme","keywords":["react","image","upload","crop","cropping","modal","ui"],"repository":{"type":"git","url":"git+https://github.com/alekpr/react-image-crop-uploader.git"},"description":"A comprehensive React image upload component with modal-based cropping capabilities and selective upload support","maintainers":[{"name":"alekpr","email":"alek.pr@gmail.com"}],"readme":"# React Image Crop Uploader\n\n[![npm version](https://badge.fury.io/js/@alekpr%2Freact-image-crop-uploader.svg)](https://www.npmjs.com/package/@alekpr/react-image-crop-uploader)\n[![npm downloads](https://img.shields.io/npm/dm/@alekpr/react-image-crop-uploader.svg)](https://www.npmjs.com/package/@alekpr/react-image-crop-uploader)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Live Demo](https://img.shields.io/badge/🚀-Live%20Demo-blue.svg)](https://github.com/alekpr/react-image-upload-library-sample)\n\nA comprehensive React image upload component with modal-based cropping capabilities. This library provides an all-in-one solution for handling image uploads with cropping functionality in your React applications.\n\n## 📚 Live Demo & Examples\n\n🚀 **[View Live Demo](https://github.com/alekpr/react-image-upload-library-sample)** - Complete sample project with multiple examples\n\nThe sample repository includes:\n- Basic upload functionality\n- Cropping with different aspect ratios\n- Initial images handling\n- Direct upload integration\n- Edit mode examples\n- TypeScript usage examples\n\n## Features\n\n- 📁 **Multi-file Support**: Upload single or multiple images\n- 📏 **Image Cropping**: Modal-based cropping with real-time preview using [react-easy-crop](https://github.com/ricardo-ch/react-easy-crop)\n- 🎯 **Configurable Crop**: Custom aspect ratios and dimensions\n- 📤 **Upload Modes**: Direct upload or form integration with selective upload support\n- 🖼️ **Image Preview**: Thumbnail previews with edit functionality\n- ✂️ **Re-cropping**: Edit existing images after upload\n- 🔄 **Selective Upload**: Smart upload that distinguishes between initial images and new files\n- 🎨 **Customizable UI**: Fully styled with standard CSS\n- 📱 **Responsive**: Mobile-friendly design\n- 🔧 **TypeScript**: Full TypeScript support with type definitions\n- 🧪 **Tested**: Comprehensive test suite\n\n## Installation\n\n```bash\nnpm install @alekpr/react-image-crop-uploader\n```\n\nor\n\n```bash\nyarn add @alekpr/react-image-crop-uploader\n```\n\n### Clone Sample Project\n\nTo quickly get started with a working example:\n\n```bash\ngit clone https://github.com/alekpr/react-image-upload-library-sample.git\ncd react-image-upload-library-sample\nnpm install\nnpm start\n```\n\n## Quick Start\n\n> **💡 Tip**: Check out the [complete sample project](https://github.com/alekpr/react-image-upload-library-sample) for more examples and usage patterns!\n\n```tsx\nimport { ImageUploader } from '@alekpr/react-image-crop-uploader';\nimport '@alekpr/react-image-crop-uploader/style.css';\n\nfunction App() {\n  const handleUploadComplete = ({ unuploadedFiles, uploadResponse }) => {\n    console.log('New files uploaded:', unuploadedFiles);\n    console.log('Server response:', uploadResponse);\n  };\n\n  return (\n    <ImageUploader\n      uploadUrl=\"/api/upload\"\n      onUploadComplete={handleUploadComplete}\n      enableCrop={true}\n      maxFiles={5}\n      initialImages={[\"existing-image.jpg\"]} // Won't be re-uploaded\n    />\n  );\n}\n```\n\n## Usage\n\n### Getting Started\n\nFor complete examples and advanced usage patterns, visit our **[Sample Project Repository](https://github.com/alekpr/react-image-upload-library-sample)**.\n\n### Basic Usage\n\n```tsx\nimport { ImageUploader } from '@alekpr/react-image-crop-uploader';\nimport '@alekpr/react-image-crop-uploader/style.css';\n\nfunction App() {\n  const handleFilesChange = (files: File[]) => {\n    console.log('Selected files:', files);\n  };\n\n  return (\n    <ImageUploader\n      maxFileSize={5}\n      maxFiles={3}\n      onFilesChange={handleFilesChange}\n    />\n  );\n}\n```\n\n### With Cropping Enabled\n\n```tsx\nimport { ImageUploader } from '@alekpr/react-image-crop-uploader';\nimport '@alekpr/react-image-crop-uploader/style.css';\n\nfunction App() {\n  const handleFilesChange = (files: File[]) => {\n    console.log('Selected files:', files);\n  };\n\n  const handleCropComplete = (croppedFile: File, originalFile: File) => {\n    console.log('Cropped file:', croppedFile);\n  };\n\n  return (\n    <ImageUploader\n      maxFileSize={10}\n      maxFiles={5}\n      enableCrop={true}\n      cropAspectRatio={16/9}\n      onFilesChange={handleFilesChange}\n      onCropComplete={handleCropComplete}\n    />\n  );\n}\n```\n\n### Upload Button Features\n\nThe component automatically shows an upload button when files are present. You can customize the upload button behavior:\n\n```tsx\nimport { ImageUploader } from '@alekpr/react-image-crop-uploader';\nimport '@alekpr/react-image-crop-uploader/style.css';\n\nfunction App() {\n  return (\n    <ImageUploader\n      uploadUrl=\"/api/images/upload\"\n      enableCrop={true}\n      // Upload button configuration\n      showUploadButton={true}           // Show/hide upload button (default: true)\n      uploadButtonText=\"Send Files\"     // Custom button text (default: \"Upload\")\n      uploadButtonClassName=\"px-6 py-3 bg-green-500 text-white rounded-lg hover:bg-green-600\"\n      onUploadComplete={(response) => console.log('Upload completed:', response)}\n    />\n  );\n}\n```\n\n**Upload Button Features:**\n- ✅ **Auto-display**: Shows automatically when files are present and `uploadUrl` is provided\n- ✅ **File count**: Displays file count for multiple files (e.g., \"Upload (3 files)\")\n- ✅ **Customizable**: Support custom text and CSS styling\n- ✅ **Smart disable**: Automatically disabled when no files are present\n- ✅ **Hide option**: Can be hidden with `showUploadButton={false}` for manual upload handling\n\n### Direct Upload Mode with Selective Upload\n\n```tsx\nimport { ImageUploader } from '@alekpr/react-image-crop-uploader';\nimport '@alekpr/react-image-crop-uploader/style.css';\n\nfunction App() {\n  const handleUploadComplete = ({ unuploadedFiles, uploadResponse }) => {\n    console.log('Files that were uploaded:', unuploadedFiles);\n    console.log('Server response:', uploadResponse);\n  };\n\n  const handleError = (error: string) => {\n    console.error('Upload error:', error);\n  };\n\n  const handleUploadProgress = (progress: number) => {\n    console.log(`Upload progress: ${progress}%`);\n  };\n\n  return (\n    <ImageUploader\n      uploadUrl=\"/api/images/upload\"\n      maxFileSize={10}\n      enableCrop={true}\n      uploadFieldName=\"image\"\n      multipleFileStrategy=\"single-request\"\n      uploadButtonText=\"Upload New Images\"\n      showUploadButton={true}\n      initialImages={[\"existing-image1.jpg\", \"existing-image2.jpg\"]}\n      onUploadComplete={handleUploadComplete}\n      onError={handleError}\n      onUploadProgress={handleUploadProgress}\n    />\n  );\n}\n```\n\n**Selective Upload Features:**\n- ✅ **Smart Upload**: Only uploads new files, skips initial images\n- ✅ **Enhanced Callback**: Provides both uploaded files and server response\n- ✅ **Initial Image Support**: Display existing images without re-uploading\n- ✅ **Mixed Content**: Handle both initial images and new uploads in one component\n```\n\n### Multiple File Upload Strategies\n\n```tsx\nimport { ImageUploader } from '@alekpr/react-image-crop-uploader';\nimport '@alekpr/react-image-crop-uploader/style.css';\n\n// Strategy 1: Send all files in a single request\nfunction SingleRequestUpload() {\n  return (\n    <ImageUploader\n      uploadUrl=\"/api/images/upload-multiple\"\n      maxFiles={5}\n      multipleFileStrategy=\"single-request\"\n      uploadFieldName=\"images\"\n      onUploadComplete={(response) => console.log('All files uploaded:', response)}\n    />\n  );\n}\n\n// Strategy 2: Send each file in separate requests\nfunction MultipleRequestsUpload() {\n  return (\n    <ImageUploader\n      uploadUrl=\"/api/images/upload\"\n      maxFiles={5}\n      multipleFileStrategy=\"multiple-requests\"\n      uploadFieldName=\"image\"\n      onUploadComplete={(responses) => console.log('Upload responses:', responses)}\n    />\n  );\n}\n```\n```\n\n### Enhanced Edit Mode with Selective Upload\n\n```tsx\nimport { ImageUploader } from '@alekpr/react-image-crop-uploader';\nimport '@alekpr/react-image-crop-uploader/style.css';\n\nfunction App() {\n  const [uploadedImages, setUploadedImages] = useState<string[]>([\n    \"https://example.com/image1.jpg\",\n    \"https://example.com/image2.jpg\"\n  ]);\n\n  const handleUploadComplete = ({ unuploadedFiles, uploadResponse }) => {\n    console.log('New files uploaded:', unuploadedFiles);\n    console.log('Server response:', uploadResponse);\n    \n    // Add new uploaded image URLs to the collection\n    if (uploadResponse?.imageUrls) {\n      setUploadedImages(prev => [...prev, ...uploadResponse.imageUrls]);\n    }\n  };\n\n  const handleFilesChange = (files: File[]) => {\n    console.log('Current files in component:', files);\n  };\n\n  return (\n    <ImageUploader\n      editMode={true}\n      initialImages={uploadedImages} // Existing images won't be re-uploaded\n      uploadUrl=\"/api/images/upload\"\n      enableCrop={true}\n      maxFiles={10}\n      showEditButton={true}\n      uploadButtonText=\"Upload New Images\"\n      onFilesChange={handleFilesChange}\n      onUploadComplete={handleUploadComplete}\n    />\n  );\n}\n```\n\n**Enhanced Edit Mode Features:**\n- ✅ **Selective Upload**: Only uploads new files, preserves initial images\n- ✅ **Mixed Content**: Display existing images alongside new uploads\n- ✅ **Enhanced Callback**: Get both uploaded files and server response details\n- ✅ **Smart State Management**: Automatically handles initial vs new file distinction\n- ✅ **Full Editing**: Crop, remove, and add images in the same interface\n\n## Props\n\n### Upload Configuration\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `uploadUrl` | `string` | `undefined` | URL to upload files to |\n| `maxFileSize` | `number` | `5` | Maximum file size in MB |\n| `maxFiles` | `number` | `1` | Maximum number of files |\n| `acceptedTypes` | `string[]` | `['image/jpeg', 'image/png', 'image/webp']` | Accepted file types |\n| `uploadFieldName` | `string` | `'image'` | FormData field name for uploaded files |\n| `multipleFileStrategy` | `'single-request' \\| 'multiple-requests'` | `'single-request'` | How to handle multiple file uploads |\n\n### Crop Configuration\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `cropAspectRatio` | `number | 'free'` | `'free'` | Aspect ratio for cropping |\n| `cropSize` | `{ width: number; height: number }` | `undefined` | Fixed crop size |\n| `enableCrop` | `boolean` | `false` | Enable cropping functionality |\n| `cropModalTitle` | `string` | `'Crop Image'` | Title for crop modal |\n\n### Initial State\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `initialImages` | `string[] | File[]` | `[]` | Initial images to display |\n| `editMode` | `boolean` | `false` | Enable edit mode |\n\n### Callbacks\n\n| Prop | Type | Description |\n|------|------|-------------|\n| `onUploadComplete` | `(result: { unuploadedFiles: File[]; uploadResponse: any }) => void` | Called when upload completes with enhanced data |\n| `onFilesChange` | `(files: File[]) => void` | Called when files change |\n| `onError` | `(error: string) => void` | Called when errors occur |\n| `onCropComplete` | `(croppedFile: File, originalFile: File, index?: number) => void` | Called when cropping completes |\n| `onCropModalOpen` | `(file: File, index?: number) => void` | Called when crop modal opens |\n| `onCropModalClose` | `() => void` | Called when crop modal closes |\n| `onUploadProgress` | `(progress: number) => void` | Called with upload progress (0-100) |\n\n### UI Configuration\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `placeholder` | `string` | `'Drag & drop images here or click to select'` | Placeholder text |\n| `disabled` | `boolean` | `false` | Disable the component |\n| `className` | `string` | `''` | Custom CSS class |\n| `showEditButton` | `boolean` | `true` | Show edit button on previews |\n| `editButtonText` | `string` | `'Edit'` | Text for edit button |\n| `showUploadButton` | `boolean` | `true` | Show upload button when files are present and uploadUrl is provided |\n| `uploadButtonText` | `string` | `'Upload'` | Text for upload button. Shows file count for multiple files |\n| `uploadButtonClassName` | `string` | `''` | Custom CSS class for upload button. Falls back to default styling if empty |\n| `uploadButtonText` | `string` | `'Upload'` | Text for upload button |\n| `uploadButtonClassName` | `string` | `''` | Custom CSS class for upload button |\n\n### Modal Configuration\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `cropModalProps` | `object` | `{}` | Configuration for crop modal |\n| `cropModalProps.title` | `string` | `'Crop Image'` | Modal title |\n| `cropModalProps.saveButtonText` | `string` | `'Save'` | Save button text |\n| `cropModalProps.cancelButtonText` | `string` | `'Cancel'` | Cancel button text |\n| `cropModalProps.resetButtonText` | `string` | `'Reset'` | Reset button text |\n\n```\n\n## Selective Upload Features\n\nThe library provides intelligent upload handling that distinguishes between initial images and newly added files:\n\n### How Selective Upload Works\n\n```tsx\nimport { ImageUploader } from '@alekpr/react-image-crop-uploader';\n\nfunction App() {\n  const existingImages = [\n    \"https://example.com/existing1.jpg\",\n    \"https://example.com/existing2.jpg\"\n  ];\n\n  const handleUploadComplete = ({ unuploadedFiles, uploadResponse }) => {\n    // unuploadedFiles: Only the new files that were actually uploaded\n    // uploadResponse: Server response from the upload request\n    console.log('New files uploaded:', unuploadedFiles.length);\n    console.log('Server response:', uploadResponse);\n  };\n\n  return (\n    <ImageUploader\n      initialImages={existingImages}  // These won't be uploaded again\n      uploadUrl=\"/api/upload\"\n      onUploadComplete={handleUploadComplete}\n    />\n  );\n}\n```\n\n### Initial Images vs New Files\n\n| Initial Images | New Files |\n|---|---|\n| ✅ Displayed in gallery | ✅ Displayed in gallery |\n| ✅ Can be cropped/edited | ✅ Can be cropped/edited |\n| ✅ Can be removed | ✅ Can be removed |\n| ❌ **Not uploaded again** | ✅ **Uploaded to server** |\n| 🏷️ Marked as `isUploaded: true` | 🏷️ Marked as `isUploaded: false` |\n\n### Enhanced Upload Callback\n\nThe `onUploadComplete` callback now provides more detailed information:\n\n```tsx\nonUploadComplete={({ unuploadedFiles, uploadResponse }) => {\n  // unuploadedFiles: Array of File objects that were just uploaded\n  // uploadResponse: The actual server response\n  \n  console.log(`${unuploadedFiles.length} new files uploaded`);\n  console.log('Server response:', uploadResponse);\n  \n  // Handle the response based on your API structure\n  if (uploadResponse.success) {\n    // Update your state with new image URLs\n    setImages(prev => [...prev, ...uploadResponse.imageUrls]);\n  }\n}}\n```\n\n### Use Cases\n\n**1. Profile Picture with History**\n```tsx\n// Show current profile picture + allow new uploads\n<ImageUploader\n  initialImages={[user.profilePicture]}\n  maxFiles={1}\n  uploadUrl=\"/api/profile/upload\"\n  onUploadComplete={({ uploadResponse }) => {\n    // Only new profile picture is uploaded\n    updateUserProfile(uploadResponse.imageUrl);\n  }}\n/>\n```\n\n**2. Product Gallery Management**\n```tsx\n// Edit product images + add new ones\n<ImageUploader\n  initialImages={product.imageUrls}\n  maxFiles={10}\n  uploadUrl=\"/api/products/images\"\n  onUploadComplete={({ unuploadedFiles, uploadResponse }) => {\n    // Only new images are uploaded to server\n    const newImageUrls = uploadResponse.imageUrls;\n    updateProduct({ \n      imageUrls: [...product.imageUrls, ...newImageUrls] \n    });\n  }}\n/>\n```\n\n**3. Document Attachment System**\n```tsx\n// Show existing attachments + upload new ones\n<ImageUploader\n  initialImages={document.attachments}\n  uploadUrl=\"/api/documents/attach\"\n  onUploadComplete={({ unuploadedFiles, uploadResponse }) => {\n    // Track only newly uploaded files\n    console.log(`Added ${unuploadedFiles.length} new attachments`);\n    refreshDocumentData();\n  }}\n/>\n```\n\n## Upload Button Behavior\n\nThe upload button is intelligently managed by the component:\n\n### When Upload Button Shows\n- ✅ Files are present (`files.length > 0`)\n- ✅ Upload URL is provided (`uploadUrl` prop)\n- ✅ Upload button is not hidden (`showUploadButton={true}`)\n\n### Upload Button Features\n- **Smart File Count**: Shows total files in gallery (e.g., \"Upload (5 files)\")\n  - Includes both initial images and new files in the count\n  - Helps users understand how many files are in the current session\n- **Selective Upload**: Only uploads new files, regardless of total count shown\n- **Auto Disable**: Automatically disabled when no files are present\n- **Custom Styling**: Use `uploadButtonClassName` for custom CSS classes\n- **Fallback Styling**: Uses default blue styling when `uploadButtonClassName` is empty\n- **Manual Control**: Set `showUploadButton={false}` to handle uploads programmatically\n\n### Upload Button Examples\n\n```tsx\n// Basic upload with file count (shows total files including initial)\n<ImageUploader \n  uploadUrl=\"/api/upload\"\n  initialImages={[\"existing1.jpg\", \"existing2.jpg\"]}\n  // Button shows \"Upload (4 files)\" when 2 new files are added\n  // But only uploads the 2 new files\n/>\n\n// Custom text with selective upload\n<ImageUploader \n  uploadUrl=\"/api/upload\"\n  uploadButtonText=\"Upload New Images\"\n  initialImages={existingImageUrls}\n  onUploadComplete={({ unuploadedFiles, uploadResponse }) => {\n    console.log(`Uploaded ${unuploadedFiles.length} new images`);\n  }}\n/>\n\n// Custom styling with smart upload\n<ImageUploader \n  uploadUrl=\"/api/upload\"\n  uploadButtonClassName=\"custom-upload-btn\"\n  initialImages={currentImages}\n  // Only new files are uploaded, existing ones are preserved\n  // Default styling uses modern CSS classes with animations\n/>\n\n// Hidden upload button (manual upload with selective logic)\n<ImageUploader \n  uploadUrl=\"/api/upload\"\n  showUploadButton={false}\n  initialImages={existingImages}\n  onFilesChange={(files) => {\n    // files contains both initial images and new files\n    // But you can trigger upload manually and only new files will be sent\n  }}\n/>\n```\n\n## Styling\n\nThe component comes with modern, built-in styling including:\n\n### Built-in CSS Classes\n\n- ✅ **Modern Upload Button**: `.upload-button` with hover effects and animations\n- ✅ **Responsive Design**: Mobile-friendly button sizing\n- ✅ **Accessibility**: Focus states and proper contrast ratios\n- ✅ **Loading States**: Disabled state styling\n- ✅ **File Count Display**: Stylized file count badges\n\n### CSS Import\n\nImport the CSS file to use the built-in styling:\n\n```tsx\nimport '@alekpr/react-image-crop-uploader/style.css';\n```\n\nOr import the CSS in your own stylesheet:\n\n```css\n@import '@alekpr/react-image-crop-uploader/style.css';\n```\n\n### Custom Styling\n\nYou can override the default upload button styling:\n\n```tsx\n// Use your own CSS class\n<ImageUploader \n  uploadUrl=\"/api/upload\"\n  uploadButtonClassName=\"my-custom-button\"\n/>\n```\n\n```css\n/* Your custom button styles */\n.my-custom-button {\n  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n  border: none;\n  border-radius: 25px;\n  padding: 12px 24px;\n  color: white;\n  font-weight: 600;\n  transition: all 0.3s ease;\n}\n\n.my-custom-button:hover:not(:disabled) {\n  transform: translateY(-2px);\n  box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);\n}\n```\n\n### Default Button Classes\n\nThe built-in upload button uses these CSS classes:\n\n- `.upload-button-container` - Container wrapper\n- `.upload-button` - Main button styling\n- `.upload-button-text` - Button text styling  \n- `.upload-file-count` - File count badge styling\n\nYou can also import the CSS file directly from the dist folder:\n\n```tsx\nimport '@alekpr/react-image-crop-uploader/dist/react-image-crop-uploader.css';\n```\n\n## TypeScript Support\n\nThis library is written in TypeScript and provides full type definitions. All props and callbacks are properly typed.\n\n## Browser Support\n\n- Chrome 60+\n- Firefox 55+\n- Safari 12+\n- Edge 79+\n\n## Dependencies\n\nThis library uses [react-easy-crop](https://github.com/ricardo-ch/react-easy-crop) for the cropping functionality, which provides a robust and feature-rich cropping experience.\n\n## 🔗 Resources\n\n- **[📚 Sample Project](https://github.com/alekpr/react-image-upload-library-sample)** - Complete examples and usage patterns\n- **[📦 NPM Package](https://www.npmjs.com/package/@alekpr/react-image-crop-uploader)** - Install from npm\n- **[🐛 Issue Tracker](https://github.com/alekpr/react-image-crop-uploader/issues)** - Report bugs or request features\n- **[📖 Documentation](https://github.com/alekpr/react-image-crop-uploader#readme)** - Full API documentation\n\n## Contributing\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a pull request\n\n## License\n\nMIT © [alekpr](https://github.com/alekpr)\n\n## Support\n\n### Getting Help\n\n- **[📚 Sample Project](https://github.com/alekpr/react-image-upload-library-sample)** - Browse working examples\n- **[🐛 GitHub Issues](https://github.com/alekpr/react-image-crop-uploader/issues)** - Report bugs or request features\n- **[📖 API Documentation](#props)** - Complete props and callback reference\n\n### Common Issues\n\nBefore opening an issue, please check the [sample project](https://github.com/alekpr/react-image-upload-library-sample) to see if your use case is covered.\n\nIf you encounter any issues or have questions, please [file an issue](https://github.com/alekpr/react-image-crop-uploader/issues) on GitHub with:\n1. Steps to reproduce\n2. Expected behavior\n3. Code example (preferably a minimal reproduction)","readmeFilename":"README.md"}