Made more client components to make the rendering not so crazy
This commit is contained in:
10
package.json
10
package.json
@ -24,7 +24,7 @@
|
||||
"@radix-ui/react-separator": "^1.1.7",
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@supabase/ssr": "^0.6.1",
|
||||
"@supabase/supabase-js": "^2.49.9",
|
||||
"@supabase/supabase-js": "^2.49.10",
|
||||
"@t3-oss/env-nextjs": "^0.12.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
@ -35,14 +35,16 @@
|
||||
"react-dom": "^19.1.0",
|
||||
"react-hook-form": "^7.57.0",
|
||||
"sonner": "^2.0.5",
|
||||
"zod": "^3.25.49"
|
||||
"zod": "^3.25.51"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@tailwindcss/postcss": "^4.1.8",
|
||||
"@types/cors": "^2.8.18",
|
||||
"@types/express": "^5.0.2",
|
||||
"@types/node": "^20.17.57",
|
||||
"@types/react": "^19.1.6",
|
||||
"@types/react-dom": "^19.1.5",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"eslint": "^9.28.0",
|
||||
"eslint-config-next": "^15.3.3",
|
||||
"postcss": "^8.5.4",
|
||||
@ -51,7 +53,7 @@
|
||||
"tailwind-merge": "^3.3.0",
|
||||
"tailwindcss": "^4.1.8",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tw-animate-css": "^1.3.3",
|
||||
"tw-animate-css": "^1.3.4",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.33.1"
|
||||
},
|
||||
|
276
pnpm-lock.yaml
generated
276
pnpm-lock.yaml
generated
@ -13,31 +13,31 @@ importers:
|
||||
version: 5.0.1(react-hook-form@7.57.0(react@19.1.0))
|
||||
'@radix-ui/react-avatar':
|
||||
specifier: ^1.1.10
|
||||
version: 1.1.10(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
version: 1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-checkbox':
|
||||
specifier: ^1.3.2
|
||||
version: 1.3.2(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
version: 1.3.2(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-dropdown-menu':
|
||||
specifier: ^2.1.15
|
||||
version: 2.1.15(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
version: 2.1.15(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-label':
|
||||
specifier: ^2.1.7
|
||||
version: 2.1.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
version: 2.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-separator':
|
||||
specifier: ^1.1.7
|
||||
version: 1.1.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
version: 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-slot':
|
||||
specifier: ^1.2.3
|
||||
version: 1.2.3(@types/react@19.1.6)(react@19.1.0)
|
||||
'@supabase/ssr':
|
||||
specifier: ^0.6.1
|
||||
version: 0.6.1(@supabase/supabase-js@2.49.9)
|
||||
version: 0.6.1(@supabase/supabase-js@2.49.10)
|
||||
'@supabase/supabase-js':
|
||||
specifier: ^2.49.9
|
||||
version: 2.49.9
|
||||
specifier: ^2.49.10
|
||||
version: 2.49.10
|
||||
'@t3-oss/env-nextjs':
|
||||
specifier: ^0.12.0
|
||||
version: 0.12.0(typescript@5.8.3)(zod@3.25.49)
|
||||
version: 0.12.0(typescript@5.8.3)(zod@3.25.51)
|
||||
class-variance-authority:
|
||||
specifier: ^0.7.1
|
||||
version: 0.7.1
|
||||
@ -66,8 +66,8 @@ importers:
|
||||
specifier: ^2.0.5
|
||||
version: 2.0.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
zod:
|
||||
specifier: ^3.25.49
|
||||
version: 3.25.49
|
||||
specifier: ^3.25.51
|
||||
version: 3.25.51
|
||||
devDependencies:
|
||||
'@eslint/eslintrc':
|
||||
specifier: ^3.3.1
|
||||
@ -75,6 +75,12 @@ importers:
|
||||
'@tailwindcss/postcss':
|
||||
specifier: ^4.1.8
|
||||
version: 4.1.8
|
||||
'@types/cors':
|
||||
specifier: ^2.8.18
|
||||
version: 2.8.18
|
||||
'@types/express':
|
||||
specifier: ^5.0.2
|
||||
version: 5.0.2
|
||||
'@types/node':
|
||||
specifier: ^20.17.57
|
||||
version: 20.17.57
|
||||
@ -82,8 +88,8 @@ importers:
|
||||
specifier: ^19.1.6
|
||||
version: 19.1.6
|
||||
'@types/react-dom':
|
||||
specifier: ^19.1.5
|
||||
version: 19.1.5(@types/react@19.1.6)
|
||||
specifier: ^19.1.6
|
||||
version: 19.1.6(@types/react@19.1.6)
|
||||
eslint:
|
||||
specifier: ^9.28.0
|
||||
version: 9.28.0(jiti@2.4.2)
|
||||
@ -109,8 +115,8 @@ importers:
|
||||
specifier: ^1.0.7
|
||||
version: 1.0.7(tailwindcss@4.1.8)
|
||||
tw-animate-css:
|
||||
specifier: ^1.3.3
|
||||
version: 1.3.3
|
||||
specifier: ^1.3.4
|
||||
version: 1.3.4
|
||||
typescript:
|
||||
specifier: ^5.8.3
|
||||
version: 5.8.3
|
||||
@ -784,8 +790,8 @@ packages:
|
||||
'@supabase/postgrest-js@1.19.4':
|
||||
resolution: {integrity: sha512-O4soKqKtZIW3olqmbXXbKugUtByD2jPa8kL2m2c1oozAO11uCcGrRhkZL0kVxjBLrXHE0mdSkFsMj7jDSfyNpw==}
|
||||
|
||||
'@supabase/realtime-js@2.11.9':
|
||||
resolution: {integrity: sha512-fLseWq8tEPCO85x3TrV9Hqvk7H4SGOqnFQ223NPJSsxjSYn0EmzU1lvYO6wbA0fc8DE94beCAiiWvGvo4g33lQ==}
|
||||
'@supabase/realtime-js@2.11.10':
|
||||
resolution: {integrity: sha512-SJKVa7EejnuyfImrbzx+HaD9i6T784khuw1zP+MBD7BmJYChegGxYigPzkKX8CK8nGuDntmeSD3fvriaH0EGZA==}
|
||||
|
||||
'@supabase/ssr@0.6.1':
|
||||
resolution: {integrity: sha512-QtQgEMvaDzr77Mk3vZ3jWg2/y+D8tExYF7vcJT+wQ8ysuvOeGGjYbZlvj5bHYsj/SpC0bihcisnwPrM4Gp5G4g==}
|
||||
@ -795,8 +801,8 @@ packages:
|
||||
'@supabase/storage-js@2.7.1':
|
||||
resolution: {integrity: sha512-asYHcyDR1fKqrMpytAS1zjyEfvxuOIp1CIXX7ji4lHHcJKqyk+sLl/Vxgm4sN6u8zvuUtae9e4kDxQP2qrwWBA==}
|
||||
|
||||
'@supabase/supabase-js@2.49.9':
|
||||
resolution: {integrity: sha512-lB2A2X8k1aWAqvlpO4uZOdfvSuZ2s0fCMwJ1Vq6tjWsi3F+au5lMbVVn92G0pG8gfmis33d64Plkm6eSDs6jRA==}
|
||||
'@supabase/supabase-js@2.49.10':
|
||||
resolution: {integrity: sha512-IRPcIdncuhD2m1eZ2Fkg0S1fq9SXlHfmAetBxPN66kVFtTucR8b01xKuVmKqcIJokB17umMf1bmqyS8yboXGsw==}
|
||||
|
||||
'@swc/counter@0.1.3':
|
||||
resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
|
||||
@ -923,29 +929,62 @@ packages:
|
||||
'@tybys/wasm-util@0.9.0':
|
||||
resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==}
|
||||
|
||||
'@types/body-parser@1.19.5':
|
||||
resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
|
||||
|
||||
'@types/connect@3.4.38':
|
||||
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
|
||||
|
||||
'@types/cors@2.8.18':
|
||||
resolution: {integrity: sha512-nX3d0sxJW41CqQvfOzVG1NCTXfFDrDWIghCZncpHeWlVFd81zxB/DLhg7avFg6eHLCRX7ckBmoIIcqa++upvJA==}
|
||||
|
||||
'@types/estree@1.0.7':
|
||||
resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
|
||||
|
||||
'@types/express-serve-static-core@5.0.6':
|
||||
resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==}
|
||||
|
||||
'@types/express@5.0.2':
|
||||
resolution: {integrity: sha512-BtjL3ZwbCQriyb0DGw+Rt12qAXPiBTPs815lsUvtt1Grk0vLRMZNMUZ741d5rjk+UQOxfDiBZ3dxpX00vSkK3g==}
|
||||
|
||||
'@types/http-errors@2.0.4':
|
||||
resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
|
||||
|
||||
'@types/json-schema@7.0.15':
|
||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||
|
||||
'@types/json5@0.0.29':
|
||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||
|
||||
'@types/mime@1.3.5':
|
||||
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
|
||||
|
||||
'@types/node@20.17.57':
|
||||
resolution: {integrity: sha512-f3T4y6VU4fVQDKVqJV4Uppy8c1p/sVvS3peyqxyWnzkqXFJLRU7Y1Bl7rMS1Qe9z0v4M6McY0Fp9yBsgHJUsWQ==}
|
||||
|
||||
'@types/phoenix@1.6.6':
|
||||
resolution: {integrity: sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==}
|
||||
|
||||
'@types/react-dom@19.1.5':
|
||||
resolution: {integrity: sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==}
|
||||
'@types/qs@6.14.0':
|
||||
resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==}
|
||||
|
||||
'@types/range-parser@1.2.7':
|
||||
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
|
||||
|
||||
'@types/react-dom@19.1.6':
|
||||
resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==}
|
||||
peerDependencies:
|
||||
'@types/react': ^19.0.0
|
||||
|
||||
'@types/react@19.1.6':
|
||||
resolution: {integrity: sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==}
|
||||
|
||||
'@types/send@0.17.4':
|
||||
resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==}
|
||||
|
||||
'@types/serve-static@1.15.7':
|
||||
resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==}
|
||||
|
||||
'@types/ws@8.18.1':
|
||||
resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
|
||||
|
||||
@ -1205,8 +1244,8 @@ packages:
|
||||
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
caniuse-lite@1.0.30001720:
|
||||
resolution: {integrity: sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==}
|
||||
caniuse-lite@1.0.30001721:
|
||||
resolution: {integrity: sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==}
|
||||
|
||||
chalk@4.1.2:
|
||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||
@ -2364,8 +2403,8 @@ packages:
|
||||
tslib@2.8.1:
|
||||
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||
|
||||
tw-animate-css@1.3.3:
|
||||
resolution: {integrity: sha512-tXE2TRWrskc4TU3RDd7T8n8Np/wCfoeH9gz22c7PzYqNPQ9FBGFbWWzwL0JyHcFp+jHozmF76tbHfPAx22ua2Q==}
|
||||
tw-animate-css@1.3.4:
|
||||
resolution: {integrity: sha512-dd1Ht6/YQHcNbq0znIT6dG8uhO7Ce+VIIhZUhjsryXsMPJQz3bZg7Q2eNzLwipb25bRZslGb2myio5mScd1TFg==}
|
||||
|
||||
type-check@0.4.0:
|
||||
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
||||
@ -2488,8 +2527,8 @@ packages:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
zod@3.25.49:
|
||||
resolution: {integrity: sha512-JMMPMy9ZBk3XFEdbM3iL1brx4NUSejd6xr3ELrrGEfGb355gjhiAWtG3K5o+AViV/3ZfkIrCzXsZn6SbLwTR8Q==}
|
||||
zod@3.25.51:
|
||||
resolution: {integrity: sha512-TQSnBldh+XSGL+opiSIq0575wvDPqu09AqWe1F7JhUMKY+M91/aGlK4MhpVNO7MgYfHcVCB1ffwAUTJzllKJqg==}
|
||||
|
||||
snapshots:
|
||||
|
||||
@ -2750,19 +2789,19 @@ snapshots:
|
||||
|
||||
'@radix-ui/primitive@1.1.2': {}
|
||||
|
||||
'@radix-ui/react-arrow@1.1.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-arrow@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-avatar@1.1.10(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-avatar@1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
@ -2770,15 +2809,15 @@ snapshots:
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-checkbox@1.3.2(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-checkbox@1.3.2(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-use-size': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
@ -2786,19 +2825,19 @@ snapshots:
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-collection@1.1.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-collection@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-slot': 1.2.3(@types/react@19.1.6)(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-compose-refs@1.1.2(@types/react@19.1.6)(react@19.1.0)':
|
||||
dependencies:
|
||||
@ -2818,33 +2857,33 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
|
||||
'@radix-ui/react-dismissable-layer@1.1.10(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-dismissable-layer@1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-dropdown-menu@2.1.15(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-dropdown-menu@2.1.15(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-menu': 2.1.15(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-menu': 2.1.15(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-focus-guards@1.1.2(@types/react@19.1.6)(react@19.1.0)':
|
||||
dependencies:
|
||||
@ -2852,16 +2891,16 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
|
||||
'@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-id@1.1.1(@types/react@19.1.6)(react@19.1.0)':
|
||||
dependencies:
|
||||
@ -2870,31 +2909,31 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
|
||||
'@radix-ui/react-label@2.1.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-label@2.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-menu@2.1.15(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-menu@2.1.15(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
'@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-dismissable-layer': 1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-focus-guards': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-popper': 1.2.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-portal': 1.1.9(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-popper': 1.2.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-portal': 1.1.9(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-slot': 1.2.3(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
aria-hidden: 1.2.6
|
||||
@ -2903,15 +2942,15 @@ snapshots:
|
||||
react-remove-scroll: 2.7.1(@types/react@19.1.6)(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-popper@1.2.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-popper@1.2.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@floating-ui/react-dom': 2.1.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-use-rect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
@ -2921,19 +2960,19 @@ snapshots:
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-portal@1.1.9(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-portal@1.1.9(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-presence@1.1.4(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-presence@1.1.4(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
@ -2941,42 +2980,42 @@ snapshots:
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/react-slot': 1.2.3(@types/react@19.1.6)(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-roving-focus@1.1.10(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-roving-focus@1.1.10(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
'@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-id': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.6)(react@19.1.0)
|
||||
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.6)(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-separator@1.1.7(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
'@radix-ui/react-separator@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.6))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react-dom': 19.1.5(@types/react@19.1.6)
|
||||
'@types/react-dom': 19.1.6(@types/react@19.1.6)
|
||||
|
||||
'@radix-ui/react-slot@1.2.3(@types/react@19.1.6)(react@19.1.0)':
|
||||
dependencies:
|
||||
@ -3070,7 +3109,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@supabase/node-fetch': 2.6.15
|
||||
|
||||
'@supabase/realtime-js@2.11.9':
|
||||
'@supabase/realtime-js@2.11.10':
|
||||
dependencies:
|
||||
'@supabase/node-fetch': 2.6.15
|
||||
'@types/phoenix': 1.6.6
|
||||
@ -3080,22 +3119,22 @@ snapshots:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
||||
'@supabase/ssr@0.6.1(@supabase/supabase-js@2.49.9)':
|
||||
'@supabase/ssr@0.6.1(@supabase/supabase-js@2.49.10)':
|
||||
dependencies:
|
||||
'@supabase/supabase-js': 2.49.9
|
||||
'@supabase/supabase-js': 2.49.10
|
||||
cookie: 1.0.2
|
||||
|
||||
'@supabase/storage-js@2.7.1':
|
||||
dependencies:
|
||||
'@supabase/node-fetch': 2.6.15
|
||||
|
||||
'@supabase/supabase-js@2.49.9':
|
||||
'@supabase/supabase-js@2.49.10':
|
||||
dependencies:
|
||||
'@supabase/auth-js': 2.69.1
|
||||
'@supabase/functions-js': 2.4.4
|
||||
'@supabase/node-fetch': 2.6.15
|
||||
'@supabase/postgrest-js': 1.19.4
|
||||
'@supabase/realtime-js': 2.11.9
|
||||
'@supabase/realtime-js': 2.11.10
|
||||
'@supabase/storage-js': 2.7.1
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
@ -3107,17 +3146,17 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@t3-oss/env-core@0.12.0(typescript@5.8.3)(zod@3.25.49)':
|
||||
'@t3-oss/env-core@0.12.0(typescript@5.8.3)(zod@3.25.51)':
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
zod: 3.25.49
|
||||
zod: 3.25.51
|
||||
|
||||
'@t3-oss/env-nextjs@0.12.0(typescript@5.8.3)(zod@3.25.49)':
|
||||
'@t3-oss/env-nextjs@0.12.0(typescript@5.8.3)(zod@3.25.51)':
|
||||
dependencies:
|
||||
'@t3-oss/env-core': 0.12.0(typescript@5.8.3)(zod@3.25.49)
|
||||
'@t3-oss/env-core': 0.12.0(typescript@5.8.3)(zod@3.25.51)
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
zod: 3.25.49
|
||||
zod: 3.25.51
|
||||
|
||||
'@tailwindcss/node@4.1.8':
|
||||
dependencies:
|
||||
@ -3196,19 +3235,53 @@ snapshots:
|
||||
tslib: 2.8.1
|
||||
optional: true
|
||||
|
||||
'@types/body-parser@1.19.5':
|
||||
dependencies:
|
||||
'@types/connect': 3.4.38
|
||||
'@types/node': 20.17.57
|
||||
|
||||
'@types/connect@3.4.38':
|
||||
dependencies:
|
||||
'@types/node': 20.17.57
|
||||
|
||||
'@types/cors@2.8.18':
|
||||
dependencies:
|
||||
'@types/node': 20.17.57
|
||||
|
||||
'@types/estree@1.0.7': {}
|
||||
|
||||
'@types/express-serve-static-core@5.0.6':
|
||||
dependencies:
|
||||
'@types/node': 20.17.57
|
||||
'@types/qs': 6.14.0
|
||||
'@types/range-parser': 1.2.7
|
||||
'@types/send': 0.17.4
|
||||
|
||||
'@types/express@5.0.2':
|
||||
dependencies:
|
||||
'@types/body-parser': 1.19.5
|
||||
'@types/express-serve-static-core': 5.0.6
|
||||
'@types/serve-static': 1.15.7
|
||||
|
||||
'@types/http-errors@2.0.4': {}
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
|
||||
'@types/json5@0.0.29': {}
|
||||
|
||||
'@types/mime@1.3.5': {}
|
||||
|
||||
'@types/node@20.17.57':
|
||||
dependencies:
|
||||
undici-types: 6.19.8
|
||||
|
||||
'@types/phoenix@1.6.6': {}
|
||||
|
||||
'@types/react-dom@19.1.5(@types/react@19.1.6)':
|
||||
'@types/qs@6.14.0': {}
|
||||
|
||||
'@types/range-parser@1.2.7': {}
|
||||
|
||||
'@types/react-dom@19.1.6(@types/react@19.1.6)':
|
||||
dependencies:
|
||||
'@types/react': 19.1.6
|
||||
|
||||
@ -3216,6 +3289,17 @@ snapshots:
|
||||
dependencies:
|
||||
csstype: 3.1.3
|
||||
|
||||
'@types/send@0.17.4':
|
||||
dependencies:
|
||||
'@types/mime': 1.3.5
|
||||
'@types/node': 20.17.57
|
||||
|
||||
'@types/serve-static@1.15.7':
|
||||
dependencies:
|
||||
'@types/http-errors': 2.0.4
|
||||
'@types/node': 20.17.57
|
||||
'@types/send': 0.17.4
|
||||
|
||||
'@types/ws@8.18.1':
|
||||
dependencies:
|
||||
'@types/node': 20.17.57
|
||||
@ -3507,7 +3591,7 @@ snapshots:
|
||||
|
||||
callsites@3.1.0: {}
|
||||
|
||||
caniuse-lite@1.0.30001720: {}
|
||||
caniuse-lite@1.0.30001721: {}
|
||||
|
||||
chalk@4.1.2:
|
||||
dependencies:
|
||||
@ -4350,7 +4434,7 @@ snapshots:
|
||||
'@swc/counter': 0.1.3
|
||||
'@swc/helpers': 0.5.15
|
||||
busboy: 1.6.0
|
||||
caniuse-lite: 1.0.30001720
|
||||
caniuse-lite: 1.0.30001721
|
||||
postcss: 8.4.31
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
@ -4803,7 +4887,7 @@ snapshots:
|
||||
|
||||
tslib@2.8.1: {}
|
||||
|
||||
tw-animate-css@1.3.3: {}
|
||||
tw-animate-css@1.3.4: {}
|
||||
|
||||
type-check@0.4.0:
|
||||
dependencies:
|
||||
@ -4968,4 +5052,4 @@ snapshots:
|
||||
|
||||
yocto-queue@0.1.0: {}
|
||||
|
||||
zod@3.25.49: {}
|
||||
zod@3.25.51: {}
|
||||
|
@ -81,7 +81,7 @@ const ProfilePage = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='max-w-3xl min-w-sm mx-auto p-4'>
|
||||
<div className='max-w-3xl min-w-sm md:min-w-lg mx-auto p-4'>
|
||||
<Card className='mb-8'>
|
||||
<CardHeader className='pb-2'>
|
||||
<CardTitle className='text-2xl'>Your Profile</CardTitle>
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
getSignedUrl,
|
||||
getUser,
|
||||
updateProfile as updateProfileAction,
|
||||
} from '@/lib/actions';
|
||||
} from '@/lib/hooks';
|
||||
import {
|
||||
type User,
|
||||
type Profile,
|
||||
@ -119,7 +119,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
||||
};
|
||||
}, [fetchUserData]);
|
||||
|
||||
const updateProfile = async (data: {
|
||||
const updateProfile = useCallback(async (data: {
|
||||
full_name?: string;
|
||||
email?: string;
|
||||
avatar_url?: string;
|
||||
@ -151,15 +151,12 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
||||
console.error('Error updating profile:', error);
|
||||
toast.error(error instanceof Error ? error.message : 'Failed to update profile');
|
||||
return { success: false, error };
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
const refreshUserData = async () => {
|
||||
console.log('Manual refresh triggered');
|
||||
const refreshUserData = useCallback(async () => {
|
||||
await fetchUserData();
|
||||
};
|
||||
}, [fetchUserData]);
|
||||
|
||||
const value = {
|
||||
user,
|
||||
@ -171,7 +168,11 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
||||
refreshUserData,
|
||||
};
|
||||
|
||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||
return (
|
||||
<AuthContext.Provider value={value}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export const useAuth = () => {
|
||||
|
@ -28,7 +28,7 @@ export const AvatarUpload = ({ onAvatarUploaded }: AvatarUploadProps) => {
|
||||
maxHeight: 500,
|
||||
quality: 0.8,
|
||||
},
|
||||
prevPath: profile?.avatar_url,
|
||||
replace: {replace: true, path: profile?.avatar_url ?? file.name},
|
||||
});
|
||||
if (result.success && result.path) {
|
||||
await onAvatarUploaded(result.path);
|
||||
|
@ -18,6 +18,7 @@ export const env = createEnv({
|
||||
client: {
|
||||
NEXT_PUBLIC_SUPABASE_URL: z.string().url(),
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY: z.string().min(1),
|
||||
NEXT_PUBLIC_SITE_URL: z.string().url(),
|
||||
},
|
||||
|
||||
/**
|
||||
@ -29,6 +30,7 @@ export const env = createEnv({
|
||||
|
||||
NEXT_PUBLIC_SUPABASE_URL: process.env.NEXT_PUBLIC_SUPABASE_URL,
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
|
||||
NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL,
|
||||
},
|
||||
/**
|
||||
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
|
||||
|
14
src/lib/actions/storage.ts
Normal file → Executable file
14
src/lib/actions/storage.ts
Normal file → Executable file
@ -23,18 +23,16 @@ export type UploadStorageProps = {
|
||||
file: File;
|
||||
options?: {
|
||||
cacheControl?: string;
|
||||
upsert?: boolean;
|
||||
contentType?: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type ReplaceStorageProps = {
|
||||
bucket: string;
|
||||
prevPath: string;
|
||||
path: string;
|
||||
file: File;
|
||||
options?: {
|
||||
cacheControl?: string;
|
||||
upsert?: boolean;
|
||||
contentType?: string;
|
||||
};
|
||||
};
|
||||
@ -135,21 +133,15 @@ export const uploadFile = async ({
|
||||
|
||||
export const replaceFile = async ({
|
||||
bucket,
|
||||
prevPath,
|
||||
path,
|
||||
file,
|
||||
options = {},
|
||||
}: ReplaceStorageProps): Promise<Result<string>> => {
|
||||
try {
|
||||
options.upsert = true;
|
||||
const supabase = await createServerClient();
|
||||
//const deleteFileData = await deleteFile({
|
||||
//bucket,
|
||||
//path: [...prevPath],
|
||||
//});
|
||||
const { data, error } = await supabase.storage
|
||||
.from(bucket)
|
||||
//.update(path, file, options);
|
||||
.update(prevPath, file, options);
|
||||
.update(path, file, {...options, upsert: true});
|
||||
if (error) throw error;
|
||||
if (!data?.path) throw new Error('No path returned from upload');
|
||||
return { success: true, data: data.path };
|
||||
|
133
src/lib/hooks/auth.ts
Normal file
133
src/lib/hooks/auth.ts
Normal file
@ -0,0 +1,133 @@
|
||||
'use client'
|
||||
import { encodedRedirect } from '@/utils/utils';
|
||||
import { createClient } from '@/utils/supabase';
|
||||
import { redirect } from 'next/navigation';
|
||||
import type { User } from '@/utils/supabase';
|
||||
import type { Result } from './index';
|
||||
|
||||
export const signUp = async (formData: FormData) => {
|
||||
const name = formData.get('name') as string;
|
||||
const email = formData.get('email') as string;
|
||||
const password = formData.get('password') as string;
|
||||
const supabase = createClient();
|
||||
const origin = process.env.NEXT_PUBLIC_SITE_URL!;
|
||||
|
||||
if (!email || !password) {
|
||||
return encodedRedirect(
|
||||
'error',
|
||||
'/sign-up',
|
||||
'Email & password are required',
|
||||
);
|
||||
}
|
||||
|
||||
const { error } = await supabase.auth.signUp({
|
||||
email,
|
||||
password,
|
||||
options: {
|
||||
emailRedirectTo: `${origin}/auth/callback`,
|
||||
data: {
|
||||
full_name: name,
|
||||
email,
|
||||
provider: 'email',
|
||||
},
|
||||
},
|
||||
});
|
||||
if (error) {
|
||||
return encodedRedirect('error', '/sign-up', error.message);
|
||||
} else {
|
||||
return encodedRedirect(
|
||||
'success',
|
||||
'/sign-up',
|
||||
'Thanks for signing up! Please check your email for a verification link.',
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const signIn = async (
|
||||
formData: FormData,
|
||||
): Promise<Result<null>> => {
|
||||
const email = formData.get('email') as string;
|
||||
const password = formData.get('password') as string;
|
||||
const supabase = createClient();
|
||||
|
||||
const { error } = await supabase.auth.signInWithPassword({
|
||||
email,
|
||||
password,
|
||||
});
|
||||
if (error) {
|
||||
return { success: false, error: error.message };
|
||||
} else {
|
||||
return { success: true, data: null };
|
||||
}
|
||||
};
|
||||
|
||||
export const forgotPassword = async (formData: FormData) => {
|
||||
const email = formData.get('email') as string;
|
||||
const supabase = createClient();
|
||||
const origin = process.env.NEXT_PUBLIC_SITE_URL!;
|
||||
const callbackUrl = formData.get('callbackUrl') as string;
|
||||
|
||||
if (!email) {
|
||||
return encodedRedirect('error', '/forgot-password', 'Email is required');
|
||||
}
|
||||
|
||||
const { error } = await supabase.auth.resetPasswordForEmail(email, {
|
||||
redirectTo: `${origin}/auth/callback?redirect_to=/reset-password`,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
return encodedRedirect(
|
||||
'error',
|
||||
'/forgot-password',
|
||||
'Could not reset password',
|
||||
);
|
||||
}
|
||||
|
||||
if (callbackUrl) {
|
||||
return redirect(callbackUrl);
|
||||
}
|
||||
|
||||
return encodedRedirect(
|
||||
'success',
|
||||
'/forgot-password',
|
||||
'Check your email for a link to reset your password.',
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export const resetPassword = async (formData: FormData): Promise<Result<null>> => {
|
||||
const password = formData.get('password') as string;
|
||||
const confirmPassword = formData.get('confirmPassword') as string;
|
||||
if (!password || !confirmPassword) {
|
||||
return { success: false, error: 'Password and confirm password are required!' };
|
||||
}
|
||||
const supabase = createClient();
|
||||
if (password !== confirmPassword) {
|
||||
return { success: false, error: 'Passwords do not match!' };
|
||||
}
|
||||
const { error } = await supabase.auth.updateUser({
|
||||
password,
|
||||
});
|
||||
if (error) {
|
||||
return { success: false, error: `Password update failed: ${error.message}` };
|
||||
}
|
||||
return { success: true, data: null };
|
||||
};
|
||||
|
||||
export const signOut = async (): Promise<Result<null>> => {
|
||||
const supabase = createClient();
|
||||
const { error } = await supabase.auth.signOut();
|
||||
if (error) return { success: false, error: error.message }
|
||||
return { success: true, data: null };
|
||||
};
|
||||
|
||||
export const getUser = async (): Promise<Result<User>> => {
|
||||
try {
|
||||
const supabase = createClient();
|
||||
const { data, error } = await supabase.auth.getUser();
|
||||
if (error) throw error;
|
||||
return { success: true, data: data.user };
|
||||
} catch (error) {
|
||||
return { success: false, error: 'Could not get user!' };
|
||||
}
|
||||
};
|
9
src/lib/hooks/index.ts
Normal file → Executable file
9
src/lib/hooks/index.ts
Normal file → Executable file
@ -1,2 +1,9 @@
|
||||
export * from './resizeImage';
|
||||
export * from './auth';
|
||||
export * from './public';
|
||||
//export * from './resizeImage';
|
||||
export * from './storage';
|
||||
export * from './useFileUpload';
|
||||
|
||||
export type Result<T> =
|
||||
| { success: true; data: T }
|
||||
| { success: false; error: string };
|
||||
|
79
src/lib/hooks/public.ts
Normal file
79
src/lib/hooks/public.ts
Normal file
@ -0,0 +1,79 @@
|
||||
'use client';
|
||||
|
||||
import { createClient, type Profile } from '@/utils/supabase';
|
||||
import { getUser } from '@/lib/hooks';
|
||||
import type { Result } from './index';
|
||||
|
||||
export const getProfile = async (): Promise<Result<Profile>> => {
|
||||
try {
|
||||
const user = await getUser();
|
||||
if (!user.success || user.data === undefined)
|
||||
throw new Error('User not found');
|
||||
const supabase = createClient();
|
||||
const { data, error } = await supabase
|
||||
.from('profiles')
|
||||
.select('*')
|
||||
.eq('id', user.data.id)
|
||||
.single();
|
||||
if (error) throw error;
|
||||
return { success: true, data: data as Profile };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Unknown error getting profile',
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
type updateProfileProps = {
|
||||
full_name?: string;
|
||||
email?: string;
|
||||
avatar_url?: string;
|
||||
};
|
||||
|
||||
export const updateProfile = async ({
|
||||
full_name,
|
||||
email,
|
||||
avatar_url,
|
||||
}: updateProfileProps): Promise<Result<Profile>> => {
|
||||
try {
|
||||
if (
|
||||
full_name === undefined &&
|
||||
email === undefined &&
|
||||
avatar_url === undefined
|
||||
)
|
||||
throw new Error('No profile data provided');
|
||||
|
||||
const userResponse = await getUser();
|
||||
if (!userResponse.success || userResponse.data === undefined)
|
||||
throw new Error('User not found');
|
||||
|
||||
const supabase = createClient();
|
||||
const { data, error } = await supabase
|
||||
.from('profiles')
|
||||
.update({
|
||||
...(full_name !== undefined && { full_name }),
|
||||
...(email !== undefined && { email }),
|
||||
...(avatar_url !== undefined && { avatar_url }),
|
||||
})
|
||||
.eq('id', userResponse.data.id)
|
||||
.select()
|
||||
.single();
|
||||
if (error) throw error;
|
||||
return {
|
||||
success: true,
|
||||
data: data as Profile,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Unknown error updating profile',
|
||||
};
|
||||
}
|
||||
};
|
@ -1,59 +0,0 @@
|
||||
'use client'
|
||||
|
||||
export type resizeImageProps = {
|
||||
file: File,
|
||||
options?: {
|
||||
maxWidth?: number,
|
||||
maxHeight?: number,
|
||||
quality?: number,
|
||||
}
|
||||
};
|
||||
|
||||
export const resizeImage = async ({
|
||||
file,
|
||||
options = {},
|
||||
}: resizeImageProps): Promise<File> => {
|
||||
const {
|
||||
maxWidth = 800,
|
||||
maxHeight = 800,
|
||||
quality = 0.8,
|
||||
} = options;
|
||||
return new Promise((resolve) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = (event) => {
|
||||
const img = new Image();
|
||||
img.src = event.target?.result as string;
|
||||
img.onload = () => {
|
||||
let width = img.width;
|
||||
let height = img.height;
|
||||
if (width > height) {
|
||||
if (width > maxWidth) {
|
||||
height = Math.round((height * maxWidth / width));
|
||||
width = maxWidth;
|
||||
}
|
||||
} else if (height > maxHeight) {
|
||||
width = Math.round((width * maxHeight / height));
|
||||
height = maxHeight;
|
||||
}
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx?.drawImage(img, 0, 0, width, height);
|
||||
canvas.toBlob(
|
||||
(blob) => {
|
||||
if (!blob) return;
|
||||
const resizedFile = new File([blob], file.name, {
|
||||
type: 'image/jpeg',
|
||||
lastModified: Date.now(),
|
||||
});
|
||||
resolve(resizedFile);
|
||||
},
|
||||
'image/jpeg',
|
||||
quality
|
||||
);
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
265
src/lib/hooks/storage.ts
Normal file
265
src/lib/hooks/storage.ts
Normal file
@ -0,0 +1,265 @@
|
||||
'use client';
|
||||
|
||||
import { createClient } from '@/utils/supabase';
|
||||
import type { Result } from './index';
|
||||
|
||||
export type GetStorageProps = {
|
||||
bucket: string;
|
||||
url: string;
|
||||
seconds?: number;
|
||||
transform?: {
|
||||
width?: number;
|
||||
height?: number;
|
||||
quality?: number;
|
||||
format?: 'origin';
|
||||
resize?: 'cover' | 'contain' | 'fill';
|
||||
};
|
||||
download?: boolean | string;
|
||||
};
|
||||
|
||||
export type UploadStorageProps = {
|
||||
bucket: string;
|
||||
path: string;
|
||||
file: File;
|
||||
options?: {
|
||||
cacheControl?: string;
|
||||
contentType?: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type ReplaceStorageProps = {
|
||||
bucket: string;
|
||||
path: string;
|
||||
file: File;
|
||||
options?: {
|
||||
cacheControl?: string;
|
||||
contentType?: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type resizeImageProps = {
|
||||
file: File,
|
||||
options?: {
|
||||
maxWidth?: number,
|
||||
maxHeight?: number,
|
||||
quality?: number,
|
||||
}
|
||||
};
|
||||
|
||||
export const getSignedUrl = async ({
|
||||
bucket,
|
||||
url,
|
||||
seconds = 3600,
|
||||
transform = {},
|
||||
download = false,
|
||||
}: GetStorageProps): Promise<Result<string>> => {
|
||||
try {
|
||||
const supabase = createClient();
|
||||
const { data, error } = await supabase.storage
|
||||
.from(bucket)
|
||||
.createSignedUrl(url, seconds, {
|
||||
download,
|
||||
transform,
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
if (!data?.signedUrl) throw new Error('No signed URL returned');
|
||||
|
||||
return { success: true, data: data.signedUrl };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Unknown error getting signed URL',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const getPublicUrl = async ({
|
||||
bucket,
|
||||
url,
|
||||
transform = {},
|
||||
download = false,
|
||||
}: GetStorageProps): Promise<Result<string>> => {
|
||||
try {
|
||||
const supabase = createClient();
|
||||
const { data } = supabase.storage
|
||||
.from(bucket)
|
||||
.getPublicUrl(url, {
|
||||
download,
|
||||
transform,
|
||||
});
|
||||
|
||||
if (!data?.publicUrl) throw new Error('No public URL returned');
|
||||
|
||||
return { success: true, data: data.publicUrl };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Unknown error getting public URL',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const uploadFile = async ({
|
||||
bucket,
|
||||
path,
|
||||
file,
|
||||
options = {},
|
||||
}: UploadStorageProps): Promise<Result<string>> => {
|
||||
try {
|
||||
const supabase = createClient();
|
||||
const { data, error } = await supabase.storage
|
||||
.from(bucket)
|
||||
.upload(path, file, options);
|
||||
|
||||
if (error) throw error;
|
||||
if (!data?.path) throw new Error('No path returned from upload');
|
||||
|
||||
return { success: true, data: data.path };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
error instanceof Error ? error.message : 'Unknown error uploading file',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const replaceFile = async ({
|
||||
bucket,
|
||||
path,
|
||||
file,
|
||||
options = {},
|
||||
}: ReplaceStorageProps): Promise<Result<string>> => {
|
||||
try {
|
||||
const supabase = createClient();
|
||||
const { data, error } = await supabase.storage
|
||||
.from(bucket)
|
||||
.update(path, file, {
|
||||
...options,
|
||||
upsert: true,
|
||||
});
|
||||
if (error) throw error;
|
||||
if (!data?.path) throw new Error('No path returned from upload');
|
||||
return { success: true, data: data.path };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
error instanceof Error ? error.message : 'Unknown error replacing file',
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Add a helper to delete files
|
||||
export const deleteFile = async ({
|
||||
bucket,
|
||||
path,
|
||||
}: {
|
||||
bucket: string;
|
||||
path: string[];
|
||||
}): Promise<Result<null>> => {
|
||||
try {
|
||||
const supabase = createClient();
|
||||
const { error } = await supabase.storage.from(bucket).remove(path);
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
return { success: true, data: null };
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
error instanceof Error ? error.message : 'Unknown error deleting file',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Add a helper to list files in a bucket
|
||||
export const listFiles = async ({
|
||||
bucket,
|
||||
path = '',
|
||||
options = {},
|
||||
}: {
|
||||
bucket: string;
|
||||
path?: string;
|
||||
options?: {
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
sortBy?: { column: string; order: 'asc' | 'desc' };
|
||||
};
|
||||
}): Promise<Result<Array<{ name: string; id: string; metadata: unknown }>>> => {
|
||||
try {
|
||||
const supabase = createClient();
|
||||
const { data, error } = await supabase.storage
|
||||
.from(bucket)
|
||||
.list(path, options);
|
||||
|
||||
if (error) throw error;
|
||||
if (!data) throw new Error('No data returned from list operation');
|
||||
|
||||
return { success: true, data };
|
||||
} catch (error) {
|
||||
console.error('Could not list files!', error);
|
||||
return {
|
||||
success: false,
|
||||
error:
|
||||
error instanceof Error ? error.message : 'Unknown error listing files',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const resizeImage = async ({
|
||||
file,
|
||||
options = {},
|
||||
}: resizeImageProps): Promise<File> => {
|
||||
const {
|
||||
maxWidth = 800,
|
||||
maxHeight = 800,
|
||||
quality = 0.8,
|
||||
} = options;
|
||||
return new Promise((resolve) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = (event) => {
|
||||
const img = new Image();
|
||||
img.src = event.target?.result as string;
|
||||
img.onload = () => {
|
||||
let width = img.width;
|
||||
let height = img.height;
|
||||
if (width > height) {
|
||||
if (width > maxWidth) {
|
||||
height = Math.round((height * maxWidth / width));
|
||||
width = maxWidth;
|
||||
}
|
||||
} else if (height > maxHeight) {
|
||||
width = Math.round((width * maxHeight / height));
|
||||
height = maxHeight;
|
||||
}
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx?.drawImage(img, 0, 0, width, height);
|
||||
canvas.toBlob(
|
||||
(blob) => {
|
||||
if (!blob) return;
|
||||
const resizedFile = new File([blob], file.name, {
|
||||
type: 'imgage/jpeg',
|
||||
lastModified: Date.now(),
|
||||
});
|
||||
resolve(resizedFile);
|
||||
},
|
||||
'image/jpeg',
|
||||
quality
|
||||
);
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
@ -1,11 +1,15 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useRef } from 'react';
|
||||
import { deleteFile, replaceFile, uploadFile } from '@/lib/actions';
|
||||
import { replaceFile, uploadFile } from '@/lib/hooks';
|
||||
import { toast } from 'sonner';
|
||||
import { useAuth } from '@/components/context/auth';
|
||||
import { resizeImage } from '@/lib/hooks';
|
||||
|
||||
export type Replace =
|
||||
| { replace: true, path: string }
|
||||
| false;
|
||||
|
||||
export type uploadToStorageProps = {
|
||||
file: File;
|
||||
bucket: string;
|
||||
@ -15,7 +19,7 @@ export type uploadToStorageProps = {
|
||||
maxHeight?: number;
|
||||
quality?: number;
|
||||
};
|
||||
prevPath?: string | null;
|
||||
replace?: Replace;
|
||||
};
|
||||
|
||||
export const useFileUpload = () => {
|
||||
@ -28,25 +32,16 @@ export const useFileUpload = () => {
|
||||
bucket,
|
||||
resize = false,
|
||||
options = {},
|
||||
prevPath = null,
|
||||
replace = false,
|
||||
}: uploadToStorageProps) => {
|
||||
try {
|
||||
if (!isAuthenticated) throw new Error('User is not authenticated');
|
||||
|
||||
setIsUploading(true);
|
||||
if (prevPath !== null) {
|
||||
const deleteResult = await deleteFile({
|
||||
bucket,
|
||||
path: [...prevPath],
|
||||
});
|
||||
if (!deleteResult.success) {
|
||||
console.error('Error deleting file:', deleteResult.error);
|
||||
throw new Error(deleteResult.error || `Failed to delete ${prevPath}`);
|
||||
} else console.log('Delete sucessful!')
|
||||
console.log('Deleted file path: ', deleteResult.data)
|
||||
if (replace) {
|
||||
const updateResult = await replaceFile({
|
||||
bucket,
|
||||
prevPath: prevPath,
|
||||
path: replace.path,
|
||||
file,
|
||||
options: {
|
||||
contentType: file.type,
|
||||
@ -74,7 +69,6 @@ export const useFileUpload = () => {
|
||||
path: fileName,
|
||||
file: fileToUpload,
|
||||
options: {
|
||||
upsert: true,
|
||||
contentType: file.type,
|
||||
},
|
||||
});
|
||||
|
Reference in New Issue
Block a user