From 7202a24bcf1a9aa02e9d5f5e419ff44e7d7d99a4 Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Thu, 5 Feb 2026 17:36:08 +0800 Subject: [PATCH] chore: migrate to eslint-better-tailwind (#31969) --- .github/workflows/autofix.yml | 23 - .../components/base/effect/index.stories.tsx | 5 +- .../website-crawl/base/error-message.tsx | 1 - web/docs/lint.md | 5 + web/eslint-suppressions.json | 700 +++++++++++++++++- web/eslint.config.mjs | 44 +- web/package.json | 14 +- web/pnpm-lock.yaml | 359 +++++---- web/utils/classnames.spec.ts | 157 ---- 9 files changed, 941 insertions(+), 367 deletions(-) delete mode 100644 web/utils/classnames.spec.ts diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index 4a8c61e7d2..4571fd1cd1 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -79,29 +79,6 @@ jobs: find . -name "*.py" -type f -exec sed -i.bak -E 's/"([^"]+)" \| None/Optional["\1"]/g; s/'"'"'([^'"'"']+)'"'"' \| None/Optional['"'"'\1'"'"']/g' {} \; find . -name "*.py.bak" -type f -delete - - name: Install pnpm - uses: pnpm/action-setup@v4 - with: - package_json_file: web/package.json - run_install: false - - - name: Setup Node.js - uses: actions/setup-node@v6 - with: - node-version: 24 - cache: pnpm - cache-dependency-path: ./web/pnpm-lock.yaml - - - name: Install web dependencies - run: | - cd web - pnpm install --frozen-lockfile - - - name: ESLint autofix - run: | - cd web - pnpm lint:fix || true - # mdformat breaks YAML front matter in markdown files. Add --exclude for directories containing YAML front matter. - name: mdformat run: | diff --git a/web/app/components/base/effect/index.stories.tsx b/web/app/components/base/effect/index.stories.tsx index 36a0e668cf..8452e9aefe 100644 --- a/web/app/components/base/effect/index.stories.tsx +++ b/web/app/components/base/effect/index.stories.tsx @@ -1,4 +1,3 @@ -/* eslint-disable tailwindcss/classnames-order */ import type { Meta, StoryObj } from '@storybook/nextjs-vite' import Effect from '.' @@ -29,8 +28,8 @@ type Story = StoryObj export const Playground: Story = { render: () => (
- - + +
Accent glow
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/error-message.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/error-message.tsx index f0a1fb64a9..9bc97d9970 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/error-message.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/error-message.tsx @@ -14,7 +14,6 @@ const ErrorMessage = ({ errorMsg, }: ErrorMessageProps) => { return ( - // eslint-disable-next-line tailwindcss/migration-from-tailwind-2
=16.0.0} - '@eslint-react/ast@2.8.1': - resolution: {integrity: sha512-4D442lxeFvvd9PMvBbA621rfz/Ne8Kod8RW0/FLKO0vx+IOxm74pP6be1uU56rqL9TvoIHxjclBjfgXplEF+Yw==} + '@eslint-react/ast@2.9.4': + resolution: {integrity: sha512-WI9iq5ePTlcWo0xhSs4wxLUC6u4QuBmQkKeSiXexkEO8C2p8QE7ECNIXhRVkYs3p3AKH5xTez9V8C/CBIGxeXA==} engines: {node: '>=20.19.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@eslint-react/core@2.8.1': - resolution: {integrity: sha512-zF73p8blyuX+zrfgyTtpKesichYzK+G54TEjFWtzagWIbnqQjtVscebL/eGep72oWzAOd5B04ACBvJ2hW4fp5g==} + '@eslint-react/core@2.9.4': + resolution: {integrity: sha512-Ob+Dip1vyR9ch9XL7LUAsGXc0UUf9Kuzn9BEiwOLT7l+cF91ieKeCvIzNPp0LmTuanPfQweJ9iDT9i295SqBZA==} engines: {node: '>=20.19.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@eslint-react/eff@2.8.1': - resolution: {integrity: sha512-ZASOs8oTZJSiu1giue7V87GEKQvlKLfGfLppal6Rl+aKnfIEz+vartmjpH12pkFQZ9ESRyHzYbU533S6pEDoNg==} + '@eslint-react/eff@2.9.4': + resolution: {integrity: sha512-7AOmozmfa0HgXY9O+J+iX3ciZfViz+W+jhRe2y0YqqkDR7PwV2huzhk/Bxq6sRzzf2uFHqoh/AQNZUhRJ3A05A==} engines: {node: '>=20.19.0'} - '@eslint-react/eslint-plugin@2.8.1': - resolution: {integrity: sha512-ob+SSDnTPnA5dhiWWJLfyHRLEzWnjilCsohgo5s9PPKF5b5bjxG+c/rwqhQwT3M9Ey83mGNdkrLzt00SOfr4pw==} + '@eslint-react/eslint-plugin@2.9.4': + resolution: {integrity: sha512-B1LOEUBuT4L7EmY3E9F7+K8Jdr9nAzx66USz4uWEtg8ZMn82E2O5TzOBPw6eeL0O9BoyLBoslZotXNQVazR2dA==} engines: {node: '>=20.19.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@eslint-react/shared@2.8.1': - resolution: {integrity: sha512-NDmJBiMiPDXR6qeZzYOtiILHxWjYwBHxquQ/bMQkWcWK+1qF5LeD8UTRcWtBpZoMPi3sNBWwR3k2Sc5HWZpJ7g==} + '@eslint-react/shared@2.9.4': + resolution: {integrity: sha512-PU7C4JzDZ6OffAWD+HwJdvzGSho25UPYJRyb4wZ/pDaI8QPTDj8AtKWKK69SEOQl2ic89ht1upjQX+jrXhN15w==} engines: {node: '>=20.19.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@eslint-react/var@2.8.1': - resolution: {integrity: sha512-iHIdEBz6kgW4dEFdhEjpy9SEQ6+d4RYg+WBzHg5J5ktT2xSQFi77Dq6Wtemik6QvvAPnYLRseQxgW+m+1rQlfA==} + '@eslint-react/var@2.9.4': + resolution: {integrity: sha512-Qiih6hT+D2vZmCbAGUooReKlqXjtb/g3SzYj2zNlci6YcWxsQB/pqhR0ayU2AOdW6U9YdeCCfPIwBBQ4AEpyBA==} engines: {node: '>=20.19.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -1208,6 +1208,10 @@ packages: resolution: {integrity: sha512-r18fEAj9uCk+VjzGt2thsbOmychS+4kxI14spVNibUO2vqKX7obOG+ymZljAwuPZl+S3clPGwCwTDtrdqTiY6Q==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@eslint/css-tree@3.6.8': + resolution: {integrity: sha512-s0f40zY7dlMp8i0Jf0u6l/aSswS0WRAgkhgETgiCJRcxIWb4S/Sp9uScKHWbkM3BnoFLbJbmOYk5AZUDFVxaLA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + '@eslint/eslintrc@3.3.3': resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2867,10 +2871,14 @@ packages: peerDependencies: solid-js: 1.9.11 - '@tanstack/eslint-plugin-query@5.91.3': - resolution: {integrity: sha512-5GMGZMYFK9dOvjpdedjJs4hU40EdPuO2AjzObQzP7eOSsikunCfrXaU3oNGXSsvoU9ve1Z1xQZZuDyPi0C1M7Q==} + '@tanstack/eslint-plugin-query@5.91.4': + resolution: {integrity: sha512-8a+GAeR7oxJ5laNyYBQ6miPK09Hi18o5Oie/jx8zioXODv/AUFLZQecKabPdpQSLmuDXEBPKFh+W5DKbWlahjQ==} peerDependencies: eslint: ^8.57.0 || ^9.0.0 + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true '@tanstack/form-core@1.24.3': resolution: {integrity: sha512-e+HzSD49NWr4aIqJWtPPzmi+/phBJAP3nSPN8dvxwmJWqAxuB/cH138EcmCFf3+oA7j3BXvwvTY0I+8UweGPjQ==} @@ -3378,6 +3386,11 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@valibot/to-json-schema@1.5.0': + resolution: {integrity: sha512-GE7DmSr1C2UCWPiV0upRH6mv0cCPsqYGs819fb6srCS1tWhyXrkGGe+zxUiwzn/L1BOfADH4sNjY/YHCuP8phQ==} + peerDependencies: + valibot: ^1.2.0 + '@vitejs/plugin-react@5.1.2': resolution: {integrity: sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4443,6 +4456,19 @@ packages: peerDependencies: eslint: '*' + eslint-plugin-better-tailwindcss@4.1.1: + resolution: {integrity: sha512-ctw461TGJi8iM0P01mNVjSW7jeUAdyUgmrrd59np5/VxqX50nayMbwKZkfmjWpP1PWOqlh4CSMOH/WW6ICWmJw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + oxlint: ^1.35.0 + tailwindcss: ^3.3.0 || ^4.1.17 + peerDependenciesMeta: + eslint: + optional: true + oxlint: + optional: true + eslint-plugin-command@3.4.0: resolution: {integrity: sha512-EW4eg/a7TKEhG0s5IEti72kh3YOTlnhfFNuctq5WnB1fst37/IHTd5OkD+vnlRf3opTvUcSRihAateP6bT5ZcA==} peerDependencies: @@ -4493,15 +4519,15 @@ packages: peerDependencies: eslint: ^9.0.0 - eslint-plugin-react-dom@2.8.1: - resolution: {integrity: sha512-VAVs3cp/0XTxdjTeLePtZVadj+om+N1VNVy7hyzSPACfh5ncAicC0zOIc5MB15KUWCj8PoG/ZnVny0YqeubgRg==} + eslint-plugin-react-dom@2.9.4: + resolution: {integrity: sha512-lRa3iN082cX3HRKdbKSESmlj+z4zMR10DughwagV7h+IOd3O07UGnYQhenH08GMSyLy1f2D6QJmKBLGbx2p20g==} engines: {node: '>=20.19.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - eslint-plugin-react-hooks-extra@2.8.1: - resolution: {integrity: sha512-YeZLGzcib6UxlY7Gf+3zz8Mfl7u+OoVj3MukGaTuU6zkm1XQMI8/k4o16bKHuWtUauhn7Udl1bLAWfLgQM5UFw==} + eslint-plugin-react-hooks-extra@2.9.4: + resolution: {integrity: sha512-8hQArFHpXubT+i++8TwIL24vQ5b/ZcnVT3EFOSvy1TdBZw8NqrcFNBVqywQ6YUWX0utuPiTQgeJB0qnBF7gx4g==} engines: {node: '>=20.19.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -4513,27 +4539,34 @@ packages: peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - eslint-plugin-react-naming-convention@2.8.1: - resolution: {integrity: sha512-fVj+hSzIe2I6HyPTf1nccMBXq72c4jbM3gk0T+szo/wewEF8/LgenjfquJoxHPpheb1fujFgdlo5HBhsilAX7Q==} + eslint-plugin-react-naming-convention@2.9.4: + resolution: {integrity: sha512-Ow9ikJ49tDjeTaO2wfUYlSlVBsbG8AZVqoVFu4HH69FZe6I5LEdjZf/gdXnN2W+/JAy7Ru5vYQ8H8LU3tTZERg==} engines: {node: '>=20.19.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - eslint-plugin-react-refresh@0.4.26: - resolution: {integrity: sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==} + eslint-plugin-react-refresh@0.5.0: + resolution: {integrity: sha512-ZYvmh7VfVgqR/7wR71I3Zl6hK/C5CcxdWYKZSpHawS5JCNgE4efhQWg/+/WPpgGAp9Ngp/rRZYyaIwmPQBq/lA==} peerDependencies: - eslint: '>=8.40' + eslint: '>=9' - eslint-plugin-react-web-api@2.8.1: - resolution: {integrity: sha512-NYsZKW1aJZ2XZuYTPzbwYLShvGcuXKRV/5TW61VO56gik/btil4Snt5UtyxshHbvT/zXx/Z+QsHul51/XM4/Qw==} + eslint-plugin-react-rsc@2.9.4: + resolution: {integrity: sha512-RwBYSLkcGXQV6SQYABdHLrafUmpfdPBYsAa/kvg6smqEn+/vPKSk0I+uAuzkmiw4y4KXW94Q9rlIdJlzOMdJfQ==} engines: {node: '>=20.19.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - eslint-plugin-react-x@2.8.1: - resolution: {integrity: sha512-4IpCMrsb63AVEa9diOApIm+T3wUGIzK+EB5vyYocO31YYPJ16+R7Fh4lV3S3fOuX1+aQ+Ad4SE0cYuZ2pF2Tlg==} + eslint-plugin-react-web-api@2.9.4: + resolution: {integrity: sha512-/k++qhGoYtMNZrsQT+M08fCGi/VurL1fE/LNiz2fMwOIU7KjXD9N0kGWPFdIAISnYXGzOg53O5WW/mnNR78emQ==} + engines: {node: '>=20.19.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + eslint-plugin-react-x@2.9.4: + resolution: {integrity: sha512-a078MHeM/FdjRu3KJsFX+PCHewZyC77EjAO7QstL/vvwjsFae3PCWMZ8Q4b+mzUsT4FkFxi5mEW43ZHksPWDFw==} engines: {node: '>=20.19.0'} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -4550,17 +4583,11 @@ packages: peerDependencies: eslint: ^8.0.0 || ^9.0.0 - eslint-plugin-storybook@10.2.1: - resolution: {integrity: sha512-5+V+dlzTuZfNKUD8hPbLvCVtggcWfI2lDGTpiq0AENrHeAgcztj17wwDva96lbg/sAG20uX71l8HQo3s/GmpHw==} + eslint-plugin-storybook@10.2.6: + resolution: {integrity: sha512-Ykf0hDS97oJlQel21WG+SYtGnzFkkSfifupJ92NQtMMSMLXsWm4P0x8ZQqu9/EQa+dUkGoj9EWyNmmbB/54uhA==} peerDependencies: eslint: '>=8' - storybook: ^10.2.1 - - eslint-plugin-tailwindcss@3.18.2: - resolution: {integrity: sha512-QbkMLDC/OkkjFQ1iz/5jkMdHfiMu/uwujUHLAJK5iwNHD8RTxVTlsUezE0toTZ6VhybNBsk+gYGPDq2agfeRNA==} - engines: {node: '>=18.12.0'} - peerDependencies: - tailwindcss: ^3.4.0 + storybook: ^10.2.6 eslint-plugin-toml@1.0.3: resolution: {integrity: sha512-GlCBX+R313RvFY2Tj0ZmvzCEv8FDp1z2itvTFTV4bW/Bkbl3xEp9inWNsRWH3SiDUlxo8Pew31ILEp/3J0WxaA==} @@ -5585,6 +5612,9 @@ packages: mdn-data@2.12.2: resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + mdn-data@2.23.0: + resolution: {integrity: sha512-786vq1+4079JSeu2XdcDjrhi/Ry7BWtjDl9WtGPWLiIHb2T66GvIVflZTBoSNZ5JqTtJGYEVMuFA/lbQlMOyDQ==} + memoize-one@5.2.1: resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} @@ -6850,11 +6880,15 @@ packages: resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} engines: {node: '>=20'} - tailwind-merge@2.6.0: - resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==} + tailwind-csstree@0.1.4: + resolution: {integrity: sha512-FzD187HuFIZEyeR7Xy6sJbJll2d4SybS90satC8SKIuaNRC05CxMvdzN7BUsfDQffcnabckRM5OIcfArjsZ0mg==} + engines: {node: '>=18.18'} - tailwindcss@3.4.18: - resolution: {integrity: sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==} + tailwind-merge@2.6.1: + resolution: {integrity: sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==} + + tailwindcss@3.4.19: + resolution: {integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==} engines: {node: '>=14.0.0'} hasBin: true @@ -7003,6 +7037,10 @@ packages: typescript: optional: true + tsconfig-paths-webpack-plugin@4.2.0: + resolution: {integrity: sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==} + engines: {node: '>=10.13.0'} + tsconfig-paths@4.2.0: resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} engines: {node: '>=6'} @@ -7171,6 +7209,14 @@ packages: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true + valibot@1.2.0: + resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==} + peerDependencies: + typescript: '>=5' + peerDependenciesMeta: + typescript: + optional: true + vfile-location@5.0.3: resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} @@ -7694,7 +7740,7 @@ snapshots: idb: 8.0.3 tslib: 2.8.1 - '@antfu/eslint-config@7.2.0(@eslint-react/eslint-plugin@2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@next/eslint-plugin-next@16.1.6)(@vue/compiler-sfc@3.5.27)(eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@1.21.7)))(eslint-plugin-react-refresh@0.4.26(eslint@9.39.2(jiti@1.21.7)))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)(vitest@4.0.17)': + '@antfu/eslint-config@7.2.0(@eslint-react/eslint-plugin@2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@next/eslint-plugin-next@16.1.6)(@vue/compiler-sfc@3.5.27)(eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@1.21.7)))(eslint-plugin-react-refresh@0.5.0(eslint@9.39.2(jiti@1.21.7)))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)(vitest@4.0.17)': dependencies: '@antfu/install-pkg': 1.1.0 '@clack/prompts': 0.11.0 @@ -7734,10 +7780,10 @@ snapshots: vue-eslint-parser: 10.2.0(eslint@9.39.2(jiti@1.21.7)) yaml-eslint-parser: 2.0.0 optionalDependencies: - '@eslint-react/eslint-plugin': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/eslint-plugin': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@next/eslint-plugin-next': 16.1.6 eslint-plugin-react-hooks: 7.0.1(eslint@9.39.2(jiti@1.21.7)) - eslint-plugin-react-refresh: 0.4.26(eslint@9.39.2(jiti@1.21.7)) + eslint-plugin-react-refresh: 0.5.0(eslint@9.39.2(jiti@1.21.7)) transitivePeerDependencies: - '@eslint/json' - '@vue/compiler-sfc' @@ -8137,9 +8183,9 @@ snapshots: '@eslint-community/regexpp@4.12.2': {} - '@eslint-react/ast@2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@eslint-react/ast@2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@eslint-react/eff': 2.8.1 + '@eslint-react/eff': 2.9.4 '@typescript-eslint/types': 8.54.0 '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) @@ -8149,12 +8195,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint-react/core@2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@eslint-react/core@2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@eslint-react/ast': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/eff': 2.8.1 - '@eslint-react/shared': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/var': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/ast': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/eff': 2.9.4 + '@eslint-react/shared': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/var': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.54.0 '@typescript-eslint/types': 8.54.0 '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) @@ -8164,30 +8210,31 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint-react/eff@2.8.1': {} + '@eslint-react/eff@2.9.4': {} - '@eslint-react/eslint-plugin@2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@eslint-react/eslint-plugin@2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@eslint-react/eff': 2.8.1 - '@eslint-react/shared': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/eff': 2.9.4 + '@eslint-react/shared': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.54.0 '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/types': 8.54.0 '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) eslint: 9.39.2(jiti@1.21.7) - eslint-plugin-react-dom: 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - eslint-plugin-react-hooks-extra: 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - eslint-plugin-react-naming-convention: 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - eslint-plugin-react-web-api: 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - eslint-plugin-react-x: 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + eslint-plugin-react-dom: 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + eslint-plugin-react-hooks-extra: 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + eslint-plugin-react-naming-convention: 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + eslint-plugin-react-rsc: 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + eslint-plugin-react-web-api: 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + eslint-plugin-react-x: 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@eslint-react/shared@2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@eslint-react/shared@2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@eslint-react/eff': 2.8.1 + '@eslint-react/eff': 2.9.4 '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) eslint: 9.39.2(jiti@1.21.7) ts-pattern: 5.9.0 @@ -8196,11 +8243,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint-react/var@2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@eslint-react/var@2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@eslint-react/ast': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/eff': 2.8.1 - '@eslint-react/shared': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/ast': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/eff': 2.9.4 + '@eslint-react/shared': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.54.0 '@typescript-eslint/types': 8.54.0 '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) @@ -8258,6 +8305,11 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 + '@eslint/css-tree@3.6.8': + dependencies: + mdn-data: 2.23.0 + source-map-js: 1.2.1 + '@eslint/eslintrc@3.3.3': dependencies: ajv: 6.12.6 @@ -9902,10 +9954,10 @@ snapshots: dependencies: '@swc/counter': 0.1.3 - '@tailwindcss/typography@0.5.19(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.2))': + '@tailwindcss/typography@0.5.19(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.8.2))': dependencies: postcss-selector-parser: 6.0.10 - tailwindcss: 3.4.18(tsx@4.21.0)(yaml@2.8.2) + tailwindcss: 3.4.19(tsx@4.21.0)(yaml@2.8.2) '@tanstack/devtools-client@0.0.5': dependencies: @@ -9957,13 +10009,14 @@ snapshots: - csstype - utf-8-validate - '@tanstack/eslint-plugin-query@5.91.3(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@tanstack/eslint-plugin-query@5.91.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@typescript-eslint/utils': 8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) eslint: 9.39.2(jiti@1.21.7) + optionalDependencies: + typescript: 5.9.3 transitivePeerDependencies: - supports-color - - typescript '@tanstack/form-core@1.24.3': dependencies: @@ -10593,6 +10646,10 @@ snapshots: '@ungap/structured-clone@1.3.0': {} + '@valibot/to-json-schema@1.5.0(valibot@1.2.0(typescript@5.9.3))': + dependencies: + valibot: 1.2.0(typescript@5.9.3) + '@vitejs/plugin-react@5.1.2(vite@7.3.1(@types/node@18.15.0)(jiti@1.21.7)(sass@1.93.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@babel/core': 7.28.6 @@ -11747,6 +11804,22 @@ snapshots: dependencies: eslint: 9.39.2(jiti@1.21.7) + eslint-plugin-better-tailwindcss@4.1.1(eslint@9.39.2(jiti@1.21.7))(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.8.2))(typescript@5.9.3): + dependencies: + '@eslint/css-tree': 3.6.8 + '@valibot/to-json-schema': 1.5.0(valibot@1.2.0(typescript@5.9.3)) + enhanced-resolve: 5.18.4 + jiti: 2.6.1 + synckit: 0.11.12 + tailwind-csstree: 0.1.4 + tailwindcss: 3.4.19(tsx@4.21.0)(yaml@2.8.2) + tsconfig-paths-webpack-plugin: 4.2.0 + valibot: 1.2.0(typescript@5.9.3) + optionalDependencies: + eslint: 9.39.2(jiti@1.21.7) + transitivePeerDependencies: + - typescript + eslint-plugin-command@3.4.0(eslint@9.39.2(jiti@1.21.7)): dependencies: '@es-joy/jsdoccomment': 0.78.0 @@ -11835,37 +11908,35 @@ snapshots: yaml: 2.8.2 yaml-eslint-parser: 2.0.0 - eslint-plugin-react-dom@2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3): + eslint-plugin-react-dom@2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3): dependencies: - '@eslint-react/ast': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/core': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/eff': 2.8.1 - '@eslint-react/shared': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/var': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/ast': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/core': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/eff': 2.9.4 + '@eslint-react/shared': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/var': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.54.0 '@typescript-eslint/types': 8.54.0 '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) compare-versions: 6.1.1 eslint: 9.39.2(jiti@1.21.7) - string-ts: 2.3.1 ts-pattern: 5.9.0 typescript: 5.9.3 transitivePeerDependencies: - supports-color - eslint-plugin-react-hooks-extra@2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3): + eslint-plugin-react-hooks-extra@2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3): dependencies: - '@eslint-react/ast': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/core': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/eff': 2.8.1 - '@eslint-react/shared': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/var': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/ast': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/core': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/eff': 2.9.4 + '@eslint-react/shared': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/var': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.54.0 '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/types': 8.54.0 '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) eslint: 9.39.2(jiti@1.21.7) - string-ts: 2.3.1 ts-pattern: 5.9.0 typescript: 5.9.3 transitivePeerDependencies: @@ -11882,13 +11953,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-react-naming-convention@2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3): + eslint-plugin-react-naming-convention@2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3): dependencies: - '@eslint-react/ast': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/core': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/eff': 2.8.1 - '@eslint-react/shared': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/var': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/ast': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/core': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/eff': 2.9.4 + '@eslint-react/shared': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/var': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.54.0 '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/types': 8.54.0 @@ -11901,35 +11972,47 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-react-refresh@0.4.26(eslint@9.39.2(jiti@1.21.7)): + eslint-plugin-react-refresh@0.5.0(eslint@9.39.2(jiti@1.21.7)): dependencies: eslint: 9.39.2(jiti@1.21.7) - eslint-plugin-react-web-api@2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3): + eslint-plugin-react-rsc@2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3): dependencies: - '@eslint-react/ast': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/core': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/eff': 2.8.1 - '@eslint-react/shared': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/var': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.54.0 + '@eslint-react/ast': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/shared': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/var': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/types': 8.54.0 '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - birecord: 0.1.1 eslint: 9.39.2(jiti@1.21.7) - string-ts: 2.3.1 ts-pattern: 5.9.0 typescript: 5.9.3 transitivePeerDependencies: - supports-color - eslint-plugin-react-x@2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3): + eslint-plugin-react-web-api@2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3): dependencies: - '@eslint-react/ast': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/core': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/eff': 2.8.1 - '@eslint-react/shared': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@eslint-react/var': 2.8.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/ast': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/core': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/eff': 2.9.4 + '@eslint-react/shared': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/var': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.54.0 + '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + birecord: 0.1.1 + eslint: 9.39.2(jiti@1.21.7) + ts-pattern: 5.9.0 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-x@2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3): + dependencies: + '@eslint-react/ast': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/core': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/eff': 2.9.4 + '@eslint-react/shared': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@eslint-react/var': 2.9.4(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.54.0 '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/types': 8.54.0 @@ -11937,7 +12020,6 @@ snapshots: compare-versions: 6.1.1 eslint: 9.39.2(jiti@1.21.7) is-immutable-type: 5.0.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - string-ts: 2.3.1 ts-api-utils: 2.4.0(typescript@5.9.3) ts-pattern: 5.9.0 typescript: 5.9.3 @@ -11969,21 +12051,15 @@ snapshots: semver: 7.7.3 typescript: 5.9.3 - eslint-plugin-storybook@10.2.1(eslint@9.39.2(jiti@1.21.7))(storybook@10.2.0(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3): + eslint-plugin-storybook@10.2.6(eslint@9.39.2(jiti@1.21.7))(storybook@10.2.0(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3): dependencies: - '@typescript-eslint/utils': 8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) eslint: 9.39.2(jiti@1.21.7) storybook: 10.2.0(@testing-library/dom@10.4.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) transitivePeerDependencies: - supports-color - typescript - eslint-plugin-tailwindcss@3.18.2(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.2)): - dependencies: - fast-glob: 3.3.3 - postcss: 8.5.6 - tailwindcss: 3.4.18(tsx@4.21.0)(yaml@2.8.2) - eslint-plugin-toml@1.0.3(eslint@9.39.2(jiti@1.21.7)): dependencies: '@eslint/core': 1.0.1 @@ -13250,6 +13326,8 @@ snapshots: mdn-data@2.12.2: {} + mdn-data@2.23.0: {} + memoize-one@5.2.1: {} merge-stream@2.0.0: {} @@ -14863,9 +14941,11 @@ snapshots: tagged-tag@1.0.0: {} - tailwind-merge@2.6.0: {} + tailwind-csstree@0.1.4: {} - tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.2): + tailwind-merge@2.6.1: {} + + tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.8.2): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -15020,6 +15100,13 @@ snapshots: optionalDependencies: typescript: 5.9.3 + tsconfig-paths-webpack-plugin@4.2.0: + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.18.4 + tapable: 2.3.0 + tsconfig-paths: 4.2.0 + tsconfig-paths@4.2.0: dependencies: json5: 2.2.3 @@ -15185,6 +15272,10 @@ snapshots: uuid@11.1.0: {} + valibot@1.2.0(typescript@5.9.3): + optionalDependencies: + typescript: 5.9.3 + vfile-location@5.0.3: dependencies: '@types/unist': 3.0.3 diff --git a/web/utils/classnames.spec.ts b/web/utils/classnames.spec.ts deleted file mode 100644 index 1b8f487856..0000000000 --- a/web/utils/classnames.spec.ts +++ /dev/null @@ -1,157 +0,0 @@ -/** - * Test suite for the classnames utility function - * This utility combines the classnames library with tailwind-merge - * to handle conditional CSS classes and merge conflicting Tailwind classes - */ -import { cn } from './classnames' - -describe('classnames', () => { - /** - * Tests basic classnames library features: - * - String concatenation - * - Array handling - * - Falsy value filtering - * - Object-based conditional classes - */ - it('classnames libs feature', () => { - expect(cn('foo')).toBe('foo') - expect(cn('foo', 'bar')).toBe('foo bar') - expect(cn(['foo', 'bar'])).toBe('foo bar') - - expect(cn(undefined)).toBe('') - expect(cn(null)).toBe('') - expect(cn(false)).toBe('') - - expect(cn({ - foo: true, - bar: false, - baz: true, - })).toBe('foo baz') - }) - - /** - * Tests tailwind-merge functionality: - * - Conflicting class resolution (last one wins) - * - Modifier handling (hover, focus, etc.) - * - Important prefix (!) - * - Custom color classes - * - Arbitrary values - */ - it('tailwind-merge', () => { - /* eslint-disable tailwindcss/classnames-order */ - expect(cn('p-0')).toBe('p-0') - expect(cn('text-right text-center text-left')).toBe('text-left') - expect(cn('pl-4 p-8')).toBe('p-8') - expect(cn('m-[2px] m-[4px]')).toBe('m-[4px]') - expect(cn('m-1 m-[4px]')).toBe('m-[4px]') - expect(cn('overflow-x-auto hover:overflow-x-hidden overflow-x-scroll')).toBe( - 'hover:overflow-x-hidden overflow-x-scroll', - ) - expect(cn('h-10 h-min')).toBe('h-min') - expect(cn('bg-grey-5 bg-hotpink')).toBe('bg-hotpink') - - expect(cn('hover:block hover:inline')).toBe('hover:inline') - - expect(cn('font-medium !font-bold')).toBe('font-medium !font-bold') - expect(cn('!font-medium !font-bold')).toBe('!font-bold') - - expect(cn('text-gray-100 text-primary-200')).toBe('text-primary-200') - expect(cn('text-some-unknown-color text-components-input-bg-disabled text-primary-200')).toBe('text-primary-200') - expect(cn('bg-some-unknown-color bg-components-input-bg-disabled bg-primary-200')).toBe('bg-primary-200') - - expect(cn('border-t border-white/10')).toBe('border-t border-white/10') - expect(cn('border-t border-white')).toBe('border-t border-white') - expect(cn('text-3.5xl text-black')).toBe('text-3.5xl text-black') - }) - - /** - * Tests the integration of classnames and tailwind-merge: - * - Object-based conditional classes with Tailwind conflict resolution - */ - it('classnames combined with tailwind-merge', () => { - expect(cn('text-right', { - 'text-center': true, - })).toBe('text-center') - - expect(cn('text-right', { - 'text-center': false, - })).toBe('text-right') - }) - - /** - * Tests handling of multiple mixed argument types: - * - Strings, arrays, and objects in a single call - * - Tailwind merge working across different argument types - */ - it('multiple mixed argument types', () => { - expect(cn('foo', ['bar', 'baz'], { qux: true, quux: false })).toBe('foo bar baz qux') - expect(cn('p-4', ['p-2', 'm-4'], { 'text-left': true, 'text-right': true })).toBe('p-2 m-4 text-right') - }) - - /** - * Tests nested array handling: - * - Deep array flattening - * - Tailwind merge with nested structures - */ - it('nested arrays', () => { - expect(cn(['foo', ['bar', 'baz']])).toBe('foo bar baz') - expect(cn(['p-4', ['p-2', 'text-center']])).toBe('p-2 text-center') - }) - - /** - * Tests empty input handling: - * - Empty strings, arrays, and objects - * - Mixed empty and non-empty values - */ - it('empty inputs', () => { - expect(cn('')).toBe('') - expect(cn([])).toBe('') - expect(cn({})).toBe('') - expect(cn('', [], {})).toBe('') - expect(cn('foo', '', 'bar')).toBe('foo bar') - }) - - /** - * Tests number input handling: - * - Truthy numbers converted to strings - * - Zero treated as falsy - */ - it('numbers as inputs', () => { - expect(cn(1)).toBe('1') - expect(cn(0)).toBe('') - expect(cn('foo', 1, 'bar')).toBe('foo 1 bar') - }) - - /** - * Tests multiple object arguments: - * - Object merging - * - Tailwind conflict resolution across objects - */ - it('multiple objects', () => { - expect(cn({ foo: true }, { bar: true })).toBe('foo bar') - expect(cn({ foo: true, bar: false }, { bar: true, baz: true })).toBe('foo bar baz') - expect(cn({ 'p-4': true }, { 'p-2': true })).toBe('p-2') - }) - - /** - * Tests complex edge cases: - * - Mixed falsy values - * - Nested arrays with falsy values - * - Multiple conflicting Tailwind classes - */ - it('complex edge cases', () => { - expect(cn('foo', null, undefined, false, 'bar', 0, 1, '')).toBe('foo bar 1') - expect(cn(['foo', null, ['bar', undefined, 'baz']])).toBe('foo bar baz') - expect(cn('text-sm', { 'text-lg': false, 'text-xl': true }, 'text-2xl')).toBe('text-2xl') - }) - - /** - * Tests important (!) modifier behavior: - * - Important modifiers in objects - * - Conflict resolution with important prefix - */ - it('important modifier with objects', () => { - expect(cn({ '!font-medium': true }, { '!font-bold': true })).toBe('!font-bold') - expect(cn('font-normal', { '!font-bold': true })).toBe('font-normal !font-bold') - }) -})