This commit is contained in:
2026-03-05 22:02:44 +08:00
parent d196b24d07
commit 575feec78b
38 changed files with 1502 additions and 431 deletions

View File

@@ -4,8 +4,7 @@ include:
.common_env: &common_env .common_env: &common_env
env: env:
TO_REPO: kevisual/cnb-center USERNAME: root
TO_URL: git.xiongxiao.me
imports: imports:
- https://cnb.cool/kevisual/env/-/blob/main/.env.development - https://cnb.cool/kevisual/env/-/blob/main/.env.development
@@ -16,29 +15,6 @@ $:
services: services:
- vscode - vscode
- docker - docker
env: !reference [.common_env, env]
imports: !reference [.common_env, imports] imports: !reference [.common_env, imports]
# 开发环境启动后会执行的任务 stages: !reference [.dev_template, stages]
# stages:
# - name: pnpm install
# script: pnpm install
stages: !reference [.dev_template, stages]
.common_sync_to_gitea: &common_sync_to_gitea
- <<: *common_env
services: !reference [.common_sync_to_gitea_template, services]
stages: !reference [.common_sync_to_gitea_template, stages]
.common_sync_from_gitea: &common_sync_from_gitea
- <<: *common_env
services: !reference [.common_sync_from_gitea_template, services]
stages: !reference [.common_sync_from_gitea_template, stages]
main:
web_trigger_sync_to_gitea:
- <<: *common_sync_to_gitea
web_trigger_sync_from_gitea:
- <<: *common_sync_from_gitea
api_trigger_sync_to_gitea:
- <<: *common_sync_to_gitea
api_trigger_sync_from_gitea:
- <<: *common_sync_from_gitea

26
.gitignore vendored
View File

@@ -1,37 +1,19 @@
# Logs # Logs
logs logs
*.log *.log
.env
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules node_modules
dist dist
dist-ssr pack-dist
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store .DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
tsconfig.app.tsbuildinfo
tsconfig.node.tsbuildinfo
.turbo .turbo
.pnpm-store .pnpm-store
.tanstack .tanstack
.env .env*
!.env.example !.env.example
.pnpm-lock.yaml

View File

@@ -25,19 +25,36 @@ src/
``` ```
pages/page-app/ pages/page-app/
├── components/ # 模块专属组件 ├── components/ # 模块专属组件
├── store/ # 模块状态管理 ├── hooks/ # 模块 React Query hooksAPI 查询封装)
── module/ # 模块功能函数 ── modules/ # 模块功能函数UI 组件、工具函数等)
└── store/ # 模块状态管理Zustand
``` ```
### hooks/ 文件夹说明
每个模块的 `hooks/` 文件夹用于封装与该模块相关的 React Query hooks
- **use-api-query.ts**: 使用 `@tanstack/react-query``useQuery` 封装 API 调用
- 定义 `queryKeys` 常量用于缓存标识
- 封装 `useQuery` hooks 用于数据获取GET 请求)
- 封装 `useMutation` hooks 用于数据修改POST/PUT/DELETE 请求)
- 支持预取prefetch和无限滚动infinite query
- **index.ts**: 导出模块所有 hooks便于统一导入使用
### 状态和数据获取 ### 状态和数据获取
- **@tanstack/react-query** 用于数据获取、缓存和状态管理
- 在模块的 `hooks/` 文件夹中封装 API 调用
- QueryClient 实例位于 `src/modules/query.ts`
-`src/routes/__root.tsx` 中通过 `QueryClientProvider` 提供
- **Zustand** 用于全局状态管理 - **Zustand** 用于全局状态管理
- **@kevisual/query** 用于数据获取QueryClient 实例位于 `src/modules/query.ts` - **@kevisual/query** 用于底层 API 请求封装
- **React Hook Form** 用于表单管理 - **React Hook Form** 用于表单管理
## 核心依赖 ## 核心依赖
- **@base-ui/react**: Headless UI 基础组件 - **@base-ui/react**: Headless UI 基础组件
- **@tanstack/react-query**: 数据获取、缓存和状态管理(配合 hooks/ 使用)
- **@tanstack/react-router**: 基于 TanStack Router 插件的文件路由 - **@tanstack/react-router**: 基于 TanStack Router 插件的文件路由
- **class-variance-authority**: 基于变体的样式系统 - **class-variance-authority**: 基于变体的样式系统
- **clsx + tailwind-merge**: 通过 `cn()` 提供 className 工具函数 - **clsx + tailwind-merge**: 通过 `cn()` 提供 className 工具函数

21
kevisual.json Normal file
View File

@@ -0,0 +1,21 @@
{
"metadata": {
"name": "kevisual",
"share": "public"
},
"registry": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template",
"clone": {
".": {
"enabled": true
}
},
"syncd": [
{
"files": [
"**/*"
],
"registry": ""
}
],
"sync": {}
}

View File

@@ -55,6 +55,7 @@
"@kevisual/query": "0.0.49", "@kevisual/query": "0.0.49",
"@kevisual/types": "^0.0.12", "@kevisual/types": "^0.0.12",
"@tailwindcss/vite": "^4.2.0", "@tailwindcss/vite": "^4.2.0",
"@tanstack/react-query": "^5.90.21",
"@tanstack/react-router-devtools": "^1.161.1", "@tanstack/react-router-devtools": "^1.161.1",
"@tanstack/router-plugin": "^1.161.1", "@tanstack/router-plugin": "^1.161.1",
"@types/node": "^25.3.0", "@types/node": "^25.3.0",

423
pnpm-lock.yaml generated
View File

@@ -10,13 +10,13 @@ importers:
dependencies: dependencies:
'@ai-sdk/anthropic': '@ai-sdk/anthropic':
specifier: ^3.0.45 specifier: ^3.0.45
version: 3.0.46(zod@4.3.6) version: 3.0.58(zod@4.3.6)
'@ai-sdk/openai': '@ai-sdk/openai':
specifier: ^3.0.30 specifier: ^3.0.30
version: 3.0.31(zod@4.3.6) version: 3.0.41(zod@4.3.6)
'@ai-sdk/openai-compatible': '@ai-sdk/openai-compatible':
specifier: ^2.0.30 specifier: ^2.0.30
version: 2.0.30(zod@4.3.6) version: 2.0.35(zod@4.3.6)
'@base-ui/react': '@base-ui/react':
specifier: ^1.2.0 specifier: ^1.2.0
version: 1.2.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 1.2.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -40,13 +40,13 @@ importers:
version: 0.0.80 version: 0.0.80
'@tanstack/react-router': '@tanstack/react-router':
specifier: ^1.161.1 specifier: ^1.161.1
version: 1.162.9(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 1.166.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@uiw/react-codemirror': '@uiw/react-codemirror':
specifier: ^4.25.5 specifier: ^4.25.5
version: 4.25.5(@babel/runtime@7.28.6)(@codemirror/autocomplete@6.20.0)(@codemirror/language@6.12.2)(@codemirror/lint@6.9.4)(@codemirror/search@6.6.0)(@codemirror/state@6.5.4)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.39.15)(codemirror@6.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 4.25.7(@babel/runtime@7.28.6)(@codemirror/autocomplete@6.20.1)(@codemirror/language@6.12.2)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.5.4)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.39.16)(codemirror@6.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
ai: ai:
specifier: ^6.0.91 specifier: ^6.0.91
version: 6.0.97(zod@4.3.6) version: 6.0.116(zod@4.3.6)
class-variance-authority: class-variance-authority:
specifier: ^0.7.1 specifier: ^0.7.1
version: 0.7.1 version: 0.7.1
@@ -58,7 +58,7 @@ importers:
version: 1.11.19 version: 1.11.19
es-toolkit: es-toolkit:
specifier: ^1.44.0 specifier: ^1.44.0
version: 1.44.0 version: 1.45.1
fuse.js: fuse.js:
specifier: ^7.1.0 specifier: ^7.1.0
version: 7.1.0 version: 7.1.0
@@ -107,16 +107,19 @@ importers:
version: 0.0.12 version: 0.0.12
'@tailwindcss/vite': '@tailwindcss/vite':
specifier: ^4.2.0 specifier: ^4.2.0
version: 4.2.1(vite@8.0.0-beta.15(@types/node@25.3.0)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)) version: 4.2.1(vite@8.0.0-beta.16(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))
'@tanstack/react-query':
specifier: ^5.90.21
version: 5.90.21(react@19.2.4)
'@tanstack/react-router-devtools': '@tanstack/react-router-devtools':
specifier: ^1.161.1 specifier: ^1.161.1
version: 1.162.9(@tanstack/react-router@1.162.9(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.162.9)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 1.166.2(@tanstack/react-router@1.166.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.166.2)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/router-plugin': '@tanstack/router-plugin':
specifier: ^1.161.1 specifier: ^1.161.1
version: 1.162.9(@tanstack/react-router@1.162.9(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.15(@types/node@25.3.0)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)) version: 1.166.2(@tanstack/react-router@1.166.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.16(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))
'@types/node': '@types/node':
specifier: ^25.3.0 specifier: ^25.3.0
version: 25.3.0 version: 25.3.3
'@types/react': '@types/react':
specifier: ^19.2.14 specifier: ^19.2.14
version: 19.2.14 version: 19.2.14
@@ -125,7 +128,7 @@ importers:
version: 19.2.3(@types/react@19.2.14) version: 19.2.3(@types/react@19.2.14)
'@vitejs/plugin-react': '@vitejs/plugin-react':
specifier: ^5.1.4 specifier: ^5.1.4
version: 5.1.4(vite@8.0.0-beta.15(@types/node@25.3.0)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)) version: 5.1.4(vite@8.0.0-beta.16(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))
dotenv: dotenv:
specifier: ^17.3.1 specifier: ^17.3.1
version: 17.3.1 version: 17.3.1
@@ -143,36 +146,36 @@ importers:
version: 5.9.3 version: 5.9.3
vite: vite:
specifier: ^8.0.0-beta.14 specifier: ^8.0.0-beta.14
version: 8.0.0-beta.15(@types/node@25.3.0)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0) version: 8.0.0-beta.16(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)
packages: packages:
'@ai-sdk/anthropic@3.0.46': '@ai-sdk/anthropic@3.0.58':
resolution: {integrity: sha512-zXJPiNHaIiQ6XUqLeSYZ3ZbSzjqt1pNWEUf2hlkXlmmw8IF8KI0ruuGaDwKCExmtuNRf0E4TDxhsc9wRgWTzpw==} resolution: {integrity: sha512-/53SACgmVukO4bkms4dpxpRlYhW8Ct6QZRe6sj1Pi5H00hYhxIrqfiLbZBGxkdRvjsBQeP/4TVGsXgH5rQeb8Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4.1.8 zod: ^3.25.76 || ^4.1.8
'@ai-sdk/gateway@3.0.53': '@ai-sdk/gateway@3.0.66':
resolution: {integrity: sha512-QT3FEoNARMRlk8JJVR7L98exiK9C8AGfrEJVbRxBT1yIXKs/N19o/+PsjTRVsARgDJNcy9JbJp1FspKucEat0Q==} resolution: {integrity: sha512-SIQ0YY0iMuv+07HLsZ+bB990zUJ6S4ujORAh+Jv1V2KGNn73qQKnGO0JBk+w+Res8YqOFSycwDoWcFlQrVxS4A==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4.1.8 zod: ^3.25.76 || ^4.1.8
'@ai-sdk/openai-compatible@2.0.30': '@ai-sdk/openai-compatible@2.0.35':
resolution: {integrity: sha512-iTjumHf1/u4NhjXYFn/aONM2GId3/o7J1Lp5ql8FCbgIMyRwrmanR5xy1S3aaVkfTscuDvLTzWiy1mAbGzK3nQ==} resolution: {integrity: sha512-g3wA57IAQFb+3j4YuFndgkUdXyRETZVvbfAWM+UX7bZSxA3xjes0v3XKgIdKdekPtDGsh4ZX2byHD0gJIMPfiA==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4.1.8 zod: ^3.25.76 || ^4.1.8
'@ai-sdk/openai@3.0.31': '@ai-sdk/openai@3.0.41':
resolution: {integrity: sha512-61DmKNdwi2S83YZO80tCUibcOq0nNKa+vF9m+3VlD0b6bZ8FSe7GrO0bCCZaBeucu79OxWPx7Q1u0v3hxb91mQ==} resolution: {integrity: sha512-IZ42A+FO+vuEQCVNqlnAPYQnnUpUfdJIwn1BEDOBywiEHa23fw7PahxVtlX9zm3/zMvTW4JKPzWyvAgDu+SQ2A==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4.1.8 zod: ^3.25.76 || ^4.1.8
'@ai-sdk/provider-utils@4.0.15': '@ai-sdk/provider-utils@4.0.19':
resolution: {integrity: sha512-8XiKWbemmCbvNN0CLR9u3PQiet4gtEVIrX4zzLxnCj06AwsEDJwJVBbKrEI4t6qE8XRSIvU2irka0dcpziKW6w==} resolution: {integrity: sha512-3eG55CrSWCu2SXlqq2QCsFjo3+E7+Gmg7i/oRVoSZzIodTuDSfLb3MRje67xE9RFea73Zao7Lm4mADIfUETKGg==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4.1.8 zod: ^3.25.76 || ^4.1.8
@@ -301,8 +304,8 @@ packages:
'@types/react': '@types/react':
optional: true optional: true
'@codemirror/autocomplete@6.20.0': '@codemirror/autocomplete@6.20.1':
resolution: {integrity: sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg==} resolution: {integrity: sha512-1cvg3Vz1dSSToCNlJfRA2WSI4ht3K+WplO0UMOgmUYPivCyy2oueZY6Lx7M9wThm7SDUBViRmuT+OG/i8+ON9A==}
'@codemirror/commands@6.10.2': '@codemirror/commands@6.10.2':
resolution: {integrity: sha512-vvX1fsih9HledO1c9zdotZYUZnE4xV0m6i3m25s5DIfXofuprk6cRcLUZvSk3CASUbwjQX21tOGbkY2BH8TpnQ==} resolution: {integrity: sha512-vvX1fsih9HledO1c9zdotZYUZnE4xV0m6i3m25s5DIfXofuprk6cRcLUZvSk3CASUbwjQX21tOGbkY2BH8TpnQ==}
@@ -313,8 +316,8 @@ packages:
'@codemirror/language@6.12.2': '@codemirror/language@6.12.2':
resolution: {integrity: sha512-jEPmz2nGGDxhRTg3lTpzmIyGKxz3Gp3SJES4b0nAuE5SWQoKdT5GoQ69cwMmFd+wvFUhYirtDTr0/DRHpQAyWg==} resolution: {integrity: sha512-jEPmz2nGGDxhRTg3lTpzmIyGKxz3Gp3SJES4b0nAuE5SWQoKdT5GoQ69cwMmFd+wvFUhYirtDTr0/DRHpQAyWg==}
'@codemirror/lint@6.9.4': '@codemirror/lint@6.9.5':
resolution: {integrity: sha512-ABc9vJ8DEmvOWuH26P3i8FpMWPQkduD9Rvba5iwb6O3hxASgclm3T3krGo8NASXkHCidz6b++LWlzWIUfEPSWw==} resolution: {integrity: sha512-GElsbU9G7QT9xXhpUg1zWGmftA/7jamh+7+ydKRuT0ORpWS3wOSP0yT1FOlIZa7mIJjpVPipErsyvVqB9cfTFA==}
'@codemirror/search@6.6.0': '@codemirror/search@6.6.0':
resolution: {integrity: sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==} resolution: {integrity: sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==}
@@ -325,8 +328,8 @@ packages:
'@codemirror/theme-one-dark@6.1.3': '@codemirror/theme-one-dark@6.1.3':
resolution: {integrity: sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==} resolution: {integrity: sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==}
'@codemirror/view@6.39.15': '@codemirror/view@6.39.16':
resolution: {integrity: sha512-aCWjgweIIXLBHh7bY6cACvXuyrZ0xGafjQ2VInjp4RM4gMfscK5uESiNdrH0pE+e1lZr2B4ONGsjchl2KsKZzg==} resolution: {integrity: sha512-m6S22fFpKtOWhq8HuhzsI1WzUP/hB9THbDj0Tl5KX4gbO6Y91hwBl7Yky33NdvB6IffuRFiBxf1R8kJMyXmA4Q==}
'@emnapi/core@1.8.1': '@emnapi/core@1.8.1':
resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==}
@@ -604,94 +607,94 @@ packages:
resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
engines: {node: '>=8.0.0'} engines: {node: '>=8.0.0'}
'@oxc-project/runtime@0.114.0': '@oxc-project/runtime@0.115.0':
resolution: {integrity: sha512-mVGQvr/uFJGQ3hsvgQ1sJfh79t5owyZZZtw+VaH+WhtvsmtgjT6imznB9sz2Q67Q0/4obM9mOOtQscU4aJteSg==} resolution: {integrity: sha512-Rg8Wlt5dCbXhQnsXPrkOjL1DTSvXLgb2R/KYfnf1/K+R0k6UMLEmbQXPM+kwrWqSmWA2t0B1EtHy2/3zikQpvQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
'@oxc-project/types@0.114.0': '@oxc-project/types@0.115.0':
resolution: {integrity: sha512-//nBfbzHQHvJs8oFIjv6coZ6uxQ4alLfiPe6D5vit6c4pmxATHHlVwgB1k+Hv4yoAMyncdxgRBF5K4BYWUCzvA==} resolution: {integrity: sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw==}
'@paralleldrive/cuid2@3.3.0': '@paralleldrive/cuid2@3.3.0':
resolution: {integrity: sha512-OqiFvSOF0dBSesELYY2CAMa4YINvlLpvKOz/rv6NeZEqiyttlHgv98Juwv4Ch+GrEV7IZ8jfI2VcEoYUjXXCjw==} resolution: {integrity: sha512-OqiFvSOF0dBSesELYY2CAMa4YINvlLpvKOz/rv6NeZEqiyttlHgv98Juwv4Ch+GrEV7IZ8jfI2VcEoYUjXXCjw==}
hasBin: true hasBin: true
'@rolldown/binding-android-arm64@1.0.0-rc.5': '@rolldown/binding-android-arm64@1.0.0-rc.6':
resolution: {integrity: sha512-zCEmUrt1bggwgBgeKLxNj217J1OrChrp3jJt24VK9jAharSTeVaHODNL+LpcQVhRz+FktYWfT9cjo5oZ99ZLpg==} resolution: {integrity: sha512-kvjTSWGcrv+BaR2vge57rsKiYdVR8V8CoS0vgKrc570qRBfty4bT+1X0z3j2TaVV+kAYzA0PjeB9+mdZyqUZlg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@rolldown/binding-darwin-arm64@1.0.0-rc.5': '@rolldown/binding-darwin-arm64@1.0.0-rc.6':
resolution: {integrity: sha512-ZP9xb9lPAex36pvkNWCjSEJW/Gfdm9I3ssiqOFLmpZ/vosPXgpoGxCmh+dX1Qs+/bWQE6toNFXWWL8vYoKoK9Q==} resolution: {integrity: sha512-+tJhD21KvGNtUrpLXrZQlT+j5HZKiEwR2qtcZb3vNOUpvoT9QjEykr75ZW/Kr0W89gose/HVXU6351uVZD8Qvw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@rolldown/binding-darwin-x64@1.0.0-rc.5': '@rolldown/binding-darwin-x64@1.0.0-rc.6':
resolution: {integrity: sha512-7IdrPunf6dp9mywMgTOKMMGDnMHQ6+h5gRl6LW8rhD8WK2kXX0IwzcM5Zc0B5J7xQs8QWOlKjv8BJsU/1CD3pg==} resolution: {integrity: sha512-DKNhjMk38FAWaHwUt1dFR3rA/qRAvn2NUvSG2UGvxvlMxSmN/qqww/j4ABAbXhNRXtGQNmrAINMXRuwHl16ZHg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@rolldown/binding-freebsd-x64@1.0.0-rc.5': '@rolldown/binding-freebsd-x64@1.0.0-rc.6':
resolution: {integrity: sha512-o/JCk+dL0IN68EBhZ4DqfsfvxPfMeoM6cJtxORC1YYoxGHZyth2Kb2maXDb4oddw2wu8iIbnYXYPEzBtAF5CAg==} resolution: {integrity: sha512-8TThsRkCPAnfyMBShxrGdtoOE6h36QepqRQI97iFaQSCRbHFWHcDHppcojZnzXoruuhPnjMEygzaykvPVJsMRg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.5': '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.6':
resolution: {integrity: sha512-IIBwTtA6VwxQLcEgq2mfrUgam7VvPZjhd/jxmeS1npM+edWsrrpRLHUdze+sk4rhb8/xpP3flemgcZXXUW6ukw==} resolution: {integrity: sha512-ZfmFoOwPUZCWtGOVC9/qbQzfc0249FrRUOzV2XabSMUV60Crp211OWLQN1zmQAsRIVWRcEwhJ46Z1mXGo/L/nQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@rolldown/binding-linux-arm64-gnu@1.0.0-rc.5': '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.6':
resolution: {integrity: sha512-KSol1De1spMZL+Xg7K5IBWXIvRWv7+pveaxFWXpezezAG7CS6ojzRjtCGCiLxQricutTAi/LkNWKMsd2wNhMKQ==} resolution: {integrity: sha512-ZsGzbNETxPodGlLTYHaCSGVhNN/rvkMDCJYHdT7PZr5jFJRmBfmDi2awhF64Dt2vxrJqY6VeeYSgOzEbHRsb7Q==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@rolldown/binding-linux-arm64-musl@1.0.0-rc.5': '@rolldown/binding-linux-arm64-musl@1.0.0-rc.6':
resolution: {integrity: sha512-WFljyDkxtXRlWxMjxeegf7xMYXxUr8u7JdXlOEWKYgDqEgxUnSEsVDxBiNWQ1D5kQKwf8Wo4sVKEYPRhCdsjwA==} resolution: {integrity: sha512-elPpdevtCdUOqziemR86C4CSCr/5sUxalzDrf/CJdMT+kZt2C556as++qHikNOz0vuFf52h+GJNXZM08eWgGPQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@rolldown/binding-linux-x64-gnu@1.0.0-rc.5': '@rolldown/binding-linux-x64-gnu@1.0.0-rc.6':
resolution: {integrity: sha512-CUlplTujmbDWp2gamvrqVKi2Or8lmngXT1WxsizJfts7JrvfGhZObciaY/+CbdbS9qNnskvwMZNEhTPrn7b+WA==} resolution: {integrity: sha512-IBwXsf56o3xhzAyaZxdM1CX8UFiBEUFCjiVUgny67Q8vPIqkjzJj0YKhd3TbBHanuxThgBa59f6Pgutg2OGk5A==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@rolldown/binding-linux-x64-musl@1.0.0-rc.5': '@rolldown/binding-linux-x64-musl@1.0.0-rc.6':
resolution: {integrity: sha512-wdf7g9NbVZCeAo2iGhsjJb7I8ZFfs6X8bumfrWg82VK+8P6AlLXwk48a1ASiJQDTS7Svq2xVzZg3sGO2aXpHRA==} resolution: {integrity: sha512-vOk7G8V9Zm+8a6PL6JTpCea61q491oYlGtO6CvnsbhNLlKdf0bbCPytFzGQhYmCKZDKkEbmnkcIprTEGCURnwg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@rolldown/binding-openharmony-arm64@1.0.0-rc.5': '@rolldown/binding-openharmony-arm64@1.0.0-rc.6':
resolution: {integrity: sha512-0CWY7ubu12nhzz+tkpHjoG3IRSTlWYe0wrfJRf4qqjqQSGtAYgoL9kwzdvlhaFdZ5ffVeyYw9qLsChcjUMEloQ==} resolution: {integrity: sha512-ASjEDI4MRv7XCQb2JVaBzfEYO98JKCGrAgoW6M03fJzH/ilCnC43Mb3ptB9q/lzsaahoJyIBoAGKAYEjUvpyvQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [openharmony] os: [openharmony]
'@rolldown/binding-wasm32-wasi@1.0.0-rc.5': '@rolldown/binding-wasm32-wasi@1.0.0-rc.6':
resolution: {integrity: sha512-LztXnGzv6t2u830mnZrFLRVqT/DPJ9DL4ZTz/y93rqUVkeHjMMYIYaFj+BUthiYxbVH9dH0SZYufETspKY/NhA==} resolution: {integrity: sha512-mYa1+h2l6Zc0LvmwUh0oXKKYihnw/1WC73vTqw+IgtfEtv47A+rWzzcWwVDkW73+UDr0d/Ie/HRXoaOY22pQDw==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
cpu: [wasm32] cpu: [wasm32]
'@rolldown/binding-win32-arm64-msvc@1.0.0-rc.5': '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.6':
resolution: {integrity: sha512-jUct1XVeGtyjqJXEAfvdFa8xoigYZ2rge7nYEm70ppQxpfH9ze2fbIrpHmP2tNM2vL/F6Dd0CpXhpjPbC6bSxQ==} resolution: {integrity: sha512-e2ABskbNH3MRUBMjgxaMjYIw11DSwjLJxBII3UgpF6WClGLIh8A20kamc+FKH5vIaFVnYQInmcLYSUVpqMPLow==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@rolldown/binding-win32-x64-msvc@1.0.0-rc.5': '@rolldown/binding-win32-x64-msvc@1.0.0-rc.6':
resolution: {integrity: sha512-VQ8F9ld5gw29epjnVGdrx8ugiLTe8BMqmhDYy7nGbdeDo4HAt4bgdZvLbViEhg7DZyHLpiEUlO5/jPSUrIuxRQ==} resolution: {integrity: sha512-dJVc3ifhaRXxIEh1xowLohzFrlQXkJ66LepHm+CmSprTWgVrPa8Fx3OL57xwIqDEH9hufcKkDX2v65rS3NZyRA==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
@@ -699,8 +702,8 @@ packages:
'@rolldown/pluginutils@1.0.0-rc.3': '@rolldown/pluginutils@1.0.0-rc.3':
resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==}
'@rolldown/pluginutils@1.0.0-rc.5': '@rolldown/pluginutils@1.0.0-rc.6':
resolution: {integrity: sha512-RxlLX/DPoarZ9PtxVrQgZhPoor987YtKQqCo5zkjX+0S0yLJ7Vv515Wk6+xtTL67VONKJKxETWZwuZjss2idYw==} resolution: {integrity: sha512-Y0+JT8Mi1mmW08K6HieG315XNRu4L0rkfCpA364HtytjgiqYnMYRdFPcxRl+BQQqNXzecL2S9nii+RUpO93XIA==}
'@standard-schema/spec@1.1.0': '@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
@@ -803,20 +806,28 @@ packages:
resolution: {integrity: sha512-Kp/WSt411ZWYvgXy6uiv5RmhHrz9cAml05AQPrtdAp7eUqvIDbMGPnML25OKbzR3RJ1q4wgENxDTvlGPa9+Mww==} resolution: {integrity: sha512-Kp/WSt411ZWYvgXy6uiv5RmhHrz9cAml05AQPrtdAp7eUqvIDbMGPnML25OKbzR3RJ1q4wgENxDTvlGPa9+Mww==}
engines: {node: '>=20.19'} engines: {node: '>=20.19'}
'@tanstack/react-router-devtools@1.162.9': '@tanstack/query-core@5.90.20':
resolution: {integrity: sha512-8xDqykw8MYWj4JoNfiJR/ZnocRBlfFeDSOQWVoWlnZKlciLCJ9dVfXuXQJlDlWr3JdmsWyyRvruZBnYr1YlUcg==} resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==}
'@tanstack/react-query@5.90.21':
resolution: {integrity: sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg==}
peerDependencies:
react: ^18 || ^19
'@tanstack/react-router-devtools@1.166.2':
resolution: {integrity: sha512-EQhFQRArwxS0OjIWWGD5wfNboJq7rIYCbioHvepgbxgblKtNLWnRr3LFj34QhXTP1aQsPYb9t8+VTi3VbFuAfA==}
engines: {node: '>=20.19'} engines: {node: '>=20.19'}
peerDependencies: peerDependencies:
'@tanstack/react-router': ^1.162.9 '@tanstack/react-router': ^1.166.2
'@tanstack/router-core': ^1.162.9 '@tanstack/router-core': ^1.166.2
react: '>=18.0.0 || >=19.0.0' react: '>=18.0.0 || >=19.0.0'
react-dom: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0'
peerDependenciesMeta: peerDependenciesMeta:
'@tanstack/router-core': '@tanstack/router-core':
optional: true optional: true
'@tanstack/react-router@1.162.9': '@tanstack/react-router@1.166.2':
resolution: {integrity: sha512-APbwKAF+YgSNpHAaA+FdgrmfI/7+qa9hApuVO9+P0IVksJayNIWFQ/6AFG90WQiTYWk64RI1R9cFV2K9Z+j2pQ==} resolution: {integrity: sha512-pKhUtrvVLlhjWhsHkJSuIzh1J4LcP+8ErbIqRLORX9Js8dUFMKoT0+8oFpi+P8QRpuhm/7rzjYiWfcyTsqQZtA==}
engines: {node: '>=20.19'} engines: {node: '>=20.19'}
peerDependencies: peerDependencies:
react: '>=18.0.0 || >=19.0.0' react: '>=18.0.0 || >=19.0.0'
@@ -828,30 +839,30 @@ packages:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 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 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
'@tanstack/router-core@1.162.9': '@tanstack/router-core@1.166.2':
resolution: {integrity: sha512-eG7C0oVtZbFOkfvsaF8UyGuNjEc1BfIfD5EzQNwG4vqLKOAyY5SMFBCNjabAi2sglRhL0ZOwKon1SExusU5fxA==} resolution: {integrity: sha512-zn3NhENOAX9ToQiX077UV2OH3aJKOvV2ZMNZZxZ3gDG3i3WqL8NfWfEgetEAfMN37/Mnt90PpotYgf7IyuoKqQ==}
engines: {node: '>=20.19'} engines: {node: '>=20.19'}
'@tanstack/router-devtools-core@1.162.9': '@tanstack/router-devtools-core@1.166.2':
resolution: {integrity: sha512-fX54Aub/mS9KVrWy/CSe5+vu/pSez45RojzBZYK4KLMA8HsTxQ4/jjBfHwGg6FaqXKL52b72f4BAB+Cx559rIA==} resolution: {integrity: sha512-Ke8HquuwMhLYpo/6nxNgrzi9Ns2lsK9uwDba6WKA8I0K7fyYZoAUu+7AD6gdEcVU4NF6LjtMPfUCHmVtYYRTDw==}
engines: {node: '>=20.19'} engines: {node: '>=20.19'}
peerDependencies: peerDependencies:
'@tanstack/router-core': ^1.162.9 '@tanstack/router-core': ^1.166.2
csstype: ^3.0.10 csstype: ^3.0.10
peerDependenciesMeta: peerDependenciesMeta:
csstype: csstype:
optional: true optional: true
'@tanstack/router-generator@1.162.9': '@tanstack/router-generator@1.166.2':
resolution: {integrity: sha512-yVYFL/b0hRNRDTJn7+k/BEgRICIV064G2aAkvioRx2apYaMaDvWPAYSSFkNM/4etA+J16ATMhK30513glQmVug==} resolution: {integrity: sha512-wbvdyP1PKKQKk4aVlGeK9S5uDy8zodTr3tEZ2gRKNavJLusXbEWqtoo42JxHFFNB6dtguehFMt8PyZPAtkgWwQ==}
engines: {node: '>=20.19'} engines: {node: '>=20.19'}
'@tanstack/router-plugin@1.162.9': '@tanstack/router-plugin@1.166.2':
resolution: {integrity: sha512-RnvDntkf4d8YxuG0zxqb9BqLnDhbCjpyzOAG/Jw9AV3d0kih0UcTbAZCzfoDAiGMuztOsAWMyiVXcoy5LnPKag==} resolution: {integrity: sha512-TnyV/7//Vp5fR49mmNbOWHGz9IJTm1lqVxzPdtpzg7D5PjkW2HFmLFLtWwpJgz2R7AJJWR4Ge5kIPmC+fVZ6eQ==}
engines: {node: '>=20.19'} engines: {node: '>=20.19'}
peerDependencies: peerDependencies:
'@rsbuild/core': '>=1.0.2' '@rsbuild/core': '>=1.0.2'
'@tanstack/react-router': ^1.162.9 '@tanstack/react-router': ^1.166.2
vite: '>=5.0.0 || >=6.0.0 || >=7.0.0' vite: '>=5.0.0 || >=6.0.0 || >=7.0.0'
vite-plugin-solid: ^2.11.10 vite-plugin-solid: ^2.11.10
webpack: '>=5.92.0' webpack: '>=5.92.0'
@@ -893,8 +904,8 @@ packages:
'@types/babel__traverse@7.28.0': '@types/babel__traverse@7.28.0':
resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
'@types/node@25.3.0': '@types/node@25.3.3':
resolution: {integrity: sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A==} resolution: {integrity: sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==}
'@types/react-dom@19.2.3': '@types/react-dom@19.2.3':
resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
@@ -904,8 +915,8 @@ packages:
'@types/react@19.2.14': '@types/react@19.2.14':
resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==}
'@uiw/codemirror-extensions-basic-setup@4.25.5': '@uiw/codemirror-extensions-basic-setup@4.25.7':
resolution: {integrity: sha512-2KWS4NqrS9SQzlPs/3sxFhuArvjB3JF6WpsrZqBtGHM5/smCNTULX3lUGeRH+f3mkfMt0k6DR+q0xCW9k+Up5w==} resolution: {integrity: sha512-tPV/AGjF4yM22D5mnyH7EuYBkWO05wF5Y4x3lmQJo6LuHmhjh0RQsVDjqeIgNOkXT3UO9OdkL4dzxw465/JZVg==}
peerDependencies: peerDependencies:
'@codemirror/autocomplete': '>=6.0.0' '@codemirror/autocomplete': '>=6.0.0'
'@codemirror/commands': '>=6.0.0' '@codemirror/commands': '>=6.0.0'
@@ -915,8 +926,8 @@ packages:
'@codemirror/state': '>=6.0.0' '@codemirror/state': '>=6.0.0'
'@codemirror/view': '>=6.0.0' '@codemirror/view': '>=6.0.0'
'@uiw/react-codemirror@4.25.5': '@uiw/react-codemirror@4.25.7':
resolution: {integrity: sha512-WUMBGwfstufdbnaiMzQzmOf+6Mzf0IbiOoleexC9ItWcDTJybidLtEi20aP2N58Wn/AQxsd5Otebydaimh7Opw==} resolution: {integrity: sha512-s/EbEe0dFANWEgfLbfdIrrOGv0R7M1XhkKG3ShroBeH6uP9pVNQy81YHOLRCSVcytTp9zAWRNfXR/+XxZTvV7w==}
peerDependencies: peerDependencies:
'@babel/runtime': '>=7.11.0' '@babel/runtime': '>=7.11.0'
'@codemirror/state': '>=6.0.0' '@codemirror/state': '>=6.0.0'
@@ -936,13 +947,13 @@ packages:
peerDependencies: peerDependencies:
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
acorn@8.16.0: acorn@8.15.0:
resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
hasBin: true hasBin: true
ai@6.0.97: ai@6.0.116:
resolution: {integrity: sha512-eZIAcBymwGhBwncRH/v9pillZNMeRCDkc4BwcvwXerXd7sxjVxRis3ZNCNCpP02pVH4NLs81ljm4cElC4vbNcQ==} resolution: {integrity: sha512-7yM+cTmyRLeNIXwt4Vj+mrrJgVQ9RMIW5WO0ydoLoYkewIvsMcvUmqS4j2RJTUXaF1HphwmSKUMQ/HypNRGOmA==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4.1.8 zod: ^3.25.76 || ^4.1.8
@@ -962,9 +973,8 @@ packages:
babel-dead-code-elimination@1.0.12: babel-dead-code-elimination@1.0.12:
resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==} resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==}
baseline-browser-mapping@2.10.0: baseline-browser-mapping@2.9.19:
resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==} resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==}
engines: {node: '>=6.0.0'}
hasBin: true hasBin: true
bignumber.js@9.3.1: bignumber.js@9.3.1:
@@ -983,8 +993,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true hasBin: true
caniuse-lite@1.0.30001774: caniuse-lite@1.0.30001770:
resolution: {integrity: sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA==} resolution: {integrity: sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==}
chokidar@3.6.0: chokidar@3.6.0:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
@@ -1052,8 +1062,8 @@ packages:
resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==}
engines: {node: '>=12'} engines: {node: '>=12'}
electron-to-chromium@1.5.302: electron-to-chromium@1.5.286:
resolution: {integrity: sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==} resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==}
enhanced-resolve@5.19.0: enhanced-resolve@5.19.0:
resolution: {integrity: sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==} resolution: {integrity: sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==}
@@ -1062,8 +1072,8 @@ packages:
error-causes@3.0.2: error-causes@3.0.2:
resolution: {integrity: sha512-i0B8zq1dHL6mM85FGoxaJnVtx6LD5nL2v0hlpGdntg5FOSyzQ46c9lmz5qx0xRS2+PWHGOHcYxGIBC5Le2dRMw==} resolution: {integrity: sha512-i0B8zq1dHL6mM85FGoxaJnVtx6LD5nL2v0hlpGdntg5FOSyzQ46c9lmz5qx0xRS2+PWHGOHcYxGIBC5Le2dRMw==}
es-toolkit@1.44.0: es-toolkit@1.45.1:
resolution: {integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==} resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==}
esbuild@0.27.3: esbuild@0.27.3:
resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==}
@@ -1366,8 +1376,8 @@ packages:
resolve-pkg-maps@1.0.0: resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
rolldown@1.0.0-rc.5: rolldown@1.0.0-rc.6:
resolution: {integrity: sha512-0AdalTs6hNTioaCYIkAa7+xsmHBfU5hCNclZnM/lp7lGGDuUOb6N4BVNtwiomybbencDjq/waKjTImqiGCs5sw==} resolution: {integrity: sha512-B8vFPV1ADyegoYfhg+E7RAucYKv0xdVlwYYsIJgfPNeiSxZGWNxts9RqhyGzC11ULK/VaeXyKezGCwpMiH8Ktw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true hasBin: true
@@ -1541,8 +1551,8 @@ packages:
peerDependencies: peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
vite@8.0.0-beta.15: vite@8.0.0-beta.16:
resolution: {integrity: sha512-RHX7IvsJlEfjyA1rS7MY0UsmF91etdLAamslHR5lfuO3W/BXRdXm2tRE64ztpSPZbKqB4wAAZ0AwtF6QzfKZLA==} resolution: {integrity: sha512-c0t7hYkxsjws89HH+BUFh/sL3BpPNhNsL9CJrTpMxBmwKQBRSa5OJ5w4o9O0bQVI/H/vx7UpUUIevvXa37NS/Q==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
@@ -1619,32 +1629,32 @@ packages:
snapshots: snapshots:
'@ai-sdk/anthropic@3.0.46(zod@4.3.6)': '@ai-sdk/anthropic@3.0.58(zod@4.3.6)':
dependencies: dependencies:
'@ai-sdk/provider': 3.0.8 '@ai-sdk/provider': 3.0.8
'@ai-sdk/provider-utils': 4.0.15(zod@4.3.6) '@ai-sdk/provider-utils': 4.0.19(zod@4.3.6)
zod: 4.3.6 zod: 4.3.6
'@ai-sdk/gateway@3.0.53(zod@4.3.6)': '@ai-sdk/gateway@3.0.66(zod@4.3.6)':
dependencies: dependencies:
'@ai-sdk/provider': 3.0.8 '@ai-sdk/provider': 3.0.8
'@ai-sdk/provider-utils': 4.0.15(zod@4.3.6) '@ai-sdk/provider-utils': 4.0.19(zod@4.3.6)
'@vercel/oidc': 3.1.0 '@vercel/oidc': 3.1.0
zod: 4.3.6 zod: 4.3.6
'@ai-sdk/openai-compatible@2.0.30(zod@4.3.6)': '@ai-sdk/openai-compatible@2.0.35(zod@4.3.6)':
dependencies: dependencies:
'@ai-sdk/provider': 3.0.8 '@ai-sdk/provider': 3.0.8
'@ai-sdk/provider-utils': 4.0.15(zod@4.3.6) '@ai-sdk/provider-utils': 4.0.19(zod@4.3.6)
zod: 4.3.6 zod: 4.3.6
'@ai-sdk/openai@3.0.31(zod@4.3.6)': '@ai-sdk/openai@3.0.41(zod@4.3.6)':
dependencies: dependencies:
'@ai-sdk/provider': 3.0.8 '@ai-sdk/provider': 3.0.8
'@ai-sdk/provider-utils': 4.0.15(zod@4.3.6) '@ai-sdk/provider-utils': 4.0.19(zod@4.3.6)
zod: 4.3.6 zod: 4.3.6
'@ai-sdk/provider-utils@4.0.15(zod@4.3.6)': '@ai-sdk/provider-utils@4.0.19(zod@4.3.6)':
dependencies: dependencies:
'@ai-sdk/provider': 3.0.8 '@ai-sdk/provider': 3.0.8
'@standard-schema/spec': 1.1.0 '@standard-schema/spec': 1.1.0
@@ -1803,23 +1813,23 @@ snapshots:
optionalDependencies: optionalDependencies:
'@types/react': 19.2.14 '@types/react': 19.2.14
'@codemirror/autocomplete@6.20.0': '@codemirror/autocomplete@6.20.1':
dependencies: dependencies:
'@codemirror/language': 6.12.2 '@codemirror/language': 6.12.2
'@codemirror/state': 6.5.4 '@codemirror/state': 6.5.4
'@codemirror/view': 6.39.15 '@codemirror/view': 6.39.16
'@lezer/common': 1.5.1 '@lezer/common': 1.5.1
'@codemirror/commands@6.10.2': '@codemirror/commands@6.10.2':
dependencies: dependencies:
'@codemirror/language': 6.12.2 '@codemirror/language': 6.12.2
'@codemirror/state': 6.5.4 '@codemirror/state': 6.5.4
'@codemirror/view': 6.39.15 '@codemirror/view': 6.39.16
'@lezer/common': 1.5.1 '@lezer/common': 1.5.1
'@codemirror/lang-yaml@6.1.2': '@codemirror/lang-yaml@6.1.2':
dependencies: dependencies:
'@codemirror/autocomplete': 6.20.0 '@codemirror/autocomplete': 6.20.1
'@codemirror/language': 6.12.2 '@codemirror/language': 6.12.2
'@codemirror/state': 6.5.4 '@codemirror/state': 6.5.4
'@lezer/common': 1.5.1 '@lezer/common': 1.5.1
@@ -1830,22 +1840,22 @@ snapshots:
'@codemirror/language@6.12.2': '@codemirror/language@6.12.2':
dependencies: dependencies:
'@codemirror/state': 6.5.4 '@codemirror/state': 6.5.4
'@codemirror/view': 6.39.15 '@codemirror/view': 6.39.16
'@lezer/common': 1.5.1 '@lezer/common': 1.5.1
'@lezer/highlight': 1.2.3 '@lezer/highlight': 1.2.3
'@lezer/lr': 1.4.8 '@lezer/lr': 1.4.8
style-mod: 4.1.3 style-mod: 4.1.3
'@codemirror/lint@6.9.4': '@codemirror/lint@6.9.5':
dependencies: dependencies:
'@codemirror/state': 6.5.4 '@codemirror/state': 6.5.4
'@codemirror/view': 6.39.15 '@codemirror/view': 6.39.16
crelt: 1.0.6 crelt: 1.0.6
'@codemirror/search@6.6.0': '@codemirror/search@6.6.0':
dependencies: dependencies:
'@codemirror/state': 6.5.4 '@codemirror/state': 6.5.4
'@codemirror/view': 6.39.15 '@codemirror/view': 6.39.16
crelt: 1.0.6 crelt: 1.0.6
'@codemirror/state@6.5.4': '@codemirror/state@6.5.4':
@@ -1856,10 +1866,10 @@ snapshots:
dependencies: dependencies:
'@codemirror/language': 6.12.2 '@codemirror/language': 6.12.2
'@codemirror/state': 6.5.4 '@codemirror/state': 6.5.4
'@codemirror/view': 6.39.15 '@codemirror/view': 6.39.16
'@lezer/highlight': 1.2.3 '@lezer/highlight': 1.2.3
'@codemirror/view@6.39.15': '@codemirror/view@6.39.16':
dependencies: dependencies:
'@codemirror/state': 6.5.4 '@codemirror/state': 6.5.4
crelt: 1.0.6 crelt: 1.0.6
@@ -2002,7 +2012,7 @@ snapshots:
'@kevisual/js-filter': 0.0.5 '@kevisual/js-filter': 0.0.5
'@kevisual/load': 0.0.6 '@kevisual/load': 0.0.6
'@paralleldrive/cuid2': 3.3.0 '@paralleldrive/cuid2': 3.3.0
es-toolkit: 1.44.0 es-toolkit: 1.45.1
eventemitter3: 5.0.4 eventemitter3: 5.0.4
fuse.js: 7.1.0 fuse.js: 7.1.0
nanoid: 5.1.6 nanoid: 5.1.6
@@ -2051,7 +2061,7 @@ snapshots:
'@kevisual/query': 0.0.40 '@kevisual/query': 0.0.40
'@kevisual/router': 0.0.70 '@kevisual/router': 0.0.70
'@kevisual/use-config': 1.0.30(dotenv@17.3.1) '@kevisual/use-config': 1.0.30(dotenv@17.3.1)
es-toolkit: 1.44.0 es-toolkit: 1.45.1
nanoid: 5.1.6 nanoid: 5.1.6
unstorage: 1.17.4(idb-keyval@6.2.2) unstorage: 1.17.4(idb-keyval@6.2.2)
ws: '@kevisual/ws@8.19.0' ws: '@kevisual/ws@8.19.0'
@@ -2083,7 +2093,7 @@ snapshots:
'@kevisual/query': 0.0.40 '@kevisual/query': 0.0.40
'@kevisual/router': 0.0.70 '@kevisual/router': 0.0.70
'@kevisual/use-config': 1.0.30(dotenv@17.3.1) '@kevisual/use-config': 1.0.30(dotenv@17.3.1)
es-toolkit: 1.44.0 es-toolkit: 1.45.1
nanoid: 5.1.6 nanoid: 5.1.6
unstorage: 1.17.4(idb-keyval@6.2.2) unstorage: 1.17.4(idb-keyval@6.2.2)
ws: '@kevisual/ws@8.19.0' ws: '@kevisual/ws@8.19.0'
@@ -2132,11 +2142,11 @@ snapshots:
'@kevisual/router@0.0.70': '@kevisual/router@0.0.70':
dependencies: dependencies:
es-toolkit: 1.44.0 es-toolkit: 1.45.1
'@kevisual/router@0.0.80': '@kevisual/router@0.0.80':
dependencies: dependencies:
es-toolkit: 1.44.0 es-toolkit: 1.45.1
'@kevisual/types@0.0.12': {} '@kevisual/types@0.0.12': {}
@@ -2176,9 +2186,9 @@ snapshots:
'@opentelemetry/api@1.9.0': {} '@opentelemetry/api@1.9.0': {}
'@oxc-project/runtime@0.114.0': {} '@oxc-project/runtime@0.115.0': {}
'@oxc-project/types@0.114.0': {} '@oxc-project/types@0.115.0': {}
'@paralleldrive/cuid2@3.3.0': '@paralleldrive/cuid2@3.3.0':
dependencies: dependencies:
@@ -2186,50 +2196,50 @@ snapshots:
bignumber.js: 9.3.1 bignumber.js: 9.3.1
error-causes: 3.0.2 error-causes: 3.0.2
'@rolldown/binding-android-arm64@1.0.0-rc.5': '@rolldown/binding-android-arm64@1.0.0-rc.6':
optional: true optional: true
'@rolldown/binding-darwin-arm64@1.0.0-rc.5': '@rolldown/binding-darwin-arm64@1.0.0-rc.6':
optional: true optional: true
'@rolldown/binding-darwin-x64@1.0.0-rc.5': '@rolldown/binding-darwin-x64@1.0.0-rc.6':
optional: true optional: true
'@rolldown/binding-freebsd-x64@1.0.0-rc.5': '@rolldown/binding-freebsd-x64@1.0.0-rc.6':
optional: true optional: true
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.5': '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.6':
optional: true optional: true
'@rolldown/binding-linux-arm64-gnu@1.0.0-rc.5': '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.6':
optional: true optional: true
'@rolldown/binding-linux-arm64-musl@1.0.0-rc.5': '@rolldown/binding-linux-arm64-musl@1.0.0-rc.6':
optional: true optional: true
'@rolldown/binding-linux-x64-gnu@1.0.0-rc.5': '@rolldown/binding-linux-x64-gnu@1.0.0-rc.6':
optional: true optional: true
'@rolldown/binding-linux-x64-musl@1.0.0-rc.5': '@rolldown/binding-linux-x64-musl@1.0.0-rc.6':
optional: true optional: true
'@rolldown/binding-openharmony-arm64@1.0.0-rc.5': '@rolldown/binding-openharmony-arm64@1.0.0-rc.6':
optional: true optional: true
'@rolldown/binding-wasm32-wasi@1.0.0-rc.5': '@rolldown/binding-wasm32-wasi@1.0.0-rc.6':
dependencies: dependencies:
'@napi-rs/wasm-runtime': 1.1.1 '@napi-rs/wasm-runtime': 1.1.1
optional: true optional: true
'@rolldown/binding-win32-arm64-msvc@1.0.0-rc.5': '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.6':
optional: true optional: true
'@rolldown/binding-win32-x64-msvc@1.0.0-rc.5': '@rolldown/binding-win32-x64-msvc@1.0.0-rc.6':
optional: true optional: true
'@rolldown/pluginutils@1.0.0-rc.3': {} '@rolldown/pluginutils@1.0.0-rc.3': {}
'@rolldown/pluginutils@1.0.0-rc.5': {} '@rolldown/pluginutils@1.0.0-rc.6': {}
'@standard-schema/spec@1.1.0': {} '@standard-schema/spec@1.1.0': {}
@@ -2294,31 +2304,38 @@ snapshots:
'@tailwindcss/oxide-win32-arm64-msvc': 4.2.1 '@tailwindcss/oxide-win32-arm64-msvc': 4.2.1
'@tailwindcss/oxide-win32-x64-msvc': 4.2.1 '@tailwindcss/oxide-win32-x64-msvc': 4.2.1
'@tailwindcss/vite@4.2.1(vite@8.0.0-beta.15(@types/node@25.3.0)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))': '@tailwindcss/vite@4.2.1(vite@8.0.0-beta.16(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))':
dependencies: dependencies:
'@tailwindcss/node': 4.2.1 '@tailwindcss/node': 4.2.1
'@tailwindcss/oxide': 4.2.1 '@tailwindcss/oxide': 4.2.1
tailwindcss: 4.2.1 tailwindcss: 4.2.1
vite: 8.0.0-beta.15(@types/node@25.3.0)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0) vite: 8.0.0-beta.16(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)
'@tanstack/history@1.161.4': {} '@tanstack/history@1.161.4': {}
'@tanstack/react-router-devtools@1.162.9(@tanstack/react-router@1.162.9(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.162.9)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': '@tanstack/query-core@5.90.20': {}
'@tanstack/react-query@5.90.21(react@19.2.4)':
dependencies: dependencies:
'@tanstack/react-router': 1.162.9(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@tanstack/query-core': 5.90.20
'@tanstack/router-devtools-core': 1.162.9(@tanstack/router-core@1.162.9)(csstype@3.2.3) react: 19.2.4
'@tanstack/react-router-devtools@1.166.2(@tanstack/react-router@1.166.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.166.2)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@tanstack/react-router': 1.166.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/router-devtools-core': 1.166.2(@tanstack/router-core@1.166.2)(csstype@3.2.3)
react: 19.2.4 react: 19.2.4
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.4(react@19.2.4)
optionalDependencies: optionalDependencies:
'@tanstack/router-core': 1.162.9 '@tanstack/router-core': 1.166.2
transitivePeerDependencies: transitivePeerDependencies:
- csstype - csstype
'@tanstack/react-router@1.162.9(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': '@tanstack/react-router@1.166.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies: dependencies:
'@tanstack/history': 1.161.4 '@tanstack/history': 1.161.4
'@tanstack/react-store': 0.9.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@tanstack/react-store': 0.9.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@tanstack/router-core': 1.162.9 '@tanstack/router-core': 1.166.2
isbot: 5.1.35 isbot: 5.1.35
react: 19.2.4 react: 19.2.4
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.4(react@19.2.4)
@@ -2332,7 +2349,7 @@ snapshots:
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.4(react@19.2.4)
use-sync-external-store: 1.6.0(react@19.2.4) use-sync-external-store: 1.6.0(react@19.2.4)
'@tanstack/router-core@1.162.9': '@tanstack/router-core@1.166.2':
dependencies: dependencies:
'@tanstack/history': 1.161.4 '@tanstack/history': 1.161.4
'@tanstack/store': 0.9.1 '@tanstack/store': 0.9.1
@@ -2342,18 +2359,18 @@ snapshots:
tiny-invariant: 1.3.3 tiny-invariant: 1.3.3
tiny-warning: 1.0.3 tiny-warning: 1.0.3
'@tanstack/router-devtools-core@1.162.9(@tanstack/router-core@1.162.9)(csstype@3.2.3)': '@tanstack/router-devtools-core@1.166.2(@tanstack/router-core@1.166.2)(csstype@3.2.3)':
dependencies: dependencies:
'@tanstack/router-core': 1.162.9 '@tanstack/router-core': 1.166.2
clsx: 2.1.1 clsx: 2.1.1
goober: 2.1.18(csstype@3.2.3) goober: 2.1.18(csstype@3.2.3)
tiny-invariant: 1.3.3 tiny-invariant: 1.3.3
optionalDependencies: optionalDependencies:
csstype: 3.2.3 csstype: 3.2.3
'@tanstack/router-generator@1.162.9': '@tanstack/router-generator@1.166.2':
dependencies: dependencies:
'@tanstack/router-core': 1.162.9 '@tanstack/router-core': 1.166.2
'@tanstack/router-utils': 1.161.4 '@tanstack/router-utils': 1.161.4
'@tanstack/virtual-file-routes': 1.161.4 '@tanstack/virtual-file-routes': 1.161.4
prettier: 3.8.1 prettier: 3.8.1
@@ -2364,7 +2381,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@tanstack/router-plugin@1.162.9(@tanstack/react-router@1.162.9(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.15(@types/node@25.3.0)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))': '@tanstack/router-plugin@1.166.2(@tanstack/react-router@1.166.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.16(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))':
dependencies: dependencies:
'@babel/core': 7.29.0 '@babel/core': 7.29.0
'@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0)
@@ -2372,16 +2389,16 @@ snapshots:
'@babel/template': 7.28.6 '@babel/template': 7.28.6
'@babel/traverse': 7.29.0 '@babel/traverse': 7.29.0
'@babel/types': 7.29.0 '@babel/types': 7.29.0
'@tanstack/router-core': 1.162.9 '@tanstack/router-core': 1.166.2
'@tanstack/router-generator': 1.162.9 '@tanstack/router-generator': 1.166.2
'@tanstack/router-utils': 1.161.4 '@tanstack/router-utils': 1.161.4
'@tanstack/virtual-file-routes': 1.161.4 '@tanstack/virtual-file-routes': 1.161.4
chokidar: 3.6.0 chokidar: 3.6.0
unplugin: 2.3.11 unplugin: 2.3.11
zod: 3.25.76 zod: 3.25.76
optionalDependencies: optionalDependencies:
'@tanstack/react-router': 1.162.9(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@tanstack/react-router': 1.166.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
vite: 8.0.0-beta.15(@types/node@25.3.0)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0) vite: 8.0.0-beta.16(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@@ -2429,7 +2446,7 @@ snapshots:
dependencies: dependencies:
'@babel/types': 7.29.0 '@babel/types': 7.29.0
'@types/node@25.3.0': '@types/node@25.3.3':
dependencies: dependencies:
undici-types: 7.18.2 undici-types: 7.18.2
@@ -2441,24 +2458,24 @@ snapshots:
dependencies: dependencies:
csstype: 3.2.3 csstype: 3.2.3
'@uiw/codemirror-extensions-basic-setup@4.25.5(@codemirror/autocomplete@6.20.0)(@codemirror/commands@6.10.2)(@codemirror/language@6.12.2)(@codemirror/lint@6.9.4)(@codemirror/search@6.6.0)(@codemirror/state@6.5.4)(@codemirror/view@6.39.15)': '@uiw/codemirror-extensions-basic-setup@4.25.7(@codemirror/autocomplete@6.20.1)(@codemirror/commands@6.10.2)(@codemirror/language@6.12.2)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.5.4)(@codemirror/view@6.39.16)':
dependencies: dependencies:
'@codemirror/autocomplete': 6.20.0 '@codemirror/autocomplete': 6.20.1
'@codemirror/commands': 6.10.2 '@codemirror/commands': 6.10.2
'@codemirror/language': 6.12.2 '@codemirror/language': 6.12.2
'@codemirror/lint': 6.9.4 '@codemirror/lint': 6.9.5
'@codemirror/search': 6.6.0 '@codemirror/search': 6.6.0
'@codemirror/state': 6.5.4 '@codemirror/state': 6.5.4
'@codemirror/view': 6.39.15 '@codemirror/view': 6.39.16
'@uiw/react-codemirror@4.25.5(@babel/runtime@7.28.6)(@codemirror/autocomplete@6.20.0)(@codemirror/language@6.12.2)(@codemirror/lint@6.9.4)(@codemirror/search@6.6.0)(@codemirror/state@6.5.4)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.39.15)(codemirror@6.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': '@uiw/react-codemirror@4.25.7(@babel/runtime@7.28.6)(@codemirror/autocomplete@6.20.1)(@codemirror/language@6.12.2)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.5.4)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.39.16)(codemirror@6.0.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies: dependencies:
'@babel/runtime': 7.28.6 '@babel/runtime': 7.28.6
'@codemirror/commands': 6.10.2 '@codemirror/commands': 6.10.2
'@codemirror/state': 6.5.4 '@codemirror/state': 6.5.4
'@codemirror/theme-one-dark': 6.1.3 '@codemirror/theme-one-dark': 6.1.3
'@codemirror/view': 6.39.15 '@codemirror/view': 6.39.16
'@uiw/codemirror-extensions-basic-setup': 4.25.5(@codemirror/autocomplete@6.20.0)(@codemirror/commands@6.10.2)(@codemirror/language@6.12.2)(@codemirror/lint@6.9.4)(@codemirror/search@6.6.0)(@codemirror/state@6.5.4)(@codemirror/view@6.39.15) '@uiw/codemirror-extensions-basic-setup': 4.25.7(@codemirror/autocomplete@6.20.1)(@codemirror/commands@6.10.2)(@codemirror/language@6.12.2)(@codemirror/lint@6.9.5)(@codemirror/search@6.6.0)(@codemirror/state@6.5.4)(@codemirror/view@6.39.16)
codemirror: 6.0.2 codemirror: 6.0.2
react: 19.2.4 react: 19.2.4
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.4(react@19.2.4)
@@ -2470,7 +2487,7 @@ snapshots:
'@vercel/oidc@3.1.0': {} '@vercel/oidc@3.1.0': {}
'@vitejs/plugin-react@5.1.4(vite@8.0.0-beta.15(@types/node@25.3.0)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))': '@vitejs/plugin-react@5.1.4(vite@8.0.0-beta.16(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))':
dependencies: dependencies:
'@babel/core': 7.29.0 '@babel/core': 7.29.0
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0)
@@ -2478,17 +2495,17 @@ snapshots:
'@rolldown/pluginutils': 1.0.0-rc.3 '@rolldown/pluginutils': 1.0.0-rc.3
'@types/babel__core': 7.20.5 '@types/babel__core': 7.20.5
react-refresh: 0.18.0 react-refresh: 0.18.0
vite: 8.0.0-beta.15(@types/node@25.3.0)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0) vite: 8.0.0-beta.16(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
acorn@8.16.0: {} acorn@8.15.0: {}
ai@6.0.97(zod@4.3.6): ai@6.0.116(zod@4.3.6):
dependencies: dependencies:
'@ai-sdk/gateway': 3.0.53(zod@4.3.6) '@ai-sdk/gateway': 3.0.66(zod@4.3.6)
'@ai-sdk/provider': 3.0.8 '@ai-sdk/provider': 3.0.8
'@ai-sdk/provider-utils': 4.0.15(zod@4.3.6) '@ai-sdk/provider-utils': 4.0.19(zod@4.3.6)
'@opentelemetry/api': 1.9.0 '@opentelemetry/api': 1.9.0
zod: 4.3.6 zod: 4.3.6
@@ -2512,7 +2529,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
baseline-browser-mapping@2.10.0: {} baseline-browser-mapping@2.9.19: {}
bignumber.js@9.3.1: {} bignumber.js@9.3.1: {}
@@ -2524,13 +2541,13 @@ snapshots:
browserslist@4.28.1: browserslist@4.28.1:
dependencies: dependencies:
baseline-browser-mapping: 2.10.0 baseline-browser-mapping: 2.9.19
caniuse-lite: 1.0.30001774 caniuse-lite: 1.0.30001770
electron-to-chromium: 1.5.302 electron-to-chromium: 1.5.286
node-releases: 2.0.27 node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1) update-browserslist-db: 1.2.3(browserslist@4.28.1)
caniuse-lite@1.0.30001774: {} caniuse-lite@1.0.30001770: {}
chokidar@3.6.0: chokidar@3.6.0:
dependencies: dependencies:
@@ -2556,13 +2573,13 @@ snapshots:
codemirror@6.0.2: codemirror@6.0.2:
dependencies: dependencies:
'@codemirror/autocomplete': 6.20.0 '@codemirror/autocomplete': 6.20.1
'@codemirror/commands': 6.10.2 '@codemirror/commands': 6.10.2
'@codemirror/language': 6.12.2 '@codemirror/language': 6.12.2
'@codemirror/lint': 6.9.4 '@codemirror/lint': 6.9.5
'@codemirror/search': 6.6.0 '@codemirror/search': 6.6.0
'@codemirror/state': 6.5.4 '@codemirror/state': 6.5.4
'@codemirror/view': 6.39.15 '@codemirror/view': 6.39.16
convert-source-map@2.0.0: {} convert-source-map@2.0.0: {}
@@ -2594,7 +2611,7 @@ snapshots:
dotenv@17.3.1: {} dotenv@17.3.1: {}
electron-to-chromium@1.5.302: {} electron-to-chromium@1.5.286: {}
enhanced-resolve@5.19.0: enhanced-resolve@5.19.0:
dependencies: dependencies:
@@ -2603,7 +2620,7 @@ snapshots:
error-causes@3.0.2: {} error-causes@3.0.2: {}
es-toolkit@1.44.0: {} es-toolkit@1.45.1: {}
esbuild@0.27.3: esbuild@0.27.3:
optionalDependencies: optionalDependencies:
@@ -2850,24 +2867,24 @@ snapshots:
resolve-pkg-maps@1.0.0: {} resolve-pkg-maps@1.0.0: {}
rolldown@1.0.0-rc.5: rolldown@1.0.0-rc.6:
dependencies: dependencies:
'@oxc-project/types': 0.114.0 '@oxc-project/types': 0.115.0
'@rolldown/pluginutils': 1.0.0-rc.5 '@rolldown/pluginutils': 1.0.0-rc.6
optionalDependencies: optionalDependencies:
'@rolldown/binding-android-arm64': 1.0.0-rc.5 '@rolldown/binding-android-arm64': 1.0.0-rc.6
'@rolldown/binding-darwin-arm64': 1.0.0-rc.5 '@rolldown/binding-darwin-arm64': 1.0.0-rc.6
'@rolldown/binding-darwin-x64': 1.0.0-rc.5 '@rolldown/binding-darwin-x64': 1.0.0-rc.6
'@rolldown/binding-freebsd-x64': 1.0.0-rc.5 '@rolldown/binding-freebsd-x64': 1.0.0-rc.6
'@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.5 '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.6
'@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.5 '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.6
'@rolldown/binding-linux-arm64-musl': 1.0.0-rc.5 '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.6
'@rolldown/binding-linux-x64-gnu': 1.0.0-rc.5 '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.6
'@rolldown/binding-linux-x64-musl': 1.0.0-rc.5 '@rolldown/binding-linux-x64-musl': 1.0.0-rc.6
'@rolldown/binding-openharmony-arm64': 1.0.0-rc.5 '@rolldown/binding-openharmony-arm64': 1.0.0-rc.6
'@rolldown/binding-wasm32-wasi': 1.0.0-rc.5 '@rolldown/binding-wasm32-wasi': 1.0.0-rc.6
'@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.5 '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.6
'@rolldown/binding-win32-x64-msvc': 1.0.0-rc.5 '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.6
scheduler@0.27.0: {} scheduler@0.27.0: {}
@@ -2937,7 +2954,7 @@ snapshots:
unplugin@2.3.11: unplugin@2.3.11:
dependencies: dependencies:
'@jridgewell/remapping': 2.3.5 '@jridgewell/remapping': 2.3.5
acorn: 8.16.0 acorn: 8.15.0
picomatch: 4.0.3 picomatch: 4.0.3
webpack-virtual-modules: 0.6.2 webpack-virtual-modules: 0.6.2
@@ -2964,16 +2981,16 @@ snapshots:
dependencies: dependencies:
react: 19.2.4 react: 19.2.4
vite@8.0.0-beta.15(@types/node@25.3.0)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0): vite@8.0.0-beta.16(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0):
dependencies: dependencies:
'@oxc-project/runtime': 0.114.0 '@oxc-project/runtime': 0.115.0
lightningcss: 1.31.1 lightningcss: 1.31.1
picomatch: 4.0.3 picomatch: 4.0.3
postcss: 8.5.6 postcss: 8.5.6
rolldown: 1.0.0-rc.5 rolldown: 1.0.0-rc.6
tinyglobby: 0.2.15 tinyglobby: 0.2.15
optionalDependencies: optionalDependencies:
'@types/node': 25.3.0 '@types/node': 25.3.3
esbuild: 0.27.3 esbuild: 0.27.3
fsevents: 2.3.3 fsevents: 2.3.3
jiti: 2.6.1 jiti: 2.6.1

43
public/auth.json Normal file
View File

@@ -0,0 +1,43 @@
{
"metadata": {
"name": "kevisual",
"share": "public"
},
"registry": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template",
"clone": {
".": {
"enabled": true
}
},
"syncd": [
{
"files": [
"**/*"
],
"registry": ""
}
],
"sync": {
"AGENTS.md": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/AGENTS.md",
"vite.config.ts": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/vite.config.ts",
"src/main.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/main.tsx",
"src/agents/app.ts": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/agents/app.ts",
"src/agents/index.ts": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/agents/index.ts",
"src/modules/basename.ts": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/modules/basename.ts",
"src/modules/query.ts": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/modules/query.ts",
"src/pages/page.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/pages/page.tsx",
"src/routes/__root.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/routes/__root.tsx",
"src/routes/demo.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/routes/demo.tsx",
"src/routes/index.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/routes/index.tsx",
"src/routes/login.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/routes/login.tsx",
"src/styles/theme.css": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/styles/theme.css",
"src/pages/auth/index.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/pages/auth/index.tsx",
"src/pages/auth/page.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/pages/auth/page.tsx",
"src/pages/auth/store.ts": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/pages/auth/store.ts",
"src/pages/demo/page.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/pages/demo/page.tsx",
"src/pages/auth/hooks/index.ts": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/pages/auth/hooks/index.ts",
"src/pages/auth/hooks/use-api-query.ts": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/pages/auth/hooks/use-api-query.ts",
"src/pages/auth/modules/BaseHeader.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/pages/auth/modules/BaseHeader.tsx",
"src/pages/demo/store/index.ts": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/pages/demo/store/index.ts"
}
}

View File

@@ -1,5 +1,5 @@
<!doctype html> <!doctype html>
<html lang="zh-CN"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />

View File

@@ -1,43 +1,3 @@
import { QueryRouterServer } from '@kevisual/router/browser' import { QueryRouterServer } from "@kevisual/router/browser"
import { useContextKey } from '@kevisual/context' import { useContextKey } from '@kevisual/context'
import { useConfigStore } from '@/pages/config/store' export const app = useContextKey('app', new QueryRouterServer())
import { useGiteaConfigStore } from '@/pages/config/gitea/store'
import { CNB } from '@kevisual/cnb'
import { Gitea } from '@kevisual/gitea';
export const app = useContextKey('app', new QueryRouterServer())
export const cnb: CNB = useContextKey('cnb', () => {
const state = useConfigStore.getState()
const config = state.config || {}
const cors: any = {}
if (config.ENABLE_CORS) {
cors.baseUrl = config.CNB_CORS_URL || 'https://cors.kevisual.cn'
}
console.log('state', state)
// if(state.config.)
return new CNB({
token: config.CNB_API_KEY,
cookie: config.CNB_COOKIE,
cors
})
})
// import '@kevisual/cnb-ai'
const url = 'https://kevisual.cn/root/cnb-ai/dist/app.js'
setTimeout(() => {
import(/* @vite-ignore */url)
}, 2000)
export const gitea = useContextKey('gitea', () => {
const state = useGiteaConfigStore.getState()
const config = state.config || {}
return new Gitea({
token: config.GITEA_TOKEN,
baseURL: config.GITEA_URL,
cors: {
baseUrl: 'https://cors.kevisual.cn'
}
})
})

1
src/agents/index.ts Normal file
View File

@@ -0,0 +1 @@
export * from './app.ts'

View File

@@ -0,0 +1,125 @@
import * as React from "react"
import { mergeProps } from "@base-ui/react/merge-props"
import { useRender } from "@base-ui/react/use-render"
import { cn } from "@/lib/utils"
import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"
function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) {
return (
<nav
aria-label="breadcrumb"
data-slot="breadcrumb"
className={cn(className)}
{...props}
/>
)
}
function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
return (
<ol
data-slot="breadcrumb-list"
className={cn(
"text-muted-foreground gap-1.5 text-sm flex flex-wrap items-center wrap-break-word",
className
)}
{...props}
/>
)
}
function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
return (
<li
data-slot="breadcrumb-item"
className={cn("gap-1 inline-flex items-center", className)}
{...props}
/>
)
}
function BreadcrumbLink({
className,
render,
...props
}: useRender.ComponentProps<"a">) {
return useRender({
defaultTagName: "a",
props: mergeProps<"a">(
{
className: cn("hover:text-foreground transition-colors", className),
},
props
),
render,
state: {
slot: "breadcrumb-link",
},
})
}
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
return (
<span
data-slot="breadcrumb-page"
role="link"
aria-disabled="true"
aria-current="page"
className={cn("text-foreground font-normal", className)}
{...props}
/>
)
}
function BreadcrumbSeparator({
children,
className,
...props
}: React.ComponentProps<"li">) {
return (
<li
data-slot="breadcrumb-separator"
role="presentation"
aria-hidden="true"
className={cn("[&>svg]:size-3.5", className)}
{...props}
>
{children ?? (
<ChevronRightIcon />
)}
</li>
)
}
function BreadcrumbEllipsis({
className,
...props
}: React.ComponentProps<"span">) {
return (
<span
data-slot="breadcrumb-ellipsis"
role="presentation"
aria-hidden="true"
className={cn(
"size-5 [&>svg]:size-4 flex items-center justify-center",
className
)}
{...props}
>
<MoreHorizontalIcon
/>
<span className="sr-only">More</span>
</span>
)
}
export {
Breadcrumb,
BreadcrumbList,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbPage,
BreadcrumbSeparator,
BreadcrumbEllipsis,
}

View File

@@ -1,5 +1,3 @@
"use client"
import { Button as ButtonPrimitive } from "@base-ui/react/button" import { Button as ButtonPrimitive } from "@base-ui/react/button"
import { cva, type VariantProps } from "class-variance-authority" import { cva, type VariantProps } from "class-variance-authority"

View File

@@ -1,3 +1,5 @@
"use client"
import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox" import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"

View File

@@ -0,0 +1,188 @@
import * as React from "react"
import { Command as CommandPrimitive } from "cmdk"
import { cn } from "@/lib/utils"
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
import {
InputGroup,
InputGroupAddon,
} from "@/components/ui/input-group"
import { SearchIcon, CheckIcon } from "lucide-react"
function Command({
className,
...props
}: React.ComponentProps<typeof CommandPrimitive>) {
return (
<CommandPrimitive
data-slot="command"
className={cn(
"bg-popover text-popover-foreground rounded-xl! p-1 flex size-full flex-col overflow-hidden",
className
)}
{...props}
/>
)
}
function CommandDialog({
title = "Command Palette",
description = "Search for a command to run...",
children,
className,
showCloseButton = false,
...props
}: Omit<React.ComponentProps<typeof Dialog>, "children"> & {
title?: string
description?: string
className?: string
showCloseButton?: boolean
children: React.ReactNode
}) {
return (
<Dialog {...props}>
<DialogHeader className="sr-only">
<DialogTitle>{title}</DialogTitle>
<DialogDescription>{description}</DialogDescription>
</DialogHeader>
<DialogContent
className={cn(
"rounded-xl! top-1/3 translate-y-0 overflow-hidden p-0",
className
)}
showCloseButton={showCloseButton}
>
{children}
</DialogContent>
</Dialog>
)
}
function CommandInput({
className,
...props
}: React.ComponentProps<typeof CommandPrimitive.Input>) {
return (
<div data-slot="command-input-wrapper" className="p-1 pb-0">
<InputGroup className="bg-input/30 border-input/30 h-8! rounded-lg! shadow-none! *:data-[slot=input-group-addon]:pl-2!">
<CommandPrimitive.Input
data-slot="command-input"
className={cn(
"w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
/>
<InputGroupAddon>
<SearchIcon className="size-4 shrink-0 opacity-50" />
</InputGroupAddon>
</InputGroup>
</div>
)
}
function CommandList({
className,
...props
}: React.ComponentProps<typeof CommandPrimitive.List>) {
return (
<CommandPrimitive.List
data-slot="command-list"
className={cn(
"no-scrollbar max-h-72 scroll-py-1 outline-none overflow-x-hidden overflow-y-auto",
className
)}
{...props}
/>
)
}
function CommandEmpty({
className,
...props
}: React.ComponentProps<typeof CommandPrimitive.Empty>) {
return (
<CommandPrimitive.Empty
data-slot="command-empty"
className={cn("py-6 text-center text-sm", className)}
{...props}
/>
)
}
function CommandGroup({
className,
...props
}: React.ComponentProps<typeof CommandPrimitive.Group>) {
return (
<CommandPrimitive.Group
data-slot="command-group"
className={cn("text-foreground **:[[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium", className)}
{...props}
/>
)
}
function CommandSeparator({
className,
...props
}: React.ComponentProps<typeof CommandPrimitive.Separator>) {
return (
<CommandPrimitive.Separator
data-slot="command-separator"
className={cn("bg-border -mx-1 h-px", className)}
{...props}
/>
)
}
function CommandItem({
className,
children,
...props
}: React.ComponentProps<typeof CommandPrimitive.Item>) {
return (
<CommandPrimitive.Item
data-slot="command-item"
className={cn(
"data-selected:bg-muted data-selected:text-foreground data-selected:*:[svg]:text-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! [&_svg:not([class*='size-'])]:size-4 group/command-item data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
className
)}
{...props}
>
{children}
<CheckIcon className="ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" />
</CommandPrimitive.Item>
)
}
function CommandShortcut({
className,
...props
}: React.ComponentProps<"span">) {
return (
<span
data-slot="command-shortcut"
className={cn("text-muted-foreground group-data-selected/command-item:text-foreground ml-auto text-xs tracking-widest", className)}
{...props}
/>
)
}
export {
Command,
CommandDialog,
CommandInput,
CommandList,
CommandEmpty,
CommandGroup,
CommandItem,
CommandShortcut,
CommandSeparator,
}

View File

@@ -1,5 +1,3 @@
"use client"
import * as React from "react" import * as React from "react"
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog" import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"
@@ -30,7 +28,7 @@ function DialogOverlay({
return ( return (
<DialogPrimitive.Backdrop <DialogPrimitive.Backdrop
data-slot="dialog-overlay" data-slot="dialog-overlay"
className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/20 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 z-50", className)} className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50", className)}
{...props} {...props}
/> />
) )

View File

@@ -130,7 +130,7 @@ function DropdownMenuSubContent({
return ( return (
<DropdownMenuContent <DropdownMenuContent
data-slot="dropdown-menu-sub-content" data-slot="dropdown-menu-sub-content"
className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-[96px] rounded-md p-1 shadow-lg ring-1 duration-100 w-auto", className)} className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-[96px] rounded-lg p-1 shadow-lg ring-1 duration-100 w-auto", className)}
align={align} align={align}
alignOffset={alignOffset} alignOffset={alignOffset}
side={side} side={side}

View File

@@ -0,0 +1,149 @@
"use client"
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="input-group"
role="group"
className={cn(
"border-input dark:bg-input/30 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-disabled:bg-input/50 dark:has-disabled:bg-input/80 h-8 rounded-lg border transition-colors in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5 group/input-group relative flex w-full min-w-0 items-center outline-none has-[>textarea]:h-auto",
className
)}
{...props}
/>
)
}
const inputGroupAddonVariants = cva(
"text-muted-foreground h-auto gap-2 py-1.5 text-sm font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4 flex cursor-text items-center justify-center select-none",
{
variants: {
align: {
"inline-start": "pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem] order-first",
"inline-end": "pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem] order-last",
"block-start":
"px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2 order-first w-full justify-start",
"block-end":
"px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2 order-last w-full justify-start",
},
},
defaultVariants: {
align: "inline-start",
},
}
)
function InputGroupAddon({
className,
align = "inline-start",
...props
}: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) {
return (
<div
role="group"
data-slot="input-group-addon"
data-align={align}
className={cn(inputGroupAddonVariants({ align }), className)}
onClick={(e) => {
if ((e.target as HTMLElement).closest("button")) {
return
}
e.currentTarget.parentElement?.querySelector("input")?.focus()
}}
{...props}
/>
)
}
const inputGroupButtonVariants = cva(
"gap-2 text-sm shadow-none flex items-center",
{
variants: {
size: {
xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
sm: "",
"icon-xs": "size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0",
"icon-sm": "size-8 p-0 has-[>svg]:p-0",
},
},
defaultVariants: {
size: "xs",
},
}
)
function InputGroupButton({
className,
type = "button",
variant = "ghost",
size = "xs",
...props
}: Omit<React.ComponentProps<typeof Button>, "size" | "type"> &
VariantProps<typeof inputGroupButtonVariants> & {
type?: "button" | "submit" | "reset"
}) {
return (
<Button
type={type}
data-size={size}
variant={variant}
className={cn(inputGroupButtonVariants({ size }), className)}
{...props}
/>
)
}
function InputGroupText({ className, ...props }: React.ComponentProps<"span">) {
return (
<span
className={cn(
"text-muted-foreground gap-2 text-sm [&_svg:not([class*='size-'])]:size-4 flex items-center [&_svg]:pointer-events-none",
className
)}
{...props}
/>
)
}
function InputGroupInput({
className,
...props
}: React.ComponentProps<"input">) {
return (
<Input
data-slot="input-group-control"
className={cn("rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent flex-1", className)}
{...props}
/>
)
}
function InputGroupTextarea({
className,
...props
}: React.ComponentProps<"textarea">) {
return (
<Textarea
data-slot="input-group-control"
className={cn("rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent flex-1 resize-none", className)}
{...props}
/>
)
}
export {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupText,
InputGroupInput,
InputGroupTextarea,
}

26
src/components/ui/kbd.tsx Normal file
View File

@@ -0,0 +1,26 @@
import { cn } from "@/lib/utils"
function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {
return (
<kbd
data-slot="kbd"
className={cn(
"bg-muted text-muted-foreground in-data-[slot=tooltip-content]:bg-background/20 in-data-[slot=tooltip-content]:text-background dark:in-data-[slot=tooltip-content]:bg-background/10 h-5 w-fit min-w-5 gap-1 rounded-sm px-1 font-sans text-xs font-medium [&_svg:not([class*='size-'])]:size-3 pointer-events-none inline-flex items-center justify-center select-none",
className
)}
{...props}
/>
)
}
function KbdGroup({ className, ...props }: React.ComponentProps<"div">) {
return (
<kbd
data-slot="kbd-group"
className={cn("gap-1 inline-flex items-center", className)}
{...props}
/>
)
}
export { Kbd, KbdGroup }

View File

@@ -1,5 +1,3 @@
"use client"
import * as React from "react" import * as React from "react"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"

View File

@@ -0,0 +1,265 @@
"use client"
import * as React from "react"
import { Menu as MenuPrimitive } from "@base-ui/react/menu"
import { Menubar as MenubarPrimitive } from "@base-ui/react/menubar"
import { cn } from "@/lib/utils"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuPortal,
DropdownMenuRadioGroup,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { CheckIcon } from "lucide-react"
function Menubar({ className, ...props }: MenubarPrimitive.Props) {
return (
<MenubarPrimitive
data-slot="menubar"
className={cn("bg-background h-8 gap-0.5 rounded-lg border p-[3px] flex items-center", className)}
{...props}
/>
)
}
function MenubarMenu({ ...props }: React.ComponentProps<typeof DropdownMenu>) {
return <DropdownMenu data-slot="menubar-menu" {...props} />
}
function MenubarGroup({
...props
}: React.ComponentProps<typeof DropdownMenuGroup>) {
return <DropdownMenuGroup data-slot="menubar-group" {...props} />
}
function MenubarPortal({
...props
}: React.ComponentProps<typeof DropdownMenuPortal>) {
return <DropdownMenuPortal data-slot="menubar-portal" {...props} />
}
function MenubarTrigger({
className,
...props
}: React.ComponentProps<typeof DropdownMenuTrigger>) {
return (
<DropdownMenuTrigger
data-slot="menubar-trigger"
className={cn(
"hover:bg-muted aria-expanded:bg-muted rounded-sm px-1.5 py-[2px] text-sm font-medium flex items-center outline-hidden select-none",
className
)}
{...props}
/>
)
}
function MenubarContent({
className,
align = "start",
alignOffset = -4,
sideOffset = 8,
...props
}: React.ComponentProps<typeof DropdownMenuContent>) {
return (
<DropdownMenuContent
data-slot="menubar-content"
align={align}
alignOffset={alignOffset}
sideOffset={sideOffset}
className={cn("bg-popover text-popover-foreground data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 min-w-36 rounded-lg p-1 shadow-md ring-1 duration-100 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2", className )}
{...props}
/>
)
}
function MenubarItem({
className,
inset,
variant = "default",
...props
}: React.ComponentProps<typeof DropdownMenuItem>) {
return (
<DropdownMenuItem
data-slot="menubar-item"
data-inset={inset}
data-variant={variant}
className={cn("focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive! not-data-[variant=destructive]:focus:**:text-accent-foreground gap-1.5 rounded-md px-1.5 py-1 text-sm data-disabled:opacity-50 data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 group/menubar-item", className)}
{...props}
/>
)
}
function MenubarCheckboxItem({
className,
children,
checked,
inset,
...props
}: MenuPrimitive.CheckboxItem.Props & {
inset?: boolean
}) {
return (
<MenuPrimitive.CheckboxItem
data-slot="menubar-checkbox-item"
data-inset={inset}
className={cn(
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-1.5 rounded-md py-1 pr-1.5 pl-7 text-sm data-inset:pl-7 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
className
)}
checked={checked}
{...props}
>
<span className="left-1.5 size-4 [&_svg:not([class*='size-'])]:size-4 pointer-events-none absolute flex items-center justify-center">
<MenuPrimitive.CheckboxItemIndicator>
<CheckIcon
/>
</MenuPrimitive.CheckboxItemIndicator>
</span>
{children}
</MenuPrimitive.CheckboxItem>
)
}
function MenubarRadioGroup({
...props
}: React.ComponentProps<typeof DropdownMenuRadioGroup>) {
return <DropdownMenuRadioGroup data-slot="menubar-radio-group" {...props} />
}
function MenubarRadioItem({
className,
children,
inset,
...props
}: MenuPrimitive.RadioItem.Props & {
inset?: boolean
}) {
return (
<MenuPrimitive.RadioItem
data-slot="menubar-radio-item"
data-inset={inset}
className={cn(
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-1.5 rounded-md py-1 pr-1.5 pl-7 text-sm data-disabled:opacity-50 data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0",
className
)}
{...props}
>
<span className="left-1.5 size-4 [&_svg:not([class*='size-'])]:size-4 pointer-events-none absolute flex items-center justify-center">
<MenuPrimitive.RadioItemIndicator>
<CheckIcon
/>
</MenuPrimitive.RadioItemIndicator>
</span>
{children}
</MenuPrimitive.RadioItem>
)
}
function MenubarLabel({
className,
inset,
...props
}: React.ComponentProps<typeof DropdownMenuLabel> & {
inset?: boolean
}) {
return (
<DropdownMenuLabel
data-slot="menubar-label"
data-inset={inset}
className={cn("px-1.5 py-1 text-sm font-medium data-inset:pl-7", className)}
{...props}
/>
)
}
function MenubarSeparator({
className,
...props
}: React.ComponentProps<typeof DropdownMenuSeparator>) {
return (
<DropdownMenuSeparator
data-slot="menubar-separator"
className={cn("bg-border -mx-1 my-1 h-px", className)}
{...props}
/>
)
}
function MenubarShortcut({
className,
...props
}: React.ComponentProps<typeof DropdownMenuShortcut>) {
return (
<DropdownMenuShortcut
data-slot="menubar-shortcut"
className={cn("text-muted-foreground group-focus/menubar-item:text-accent-foreground text-xs tracking-widest ml-auto", className)}
{...props}
/>
)
}
function MenubarSub({
...props
}: React.ComponentProps<typeof DropdownMenuSub>) {
return <DropdownMenuSub data-slot="menubar-sub" {...props} />
}
function MenubarSubTrigger({
className,
inset,
...props
}: React.ComponentProps<typeof DropdownMenuSubTrigger> & {
inset?: boolean
}) {
return (
<DropdownMenuSubTrigger
data-slot="menubar-sub-trigger"
data-inset={inset}
className={cn("focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground gap-1.5 rounded-md px-1.5 py-1 text-sm data-inset:pl-7 [&_svg:not([class*='size-'])]:size-4", className)}
{...props}
/>
)
}
function MenubarSubContent({
className,
...props
}: React.ComponentProps<typeof DropdownMenuSubContent>) {
return (
<DropdownMenuSubContent
data-slot="menubar-sub-content"
className={cn("bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 min-w-32 rounded-lg p-1 shadow-lg ring-1 duration-100", className)}
{...props}
/>
)
}
export {
Menubar,
MenubarPortal,
MenubarMenu,
MenubarTrigger,
MenubarContent,
MenubarGroup,
MenubarSeparator,
MenubarLabel,
MenubarItem,
MenubarShortcut,
MenubarCheckboxItem,
MenubarRadioGroup,
MenubarRadioItem,
MenubarSub,
MenubarSubTrigger,
MenubarSubContent,
}

129
src/components/ui/sheet.tsx Normal file
View File

@@ -0,0 +1,129 @@
"use client"
import * as React from "react"
import { Dialog as SheetPrimitive } from "@base-ui/react/dialog"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { XIcon } from "lucide-react"
function Sheet({ ...props }: SheetPrimitive.Root.Props) {
return <SheetPrimitive.Root data-slot="sheet" {...props} />
}
function SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
}
function SheetClose({ ...props }: SheetPrimitive.Close.Props) {
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
}
function SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
}
function SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {
return (
<SheetPrimitive.Backdrop
data-slot="sheet-overlay"
className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 z-50", className)}
{...props}
/>
)
}
function SheetContent({
className,
children,
side = "right",
showCloseButton = true,
...props
}: SheetPrimitive.Popup.Props & {
side?: "top" | "right" | "bottom" | "left"
showCloseButton?: boolean
}) {
return (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Popup
data-slot="sheet-content"
data-side={side}
className={cn("bg-background data-open:animate-in data-closed:animate-out data-[side=right]:data-closed:slide-out-to-right-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=top]:data-closed:slide-out-to-top-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:fade-out-0 data-open:fade-in-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=bottom]:data-open:slide-in-from-bottom-10 fixed z-50 flex flex-col gap-4 bg-clip-padding text-sm shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm", className)}
{...props}
>
{children}
{showCloseButton && (
<SheetPrimitive.Close
data-slot="sheet-close"
render={
<Button
variant="ghost"
className="absolute top-3 right-3"
size="icon-sm"
/>
}
>
<XIcon
/>
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
)}
</SheetPrimitive.Popup>
</SheetPortal>
)
}
function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="sheet-header"
className={cn("gap-0.5 p-4 flex flex-col", className)}
{...props}
/>
)
}
function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="sheet-footer"
className={cn("gap-2 p-4 mt-auto flex flex-col", className)}
{...props}
/>
)
}
function SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {
return (
<SheetPrimitive.Title
data-slot="sheet-title"
className={cn("text-foreground text-base font-medium", className)}
{...props}
/>
)
}
function SheetDescription({
className,
...props
}: SheetPrimitive.Description.Props) {
return (
<SheetPrimitive.Description
data-slot="sheet-description"
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
}
export {
Sheet,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
}

View File

@@ -1,3 +1,5 @@
"use client"
import { useTheme } from "next-themes" import { useTheme } from "next-themes"
import { Toaster as Sonner, type ToasterProps } from "sonner" import { Toaster as Sonner, type ToasterProps } from "sonner"
import { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from "lucide-react" import { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from "lucide-react"

View File

@@ -48,13 +48,13 @@ function TooltipContent({
<TooltipPrimitive.Popup <TooltipPrimitive.Popup
data-slot="tooltip-content" data-slot="tooltip-content"
className={cn( className={cn(
"data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 rounded-md px-3 py-1.5 text-xs data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 bg-neutral-900 text-white shadow-lg z-50 w-fit max-w-xs origin-(--transform-origin)", "data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 rounded-md px-3 py-1.5 text-xs data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 bg-foreground text-background z-50 w-fit max-w-xs origin-(--transform-origin)",
className className
)} )}
{...props} {...props}
> >
{children} {children}
<TooltipPrimitive.Arrow className="size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 bg-neutral-900 fill-neutral-900 z-50 data-[side=bottom]:top-1 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" /> <TooltipPrimitive.Arrow className="size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 bg-foreground fill-foreground z-50 data-[side=bottom]:top-1 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" />
</TooltipPrimitive.Popup> </TooltipPrimitive.Popup>
</TooltipPrimitive.Positioner> </TooltipPrimitive.Positioner>
</TooltipPrimitive.Portal> </TooltipPrimitive.Portal>

View File

@@ -2,12 +2,12 @@ import ReactDOM from 'react-dom/client'
import { RouterProvider, createRouter } from '@tanstack/react-router' import { RouterProvider, createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen' import { routeTree } from './routeTree.gen'
import './index.css' import './index.css'
import { basename } from './modules/basename' import { getDynamicBasename } from './modules/basename'
// import './agents/app' import './agents/index.ts';
// Set up a Router instance // Set up a Router instance
const router = createRouter({ const router = createRouter({
routeTree, routeTree,
basepath: basename, basepath: getDynamicBasename(),
defaultPreload: 'intent', defaultPreload: 'intent',
scrollRestoration: true, scrollRestoration: true,
}) })

View File

@@ -1,2 +1,22 @@
// @ts-ignore // @ts-ignore
export const basename = BASE_NAME; export const basename = BASE_NAME;
export const wrapBasename = (path: string) => {
const hasEnd = path.endsWith('/')
if (basename) {
return `${basename}${path}` + (hasEnd ? '' : '/');
} else {
return path;
}
}
// 动态计算 basename根据当前 URL 路径
export const getDynamicBasename = (): string => {
const path = window.location.pathname
const [user, key, id] = path.split('/').filter(Boolean)
if (key === 'v1' && id) {
return `/${user}/v1/${id}`
}
// 默认使用构建时的 basename
return basename
}

View File

@@ -1,6 +1,8 @@
import { Query, DataOpts } from '@kevisual/query'; import { Query, DataOpts } from '@kevisual/query';
import { QueryLoginBrowser } from '@kevisual/api/query-login' import { QueryLoginBrowser } from '@kevisual/api/query-login'
import { useContextKey } from '@kevisual/context'; import { useContextKey } from '@kevisual/context';
import { QueryClient } from '@tanstack/react-query';
export const query = useContextKey('query', new Query({ export const query = useContextKey('query', new Query({
url: '/api/router', url: '/api/router',
})); }));
@@ -11,4 +13,6 @@ export const queryClient = useContextKey('queryClient', new Query({
export const queryLogin = useContextKey('queryLogin', new QueryLoginBrowser({ export const queryLogin = useContextKey('queryLogin', new QueryLoginBrowser({
query: query query: query
})); }));
export const stackQueryClient = useContextKey('stackQueryClient', new QueryClient());

View File

@@ -0,0 +1 @@
export * from './use-api-query';

View File

@@ -0,0 +1,55 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { queryLogin } from '@/modules/query';
import { toast } from 'sonner';
import type { UserInfo } from '../store';
export const authQueryKeys = {
me: ['auth', 'me'] as const,
token: ['auth', 'token'] as const,
} as const;
export const useMe = () => {
return useQuery({
queryKey: authQueryKeys.me,
queryFn: async () => {
const res = await queryLogin.getMe();
if (res.code === 200) {
return res.data;
}
throw new Error(res.message || 'Failed to fetch user info');
},
staleTime: 1000 * 60 * 5, // 5 minutes
});
};
export const useSwitchOrg = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (username?: string) => {
const res = await queryLogin.switchUser(username || '');
if (res.code === 200) {
return res.data;
}
throw new Error(res.message || 'Switch failed');
},
onSuccess: () => {
toast.success('切换成功');
queryClient.invalidateQueries({ queryKey: authQueryKeys.me });
setTimeout(() => {
window.location.reload();
}, 1000);
},
onError: (error) => {
toast.error(error.message || '请求失败');
},
});
};
export const useGetToken = () => {
return useQuery({
queryKey: authQueryKeys.token,
queryFn: () => queryLogin.getToken(),
staleTime: Infinity,
});
};

View File

@@ -6,7 +6,6 @@ export { BaseHeader } from './modules/BaseHeader'
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useLocation, useNavigate } from '@tanstack/react-router'; import { useLocation, useNavigate } from '@tanstack/react-router';
type Props = { type Props = {
children?: React.ReactNode, children?: React.ReactNode,
mustLogin?: boolean, mustLogin?: boolean,

View File

@@ -9,6 +9,7 @@ export const BaseHeader = (props: { main?: React.ComponentType | null }) => {
me: state.me, me: state.me,
clearMe: state.clearMe, clearMe: state.clearMe,
links: state.links, links: state.links,
showBaseHeader: state.showBaseHeader,
}))); })));
const navigate = useNavigate(); const navigate = useNavigate();
const meInfo = useMemo(() => { const meInfo = useMemo(() => {
@@ -48,6 +49,9 @@ export const BaseHeader = (props: { main?: React.ComponentType | null }) => {
</div> </div>
) )
}, [store.me, store.clearMe]) }, [store.me, store.clearMe])
if (!store.showBaseHeader) {
return null;
}
return ( return (
<> <>
<div className="flex gap-2 text-lg w-full h-12 items-center justify-between bg-gray-200"> <div className="flex gap-2 text-lg w-full h-12 items-center justify-between bg-gray-200">

View File

@@ -1,8 +1,9 @@
import { queryLogin } from '@/modules/query'; import { queryLogin, stackQueryClient } from '@/modules/query';
import { create } from 'zustand'; import { create } from 'zustand';
import { toast } from 'sonner'; import { toast } from 'sonner';
type UserInfo = { import { authQueryKeys } from './hooks';
export type UserInfo = {
id?: string; id?: string;
username?: string; username?: string;
nickname?: string | null; nickname?: string | null;
@@ -35,6 +36,11 @@ export type LayoutStore = {
setLoginPageConfig: (config: Partial<LayoutStore['loginPageConfig']>) => void; setLoginPageConfig: (config: Partial<LayoutStore['loginPageConfig']>) => void;
links: HeaderLink[]; links: HeaderLink[];
setLinks: (links: HeaderLink[]) => void; setLinks: (links: HeaderLink[]) => void;
showBaseHeader: boolean;
setShowBaseHeader: (showBaseHeader: boolean) => void;
serverData: Record<string, any> | null;
setServerData: (data: Record<string, any>) => void;
initConvex: () => Promise<void>;
}; };
type HeaderLink = { type HeaderLink = {
title?: string; title?: string;
@@ -56,16 +62,23 @@ export const useLayoutStore = create<LayoutStore>((set, get) => ({
set({ me: undefined, isAdmin: false }); set({ me: undefined, isAdmin: false });
}, },
getMe: async () => { getMe: async () => {
const res = await queryLogin.getMe(); const data = await stackQueryClient.fetchQuery({
if (res.code === 200) { queryKey: authQueryKeys.me,
set({ me: res.data }); queryFn: async () => {
set({ isAdmin: res.data.orgs?.includes?.('admin') || false }); const res = await queryLogin.getMe();
} if (res.code === 200) {
return res.data;
}
throw new Error(res.message || 'Failed to fetch user info');
},
});
set({ me: data, isAdmin: data?.orgs?.includes?.('admin') || false });
}, },
switchOrg: async (username?: string) => { switchOrg: async (username?: string) => {
const res = await queryLogin.switchUser(username || ''); const res = await queryLogin.switchUser(username || '');
if (res.code === 200) { if (res.code === 200) {
toast.success('切换成功'); toast.success('切换成功');
stackQueryClient.invalidateQueries({ queryKey: authQueryKeys.me });
setTimeout(() => { setTimeout(() => {
window.location.reload(); window.location.reload();
}, 1000); }, 1000);
@@ -76,20 +89,32 @@ export const useLayoutStore = create<LayoutStore>((set, get) => ({
isAdmin: false, isAdmin: false,
setIsAdmin: (isAdmin) => set({ isAdmin }), setIsAdmin: (isAdmin) => set({ isAdmin }),
init: async () => { init: async () => {
const token = await queryLogin.getToken(); await queryLogin.init();
const token = await queryLogin.checkLocalToken();
if (token) { if (token) {
set({ me: {} }) set({ me: {} });
const me = await queryLogin.getMe(); try {
// const user = await queryLogin.checkLocalUser() as UserInfo; // const data = await stackQueryClient.fetchQuery({
const user = me.code === 200 ? me.data : undefined; // queryKey: authQueryKeys.me,
if (user) { // }) as UserInfo;
set({ me: user }); const userInfo = await queryLogin.checkLocalUser();
set({ isAdmin: user.orgs?.includes?.('admin') || false }); if (userInfo) {
} else { set({ me: userInfo as UserInfo, isAdmin: userInfo.orgs?.includes?.('admin') || false });
} else {
set({ me: undefined, isAdmin: false });
}
} catch {
set({ me: undefined, isAdmin: false }); set({ me: undefined, isAdmin: false });
} }
} }
// 获取服务端数据
// @ts-ignore
const sererData = window.__SERVER_DATA__;
if (sererData) {
set({ serverData: sererData });
}
}, },
initConvex: async () => { },
openLinkList: ['/login'], openLinkList: ['/login'],
setOpenLinkList: (openLinkList) => set({ openLinkList }), setOpenLinkList: (openLinkList) => set({ openLinkList }),
loginPageConfig: { loginPageConfig: {
@@ -102,4 +127,8 @@ export const useLayoutStore = create<LayoutStore>((set, get) => ({
})), })),
links: [{ title: '', href: '/', key: 'home' }], links: [{ title: '', href: '/', key: 'home' }],
setLinks: (links) => set({ links }), setLinks: (links) => set({ links }),
showBaseHeader: true,
setShowBaseHeader: (showBaseHeader) => set({ showBaseHeader }),
serverData: null,
setServerData: (data) => set({ serverData: data }),
})); }));

8
src/pages/demo/page.tsx Normal file
View File

@@ -0,0 +1,8 @@
import { useDemoStore } from './store/index'
export const App = () => {
const demoStore = useDemoStore()
console.log('demo', demoStore.formData)
return <div>App</div>
}
export default App;

View File

@@ -0,0 +1,95 @@
import { create } from 'zustand';
import { query } from '@/modules/query';
import { toast } from 'sonner';
interface Data {
id: string;
[key: string]: any;
}
type State = {
formData: Record<string, any>;
setFormData: (data: Record<string, any>) => void;
showEdit: boolean;
setShowEdit: (showEdit: boolean) => void;
loading: boolean;
setLoading: (loading: boolean) => void;
list: Data[];
getItem: (id: string) => Promise<any>;
getList: () => Promise<any>;
updateData: (data: Data) => Promise<void>;
deleteData: (id: string) => Promise<void>;
}
export const useDemoStore = create<State>((set, get) => {
return {
formData: {},
setFormData: (data) => set({ formData: data }),
showEdit: false,
setShowEdit: (showEdit) => set({ showEdit }),
loading: false,
setLoading: (loading) => set({ loading }),
list: [],
getItem: async (id) => {
const { setLoading } = get();
setLoading(true);
try {
const res = await query.post({
path: 'demo',
key: 'item',
data: { id }
})
if (res.code === 200) {
return res;
} else {
toast.error(res.message || '请求失败');
}
} finally {
setLoading(false);
}
},
getList: async () => {
const { setLoading } = get();
setLoading(true);
try {
const res = await query.post({
path: 'demo',
key: 'list'
});
if (res.code === 200) {
const list = res.data?.list || []
set({ list });
} else {
toast.error(res.message || '请求失败');
}
return res;
} finally {
setLoading(false);
}
},
updateData: async (data) => {
const res = await query.post({
path: 'demo',
key: 'update',
data
})
if (res.code === 200) {
get().getList()
} else {
toast.error(res.message || '请求失败');
}
},
deleteData: async (id) => {
const res = await query.post({
path: 'demo',
key: 'delete',
data: { id }
})
if (res.code === 200) {
get().getList()
} else {
toast.error(res.message || '请求失败');
}
}
}
})

View File

@@ -1,3 +1,5 @@
import App from './repos/page' const Home = () => {
return <div>Home Page</div>
}
export default App; export default Home;

View File

@@ -10,96 +10,53 @@
import { Route as rootRouteImport } from './routes/__root' import { Route as rootRouteImport } from './routes/__root'
import { Route as LoginRouteImport } from './routes/login' import { Route as LoginRouteImport } from './routes/login'
import { Route as DemoRouteImport } from './routes/demo'
import { Route as IndexRouteImport } from './routes/index' import { Route as IndexRouteImport } from './routes/index'
import { Route as WorkspacesIndexRouteImport } from './routes/workspaces/index'
import { Route as RepoIndexRouteImport } from './routes/repo/index'
import { Route as ConfigIndexRouteImport } from './routes/config/index'
import { Route as ConfigGiteaRouteImport } from './routes/config/gitea'
const LoginRoute = LoginRouteImport.update({ const LoginRoute = LoginRouteImport.update({
id: '/login', id: '/login',
path: '/login', path: '/login',
getParentRoute: () => rootRouteImport, getParentRoute: () => rootRouteImport,
} as any) } as any)
const DemoRoute = DemoRouteImport.update({
id: '/demo',
path: '/demo',
getParentRoute: () => rootRouteImport,
} as any)
const IndexRoute = IndexRouteImport.update({ const IndexRoute = IndexRouteImport.update({
id: '/', id: '/',
path: '/', path: '/',
getParentRoute: () => rootRouteImport, getParentRoute: () => rootRouteImport,
} as any) } as any)
const WorkspacesIndexRoute = WorkspacesIndexRouteImport.update({
id: '/workspaces/',
path: '/workspaces/',
getParentRoute: () => rootRouteImport,
} as any)
const RepoIndexRoute = RepoIndexRouteImport.update({
id: '/repo/',
path: '/repo/',
getParentRoute: () => rootRouteImport,
} as any)
const ConfigIndexRoute = ConfigIndexRouteImport.update({
id: '/config/',
path: '/config/',
getParentRoute: () => rootRouteImport,
} as any)
const ConfigGiteaRoute = ConfigGiteaRouteImport.update({
id: '/config/gitea',
path: '/config/gitea',
getParentRoute: () => rootRouteImport,
} as any)
export interface FileRoutesByFullPath { export interface FileRoutesByFullPath {
'/': typeof IndexRoute '/': typeof IndexRoute
'/demo': typeof DemoRoute
'/login': typeof LoginRoute '/login': typeof LoginRoute
'/config/gitea': typeof ConfigGiteaRoute
'/config/': typeof ConfigIndexRoute
'/repo/': typeof RepoIndexRoute
'/workspaces/': typeof WorkspacesIndexRoute
} }
export interface FileRoutesByTo { export interface FileRoutesByTo {
'/': typeof IndexRoute '/': typeof IndexRoute
'/demo': typeof DemoRoute
'/login': typeof LoginRoute '/login': typeof LoginRoute
'/config/gitea': typeof ConfigGiteaRoute
'/config': typeof ConfigIndexRoute
'/repo': typeof RepoIndexRoute
'/workspaces': typeof WorkspacesIndexRoute
} }
export interface FileRoutesById { export interface FileRoutesById {
__root__: typeof rootRouteImport __root__: typeof rootRouteImport
'/': typeof IndexRoute '/': typeof IndexRoute
'/demo': typeof DemoRoute
'/login': typeof LoginRoute '/login': typeof LoginRoute
'/config/gitea': typeof ConfigGiteaRoute
'/config/': typeof ConfigIndexRoute
'/repo/': typeof RepoIndexRoute
'/workspaces/': typeof WorkspacesIndexRoute
} }
export interface FileRouteTypes { export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: fullPaths: '/' | '/demo' | '/login'
| '/'
| '/login'
| '/config/gitea'
| '/config/'
| '/repo/'
| '/workspaces/'
fileRoutesByTo: FileRoutesByTo fileRoutesByTo: FileRoutesByTo
to: '/' | '/login' | '/config/gitea' | '/config' | '/repo' | '/workspaces' to: '/' | '/demo' | '/login'
id: id: '__root__' | '/' | '/demo' | '/login'
| '__root__'
| '/'
| '/login'
| '/config/gitea'
| '/config/'
| '/repo/'
| '/workspaces/'
fileRoutesById: FileRoutesById fileRoutesById: FileRoutesById
} }
export interface RootRouteChildren { export interface RootRouteChildren {
IndexRoute: typeof IndexRoute IndexRoute: typeof IndexRoute
DemoRoute: typeof DemoRoute
LoginRoute: typeof LoginRoute LoginRoute: typeof LoginRoute
ConfigGiteaRoute: typeof ConfigGiteaRoute
ConfigIndexRoute: typeof ConfigIndexRoute
RepoIndexRoute: typeof RepoIndexRoute
WorkspacesIndexRoute: typeof WorkspacesIndexRoute
} }
declare module '@tanstack/react-router' { declare module '@tanstack/react-router' {
@@ -111,6 +68,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof LoginRouteImport preLoaderRoute: typeof LoginRouteImport
parentRoute: typeof rootRouteImport parentRoute: typeof rootRouteImport
} }
'/demo': {
id: '/demo'
path: '/demo'
fullPath: '/demo'
preLoaderRoute: typeof DemoRouteImport
parentRoute: typeof rootRouteImport
}
'/': { '/': {
id: '/' id: '/'
path: '/' path: '/'
@@ -118,44 +82,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexRouteImport preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport parentRoute: typeof rootRouteImport
} }
'/workspaces/': {
id: '/workspaces/'
path: '/workspaces'
fullPath: '/workspaces/'
preLoaderRoute: typeof WorkspacesIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/repo/': {
id: '/repo/'
path: '/repo'
fullPath: '/repo/'
preLoaderRoute: typeof RepoIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/config/': {
id: '/config/'
path: '/config'
fullPath: '/config/'
preLoaderRoute: typeof ConfigIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/config/gitea': {
id: '/config/gitea'
path: '/config/gitea'
fullPath: '/config/gitea'
preLoaderRoute: typeof ConfigGiteaRouteImport
parentRoute: typeof rootRouteImport
}
} }
} }
const rootRouteChildren: RootRouteChildren = { const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute, IndexRoute: IndexRoute,
DemoRoute: DemoRoute,
LoginRoute: LoginRoute, LoginRoute: LoginRoute,
ConfigGiteaRoute: ConfigGiteaRoute,
ConfigIndexRoute: ConfigIndexRoute,
RepoIndexRoute: RepoIndexRoute,
WorkspacesIndexRoute: WorkspacesIndexRoute,
} }
export const routeTree = rootRouteImport export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren) ._addFileChildren(rootRouteChildren)

View File

@@ -4,24 +4,37 @@ import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
import { Toaster } from '@/components/ui/sonner' import { Toaster } from '@/components/ui/sonner'
import { AuthProvider } from '@/pages/auth' import { AuthProvider } from '@/pages/auth'
import { TooltipProvider } from '@/components/ui/tooltip' import { TooltipProvider } from '@/components/ui/tooltip'
import { useLayoutStore } from '@/pages/auth/store';
import { useShallow } from 'zustand/shallow';
import { stackQueryClient } from '@/modules/query'
import { QueryClientProvider } from '@tanstack/react-query'
import clsx from 'clsx';
export const Route = createRootRoute({ export const Route = createRootRoute({
component: RootComponent, component: RootComponent,
}) })
function RootComponent() { function RootComponent() {
const store = useLayoutStore(useShallow(state => ({
showBaseHeader: state.showBaseHeader,
})));
return ( return (
<div className='h-full overflow-hidden'> <QueryClientProvider client={stackQueryClient}>
<LayoutMain /> <div className='h-full overflow-hidden'>
<AuthProvider mustLogin={false}> <LayoutMain />
<TooltipProvider> <AuthProvider mustLogin={true}>
<main className='h-[calc(100%-3rem)] overflow-auto scrollbar'> <TooltipProvider>
<Outlet /> <main className={clsx('overflow-auto scrollbar', {
</main> 'h-[calc(100%-3rem)]': store.showBaseHeader,
</TooltipProvider> 'h-full': !store.showBaseHeader,
</AuthProvider> })}>
<TanStackRouterDevtools position="bottom-right" /> <Outlet />
<Toaster /> </main>
</div> </TooltipProvider>
</AuthProvider>
<TanStackRouterDevtools position="bottom-right" />
<Toaster />
</div>
</QueryClientProvider>
) )
} }

9
src/routes/demo.tsx Normal file
View File

@@ -0,0 +1,9 @@
import { createFileRoute } from '@tanstack/react-router'
import App from '@/pages/demo/page'
export const Route = createFileRoute('/demo')({
component: RouteComponent,
})
function RouteComponent() {
return <App />
}

View File

@@ -5,6 +5,7 @@ import pkgs from './package.json';
import tailwindcss from '@tailwindcss/vite'; import tailwindcss from '@tailwindcss/vite';
import { tanstackRouter } from '@tanstack/router-plugin/vite' import { tanstackRouter } from '@tanstack/router-plugin/vite'
import 'dotenv/config'; import 'dotenv/config';
const isDev = process.env.NODE_ENV === 'development'; const isDev = process.env.NODE_ENV === 'development';
const basename = isDev ? '/' : pkgs?.basename || '/'; const basename = isDev ? '/' : pkgs?.basename || '/';