diff --git a/package.json b/package.json index 2ace533..bb73693 100644 --- a/package.json +++ b/package.json @@ -33,11 +33,14 @@ "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "autoprefixer": "^10.4.20", "eslint": "^8", "eslint-config-next": "15.0.2", "husky": "^9.1.6", "lint-staged": "^15.2.10", + "postcss": "^8.4.49", "prettier": "^3.3.3", + "tailwindcss": "^3.4.15", "typescript": "^5" }, "lint-staged": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1f71681..a708adc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,6 +51,9 @@ importers: '@types/react-dom': specifier: ^18 version: 18.3.1 + autoprefixer: + specifier: ^10.4.20 + version: 10.4.20(postcss@8.4.49) eslint: specifier: ^8 version: 8.57.1 @@ -63,9 +66,15 @@ importers: lint-staged: specifier: ^15.2.10 version: 15.2.10 + postcss: + specifier: ^8.4.49 + version: 8.4.49 prettier: specifier: ^3.3.3 version: 3.3.3 + tailwindcss: + specifier: ^3.4.15 + version: 3.4.15 typescript: specifier: ^5 version: 5.6.3 @@ -124,6 +133,10 @@ packages: '@adraffy/ens-normalize@1.11.0': resolution: {integrity: sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==} + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} @@ -391,6 +404,28 @@ packages: cpu: [x64] os: [win32] + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@module-federation/runtime@0.1.21': resolution: {integrity: sha512-/p4BhZ0SnjJuiL0wwu+FebFgIUJ9vM+oCY7CyprUHImyi/Y23ulI61WNWMVrKQGgdMoXQDQCL8RH4EnrVP2ZFw==} @@ -571,6 +606,10 @@ packages: resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==} engines: {node: '>= 10.0.0'} + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + '@playwright/test@1.48.2': resolution: {integrity: sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==} engines: {node: '>=18'} @@ -898,10 +937,16 @@ packages: ansicolors@0.3.2: resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -954,6 +999,13 @@ packages: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -998,6 +1050,11 @@ packages: brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + browserslist@4.24.2: + resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} @@ -1010,6 +1067,10 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + caniuse-lite@1.0.30001676: resolution: {integrity: sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==} @@ -1076,6 +1137,10 @@ packages: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + compare-func@2.0.0: resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} @@ -1129,6 +1194,11 @@ packages: crossws@0.3.1: resolution: {integrity: sha512-HsZgeVYaG+b5zA+9PbIPGq4+J/CJynJuearykPsXx4V/eMhyQ5EDVg3Ak2FBZtVXCiOLu/U7IiwDHTr9MA+IKw==} + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -1205,6 +1275,12 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -1224,6 +1300,12 @@ packages: duplexify@4.1.3: resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + electron-to-chromium@1.5.60: + resolution: {integrity: sha512-HcraRUkTKJ+8yA3b10i9qvhUlPBRDlKjn1XGek1zDGVfAKcvi8TsUnImGqLiEm9j6ZulxXIWWIo9BmbkbCTGgA==} + elliptic@6.5.4: resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} @@ -1489,10 +1571,17 @@ packages: for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + form-data@4.0.1: resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} engines: {node: '>= 6'} + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -1562,6 +1651,10 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -1848,6 +1941,9 @@ packages: resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==} engines: {node: '>= 0.4'} + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jiti@1.21.6: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true @@ -1913,6 +2009,10 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + lilconfig@3.1.2: resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} engines: {node: '>=14'} @@ -2040,6 +2140,10 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + mlly@1.7.2: resolution: {integrity: sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==} @@ -2053,6 +2157,9 @@ packages: multiformats@9.9.0: resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2101,10 +2208,17 @@ packages: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + npm-run-path@5.3.0: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2185,6 +2299,9 @@ packages: resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + pako@2.1.0: resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} @@ -2219,6 +2336,10 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -2234,6 +2355,10 @@ packages: engines: {node: '>=0.10'} hasBin: true + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + pino-abstract-transport@0.5.0: resolution: {integrity: sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==} @@ -2244,6 +2369,10 @@ packages: resolution: {integrity: sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==} hasBin: true + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + pkg-types@1.2.1: resolution: {integrity: sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==} @@ -2261,10 +2390,51 @@ packages: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + postcss@8.4.31: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} + postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + engines: {node: ^10 || ^12 || >=14} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -2327,6 +2497,9 @@ packages: resolution: {integrity: sha512-GbZ7hpPHQMiEu53BqEaPQVM/4GG4hARo+mqEEnx4rYporDvNvUjutiAFxYFSbu6sgHwcr7LeFv8htEOwALVA2A==} engines: {node: '>=0.10.0'} + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -2516,6 +2689,10 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + string-width@7.2.0: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} @@ -2578,6 +2755,11 @@ packages: babel-plugin-macros: optional: true + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -2598,6 +2780,11 @@ packages: resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} engines: {node: '>=18'} + tailwindcss@3.4.15: + resolution: {integrity: sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==} + engines: {node: '>=14.0.0'} + hasBin: true + tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} @@ -2609,6 +2796,13 @@ packages: text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + thread-stream@0.15.2: resolution: {integrity: sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==} @@ -2641,6 +2835,9 @@ packages: peerDependencies: typescript: '>=4.2.0' + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + ts-mixer@6.0.4: resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==} @@ -2760,6 +2957,12 @@ packages: resolution: {integrity: sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ==} hasBin: true + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uqr@0.1.2: resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} @@ -2827,6 +3030,10 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + wrap-ansi@9.0.0: resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} engines: {node: '>=18'} @@ -2890,6 +3097,8 @@ snapshots: '@adraffy/ens-normalize@1.11.0': {} + '@alloc/quick-lru@5.2.0': {} + '@babel/code-frame@7.26.2': dependencies: '@babel/helper-validator-identifier': 7.25.9 @@ -3234,6 +3443,32 @@ snapshots: '@img/sharp-win32-x64@0.33.5': optional: true + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@module-federation/runtime@0.1.21': dependencies: '@module-federation/sdk': 0.1.21 @@ -3363,6 +3598,9 @@ snapshots: '@parcel/watcher-win32-ia32': 2.4.1 '@parcel/watcher-win32-x64': 2.4.1 + '@pkgjs/parseargs@0.11.0': + optional: true + '@playwright/test@1.48.2': dependencies: playwright: 1.48.2 @@ -3907,11 +4145,15 @@ snapshots: ansicolors@0.3.2: {} + any-promise@1.3.0: {} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 + arg@5.0.2: {} + argparse@2.0.1: {} aria-query@5.3.2: {} @@ -3989,6 +4231,16 @@ snapshots: atomic-sleep@1.0.0: {} + autoprefixer@10.4.20(postcss@8.4.49): + dependencies: + browserslist: 4.24.2 + caniuse-lite: 1.0.30001676 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.4.49 + postcss-value-parser: 4.2.0 + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 @@ -4030,6 +4282,13 @@ snapshots: brorand@1.1.0: {} + browserslist@4.24.2: + dependencies: + caniuse-lite: 1.0.30001676 + electron-to-chromium: 1.5.60 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.24.2) + busboy@1.6.0: dependencies: streamsearch: 1.1.0 @@ -4044,6 +4303,8 @@ snapshots: callsites@3.1.0: {} + camelcase-css@2.0.1: {} + caniuse-lite@1.0.30001676: {} cardinal@2.1.1: @@ -4123,6 +4384,8 @@ snapshots: commander@12.1.0: {} + commander@4.1.1: {} + compare-func@2.0.0: dependencies: array-ify: 1.0.0 @@ -4177,6 +4440,8 @@ snapshots: dependencies: uncrypto: 0.1.3 + cssesc@3.0.0: {} + csstype@3.1.3: {} damerau-levenshtein@1.0.8: {} @@ -4238,6 +4503,10 @@ snapshots: detect-libc@2.0.3: optional: true + didyoumean@1.2.2: {} + + dlv@1.1.3: {} + doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -4259,6 +4528,10 @@ snapshots: readable-stream: 3.6.2 stream-shift: 1.0.3 + eastasianwidth@0.2.0: {} + + electron-to-chromium@1.5.60: {} + elliptic@6.5.4: dependencies: bn.js: 4.12.0 @@ -4686,12 +4959,19 @@ snapshots: dependencies: is-callable: 1.2.7 + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + form-data@4.0.1: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 + fraction.js@4.3.7: {} + fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 @@ -4761,6 +5041,15 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -5031,6 +5320,12 @@ snapshots: reflect.getprototypeof: 1.0.6 set-function-name: 2.0.2 + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + jiti@1.21.6: {} jiti@2.3.3: {} @@ -5089,6 +5384,8 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lilconfig@2.1.0: {} + lilconfig@3.1.2: {} lines-and-columns@1.2.4: {} @@ -5221,6 +5518,8 @@ snapshots: minimist@1.2.8: {} + minipass@7.1.2: {} + mlly@1.7.2: dependencies: acorn: 8.14.0 @@ -5234,6 +5533,12 @@ snapshots: multiformats@9.9.0: {} + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + nanoid@3.3.7: {} natural-compare@1.4.0: {} @@ -5274,8 +5579,12 @@ snapshots: node-forge@1.3.1: {} + node-releases@2.0.18: {} + normalize-path@3.0.0: {} + normalize-range@0.1.2: {} + npm-run-path@5.3.0: dependencies: path-key: 4.0.0 @@ -5367,6 +5676,8 @@ snapshots: dependencies: p-limit: 4.0.0 + package-json-from-dist@1.0.1: {} + pako@2.1.0: {} parent-module@1.0.1: @@ -5392,6 +5703,11 @@ snapshots: path-parse@1.0.7: {} + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + pathe@1.1.2: {} picocolors@1.1.1: {} @@ -5400,6 +5716,8 @@ snapshots: pidtree@0.6.0: {} + pify@2.3.0: {} + pino-abstract-transport@0.5.0: dependencies: duplexify: 4.1.3 @@ -5421,6 +5739,8 @@ snapshots: sonic-boom: 2.8.0 thread-stream: 0.15.2 + pirates@4.0.6: {} + pkg-types@1.2.1: dependencies: confbox: 0.1.8 @@ -5437,12 +5757,49 @@ snapshots: possible-typed-array-names@1.0.0: {} + postcss-import@15.1.0(postcss@8.4.49): + dependencies: + postcss: 8.4.49 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + + postcss-js@4.0.1(postcss@8.4.49): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.49 + + postcss-load-config@4.0.2(postcss@8.4.49): + dependencies: + lilconfig: 3.1.2 + yaml: 2.5.1 + optionalDependencies: + postcss: 8.4.49 + + postcss-nested@6.2.0(postcss@8.4.49): + dependencies: + postcss: 8.4.49 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + postcss@8.4.31: dependencies: nanoid: 3.3.7 picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.4.49: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.1 + source-map-js: 1.2.1 + prelude-ls@1.2.1: {} prettier@3.3.3: {} @@ -5495,6 +5852,10 @@ snapshots: react@19.0.0-rc-02c0e824-20241028: {} + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 @@ -5748,6 +6109,12 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + string-width@7.2.0: dependencies: emoji-regex: 10.4.0 @@ -5822,6 +6189,16 @@ snapshots: client-only: 0.0.1 react: 19.0.0-rc-02c0e824-20241028 + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -5838,12 +6215,47 @@ snapshots: system-architecture@0.1.0: {} + tailwindcss@3.4.15: + 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: 2.1.0 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.4.49 + postcss-import: 15.1.0(postcss@8.4.49) + postcss-js: 4.0.1(postcss@8.4.49) + postcss-load-config: 4.0.2(postcss@8.4.49) + postcss-nested: 6.2.0(postcss@8.4.49) + postcss-selector-parser: 6.1.2 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + tapable@2.2.1: {} text-extensions@2.4.0: {} text-table@0.2.0: {} + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + thread-stream@0.15.2: dependencies: real-require: 0.1.0 @@ -5874,6 +6286,8 @@ snapshots: dependencies: typescript: 5.6.3 + ts-interface-checker@0.1.13: {} + ts-mixer@6.0.4: {} tsconfig-paths@3.15.0: @@ -5979,6 +6393,12 @@ snapshots: consola: 3.2.3 pathe: 1.1.2 + update-browserslist-db@1.1.1(browserslist@4.24.2): + dependencies: + browserslist: 4.24.2 + escalade: 3.2.0 + picocolors: 1.1.1 + uqr@0.1.2: {} uri-js@4.4.1: @@ -6078,6 +6498,12 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + wrap-ansi@9.0.0: dependencies: ansi-styles: 6.2.1 diff --git a/postcss.config.cjs b/postcss.config.cjs new file mode 100644 index 0000000..33ad091 --- /dev/null +++ b/postcss.config.cjs @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/public/starknet_logo.png b/public/starknet_logo.png new file mode 100644 index 0000000..49fac48 Binary files /dev/null and b/public/starknet_logo.png differ diff --git a/src/app/globals.css b/src/app/globals.css index 982f8dd..d3e793f 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,7 +1,16 @@ +/* app/globals.css */ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* Your custom CSS here */ + html, body { max-width: 100vw; overflow-x: hidden; + background-color: #000; + color: #fff; } body { @@ -21,105 +30,291 @@ a { text-decoration: none; } -.full { - width: 100%; +.column { + flex-direction: column; } -/* Accordion */ - -.accordion-button { - width: 100%; +/* Button -- START */ +button { + font-size: 18px; + font-weight: 500; + line-height: 24px; + text-align: left; + text-underline-position: from-font; + text-decoration-skip-ink: none; + border: none; + background-color: #262933; + color: #fff; + border-radius: 8px; + padding: 12px; display: flex; - justify-content: space-between; align-items: center; - background-color: transparent; - border: none; + justify-content: space-between; cursor: pointer; - transition: background-color 0.2s; - padding: 16px 0; + gap: 4px; + position: relative; } -.accordion-button-with-border { - padding: 8px; +button.sections-list-button { + background-color: #14161c; + color: #6f727c; } -.accordion-title { - font-weight: bold; - font-size: 1.5em; +button:not(.selected, :disabled):hover { + background-color: #464c5e; } -.accordion-title-with-border { - font-size: 1em; +button.disabled { + opacity: 0.4; + cursor: default; } -.accordion-icon { - width: 16px; - height: 16px; - transition: transform 0.2s; +button.selected { + background-color: #aecbfc; + color: #090e12; } -.accordion-icon-open { - transform: rotate(180deg); +button.connector { + background-color: #464c5e; + height: 40px; + font-size: 14px; + line-height: 14px; + font-weight: 500; + gap: 8px; + justify-content: center; } -.accordion-content { - overflow: hidden; - transition: max-height 0.2s ease-out; - max-height: 0; +button.connector > div { + gap: 8px; + align-items: center; } -.accordion-content-open { - max-height: 500px; +.connectors-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: 16px; } -/* Button */ -button { - border: 1px solid #c8c8c8; - background-color: transparent; - border-radius: 8px; - padding: 8px; - display: flex; - align-items: center; - justify-content: space-between; - cursor: pointer; - gap: 4px; - font-weight: bold; -} +/* Button -- END */ .chevron-right { width: 16px; height: 16px; transition: transform 0.2s; transform: rotate(-90deg); + color: #090e12; +} + +.chevron-down { + width: 16px; + height: 16px; + transition: transform 0.2s; + color: #6f727c; +} + +.chevron-up { + width: 16px; + height: 16px; + transition: transform 0.2s; + color: #6f727c; + transform: rotate(-180deg); +} + +.chevron-left { + width: 16px; + height: 16px; + transition: transform 0.2s; + color: #6f727c; + transform: rotate(-270deg); } input, textarea { padding: 8px; border-radius: 8px; - border: 1px solid #c8c8c8; + border: 1px solid #464c5e; + background-color: #14161c; + color: #a2a2a2; } button[type="submit"] { - background-color: #cefff3; + border: solid 1px #85b6ff; + color: #85b6ff; + text-align: center; } -.demo-dapp-container { - padding: 40px 0; +/* Header */ + +.header-container { + padding: 32px 116px 16px; } -/* Small screens (smartphones) - Portrait and Landscape */ -@media only screen and (max-width: 767px) { - .demo-dapp-container { - padding: 20px; - } - /* Your mobile styles here */ +.header-profile-container { + background-color: #14161c; + border-radius: 12px; + gap: 12px; + padding: 16px; +} + +.header-title { + font-weight: 400; + font-size: 20px; + line-height: 24px; + letter-spacing: 1%; + margin-top: 2px; } -/* Extra small screens (smaller smartphones) */ -@media only screen and (max-width: 480px) { - /* Your styles for very small devices */ - .demo-dapp-container { - padding: 16px; +.header-account-separator { + border-left: solid 1px #464c5e; + margin: -4px 0; +} + +/* Header - END */ + +/* Section */ +.section-layout-heading { + gap: 8px; + position: relative; + border-bottom: solid 1px #262933; + padding-bottom: 16px; +} + +.section-layout-container { + flex-direction: column; + gap: 24px; + width: 100%; + background-color: #14161c; + padding: 24px; + border-radius: 12px; + height: fit-content; +} + +.section-title { + font-size: 18px; + font-weight: 600; + line-height: 24px; + text-align: left; + text-underline-position: from-font; + text-decoration-skip-ink: none; +} + +.connector-icon { + height: 17px; + width: 17px; +} + +.connector-icon > svg { + height: 17px; + width: 17px; +} + +.get-started-title { + font-size: 48px; + font-weight: 600; + line-height: 58px; + text-align: left; + text-underline-position: from-font; + text-decoration-skip-ink: none; + color: "#FFF"; +} + +.get-started-title::before { + content: "Manage "; +} + +.get-started-title::after { + content: " Starknet accounts"; +} + +.get-started-title { + color: #6f727c; +} + +.get-started-title::before, +.get-started-title::after { + color: #fff; +} + +.get-started-subtitle { + color: #6f727c; + font-size: 16px; + font-weight: 500; + line-height: 24px; + text-align: left; + text-underline-position: from-font; + text-decoration-skip-ink: none; +} + +/* Section */ + +/* Status -- Start */ +.status-grid-container { + /* Create a grid with auto-fill columns, minimum 200px width */ + display: grid; + grid-template-columns: repeat(2, 1fr); + /* Limit to maximum 4 columns using max-width */ + max-width: 800px; + width: 100%; + gap: 80px; +} + +.status-grid-item-title { + font-size: 14px; + font-weight: 500; + line-height: 14px; + text-align: left; + text-underline-position: from-font; + text-decoration-skip-ink: none; + color: #6f727c; +} + +.status-grid-item-value { + font-size: 16px; + font-weight: 500; + line-height: 24px; + text-align: left; + text-underline-position: from-font; + text-decoration-skip-ink: none; + display: flex; + align-items: center; +} + +.truncate { + display: inline-block; + max-width: 100%; + vertical-align: top; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* Ensure no more than 4 columns at any viewport width */ +@media (min-width: 1000px) { + .status-grid-container { + grid-template-columns: repeat(4, 1fr); } } +/* Status -- End */ + +/* Sections list */ +.sections-container { + gap: 180px; + background-color: #090e12; + padding: 76px 116px; + flex: 1; + height: 100%; +} + +/* Section list - End */ + +/* Connection -- Start */ + +.starknet-react-connectors-title { + font-size: 16px; + font-weight: 500; + line-height: 24px; + text-align: left; + text-underline-position: from-font; + text-decoration-skip-ink: none; +} +/* Connection -- End */ diff --git a/src/app/layout.tsx b/src/app/layout.tsx index fcef23f..599f1b5 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,9 @@ import type { Metadata } from "next" +import { Inter } from "next/font/google" import "./globals.css" +const inter = Inter({ subsets: ["latin"] }) + export const metadata: Metadata = { title: "Demo dapp starknet", description: @@ -14,7 +17,13 @@ export default function RootLayout({ }>) { return ( - {children} + +
+ {children} +
+ ) } diff --git a/src/app/page.tsx b/src/app/page.tsx index eeafec3..9bc0f3b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,23 +1,16 @@ "use client" import { StarknetDapp } from "@/components/StarknetDapp" -import { Flex } from "@/components/ui/Flex" import { connectors } from "@/connectors" -import { CHAIN_ID } from "@/constants" import { mainnet, sepolia } from "@starknet-react/chains" import { publicProvider, StarknetConfig } from "@starknet-react/core" -import { constants } from "starknet" - -/* TODO: update ui */ export default function Home() { - const chains = [ - CHAIN_ID === constants.NetworkName.SN_MAIN ? mainnet : sepolia, - ] + const chains = [mainnet, sepolia] const providers = publicProvider() return ( - +
{/* eslint-disable @typescript-eslint/no-explicit-any */} {/* eslint-enable @typescript-eslint/no-explicit-any */} - +
) } diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 0000000..901eb8a --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,54 @@ +import { isMainnet, toHexChainid } from "@/helpers/chainId" +import { formatTruncatedAddress } from "@/helpers/formatAddress" +import { useAccount, useBalance } from "@starknet-react/core" +import { AvatarIcon } from "./icons/AvatarIcon" +import { LogoIcon } from "./icons/LogoIcon" +import { WalletIcon } from "./icons/WalletIcon" + +const Header = () => { + const { address, isConnected, chainId } = useAccount() + + const { data: balance } = useBalance({ + address: address, + }) + + const hexChainId = toHexChainid(chainId) + + return ( +
+
+ +

Demo dapp

+
+ + {isConnected && ( +
+
+ + {balance && balance?.formatted.length > 7 + ? `${balance.formatted.slice(0, 7)} ETH` + : `${balance?.formatted} ETH`} +
+
+
+ window.open( + isMainnet(hexChainId) + ? `https://voyager.online/contract/${address}` + : `https://sepolia.voyager.online/contract/${address}`, + "_blank", + ) + } + > + + {formatTruncatedAddress(address || "")} +
+
+ )} +
+
+ ) +} + +export { Header } diff --git a/src/components/StarknetDapp.tsx b/src/components/StarknetDapp.tsx index 0479d12..b271ac9 100644 --- a/src/components/StarknetDapp.tsx +++ b/src/components/StarknetDapp.tsx @@ -1,27 +1,81 @@ "use client" import { SignMessage } from "@/components/sections/SignMessage" import { Transactions } from "@/components/sections/Transactions/Transactions" +import { useAccount } from "@starknet-react/core" +import { useState } from "react" import { Connect } from "./connect/Connect" -import { Flex } from "./ui/Flex" +import { Header } from "./Header" import { AccountStatus } from "./sections/AccountStatus" import { AddToken } from "./sections/ERC20/AddToken" import { Network } from "./sections/Network/Network" +import { SectionButton } from "./sections/SectionButton" +import { Section } from "./sections/types" -const StarknetDapp = () => ( - - - - - - - - -) +const StarknetDapp = () => { + const [section, setSection] = useState
(undefined) + const { isConnected } = useAccount() + + return ( +
+
+ +
+
+

your

+ + Starknet utilizes the power of STARK technology to ensure + computational integrity. + +
+ +
+ +
+
+ +
+
+ + + + + +
+ +
+ {section === "Connection" && } + {section === "Transactions" && } + {section === "Signing" && } + {section === "Network" && } + {section === "ERC20" && } +
+
+
+ ) +} export { StarknetDapp } diff --git a/src/components/connect/Connect.tsx b/src/components/connect/Connect.tsx index 64a3859..610f295 100644 --- a/src/components/connect/Connect.tsx +++ b/src/components/connect/Connect.tsx @@ -1,15 +1,16 @@ -import { useAccount, useConnect } from "@starknet-react/core" +import { useAccount, useConnect, useDisconnect } from "@starknet-react/core" +import Image from "next/image" import { useEffect, useState } from "react" -import { disconnect } from "starknetkit" -import { Accordion } from "../ui/Accordion" +import { SectionLayout } from "../sections/SectionLayout" import { Button } from "../ui/Button" -import { Flex } from "../ui/Flex" import { ConnectorButton } from "./ConnectorButton" import { ConnectStarknetkitModal } from "./ConnectStarknetkitModal" +import { DisconnectIcon } from "../icons/DisconnectIcon" const Connect = () => { const { isConnected } = useAccount() const { connectors } = useConnect() + const { disconnect } = useDisconnect({}) const [isClient, setIsClient] = useState(false) useEffect(() => { @@ -21,57 +22,59 @@ const Connect = () => { } return ( - - - - - - - {connectors.map((connector) => ( - - ))} - - ), - }, - ]} - /> - - - - - - - ), - }, - ]} - /> - + +
+
+ + +
+
+ + Starknet-react connectors + +
+ {connectors.map((connector) => { + const icon = + typeof connector.icon === "string" + ? connector.icon + : connector.icon.dark + const isSvg = icon?.startsWith(" + {isSvg ? ( +
+ ) : ( + {connector.name} + )} + + } + /> + ) + })} +
+
+
+ ) } diff --git a/src/components/connect/ConnectStarknetkitModal.tsx b/src/components/connect/ConnectStarknetkitModal.tsx index 30d572c..31ff465 100644 --- a/src/components/connect/ConnectStarknetkitModal.tsx +++ b/src/components/connect/ConnectStarknetkitModal.tsx @@ -11,13 +11,14 @@ const ConnectStarknetkitModal = () => { return ( diff --git a/src/components/connect/ConnectorButton.tsx b/src/components/connect/ConnectorButton.tsx index 911b4f3..b2434f6 100644 --- a/src/components/connect/ConnectorButton.tsx +++ b/src/components/connect/ConnectorButton.tsx @@ -1,8 +1,11 @@ import { Connector, useConnect } from "@starknet-react/core" -import { FC } from "react" +import { FC, ReactNode } from "react" import { Button } from "../ui/Button" -const ConnectorButton: FC<{ connector: Connector }> = ({ connector }) => { +const ConnectorButton: FC<{ connector: Connector; icon: ReactNode }> = ({ + connector, + icon, +}) => { const { connectAsync } = useConnect() if (!connector.available()) { return null @@ -10,13 +13,17 @@ const ConnectorButton: FC<{ connector: Connector }> = ({ connector }) => { return ( ) } diff --git a/src/components/icons/AvatarIcon.tsx b/src/components/icons/AvatarIcon.tsx new file mode 100644 index 0000000..781d8e1 --- /dev/null +++ b/src/components/icons/AvatarIcon.tsx @@ -0,0 +1,36 @@ +const AvatarIcon = () => ( + + + + + + + + + + + + + + + + +) + +export { AvatarIcon } diff --git a/src/components/icons/Chevron.tsx b/src/components/icons/Chevron.tsx new file mode 100644 index 0000000..0c50a0b --- /dev/null +++ b/src/components/icons/Chevron.tsx @@ -0,0 +1,65 @@ +const ChevronRight = () => ( + + + +) + +const ChevronLeft = () => ( + + + +) + +const ChevronUp = () => ( + + + +) + +const ChevronDown = () => ( + + + +) + +export { ChevronRight, ChevronLeft, ChevronUp, ChevronDown } diff --git a/src/components/icons/CopyIcon.tsx b/src/components/icons/CopyIcon.tsx new file mode 100644 index 0000000..b39e98f --- /dev/null +++ b/src/components/icons/CopyIcon.tsx @@ -0,0 +1,32 @@ +import { FC } from "react" + +const CopyIcon: FC<{ + copyValue?: string +}> = ({ copyValue }) => ( + navigator.clipboard.writeText(copyValue || "")} + > + + + +) + +export { CopyIcon } diff --git a/src/components/icons/DisconnectIcon.tsx b/src/components/icons/DisconnectIcon.tsx new file mode 100644 index 0000000..ad41cdf --- /dev/null +++ b/src/components/icons/DisconnectIcon.tsx @@ -0,0 +1,32 @@ +const DisconnectIcon = () => ( + + + + + +) + +export { DisconnectIcon } diff --git a/src/components/icons/IconStatusIcon.tsx b/src/components/icons/IconStatusIcon.tsx new file mode 100644 index 0000000..9a4997b --- /dev/null +++ b/src/components/icons/IconStatusIcon.tsx @@ -0,0 +1,38 @@ +const IconStatusIcon = () => { + return ( + + + + + + ) +} + +export { IconStatusIcon } diff --git a/src/components/icons/InfoIcon.tsx b/src/components/icons/InfoIcon.tsx new file mode 100644 index 0000000..12709f7 --- /dev/null +++ b/src/components/icons/InfoIcon.tsx @@ -0,0 +1,19 @@ +import { FC, SVGProps } from "react" + +const InfoIcon: FC> = ({ ...props }) => ( + + + +) + +export { InfoIcon } diff --git a/src/components/icons/LogoIcon.tsx b/src/components/icons/LogoIcon.tsx new file mode 100644 index 0000000..a6acf72 --- /dev/null +++ b/src/components/icons/LogoIcon.tsx @@ -0,0 +1,73 @@ +const LogoIcon = () => ( + + + + + + + + + + + + + + + + + +) + +export { LogoIcon } diff --git a/src/components/icons/WalletIcon.tsx b/src/components/icons/WalletIcon.tsx new file mode 100644 index 0000000..13d80bc --- /dev/null +++ b/src/components/icons/WalletIcon.tsx @@ -0,0 +1,33 @@ +const WalletIcon = () => ( + + + + + +) + +export { WalletIcon } diff --git a/src/components/sections/AccountStatus.tsx b/src/components/sections/AccountStatus.tsx index 8b726a5..9f547b2 100644 --- a/src/components/sections/AccountStatus.tsx +++ b/src/components/sections/AccountStatus.tsx @@ -1,3 +1,4 @@ +import { toHexChainid } from "@/helpers/chainId" import { useAccount, useBalance, @@ -6,19 +7,24 @@ import { useStarkProfile, } from "@starknet-react/core" import { FC } from "react" -import { constants, num } from "starknet" -import { Accordion } from "../ui/Accordion" -import { Flex } from "../ui/Flex" +import { constants } from "starknet" +import { CopyIcon } from "../icons/CopyIcon" -const Box: FC<{ +interface BoxProps { title: string value?: string -}> = ({ title, value }) => ( - - - {title}: {value || "-----"} + copy?: boolean + truncate?: boolean +} + +const Box: FC = ({ title, value, copy, truncate }) => ( +
+ {title} + + {value || "-"} + {value && copy && } - +
) const AccountStatus = () => { @@ -37,72 +43,43 @@ const AccountStatus = () => { address, }) - const hexChainId = - typeof chainId === "bigint" ? num.toHex(chainId ?? 0) : null + const hexChainId = toHexChainid(chainId) return ( - - - - - - - - - {balance ? ( - 7 - ? `${balance.formatted.slice(0, 5)} ETH` - : `${balance?.formatted} ETH` - } - /> - ) : ( - - )} - - - - - - ), - }, - ]} - /> -
- ), - }, - ]} + <> + + + + 7 + ? `${balance.formatted.slice(0, 7)} ETH` + : `${balance?.formatted} ETH` + : "-" + } + /> + + - + ) } diff --git a/src/components/sections/ERC20/AddToken.tsx b/src/components/sections/ERC20/AddToken.tsx index d91a2fc..07c2e17 100644 --- a/src/components/sections/ERC20/AddToken.tsx +++ b/src/components/sections/ERC20/AddToken.tsx @@ -1,7 +1,6 @@ -import { Accordion } from "@/components/ui/Accordion" import { Button } from "@/components/ui/Button" -import { Flex } from "@/components/ui/Flex" import { useAccount, useWalletRequest } from "@starknet-react/core" +import { SectionLayout } from "../SectionLayout" const AddToken = () => { const { account, address } = useAccount() @@ -25,31 +24,19 @@ const AddToken = () => { } return ( - - - - ), - }, - ]} - /> + +
+ +
+
) } diff --git a/src/components/sections/Network/AddNetwork.tsx b/src/components/sections/Network/AddNetwork.tsx index 01f9769..1b59973 100644 --- a/src/components/sections/Network/AddNetwork.tsx +++ b/src/components/sections/Network/AddNetwork.tsx @@ -1,5 +1,4 @@ import { Button } from "@/components/ui/Button" -import { Flex } from "@/components/ui/Flex" import { ETHTokenAddress } from "@/constants" import { useWalletRequest } from "@starknet-react/core" import { shortString } from "starknet" @@ -25,22 +24,17 @@ const AddNetwork = () => { }) return ( - +
- +
) } diff --git a/src/components/sections/Network/ChangeNetwork.tsx b/src/components/sections/Network/ChangeNetwork.tsx index 421678f..028a034 100644 --- a/src/components/sections/Network/ChangeNetwork.tsx +++ b/src/components/sections/Network/ChangeNetwork.tsx @@ -1,33 +1,32 @@ import { Button } from "@/components/ui/Button" -import { Flex } from "@/components/ui/Flex" -import { useWalletRequest } from "@starknet-react/core" +import { isMainnet, toHexChainid } from "@/helpers/chainId" +import { useAccount, useWalletRequest } from "@starknet-react/core" import { constants } from "starknet" const ChangeNetwork = () => { + const { chainId } = useAccount() + const walletRequest = useWalletRequest({ type: "wallet_switchStarknetChain", params: { - chainId: constants.StarknetChainId.SN_MAIN, + chainId: isMainnet(toHexChainid(chainId)) + ? constants.StarknetChainId.SN_SEPOLIA + : constants.StarknetChainId.SN_MAIN, }, }) return ( - +
- +
) } diff --git a/src/components/sections/Network/Network.tsx b/src/components/sections/Network/Network.tsx index 9fa334c..64c659f 100644 --- a/src/components/sections/Network/Network.tsx +++ b/src/components/sections/Network/Network.tsx @@ -1,8 +1,7 @@ -import { Flex } from "@/components/ui/Flex" +import { useAccount } from "@starknet-react/core" +import { SectionLayout } from "../SectionLayout" import { AddNetwork } from "./AddNetwork" import { ChangeNetwork } from "./ChangeNetwork" -import { Accordion } from "@/components/ui/Accordion" -import { useAccount } from "@starknet-react/core" const Network = () => { const { account, address } = useAccount() @@ -12,19 +11,12 @@ const Network = () => { } return ( - - - -
- ), - }, - ]} - /> + +
+ + +
+
) } diff --git a/src/components/sections/SectionButton.tsx b/src/components/sections/SectionButton.tsx new file mode 100644 index 0000000..5bdb90c --- /dev/null +++ b/src/components/sections/SectionButton.tsx @@ -0,0 +1,34 @@ +import { FC } from "react" +import { Button } from "../ui/Button" +import { Section } from "./types" + +interface SectionButtonProps { + disabled?: boolean + section: Section + selected: boolean + setSection: ( + value?: ((prevState?: Section | undefined) => Section) | undefined, + ) => void +} + +const SectionButton: FC = ({ + disabled, + section, + selected, + setSection, +}) => { + return ( + + ) +} + +export { SectionButton } diff --git a/src/components/sections/SectionLayout.tsx b/src/components/sections/SectionLayout.tsx new file mode 100644 index 0000000..45f787a --- /dev/null +++ b/src/components/sections/SectionLayout.tsx @@ -0,0 +1,27 @@ +import { FC, PropsWithChildren } from "react" +import { IconStatusIcon } from "../icons/IconStatusIcon" +import { InfoIcon } from "../icons/InfoIcon" + +interface SectionLayoutProps extends PropsWithChildren { + sectionTitle: string +} + +const SectionLayout: FC = ({ children, sectionTitle }) => { + return ( +
+
+ +

{sectionTitle}

+ +
+
{children}
+
+ ) +} + +export { SectionLayout } diff --git a/src/components/sections/SignMessage.tsx b/src/components/sections/SignMessage.tsx index bad4e59..00d6d01 100644 --- a/src/components/sections/SignMessage.tsx +++ b/src/components/sections/SignMessage.tsx @@ -1,19 +1,16 @@ -import { Flex } from "@/components/ui/Flex" +import { toHexChainid } from "@/helpers/chainId" import { useAccount, useSignTypedData } from "@starknet-react/core" import { useState } from "react" -import { constants, num, stark } from "starknet" +import { constants, stark } from "starknet" import { Button } from "../ui/Button" -import { Accordion } from "../ui/Accordion" +import { SectionLayout } from "./SectionLayout" const SignMessage = () => { const { account, address, chainId } = useAccount() const [shortText, setShortText] = useState("") const [lastSig, setLastSig] = useState([]) - const hexChainId = - typeof chainId === "bigint" - ? (num.toHex(chainId ?? 0) as constants.StarknetChainId) - : null + const hexChainId = toHexChainid(chainId) const { signTypedDataAsync } = useSignTypedData({ params: { @@ -54,141 +51,131 @@ const SignMessage = () => { } return ( - <> - +
+
{ + e.preventDefault() + handleSignSubmit() + }} + > +