From 4a9bbf19111e204efd8e75edf485a81a2875e123 Mon Sep 17 00:00:00 2001 From: abearxiong Date: Mon, 9 Feb 2026 00:29:46 +0800 Subject: [PATCH] refactor: update UI components to use base-ui library and improve accessibility - Refactored Dialog component to use base-ui's dialog implementation, enhancing structure and accessibility features. - Updated Input component to utilize base-ui's input, improving styling and consistency. - Reworked Label component for better accessibility and styling. - Refined Select component to leverage base-ui's select, enhancing usability and visual consistency. - Modified Separator component to use base-ui's separator, improving styling. - Enhanced Sonner component to include custom icons and improved theming. - Refactored Table component for better structure and accessibility. - Updated Tabs component to utilize base-ui's tabs, improving styling and functionality. - Introduced Checkbox component using base-ui's checkbox, enhancing accessibility and styling. --- components.json | 2 +- package.json | 18 +- pnpm-lock.yaml | 239 +++++++++++++++++-------- src/app/config/page.tsx | 14 +- src/app/config/store/index.ts | 2 + src/app/config/store/schema.ts | 2 + src/components/ui/avatar.tsx | 138 ++++++++++----- src/components/ui/badge.tsx | 46 +++-- src/components/ui/button.tsx | 64 ++++--- src/components/ui/card.tsx | 150 +++++++++------- src/components/ui/checkbox.tsx | 27 +++ src/components/ui/dialog.tsx | 221 +++++++++++++---------- src/components/ui/input.tsx | 30 ++-- src/components/ui/label.tsx | 32 ++-- src/components/ui/select.tsx | 300 ++++++++++++++++++-------------- src/components/ui/separator.tsx | 28 ++- src/components/ui/sonner.tsx | 38 ++-- src/components/ui/table.tsx | 175 +++++++++---------- src/components/ui/tabs.tsx | 119 ++++++++----- 19 files changed, 974 insertions(+), 671 deletions(-) create mode 100644 src/components/ui/checkbox.tsx diff --git a/components.json b/components.json index a78ad5d..c3cc1db 100644 --- a/components.json +++ b/components.json @@ -1,6 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema.json", - "style": "new-york", + "style": "base-nova", "rsc": false, "tsx": true, "tailwind": { diff --git a/package.json b/package.json index 49837c1..1ae0e2b 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,12 @@ "@ai-sdk/anthropic": "^3.0.38", "@ai-sdk/openai": "^3.0.26", "@ai-sdk/openai-compatible": "^2.0.28", - "@kevisual/cnb": "^0.0.19", + "@base-ui/react": "^1.1.0", + "@kevisual/cnb": "^0.0.20", "@kevisual/context": "^0.0.4", "@kevisual/router": "0.0.70", "@radix-ui/react-avatar": "^1.1.11", + "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-label": "^2.1.8", @@ -31,7 +33,7 @@ "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-tabs": "^1.1.13", - "@tanstack/react-router": "^1.158.1", + "@tanstack/react-router": "^1.158.4", "ai": "^6.0.77", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -51,21 +53,21 @@ "access": "public" }, "devDependencies": { - "@kevisual/query": "0.0.39", + "@kevisual/query": "0.0.40", "@kevisual/types": "^0.0.12", "@tailwindcss/vite": "^4.1.18", - "@tanstack/react-router-devtools": "^1.158.1", - "@tanstack/router-plugin": "^1.158.1", - "@types/node": "^25.2.1", + "@tanstack/react-router-devtools": "^1.158.4", + "@tanstack/router-plugin": "^1.158.4", + "@types/node": "^25.2.2", "@types/react": "^19.2.13", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^5.1.3", - "dotenv": "^17.2.3", + "dotenv": "^17.2.4", "tailwind-merge": "^3.4.0", "tailwindcss": "^4.1.18", "tw-animate-css": "^1.4.0", "typescript": "^5.9.3", "vite": "^8.0.0-beta.13" }, - "packageManager": "pnpm@10.28.2" + "packageManager": "pnpm@10.29.1" } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7854d07..2ca8991 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,9 +17,12 @@ importers: '@ai-sdk/openai-compatible': specifier: ^2.0.28 version: 2.0.28(zod@4.3.6) + '@base-ui/react': + specifier: ^1.1.0 + version: 1.1.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@kevisual/cnb': - specifier: ^0.0.19 - version: 0.0.19(dotenv@17.2.3)(idb-keyval@6.2.1) + specifier: ^0.0.20 + version: 0.0.20(dotenv@17.2.4)(idb-keyval@6.2.1) '@kevisual/context': specifier: ^0.0.4 version: 0.0.4 @@ -29,6 +32,9 @@ importers: '@radix-ui/react-avatar': specifier: ^1.1.11 version: 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-checkbox': + specifier: ^1.3.3 + version: 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@radix-ui/react-dialog': specifier: ^1.1.15 version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -51,8 +57,8 @@ importers: specifier: ^1.1.13 version: 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@tanstack/react-router': - specifier: ^1.158.1 - version: 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + specifier: ^1.158.4 + version: 1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) ai: specifier: ^6.0.77 version: 6.0.77(zod@4.3.6) @@ -97,23 +103,23 @@ importers: version: 5.0.11(@types/react@19.2.13)(immer@10.1.1)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) devDependencies: '@kevisual/query': - specifier: 0.0.39 - version: 0.0.39 + specifier: 0.0.40 + version: 0.0.40 '@kevisual/types': specifier: ^0.0.12 version: 0.0.12 '@tailwindcss/vite': specifier: ^4.1.18 - version: 4.1.18(vite@8.0.0-beta.13(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1)) + version: 4.1.18(vite@8.0.0-beta.13(@types/node@25.2.2)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1)) '@tanstack/react-router-devtools': - specifier: ^1.158.1 - version: 1.158.1(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.158.1)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + specifier: ^1.158.4 + version: 1.158.4(@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.158.4)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@tanstack/router-plugin': - specifier: ^1.158.1 - version: 1.158.1(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.13(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1)) + specifier: ^1.158.4 + version: 1.158.4(@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.13(@types/node@25.2.2)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1)) '@types/node': - specifier: ^25.2.1 - version: 25.2.1 + specifier: ^25.2.2 + version: 25.2.2 '@types/react': specifier: ^19.2.13 version: 19.2.13 @@ -122,10 +128,10 @@ importers: version: 19.2.3(@types/react@19.2.13) '@vitejs/plugin-react': specifier: ^5.1.3 - version: 5.1.3(vite@8.0.0-beta.13(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1)) + version: 5.1.3(vite@8.0.0-beta.13(@types/node@25.2.2)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1)) dotenv: - specifier: ^17.2.3 - version: 17.2.3 + specifier: ^17.2.4 + version: 17.2.4 tailwind-merge: specifier: ^3.4.0 version: 3.4.0 @@ -140,7 +146,7 @@ importers: version: 5.9.3 vite: specifier: ^8.0.0-beta.13 - version: 8.0.0-beta.13(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1) + version: 8.0.0-beta.13(@types/node@25.2.2)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1) packages/components: dependencies: @@ -339,6 +345,10 @@ packages: resolution: {integrity: sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + engines: {node: '>=6.9.0'} + '@babel/template@7.25.9': resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} engines: {node: '>=6.9.0'} @@ -367,6 +377,27 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@base-ui/react@1.1.0': + resolution: {integrity: sha512-ikcJRNj1mOiF2HZ5jQHrXoVoHcNHdBU5ejJljcBl+VTLoYXR6FidjTN86GjO6hyshi6TZFuNvv0dEOgaOFv6Lw==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@types/react': ^17 || ^18 || ^19 + react: ^17 || ^18 || ^19 + react-dom: ^17 || ^18 || ^19 + peerDependenciesMeta: + '@types/react': + optional: true + + '@base-ui/utils@0.2.4': + resolution: {integrity: sha512-smZwpMhjO29v+jrZusBSc5T+IJ3vBb9cjIiBjtKcvWmRj9Z4DWGVR3efr1eHR56/bqY5a4qyY9ElkOY5ljo3ng==} + peerDependencies: + '@types/react': ^17 || ^18 || ^19 + react: ^17 || ^18 || ^19 + react-dom: ^17 || ^18 || ^19 + peerDependenciesMeta: + '@types/react': + optional: true + '@emnapi/core@1.8.1': resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} @@ -634,8 +665,8 @@ packages: '@kevisual/cache@0.0.2': resolution: {integrity: sha512-2Cl5KF2Gi27uLfhO6CdTMFnRzx9vYnqevAo7d9ab3rOaqTgF8tLeAXglXyRbaWW3WUbHU2XaOb4r98uUsqIQQw==} - '@kevisual/cnb@0.0.19': - resolution: {integrity: sha512-SyO1C5yGsySsslSKr2BtwsxXzualNUJVH5HKE4FQga4dX/uxepBnSoDtdczbOWf3RgsQFZNzR0cihkgtWwkmtQ==} + '@kevisual/cnb@0.0.20': + resolution: {integrity: sha512-3ODGAT8vEnU90X/6SUeqMK1ZJCcvyn44bMsC7Joz0kvDKhntstbf/nZIm5TRhngvPEcOPyc+KROchTweC/qcNA==} '@kevisual/context@0.0.4': resolution: {integrity: sha512-HJeLeZQLU+7tCluSfOyvkgKLs0HjCZrdJlZgEgKRSa8XTwZfMAUt6J7qZTbrZAHBlPtX68EPu/PI8JMCeu3WAQ==} @@ -651,8 +682,8 @@ packages: '@kevisual/query@0.0.28': resolution: {integrity: sha512-ijgKhfYzrNEoRuQOVD/ed8fqo+MKcNdvNFCBFHiBLVtyUrnSVNeEeyoM3eEw9iASBCltR1L4yoVn4Rls2jvpFA==} - '@kevisual/query@0.0.39': - resolution: {integrity: sha512-3UEPBIvtdykNkrby3hvrgrHdgd17Uq+Pnr4zs+JBzATkU2eKaOqtTUJqdyIEwuySCwzGTxrnlUzWP4tziDQDLQ==} + '@kevisual/query@0.0.40': + resolution: {integrity: sha512-7m5BgDzd01m51hCHUId6ugQHdwgrLTb6fI7DSuMY17VjWb0+zGnkYmvRBqkTXzoIjjYbP5iwtRnrooEoToQfhg==} '@kevisual/router@0.0.70': resolution: {integrity: sha512-vXlIj9jRufhcIfeuPWemjSI+dxdzSmIBq5eRxQzqEfAJ7k+mBPhoI4KxH8vHnwyL30bqm8EdODL/p6Wg8uBw3g==} @@ -798,6 +829,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-checkbox@1.3.3': + resolution: {integrity: sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-collection@1.1.7': resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} peerDependencies: @@ -1503,20 +1547,20 @@ packages: resolution: {integrity: sha512-xyIfof8eHBuub1CkBnbKNKQXeRZC4dClhmzePHVOEel4G7lk/dW+TQ16da7CFdeNLv6u6Owf5VoBQxoo6DFTSA==} engines: {node: '>=12'} - '@tanstack/react-router-devtools@1.158.1': - resolution: {integrity: sha512-H0iTfsLNkadF/JhJnu/pUxlxOiLjE0866vFqXK/7EYVcyYwx2uWQuGxEkyF7a04oXXrbEImAOoXDRBQcZ9T5Zw==} + '@tanstack/react-router-devtools@1.158.4': + resolution: {integrity: sha512-/EkrrJGTPC7MwLfcYYmZM71ANDMLbwcYvBtDA+48LqHUKal8mpWlaodiWdFFnVQ7ny/unbUxljgdrNV9YZiyFQ==} engines: {node: '>=12'} peerDependencies: - '@tanstack/react-router': ^1.158.1 - '@tanstack/router-core': ^1.158.1 + '@tanstack/react-router': ^1.158.4 + '@tanstack/router-core': ^1.158.4 react: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0' peerDependenciesMeta: '@tanstack/router-core': optional: true - '@tanstack/react-router@1.158.1': - resolution: {integrity: sha512-ZRBhs0tJDPeYGVrBhXPkGs+mOKqKKMM4OfvYSNvWIYZGfs8KQcqxPaN8OnUvKsnAGtzwusVWDpBipqVZWJd0lA==} + '@tanstack/react-router@1.158.4': + resolution: {integrity: sha512-i15xXumgvpuM+4NSuIwgouGezuj9eHjZsgpTZSQ7E9pa8rYmhZbWnf8xU68qaLmaKIol/e75o/YzVH2QWHs3iQ==} engines: {node: '>=12'} peerDependencies: react: '>=18.0.0 || >=19.0.0' @@ -1528,30 +1572,30 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/router-core@1.158.1': - resolution: {integrity: sha512-8B9X3GzN1JWsqa+OTgg2k+LrayLQYmgtv26b96difyrRS32DaDBvEpU3xXDaLNmi/+zoqG1ffAcDT4D6tyC2hw==} + '@tanstack/router-core@1.158.4': + resolution: {integrity: sha512-KikgYdyrEFqsjjgv9pMhDTMmASMAyFRvUiKFdQPQtXq3aD1qv/zck4CbA4bfzp9N9nYu/qvWwU1mlYU4u5JeXg==} engines: {node: '>=12'} - '@tanstack/router-devtools-core@1.158.1': - resolution: {integrity: sha512-iGCqmIJ5NXMIuyFwJgfikEmRrceT3tmynMTMSuVxFiv9+Dlk1tsp8bsYS+UGhyY4beoASsRnlikAeNAMsCjhwA==} + '@tanstack/router-devtools-core@1.158.4': + resolution: {integrity: sha512-9MKzstYp/6sNRSwJY2b9ipVW8b8/x1iSFNfLhOJur2tnjB3RhwCDfy0u+to70BrRpBEWeq7jvJoVdP029gzUUg==} engines: {node: '>=12'} peerDependencies: - '@tanstack/router-core': ^1.158.1 + '@tanstack/router-core': ^1.158.4 csstype: ^3.0.10 peerDependenciesMeta: csstype: optional: true - '@tanstack/router-generator@1.158.1': - resolution: {integrity: sha512-geBpsIxJNvdjw2kt/Ii/j68hIUvfGnra0HKlGrDZw8/Ny4AJ2nnOcszUlZRbuQyxByk05r4lneOShKy5V5MUCQ==} + '@tanstack/router-generator@1.158.4': + resolution: {integrity: sha512-RQmqMTT0oV8dS/3Glcq9SPzDZqOPyKb/LVFUkNoTfMwW88WyGnQcYqZAkmVk/CGBWWDfwObOUZoGq5jTF7bG8w==} engines: {node: '>=12'} - '@tanstack/router-plugin@1.158.1': - resolution: {integrity: sha512-IPCnf1CBc0jnczuy65+3iBaoABv5TKhOJ1YLzwel4kb9D8Abcq0vF8ooR5FiPmaGnree/z3SvjgHe5eQtgcsSQ==} + '@tanstack/router-plugin@1.158.4': + resolution: {integrity: sha512-g2sytAhljw6Jd6Klu37OZ75+o+vhiGdbWtnBy/4rYLC4NN6hSnjgJQRI3+h1CI1KQ4EUgsZYZr/hgE1KHoiWYQ==} engines: {node: '>=12'} peerDependencies: '@rsbuild/core': '>=1.0.2' - '@tanstack/react-router': ^1.158.1 + '@tanstack/react-router': ^1.158.4 vite: '>=5.0.0 || >=6.0.0 || >=7.0.0' vite-plugin-solid: ^2.11.10 webpack: '>=5.92.0' @@ -1599,8 +1643,8 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/node@25.2.1': - resolution: {integrity: sha512-CPrnr8voK8vC6eEtyRzvMpgp3VyVRhgclonE7qYi6P9sXwYb59ucfrnmFBTaP0yUi8Gk4yZg/LlTJULGxvTNsg==} + '@types/node@25.2.2': + resolution: {integrity: sha512-BkmoP5/FhRYek5izySdkOneRyXYN35I860MFAGupTdebyE66uZaR+bXLHq8k4DirE5DwQi3NuhvRU1jqTVwUrQ==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -1778,8 +1822,8 @@ packages: resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} engines: {node: '>=12'} - dotenv@17.2.3: - resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} + dotenv@17.2.4: + resolution: {integrity: sha512-mudtfb4zRB4bVvdj0xRo+e6duH1csJRM8IukBqfTRvHotn9+LBXB8ynAidP9zHqoRC/fsllXgk4kCKlR21fIhw==} engines: {node: '>=12'} electron-to-chromium@1.5.65: @@ -2366,6 +2410,9 @@ packages: regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + reselect@5.1.1: + resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -2444,6 +2491,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + tabbable@6.4.0: + resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} + tailwind-merge@3.3.0: resolution: {integrity: sha512-fyW/pEfcQSiigd5SNn0nApUOxx0zB/dm6UDU/rEwc2c3sX2smWUNbapHv+QRqLGVp9GWX3THIa7MUGPo+YkDzQ==} @@ -2872,6 +2922,8 @@ snapshots: '@babel/runtime@7.27.1': {} + '@babel/runtime@7.28.6': {} + '@babel/template@7.25.9': dependencies: '@babel/code-frame': 7.26.2 @@ -2923,6 +2975,31 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@base-ui/react@1.1.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@babel/runtime': 7.28.6 + '@base-ui/utils': 0.2.4(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@floating-ui/react-dom': 2.1.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@floating-ui/utils': 0.2.10 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + reselect: 5.1.1 + tabbable: 6.4.0 + use-sync-external-store: 1.6.0(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.13 + + '@base-ui/utils@0.2.4(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@babel/runtime': 7.28.6 + '@floating-ui/utils': 0.2.10 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + reselect: 5.1.1 + use-sync-external-store: 1.6.0(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.13 + '@emnapi/core@1.8.1': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -3163,11 +3240,11 @@ snapshots: - tslib - typescript - '@kevisual/cnb@0.0.19(dotenv@17.2.3)(idb-keyval@6.2.1)': + '@kevisual/cnb@0.0.20(dotenv@17.2.4)(idb-keyval@6.2.1)': dependencies: - '@kevisual/query': 0.0.39 + '@kevisual/query': 0.0.40 '@kevisual/router': 0.0.70 - '@kevisual/use-config': 1.0.30(dotenv@17.2.3) + '@kevisual/use-config': 1.0.30(dotenv@17.2.4) es-toolkit: 1.44.0 nanoid: 5.1.6 unstorage: 1.17.4(idb-keyval@6.2.1) @@ -3218,7 +3295,7 @@ snapshots: - ws - zod - '@kevisual/query@0.0.39': + '@kevisual/query@0.0.40': dependencies: tslib: 2.8.1 @@ -3228,10 +3305,10 @@ snapshots: '@kevisual/types@0.0.12': {} - '@kevisual/use-config@1.0.30(dotenv@17.2.3)': + '@kevisual/use-config@1.0.30(dotenv@17.2.4)': dependencies: '@kevisual/load': 0.0.6 - dotenv: 17.2.3 + dotenv: 17.2.4 '@kevisual/ws@8.19.0': {} @@ -3355,6 +3432,22 @@ snapshots: '@types/react': 19.2.13 '@types/react-dom': 19.2.3(@types/react@19.2.13) + '@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.13)(react@19.2.4) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.13)(react@19.2.4) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.13)(react@19.2.4) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.13)(react@19.2.4) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.13)(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.13 + '@types/react-dom': 19.2.3(@types/react@19.2.13) + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.13)(react@19.2.4) @@ -3919,31 +4012,31 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 - '@tailwindcss/vite@4.1.18(vite@8.0.0-beta.13(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1))': + '@tailwindcss/vite@4.1.18(vite@8.0.0-beta.13(@types/node@25.2.2)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1))': dependencies: '@tailwindcss/node': 4.1.18 '@tailwindcss/oxide': 4.1.18 tailwindcss: 4.1.18 - vite: 8.0.0-beta.13(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1) + vite: 8.0.0-beta.13(@types/node@25.2.2)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1) '@tanstack/history@1.154.14': {} - '@tanstack/react-router-devtools@1.158.1(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.158.1)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@tanstack/react-router-devtools@1.158.4(@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.158.4)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@tanstack/react-router': 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@tanstack/router-devtools-core': 1.158.1(@tanstack/router-core@1.158.1)(csstype@3.2.3) + '@tanstack/react-router': 1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@tanstack/router-devtools-core': 1.158.4(@tanstack/router-core@1.158.4)(csstype@3.2.3) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) optionalDependencies: - '@tanstack/router-core': 1.158.1 + '@tanstack/router-core': 1.158.4 transitivePeerDependencies: - csstype - '@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@tanstack/history': 1.154.14 '@tanstack/react-store': 0.8.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@tanstack/router-core': 1.158.1 + '@tanstack/router-core': 1.158.4 isbot: 5.1.34 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) @@ -3957,7 +4050,7 @@ snapshots: react-dom: 19.2.4(react@19.2.4) use-sync-external-store: 1.6.0(react@19.2.4) - '@tanstack/router-core@1.158.1': + '@tanstack/router-core@1.158.4': dependencies: '@tanstack/history': 1.154.14 '@tanstack/store': 0.8.0 @@ -3967,18 +4060,18 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - '@tanstack/router-devtools-core@1.158.1(@tanstack/router-core@1.158.1)(csstype@3.2.3)': + '@tanstack/router-devtools-core@1.158.4(@tanstack/router-core@1.158.4)(csstype@3.2.3)': dependencies: - '@tanstack/router-core': 1.158.1 + '@tanstack/router-core': 1.158.4 clsx: 2.1.1 goober: 2.1.18(csstype@3.2.3) tiny-invariant: 1.3.3 optionalDependencies: csstype: 3.2.3 - '@tanstack/router-generator@1.158.1': + '@tanstack/router-generator@1.158.4': dependencies: - '@tanstack/router-core': 1.158.1 + '@tanstack/router-core': 1.158.4 '@tanstack/router-utils': 1.158.0 '@tanstack/virtual-file-routes': 1.154.7 prettier: 3.8.1 @@ -3989,7 +4082,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.158.1(@tanstack/react-router@1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.13(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1))': + '@tanstack/router-plugin@1.158.4(@tanstack/react-router@1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.13(@types/node@25.2.2)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) @@ -3997,16 +4090,16 @@ snapshots: '@babel/template': 7.28.6 '@babel/traverse': 7.29.0 '@babel/types': 7.29.0 - '@tanstack/router-core': 1.158.1 - '@tanstack/router-generator': 1.158.1 + '@tanstack/router-core': 1.158.4 + '@tanstack/router-generator': 1.158.4 '@tanstack/router-utils': 1.158.0 '@tanstack/virtual-file-routes': 1.154.7 chokidar: 3.6.0 unplugin: 2.3.11 zod: 3.25.76 optionalDependencies: - '@tanstack/react-router': 1.158.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - vite: 8.0.0-beta.13(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1) + '@tanstack/react-router': 1.158.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + vite: 8.0.0-beta.13(@types/node@25.2.2)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1) transitivePeerDependencies: - supports-color @@ -4058,7 +4151,7 @@ snapshots: '@types/estree@1.0.8': {} - '@types/node@25.2.1': + '@types/node@25.2.2': dependencies: undici-types: 7.16.0 @@ -4086,7 +4179,7 @@ snapshots: '@vercel/oidc@3.1.0': {} - '@vitejs/plugin-react@5.1.3(vite@8.0.0-beta.13(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1))': + '@vitejs/plugin-react@5.1.3(vite@8.0.0-beta.13(@types/node@25.2.2)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) @@ -4094,7 +4187,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-rc.2 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 8.0.0-beta.13(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1) + vite: 8.0.0-beta.13(@types/node@25.2.2)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1) transitivePeerDependencies: - supports-color @@ -4230,7 +4323,7 @@ snapshots: dotenv@16.5.0: {} - dotenv@17.2.3: {} + dotenv@17.2.4: {} electron-to-chromium@1.5.65: {} @@ -4703,6 +4796,8 @@ snapshots: regenerator-runtime@0.14.1: {} + reselect@5.1.1: {} + resolve-from@4.0.0: {} resolve-pkg-maps@1.0.0: {} @@ -4795,6 +4890,8 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + tabbable@6.4.0: {} + tailwind-merge@3.3.0: {} tailwind-merge@3.4.0: {} @@ -4882,7 +4979,7 @@ snapshots: dependencies: react: 19.2.4 - vite@8.0.0-beta.13(@types/node@25.2.1)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1): + vite@8.0.0-beta.13(@types/node@25.2.2)(esbuild@0.27.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.5.1): dependencies: '@oxc-project/runtime': 0.112.0 fdir: 6.5.0(picomatch@4.0.3) @@ -4892,7 +4989,7 @@ snapshots: rolldown: 1.0.0-rc.3 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 25.2.1 + '@types/node': 25.2.2 esbuild: 0.27.2 fsevents: 2.3.3 jiti: 2.6.1 diff --git a/src/app/config/page.tsx b/src/app/config/page.tsx index 33e6c1f..3ea7c29 100644 --- a/src/app/config/page.tsx +++ b/src/app/config/page.tsx @@ -3,6 +3,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Button } from '@/components/ui/button'; +import { Checkbox } from '@/components/ui/checkbox'; import { configSchema } from './store/schema'; export const ConfigPage = () => { @@ -19,7 +20,7 @@ export const ConfigPage = () => { } }; - const handleChange = (field: keyof typeof config, value: string) => { + const handleChange = (field: keyof typeof config, value: string | boolean) => { setConfig({ [field]: value }); }; @@ -67,6 +68,17 @@ export const ConfigPage = () => { /> +
+ handleChange('ENABLE_CORS', checked === true)} + /> + +
+
{ CNB_API_KEY: '', CNB_COOKIE: '', CNB_CORS_URL: 'https://cors.kevisual.cn', + ENABLE_CORS: true, AI_BASE_URL: '', AI_MODEL: '', AI_API_KEY: '' @@ -43,6 +44,7 @@ export const useConfigStore = create()( CNB_API_KEY: '', CNB_COOKIE: '', CNB_CORS_URL: 'https://cors.kevisual.cn', + ENABLE_CORS: true, AI_BASE_URL: 'https://api.cnb.cool/kevisual/cnb-ai/-/ai/', AI_MODEL: 'CNB-Models', AI_API_KEY: '' diff --git a/src/app/config/store/schema.ts b/src/app/config/store/schema.ts index d04ae7a..68f8cbc 100644 --- a/src/app/config/store/schema.ts +++ b/src/app/config/store/schema.ts @@ -4,6 +4,7 @@ export const configSchema = z.object({ CNB_API_KEY: z.string().min(1, 'API Key is required'), CNB_COOKIE: z.string().min(1, 'Cookie is required'), CNB_CORS_URL: z.url('Must be a valid URL'), + ENABLE_CORS: z.boolean(), AI_BASE_URL: z.url('Must be a valid URL'), AI_MODEL: z.string().min(1, 'AI Model is required'), AI_API_KEY: z.string().min(1, 'AI API Key is required'), @@ -15,6 +16,7 @@ export const defaultConfig: Config = { CNB_API_KEY: '', CNB_COOKIE: '', CNB_CORS_URL: 'https://cors.kevisual.cn', + ENABLE_CORS: true, AI_BASE_URL: '', AI_MODEL: '', AI_API_KEY: '' diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx index 991f56e..2871ad1 100644 --- a/src/components/ui/avatar.tsx +++ b/src/components/ui/avatar.tsx @@ -1,48 +1,104 @@ import * as React from "react" -import * as AvatarPrimitive from "@radix-ui/react-avatar" +import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar" import { cn } from "@/lib/utils" -const Avatar = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -Avatar.displayName = AvatarPrimitive.Root.displayName +function Avatar({ + className, + size = "default", + ...props +}: AvatarPrimitive.Root.Props & { + size?: "default" | "sm" | "lg" +}) { + return ( + + ) +} -const AvatarImage = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AvatarImage.displayName = AvatarPrimitive.Image.displayName +function AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) { + return ( + + ) +} -const AvatarFallback = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName +function AvatarFallback({ + className, + ...props +}: AvatarPrimitive.Fallback.Props) { + return ( + + ) +} -export { Avatar, AvatarImage, AvatarFallback } +function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) { + return ( + svg]:hidden", + "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2", + "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2", + className + )} + {...props} + /> + ) +} + +function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function AvatarGroupCount({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3 ring-background relative flex shrink-0 items-center justify-center ring-2", className)} + {...props} + /> + ) +} + +export { + Avatar, + AvatarImage, + AvatarFallback, + AvatarGroup, + AvatarGroupCount, + AvatarBadge, +} diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx index e87d62b..c0d4ad8 100644 --- a/src/components/ui/badge.tsx +++ b/src/components/ui/badge.tsx @@ -1,20 +1,20 @@ -import * as React from "react" +import { mergeProps } from "@base-ui/react/merge-props" +import { useRender } from "@base-ui/react/use-render" import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" const badgeVariants = cva( - "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + "h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive overflow-hidden group/badge", { variants: { variant: { - default: - "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80", - secondary: - "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", - destructive: - "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80", - outline: "text-foreground", + default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80", + secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80", + destructive: "bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20", + outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground", + ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50", + link: "text-primary underline-offset-4 hover:underline", }, }, defaultVariants: { @@ -23,14 +23,26 @@ const badgeVariants = cva( } ) -export interface BadgeProps - extends React.HTMLAttributes, - VariantProps {} - -function Badge({ className, variant, ...props }: BadgeProps) { - return ( -
- ) +function Badge({ + className, + variant = "default", + render, + ...props +}: useRender.ComponentProps<"span"> & VariantProps) { + return useRender({ + defaultTagName: "span", + props: mergeProps<"span">( + { + className: cn(badgeVariants({ className, variant })), + }, + props + ), + render, + state: { + slot: "badge", + variant, + }, + }) } export { Badge, badgeVariants } diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 65d4fcd..e38fd55 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -1,30 +1,31 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" +"use client" + +import { Button as ButtonPrimitive } from "@base-ui/react/button" import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none", { variants: { variant: { - default: - "bg-primary text-primary-foreground shadow hover:bg-primary/90", - destructive: - "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", - outline: - "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", - secondary: - "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", + default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80", + outline: "border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground", + secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground", + ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground", + destructive: "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30", link: "text-primary underline-offset-4 hover:underline", }, size: { - default: "h-9 px-4 py-2", - sm: "h-8 rounded-md px-3 text-xs", - lg: "h-10 rounded-md px-8", - icon: "h-9 w-9", + default: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2", + xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3", + sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5", + lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3", + icon: "size-8", + "icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3", + "icon-sm": "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg", + "icon-lg": "size-9", }, }, defaultVariants: { @@ -34,24 +35,19 @@ const buttonVariants = cva( } ) -export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean +function Button({ + className, + variant = "default", + size = "default", + ...props +}: ButtonPrimitive.Props & VariantProps) { + return ( + + ) } -const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button" - return ( - - ) - } -) -Button.displayName = "Button" - export { Button, buttonVariants } diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx index cabfbfc..84bfaa4 100644 --- a/src/components/ui/card.tsx +++ b/src/components/ui/card.tsx @@ -2,75 +2,93 @@ import * as React from "react" import { cn } from "@/lib/utils" -const Card = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -Card.displayName = "Card" +function Card({ + className, + size = "default", + ...props +}: React.ComponentProps<"div"> & { size?: "default" | "sm" }) { + return ( +
img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col", className)} + {...props} + /> + ) +} -const CardHeader = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -CardHeader.displayName = "CardHeader" +function CardHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} -const CardTitle = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -CardTitle.displayName = "CardTitle" +function CardTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} -const CardDescription = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -CardDescription.displayName = "CardDescription" +function CardDescription({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} -const CardContent = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -CardContent.displayName = "CardContent" +function CardAction({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} -const CardFooter = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -CardFooter.displayName = "CardFooter" +function CardContent({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} -export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } +function CardFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +export { + Card, + CardHeader, + CardFooter, + CardTitle, + CardAction, + CardDescription, + CardContent, +} diff --git a/src/components/ui/checkbox.tsx b/src/components/ui/checkbox.tsx new file mode 100644 index 0000000..e010fd9 --- /dev/null +++ b/src/components/ui/checkbox.tsx @@ -0,0 +1,27 @@ +import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox" + +import { cn } from "@/lib/utils" +import { CheckIcon } from "lucide-react" + +function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) { + return ( + + + + + + ) +} + +export { Checkbox } diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx index 9dbeaa0..c509160 100644 --- a/src/components/ui/dialog.tsx +++ b/src/components/ui/dialog.tsx @@ -1,120 +1,151 @@ +"use client" + import * as React from "react" -import * as DialogPrimitive from "@radix-ui/react-dialog" -import { X } from "lucide-react" +import { Dialog as DialogPrimitive } from "@base-ui/react/dialog" import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" +import { XIcon } from "lucide-react" -const Dialog = DialogPrimitive.Root +function Dialog({ ...props }: DialogPrimitive.Root.Props) { + return +} -const DialogTrigger = DialogPrimitive.Trigger +function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) { + return +} -const DialogPortal = DialogPrimitive.Portal +function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) { + return +} -const DialogClose = DialogPrimitive.Close +function DialogClose({ ...props }: DialogPrimitive.Close.Props) { + return +} -const DialogOverlay = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DialogOverlay.displayName = DialogPrimitive.Overlay.displayName +function DialogOverlay({ + className, + ...props +}: DialogPrimitive.Backdrop.Props) { + return ( + + ) +} -const DialogContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - + + + {children} + {showCloseButton && ( + + } + > + + Close + + )} + + + ) +} + +function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function DialogFooter({ + className, + showCloseButton = false, + children, + ...props +}: React.ComponentProps<"div"> & { + showCloseButton?: boolean +}) { + return ( +
{children} - - - Close - - - -)) -DialogContent.displayName = DialogPrimitive.Content.displayName + {showCloseButton && ( + }> + Close + + )} +
+ ) +} -const DialogHeader = ({ +function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) { + return ( + + ) +} + +function DialogDescription({ className, ...props -}: React.HTMLAttributes) => ( -
-) -DialogHeader.displayName = "DialogHeader" - -const DialogFooter = ({ - className, - ...props -}: React.HTMLAttributes) => ( -
-) -DialogFooter.displayName = "DialogFooter" - -const DialogTitle = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DialogTitle.displayName = DialogPrimitive.Title.displayName - -const DialogDescription = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DialogDescription.displayName = DialogPrimitive.Description.displayName +}: DialogPrimitive.Description.Props) { + return ( + + ) +} export { Dialog, - DialogPortal, - DialogOverlay, - DialogTrigger, DialogClose, DialogContent, - DialogHeader, - DialogFooter, - DialogTitle, DialogDescription, + DialogFooter, + DialogHeader, + DialogOverlay, + DialogPortal, + DialogTitle, + DialogTrigger, } diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx index 69b64fb..981e825 100644 --- a/src/components/ui/input.tsx +++ b/src/components/ui/input.tsx @@ -1,22 +1,20 @@ import * as React from "react" +import { Input as InputPrimitive } from "@base-ui/react/input" import { cn } from "@/lib/utils" -const Input = React.forwardRef>( - ({ className, type, ...props }, ref) => { - return ( - - ) - } -) -Input.displayName = "Input" +function Input({ className, type, ...props }: React.ComponentProps<"input">) { + return ( + + ) +} export { Input } diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx index 683faa7..5ac813e 100644 --- a/src/components/ui/label.tsx +++ b/src/components/ui/label.tsx @@ -1,24 +1,20 @@ +"use client" + import * as React from "react" -import * as LabelPrimitive from "@radix-ui/react-label" -import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" -const labelVariants = cva( - "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" -) - -const Label = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & - VariantProps ->(({ className, ...props }, ref) => ( - -)) -Label.displayName = LabelPrimitive.Root.displayName +function Label({ className, ...props }: React.ComponentProps<"label">) { + return ( +