From 71130970d1f7d8be6ef73d249457fded4e6153b7 Mon Sep 17 00:00:00 2001 From: Shibam Roy Date: Tue, 28 Oct 2025 03:04:11 +0530 Subject: [PATCH 1/4] Added shadcn and switched to typescript --- site/components.json | 22 + site/package.json | 12 +- site/pnpm-lock.yaml | 783 +++++++++++++++++- site/public/hc.png | Bin 0 -> 8494 bytes .../{PrinterCard.jsx => PrinterCard.tsx} | 0 site/src/components/theme-provider.tsx | 73 ++ site/src/components/ui/button.tsx | 60 ++ site/src/components/ui/dropdown-menu.tsx | 255 ++++++ site/src/components/ui/hackclub.tsx | 9 + site/src/components/ui/mode-toggle.tsx | 37 + site/src/components/ui/navbar.tsx | 78 ++ site/src/index.css | 128 ++- site/src/lib/utils.ts | 6 + site/src/main.jsx | 33 - site/src/main.tsx | 39 + site/src/pages/Landing.jsx | 89 +- site/tsconfig.json | 48 ++ site/{vite.config.js => vite.config.ts} | 6 + 18 files changed, 1597 insertions(+), 81 deletions(-) create mode 100644 site/components.json create mode 100644 site/public/hc.png rename site/src/components/{PrinterCard.jsx => PrinterCard.tsx} (100%) create mode 100644 site/src/components/theme-provider.tsx create mode 100644 site/src/components/ui/button.tsx create mode 100644 site/src/components/ui/dropdown-menu.tsx create mode 100644 site/src/components/ui/hackclub.tsx create mode 100644 site/src/components/ui/mode-toggle.tsx create mode 100644 site/src/components/ui/navbar.tsx create mode 100644 site/src/lib/utils.ts delete mode 100644 site/src/main.jsx create mode 100644 site/src/main.tsx create mode 100644 site/tsconfig.json rename site/{vite.config.js => vite.config.ts} (80%) diff --git a/site/components.json b/site/components.json new file mode 100644 index 0000000..2b0833f --- /dev/null +++ b/site/components.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/index.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": {} +} diff --git a/site/package.json b/site/package.json index 87b86ac..f18647a 100644 --- a/site/package.json +++ b/site/package.json @@ -10,15 +10,24 @@ "preview": "vite preview" }, "dependencies": { + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-slot": "^1.2.3", "@tailwindcss/vite": "^4.1.10", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^0.548.0", "react": "^19.1.0", "react-dom": "^19.1.0", "react-markdown": "^10.1.0", "react-router": "^7.6.2", - "tailwindcss": "^4.1.10" + "react-router-dom": "^7.9.4", + "tailwind-merge": "^3.3.1", + "tailwindcss": "^4.1.10", + "typescript": "^5.9.3" }, "devDependencies": { "@eslint/js": "^9.25.0", + "@types/node": "^24.9.1", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", "@vitejs/plugin-react": "^4.4.1", @@ -26,6 +35,7 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.19", "globals": "^16.0.0", + "tw-animate-css": "^1.4.0", "vite": "^6.3.5" } } diff --git a/site/pnpm-lock.yaml b/site/pnpm-lock.yaml index 9f4bdd0..bf83bb4 100644 --- a/site/pnpm-lock.yaml +++ b/site/pnpm-lock.yaml @@ -8,9 +8,24 @@ importers: .: dependencies: + '@radix-ui/react-dropdown-menu': + specifier: ^2.1.16 + version: 2.1.16(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': + specifier: ^1.2.3 + version: 1.2.3(@types/react@19.1.8)(react@19.1.0) '@tailwindcss/vite': specifier: ^4.1.10 - version: 4.1.10(vite@6.3.5(jiti@2.4.2)(lightningcss@1.30.1)) + version: 4.1.10(vite@6.3.5(@types/node@24.9.1)(jiti@2.4.2)(lightningcss@1.30.1)) + class-variance-authority: + specifier: ^0.7.1 + version: 0.7.1 + clsx: + specifier: ^2.1.1 + version: 2.1.1 + lucide-react: + specifier: ^0.548.0 + version: 0.548.0(react@19.1.0) react: specifier: ^19.1.0 version: 19.1.0 @@ -23,13 +38,25 @@ importers: react-router: specifier: ^7.6.2 version: 7.6.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react-router-dom: + specifier: ^7.9.4 + version: 7.9.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + tailwind-merge: + specifier: ^3.3.1 + version: 3.3.1 tailwindcss: specifier: ^4.1.10 version: 4.1.10 + typescript: + specifier: ^5.9.3 + version: 5.9.3 devDependencies: '@eslint/js': specifier: ^9.25.0 version: 9.28.0 + '@types/node': + specifier: ^24.9.1 + version: 24.9.1 '@types/react': specifier: ^19.1.2 version: 19.1.8 @@ -38,7 +65,7 @@ importers: version: 19.1.6(@types/react@19.1.8) '@vitejs/plugin-react': specifier: ^4.4.1 - version: 4.5.2(vite@6.3.5(jiti@2.4.2)(lightningcss@1.30.1)) + version: 4.5.2(vite@6.3.5(@types/node@24.9.1)(jiti@2.4.2)(lightningcss@1.30.1)) eslint: specifier: ^9.25.0 version: 9.28.0(jiti@2.4.2) @@ -51,9 +78,12 @@ importers: globals: specifier: ^16.0.0 version: 16.2.0 + tw-animate-css: + specifier: ^1.4.0 + version: 1.4.0 vite: specifier: ^6.3.5 - version: 6.3.5(jiti@2.4.2)(lightningcss@1.30.1) + version: 6.3.5(@types/node@24.9.1)(jiti@2.4.2)(lightningcss@1.30.1) packages: @@ -332,6 +362,21 @@ packages: resolution: {integrity: sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@floating-ui/core@1.7.3': + resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} + + '@floating-ui/dom@1.7.4': + resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==} + + '@floating-ui/react-dom@2.1.6': + resolution: {integrity: sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/utils@0.2.10': + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -374,6 +419,272 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@radix-ui/primitive@1.1.3': + resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} + + '@radix-ui/react-arrow@1.1.7': + resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} + 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 + + '@radix-ui/react-collection@1.1.7': + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} + 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 + + '@radix-ui/react-compose-refs@1.1.2': + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-context@1.1.2': + resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-direction@1.1.1': + resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dismissable-layer@1.1.11': + resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} + 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 + + '@radix-ui/react-dropdown-menu@2.1.16': + resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} + 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 + + '@radix-ui/react-focus-guards@1.1.3': + resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-focus-scope@1.1.7': + resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} + 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 + + '@radix-ui/react-id@1.1.1': + resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-menu@2.1.16': + resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} + 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 + + '@radix-ui/react-popper@1.2.8': + resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} + 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 + + '@radix-ui/react-portal@1.1.9': + resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} + 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 + + '@radix-ui/react-presence@1.1.5': + resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} + 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 + + '@radix-ui/react-primitive@2.1.3': + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} + 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 + + '@radix-ui/react-roving-focus@1.1.11': + resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} + 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 + + '@radix-ui/react-slot@1.2.3': + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-callback-ref@1.1.1': + resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-controllable-state@1.2.2': + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.2': + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-escape-keydown@1.1.1': + resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.1': + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-rect@1.1.1': + resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-size@1.1.1': + resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/rect@1.1.1': + resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + '@rolldown/pluginutils@1.0.0-beta.11': resolution: {integrity: sha512-L/gAA/hyCSuzTF1ftlzUSI/IKr2POHsv1Dd78GfqkR83KMNuswWD61JxGV2L7nRwBBBSDr6R1gCkdTmoN7W4ag==} @@ -603,6 +914,9 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node@24.9.1': + resolution: {integrity: sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==} + '@types/react-dom@19.1.6': resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==} peerDependencies: @@ -646,6 +960,10 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -690,6 +1008,13 @@ packages: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} + class-variance-authority@0.7.1: + resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -740,6 +1065,9 @@ packages: resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} engines: {node: '>=8'} + detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -863,6 +1191,10 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} @@ -1051,6 +1383,11 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lucide-react@0.548.0: + resolution: {integrity: sha512-63b16z63jM9yc1MwxajHeuu0FRZFsDtljtDjYm26Kd86UQ5HQzu9ksEtoUUw4RBuewodw/tGFmvipePvRsKeDA==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} @@ -1235,6 +1572,33 @@ packages: resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-remove-scroll@2.7.1: + resolution: {integrity: sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react-router-dom@7.9.4: + resolution: {integrity: sha512-f30P6bIkmYvnHHa5Gcu65deIXoA2+r3Eb6PJIAddvsT9aGlchMatJ51GgpU470aSqRRbFX22T70yQNUGuW3DfA==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + react-router@7.6.2: resolution: {integrity: sha512-U7Nv3y+bMimgWjhlT5CRdzHPu2/KVmqPwKUCChW8en5P3znxUqwlYFlbmyj8Rgp1SF6zs5X4+77kBVknkg6a0w==} engines: {node: '>=20.0.0'} @@ -1245,6 +1609,26 @@ packages: react-dom: optional: true + react-router@7.9.4: + resolution: {integrity: sha512-SD3G8HKviFHg9xj7dNODUKDFgpG4xqD5nhyd0mYoB5iISepuZAvzSr8ywxgxKJ52yRzf/HWtVHc9AWwoTbljvA==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + react@19.1.0: resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} engines: {node: '>=0.10.0'} @@ -1306,6 +1690,9 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + tailwind-merge@3.3.1: + resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==} + tailwindcss@4.1.10: resolution: {integrity: sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==} @@ -1327,10 +1714,24 @@ packages: trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tw-animate-css@1.4.0: + resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} @@ -1358,6 +1759,26 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + vfile-message@4.0.3: resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} @@ -1667,6 +2088,23 @@ snapshots: '@eslint/core': 0.15.0 levn: 0.4.1 + '@floating-ui/core@1.7.3': + dependencies: + '@floating-ui/utils': 0.2.10 + + '@floating-ui/dom@1.7.4': + dependencies: + '@floating-ui/core': 1.7.3 + '@floating-ui/utils': 0.2.10 + + '@floating-ui/react-dom@2.1.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@floating-ui/dom': 1.7.4 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + + '@floating-ui/utils@0.2.10': {} + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -1701,6 +2139,246 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@radix-ui/primitive@1.1.3': {} + + '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) + + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) + + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.1.8)(react@19.1.0)': + dependencies: + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/react-context@1.1.2(@types/react@19.1.8)(react@19.1.0)': + dependencies: + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/react-direction@1.1.1(@types/react@19.1.8)(react@19.1.0)': + dependencies: + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) + + '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) + + '@radix-ui/react-focus-guards@1.1.3(@types/react@19.1.8)(react@19.1.0)': + dependencies: + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) + + '@radix-ui/react-id@1.1.1(@types/react@19.1.8)(react@19.1.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/react-menu@2.1.16(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.8)(react@19.1.0) + aria-hidden: 1.2.6 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + react-remove-scroll: 2.7.1(@types/react@19.1.8)(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) + + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@floating-ui/react-dom': 2.1.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-use-rect': 1.1.1(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/rect': 1.1.1 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) + + '@radix-ui/react-portal@1.1.9(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) + + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) + + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) + + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) + + '@radix-ui/react-slot@1.2.3(@types/react@19.1.8)(react@19.1.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.1.8)(react@19.1.0)': + dependencies: + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.1.8)(react@19.1.0)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.1.8)(react@19.1.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.1.8)(react@19.1.0)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.1.8)(react@19.1.0)': + dependencies: + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/react-use-rect@1.1.1(@types/react@19.1.8)(react@19.1.0)': + dependencies: + '@radix-ui/rect': 1.1.1 + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/react-use-size@1.1.1(@types/react@19.1.8)(react@19.1.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.8 + + '@radix-ui/rect@1.1.1': {} + '@rolldown/pluginutils@1.0.0-beta.11': {} '@rollup/rollup-android-arm-eabi@4.43.0': @@ -1827,12 +2505,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.10 '@tailwindcss/oxide-win32-x64-msvc': 4.1.10 - '@tailwindcss/vite@4.1.10(vite@6.3.5(jiti@2.4.2)(lightningcss@1.30.1))': + '@tailwindcss/vite@4.1.10(vite@6.3.5(@types/node@24.9.1)(jiti@2.4.2)(lightningcss@1.30.1))': dependencies: '@tailwindcss/node': 4.1.10 '@tailwindcss/oxide': 4.1.10 tailwindcss: 4.1.10 - vite: 6.3.5(jiti@2.4.2)(lightningcss@1.30.1) + vite: 6.3.5(@types/node@24.9.1)(jiti@2.4.2)(lightningcss@1.30.1) '@types/babel__core@7.20.5': dependencies: @@ -1879,6 +2557,10 @@ snapshots: '@types/ms@2.1.0': {} + '@types/node@24.9.1': + dependencies: + undici-types: 7.16.0 + '@types/react-dom@19.1.6(@types/react@19.1.8)': dependencies: '@types/react': 19.1.8 @@ -1893,7 +2575,7 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@vitejs/plugin-react@4.5.2(vite@6.3.5(jiti@2.4.2)(lightningcss@1.30.1))': + '@vitejs/plugin-react@4.5.2(vite@6.3.5(@types/node@24.9.1)(jiti@2.4.2)(lightningcss@1.30.1))': dependencies: '@babel/core': 7.27.4 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.4) @@ -1901,7 +2583,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.11 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.3.5(jiti@2.4.2)(lightningcss@1.30.1) + vite: 6.3.5(@types/node@24.9.1)(jiti@2.4.2)(lightningcss@1.30.1) transitivePeerDependencies: - supports-color @@ -1924,6 +2606,10 @@ snapshots: argparse@2.0.1: {} + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + bail@2.0.2: {} balanced-match@1.0.2: {} @@ -1961,6 +2647,12 @@ snapshots: chownr@3.0.0: {} + class-variance-authority@0.7.1: + dependencies: + clsx: 2.1.1 + + clsx@2.1.1: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -1997,6 +2689,8 @@ snapshots: detect-libc@2.0.4: {} + detect-node-es@1.1.0: {} + devlop@1.1.0: dependencies: dequal: 2.0.3 @@ -2152,6 +2846,8 @@ snapshots: gensync@1.0.0-beta.2: {} + get-nonce@1.0.1: {} + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 @@ -2308,6 +3004,10 @@ snapshots: dependencies: yallist: 3.1.1 + lucide-react@0.548.0(react@19.1.0): + dependencies: + react: 19.1.0 + magic-string@0.30.17: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -2630,6 +3330,31 @@ snapshots: react-refresh@0.17.0: {} + react-remove-scroll-bar@2.3.8(@types/react@19.1.8)(react@19.1.0): + dependencies: + react: 19.1.0 + react-style-singleton: 2.2.3(@types/react@19.1.8)(react@19.1.0) + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.1.8 + + react-remove-scroll@2.7.1(@types/react@19.1.8)(react@19.1.0): + dependencies: + react: 19.1.0 + react-remove-scroll-bar: 2.3.8(@types/react@19.1.8)(react@19.1.0) + react-style-singleton: 2.2.3(@types/react@19.1.8)(react@19.1.0) + tslib: 2.8.1 + use-callback-ref: 1.3.3(@types/react@19.1.8)(react@19.1.0) + use-sidecar: 1.1.3(@types/react@19.1.8)(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + + react-router-dom@7.9.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + react-router: 7.9.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react-router@7.6.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: cookie: 1.0.2 @@ -2638,6 +3363,22 @@ snapshots: optionalDependencies: react-dom: 19.1.0(react@19.1.0) + react-router@7.9.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + cookie: 1.0.2 + react: 19.1.0 + set-cookie-parser: 2.7.1 + optionalDependencies: + react-dom: 19.1.0(react@19.1.0) + + react-style-singleton@2.2.3(@types/react@19.1.8)(react@19.1.0): + dependencies: + get-nonce: 1.0.1 + react: 19.1.0 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.1.8 + react@19.1.0: {} remark-parse@11.0.0: @@ -2720,6 +3461,8 @@ snapshots: dependencies: has-flag: 4.0.0 + tailwind-merge@3.3.1: {} + tailwindcss@4.1.10: {} tapable@2.2.2: {} @@ -2742,10 +3485,18 @@ snapshots: trough@2.2.0: {} + tslib@2.8.1: {} + + tw-animate-css@1.4.0: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 + typescript@5.9.3: {} + + undici-types@7.16.0: {} + unified@11.0.5: dependencies: '@types/unist': 3.0.3 @@ -2789,6 +3540,21 @@ snapshots: dependencies: punycode: 2.3.1 + use-callback-ref@1.3.3(@types/react@19.1.8)(react@19.1.0): + dependencies: + react: 19.1.0 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.1.8 + + use-sidecar@1.1.3(@types/react@19.1.8)(react@19.1.0): + dependencies: + detect-node-es: 1.1.0 + react: 19.1.0 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.1.8 + vfile-message@4.0.3: dependencies: '@types/unist': 3.0.3 @@ -2799,7 +3565,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite@6.3.5(jiti@2.4.2)(lightningcss@1.30.1): + vite@6.3.5(@types/node@24.9.1)(jiti@2.4.2)(lightningcss@1.30.1): dependencies: esbuild: 0.25.5 fdir: 6.4.6(picomatch@4.0.2) @@ -2808,6 +3574,7 @@ snapshots: rollup: 4.43.0 tinyglobby: 0.2.14 optionalDependencies: + '@types/node': 24.9.1 fsevents: 2.3.3 jiti: 2.4.2 lightningcss: 1.30.1 diff --git a/site/public/hc.png b/site/public/hc.png new file mode 100644 index 0000000000000000000000000000000000000000..ce58e3f1820d70d7734e6959659e43591cb9432b GIT binary patch literal 8494 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 void +} + +const initialState: ThemeProviderState = { + theme: "system", + setTheme: () => null, +} + +const ThemeProviderContext = createContext(initialState) + +export function ThemeProvider({ + children, + defaultTheme = "system", + storageKey = "vite-ui-theme", + ...props +}: ThemeProviderProps) { + const [theme, setTheme] = useState( + () => (localStorage.getItem(storageKey) as Theme) || defaultTheme + ) + + useEffect(() => { + const root = window.document.documentElement + + root.classList.remove("light", "dark") + + if (theme === "system") { + const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") + .matches + ? "dark" + : "light" + + root.classList.add(systemTheme) + return + } + + root.classList.add(theme) + }, [theme]) + + const value = { + theme, + setTheme: (theme: Theme) => { + localStorage.setItem(storageKey, theme) + setTheme(theme) + }, + } + + return ( + + {children} + + ) +} + +export const useTheme = () => { + const context = useContext(ThemeProviderContext) + + if (context === undefined) + throw new Error("useTheme must be used within a ThemeProvider") + + return context +} diff --git a/site/src/components/ui/button.tsx b/site/src/components/ui/button.tsx new file mode 100644 index 0000000..21409a0 --- /dev/null +++ b/site/src/components/ui/button.tsx @@ -0,0 +1,60 @@ +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-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + outline: + "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: + "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2 has-[>svg]:px-3", + sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", + lg: "h-10 rounded-md px-6 has-[>svg]:px-4", + icon: "size-9", + "icon-sm": "size-8", + "icon-lg": "size-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +function Button({ + className, + variant, + size, + asChild = false, + ...props +}: React.ComponentProps<"button"> & + VariantProps & { + asChild?: boolean + }) { + const Comp = asChild ? Slot : "button" + + return ( + + ) +} + +export { Button, buttonVariants } diff --git a/site/src/components/ui/dropdown-menu.tsx b/site/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..eaed9ba --- /dev/null +++ b/site/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,255 @@ +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function DropdownMenu({ + ...props +}: React.ComponentProps) { + return +} + +function DropdownMenuPortal({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuContent({ + className, + sideOffset = 4, + ...props +}: React.ComponentProps) { + return ( + + + + ) +} + +function DropdownMenuGroup({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuItem({ + className, + inset, + variant = "default", + ...props +}: React.ComponentProps & { + inset?: boolean + variant?: "default" | "destructive" +}) { + return ( + + ) +} + +function DropdownMenuCheckboxItem({ + className, + children, + checked, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ) +} + +function DropdownMenuRadioGroup({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuRadioItem({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ) +} + +function DropdownMenuLabel({ + className, + inset, + ...props +}: React.ComponentProps & { + inset?: boolean +}) { + return ( + + ) +} + +function DropdownMenuSeparator({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuShortcut({ + className, + ...props +}: React.ComponentProps<"span">) { + return ( + + ) +} + +function DropdownMenuSub({ + ...props +}: React.ComponentProps) { + return +} + +function DropdownMenuSubTrigger({ + className, + inset, + children, + ...props +}: React.ComponentProps & { + inset?: boolean +}) { + return ( + + {children} + + + ) +} + +function DropdownMenuSubContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + DropdownMenu, + DropdownMenuPortal, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuLabel, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuSub, + DropdownMenuSubTrigger, + DropdownMenuSubContent, +} diff --git a/site/src/components/ui/hackclub.tsx b/site/src/components/ui/hackclub.tsx new file mode 100644 index 0000000..1200e83 --- /dev/null +++ b/site/src/components/ui/hackclub.tsx @@ -0,0 +1,9 @@ +import { Link } from "react-router-dom" + +export default function Hackclub() { + return ( + + Hackclub + + ) +} diff --git a/site/src/components/ui/mode-toggle.tsx b/site/src/components/ui/mode-toggle.tsx new file mode 100644 index 0000000..352279c --- /dev/null +++ b/site/src/components/ui/mode-toggle.tsx @@ -0,0 +1,37 @@ +import { Moon, Sun } from "lucide-react" + +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { useTheme } from "@/components/theme-provider" + +export function ModeToggle() { + const { setTheme } = useTheme() + + return ( + + + + + + setTheme("light")}> + Light + + setTheme("dark")}> + Dark + + setTheme("system")}> + System + + + + ) +} diff --git a/site/src/components/ui/navbar.tsx b/site/src/components/ui/navbar.tsx new file mode 100644 index 0000000..4e79e4f --- /dev/null +++ b/site/src/components/ui/navbar.tsx @@ -0,0 +1,78 @@ +import { useState } from "react" +import { Link, useLocation } from "react-router-dom" +import { Button } from "@/components/ui/button" +import { Menu, X } from "lucide-react" +import { ModeToggle } from "@/components/ui/mode-toggle" +import Hackclub from "./hackclub.js" + +export default function Navbar() { + + const [isOpen, setIsOpen] = useState(false) + const location = useLocation() + + const navLinks = [ + { path: "/", label: "Home" }, + { path: "/printers", label: "Printers" }, + { path: "/#details", label: "Details" }, + { path: "/#faq", label: "FAQ" }, + ] + + return ( + + ) +} diff --git a/site/src/index.css b/site/src/index.css index a461c50..d5c1ac2 100644 --- a/site/src/index.css +++ b/site/src/index.css @@ -1 +1,127 @@ -@import "tailwindcss"; \ No newline at end of file +@import "tailwindcss"; +@import "tw-animate-css"; +@import url('https://fonts.googleapis.com/css2?family=Silkscreen:wght@400;700&display=swap'); + +@custom-variant dark (&:is(.dark *)); + +@theme inline { + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +:root { + --radius: 0.625rem; + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} + + +body{ + max-width:100vw; + overflow-x:hidden; +} diff --git a/site/src/lib/utils.ts b/site/src/lib/utils.ts new file mode 100644 index 0000000..bd0c391 --- /dev/null +++ b/site/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/site/src/main.jsx b/site/src/main.jsx deleted file mode 100644 index 513119a..0000000 --- a/site/src/main.jsx +++ /dev/null @@ -1,33 +0,0 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import { - createBrowserRouter, - RouterProvider, -} from "react-router"; -import './index.css' - -import PrintersPage from './pages/PrintersPage.jsx'; -import Landing from './pages/Landing.jsx'; - -// actual routing -const router = createBrowserRouter([ - { - path: "/", - element: , - }, - { - path: "/printers", - element: , - }, - { - path: "/test", - element:
TEST ROUTE
- } -]); - -// dom setup -createRoot(document.getElementById('root')).render( - - - , -) \ No newline at end of file diff --git a/site/src/main.tsx b/site/src/main.tsx new file mode 100644 index 0000000..7569e01 --- /dev/null +++ b/site/src/main.tsx @@ -0,0 +1,39 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import { ThemeProvider } from '@/components/theme-provider'; + +import PrintersPage from './pages/PrintersPage'; +import Landing from './pages/Landing'; + +import { + createBrowserRouter, + RouterProvider, +} from "react-router-dom"; + + + +// actual routing +const router = createBrowserRouter([ + { + path: "/", + element: , + }, + { + path: "/printers", + element: , + }, + { + path: "/test", + element:
TEST ROUTE
+ } +]); + +// dom setup +createRoot(document.getElementById('root')).render( + + + + + , +) diff --git a/site/src/pages/Landing.jsx b/site/src/pages/Landing.jsx index 33d53e7..798b7b0 100644 --- a/site/src/pages/Landing.jsx +++ b/site/src/pages/Landing.jsx @@ -1,15 +1,15 @@ +import { Button } from "@/components/ui/button"; +import { Link } from "react-router-dom"; +import Navbar from "@/components/ui/navbar"; import ReactMarkdown from 'react-markdown'; const markdownContent = ` ### **For requesters** - 1. Post your request in \#printing-legion\! Include your country, the .STL files to print, and a picture of what you need 2. Go to [printlegion.hackclub.com](http://printlegion.hackclub.com) and reach out to someone\! Ask them to print your stuff 3. Pay for the shipping label using your YSWS card grant. You do not get extra money for this\! 4. Repeat - ### **For printers:** - 1. Sign up by filling out [forms.hackclub.com/printing-legion](http://forms.hackclub.com/printing-legion) 2. Wait for someone to reach out\! If you want a job sooner, feel free to grab any you see in \#printing-legion 3. Print their part\! Once you do, ping them in \#printing-legion with a picture of their print\! @@ -17,12 +17,9 @@ const markdownContent = ` 5. Fill out [https://forms.hackclub.com/sent-print](https://forms.hackclub.com/sent-print) 6. Once you’ve printed 750g of filament & shipped it all out, you’ll get an email asking for your info\! 7. Repeat\! - ### Notes: - **Filament reimbursement:** Printing legion is sponsored by Polymaker\! They’ve provided us free filament for the following countries: - - United States - Canada - Australia @@ -30,43 +27,59 @@ Printing legion is sponsored by Polymaker\! They’ve provided us free filament - France - Germany - South Africa - Filament will be shipped directly from Polymaker warehouses. These countries are confirmed to not need to pay any customs, so you shouldn’t have issues\! - If you’re not from one of these countries, we’ll send you a $20-25 HCB Card grant to get filament instead! `; export default function Landing() { return ( -
-

Printing Legion

-

- Welcome to the printing legion! This is the international network of 3D printers from Hack Club! -

- - {} -
-

, - h2: ({node, ...props}) =>

, - h3: ({node, ...props}) =>

, - p: ({node, ...props}) =>

, - ul: ({node, ...props}) =>

    , - ol: ({node, ...props}) =>
      , - li: ({node, ...props}) =>
    1. , - strong: ({node, ...props}) => , - em: ({node, ...props}) => , - a: ({node, ...props}) => , - }} - > - {markdownContent} - -

+ <> + + +
+ ); - } \ No newline at end of file +} diff --git a/site/tsconfig.json b/site/tsconfig.json new file mode 100644 index 0000000..f065e3a --- /dev/null +++ b/site/tsconfig.json @@ -0,0 +1,48 @@ +{ + // Visit https://aka.ms/tsconfig to read more about this file + "compilerOptions": { + // File Layout + // "rootDir": "./src", + // "outDir": "./dist", + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, + + // Environment Settings + // See also https://aka.ms/tsconfig/module + "module": "nodenext", + "target": "esnext", + "types": [], + // For nodejs: + // "lib": ["esnext"], + // "types": ["node"], + // and npm install -D @types/node + + // Other Outputs + "sourceMap": true, + "declaration": true, + "declarationMap": true, + + // Stricter Typechecking Options + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + + // Style Options + // "noImplicitReturns": true, + // "noImplicitOverride": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, + // "noFallthroughCasesInSwitch": true, + // "noPropertyAccessFromIndexSignature": true, + + // Recommended Options + "strict": true, + "jsx": "react-jsx", + "verbatimModuleSyntax": true, + "isolatedModules": true, + "noUncheckedSideEffectImports": true, + "moduleDetection": "force", + "skipLibCheck": true, + } +} diff --git a/site/vite.config.js b/site/vite.config.ts similarity index 80% rename from site/vite.config.js rename to site/vite.config.ts index 7ee4159..fd15dc0 100644 --- a/site/vite.config.js +++ b/site/vite.config.ts @@ -1,6 +1,7 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' +import path from "path"; // https://vite.dev/config/ export default defineConfig({ @@ -17,4 +18,9 @@ server: { react(), tailwindcss() ], +resolve: { + alias: { + "@": path.resolve(__dirname, "./src"), + }, + }, }) From 96baee0c7aac11ef031c2973133f9a002737ceb8 Mon Sep 17 00:00:00 2001 From: Shibam Roy Date: Tue, 28 Oct 2025 11:45:14 +0530 Subject: [PATCH 2/4] Added footer and improved UI --- site/src/components/ui/footer.tsx | 33 +++++++++++++++++++++++++++++++ site/src/components/ui/navbar.tsx | 1 - site/src/pages/Landing.jsx | 12 +++++++---- 3 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 site/src/components/ui/footer.tsx diff --git a/site/src/components/ui/footer.tsx b/site/src/components/ui/footer.tsx new file mode 100644 index 0000000..16d4740 --- /dev/null +++ b/site/src/components/ui/footer.tsx @@ -0,0 +1,33 @@ +import { Button } from "./button.js"; +import { ArrowUpIcon, Heart } from "lucide-react"; + +export default function Footer() { + return ( +
+
+ + +
+

Made with ❤️ by

+

Hackclubbers :3

+
+ + +
+ +
+ © {new Date().getFullYear()} Hack Club. 501(c)(3) nonprofit (EIN: 81-2908499) +
+
+ ) +} diff --git a/site/src/components/ui/navbar.tsx b/site/src/components/ui/navbar.tsx index 4e79e4f..863a7c6 100644 --- a/site/src/components/ui/navbar.tsx +++ b/site/src/components/ui/navbar.tsx @@ -14,7 +14,6 @@ export default function Navbar() { { path: "/", label: "Home" }, { path: "/printers", label: "Printers" }, { path: "/#details", label: "Details" }, - { path: "/#faq", label: "FAQ" }, ] return ( diff --git a/site/src/pages/Landing.jsx b/site/src/pages/Landing.jsx index 798b7b0..0d84485 100644 --- a/site/src/pages/Landing.jsx +++ b/site/src/pages/Landing.jsx @@ -2,6 +2,7 @@ import { Button } from "@/components/ui/button"; import { Link } from "react-router-dom"; import Navbar from "@/components/ui/navbar"; import ReactMarkdown from 'react-markdown'; +import Footer from "@/components/ui/footer"; const markdownContent = ` ### **For requesters** @@ -49,17 +50,18 @@ export default function Landing() {
-
-
+
+
+

Details

, @@ -79,7 +81,9 @@ export default function Landing() {

+
+
@@ -83,7 +83,6 @@ export default function Landing() { -