From 365a89ac63a89f4f5b7b1e8057a079da882adf38 Mon Sep 17 00:00:00 2001 From: Nyxian <98602240+tockawaffle@users.noreply.github.com> Date: Tue, 10 Dec 2024 18:49:47 -0300 Subject: [PATCH] initial start --- .gitignore | 13 +- .idea/.gitignore | 8 + .idea/discord.xml | 14 + .idea/material_theme_project_new.xml | 13 + .idea/modules.xml | 8 + .idea/sipher.iml | 12 + .idea/vcs.xml | 6 + README.md | 103 +- components.json | 14 +- next.config.ts | 7 + package-lock.json | 2804 +++++++++++++++++++++++ package.json | 51 +- postcss.config.mjs | 8 + public/logos/logo-light.png | Bin 0 -> 43282 bytes public/logos/logo.png | Bin 0 -> 43429 bytes public/logos/united-chat.png | Bin 0 -> 6188 bytes src/app/api/auth/get_user/route.ts | 44 + src/app/api/auth/login/route.ts | 38 + src/app/api/auth/register/route.ts | 45 + src/app/api/user/get/threads/route.ts | 37 + src/app/auth/login/login.ts | 36 + src/app/auth/login/page.tsx | 198 ++ src/app/auth/login/register.ts | 38 + src/app/globals.css | 61 + src/app/layout.tsx | 75 + src/app/page.tsx | 12 + src/components/main/sidebar/mobile.tsx | 58 + src/components/main/sidebar/sidebar.tsx | 229 ++ src/components/ui/avatar.tsx | 50 + src/components/ui/button.tsx | 57 + src/components/ui/card.tsx | 76 + src/components/ui/input.tsx | 22 + src/components/ui/label.tsx | 26 + src/components/ui/scroll-area.tsx | 48 + src/components/ui/separator.tsx | 31 + src/components/ui/toast.tsx | 129 ++ src/components/ui/toaster.tsx | 35 + src/contexts/user.tsx | 82 + src/hooks/shared-states.tsx | 171 ++ src/hooks/use-toast.ts | 194 ++ src/lib/auth/index.ts | 41 + src/lib/supabase/server.ts | 38 + src/lib/utils.ts | 6 + src/middleware.ts | 59 + src/types/user.d.ts | 31 + tailwind.config.ts | 128 +- tsconfig.json | 7 +- 47 files changed, 4970 insertions(+), 193 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/discord.xml create mode 100644 .idea/material_theme_project_new.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/sipher.iml create mode 100644 .idea/vcs.xml create mode 100644 next.config.ts create mode 100644 package-lock.json create mode 100644 postcss.config.mjs create mode 100644 public/logos/logo-light.png create mode 100644 public/logos/logo.png create mode 100644 public/logos/united-chat.png create mode 100644 src/app/api/auth/get_user/route.ts create mode 100644 src/app/api/auth/login/route.ts create mode 100644 src/app/api/auth/register/route.ts create mode 100644 src/app/api/user/get/threads/route.ts create mode 100644 src/app/auth/login/login.ts create mode 100644 src/app/auth/login/page.tsx create mode 100644 src/app/auth/login/register.ts create mode 100644 src/app/globals.css create mode 100644 src/app/layout.tsx create mode 100644 src/app/page.tsx create mode 100644 src/components/main/sidebar/mobile.tsx create mode 100644 src/components/main/sidebar/sidebar.tsx create mode 100644 src/components/ui/avatar.tsx create mode 100644 src/components/ui/button.tsx create mode 100644 src/components/ui/card.tsx create mode 100644 src/components/ui/input.tsx create mode 100644 src/components/ui/label.tsx create mode 100644 src/components/ui/scroll-area.tsx create mode 100644 src/components/ui/separator.tsx create mode 100644 src/components/ui/toast.tsx create mode 100644 src/components/ui/toaster.tsx create mode 100644 src/contexts/user.tsx create mode 100644 src/hooks/shared-states.tsx create mode 100644 src/hooks/use-toast.ts create mode 100644 src/lib/auth/index.ts create mode 100644 src/lib/supabase/server.ts create mode 100644 src/lib/utils.ts create mode 100644 src/middleware.ts create mode 100644 src/types/user.d.ts diff --git a/.gitignore b/.gitignore index 00bba9b..d32cc78 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,12 @@ # dependencies /node_modules /.pnp -.pnp.js -.yarn/install-state.gz +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions # testing /coverage @@ -25,9 +29,8 @@ npm-debug.log* yarn-debug.log* yarn-error.log* -# local env files -.env*.local -.env +# env files (can opt-in for committing if needed) +.env* # vercel .vercel diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..104c42f --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml new file mode 100644 index 0000000..9c331f5 --- /dev/null +++ b/.idea/material_theme_project_new.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..6d06177 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/sipher.iml b/.idea/sipher.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/sipher.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 53c555a..3ea1400 100644 --- a/README.md +++ b/README.md @@ -1,96 +1,33 @@ - - Next.js and Supabase Starter Kit - the fastest way to build apps with Next.js and Supabase -

Next.js and Supabase Starter Kit

-
+- 1 - What will your software do? -

- The fastest way to build apps with Next.js and Supabase -

+My software will encrypt messages just like WhatsApp does by using a system of people having a key and sharing them +with one another. -

- Features · - Demo · - Deploy to Vercel · - Clone and run locally · - Feedback and issues - More Examples -

-
+- 1.1 - What features will it have? -## Features +I'll let the user choose multiple encryption methods, this will make it more secure and reliable. +Only the user will have its password that he could share with another user. -- Works across the entire [Next.js](https://nextjs.org) stack - - App Router - - Pages Router - - Middleware - - Client - - Server - - It just works! -- supabase-ssr. A package to configure Supabase Auth to use cookies -- Styling with [Tailwind CSS](https://tailwindcss.com) -- Components with [shadcn/ui](https://ui.shadcn.com/) -- Optional deployment with [Supabase Vercel Integration and Vercel deploy](#deploy-your-own) - - Environment variables automatically assigned to Vercel project +- 1.2 How will it be executed? -## Demo +Mainly by creating a database that would only hold a username and a password, could use Supabase for that +or a simple MongoDb cluster. -You can view a fully working demo at [demo-nextjs-with-supabase.vercel.app](https://demo-nextjs-with-supabase.vercel.app/). +- 2- What new skills will you need to acquire? -## Deploy to Vercel +For this one, mainly how cryptography works on message exchanging. -Vercel deployment will guide you through creating a Supabase account and project. +- 2.1 - What topics will you need to research? -After installation of the Supabase integration, all relevant environment variables will be assigned to the project so the deployment is fully functioning. +I'll also have to research about the recommended cases on how to store or handle each user. -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-supabase&project-name=nextjs-with-supabase&repository-name=nextjs-with-supabase&demo-title=nextjs-with-supabase&demo-description=This+starter+configures+Supabase+Auth+to+use+cookies%2C+making+the+user%27s+session+available+throughout+the+entire+Next.js+app+-+Client+Components%2C+Server+Components%2C+Route+Handlers%2C+Server+Actions+and+Middleware.&demo-url=https%3A%2F%2Fdemo-nextjs-with-supabase.vercel.app%2F&external-id=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fwith-supabase&demo-image=https%3A%2F%2Fdemo-nextjs-with-supabase.vercel.app%2Fopengraph-image.png) +- 3- If working with one or two classmates, who will do what? -The above will also clone the Starter kit to your GitHub, you can clone that locally and develop locally. +Will do by myself. -If you wish to just develop locally and not deploy to Vercel, [follow the steps below](#clone-and-run-locally). +- 4 - In the world of software, most everything takes longer to implement than you expect. And so it’s not uncommon to accomplish less in a fixed amount of time than you hope. What might you consider to be a good outcome for your project? A better outcome? The best outcome? -## Clone and run locally - -1. You'll first need a Supabase project which can be made [via the Supabase dashboard](https://database.new) - -2. Create a Next.js app using the Supabase Starter template npx command - - ```bash - npx create-next-app -e with-supabase - ``` - -3. Use `cd` to change into the app's directory - - ```bash - cd name-of-new-app - ``` - -4. Rename `.env.example` to `.env.local` and update the following: - - ``` - NEXT_PUBLIC_SUPABASE_URL=[INSERT SUPABASE PROJECT URL] - NEXT_PUBLIC_SUPABASE_ANON_KEY=[INSERT SUPABASE PROJECT API ANON KEY] - ``` - - Both `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_ANON_KEY` can be found in [your Supabase project's API settings](https://app.supabase.com/project/_/settings/api) - -5. You can now run the Next.js local development server: - - ```bash - npm run dev - ``` - - The starter kit should now be running on [localhost:3000](http://localhost:3000/). - -6. This template comes with the default shadcn/ui style initialized. If you instead want other ui.shadcn styles, delete `components.json` and [re-install shadcn/ui](https://ui.shadcn.com/docs/installation/next) - -> Check out [the docs for Local Development](https://supabase.com/docs/guides/getting-started/local-development) to also run Supabase locally. - -## Feedback and issues - -Please file feedback and issues over on the [Supabase GitHub org](https://github.com/supabase/supabase/issues/new/choose). - -## More Supabase examples - -- [Next.js Subscription Payments Starter](https://github.com/vercel/nextjs-subscription-payments) -- [Cookie-based Auth and the Next.js 13 App Router (free course)](https://youtube.com/playlist?list=PL5S4mPUpp4OtMhpnp93EFSo42iQ40XjbF) -- [Supabase Auth and the Next.js App Router](https://github.com/supabase/supabase/tree/master/examples/auth/nextjs) +The best outcome for this would be an app that could at least: +Log in/Register the user +Let the user choose its encryption method +Let the user change his password to a maximum of a 12-letter word \ No newline at end of file diff --git a/components.json b/components.json index ec9676b..0e8b633 100644 --- a/components.json +++ b/components.json @@ -1,17 +1,21 @@ { "$schema": "https://ui.shadcn.com/schema.json", - "style": "default", + "style": "new-york", "rsc": true, "tsx": true, "tailwind": { "config": "tailwind.config.ts", - "css": "app/globals.css", + "css": "src/app/globals.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" }, "aliases": { "components": "@/components", - "utils": "@/lib/utils" - } -} + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} \ No newline at end of file diff --git a/next.config.ts b/next.config.ts new file mode 100644 index 0000000..e9ffa30 --- /dev/null +++ b/next.config.ts @@ -0,0 +1,7 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + /* config options here */ +}; + +export default nextConfig; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..0460be7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2804 @@ +{ + "name": "whispr", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "whispr", + "version": "0.1.0", + "dependencies": { + "@radix-ui/react-avatar": "^1.1.1", + "@radix-ui/react-icons": "^1.3.2", + "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-scroll-area": "^1.2.1", + "@radix-ui/react-separator": "^1.1.0", + "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-toast": "^1.2.2", + "@supabase/ssr": "^0.5.2", + "@supabase/supabase-js": "^2.47.3", + "argon2": "^0.41.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "framer-motion": "^11.13.5", + "lucide-react": "^0.468.0", + "next": "15.0.4", + "next-themes": "^0.4.4", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^2.5.5", + "tailwindcss-animate": "^1.0.7" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "postcss": "^8", + "tailwindcss": "^3.4.1", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", + "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.2.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@next/env": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.0.4.tgz", + "integrity": "sha512-WNRvtgnRVDD4oM8gbUcRc27IAhaL4eXQ/2ovGbgLnPGUvdyDr8UdXP4Q/IBDdAdojnD2eScryIDirv0YUCjUVw==" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.4.tgz", + "integrity": "sha512-QecQXPD0yRHxSXWL5Ff80nD+A56sUXZG9koUsjWJwA2Z0ZgVQfuy7gd0/otjxoOovPVHR2eVEvPMHbtZP+pf9w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.4.tgz", + "integrity": "sha512-pb7Bye3y1Og3PlCtnz2oO4z+/b3pH2/HSYkLbL0hbVuTGil7fPen8/3pyyLjdiTLcFJ+ymeU3bck5hd4IPFFCA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.4.tgz", + "integrity": "sha512-12oSaBFjGpB227VHzoXF3gJoK2SlVGmFJMaBJSu5rbpaoT5OjP5OuCLuR9/jnyBF1BAWMs/boa6mLMoJPRriMA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.4.tgz", + "integrity": "sha512-QARO88fR/a+wg+OFC3dGytJVVviiYFEyjc/Zzkjn/HevUuJ7qGUUAUYy5PGVWY1YgTzeRYz78akQrVQ8r+sMjw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.4.tgz", + "integrity": "sha512-Z50b0gvYiUU1vLzfAMiChV8Y+6u/T2mdfpXPHraqpypP7yIT2UV9YBBhcwYkxujmCvGEcRTVWOj3EP7XW/wUnw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.4.tgz", + "integrity": "sha512-7H9C4FAsrTAbA/ENzvFWsVytqRYhaJYKa2B3fyQcv96TkOGVMcvyS6s+sj4jZlacxxTcn7ygaMXUPkEk7b78zw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.4.tgz", + "integrity": "sha512-Z/v3WV5xRaeWlgJzN9r4PydWD8sXV35ywc28W63i37G2jnUgScA4OOgS8hQdiXLxE3gqfSuHTicUhr7931OXPQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.4.tgz", + "integrity": "sha512-NGLchGruagh8lQpDr98bHLyWJXOBSmkEAfK980OiNBa7vNm6PsNoPvzTfstT78WyOeMRQphEQ455rggd7Eo+Dw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@phc/format": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", + "integrity": "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@radix-ui/number": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", + "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" + }, + "node_modules/@radix-ui/react-avatar": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.1.tgz", + "integrity": "sha512-eoOtThOmxeoizxpX6RiEsQZ2wj5r4+zoeqAwO0cBaFQGjJwIH3dIX0OCxNrCyrrdxG+vBweMETh3VziQG7c1kw==", + "dependencies": { + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", + "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-context": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", + "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", + "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-icons": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.2.tgz", + "integrity": "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==", + "peerDependencies": { + "react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz", + "integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", + "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", + "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "dependencies": { + "@radix-ui/react-slot": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.1.tgz", + "integrity": "sha512-FnM1fHfCtEZ1JkyfH/1oMiTcFBQvHKl4vD9WnpwkLgtF+UmnXMCad6ECPTaAjcDjam+ndOEJWgHyKDGNteWSHw==", + "dependencies": { + "@radix-ui/number": "1.1.0", + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.0.tgz", + "integrity": "sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toast": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.2.tgz", + "integrity": "sha512-Z6pqSzmAP/bFJoqMAston4eSNa+ud44NSZTiZUmUen+IOZ5nBY8kzuU5WDBVyFXPtcW6yUalOHsxM/BP6Sv8ww==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-visually-hidden": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", + "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz", + "integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@supabase/auth-js": { + "version": "2.66.1", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.66.1.tgz", + "integrity": "sha512-kOW+04SuDXmP2jRX9JL1Rgzduj8BcOG1qC3RaWdZsxnv89svNCdLRv8PfXW3QPKJdw0k1jF30OlQDPkzbDEL9w==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/functions-js": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.4.3.tgz", + "integrity": "sha512-sOLXy+mWRyu4LLv1onYydq+10mNRQ4rzqQxNhbrKLTLTcdcmS9hbWif0bGz/NavmiQfPs4ZcmQJp4WqOXlR4AQ==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/node-fetch": { + "version": "2.6.15", + "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", + "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.16.3.tgz", + "integrity": "sha512-HI6dsbW68AKlOPofUjDTaosiDBCtW4XAm0D18pPwxoW3zKOE2Ru13Z69Wuys9fd6iTpfDViNco5sgrtnP0666A==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.11.2.tgz", + "integrity": "sha512-u/XeuL2Y0QEhXSoIPZZwR6wMXgB+RQbJzG9VErA3VghVt7uRfSVsjeqd7m5GhX3JR6dM/WRmLbVR8URpDWG4+w==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14", + "@types/phoenix": "^1.5.4", + "@types/ws": "^8.5.10", + "ws": "^8.18.0" + } + }, + "node_modules/@supabase/ssr": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@supabase/ssr/-/ssr-0.5.2.tgz", + "integrity": "sha512-n3plRhr2Bs8Xun1o4S3k1CDv17iH5QY9YcoEvXX3bxV1/5XSasA0mNXYycFmADIdtdE6BG9MRjP5CGIs8qxC8A==", + "dependencies": { + "@types/cookie": "^0.6.0", + "cookie": "^0.7.0" + }, + "peerDependencies": { + "@supabase/supabase-js": "^2.43.4" + } + }, + "node_modules/@supabase/storage-js": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.7.1.tgz", + "integrity": "sha512-asYHcyDR1fKqrMpytAS1zjyEfvxuOIp1CIXX7ji4lHHcJKqyk+sLl/Vxgm4sN6u8zvuUtae9e4kDxQP2qrwWBA==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "2.47.3", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.47.3.tgz", + "integrity": "sha512-AmwTyHtOXdfjLVKiM+neYItB62T4gAl1jV8ZrIg3yp1Z1NICzYfsujJDSuELkrLkYvU/RGfZXpIBheDTt7fmwA==", + "dependencies": { + "@supabase/auth-js": "2.66.1", + "@supabase/functions-js": "2.4.3", + "@supabase/node-fetch": "2.6.15", + "@supabase/postgrest-js": "1.16.3", + "@supabase/realtime-js": "2.11.2", + "@supabase/storage-js": "2.7.1" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/helpers": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz", + "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==" + }, + "node_modules/@types/node": { + "version": "20.17.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.9.tgz", + "integrity": "sha512-0JOXkRyLanfGPE2QRCwgxhzlBAvaRdCNMcvbd7jFfpmD4eEXll7LRwy5ymJmyeZqk7Nh7eD2LeUyQ68BbndmXw==", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/phoenix": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz", + "integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==" + }, + "node_modules/@types/react": { + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.1.tgz", + "integrity": "sha512-YW6614BDhqbpR5KtUYzTA+zlA7nayzJRA9ljz9CQoxthR0sDisYZLuvSMsil36t4EH/uAt8T52Xb4sVw17G+SQ==", + "devOptional": true, + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.2.tgz", + "integrity": "sha512-c1s+7TKFaDRRxr1TxccIX2u7sfCnc3RxkVyBIUA2lCpyqCF+QoAwQ/CBg7bsMdVwP120HEH143VQezKtef5nCg==", + "devOptional": true, + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@types/ws": { + "version": "8.5.13", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", + "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argon2": { + "version": "0.41.1", + "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.41.1.tgz", + "integrity": "sha512-dqCW8kJXke8Ik+McUcMDltrbuAWETPyU6iq+4AhxqKphWi7pChB/Zgd/Tp/o8xRLbg8ksMj46F/vph9wnxpTzQ==", + "hasInstallScript": true, + "dependencies": { + "@phc/format": "^1.0.0", + "node-addon-api": "^8.1.0", + "node-gyp-build": "^4.8.1" + }, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001687", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001687.tgz", + "integrity": "sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/framer-motion": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.13.5.tgz", + "integrity": "sha512-rArI0zPU9VkpS3Wt0J7dmRxAFUWtzPWoSofNQAP0UO276CmJ+Xlf5xN19GMw3w2QsdrS2sU+0+Q2vtuz4IEZaw==", + "dependencies": { + "motion-dom": "^11.13.0", + "motion-utils": "^11.13.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "optional": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/lucide-react": { + "version": "0.468.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.468.0.tgz", + "integrity": "sha512-6koYRhnM2N0GGZIdXzSeiNwguv1gt/FAjZOiPl76roBi3xKEXa4WmfpxgQwTTL4KipXjefrnf3oV4IsYhi4JFA==", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/motion-dom": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.13.0.tgz", + "integrity": "sha512-Oc1MLGJQ6nrvXccXA89lXtOqFyBmvHtaDcTRGT66o8Czl7nuA8BeHAd9MQV1pQKX0d2RHFBFaw5g3k23hQJt0w==" + }, + "node_modules/motion-utils": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.13.0.tgz", + "integrity": "sha512-lq6TzXkH5c/ysJQBxgLXgM01qwBH1b4goTPh57VvZWJbVJZF/0SB31UWEn4EIqbVPf3au88n2rvK17SpDTja1A==" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/next/-/next-15.0.4.tgz", + "integrity": "sha512-nuy8FH6M1FG0lktGotamQDCXhh5hZ19Vo0ht1AOIQWrYJLP598TIUagKtvJrfJ5AGwB/WmDqkKaKhMpVifvGPA==", + "dependencies": { + "@next/env": "15.0.4", + "@swc/counter": "0.1.3", + "@swc/helpers": "0.5.13", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.0.4", + "@next/swc-darwin-x64": "15.0.4", + "@next/swc-linux-arm64-gnu": "15.0.4", + "@next/swc-linux-arm64-musl": "15.0.4", + "@next/swc-linux-x64-gnu": "15.0.4", + "@next/swc-linux-x64-musl": "15.0.4", + "@next/swc-win32-arm64-msvc": "15.0.4", + "@next/swc-win32-x64-msvc": "15.0.4", + "sharp": "^0.33.5" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-66855b96-20241106 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-66855b96-20241106 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next-themes": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.4.tgz", + "integrity": "sha512-LDQ2qIOJF0VnuVrrMSMLrWGjRMkq+0mpgl6e0juCLqdJ+oo8Q84JRWT6Wh11VDQKkMMe+dVzDKLWs5n87T+PkQ==", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-addon-api": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.0.tgz", + "integrity": "sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg==", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", + "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", + "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", + "dependencies": { + "scheduler": "^0.25.0" + }, + "peerDependencies": { + "react": "^19.0.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", + "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==" + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.5.tgz", + "integrity": "sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.16", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.16.tgz", + "integrity": "sha512-TI4Cyx7gDiZ6r44ewaJmt0o6BrMCT5aK5e0rmJ/G9Xq3w7CX/5VXl/zIPEJZFUK5VEqwByyhqNPycPlvcK4ZNw==", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss-animate": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/typescript": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yaml": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + } + } +} diff --git a/package.json b/package.json index 6f02c89..b8d326f 100644 --- a/package.json +++ b/package.json @@ -1,36 +1,41 @@ { + "name": "whispr", + "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev", + "dev": "next dev --turbopack", "build": "next build", - "start": "next start" + "start": "next start", + "lint": "next lint" }, "dependencies": { - "@radix-ui/react-checkbox": "^1.1.1", - "@radix-ui/react-dropdown-menu": "^2.1.1", + "@radix-ui/react-avatar": "^1.1.1", + "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-scroll-area": "^1.2.1", + "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", - "@supabase/ssr": "latest", - "@supabase/supabase-js": "latest", - "autoprefixer": "10.4.20", - "class-variance-authority": "^0.7.0", + "@radix-ui/react-toast": "^1.2.2", + "@supabase/ssr": "^0.5.2", + "@supabase/supabase-js": "^2.47.3", + "argon2": "^0.41.1", + "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "geist": "^1.2.1", - "lucide-react": "^0.456.0", - "next": "latest", - "next-themes": "^0.4.3", - "prettier": "^3.3.3", - "react": "18.3.1", - "react-dom": "18.3.1" + "framer-motion": "^11.13.5", + "lucide-react": "^0.468.0", + "next": "15.0.4", + "next-themes": "^0.4.4", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^2.5.5", + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { - "@types/node": "22.9.0", - "@types/react": "^18.3.12", - "@types/react-dom": "18.3.1", - "postcss": "8.4.49", - "tailwind-merge": "^2.5.2", - "tailwindcss": "3.4.14", - "tailwindcss-animate": "^1.0.7", - "typescript": "5.6.3" + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "postcss": "^8", + "tailwindcss": "^3.4.1", + "typescript": "^5" } } diff --git a/postcss.config.mjs b/postcss.config.mjs new file mode 100644 index 0000000..1a69fd2 --- /dev/null +++ b/postcss.config.mjs @@ -0,0 +1,8 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + tailwindcss: {}, + }, +}; + +export default config; diff --git a/public/logos/logo-light.png b/public/logos/logo-light.png new file mode 100644 index 0000000000000000000000000000000000000000..cb478f19080f33aa03c37235ad31a5260ad89772 GIT binary patch literal 43282 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 literal 0 HcmV?d00001 diff --git a/public/logos/logo.png b/public/logos/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f05e14c6ee9ebbdb9a2559af9d4a33f0b9063838 GIT binary patch literal 43429 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

ycY;zWUV{m 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 Q!T+)_vAX=`;_V0j1;kMJiU0rr literal 0 HcmV?d00001 diff --git a/public/logos/united-chat.png b/public/logos/united-chat.png new file mode 100644 index 0000000000000000000000000000000000000000..fb550dcfdd8bfb20944dfa71982dd560efe85bb0 GIT binary patch literal 6188 zcmWkycRW@98~>c+;Mn)t5w028GO~{yNk*ZJgro>1qQbd0nMG(AH=>1*T`no2jLb-` zzC}V-$o~2L^Q_nNdS0*R^}L?-PO!EzV`COz1^}>`A2GHC0NN8FfHLec=PM;%|JMR- z%?v?l*Zye$_$JMb4Nio(&bi#m{94UEV9#01c_8yg(H?1iB4I9>Ap7O~Ec-Q85hlQd zBcVZExh^-3q%{HsDE@P!Z!JzG!iuBSui@MrB8kVrwLHaw_Bkl(ao-b5oe2h*kh(Zb z;2i+M^)RH3STcd|OU3+0V3>$zb7HO0$_xYm2ctNcEsvHUrLmLGGJ$DhEvJ@fE-@uJ zNTO9`A|tTR_wkohEe8T-SQDo5^LW`NybE~8J?|Sv;cS=R7ztIv19o_m3O=~}zyPt*MbX7n7 zKn%eALs)z7Zp|gZIa*%z+|Od;wk2lBIs@ya+s@T+=O2n4&LIQG_~!!Uqt2H@?z@a# z90|U%nhvAQ>_bxKBtU=jIg6~Pi(%-<#QC5Qb~Z6YEb_J%$&f|}{I?&Wf!_&7I>x4_ zj?R|Ln2vI_3~?XIb-PUh5t4U%gsl|Y>eHI@N`%@C8vJDv91XzAzuXl$tKCk?{)lh( z6w$o(bGI!#F=NbzO#1_41JZm*zQIi6+^mU?cHwVHBD57Q8g*Uf^$qq`8xnrdqqdi3 zD7vF`SKA@6hiFg0c%a50v9{vI+=J`2&ICdzLlHv>&x!95l7KkK^C;xQi|j-jzAIb$ zmR7WV$58igg!~ek12veryHrIGqUrhnTh{zQ82WICAE8~fif zf6%4NG+UR1d|6UrvjJ#xJ2v^xV@`)za6sd=%f-6nfA?K`wsbL&s%4s@Up&@lEOldUkp%>{ug#Z?0sL$3@2u#BihyxC$`j9f1B?|; zZ-`K#8hiBSg_Gx1E^8TK2Ur-*S-wwuo`bPk|L;aG4fi{HPFJ~^!1*q_ieI}^gT5k< zh{P=&D^)_&@I?f7(SKiBk#bvBKnab5QL5YBxyfkfCZV^@lHPN(Rof~xtaNC8!m_uIL-+76(QjW4ce`<{IR*1T`bt^eTLE(WvAnEm<8%7)gO9R zmn5h5Fm5tufgsUyQHl}iIjC-XOEKcosLy)E$9A$ZFCqUt(=XzGRSuIV$lR&&(imuc zqOjmG$a78-_v^}&QSZ2z!8G-7RWmXP!Mb++4aJ)?rc6naOrGN4>wkHp2^D1uznd8l(oXej}3qtbkl_v)AC;{4K@8HDi2Sr(uZhIu}^l$z@1k2f5SNr#z-tN$7{l57+fDSp zPL&Qq6S_oH1~nyMT`gyh4|w>VM?UvF-E@j>WOB=F5s~?Qe>uHFvCH+WeD2dPxkFR* z-+1T3)v5PE{kLU~AE6tG-eOSq%z$0(%h~vapv)SxI$lJV$&H6TeZG;1ADX~{->Hk5 zn<`S%8kcjC0K0#I!R#Eqswz{rzzFvwALKmsiW91xm^J~jGE?GkkCLg0lQEbv1yxtF zMk8I39<{ZyfYLz)4>NG7A(TzsPkYc$<=G__h3pYdYD2+`$Na`1mHV>q^I*>tXU_*m z4V6<2M3$wgcfmJ@+L1pTa1Q||^En%zAYfy(KUJb4)U6ae8$<^>ue8q(%U}=3YW`kf za+sImHU;w7;lFChFoKY-ZhyEI!9Y)-z9=dd2br1LA+HPzFL0AcV6oqRY&#vc%!T81 zNu>p+xZTWw?BtHg&v@WBE_Yu6j$d}Ulm5d7aE&+;sT~awZ&0fKw`~$=E3kh7aWg0< zz|T>)m9oF4NLnMqLb;;0ibEJ{z#*AX?f{j19>`Ox$Ub%Va(4nsZCy%-LmYGHKAa{{ ze-}7TaZ_8*zW6kd0#dRV8ya+?2Prx%uw&i7tP+&pf;$)q@EyBD!0x!->jNxs3G?p# zyJLo-dSM4FAWHy4I#IoCzwRfJUm!|MEER zpzE3?fvP=utk<3edLBL>;lD%z9PnWd2m=l`pZ4LrFkyUi%{=Vh+u)-R50YaV9Em#VU1`ho~oVHz4({ z!%^Ti?qqBLjzE?&g@%qN1+0&P?+Z=tqWcY@%7BF--zBtRnJam{?Nt0hXug%5|c-r`X;Mo8d8LBfW0 z8V-aXCv5H71acrWT5t|Ufq+L{(@(rvt`a1a9}CiUSx~CME(v$CCMM_!;YCFRTi01L1-oC2~@W|HpAQdR0~&!u^kZu z&|Skz04Qe2x@WozRQ65CJHA;QpU|Oep4E#D`~BmA0Y{ZvEO69!3Kc^4_To+ z;CE)!Wy1fd!a?y9=5N$vb%p5;l+wu^2d07^FkEuAvffV%F0q4Anxn>dEj$+7?cC)F zW`b+gOogESbXJtcuW?xjGXk}{d0O-(%M~52B;10QRG+XoM4%c$)-R0&UicU*`%9Bx z3{kp$`8|PpMD~wPRuGE4-*Bh%?Gd!a0~f*@8x@ z>_GU}D<&FIgaG^x5#@)qAx;?dEj@*yd}|GwvP{X1127TU{G2do>az zc`z&CarVRa9VZUM*?LDiC%lN2is6r5)gLbg4?gcb99`+ zyR_!MDgb4h0l6(Ngy1VX+ma;sz;yjKH%SuWk7`e#gCwMYRow@De<{!pgym>wy8(m) z)1OQP4EMqS2?vMlIL_MAQ4L7K*9e#e9MHA%@ZGXk9T^~`Q>w}&FnC&Jz}@lfAuv{m zwo|$+t6nuh?B~TS*+MWDImnr4S{d9`-ISE716-p&CF} zV|G0P1{EZ`VcLCi$hiv3&RcFySG8`tm}C)=a%0caF*^epmME>S`jY3(+7#liqafM- zd%hz9rz_zRd%|v1f4EVC2vFSYjUu$Le9I4l<4w2LL!L)evMF5Aj>+@Lm(G4SJ;(cq zO{*`#auvA;>`Kl5L27=6bm3ha8l$v|63h2PMjW%-_EF~NK0_!Kn@AQjR+o_kmz&>t z*Z4T!2)RZaPOj`Q0P_q4GNTwC7{xhFeEvO zgX(W$$ttv-^2SG{?oT<3-2~vn9}M1c1%h+@=|t@_v0C`>KLOROX-ng`D$g1cw@-gv zP|0K!^;Wx>Ec7lW>;2`cTJb+8m6g2_9f!57ve8uwo9tg&qImJ$O7CBiEh^vbNyl1M zcX?h|ev=m4D*oar6Wftq>GR}s^Q|jU?S#k?gD1%O(du|Z(lky18@iu)Oz;wuhdwTu zkr(WMfWX?BR33s2TG+e&06Tu2J{euoPQZU3(Br%%@X_RF-_!TRApFP0qz zk-q18 zds3Ci!_3F|YyFMsm2efUd9E}QNSqHlY5Kk2F>`l_6Ra5VR7VKqf5g$87Wbzt#;)np z>@5*FUIT*l^+v`*SoPppCzH5VNzVMS#iOhT6`LZ;={-c}s^ z+{b^d`{t=b-Mymt zC+*_uxEGWay5uYG)HC}6gBxRQ94D12yq_kTP9oTqyGigtaqBedOY&y%olJ{6>z>}S zccQ%Pi6D`zH5P>kFW%d#%Im_i2c;UC&LLRE1D?YiL1!{pIBQR9wuB4mXV2~oB0ZYS zN6ZP&#>M`IUtg?qDpJi%Ey@;FsI-J&3J^Lb{7Tqz_nGiM;h&ja$4m#B?|ux9NJaAl zxqAvbb03<8{!oYMu53}WvW(@P1hcAzW&hc6MQF|}CG^@ROk-AX7 zd4mWjAlV|X=3z4GZI}O6*W+f6xs{mm__i(+u)(yM(xMHK!mSdGd6h$aH#iK#1O=sS zKVFMC4*#+ndqsa!^@1_O)tP{dn!h@4ix2C*4wc@JfA?s*^NOBd_ie{<`eDV9-4j`o zt#zL12G+(4$Ily*;uOpFNA+!fN$dPGzYpS;UP!|8Y-T0rnFq#Q2viz0#X};k@qBLYy-brT^oWxtk=J@D7<>09jZ7ySm?_V!5HXs0DPfb zcIp}ZM~YBKxMTElxb)~s9)cg`Qwr#yhn$)B(p}v8x!X|7csOr5f=AMFb|!?}=Npg5~&%d%`iamT#w?NbRf+yFRz;CjbEBLt~A}woo~tb1jm%U zDu9IQSJiJZ35xbe&Wj|2$udTX zc%x)i0rwy1)y_>b30!#wx^j*pN$4T(joEx>zTlsquuv&b^|y0 zjCRxeIj>w@e>!0(mXhC}(NhYOOX+j|m^9s>no0m;n8zzw;jOrmajzl^WUWi<{5jps z|4GY_HHG3)-YoqBWu4xtk~TnkKHXd#gI{=QoY?gX?iY+X`|!*W;IjC3uDNum#lGi<8r-;+hH1xgS@7#o_`j|1E%0{%1~6CsLhDhnsp8SF*{sUH?@2~T`2ljo z4Z7GxT>^i&#*o7G>?pmjt%r!c zMC07#=&=^=E`4XjjmG)mNdA4ugLWN>y`I|?zHeUld?HwVXRy%)S+I2}(!HOErRj;d zF@NP=T-SzW{Fg6x+~2FsCzc`l!Z8lv?VsH_+f^){J!V~>ADG(v21dNAvf6`mpfQucxb}r?Yt>$Eval5_()GEMa8|m2i$uv-`rzm*)waS(c z@OpZUh=>J{)sn3{R;JxJ=5~&{KI6h{Hja;0_uh%wnkbO`=JzU{@<`DwEL?HnK9! zr01-SwCfZfhXlgX9_0O|YwCX;impC3$hUD=GiqL>r*W8qBqn~Rc#s#ym55@9MUR$h z+<&r|ND|;aG(W^WerlLwvohW0OIZ&Knh#eU<*RmdR20zVLGx>i!OR;OG#}C-7-)yE zaax@9|6-)WHXL@99&*h8r$9$4E-6iE8r_ zjY>S{7p~5vga-tf0;J~@bifl6=~ec$*vG7yq&XUQ>NSyBQ%7^XrqloM7Cu4;v6f`q zks%T@@(fvjj_cZ2j1OG6IXkOc)uSY}mvLi_*^~Dn5n-Y3>0%7^9ZeC#^8ULgJk}ew zzDw?;9*^_lrQz2L^yWF?viB zXHHkxgUFrTVysDNbdWwwRnLA4D|HqT7sP?gb3+P2{Z2|^Fb2@)3s%&9uUJ(c*gOjx n{Hp`wF)O_cru1+#x+P+ALg3hz_Nk#g_#c>?SQ(cZx<&pEpQowG literal 0 HcmV?d00001 diff --git a/src/app/api/auth/get_user/route.ts b/src/app/api/auth/get_user/route.ts new file mode 100644 index 0000000..19192bf --- /dev/null +++ b/src/app/api/auth/get_user/route.ts @@ -0,0 +1,44 @@ +import {createClient} from "@/lib/supabase/server"; +import {NextResponse} from "next/server"; + +// Helper function to get user data by UUID +async function getUserByUUID(supabase: any, uuid: string) { + const {data: userData, error: userError} = await supabase + .from('users') + .select('*') + .eq('uuid', uuid) + .single(); + + if (userError) throw userError; + return userData; +} + +export async function GET(request: Request) { + try { + const supabase = await createClient(); + const {searchParams} = new URL(request.url); + const uuid = searchParams.get('uuid'); + + if (uuid) { + // Get specific user by UUID + const userData = await getUserByUUID(supabase, uuid); + return NextResponse.json({user: userData}); + } else { + // Get current authenticated user + const {data: {user}, error: authError} = await supabase.auth.getUser(); + if (authError) throw authError; + + if (!user) { + return NextResponse.json({user: null}, {status: 401}); + } + + const userData = await getUserByUUID(supabase, user.id); + return NextResponse.json({user: userData}); + } + } catch (error) { + return NextResponse.json( + {error: `Failed to fetch user: ${error}`}, + {status: 500} + ); + } +} \ No newline at end of file diff --git a/src/app/api/auth/login/route.ts b/src/app/api/auth/login/route.ts new file mode 100644 index 0000000..9a02186 --- /dev/null +++ b/src/app/api/auth/login/route.ts @@ -0,0 +1,38 @@ +// app/api/auth/login/route.ts +import {createClient} from "@/lib/supabase/server"; +import {NextResponse} from "next/server"; + +export async function POST(request: Request) { + try { + const {username, password} = await request.json() + const supabase = await createClient() + + // Mocks the email with the domain we configured on the local env + const email = `${username.toLowerCase()}@${process.env.DOMAIN}` + + // Sends the request through supabase + const {data: {user}, error: authError} = await supabase.auth.signInWithPassword({ + email: email, + password: password, + }) + + if (authError) throw authError + + // Fetch our custom user data + const {data: userData, error: userError} = await supabase + .from('users') + .select('*') + .eq('uuid', user?.id) + .single() + + if (userError) throw userError + + // Returns simple data + return NextResponse.json({user: userData}) + } catch (error) { + return NextResponse.json( + {error: `Login failed: ${error}`}, + {status: 401} + ) + } +} \ No newline at end of file diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts new file mode 100644 index 0000000..ff626bc --- /dev/null +++ b/src/app/api/auth/register/route.ts @@ -0,0 +1,45 @@ +import {NextResponse} from 'next/server' +import {createClient} from "@/lib/supabase/server"; + +export async function POST(request: Request) { + const {username, password} = await request.json() + const supabase = await createClient() + + try { + // First create the auth user + const {data: {user}, error: authError} = await supabase.auth.signUp({ + email: `${username}@${process.env.DOMAIN}`, // Using username as email + password: password, + }) + + if (authError) throw authError + if (!user) throw new Error('No user returned from sign up') + + // Then create our custom user record + const {error: insertError} = await supabase + .from('users') + .insert({ + uuid: user.id, + username: username, + }) + + if (insertError) { + // Rollback auth user if custom user creation fails + await supabase.auth.admin.deleteUser(user.id) + throw insertError + } + + return NextResponse.json({success: true}) + } catch (error) { + if (typeof error === "object") { + return NextResponse.json( + {error: `Registration failed: ${JSON.stringify(error)}`}, + {status: 400} + ) + } + return NextResponse.json( + {error: `Registration failed: ${error}`}, + {status: 400} + ) + } +} \ No newline at end of file diff --git a/src/app/api/user/get/threads/route.ts b/src/app/api/user/get/threads/route.ts new file mode 100644 index 0000000..e08385c --- /dev/null +++ b/src/app/api/user/get/threads/route.ts @@ -0,0 +1,37 @@ +import {createClient} from "@/lib/supabase/server"; +import {NextResponse} from "next/server"; + +export async function GET() { + try { + const supabase = await createClient(); + + const {data: {user}, error: userError} = await supabase.auth.getUser() + + if (userError) { + NextResponse.json( + {error: userError}, + {status: userError?.status} + ) + } else if (!user) { + NextResponse.json( + {error: "User not found"}, + {status: 401} + ) + } + + const {data, error} = await supabase.rpc( + "get_user_threads", + { + user_id: user!.id + } + ) + + if (data.length === 0) { + return NextResponse.json({threads: []}, {status: 200}); + } + + return NextResponse.json({threads: data}, {status: 200}); + + } catch (e) { + } +} \ No newline at end of file diff --git a/src/app/auth/login/login.ts b/src/app/auth/login/login.ts new file mode 100644 index 0000000..c59245b --- /dev/null +++ b/src/app/auth/login/login.ts @@ -0,0 +1,36 @@ +/** + * + * @param username - The unique username of that user. This will be checked for collision. + * @param password - The plain-text password of the user. Supabase will try to match it. + * @constructor + */ +export default async function Login(username: string, password: string) { + try { + let response = await fetch('/api/auth/login', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({username, password}), + }); + + // Simple error handling. + // Since we mock an email on the main app to bypass Supabase's authentication method, we can just return whatever the API returns. + // This also means this might be insecure, but oh well. Don't lose your password, I guess? + let resData = await response.json(); + + if (!response.ok) { + return ({ + code: resData.code, + message: resData.message + }); + } + + return ({ + code: 200, + message: resData.data + }); + } catch (e) { + return {code: 500, message: "An unknown error occurred"}; + } +} diff --git a/src/app/auth/login/page.tsx b/src/app/auth/login/page.tsx new file mode 100644 index 0000000..522fecb --- /dev/null +++ b/src/app/auth/login/page.tsx @@ -0,0 +1,198 @@ +"use client" + +import React, {useEffect, useState} from 'react' +import Image from 'next/image' +import {motion} from 'framer-motion' +import {Button} from "@/components/ui/button" +import {Input} from "@/components/ui/input" +import {Label} from "@/components/ui/label" +import {Card, CardContent} from "@/components/ui/card" +import {EyeIcon, EyeOffIcon} from 'lucide-react' +import {useToast} from "@/hooks/use-toast" +import {ToastActionElement} from "@/components/ui/toast"; +import {useUser} from "@/contexts/user"; +import {useRouter} from "next/navigation"; +import {useTheme} from "next-themes"; +import Register from "@/app/auth/login/register"; +import Login from "@/app/auth/login/login"; + +export default function AuthPage() { + const {checkAuth} = useUser(); + const {theme, systemTheme} = useTheme() + const {toast} = useToast(); + const [mounted, setMounted] = useState(false); + const [isLogin, setIsLogin] = useState(true); + const [showPassword, setShowPassword] = useState(false); + const [isSubmitting, setIsSubmitting] = useState(false); + const router = useRouter(); + + useEffect(() => { + const check = async () => { + const isAuthenticated = await checkAuth(); + if (isAuthenticated) { + router.replace('/'); + } else { + setMounted(true); + } + }; + + check(); + }, [checkAuth, router]); + + if (!mounted) return null; + + + const getTheme = () => { + if (theme === "system") { + switch (systemTheme) { + case "dark": + return "dark" + default: + return "light" + } + } + + return theme === "dark" ? "dark" : "light" + } + + const logoSrc = getTheme() === 'dark' ? '/logos/logo-light.png' : '/logos/logo.png'; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setIsSubmitting(true); + + const username = (document.getElementById('username') as HTMLInputElement).value; + const password = (document.getElementById('password') as HTMLInputElement).value; + + let response: { + code: number; + message: string; + action?: ToastActionElement | undefined; + } + if (!isLogin) { + response = await Register(username, password); + } else { + response = await Login(username, password); + } + + if (response.code !== 200) { + if (isLogin && response.code === 400) { + console.log(response) + toast({ + title: "E-mail not verified", + description: response.message, + variant: "destructive", + duration: 5000, // Increased duration for better visibility + action: response.action! + }); + setIsSubmitting(false); + return; + } + + toast({ + title: "Error", + description: response.message, + variant: "destructive", + duration: 5000, // Increased duration for better visibility + }); + } else { + toast({ + title: "Success", + description: response.message, + variant: "default", + duration: 5000, // Increased duration for better visibility + }); + window.location.href = "/"; + } + + setTimeout(() => { + setIsSubmitting(false); + }, 2000) + }; + + return ( +

+ + +
+
+ SiPher +

+ Silent Whisper +

+

+ Trust the shadows. Whisper safely. +

+
+
+ +

+ {isLogin ? "Sign In" : "Sign Up"} +

+
+
+ + +
+
+ +
+ + +
+
+ +
+
+ +
+
+
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/auth/login/register.ts b/src/app/auth/login/register.ts new file mode 100644 index 0000000..33c3c00 --- /dev/null +++ b/src/app/auth/login/register.ts @@ -0,0 +1,38 @@ +/** + * + * @param username - The unique username of that user. This will be checked for collision. + * @param password - The plain-text password of the user. Will be encrypted later by Supabase + * @constructor + */ +export default async function Register(password: string, username: string) { + try { + // Sends the request to the API + let res = await fetch('/api/auth/register', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({username, password}), // Stringifies the JSON + }); + + // Default error handler, if not OK just return whatever the API returned + if (!res.ok) { + let data = await res.json(); + return { + code: data.code, + message: data.message + } + } + + // User was created, now it just needs to login on the service. + return { + code: 200, + message: "User created successfully, go ahead and login." + } + } catch (e: any) { + return { + code: 500, + message: `An unknown error occurred: ${e.message}` + } + } +} diff --git a/src/app/globals.css b/src/app/globals.css new file mode 100644 index 0000000..b1b7658 --- /dev/null +++ b/src/app/globals.css @@ -0,0 +1,61 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 20 14.3% 4.1%; + --foreground: 60 9.1% 97.8%; + --card: 20 14.3% 4.1%; + --card-foreground: 60 9.1% 97.8%; + --popover: 20 14.3% 4.1%; + --popover-foreground: 60 9.1% 97.8%; + --primary: 20.5 90.2% 48.2%; + --primary-foreground: 60 9.1% 97.8%; + --secondary: 12 6.5% 15.1%; + --secondary-foreground: 60 9.1% 97.8%; + --muted: 12 6.5% 15.1%; + --muted-foreground: 24 5.4% 63.9%; + --accent: 12 6.5% 15.1%; + --accent-foreground: 60 9.1% 97.8%; + --destructive: 0 72.2% 50.6%; + --destructive-foreground: 60 9.1% 97.8%; + --border: 12 6.5% 15.1%; + --input: 12 6.5% 15.1%; + --ring: 20.5 90.2% 48.2%; + --radius: 0.75rem; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + } + + .dark { + --background: 20 14.3% 4.1%; + --foreground: 60 9.1% 97.8%; + --card: 20 14.3% 4.1%; + --card-foreground: 60 9.1% 97.8%; + --popover: 20 14.3% 4.1%; + --popover-foreground: 60 9.1% 97.8%; + --primary: 20.5 90.2% 48.2%; + --primary-foreground: 60 9.1% 97.8%; + --secondary: 12 6.5% 15.1%; + --secondary-foreground: 60 9.1% 97.8%; + --muted: 12 6.5% 15.1%; + --muted-foreground: 24 5.4% 63.9%; + --accent: 12 6.5% 15.1%; + --accent-foreground: 60 9.1% 97.8%; + --destructive: 0 72.2% 50.6%; + --destructive-foreground: 60 9.1% 97.8%; + --border: 12 6.5% 15.1%; + --input: 12 6.5% 15.1%; + --ring: 20.5 90.2% 48.2%; + --radius: 0.75rem; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + } +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 0000000..4f4ac70 --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,75 @@ +// app/layout.tsx +import type {Metadata} from "next"; +import "./globals.css"; +import {Public_Sans} from 'next/font/google'; +import {UserProvider} from "@/contexts/user"; +import Sidebar from "@/components/main/sidebar/sidebar"; +import {getAuthenticatedUser} from "@/lib/auth"; +import {SharedStateProvider} from "@/hooks/shared-states"; +import {ThemeProvider} from "next-themes"; + +const publicSans = Public_Sans({ + subsets: ['latin'], + display: 'swap', + variable: '--font-public-sans' +}); + +export const metadata: Metadata = { + title: "Create Next App", + description: "Generated by create next app", +}; + +export default async function RootLayout({ + children, + }: { + children: React.ReactNode & { props?: { childProp?: { segment?: string } } }; +}) { + const initialUser = await getAuthenticatedUser(); + const isAuthPage = (children as any)?.props?.childProp?.segment === 'auth'; + + // Auth layout + if (isAuthPage) { + return ( + + + + +
+ {children} +
+
+
+ + + ); + } + + // Main layout + return ( + + + + + +
+
+ + {children} + +
+
+
+
+
+ + + ); +} \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx new file mode 100644 index 0000000..0bc456a --- /dev/null +++ b/src/app/page.tsx @@ -0,0 +1,12 @@ +"use client" +import {useTheme} from "next-themes"; + +export default function SiPher() { + const {theme} = useTheme() + + return ( +
+ abc +
+ ) +} diff --git a/src/components/main/sidebar/mobile.tsx b/src/components/main/sidebar/mobile.tsx new file mode 100644 index 0000000..a0e4971 --- /dev/null +++ b/src/components/main/sidebar/mobile.tsx @@ -0,0 +1,58 @@ +import React from 'react' +import { Button } from "@/components/ui/button" +import { HamburgerMenuIcon } from "@radix-ui/react-icons" +import { useTheme } from "next-themes" +import Image from "next/image" +import { useUIState } from "@/hooks/shared-states" +import Link from "next/link"; + +const MobileHeader: React.FC = () => { + const { setIsDrawerOpen } = useUIState() + const { theme, systemTheme } = useTheme() + + const getTheme = () => { + if (theme === "system") { + switch (systemTheme) { + case "dark": + return "dark" + default: + return "light" + } + } + return theme === "dark" ? "dark" : "light" + } + + const logoSrc = getTheme() === 'dark' ? '/logos/logo-light.png' : '/logos/logo.png' + + return ( +
+
+ + +
+ + Logo + +
+ + {/* Empty div to maintain center alignment */} +
+
+
+ ) +} + +export default MobileHeader \ No newline at end of file diff --git a/src/components/main/sidebar/sidebar.tsx b/src/components/main/sidebar/sidebar.tsx new file mode 100644 index 0000000..537d49e --- /dev/null +++ b/src/components/main/sidebar/sidebar.tsx @@ -0,0 +1,229 @@ +"use client" +import React, {useCallback, useEffect, useRef, useState} from "react" +import {usePathname} from "next/navigation" +import Link from "next/link" +import {AnimatePresence, motion} from "framer-motion" +import {LogOut, X} from "lucide-react" +import {Button} from "@/components/ui/button" +import {Avatar, AvatarFallback} from "@/components/ui/avatar" +import {Separator} from "@/components/ui/separator" +import {ScrollArea} from "@/components/ui/scroll-area" +import {useTheme} from "next-themes" +import {GearIcon} from "@radix-ui/react-icons" +import Image from "next/image"; +import MobileHeader from "@/components/main/sidebar/mobile"; +import {useUser} from "@/contexts/user"; +import {useUIState} from "@/hooks/shared-states"; +import {useToast} from "@/hooks/use-toast"; + +type SidebarProps = { + children?: React.ReactNode +} + +function Sidebar( + { + children + }: SidebarProps +) { + const pathname = usePathname() + const drawerRef = useRef(null) + + const [selectedThreads, setSelectedThreads] = useState(""); + const [threads, setThreads] = useState([]); + const [threadMenu, setThreadMenu] = useState([]); + const {toast} = useToast(); + + useEffect(() => { + const getThreads = async () => { + const req = await fetch("/api/user/get/threads") + + if (req.ok) { + const {threads} = await req.json() as { threads: SiPher.Messages[] | [] } + setThreads(threads) + return; + } else { + setThreads([]); + toast({ + title: "Error", + description: "An unknown error occurred", + variant: "destructive", + duration: 5000, // Increased duration for better visibility + }) + } + } + + getThreads(); + + return () => { + setThreads([]); + } + }, [setThreads]) + + const generateThreads = useCallback(() => { + threads.map(async(thread) => { + if (thread.participants.length > 2) { + return ( +
  • + + + +
  • + ) + } else { + const fetchOtherUser = await useUser().getUser(thread.id) + } + }) + }, [threads]) + + const user = useUser().user!; + + const { + username, + suuid + } = user + + const {isDrawerOpen, setIsDrawerOpen} = useUIState() + + const {theme, systemTheme} = useTheme() + const getTheme = () => { + if (theme === "system") { + switch (systemTheme) { + case "dark": + return "dark" + default: + return "light" + } + } + + return theme === "dark" ? "dark" : "light" + } + const isDarkMode = getTheme() === "dark"; + + const RightSidebarContent = () => ( +
    +
    + + {username.charAt(0)} + +
    +

    {username}

    +

    @{username}

    +

    ${suuid}

    +
    +
    + + + + +
    + + + +
    +
    + ) + + return ( + <> + + + + {isDrawerOpen && ( + +
    + + +
    +
    + )} +
    + { + children ?? null + } + + ) +} + +export default Sidebar \ No newline at end of file diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx new file mode 100644 index 0000000..51e507b --- /dev/null +++ b/src/components/ui/avatar.tsx @@ -0,0 +1,50 @@ +"use client" + +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..65d4fcd --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,57 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + outline: + "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx new file mode 100644 index 0000000..cabfbfc --- /dev/null +++ b/src/components/ui/card.tsx @@ -0,0 +1,76 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx new file mode 100644 index 0000000..69b64fb --- /dev/null +++ b/src/components/ui/input.tsx @@ -0,0 +1,22 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Input = React.forwardRef>( + ({ className, type, ...props }, ref) => { + return ( + + ) + } +) +Input.displayName = "Input" + +export { Input } diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx new file mode 100644 index 0000000..5341821 --- /dev/null +++ b/src/components/ui/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" +) + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)) +Label.displayName = LabelPrimitive.Root.displayName + +export { Label } diff --git a/src/components/ui/scroll-area.tsx b/src/components/ui/scroll-area.tsx new file mode 100644 index 0000000..0b4a48d --- /dev/null +++ b/src/components/ui/scroll-area.tsx @@ -0,0 +1,48 @@ +"use client" + +import * as React from "react" +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" + +import { cn } from "@/lib/utils" + +const ScrollArea = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + {children} + + + + +)) +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName + +const ScrollBar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, orientation = "vertical", ...props }, ref) => ( + + + +)) +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName + +export { ScrollArea, ScrollBar } diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx new file mode 100644 index 0000000..12d81c4 --- /dev/null +++ b/src/components/ui/separator.tsx @@ -0,0 +1,31 @@ +"use client" + +import * as React from "react" +import * as SeparatorPrimitive from "@radix-ui/react-separator" + +import { cn } from "@/lib/utils" + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref + ) => ( + + ) +) +Separator.displayName = SeparatorPrimitive.Root.displayName + +export { Separator } diff --git a/src/components/ui/toast.tsx b/src/components/ui/toast.tsx new file mode 100644 index 0000000..40ac9dd --- /dev/null +++ b/src/components/ui/toast.tsx @@ -0,0 +1,129 @@ +"use client" + +import * as React from "react" +import * as ToastPrimitives from "@radix-ui/react-toast" +import { cva, type VariantProps } from "class-variance-authority" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const ToastProvider = ToastPrimitives.Provider + +const ToastViewport = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +ToastViewport.displayName = ToastPrimitives.Viewport.displayName + +const toastVariants = cva( + "group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full", + { + variants: { + variant: { + default: "border bg-background text-foreground", + destructive: + "destructive group border-destructive bg-destructive text-destructive-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +const Toast = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, variant, ...props }, ref) => { + return ( + + ) +}) +Toast.displayName = ToastPrimitives.Root.displayName + +const ToastAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +ToastAction.displayName = ToastPrimitives.Action.displayName + +const ToastClose = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +ToastClose.displayName = ToastPrimitives.Close.displayName + +const ToastTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +ToastTitle.displayName = ToastPrimitives.Title.displayName + +const ToastDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +ToastDescription.displayName = ToastPrimitives.Description.displayName + +type ToastProps = React.ComponentPropsWithoutRef + +type ToastActionElement = React.ReactElement + +export { + type ToastProps, + type ToastActionElement, + ToastProvider, + ToastViewport, + Toast, + ToastTitle, + ToastDescription, + ToastClose, + ToastAction, +} diff --git a/src/components/ui/toaster.tsx b/src/components/ui/toaster.tsx new file mode 100644 index 0000000..171beb4 --- /dev/null +++ b/src/components/ui/toaster.tsx @@ -0,0 +1,35 @@ +"use client" + +import { useToast } from "@/hooks/use-toast" +import { + Toast, + ToastClose, + ToastDescription, + ToastProvider, + ToastTitle, + ToastViewport, +} from "@/components/ui/toast" + +export function Toaster() { + const { toasts } = useToast() + + return ( + + {toasts.map(function ({ id, title, description, action, ...props }) { + return ( + +
    + {title && {title}} + {description && ( + {description} + )} +
    + {action} + +
    + ) + })} + +
    + ) +} diff --git a/src/contexts/user.tsx b/src/contexts/user.tsx new file mode 100644 index 0000000..2773e59 --- /dev/null +++ b/src/contexts/user.tsx @@ -0,0 +1,82 @@ +// contexts/user.tsx +'use client'; + +import {createContext, useContext} from 'react'; +import {useRouter} from 'next/navigation'; + +interface UserContextType { + user: NonNullable; + getUser: () => Promise>; +} + +const UserContext = createContext(null); + +export function useUser() { + const context = useContext(UserContext); + const router = useRouter(); + + if (!context) { + throw new Error('useUser must be used within a UserProvider'); + } + + return { + user: context.user, + getUser: async (userId?: string) => { + try { + const response = await fetch(`/api/auth/get_user?${ + userId && `uuid=${ + encodeURIComponent(userId) + }` + }`); + if (!response.ok) { + const error = await response.json(); + if (error.message?.includes("Auth session missing!")) { + throw new Error('No authenticated user'); + } + throw new Error(error.message || 'Authentication failed'); + } + + const {user} = await response.json(); + return user as NonNullable; + } catch (error) { + console.error('Failed to get user:', error); + router.push('/auth/login'); + throw error; + } + }, + checkAuth: async () => { + try { + const response = await fetch('/api/auth/get/user'); + return response.ok; + } catch { + return false; + } + } + }; +} + +export function UserProvider( + { + children, + initialUser + }: { + children: React.ReactNode; + initialUser: NonNullable; + } +) { + return ( + { + const response = await fetch('/api/auth/get/user'); + if (!response.ok) { + throw new Error('Failed to get user'); + } + const {user} = await response.json(); + return user as NonNullable; + } + }}> + {children} + + ); +} \ No newline at end of file diff --git a/src/hooks/shared-states.tsx b/src/hooks/shared-states.tsx new file mode 100644 index 0000000..cbd1117 --- /dev/null +++ b/src/hooks/shared-states.tsx @@ -0,0 +1,171 @@ +"use client"; + +// src/hooks/useSharedState.tsx +import React, {createContext, MutableRefObject, useContext, useRef, useState} from 'react' +import {useTheme} from 'next-themes' + +// Define the shape of our shared state +interface SharedState { + // UI States + isScrolled: boolean + setIsScrolled: React.Dispatch> + isSearchExpanded: boolean + setIsSearchExpanded: React.Dispatch> + isDrawerOpen: boolean + setIsDrawerOpen: React.Dispatch> + isCreateModalOpen: boolean + setIsCreateModalOpen: React.Dispatch> + isUserModalOpen: boolean + setIsUserModalOpen: React.Dispatch> + isNotificationsOpen: boolean + setIsNotificationsOpen: React.Dispatch> + showBackToTop: boolean + setShowBackToTop: React.Dispatch> + + // Refs + drawerRef: React.RefObject + userModalRef: React.RefObject + notificationsRef: React.RefObject + createModalRef: React.RefObject + fileInputRef: React.RefObject + observerRef: MutableRefObject + loadingRef: MutableRefObject + + // Theme + theme: string | undefined +} + +export function useMutableRef(initialValue: T): MutableRefObject { + return useRef(initialValue) as MutableRefObject +} + +// Create the context +const SharedStateContext = createContext(undefined) + +// Create the provider component +export function SharedStateProvider({children}: { children: React.ReactNode }) { + // UI States + const [isScrolled, setIsScrolled] = useState(false) + const [isSearchExpanded, setIsSearchExpanded] = useState(false) + const [isDrawerOpen, setIsDrawerOpen] = useState(false) + const [isCreateModalOpen, setIsCreateModalOpen] = useState(false) + const [isUserModalOpen, setIsUserModalOpen] = useState(false) + const [isNotificationsOpen, setIsNotificationsOpen] = useState(false) + const [showBackToTop, setShowBackToTop] = useState(false) + + // Refs + const drawerRef = useRef(null) + const userModalRef = useRef(null) + const notificationsRef = useRef(null) + const createModalRef = useRef(null) + const fileInputRef = useRef(null) + const loadingRef = useMutableRef(false) + const observerRef = useMutableRef(null) + + // Theme + const {theme} = useTheme() + + const value = { + // UI States + isScrolled, + setIsScrolled, + isSearchExpanded, + setIsSearchExpanded, + isDrawerOpen, + setIsDrawerOpen, + isCreateModalOpen, + setIsCreateModalOpen, + isUserModalOpen, + setIsUserModalOpen, + isNotificationsOpen, + setIsNotificationsOpen, + showBackToTop, + setShowBackToTop, + + // Refs + drawerRef, + userModalRef, + notificationsRef, + createModalRef, + fileInputRef, + observerRef, + loadingRef, + + // Theme + theme, + } + + return ( + + {children} + + ) +} + +// Create the custom hook +export function useSharedState() { + const context = useContext(SharedStateContext) + if (context === undefined) { + throw new Error('useSharedState must be used within a SharedStateProvider') + } + return context +} + +// Optional: Create specific hooks for different parts of the state +export function useUIState() { + const { + isScrolled, + setIsScrolled, + isSearchExpanded, + setIsSearchExpanded, + isDrawerOpen, + setIsDrawerOpen, + isCreateModalOpen, + setIsCreateModalOpen, + isUserModalOpen, + setIsUserModalOpen, + isNotificationsOpen, + setIsNotificationsOpen, + showBackToTop, + setShowBackToTop, + } = useSharedState() + + return { + isScrolled, + setIsScrolled, + isSearchExpanded, + setIsSearchExpanded, + isDrawerOpen, + setIsDrawerOpen, + isCreateModalOpen, + setIsCreateModalOpen, + isUserModalOpen, + setIsUserModalOpen, + isNotificationsOpen, + setIsNotificationsOpen, + showBackToTop, + setShowBackToTop, + } +} + +export function useRefs() { + const { + drawerRef, + userModalRef, + notificationsRef, + createModalRef, + fileInputRef, + observerRef, + loadingRef, + } = useSharedState() + + return { + drawerRef, + userModalRef, + notificationsRef, + createModalRef, + fileInputRef, + observerRef, + loadingRef, + } +} \ No newline at end of file diff --git a/src/hooks/use-toast.ts b/src/hooks/use-toast.ts new file mode 100644 index 0000000..02e111d --- /dev/null +++ b/src/hooks/use-toast.ts @@ -0,0 +1,194 @@ +"use client" + +// Inspired by react-hot-toast library +import * as React from "react" + +import type { + ToastActionElement, + ToastProps, +} from "@/components/ui/toast" + +const TOAST_LIMIT = 1 +const TOAST_REMOVE_DELAY = 1000000 + +type ToasterToast = ToastProps & { + id: string + title?: React.ReactNode + description?: React.ReactNode + action?: ToastActionElement +} + +const actionTypes = { + ADD_TOAST: "ADD_TOAST", + UPDATE_TOAST: "UPDATE_TOAST", + DISMISS_TOAST: "DISMISS_TOAST", + REMOVE_TOAST: "REMOVE_TOAST", +} as const + +let count = 0 + +function genId() { + count = (count + 1) % Number.MAX_SAFE_INTEGER + return count.toString() +} + +type ActionType = typeof actionTypes + +type Action = + | { + type: ActionType["ADD_TOAST"] + toast: ToasterToast + } + | { + type: ActionType["UPDATE_TOAST"] + toast: Partial + } + | { + type: ActionType["DISMISS_TOAST"] + toastId?: ToasterToast["id"] + } + | { + type: ActionType["REMOVE_TOAST"] + toastId?: ToasterToast["id"] + } + +interface State { + toasts: ToasterToast[] +} + +const toastTimeouts = new Map>() + +const addToRemoveQueue = (toastId: string) => { + if (toastTimeouts.has(toastId)) { + return + } + + const timeout = setTimeout(() => { + toastTimeouts.delete(toastId) + dispatch({ + type: "REMOVE_TOAST", + toastId: toastId, + }) + }, TOAST_REMOVE_DELAY) + + toastTimeouts.set(toastId, timeout) +} + +export const reducer = (state: State, action: Action): State => { + switch (action.type) { + case "ADD_TOAST": + return { + ...state, + toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), + } + + case "UPDATE_TOAST": + return { + ...state, + toasts: state.toasts.map((t) => + t.id === action.toast.id ? { ...t, ...action.toast } : t + ), + } + + case "DISMISS_TOAST": { + const { toastId } = action + + // ! Side effects ! - This could be extracted into a dismissToast() action, + // but I'll keep it here for simplicity + if (toastId) { + addToRemoveQueue(toastId) + } else { + state.toasts.forEach((toast) => { + addToRemoveQueue(toast.id) + }) + } + + return { + ...state, + toasts: state.toasts.map((t) => + t.id === toastId || toastId === undefined + ? { + ...t, + open: false, + } + : t + ), + } + } + case "REMOVE_TOAST": + if (action.toastId === undefined) { + return { + ...state, + toasts: [], + } + } + return { + ...state, + toasts: state.toasts.filter((t) => t.id !== action.toastId), + } + } +} + +const listeners: Array<(state: State) => void> = [] + +let memoryState: State = { toasts: [] } + +function dispatch(action: Action) { + memoryState = reducer(memoryState, action) + listeners.forEach((listener) => { + listener(memoryState) + }) +} + +type Toast = Omit + +function toast({ ...props }: Toast) { + const id = genId() + + const update = (props: ToasterToast) => + dispatch({ + type: "UPDATE_TOAST", + toast: { ...props, id }, + }) + const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }) + + dispatch({ + type: "ADD_TOAST", + toast: { + ...props, + id, + open: true, + onOpenChange: (open) => { + if (!open) dismiss() + }, + }, + }) + + return { + id: id, + dismiss, + update, + } +} + +function useToast() { + const [state, setState] = React.useState(memoryState) + + React.useEffect(() => { + listeners.push(setState) + return () => { + const index = listeners.indexOf(setState) + if (index > -1) { + listeners.splice(index, 1) + } + } + }, [state]) + + return { + ...state, + toast, + dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }), + } +} + +export { useToast, toast } diff --git a/src/lib/auth/index.ts b/src/lib/auth/index.ts new file mode 100644 index 0000000..3b8c751 --- /dev/null +++ b/src/lib/auth/index.ts @@ -0,0 +1,41 @@ +// lib/auth/index.ts +import {createClient} from '@/lib/supabase/server'; +import {headers} from 'next/headers'; + +const PUBLIC_PATHS = [ + '/auth/login', + '/auth/signup', +]; + +/** + * Mostly used for getting the first user to prevent it being null + */ +export async function getAuthenticatedUser() { + const headersList = await headers(); + const path = headersList.get("x-invoke-path") || ""; + + // If we're on a public path, don't require authentication + if (PUBLIC_PATHS.some(publicPath => path.startsWith(publicPath))) { + return null; + } + + const supabase = await createClient(); + + const {data: {user: session}, error: sessionError} = await supabase.auth.getUser(); + + if (sessionError || !session) { + return null; + } + + const {data: profile, error: profileError} = await supabase + .from('users') + .select('*') + .eq('uuid', session.id) + .single(); + + if (profileError || !profile) { + return null; + } + + return profile +} \ No newline at end of file diff --git a/src/lib/supabase/server.ts b/src/lib/supabase/server.ts new file mode 100644 index 0000000..144103e --- /dev/null +++ b/src/lib/supabase/server.ts @@ -0,0 +1,38 @@ +import {CookieOptions, createServerClient} from '@supabase/ssr'; + +import {cookies} from 'next/headers'; + +export async function createClient() { + const cookieStore = await cookies(); + + return createServerClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + getAll() { + return cookieStore.getAll().map(cookie => ({ + name: cookie.name, + value: cookie.value, + })) + }, + setAll(cookiesList: { name: string; value: string; options?: CookieOptions }[]) { + try { + cookiesList.forEach(({name, value, options}) => { + cookieStore.set({ + name, + value, + ...options, + // Ensure cookies are secure in production + secure: process.env.NODE_ENV === 'production', + sameSite: 'lax' + }) + }) + } catch (error) { + console.error('Error setting cookies:', error) + } + } + } + } + ) +} \ No newline at end of file diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..bd0c391 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 0000000..22a24e0 --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,59 @@ +import {NextRequest, NextResponse} from "next/server"; +import {createClient} from "@/lib/supabase/server"; + +const PUBLIC_ROUTES = [ + '/auth/login', + '/auth/signup', + '/api/auth', + '/_next', + '/favicon.ico', + '/static', + '/images', +]; + +const isPublicRoute = (path: string) => { + return PUBLIC_ROUTES.some(route => path.startsWith(route)); +} + +export async function middleware(request: NextRequest) { + let response = NextResponse.next({ + request: { + headers: request.headers, + }, + }); + + try { + const supabase = await createClient(); + const {data: {user}, error} = await supabase.auth.getUser(); + const path = request.nextUrl.pathname; + + if (!user && !isPublicRoute(path)) { + const redirectUrl = new URL('/auth/login', request.url); + if (request.nextUrl.search) { + redirectUrl.search = request.nextUrl.search; + } + redirectUrl.searchParams.set('redirectTo', request.nextUrl.pathname); + return NextResponse.redirect(redirectUrl); + } + + if (user && path.startsWith('/auth/') && !path.includes("/auth/complete")) { + return NextResponse.redirect(new URL('/', request.url)); + } + + if (user?.id) { + response.headers.set('x-user-id', user.id); + } + + return response; + } catch (error) { + console.error('Middleware error:', error); + return response; + } +} + +export const config = { + matcher: [ + '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)', + "/api/preferences/language", + ], +} \ No newline at end of file diff --git a/src/types/user.d.ts b/src/types/user.d.ts new file mode 100644 index 0000000..60d2818 --- /dev/null +++ b/src/types/user.d.ts @@ -0,0 +1,31 @@ +declare global { + namespace SiPher { + type Messages = { + id: string; + participants: string[]; + name?: string; + messages: { + id: string; + content: string; + }[]; + indexable?: boolean; + } + + type User = { + /** Represents the unique username of a user. */ + username: string, + /** The encrypted password of said user. */ + password: string, + /** Unique UUID, long */ + uuid: string, + /** Short UUID, for index reasons */ + suuid: string, + /** Created at timestamp in UTC */ + created_at: string, + /** Messages field */ + messages: Messages[] + } + } +} + +export {} \ No newline at end of file diff --git a/tailwind.config.ts b/tailwind.config.ts index 41668a3..266c06d 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,80 +1,62 @@ import type { Config } from "tailwindcss"; -const config = { - darkMode: ["class"], - content: [ - "./pages/**/*.{ts,tsx}", - "./components/**/*.{ts,tsx}", - "./app/**/*.{ts,tsx}", - "./src/**/*.{ts,tsx}", +export default { + darkMode: ["class"], + content: [ + "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", + "./src/components/**/*.{js,ts,jsx,tsx,mdx}", + "./src/app/**/*.{js,ts,jsx,tsx,mdx}", ], - prefix: "", theme: { - container: { - center: true, - padding: "2rem", - screens: { - "2xl": "1400px", - }, - }, - extend: { - colors: { - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", - }, - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - }, - borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", - }, - keyframes: { - "accordion-down": { - from: { height: "0" }, - to: { height: "var(--radix-accordion-content-height)" }, - }, - "accordion-up": { - from: { height: "var(--radix-accordion-content-height)" }, - to: { height: "0" }, - }, - }, - animation: { - "accordion-down": "accordion-down 0.2s ease-out", - "accordion-up": "accordion-up 0.2s ease-out", - }, - }, + extend: { + colors: { + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' + }, + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + chart: { + '1': 'hsl(var(--chart-1))', + '2': 'hsl(var(--chart-2))', + '3': 'hsl(var(--chart-3))', + '4': 'hsl(var(--chart-4))', + '5': 'hsl(var(--chart-5))' + } + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' + } + } }, plugins: [require("tailwindcss-animate")], } satisfies Config; - -export default config; diff --git a/tsconfig.json b/tsconfig.json index e06a445..c133409 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,15 +1,14 @@ { "compilerOptions": { - "target": "es5", + "target": "ES2017", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, - "forceConsistentCasingInFileNames": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", - "moduleResolution": "node", + "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", @@ -20,7 +19,7 @@ } ], "paths": { - "@/*": ["./*"] + "@/*": ["./src/*"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],