Most browsers (everything but Safari/WebKit) can't decode HEIC in <img> or canvas, so picking an iPhone HEIC photo broke the preview and the crop editor, and could reach the backend in a format it couldn't process. Convert HEIC/HEIF to JPEG right after selection via heic2any (dynamically imported, browser-only). - new util app/utils/convert-heic.ts: isHeic() detection (MIME or extension when iOS reports no type) + convertHeicToJpeg()/convertHeicFiles(); never throws — falls back to the original file on failure. - wired into the product image picker (store.add.manual) and the store logo picker (StoreForm). - adds heic2any dependency. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
90 lines
2.9 KiB
JSON
90 lines
2.9 KiB
JSON
{
|
|
"name": "vitrown",
|
|
"private": true,
|
|
"sideEffects": false,
|
|
"type": "module",
|
|
"scripts": {
|
|
"build": "remix vite:build",
|
|
"build:dev": "NODE_ENV=development remix vite:build --mode development",
|
|
"build:fast": "NODE_ENV=development VITE_BUILD_TARGET=development remix vite:build --mode development --minify false",
|
|
"dev": "remix vite:dev",
|
|
"lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
|
|
"generate:types": "bash ./generate-types.sh",
|
|
"generate:types:win": "powershell -ExecutionPolicy Bypass -File ./generate-types.ps1",
|
|
"start": "remix-serve ./build/server/index.js",
|
|
"typecheck": "tsc"
|
|
},
|
|
"dependencies": {
|
|
"@emotion/react": "^11.14.0",
|
|
"@emotion/styled": "^11.14.0",
|
|
"@radix-ui/react-dialog": "^1.1.6",
|
|
"@radix-ui/react-dropdown-menu": "^2.1.14",
|
|
"@radix-ui/react-label": "^2.1.2",
|
|
"@radix-ui/react-popover": "^1.1.6",
|
|
"@radix-ui/react-radio-group": "^1.2.3",
|
|
"@radix-ui/react-select": "^2.1.6",
|
|
"@radix-ui/react-slider": "^1.3.4",
|
|
"@radix-ui/react-slot": "^1.1.2",
|
|
"@radix-ui/react-switch": "^1.2.5",
|
|
"@radix-ui/react-toast": "^1.2.6",
|
|
"@remix-run/node": "^2.17.2",
|
|
"@remix-run/react": "^2.16.0",
|
|
"@remix-run/serve": "^2.16.0",
|
|
"@tanstack/react-query": "^5.66.11",
|
|
"@tanstack/react-query-devtools": "^5.66.11",
|
|
"class-variance-authority": "^0.7.1",
|
|
"clsx": "^2.1.1",
|
|
"cmdk": "^1.1.1",
|
|
"embla-carousel-react": "^8.5.2",
|
|
"framer-motion": "^12.4.10",
|
|
"heic2any": "^0.0.4",
|
|
"i18next": "^24.2.2",
|
|
"i18next-browser-languagedetector": "^8.0.4",
|
|
"i18next-http-backend": "^3.0.2",
|
|
"input-otp": "^1.4.2",
|
|
"isbot": "^4.1.0",
|
|
"jalali-moment": "^3.3.11",
|
|
"leaflet": "^1.9.4",
|
|
"lucide-react": "^0.477.0",
|
|
"moment-jalaali": "^0.10.4",
|
|
"react": "^18.2.0",
|
|
"react-dom": "^18.2.0",
|
|
"react-i18next": "^15.4.1",
|
|
"react-leaflet": "^4.2.1",
|
|
"remix-auth": "^3.6.0",
|
|
"remix-auth-form": "^1.4.0",
|
|
"tailwind-merge": "^3.0.2",
|
|
"tailwindcss-animate": "^1.0.7",
|
|
"universal-cookie": "^7.2.2",
|
|
"vaul": "^1.1.2",
|
|
"zustand": "^5.0.3"
|
|
},
|
|
"devDependencies": {
|
|
"@remix-run/dev": "^2.16.0",
|
|
"@types/leaflet": "^1.9.17",
|
|
"@types/react": "^18.2.20",
|
|
"@types/react-dom": "^18.2.7",
|
|
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
|
"@typescript-eslint/parser": "^6.7.4",
|
|
"autoprefixer": "^10.4.19",
|
|
"eslint": "^8.38.0",
|
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
"eslint-plugin-import": "^2.28.1",
|
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
|
"eslint-plugin-react": "^7.33.2",
|
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
"glob": "^11.0.3",
|
|
"postcss": "^8.4.38",
|
|
"rollup": "^4.52.5",
|
|
"sharp": "^0.34.3",
|
|
"tailwindcss": "^3.4.4",
|
|
"terser": "^5.43.1",
|
|
"typescript": "^5.9.2",
|
|
"vite": "^6.0.0",
|
|
"vite-tsconfig-paths": "^4.2.1"
|
|
},
|
|
"engines": {
|
|
"node": ">=20.0.0"
|
|
}
|
|
}
|