diff --git a/package.json b/package.json index 36f4cda..2ba6fda 100644 --- a/package.json +++ b/package.json @@ -14,19 +14,20 @@ "lint": "eslint ." }, "dependencies": { + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "react": "^18.3.1", - "react-dom": "^18.3.1", - "styled-components": "^5.2.1" + "react-dom": "^18.3.1" }, "devDependencies": { "@eslint/js": "^9.17.0", + "@tailwindcss/vite": "^4.3.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.1.0", "@testing-library/user-event": "^14.5.2", "@types/node": "^22.10.5", "@types/react": "^18.3.18", "@types/react-dom": "^18.3.5", - "@types/styled-components": "^5.1.34", "@vitejs/plugin-react": "6.0.2", "@vitest/ui": "^4.1.7", "eslint": "^9.17.0", @@ -35,6 +36,7 @@ "eslint-plugin-react-refresh": "^0.4.16", "globals": "^17.6.0", "jsdom": "^29.1.1", + "tailwindcss": "^4.3.0", "typescript": "^5.7.2", "typescript-eslint": "^8.19.0", "vite": "8.0.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a68b793..a2e0413 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,19 +8,25 @@ importers: .: dependencies: + class-variance-authority: + specifier: ^0.7.1 + version: 0.7.1 + clsx: + specifier: ^2.1.1 + version: 2.1.1 react: specifier: ^18.3.1 version: 18.3.1 react-dom: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) - styled-components: - specifier: ^5.2.1 - version: 5.3.11(@babel/core@7.29.0)(react-dom@18.3.1(react@18.3.1))(react-is@17.0.2)(react@18.3.1) devDependencies: '@eslint/js': specifier: ^9.17.0 version: 9.39.4 + '@tailwindcss/vite': + specifier: ^4.3.0 + version: 4.3.0(vite@8.0.10(@types/node@22.19.19)(jiti@2.7.0)) '@testing-library/jest-dom': specifier: ^6.6.3 version: 6.9.1 @@ -39,45 +45,45 @@ importers: '@types/react-dom': specifier: ^18.3.5 version: 18.3.7(@types/react@18.3.29) - '@types/styled-components': - specifier: ^5.1.34 - version: 5.1.36 '@vitejs/plugin-react': specifier: 6.0.2 - version: 6.0.2(vite@8.0.10(@types/node@22.19.19)) + version: 6.0.2(vite@8.0.10(@types/node@22.19.19)(jiti@2.7.0)) '@vitest/ui': specifier: ^4.1.7 version: 4.1.7(vitest@4.1.7) eslint: specifier: ^9.17.0 - version: 9.39.4 + version: 9.39.4(jiti@2.7.0) eslint-plugin-react: specifier: ^7.37.3 - version: 7.37.5(eslint@9.39.4) + version: 7.37.5(eslint@9.39.4(jiti@2.7.0)) eslint-plugin-react-hooks: specifier: ^5.1.0 - version: 5.2.0(eslint@9.39.4) + version: 5.2.0(eslint@9.39.4(jiti@2.7.0)) eslint-plugin-react-refresh: specifier: ^0.4.16 - version: 0.4.26(eslint@9.39.4) + version: 0.4.26(eslint@9.39.4(jiti@2.7.0)) globals: specifier: ^17.6.0 version: 17.6.0 jsdom: specifier: ^29.1.1 version: 29.1.1 + tailwindcss: + specifier: ^4.3.0 + version: 4.3.0 typescript: specifier: ^5.7.2 version: 5.9.3 typescript-eslint: specifier: ^8.19.0 - version: 8.59.4(eslint@9.39.4)(typescript@5.9.3) + version: 8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) vite: specifier: 8.0.10 - version: 8.0.10(@types/node@22.19.19) + version: 8.0.10(@types/node@22.19.19)(jiti@2.7.0) vitest: specifier: ^4.1.7 - version: 4.1.7(@types/node@22.19.19)(@vitest/ui@4.1.7)(jsdom@29.1.1)(vite@8.0.10(@types/node@22.19.19)) + version: 4.1.7(@types/node@22.19.19)(@vitest/ui@4.1.7)(jsdom@29.1.1)(vite@8.0.10(@types/node@22.19.19)(jiti@2.7.0)) packages: @@ -103,87 +109,14 @@ packages: resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.29.3': - resolution: {integrity: sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.29.0': - resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.29.1': - resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-annotate-as-pure@7.27.3': - resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.28.6': - resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-globals@7.28.0': - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.28.6': - resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.28.6': - resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-plugin-utils@7.28.6': - resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.28.5': resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.27.1': - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.29.2': - resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.29.3': - resolution: {integrity: sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/plugin-syntax-jsx@7.28.6': - resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/runtime@7.29.2': resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} engines: {node: '>=6.9.0'} - '@babel/template@7.28.6': - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.29.0': - resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} - engines: {node: '>=6.9.0'} - '@bramus/specificity@2.4.2': resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} hasBin: true @@ -233,18 +166,6 @@ packages: '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} - '@emotion/is-prop-valid@1.4.0': - resolution: {integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==} - - '@emotion/memoize@0.9.0': - resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} - - '@emotion/stylis@0.8.5': - resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} - - '@emotion/unitless@0.7.5': - resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} - '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -444,6 +365,100 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@tailwindcss/node@4.3.0': + resolution: {integrity: sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==} + + '@tailwindcss/oxide-android-arm64@4.3.0': + resolution: {integrity: sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.3.0': + resolution: {integrity: sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.3.0': + resolution: {integrity: sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.3.0': + resolution: {integrity: sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0': + resolution: {integrity: sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.0': + resolution: {integrity: sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-arm64-musl@4.3.0': + resolution: {integrity: sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-linux-x64-gnu@4.3.0': + resolution: {integrity: sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-x64-musl@4.3.0': + resolution: {integrity: sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-wasm32-wasi@4.3.0': + resolution: {integrity: sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.0': + resolution: {integrity: sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.3.0': + resolution: {integrity: sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.3.0': + resolution: {integrity: sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==} + engines: {node: '>= 20'} + + '@tailwindcss/vite@4.3.0': + resolution: {integrity: sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -488,11 +503,6 @@ packages: '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - '@types/hoist-non-react-statics@3.3.7': - resolution: {integrity: sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==} - peerDependencies: - '@types/react': '*' - '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -510,9 +520,6 @@ packages: '@types/react@18.3.29': resolution: {integrity: sha512-ch0qJdr2JY0r04NXSprbK6TXOgnaJ1Tz23fm5W+z0/CBah6BSBc3n96h7K9GOtwh0HrilNWHIBzE1Ko4Dcw/Wg==} - '@types/styled-components@5.1.36': - resolution: {integrity: sha512-pGMRNY5G2rNDKEv2DOiFYa7Ft1r0jrhmgBwHhOMzPTgCjO76bCot0/4uEfqj7K0Jf1KdQmDtAuaDk9EAs9foSw==} - '@typescript-eslint/eslint-plugin@8.59.4': resolution: {integrity: sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -694,12 +701,6 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - babel-plugin-styled-components@2.3.0: - resolution: {integrity: sha512-nP/y6PbBqS/qtKROnJCgpGo8hYUzlBAVXN1QAjSBANL6vZiQXPQN7FYW/nUwoxY7nZhBEGm9T5tjL9gbzwulDw==} - peerDependencies: - '@babel/core': ^7.0.0 - styled-components: '>= 2' - balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -707,11 +708,6 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - baseline-browser-mapping@2.10.32: - resolution: {integrity: sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==} - engines: {node: '>=6.0.0'} - hasBin: true - bidi-js@1.0.3: resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} @@ -722,11 +718,6 @@ packages: resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} engines: {node: 18 || 20 || >=22} - browserslist@4.28.2: - resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -743,12 +734,6 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - camelize@1.0.1: - resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} - - caniuse-lite@1.0.30001793: - resolution: {integrity: sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==} - chai@6.2.2: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} @@ -757,6 +742,13 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + 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'} @@ -774,13 +766,6 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - css-color-keywords@1.0.0: - resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} - engines: {node: '>=4'} - - css-to-react-native@3.2.0: - resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} - css-tree@3.2.1: resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} @@ -852,8 +837,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - electron-to-chromium@1.5.361: - resolution: {integrity: sha512-Q6Hts7N9FnJc5LeGRINFvLhCI9xZmNtTDe5ZbcVezQz7cU4a8Aua3GH1b8J2XY8Al9PF+OCwYqhgsOOheMdvkA==} + enhanced-resolve@5.22.0: + resolution: {integrity: sha512-xYcDWrpELkFzz9SpZ3PlI6Eu6eD93Yf0WLDRxikGhWJ3MAir2SNZTIVCVZqZ/NUyx8AdMc2gT9C0gPiw18kG+A==} + engines: {node: '>=10.13.0'} entities@8.0.0: resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} @@ -894,10 +880,6 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -1031,10 +1013,6 @@ packages: resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} engines: {node: '>= 0.4'} - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -1067,14 +1045,13 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} - has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -1098,9 +1075,6 @@ packages: resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} engines: {node: '>= 0.4'} - hoist-non-react-statics@3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - html-encoding-sniffer@6.0.0: resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -1238,6 +1212,10 @@ packages: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1254,11 +1232,6 @@ packages: canvas: optional: true - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -1268,11 +1241,6 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -1373,9 +1341,6 @@ packages: resolution: {integrity: sha512-5YgH9UJd7wVb9hIouI2adWpgqrrICkt070Dnj8EUY1+B4B2P9eRLPAkAAo6NICA7CEhOIeBHl46u9zSNpNu7zA==} engines: {node: 20 || >=22} - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true @@ -1420,10 +1385,6 @@ packages: resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==} engines: {node: '>= 0.4'} - node-releases@2.0.46: - resolution: {integrity: sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==} - engines: {node: '>=18'} - object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -1503,9 +1464,6 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} - postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.5.15: resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} @@ -1610,9 +1568,6 @@ packages: resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} engines: {node: '>= 0.4'} - shallowequal@1.1.0: - resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -1685,18 +1640,6 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - styled-components@5.3.11: - resolution: {integrity: sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==} - engines: {node: '>=10'} - peerDependencies: - react: '>= 16.8.0' - react-dom: '>= 16.8.0' - react-is: '>= 16.8.0' - - supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -1708,6 +1651,13 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + tailwindcss@4.3.0: + resolution: {integrity: sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -1794,12 +1744,6 @@ packages: resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==} engines: {node: '>=20.18.1'} - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -1940,9 +1884,6 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -1977,113 +1918,10 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.29.3': {} - - '@babel/core@7.29.0': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helpers': 7.29.2 - '@babel/parser': 7.29.3 - '@babel/template': 7.28.6 - '@babel/traverse': 7.29.0(supports-color@5.5.0) - '@babel/types': 7.29.0 - '@jridgewell/remapping': 2.3.5 - convert-source-map: 2.0.0 - debug: 4.4.3(supports-color@5.5.0) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/generator@7.29.1': - dependencies: - '@babel/parser': 7.29.3 - '@babel/types': 7.29.0 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - - '@babel/helper-annotate-as-pure@7.27.3': - dependencies: - '@babel/types': 7.29.0 - - '@babel/helper-compilation-targets@7.28.6': - dependencies: - '@babel/compat-data': 7.29.3 - '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.2 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-globals@7.28.0': {} - - '@babel/helper-module-imports@7.28.6(supports-color@5.5.0)': - dependencies: - '@babel/traverse': 7.29.0(supports-color@5.5.0) - '@babel/types': 7.29.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6(supports-color@5.5.0) - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/helper-plugin-utils@7.28.6': {} - - '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.28.5': {} - '@babel/helper-validator-option@7.27.1': {} - - '@babel/helpers@7.29.2': - dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - - '@babel/parser@7.29.3': - dependencies: - '@babel/types': 7.29.0 - - '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/runtime@7.29.2': {} - '@babel/template@7.28.6': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.3 - '@babel/types': 7.29.0 - - '@babel/traverse@7.29.0(supports-color@5.5.0)': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.3 - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - debug: 4.4.3(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/types@7.29.0': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - '@bramus/specificity@2.4.2': dependencies: css-tree: 3.2.1 @@ -2128,19 +1966,9 @@ snapshots: tslib: 2.8.1 optional: true - '@emotion/is-prop-valid@1.4.0': + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.7.0))': dependencies: - '@emotion/memoize': 0.9.0 - - '@emotion/memoize@0.9.0': {} - - '@emotion/stylis@0.8.5': {} - - '@emotion/unitless@0.7.5': {} - - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4)': - dependencies: - eslint: 9.39.4 + eslint: 9.39.4(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -2148,7 +1976,7 @@ snapshots: '@eslint/config-array@0.21.2': dependencies: '@eslint/object-schema': 2.1.7 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3 minimatch: 3.1.5 transitivePeerDependencies: - supports-color @@ -2164,7 +1992,7 @@ snapshots: '@eslint/eslintrc@3.3.5': dependencies: ajv: 6.15.0 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3 espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 @@ -2287,6 +2115,74 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@tailwindcss/node@4.3.0': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.22.0 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.3.0 + + '@tailwindcss/oxide-android-arm64@4.3.0': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.3.0': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.3.0': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.3.0': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.0': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.3.0': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.3.0': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.3.0': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.3.0': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.0': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.3.0': + optional: true + + '@tailwindcss/oxide@4.3.0': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.3.0 + '@tailwindcss/oxide-darwin-arm64': 4.3.0 + '@tailwindcss/oxide-darwin-x64': 4.3.0 + '@tailwindcss/oxide-freebsd-x64': 4.3.0 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.0 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.0 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.0 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.0 + '@tailwindcss/oxide-linux-x64-musl': 4.3.0 + '@tailwindcss/oxide-wasm32-wasi': 4.3.0 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.0 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.0 + + '@tailwindcss/vite@4.3.0(vite@8.0.10(@types/node@22.19.19)(jiti@2.7.0))': + dependencies: + '@tailwindcss/node': 4.3.0 + '@tailwindcss/oxide': 4.3.0 + tailwindcss: 4.3.0 + vite: 8.0.10(@types/node@22.19.19)(jiti@2.7.0) + '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.29.0 @@ -2337,11 +2233,6 @@ snapshots: '@types/estree@1.0.9': {} - '@types/hoist-non-react-statics@3.3.7(@types/react@18.3.29)': - dependencies: - '@types/react': 18.3.29 - hoist-non-react-statics: 3.3.2 - '@types/json-schema@7.0.15': {} '@types/node@22.19.19': @@ -2359,21 +2250,15 @@ snapshots: '@types/prop-types': 15.7.15 csstype: 3.2.3 - '@types/styled-components@5.1.36': - dependencies: - '@types/hoist-non-react-statics': 3.3.7(@types/react@18.3.29) - '@types/react': 18.3.29 - csstype: 3.2.3 - - '@typescript-eslint/eslint-plugin@8.59.4(@typescript-eslint/parser@8.59.4(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.59.4(@typescript-eslint/parser@8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.59.4(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/parser': 8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.59.4 - '@typescript-eslint/type-utils': 8.59.4(eslint@9.39.4)(typescript@5.9.3) - '@typescript-eslint/utils': 8.59.4(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/type-utils': 8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/utils': 8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.59.4 - eslint: 9.39.4 + eslint: 9.39.4(jiti@2.7.0) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@5.9.3) @@ -2381,14 +2266,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.59.4(eslint@9.39.4)(typescript@5.9.3)': + '@typescript-eslint/parser@8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.59.4 '@typescript-eslint/types': 8.59.4 '@typescript-eslint/typescript-estree': 8.59.4(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.59.4 - debug: 4.4.3(supports-color@5.5.0) - eslint: 9.39.4 + debug: 4.4.3 + eslint: 9.39.4(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -2397,7 +2282,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.59.4(typescript@5.9.3) '@typescript-eslint/types': 8.59.4 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -2411,13 +2296,13 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.59.4(eslint@9.39.4)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.59.4 '@typescript-eslint/typescript-estree': 8.59.4(typescript@5.9.3) - '@typescript-eslint/utils': 8.59.4(eslint@9.39.4)(typescript@5.9.3) - debug: 4.4.3(supports-color@5.5.0) - eslint: 9.39.4 + '@typescript-eslint/utils': 8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.39.4(jiti@2.7.0) ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -2431,7 +2316,7 @@ snapshots: '@typescript-eslint/tsconfig-utils': 8.59.4(typescript@5.9.3) '@typescript-eslint/types': 8.59.4 '@typescript-eslint/visitor-keys': 8.59.4 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3 minimatch: 10.2.5 semver: 7.8.1 tinyglobby: 0.2.16 @@ -2440,13 +2325,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.59.4(eslint@9.39.4)(typescript@5.9.3)': + '@typescript-eslint/utils@8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) '@typescript-eslint/scope-manager': 8.59.4 '@typescript-eslint/types': 8.59.4 '@typescript-eslint/typescript-estree': 8.59.4(typescript@5.9.3) - eslint: 9.39.4 + eslint: 9.39.4(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -2456,10 +2341,10 @@ snapshots: '@typescript-eslint/types': 8.59.4 eslint-visitor-keys: 5.0.1 - '@vitejs/plugin-react@6.0.2(vite@8.0.10(@types/node@22.19.19))': + '@vitejs/plugin-react@6.0.2(vite@8.0.10(@types/node@22.19.19)(jiti@2.7.0))': dependencies: '@rolldown/pluginutils': 1.0.1 - vite: 8.0.10(@types/node@22.19.19) + vite: 8.0.10(@types/node@22.19.19)(jiti@2.7.0) '@vitest/expect@4.1.7': dependencies: @@ -2470,13 +2355,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.7(vite@8.0.10(@types/node@22.19.19))': + '@vitest/mocker@4.1.7(vite@8.0.10(@types/node@22.19.19)(jiti@2.7.0))': dependencies: '@vitest/spy': 4.1.7 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.10(@types/node@22.19.19) + vite: 8.0.10(@types/node@22.19.19)(jiti@2.7.0) '@vitest/pretty-format@4.1.7': dependencies: @@ -2505,7 +2390,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vitest: 4.1.7(@types/node@22.19.19)(@vitest/ui@4.1.7)(jsdom@29.1.1)(vite@8.0.10(@types/node@22.19.19)) + vitest: 4.1.7(@types/node@22.19.19)(@vitest/ui@4.1.7)(jsdom@29.1.1)(vite@8.0.10(@types/node@22.19.19)(jiti@2.7.0)) '@vitest/utils@4.1.7': dependencies: @@ -2607,23 +2492,10 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 - babel-plugin-styled-components@2.3.0(@babel/core@7.29.0)(styled-components@5.3.11(@babel/core@7.29.0)(react-dom@18.3.1(react@18.3.1))(react-is@17.0.2)(react@18.3.1))(supports-color@5.5.0): - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-module-imports': 7.28.6(supports-color@5.5.0) - '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) - picomatch: 4.0.4 - styled-components: 5.3.11(@babel/core@7.29.0)(react-dom@18.3.1(react@18.3.1))(react-is@17.0.2)(react@18.3.1) - transitivePeerDependencies: - - supports-color - balanced-match@1.0.2: {} balanced-match@4.0.4: {} - baseline-browser-mapping@2.10.32: {} - bidi-js@1.0.3: dependencies: require-from-string: 2.0.2 @@ -2637,14 +2509,6 @@ snapshots: dependencies: balanced-match: 4.0.4 - browserslist@4.28.2: - dependencies: - baseline-browser-mapping: 2.10.32 - caniuse-lite: 1.0.30001793 - electron-to-chromium: 1.5.361 - node-releases: 2.0.46 - update-browserslist-db: 1.2.3(browserslist@4.28.2) - call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -2664,10 +2528,6 @@ snapshots: callsites@3.1.0: {} - camelize@1.0.1: {} - - caniuse-lite@1.0.30001793: {} - chai@6.2.2: {} chalk@4.1.2: @@ -2675,6 +2535,12 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.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 @@ -2691,14 +2557,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - css-color-keywords@1.0.0: {} - - css-to-react-native@3.2.0: - dependencies: - camelize: 1.0.1 - css-color-keywords: 1.0.0 - postcss-value-parser: 4.2.0 - css-tree@3.2.1: dependencies: mdn-data: 2.27.1 @@ -2733,11 +2591,9 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 - debug@4.4.3(supports-color@5.5.0): + debug@4.4.3: dependencies: ms: 2.1.3 - optionalDependencies: - supports-color: 5.5.0 decimal.js@10.6.0: {} @@ -2773,7 +2629,10 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - electron-to-chromium@1.5.361: {} + enhanced-resolve@5.22.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 entities@8.0.0: {} @@ -2880,19 +2739,17 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - escalade@3.2.0: {} - escape-string-regexp@4.0.0: {} - eslint-plugin-react-hooks@5.2.0(eslint@9.39.4): + eslint-plugin-react-hooks@5.2.0(eslint@9.39.4(jiti@2.7.0)): dependencies: - eslint: 9.39.4 + eslint: 9.39.4(jiti@2.7.0) - eslint-plugin-react-refresh@0.4.26(eslint@9.39.4): + eslint-plugin-react-refresh@0.4.26(eslint@9.39.4(jiti@2.7.0)): dependencies: - eslint: 9.39.4 + eslint: 9.39.4(jiti@2.7.0) - eslint-plugin-react@7.37.5(eslint@9.39.4): + eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.7.0)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 @@ -2900,7 +2757,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.3.2 - eslint: 9.39.4 + eslint: 9.39.4(jiti@2.7.0) estraverse: 5.3.0 hasown: 2.0.3 jsx-ast-utils: 3.3.5 @@ -2925,9 +2782,9 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@9.39.4: + eslint@9.39.4(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.2 '@eslint/config-helpers': 0.4.2 @@ -2942,7 +2799,7 @@ snapshots: ajv: 6.15.0 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@5.5.0) + debug: 4.4.3 escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -2961,6 +2818,8 @@ snapshots: minimatch: 3.1.5 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 2.7.0 transitivePeerDependencies: - supports-color @@ -3038,8 +2897,6 @@ snapshots: generator-function@2.0.1: {} - gensync@1.0.0-beta.2: {} - get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -3079,9 +2936,9 @@ snapshots: gopd@1.2.0: {} - has-bigints@1.1.0: {} + graceful-fs@4.2.11: {} - has-flag@3.0.0: {} + has-bigints@1.1.0: {} has-flag@4.0.0: {} @@ -3103,10 +2960,6 @@ snapshots: dependencies: function-bind: 1.1.2 - hoist-non-react-statics@3.3.2: - dependencies: - react-is: 16.13.1 - html-encoding-sniffer@6.0.0: dependencies: '@exodus/bytes': 1.15.1 @@ -3253,6 +3106,8 @@ snapshots: has-symbols: 1.1.0 set-function-name: 2.0.2 + jiti@2.7.0: {} + js-tokens@4.0.0: {} js-yaml@4.1.1: @@ -3285,16 +3140,12 @@ snapshots: transitivePeerDependencies: - '@noble/hashes' - jsesc@3.1.0: {} - json-buffer@3.0.1: {} json-schema-traverse@0.4.1: {} json-stable-stringify-without-jsonify@1.0.1: {} - json5@2.2.3: {} - jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.9 @@ -3372,10 +3223,6 @@ snapshots: lru-cache@11.5.0: {} - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 - lz-string@1.5.0: {} magic-string@0.30.21: @@ -3411,8 +3258,6 @@ snapshots: object.entries: 1.1.9 semver: 6.3.1 - node-releases@2.0.46: {} - object-assign@4.1.1: {} object-inspect@1.13.4: {} @@ -3496,8 +3341,6 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-value-parser@4.2.0: {} - postcss@8.5.15: dependencies: nanoid: 3.3.12 @@ -3646,8 +3489,6 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.1.2 - shallowequal@1.1.0: {} - shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -3751,28 +3592,6 @@ snapshots: strip-json-comments@3.1.1: {} - styled-components@5.3.11(@babel/core@7.29.0)(react-dom@18.3.1(react@18.3.1))(react-is@17.0.2)(react@18.3.1): - dependencies: - '@babel/helper-module-imports': 7.28.6(supports-color@5.5.0) - '@babel/traverse': 7.29.0(supports-color@5.5.0) - '@emotion/is-prop-valid': 1.4.0 - '@emotion/stylis': 0.8.5 - '@emotion/unitless': 0.7.5 - babel-plugin-styled-components: 2.3.0(@babel/core@7.29.0)(styled-components@5.3.11(@babel/core@7.29.0)(react-dom@18.3.1(react@18.3.1))(react-is@17.0.2)(react@18.3.1))(supports-color@5.5.0) - css-to-react-native: 3.2.0 - hoist-non-react-statics: 3.3.2 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-is: 17.0.2 - shallowequal: 1.1.0 - supports-color: 5.5.0 - transitivePeerDependencies: - - '@babel/core' - - supports-color@5.5.0: - dependencies: - has-flag: 3.0.0 - supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -3781,6 +3600,10 @@ snapshots: symbol-tree@3.2.4: {} + tailwindcss@4.3.0: {} + + tapable@2.3.3: {} + tinybench@2.9.0: {} tinyexec@1.1.2: {} @@ -3852,13 +3675,13 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.59.4(eslint@9.39.4)(typescript@5.9.3): + typescript-eslint@8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.59.4(@typescript-eslint/parser@8.59.4(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(typescript@5.9.3) - '@typescript-eslint/parser': 8.59.4(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.59.4(@typescript-eslint/parser@8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/parser': 8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.59.4(typescript@5.9.3) - '@typescript-eslint/utils': 8.59.4(eslint@9.39.4)(typescript@5.9.3) - eslint: 9.39.4 + '@typescript-eslint/utils': 8.59.4(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + eslint: 9.39.4(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -3876,17 +3699,11 @@ snapshots: undici@7.25.0: {} - update-browserslist-db@1.2.3(browserslist@4.28.2): - dependencies: - browserslist: 4.28.2 - escalade: 3.2.0 - picocolors: 1.1.1 - uri-js@4.4.1: dependencies: punycode: 2.3.1 - vite@8.0.10(@types/node@22.19.19): + vite@8.0.10(@types/node@22.19.19)(jiti@2.7.0): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 @@ -3896,11 +3713,12 @@ snapshots: optionalDependencies: '@types/node': 22.19.19 fsevents: 2.3.3 + jiti: 2.7.0 - vitest@4.1.7(@types/node@22.19.19)(@vitest/ui@4.1.7)(jsdom@29.1.1)(vite@8.0.10(@types/node@22.19.19)): + vitest@4.1.7(@types/node@22.19.19)(@vitest/ui@4.1.7)(jsdom@29.1.1)(vite@8.0.10(@types/node@22.19.19)(jiti@2.7.0)): dependencies: '@vitest/expect': 4.1.7 - '@vitest/mocker': 4.1.7(vite@8.0.10(@types/node@22.19.19)) + '@vitest/mocker': 4.1.7(vite@8.0.10(@types/node@22.19.19)(jiti@2.7.0)) '@vitest/pretty-format': 4.1.7 '@vitest/runner': 4.1.7 '@vitest/snapshot': 4.1.7 @@ -3917,7 +3735,7 @@ snapshots: tinyexec: 1.1.2 tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vite: 8.0.10(@types/node@22.19.19) + vite: 8.0.10(@types/node@22.19.19)(jiti@2.7.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.19.19 @@ -3998,6 +3816,4 @@ snapshots: xmlchars@2.2.0: {} - yallist@3.1.1: {} - yocto-queue@0.1.0: {} diff --git a/src/App.tsx b/src/App.tsx index 03f1250..59812f9 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,29 +1,21 @@ -import React from "react"; -import styled from "styled-components"; - import { AppGrid, AppForm, AppHeader } from "./components"; -import { Wrapper } from "./container/wrapper"; import { GridProvider } from "./context/gridContext"; import { FormProvider } from "./context/formContext"; -const StylesApp = styled.div` - margin: 5vmin 5vmin 0; -`; - function App() { return ( - +
- +
- - +
+
); } diff --git a/src/components/CLAUDE.md b/src/components/CLAUDE.md index 4529f8a..1d8b331 100644 --- a/src/components/CLAUDE.md +++ b/src/components/CLAUDE.md @@ -4,11 +4,7 @@ Guidance for Claude Code when working in `src/components/`. ## Layout -Each component lives in its own folder with: -- `index.tsx` — default-exported React function component -- `styles.ts` (or legacy `styles.js`) — `styled-components/macro` styled elements - -A few files (e.g. `form/styles.js`) are still JavaScript; the repo is mid-migration to TypeScript. New styles files must be `.ts`. +Each component lives in its own folder with an `index.tsx` (default-exported React function component). Styling is inline via Tailwind CSS v4 classes on the JSX — no separate `styles.*` files. ## Exports @@ -16,8 +12,9 @@ A few files (e.g. `form/styles.js`) are still JavaScript; the repo is mid-migrat ## Styling -- Use `styled-components/macro` (not `styled-components`) so generated class names are readable. -- Styled elements that take dynamic props must have a typed prop interface in `styles.ts` (see `grid/styles.ts` for the pattern: a `GapType` base extended per element). +- Use Tailwind utility classes on JSX. Theme tokens (colors, fonts, the `tablet` breakpoint) live in `src/index.css` under `@theme`. +- Shared form-control primitives (`Button`, `Input`, `Label`, `Fieldset`) live in `src/components/ui/`. `Button` exposes a `variant` prop (`"primary" | "reset"`, default `"primary"`) via `class-variance-authority`. All four accept an extra `className` that is merged with `clsx`. Reuse these rather than re-deriving the styles on raw ` - + +

Your Grid Code

@@ -102,9 +86,12 @@ export default function AppForm() {
- setExplainModalStatus(true)}> +

setExplainModalStatus(true)} + > What does this project do? - +

- + ); } diff --git a/src/components/form/styles.js b/src/components/form/styles.js deleted file mode 100644 index e69de29..0000000 diff --git a/src/components/grid/index.tsx b/src/components/grid/index.tsx index 77f87f3..186dd18 100644 --- a/src/components/grid/index.tsx +++ b/src/components/grid/index.tsx @@ -1,18 +1,9 @@ -import React, { useContext, useState, useEffect, FocusEvent } from "react"; -import { - AppGridMain, - AppGridColumnSizeSelector, - AppGridRowSizeSelector, - Grid, - GridChildren, - GridChildrenArea, - StyledError, - AppGridContainer, -} from "./styles"; +import { useContext, useState, useEffect, FocusEvent } from "react"; import validator from "../../utils/validatator"; import GridContext from "../../context/gridContext"; import FormContext from "../../context/formContext"; +import { Input } from "../ui"; type ChildType = { erow: number; @@ -26,6 +17,18 @@ export type ErrorType = { row: number[]; }; +const BOX_BG_SVG = + "url(\"data:image/svg+xml,%3Csvg width='8' height='8' viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%239C92AC' fill-opacity='0.4' fill-rule='evenodd'%3E%3Cpath d='M5 0h1L0 6V5zM6 5v1H5z'/%3E%3C/g%3E%3C/svg%3E\")"; + +const CHILD_MAX = 20; +const CHILD_COLOR_STEP = 300 / CHILD_MAX; + +function childBackground(index0: number) { + const idx = index0 + 1; + const hue = (idx - 15) * (CHILD_COLOR_STEP * 1.5); + return `hsla(${hue}, 80%, 30%, 0.7)`; +} + export default function AppGrid() { let { rowGap, columnGap, columns } = useContext(FormContext); let { @@ -113,71 +116,100 @@ export default function AppGrid() { } }, [child]); + const gapStyle = { + columnGap: `${columnGap}px`, + rowGap: `${rowGap}px`, + }; + return ( - - 8} +
+
8 ? "w-full" : ""}`} + style={{ + gridTemplateColumns: columnTemplate, + gridTemplateRows: "50px", + ...gapStyle, + }} > {colArr.map((col, index) => ( -
- + {errors.col.indexOf(index) !== -1 ? ( - Must use real CSS unit. +
+ Must use real CSS unit. +
) : null}
))} - - +
{rowArr.map((row, index) => ( -
- +
))} - - - +
+
- {divs.map((i, idx) => ( + {divs.map((_i, idx) => (
placeChild(idx + 1, "e")} onMouseDown={() => placeChild(idx + 1, "s")} - className={`box${idx}`} + className={`box${idx} border border-dotted border-white transition-all duration-200 cursor-move relative z-[1000] opacity-50`} + style={{ backgroundImage: BOX_BG_SVG }} key={idx} >
))} - - +
{childArea.map((i, idx) => ( - - - +
+ +
))} - - - +
+
+
); } diff --git a/src/components/grid/styles.ts b/src/components/grid/styles.ts deleted file mode 100644 index 6889ce8..0000000 --- a/src/components/grid/styles.ts +++ /dev/null @@ -1,178 +0,0 @@ -import styled, { css } from "styled-components"; - -type GapType = { - columnGap: number; - rowGap: number; -}; - -type ColumnSizeSelectorType = GapType & { - widthFull: boolean; - colTemplate: string; -}; - -type RowSizeSelectorType = GapType & { - rowTemplate: string; -}; - -type GridType = GapType & { - rowTemplate: string; - colTemplate: string; -}; - -function generateGridChildStyle(max: number) { - let color = 300 / max, - divs = Array(max).fill(0); - return divs - .map((_, index) => { - let idx = index + 1; - return `div[class*="child"]:nth-child(${idx}){ - background: hsla(${(idx - 15) * (color * 1.5)}, 80%, 30%, 0.7); - border: 1px solid #ddd; - }`; - }) - .join(""); -} - -export const AppGridMain = styled.main` - width: calc(70vw - 50px); - height: calc(70vh - 50px); - margin: 15px 0 0 75px; - @media screen and (max-width: 700px) { - width: calc(80vw - 50px); - height: calc(40vh - 50px); - } -`; - -export const AppGridContainer = styled.div` - border: 1px solid #08ffbd; - width: 100%; - height: 100%; - z-index: 0; - position: relative; - background: #131321; /* Old browsers */ - background: -moz-linear-gradient( - top, - #131321 0%, - #1f1c2c 100% - ); /* FF3.6-15 */ - background: -webkit-linear-gradient( - top, - #131321 0%, - #1f1c2c 100% - ); /* Chrome10-25,Safari5.1-6 */ - background: linear-gradient( - to bottom, - #131321 0%, - #1f1c2c 100% - ); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#131321', endColorstr='#1f1c2c',GradientType=0 ); /* IE6-9 */ - box-shadow: 0 2px 20px 0 #000; -`; - -export const AppGridColumnSizeSelector = styled.section` - display: grid; - grid-template-columns: ${({ colTemplate }) => colTemplate}; - grid-template-rows: 50px; - column-gap: ${({ columnGap }) => `${columnGap}px`}; - row-gap: ${({ rowGap }) => `${rowGap}px`}; - div { - text-align: center; - position: relative; - } - ${({ widthFull }) => - widthFull && - css` - width: 100%; - `} -`; - -export const AppGridRowSizeSelector = styled.section` - margin-left: -70px; - float: left; - height: 100%; - display: grid; - grid-template-columns: 50px; - grid-template-rows: ${({ rowTemplate }) => rowTemplate}; - column-gap: ${({ columnGap }) => `${columnGap}px`}; - row-gap: ${({ rowGap }) => `${rowGap}px`}; - div { - align-self: center; - text-align: center; - position: relative; - } -`; - -const GridStyles = styled.section` - width: 100%; - height: 100%; - position: absolute; - display: grid; - grid-auto-flow: row dense; -`; - -export const Grid = styled(GridStyles)` - grid-template-columns: ${({ colTemplate }) => colTemplate}; - grid-template-rows: ${({ rowTemplate }) => rowTemplate}; - column-gap: ${({ columnGap }) => `${columnGap}px`}; - row-gap: ${({ rowGap }) => `${rowGap}px`}; - - div[class*="box"] { - background-image: url("data:image/svg+xml,%3Csvg width='8' height='8' viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%239C92AC' fill-opacity='0.4' fill-rule='evenodd'%3E%3Cpath d='M5 0h1L0 6V5zM6 5v1H5z'/%3E%3C/g%3E%3C/svg%3E"); - border: 1px dotted white; - transition: 0.2s all ease; - cursor: move; - position: relative; - z-index: 1000; - opacity: 0.5; - } - p { - padding: 0 10px; - } -`; - -export const GridChildrenArea = styled(GridStyles)` - ${generateGridChildStyle(20)} - counter-reset: step; - div { - counter-increment: step; - position: relative; - &:before { - position: absolute; - content: ".div" counter(step); - display: block; - padding: 0 5px; - text-align: center; - color: white; - } - button { - position: absolute; - right: 0; - padding: 0 5px; - margin: 0; - color: white; - background-color: transparent; - border: none; - z-index: 99999; - } - } - grid-template-columns: ${({ colTemplate }) => colTemplate}; - grid-template-rows: ${({ rowTemplate }) => rowTemplate}; - column-gap: ${({ columnGap }) => `${columnGap}px`}; - row-gap: ${({ rowGap }) => `${rowGap}px`}; -`; - -export const GridChildren = styled.div<{ childArea: string }>` - grid-area: ${({ childArea }) => childArea}; -`; - -export const StyledError = styled.div` - position: absolute; - bottom: -5px; - border-radius: 4px; - padding: 8px 12px; - z-index: 1; - font-weight: bold; - width: 150px; - min-height: 50px; - background: #6d1a39; -`; diff --git a/src/components/header/index.tsx b/src/components/header/index.tsx index d2a8eca..449b4ed 100644 --- a/src/components/header/index.tsx +++ b/src/components/header/index.tsx @@ -1,37 +1,21 @@ -import styled from "styled-components"; - -const StylesNav = styled.nav` - font-size: 40px; - font-weight: 700; - margin-bottom: 40px; - text-shadow: 0px 2px 5px #000; - text-align: center; -`; - -const StylesLogo = styled.svg` - vertical-align: middle; - margin-top: -3px; - .logo { - fill: var(--teal); - } -`; export default function AppHeader() { return ( - - + - + - + CSS Grid Generator - + ); } diff --git a/src/components/modal-dialog/index.tsx b/src/components/modal-dialog/index.tsx index 1764b53..ba7b109 100644 --- a/src/components/modal-dialog/index.tsx +++ b/src/components/modal-dialog/index.tsx @@ -1,71 +1,10 @@ -import React, { +import { useEffect, useCallback, ReactNode, PropsWithChildren, } from "react"; -import styled from "styled-components"; - -/* - modal styled components - start -*/ -const StyledModalMask = styled.div` - position: fixed; - z-index: 100; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.7); - display: grid; - grid-template: 1fr auto 1fr / 1fr auto 1fr; - overflow: auto; - transition: opacity 0.25s ease; -`; - -const StyledModalWrapper = styled.div` - grid-area: 2 / 2 / 2 / 2; -`; - -const StyledModalContainer = styled.div` - position: relative; - width: 80vw; - max-width: 700px; - padding: 0px 50px 60px; - background-color: #192d38; - border-radius: 5px; - box-shadow: 0 2px 20px rgba(0, 0, 0, 0.8); - transition: all 0.3s ease; - border: 1px solid black; - - @media screen and (max-width: 700px) { - padding: 0px 20px 20px; - width: calc(100% - 40px); - } -`; - -const StyledModalButton = styled.button` - margin: 40px auto; - display: table; - - @media screen and (max-width: 700px) { - margin: 20px auto 0; - } -`; - -const StyledModalHeader = styled.header` - font-size: 1.5em; - text-align: center; -`; -const StyledModalBody = styled.section` - margin: 20px 0; -`; - -/* - modal styled components - end -*/ +import { Button } from "../ui"; type AppModalType = { modalHandler: (val: boolean) => void; @@ -93,25 +32,39 @@ const AppModal = function ({ if (!modalStatus) return null; return ( - - - +
+
+
{children} - modalHandler(false)}> + +
+
+
); }; AppModal.Header = function ({ children }: { children: ReactNode }) { - return {children}; + return ( +
+ {children} +
+ ); }; AppModal.Section = function ({ children }: { children: ReactNode }) { - return {children}; + return ( +
+ {children} +
+ ); }; export default AppModal; diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..089149e --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,24 @@ +import { ComponentPropsWithoutRef } from "react"; +import { cva, type VariantProps } from "class-variance-authority"; +import clsx from "clsx"; + +const button = cva( + "px-[30px] py-[4px] pb-[5px] rounded-full text-base mt-5 cursor-pointer transition-all duration-[0.35s] bg-transparent border font-sans", + { + variants: { + variant: { + primary: "text-teal border-teal hover:bg-teal hover:text-black", + reset: + "text-grey border-grey hover:bg-grey hover:text-black max-tablet:ml-5", + }, + }, + defaultVariants: { variant: "primary" }, + } +); + +type ButtonProps = ComponentPropsWithoutRef<"button"> & + VariantProps; + +export function Button({ variant, className, ...rest }: ButtonProps) { + return
{showHtml ? (

< - div - class="parent"> + div + class="parent">
{childArea.length > 0 ? ( - {childArea.map((area, i) => ( - - - <div - + {childArea.map((_area, i) => ( + + + <div +  class="div{i + 1}" - - ></div> - + + ></div> +
))} @@ -75,38 +91,38 @@ export default function AppCodeContainer() {
)} - </div> + </div>

) : ( <>

- .parent + .parent {"{"}
- - display: - grid; - + + display: + grid; +
- - grid-template-columns: - {columnTemplate}; - + + grid-template-columns: + {columnTemplate}; +
- - grid-template-rows: - {rowTemplate}; - + + grid-template-rows: + {rowTemplate}; +
- - grid-column-gap: - {columnGap}px; - + + grid-column-gap: + {columnGap}px; +
- - grid-row-gap: - {rowGap}px; - + + grid-row-gap: + {rowGap}px; +
{"}"}

@@ -115,10 +131,10 @@ export default function AppCodeContainer() { {childArea.map((area, i) => ( - .div{i + 1} + .div{i + 1} {"{"} - grid-area: - {area} + grid-area: + {area} {"}"}
@@ -129,7 +145,7 @@ export default function AppCodeContainer() { )}
- + ); } diff --git a/src/container/wrapper.ts b/src/container/wrapper.ts deleted file mode 100644 index b1f1889..0000000 --- a/src/container/wrapper.ts +++ /dev/null @@ -1,8 +0,0 @@ -import styled from "styled-components"; - -export const Wrapper = styled.section` - display: flex; - @media screen and (max-width: 700px) { - flex-direction: column; - } -`; diff --git a/src/global-styles.ts b/src/global-styles.ts deleted file mode 100644 index 86fd6e8..0000000 --- a/src/global-styles.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { createGlobalStyle } from "styled-components"; - -export const GlobalStyles = createGlobalStyle` - html{ - --grey: #aaaaaa; - --teal: #08ffbd; - --gray: var(--grey, #aaaaaa); - } - - * { - box-sizing: border-box; - } - - *, - *::before, - *::after { - box-sizing: inherit; - } - - body { - width: 100%; - height: 90vh; - padding: 0; - margin: 0; - background: #192d38; /* Old browsers */ - background: -moz-radial-gradient( - center, - ellipse cover, - #192d38 0%, - #211f2f 100% - ); /* FF3.6-15 */ - background: -webkit-radial-gradient( - center, - ellipse cover, - #192d38 0%, - #211f2f 100% - ); /* Chrome10-25,Safari5.1-6 */ - background: radial-gradient( - ellipse at center, - #192d38 0%, - #211f2f 100% - ); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#192d38', endColorstr='#211f2f',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */ - font-family: "Mukta Mahee", Helvetica, Arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - color: white; - font-weight: 300; - } - - input, - label, - button { - font-family: "Mukta Mahee", Helvetica, Arial, sans-serif; - } - - label { - padding-right: 18px; - display: inline-block; - width: 150px; - - .label-extra-info { - opacity: .7; - } - } - - input { - font-size: 17px; - background: #211f2f; - color: white; - width: 50px; - padding: 0.3ch 5px; - max-height: 40px; - border: 1px solid #666; - } - - fieldset { - margin-bottom: 20px; - border: none; - margin: 0; - padding: 5px 0; - } - - button { - background: transparent; - color: var(--teal); - padding: 4px 30px 5px; - border-radius: 1000px; - border: 1px solid var(--teal); - font-size: 16px; - margin: 20px 0 0; - cursor: pointer; - transition: 0.35s all; - - &:hover { - background: var(--teal); - color: black; - } - } - - [type="reset"] { - color: var(--grey); - border: 1px solid var(--grey); - - &:hover { - background: var(--grey); - color: black; - } - @media screen and (max-width:700px){ - margin-left: 20px; - } - } - -`; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..e0cf205 --- /dev/null +++ b/src/index.css @@ -0,0 +1,83 @@ +@import "tailwindcss"; + +@theme { + --color-teal: #08ffbd; + --color-grey: #aaaaaa; + --color-bg-start: #192d38; + --color-bg-end: #211f2f; + --color-panel-start: #131321; + --color-panel-end: #1f1c2c; + --color-input-bg: #211f2f; + --color-input-border: #666666; + --color-error-bg: #6d1a39; + --color-code-name: #ffea18; + --color-code-props: #f8a384; + --color-code-key: #6af2d7; + --color-accent-yellow: #ffd908; + --color-accent-orange: #fb7826; + --color-wat: #a8c9cc; + --color-copy-btn: #0f8a8ab3; + + --font-sans: "Mukta Mahee", Helvetica, Arial, sans-serif; + --font-cursive: "Caveat", cursive; + --font-mono: "Roboto Mono", Courier, monospace; + + --breakpoint-tablet: 700px; +} + +html { + --grey: #aaaaaa; + --teal: #08ffbd; + --gray: var(--grey, #aaaaaa); +} + +* { + box-sizing: border-box; +} + +*, +*::before, +*::after { + box-sizing: inherit; +} + +body { + width: 100%; + height: 90vh; + padding: 0; + margin: 0; + background: radial-gradient(ellipse at center, #192d38 0%, #211f2f 100%); + font-family: var(--font-sans); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: white; + font-weight: 300; +} + +strong { + color: var(--color-accent-yellow); +} + +a, +a:visited, +a:active { + color: var(--color-teal); + text-decoration: none; +} + +.grid-children-area { + counter-reset: step; +} + +.grid-child { + counter-increment: step; +} + +.grid-child::before { + position: absolute; + content: ".div" counter(step); + display: block; + padding: 0 5px; + text-align: center; + color: white; +} diff --git a/src/index.tsx b/src/index.tsx index e32341c..2a4918a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,13 +1,12 @@ import { createRoot } from "react-dom/client"; import { StrictMode } from "react"; +import "./index.css"; import App from "./App"; -import { GlobalStyles } from "./global-styles"; const container = document.getElementById("root"); if (!container) throw new Error("Root container missing"); createRoot(container).render( - ); diff --git a/vite.config.ts b/vite.config.ts index adfa0c8..a9c4d8f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,8 +1,9 @@ import { defineConfig } from "vitest/config"; import react from "@vitejs/plugin-react"; +import tailwindcss from "@tailwindcss/vite"; export default defineConfig({ - plugins: [react()], + plugins: [react(), tailwindcss()], server: { port: 5173, },