diff --git a/electron.vite.config.ts b/electron.vite.config.ts
index 026303f0fc..d0a4a6bef8 100644
--- a/electron.vite.config.ts
+++ b/electron.vite.config.ts
@@ -103,7 +103,8 @@ export default defineConfig({
'@cherrystudio/ai-core/provider': resolve('packages/aiCore/src/core/providers'),
'@cherrystudio/ai-core/built-in/plugins': resolve('packages/aiCore/src/core/plugins/built-in'),
'@cherrystudio/ai-core': resolve('packages/aiCore/src'),
- '@cherrystudio/extension-table-plus': resolve('packages/extension-table-plus/src')
+ '@cherrystudio/extension-table-plus': resolve('packages/extension-table-plus/src'),
+ '@cherrystudio/ui': resolve('packages/ui/src')
}
},
optimizeDeps: {
diff --git a/package.json b/package.json
index e560d8e855..9785143c57 100644
--- a/package.json
+++ b/package.json
@@ -120,6 +120,7 @@
"@cherrystudio/embedjs-ollama": "^0.1.31",
"@cherrystudio/embedjs-openai": "^0.1.31",
"@cherrystudio/extension-table-plus": "workspace:^",
+ "@cherrystudio/ui": "workspace:*",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/modifiers": "^9.0.0",
"@dnd-kit/sortable": "^10.0.0",
diff --git a/packages/ui/README.md b/packages/ui/README.md
new file mode 100644
index 0000000000..0698bad4a6
--- /dev/null
+++ b/packages/ui/README.md
@@ -0,0 +1,220 @@
+# @cherrystudio/ui
+
+Cherry Studio UI 组件库 - 为 Cherry Studio 设计的 React 组件集合
+
+## 特性
+
+- 🎨 基于 Tailwind CSS 的现代化设计
+- 📦 支持 ESM 和 CJS 格式
+- 🔷 完整的 TypeScript 支持
+- 🚀 可以作为 npm 包发布
+- 🔧 开箱即用的常用 hooks 和工具函数
+
+## 安装
+
+```bash
+# 安装组件库
+npm install @cherrystudio/ui
+
+# 安装必需的 peer dependencies
+npm install @heroui/react framer-motion react react-dom tailwindcss
+```
+
+## 配置
+
+### 1. Tailwind CSS 配置
+
+在你的项目根目录创建 `tailwind.config.js` 文件:
+
+```javascript
+const { heroui } = require('@heroui/react')
+
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: [
+ // 你的应用内容
+ './src/**/*.{js,ts,jsx,tsx}',
+ './app/**/*.{js,ts,jsx,tsx}',
+ './pages/**/*.{js,ts,jsx,tsx}',
+ './components/**/*.{js,ts,jsx,tsx}',
+
+ // 包含 @cherrystudio/ui 组件
+ './node_modules/@cherrystudio/ui/dist/**/*.{js,ts,jsx,tsx}',
+
+ // 包含 HeroUI 主题
+ './node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}'
+ ],
+ theme: {
+ extend: {
+ // 你的自定义主题扩展
+ }
+ },
+ darkMode: 'class',
+ plugins: [
+ heroui({
+ // HeroUI 主题配置
+ // 参考: https://heroui.com/docs/customization/theme
+ })
+ ]
+}
+```
+
+### 2. CSS 导入
+
+在你的主 CSS 文件中导入 Tailwind:
+
+```css
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+```
+
+### 3. Provider 配置
+
+在你的 App 根组件中添加 HeroUI Provider:
+
+```tsx
+import { HeroUIProvider } from '@heroui/react'
+
+function App() {
+ return (
+
+ {/* 你的应用内容 */}
+
+ )
+}
+```
+
+## 使用
+
+### 基础组件
+
+```tsx
+import { Button, Input } from '@cherrystudio/ui'
+
+function App() {
+ return (
+
+
+ console.log(value)}
+ />
+
+ )
+}
+```
+
+### 分模块导入
+
+```tsx
+// 只导入组件
+import { Button } from '@cherrystudio/ui/components'
+
+// 只导入 hooks
+import { useDebounce, useLocalStorage } from '@cherrystudio/ui/hooks'
+
+// 只导入工具函数
+import { cn, formatFileSize } from '@cherrystudio/ui/utils'
+```
+
+## 开发
+
+```bash
+# 安装依赖
+yarn install
+
+# 开发模式(监听文件变化)
+yarn dev
+
+# 构建
+yarn build
+
+# 类型检查
+yarn type-check
+
+# 运行测试
+yarn test
+```
+
+## 目录结构
+
+```text
+src/
+├── components/ # React 组件
+│ ├── Button/ # 按钮组件
+│ ├── Input/ # 输入框组件
+│ └── index.ts # 组件导出
+├── hooks/ # React Hooks
+├── utils/ # 工具函数
+├── types/ # 类型定义
+└── index.ts # 主入口文件
+```
+
+## 组件列表
+
+### Button 按钮
+
+支持多种变体和尺寸的按钮组件。
+
+**Props:**
+
+- `variant`: 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger'
+- `size`: 'sm' | 'md' | 'lg'
+- `loading`: boolean
+- `fullWidth`: boolean
+- `leftIcon` / `rightIcon`: React.ReactNode
+
+### Input 输入框
+
+带有错误处理和密码显示切换的输入框组件。
+
+**Props:**
+
+- `type`: 'text' | 'password' | 'email' | 'number'
+- `error`: boolean
+- `errorMessage`: string
+- `onChange`: (value: string) => void
+
+## Hooks
+
+### useDebounce
+
+防抖处理,延迟执行状态更新。
+
+### useLocalStorage
+
+本地存储的 React Hook 封装。
+
+### useClickOutside
+
+检测点击元素外部区域。
+
+### useCopyToClipboard
+
+复制文本到剪贴板。
+
+## 工具函数
+
+### cn(...inputs)
+
+基于 clsx 的类名合并工具,支持条件类名。
+
+### formatFileSize(bytes)
+
+格式化文件大小显示。
+
+### debounce(func, delay)
+
+防抖函数。
+
+### throttle(func, delay)
+
+节流函数。
+
+## 许可证
+
+MIT
diff --git a/packages/ui/package.json b/packages/ui/package.json
new file mode 100644
index 0000000000..b35677bf05
--- /dev/null
+++ b/packages/ui/package.json
@@ -0,0 +1,97 @@
+{
+ "name": "@cherrystudio/ui",
+ "version": "1.0.0-alpha.1",
+ "description": "Cherry Studio UI Component Library - React Components for Cherry Studio",
+ "main": "dist/index.js",
+ "module": "dist/index.mjs",
+ "types": "dist/index.d.ts",
+ "react-native": "dist/index.js",
+ "scripts": {
+ "build": "tsdown",
+ "dev": "tsc -w",
+ "clean": "rm -rf dist",
+ "test": "vitest run",
+ "test:watch": "vitest",
+ "lint": "eslint src --ext .ts,.tsx --fix",
+ "type-check": "tsc --noEmit"
+ },
+ "keywords": [
+ "ui",
+ "components",
+ "react",
+ "tailwindcss",
+ "typescript",
+ "cherry-studio"
+ ],
+ "author": "Cherry Studio",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/CherryHQ/cherry-studio.git"
+ },
+ "bugs": {
+ "url": "https://github.com/CherryHQ/cherry-studio/issues"
+ },
+ "homepage": "https://github.com/CherryHQ/cherry-studio#readme",
+ "peerDependencies": {
+ "@heroui/react": "^2.8.4",
+ "framer-motion": "^11.0.0 || ^12.0.0",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
+ "tailwindcss": "^4.1.13"
+ },
+ "dependencies": {
+ "clsx": "^2.1.1",
+ "lucide-react": "^0.525.0"
+ },
+ "devDependencies": {
+ "@heroui/react": "^2.8.4",
+ "@types/react": "^19.0.12",
+ "@types/react-dom": "^19.0.4",
+ "framer-motion": "^12.23.12",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
+ "tsdown": "^0.12.9",
+ "typescript": "^5.6.2",
+ "vitest": "^3.2.4"
+ },
+ "sideEffects": false,
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "files": [
+ "dist",
+ "README.md"
+ ],
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "react-native": "./dist/index.js",
+ "import": "./dist/index.mjs",
+ "require": "./dist/index.js",
+ "default": "./dist/index.js"
+ },
+ "./components": {
+ "types": "./dist/components/index.d.ts",
+ "react-native": "./dist/components/index.js",
+ "import": "./dist/components/index.mjs",
+ "require": "./dist/components/index.js",
+ "default": "./dist/components/index.js"
+ },
+ "./hooks": {
+ "types": "./dist/hooks/index.d.ts",
+ "react-native": "./dist/hooks/index.js",
+ "import": "./dist/hooks/index.mjs",
+ "require": "./dist/hooks/index.js",
+ "default": "./dist/hooks/index.js"
+ },
+ "./utils": {
+ "types": "./dist/utils/index.d.ts",
+ "react-native": "./dist/utils/index.js",
+ "import": "./dist/utils/index.mjs",
+ "require": "./dist/utils/index.js",
+ "default": "./dist/utils/index.js"
+ }
+ },
+ "packageManager": "yarn@4.9.1"
+}
diff --git a/packages/ui/src/components/base/DividerWithText.tsx b/packages/ui/src/components/base/DividerWithText.tsx
new file mode 100644
index 0000000000..4359b921b5
--- /dev/null
+++ b/packages/ui/src/components/base/DividerWithText.tsx
@@ -0,0 +1,37 @@
+// Original: src/renderer/src/components/DividerWithText.tsx
+import React, { CSSProperties } from 'react'
+import styled from 'styled-components'
+
+interface DividerWithTextProps {
+ text: string
+ style?: CSSProperties
+}
+
+const DividerWithText: React.FC = ({ text, style }) => {
+ return (
+
+ {text}
+
+
+ )
+}
+
+const DividerContainer = styled.div`
+ display: flex;
+ align-items: center;
+ margin: 0px 0;
+`
+
+const DividerText = styled.span`
+ font-size: 12px;
+ color: var(--color-text-2);
+ margin-right: 8px;
+`
+
+const DividerLine = styled.div`
+ flex: 1;
+ height: 1px;
+ background-color: var(--color-border);
+`
+
+export default DividerWithText
diff --git a/packages/ui/src/components/base/IndicatorLight.tsx b/packages/ui/src/components/base/IndicatorLight.tsx
new file mode 100644
index 0000000000..21f2d033ac
--- /dev/null
+++ b/packages/ui/src/components/base/IndicatorLight.tsx
@@ -0,0 +1,45 @@
+// Original: src/renderer/src/components/IndicatorLight.tsx
+import React from 'react'
+import styled from 'styled-components'
+
+interface IndicatorLightProps {
+ color: string
+ size?: number
+ shadow?: boolean
+ style?: React.CSSProperties
+ animation?: boolean
+}
+
+const Light = styled.div<{
+ color: string
+ size: number
+ shadow?: boolean
+ style?: React.CSSProperties
+ animation?: boolean
+}>`
+ width: ${({ size }) => size}px;
+ height: ${({ size }) => size}px;
+ border-radius: 50%;
+ background-color: ${({ color }) => color};
+ box-shadow: ${({ shadow, color }) => (shadow ? `0 0 6px ${color}` : 'none')};
+ animation: ${({ animation }) => (animation ? 'pulse 2s infinite' : 'none')};
+
+ @keyframes pulse {
+ 0% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.6;
+ }
+ 100% {
+ opacity: 1;
+ }
+ }
+`
+
+const IndicatorLight: React.FC = ({ color, size = 8, shadow = true, style, animation = true }) => {
+ const actualColor = color === 'green' ? '#22c55e' : color
+ return
+}
+
+export default IndicatorLight
diff --git a/packages/ui/src/components/base/Spinner.tsx b/packages/ui/src/components/base/Spinner.tsx
new file mode 100644
index 0000000000..1fa5159a7e
--- /dev/null
+++ b/packages/ui/src/components/base/Spinner.tsx
@@ -0,0 +1,45 @@
+// Original: src/renderer/src/components/Spinner.tsx
+import { motion } from 'framer-motion'
+import { Search } from 'lucide-react'
+import styled from 'styled-components'
+
+interface Props {
+ text: React.ReactNode
+}
+
+// Define variants for the spinner animation
+const spinnerVariants = {
+ defaultColor: {
+ color: '#2a2a2a'
+ },
+ dimmed: {
+ color: '#8C9296'
+ }
+}
+
+export default function Spinner({ text }: Props) {
+ return (
+
+
+ {text}
+
+ )
+}
+const SearchWrapper = styled.div`
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ /* font-size: 14px; */
+ padding: 0px;
+ /* padding-left: 0; */
+`
+const Searching = motion.create(SearchWrapper)
diff --git a/packages/ui/src/components/base/TextBadge.tsx b/packages/ui/src/components/base/TextBadge.tsx
new file mode 100644
index 0000000000..ab49fd3e0c
--- /dev/null
+++ b/packages/ui/src/components/base/TextBadge.tsx
@@ -0,0 +1,23 @@
+// Original: src/renderer/src/components/TextBadge.tsx
+import { FC } from 'react'
+import styled from 'styled-components'
+
+interface Props {
+ text: string
+ style?: React.CSSProperties
+}
+
+const TextBadge: FC = ({ text, style }) => {
+ return {text}
+}
+
+const Container = styled.span`
+ font-size: 12px;
+ color: var(--color-primary);
+ background: var(--color-primary-bg);
+ padding: 2px 6px;
+ border-radius: 4px;
+ font-weight: 500;
+`
+
+export default TextBadge
diff --git a/packages/ui/src/components/display/Ellipsis.tsx b/packages/ui/src/components/display/Ellipsis.tsx
new file mode 100644
index 0000000000..45c60fdd40
--- /dev/null
+++ b/packages/ui/src/components/display/Ellipsis.tsx
@@ -0,0 +1,36 @@
+// Original: src/renderer/src/components/Ellipsis/index.tsx
+import type { HTMLAttributes } from 'react'
+import styled, { css } from 'styled-components'
+
+type Props = {
+ maxLine?: number
+} & HTMLAttributes
+
+const Ellipsis = (props: Props) => {
+ const { maxLine = 1, children, ...rest } = props
+ return (
+
+ {children}
+
+ )
+}
+
+const multiLineEllipsis = css<{ $maxLine: number }>`
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: ${({ $maxLine }) => $maxLine};
+ overflow-wrap: break-word;
+`
+
+const singleLineEllipsis = css`
+ display: block;
+ white-space: nowrap;
+`
+
+const EllipsisContainer = styled.div<{ $maxLine: number }>`
+ overflow: hidden;
+ text-overflow: ellipsis;
+ ${({ $maxLine }) => ($maxLine > 1 ? multiLineEllipsis : singleLineEllipsis)}
+`
+
+export default Ellipsis
diff --git a/packages/ui/src/components/display/ExpandableText.tsx b/packages/ui/src/components/display/ExpandableText.tsx
new file mode 100644
index 0000000000..c8010bf698
--- /dev/null
+++ b/packages/ui/src/components/display/ExpandableText.tsx
@@ -0,0 +1,52 @@
+// Original: src/renderer/src/components/ExpandableText.tsx
+import { Button } from 'antd'
+import { memo, useCallback, useMemo, useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import styled from 'styled-components'
+
+interface ExpandableTextProps {
+ text: string
+ style?: React.CSSProperties
+}
+
+const ExpandableText = ({
+ ref,
+ text,
+ style
+}: ExpandableTextProps & { ref?: React.RefObject | null }) => {
+ const { t } = useTranslation()
+ const [isExpanded, setIsExpanded] = useState(false)
+
+ const toggleExpand = useCallback(() => {
+ setIsExpanded((prev) => !prev)
+ }, [])
+
+ const button = useMemo(() => {
+ return (
+
+ )
+ }, [isExpanded, t, toggleExpand])
+
+ return (
+
+ {text}
+ {button}
+
+ )
+}
+
+const Container = styled.div<{ $expanded?: boolean }>`
+ display: flex;
+ flex-direction: ${(props) => (props.$expanded ? 'column' : 'row')};
+`
+
+const TextContainer = styled.div<{ $expanded?: boolean }>`
+ overflow: hidden;
+ text-overflow: ${(props) => (props.$expanded ? 'unset' : 'ellipsis')};
+ white-space: ${(props) => (props.$expanded ? 'normal' : 'nowrap')};
+ line-height: ${(props) => (props.$expanded ? 'unset' : '30px')};
+`
+
+export default memo(ExpandableText)
diff --git a/packages/ui/src/components/icons/ToolsCallingIcon.tsx b/packages/ui/src/components/icons/ToolsCallingIcon.tsx
new file mode 100644
index 0000000000..4f0b7f96e3
--- /dev/null
+++ b/packages/ui/src/components/icons/ToolsCallingIcon.tsx
@@ -0,0 +1,32 @@
+// Original: src/renderer/src/components/Icons/ToolsCallingIcon.tsx
+import { ToolOutlined } from '@ant-design/icons'
+import { Tooltip } from 'antd'
+import React, { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import styled from 'styled-components'
+
+const ToolsCallingIcon: FC, HTMLElement>> = (props) => {
+ const { t } = useTranslation()
+
+ return (
+
+
+
+
+
+ )
+}
+
+const Container = styled.div`
+ display: flex;
+ justify-content: center;
+ align-items: center;
+`
+
+const Icon = styled(ToolOutlined)`
+ color: var(--color-primary);
+ font-size: 15px;
+ margin-right: 6px;
+`
+
+export default ToolsCallingIcon
diff --git a/packages/ui/src/components/icons/VisionIcon.tsx b/packages/ui/src/components/icons/VisionIcon.tsx
new file mode 100644
index 0000000000..14de121b3c
--- /dev/null
+++ b/packages/ui/src/components/icons/VisionIcon.tsx
@@ -0,0 +1,31 @@
+// Original: src/renderer/src/components/Icons/VisionIcon.tsx
+import { Tooltip } from 'antd'
+import { ImageIcon } from 'lucide-react'
+import React, { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import styled from 'styled-components'
+
+const VisionIcon: FC, HTMLElement>> = (props) => {
+ const { t } = useTranslation()
+
+ return (
+
+
+
+
+
+ )
+}
+
+const Container = styled.div`
+ display: flex;
+ justify-content: center;
+ align-items: center;
+`
+
+const Icon = styled(ImageIcon)`
+ color: var(--color-primary);
+ margin-right: 6px;
+`
+
+export default VisionIcon
diff --git a/packages/ui/src/components/icons/WebSearchIcon.tsx b/packages/ui/src/components/icons/WebSearchIcon.tsx
new file mode 100644
index 0000000000..69646c3dd7
--- /dev/null
+++ b/packages/ui/src/components/icons/WebSearchIcon.tsx
@@ -0,0 +1,32 @@
+// Original: src/renderer/src/components/Icons/WebSearchIcon.tsx
+import { GlobalOutlined } from '@ant-design/icons'
+import { Tooltip } from 'antd'
+import React, { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import styled from 'styled-components'
+
+const WebSearchIcon: FC, HTMLElement>> = (props) => {
+ const { t } = useTranslation()
+
+ return (
+
+
+
+
+
+ )
+}
+
+const Container = styled.div`
+ display: flex;
+ justify-content: center;
+ align-items: center;
+`
+
+const Icon = styled(GlobalOutlined)`
+ color: var(--color-link);
+ font-size: 15px;
+ margin-right: 6px;
+`
+
+export default WebSearchIcon
diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts
new file mode 100644
index 0000000000..97104d11af
--- /dev/null
+++ b/packages/ui/src/components/index.ts
@@ -0,0 +1,21 @@
+// Base Components
+export { default as DividerWithText } from './base/DividerWithText'
+export { default as IndicatorLight } from './base/IndicatorLight'
+export { default as Spinner } from './base/Spinner'
+export { default as TextBadge } from './base/TextBadge'
+
+// Display Components
+export { default as Ellipsis } from './display/Ellipsis'
+export { default as ExpandableText } from './display/ExpandableText'
+
+// Layout Components
+export { default as HorizontalScrollContainer } from './layout/HorizontalScrollContainer'
+export { default as Scrollbar } from './layout/Scrollbar'
+
+// Icon Components
+export { default as ToolsCallingIcon } from './icons/ToolsCallingIcon'
+export { default as VisionIcon } from './icons/VisionIcon'
+export { default as WebSearchIcon } from './icons/WebSearchIcon'
+
+// Interactive Components
+export { default as InfoTooltip } from './interactive/InfoTooltip'
diff --git a/packages/ui/src/components/interactive/InfoTooltip.tsx b/packages/ui/src/components/interactive/InfoTooltip.tsx
new file mode 100644
index 0000000000..53aa0c2a85
--- /dev/null
+++ b/packages/ui/src/components/interactive/InfoTooltip.tsx
@@ -0,0 +1,21 @@
+// Original: src/renderer/src/components/TooltipIcons/InfoTooltip.tsx
+import { Tooltip, TooltipProps } from 'antd'
+import { Info } from 'lucide-react'
+
+type InheritedTooltipProps = Omit
+
+interface InfoTooltipProps extends InheritedTooltipProps {
+ iconColor?: string
+ iconSize?: string | number
+ iconStyle?: React.CSSProperties
+}
+
+const InfoTooltip = ({ iconColor = 'var(--color-text-2)', iconSize = 14, iconStyle, ...rest }: InfoTooltipProps) => {
+ return (
+
+
+
+ )
+}
+
+export default InfoTooltip
\ No newline at end of file
diff --git a/packages/ui/src/components/layout/HorizontalScrollContainer.tsx b/packages/ui/src/components/layout/HorizontalScrollContainer.tsx
new file mode 100644
index 0000000000..78b45481d6
--- /dev/null
+++ b/packages/ui/src/components/layout/HorizontalScrollContainer.tsx
@@ -0,0 +1,181 @@
+// Original: src/renderer/src/components/HorizontalScrollContainer/index.tsx
+import { ChevronRight } from 'lucide-react'
+import { useEffect, useRef, useState } from 'react'
+import styled from 'styled-components'
+
+import Scrollbar from './Scrollbar'
+
+/**
+ * 水平滚动容器
+ * @param children 子元素
+ * @param dependencies 依赖项
+ * @param scrollDistance 滚动距离
+ * @param className 类名
+ * @param gap 间距
+ * @param expandable 是否可展开
+ */
+export interface HorizontalScrollContainerProps {
+ children: React.ReactNode
+ dependencies?: readonly unknown[]
+ scrollDistance?: number
+ className?: string
+ gap?: string
+ expandable?: boolean
+}
+
+const HorizontalScrollContainer: React.FC = ({
+ children,
+ dependencies = [],
+ scrollDistance = 200,
+ className,
+ gap = '8px',
+ expandable = false
+}) => {
+ const scrollRef = useRef(null)
+ const [canScroll, setCanScroll] = useState(false)
+ const [isExpanded, setIsExpanded] = useState(false)
+ const [isScrolledToEnd, setIsScrolledToEnd] = useState(false)
+
+ const handleScrollRight = (event: React.MouseEvent) => {
+ scrollRef.current?.scrollBy({ left: scrollDistance, behavior: 'smooth' })
+ event.stopPropagation()
+ }
+
+ const handleContainerClick = (e: React.MouseEvent) => {
+ if (expandable) {
+ // 确保不是点击了其他交互元素(如 tag 的关闭按钮)
+ const target = e.target as HTMLElement
+ if (!target.closest('[data-no-expand]')) {
+ setIsExpanded(!isExpanded)
+ }
+ }
+ }
+
+ const checkScrollability = () => {
+ const scrollElement = scrollRef.current
+ if (scrollElement) {
+ const parentElement = scrollElement.parentElement
+ const availableWidth = parentElement ? parentElement.clientWidth : scrollElement.clientWidth
+
+ // 确保容器不会超出可用宽度
+ const canScrollValue = scrollElement.scrollWidth > Math.min(availableWidth, scrollElement.clientWidth)
+ setCanScroll(canScrollValue)
+
+ // 检查是否滚动到最右侧
+ if (canScrollValue) {
+ const isAtEnd = Math.abs(scrollElement.scrollLeft + scrollElement.clientWidth - scrollElement.scrollWidth) <= 1
+ setIsScrolledToEnd(isAtEnd)
+ } else {
+ setIsScrolledToEnd(false)
+ }
+ }
+ }
+
+ useEffect(() => {
+ const scrollElement = scrollRef.current
+ if (!scrollElement) return
+
+ checkScrollability()
+
+ const handleScroll = () => {
+ checkScrollability()
+ }
+
+ const resizeObserver = new ResizeObserver(checkScrollability)
+ resizeObserver.observe(scrollElement)
+
+ scrollElement.addEventListener('scroll', handleScroll)
+ window.addEventListener('resize', checkScrollability)
+
+ return () => {
+ resizeObserver.disconnect()
+ scrollElement.removeEventListener('scroll', handleScroll)
+ window.removeEventListener('resize', checkScrollability)
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, dependencies)
+
+ return (
+
+
+ {children}
+
+ {canScroll && !isExpanded && !isScrolledToEnd && (
+
+
+
+ )}
+
+ )
+}
+
+const Container = styled.div<{ $expandable?: boolean; $disableHoverButton?: boolean }>`
+ display: flex;
+ align-items: center;
+ flex: 1 1 auto;
+ min-width: 0;
+ max-width: 100%;
+ position: relative;
+ cursor: ${(props) => (props.$expandable ? 'pointer' : 'default')};
+
+ ${(props) =>
+ !props.$disableHoverButton &&
+ `
+ &:hover {
+ .scroll-right-button {
+ opacity: 1;
+ }
+ }
+ `}
+`
+
+const ScrollContent = styled(Scrollbar)<{
+ $gap: string
+ $isExpanded?: boolean
+ $expandable?: boolean
+}>`
+ display: flex;
+ overflow-x: ${(props) => (props.$expandable && props.$isExpanded ? 'hidden' : 'auto')};
+ overflow-y: hidden;
+ white-space: ${(props) => (props.$expandable && props.$isExpanded ? 'normal' : 'nowrap')};
+ gap: ${(props) => props.$gap};
+ flex-wrap: ${(props) => (props.$expandable && props.$isExpanded ? 'wrap' : 'nowrap')};
+
+ &::-webkit-scrollbar {
+ display: none;
+ }
+`
+
+const ScrollButton = styled.div`
+ position: absolute;
+ right: 8px;
+ top: 50%;
+ transform: translateY(-50%);
+ z-index: 1;
+ opacity: 0;
+ transition: opacity 0.2s ease-in-out;
+ cursor: pointer;
+ background: var(--color-background);
+ border-radius: 50%;
+ width: 24px;
+ height: 24px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow:
+ 0 6px 16px 0 rgba(0, 0, 0, 0.08),
+ 0 3px 6px -4px rgba(0, 0, 0, 0.12),
+ 0 9px 28px 8px rgba(0, 0, 0, 0.05);
+ color: var(--color-text-2);
+
+ &:hover {
+ color: var(--color-text);
+ background: var(--color-list-item);
+ }
+`
+
+export default HorizontalScrollContainer
diff --git a/packages/ui/src/components/layout/Scrollbar.tsx b/packages/ui/src/components/layout/Scrollbar.tsx
new file mode 100644
index 0000000000..4081a716ad
--- /dev/null
+++ b/packages/ui/src/components/layout/Scrollbar.tsx
@@ -0,0 +1,75 @@
+// Original: src/renderer/src/components/Scrollbar/index.tsx
+import { throttle } from 'lodash'
+import { FC, useCallback, useEffect, useRef, useState } from 'react'
+import styled from 'styled-components'
+
+export interface ScrollbarProps extends Omit, 'onScroll'> {
+ ref?: React.Ref
+ onScroll?: () => void // Custom onScroll prop for useScrollPosition's handleScroll
+}
+
+const Scrollbar: FC = ({ ref: passedRef, children, onScroll: externalOnScroll, ...htmlProps }) => {
+ const [isScrolling, setIsScrolling] = useState(false)
+ const timeoutRef = useRef(null)
+
+ const clearScrollingTimeout = useCallback(() => {
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current)
+ timeoutRef.current = null
+ }
+ }, [])
+
+ const handleScroll = useCallback(() => {
+ setIsScrolling(true)
+ clearScrollingTimeout()
+ timeoutRef.current = setTimeout(() => {
+ setIsScrolling(false)
+ timeoutRef.current = null
+ }, 1500)
+ }, [clearScrollingTimeout])
+
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ const throttledInternalScrollHandler = useCallback(throttle(handleScroll, 100, { leading: true, trailing: true }), [
+ handleScroll
+ ])
+
+ // Combined scroll handler
+ const combinedOnScroll = useCallback(() => {
+ throttledInternalScrollHandler()
+ if (externalOnScroll) {
+ externalOnScroll()
+ }
+ }, [throttledInternalScrollHandler, externalOnScroll])
+
+ useEffect(() => {
+ return () => {
+ clearScrollingTimeout()
+ throttledInternalScrollHandler.cancel()
+ }
+ }, [throttledInternalScrollHandler, clearScrollingTimeout])
+
+ return (
+
+ {children}
+
+ )
+}
+
+const ScrollBarContainer = styled.div<{ $isScrolling: boolean }>`
+ overflow-y: auto;
+ &::-webkit-scrollbar-thumb {
+ transition: background 2s ease;
+ background: ${(props) => (props.$isScrolling ? 'var(--color-scrollbar-thumb)' : 'transparent')};
+ &:hover {
+ background: var(--color-scrollbar-thumb-hover);
+ }
+ }
+`
+
+Scrollbar.displayName = 'Scrollbar'
+
+export default Scrollbar
diff --git a/packages/ui/src/hooks/index.ts b/packages/ui/src/hooks/index.ts
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts
new file mode 100644
index 0000000000..bd424b2e8b
--- /dev/null
+++ b/packages/ui/src/index.ts
@@ -0,0 +1,5 @@
+// 主入口文件 - 导出所有公共API
+export * from './components'
+// export * from './hooks'
+// export * from './types'
+export * from './utils'
diff --git a/packages/ui/src/utils/index.ts b/packages/ui/src/utils/index.ts
new file mode 100644
index 0000000000..9eb12d4de3
--- /dev/null
+++ b/packages/ui/src/utils/index.ts
@@ -0,0 +1,9 @@
+import { type ClassValue, clsx } from 'clsx'
+
+/**
+ * 合并CSS类名的工具函数
+ * 基于clsx,支持条件类名和Tailwind CSS
+ */
+export function cn(...inputs: ClassValue[]) {
+ return clsx(inputs)
+}
diff --git a/packages/ui/tailwind.config.js b/packages/ui/tailwind.config.js
new file mode 100644
index 0000000000..58fe3624ac
--- /dev/null
+++ b/packages/ui/tailwind.config.js
@@ -0,0 +1,28 @@
+// Tailwind config for UI component library
+// This config is used for development and provides a template for consumers
+
+let heroui
+try {
+ // Try to load heroui if available (dev environment)
+ heroui = require('@heroui/react').heroui
+} catch (e) {
+ // Fallback for environments without heroui
+ heroui = () => ({})
+}
+
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: [
+ // 扫描当前包的所有组件文件
+ './src/**/*.{js,ts,jsx,tsx}',
+ // 扫描 HeroUI 的组件样式(如果存在)
+ './node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}'
+ ],
+ theme: {
+ extend: {
+ // 基础组件库主题扩展
+ }
+ },
+ darkMode: 'class',
+ plugins: [heroui()]
+}
diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json
new file mode 100644
index 0000000000..67c334760a
--- /dev/null
+++ b/packages/ui/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "declaration": true,
+ "outDir": "./dist",
+ "rootDir": "./src",
+ "strict": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "allowSyntheticDefaultImports": true,
+ "jsx": "react-jsx",
+ "lib": ["DOM", "DOM.Iterable", "ES6"],
+ "incremental": true,
+ "isolatedModules": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "node_modules",
+ "dist",
+ "**/*.test.*",
+ "**/__tests__/**"
+ ]
+}
diff --git a/packages/ui/tsdown.config.ts b/packages/ui/tsdown.config.ts
new file mode 100644
index 0000000000..569c983b40
--- /dev/null
+++ b/packages/ui/tsdown.config.ts
@@ -0,0 +1,16 @@
+import { defineConfig } from 'tsdown'
+
+export default defineConfig({
+ entry: {
+ index: 'src/index.ts',
+ 'components/index': 'src/components/index.ts',
+ 'hooks/index': 'src/hooks/index.ts',
+ 'utils/index': 'src/utils/index.ts'
+ },
+ outDir: 'dist',
+ format: ['esm', 'cjs'],
+ clean: true,
+ dts: true,
+ tsconfig: 'tsconfig.json',
+ external: ['react', 'react-dom']
+})
diff --git a/src/renderer/src/components/DraggableList/virtual-list.tsx b/src/renderer/src/components/DraggableList/virtual-list.tsx
index b2efe7c247..67089332ae 100644
--- a/src/renderer/src/components/DraggableList/virtual-list.tsx
+++ b/src/renderer/src/components/DraggableList/virtual-list.tsx
@@ -1,3 +1,4 @@
+import { Scrollbar } from '@cherrystudio/ui'
import {
DragDropContext,
Draggable,
@@ -8,7 +9,6 @@ import {
OnDragStartResponder,
ResponderProvided
} from '@hello-pangea/dnd'
-import Scrollbar from '@renderer/components/Scrollbar'
import { droppableReorder } from '@renderer/utils'
import { type ScrollToOptions, useVirtualizer, type VirtualItem } from '@tanstack/react-virtual'
import { type Key, memo, useCallback, useImperativeHandle, useRef } from 'react'
diff --git a/tsconfig.web.json b/tsconfig.web.json
index db2f95a553..82d5a573db 100644
--- a/tsconfig.web.json
+++ b/tsconfig.web.json
@@ -9,7 +9,8 @@
"packages/mcp-trace/**/*",
"packages/aiCore/src/**/*",
"src/main/integration/cherryin/index.js",
- "packages/extension-table-plus/**/*"
+ "packages/extension-table-plus/**/*",
+ "packages/ui/**/*"
],
"compilerOptions": {
"composite": true,
@@ -29,7 +30,8 @@
"@cherrystudio/ai-core/built-in/plugins": ["packages/aiCore/src/core/plugins/built-in/index.ts"],
"@cherrystudio/ai-core/*": ["packages/aiCore/src/*"],
"@cherrystudio/ai-core": ["packages/aiCore/src/index.ts"],
- "@cherrystudio/extension-table-plus": ["packages/extension-table-plus/src/index.ts"]
+ "@cherrystudio/extension-table-plus": ["packages/extension-table-plus/src/index.ts"],
+ "@cherrystudio/ui": ["packages/ui/src/index.ts"]
},
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
diff --git a/yarn.lock b/yarn.lock
index 4481e24ab4..b48fd0fa1c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2525,6 +2525,30 @@ __metadata:
languageName: unknown
linkType: soft
+"@cherrystudio/ui@workspace:*, @cherrystudio/ui@workspace:packages/ui":
+ version: 0.0.0-use.local
+ resolution: "@cherrystudio/ui@workspace:packages/ui"
+ dependencies:
+ "@heroui/react": "npm:^2.8.4"
+ "@types/react": "npm:^19.0.12"
+ "@types/react-dom": "npm:^19.0.4"
+ clsx: "npm:^2.1.1"
+ framer-motion: "npm:^12.23.12"
+ lucide-react: "npm:^0.525.0"
+ react: "npm:^19.0.0"
+ react-dom: "npm:^19.0.0"
+ tsdown: "npm:^0.12.9"
+ typescript: "npm:^5.6.2"
+ vitest: "npm:^3.2.4"
+ peerDependencies:
+ "@heroui/react": ^2.8.4
+ framer-motion: ^11.0.0 || ^12.0.0
+ react: ^19.0.0
+ react-dom: ^19.0.0
+ tailwindcss: ^4.1.13
+ languageName: unknown
+ linkType: soft
+
"@chevrotain/cst-dts-gen@npm:11.0.3":
version: 11.0.3
resolution: "@chevrotain/cst-dts-gen@npm:11.0.3"
@@ -4134,6 +4158,33 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/accordion@npm:2.2.23":
+ version: 2.2.23
+ resolution: "@heroui/accordion@npm:2.2.23"
+ dependencies:
+ "@heroui/aria-utils": "npm:2.2.23"
+ "@heroui/divider": "npm:2.2.19"
+ "@heroui/dom-animation": "npm:2.1.10"
+ "@heroui/framer-utils": "npm:2.1.22"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-icons": "npm:2.1.10"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-aria-accordion": "npm:2.2.17"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-stately/tree": "npm:3.9.2"
+ "@react-types/accordion": "npm:3.0.0-alpha.26"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/1de0fedf840968f8da73dd181fd3af1294155f4b1d30a5318cceaba1cf43d6ac6eaee68b977f7d28bc1ec0f80a9407c6389054cf2e937f11adce4b632b4de90d
+ languageName: node
+ linkType: hard
+
"@heroui/alert@npm:2.2.25":
version: 2.2.25
resolution: "@heroui/alert@npm:2.2.25"
@@ -4152,6 +4203,24 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/alert@npm:2.2.26":
+ version: 2.2.26
+ resolution: "@heroui/alert@npm:2.2.26"
+ dependencies:
+ "@heroui/button": "npm:2.2.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-icons": "npm:2.1.10"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@react-stately/utils": "npm:3.10.8"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.19"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/477adf434f00d9bb8797a4c698dbc2f45ad5fc7ac5b88083bc9b4d9db332e887c20314773e964878dbe516e88be32db53d9e4263833082ba7fd0e9658bc2fdee
+ languageName: node
+ linkType: hard
+
"@heroui/aria-utils@npm:2.2.22":
version: 2.2.22
resolution: "@heroui/aria-utils@npm:2.2.22"
@@ -4168,6 +4237,22 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/aria-utils@npm:2.2.23":
+ version: 2.2.23
+ resolution: "@heroui/aria-utils@npm:2.2.23"
+ dependencies:
+ "@heroui/system": "npm:2.4.22"
+ "@react-aria/utils": "npm:3.30.1"
+ "@react-stately/collections": "npm:3.12.7"
+ "@react-types/overlays": "npm:3.9.1"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/f71d144c3b44d4fe27a94b74f5b6885a8ee94879fe3569f9edbe251bc35af61d3cb91ffca2bbad3930708dcd2853e0a3d9de37fcc8d5e6412b09dbdbffe7ce62
+ languageName: node
+ linkType: hard
+
"@heroui/autocomplete@npm:2.3.27":
version: 2.3.27
resolution: "@heroui/autocomplete@npm:2.3.27"
@@ -4198,6 +4283,36 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/autocomplete@npm:2.3.28":
+ version: 2.3.28
+ resolution: "@heroui/autocomplete@npm:2.3.28"
+ dependencies:
+ "@heroui/aria-utils": "npm:2.2.23"
+ "@heroui/button": "npm:2.2.26"
+ "@heroui/form": "npm:2.1.26"
+ "@heroui/input": "npm:2.4.27"
+ "@heroui/listbox": "npm:2.3.25"
+ "@heroui/popover": "npm:2.3.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/scroll-shadow": "npm:2.3.17"
+ "@heroui/shared-icons": "npm:2.1.10"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-safe-layout-effect": "npm:2.1.8"
+ "@react-aria/combobox": "npm:3.13.1"
+ "@react-aria/i18n": "npm:3.12.12"
+ "@react-stately/combobox": "npm:3.11.1"
+ "@react-types/combobox": "npm:3.13.8"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/1d56cf6df8441c8c6938584790c91f86cf108a8ccd25f430a1f89dba21e585eaaa4b7b478d614e14a04eaf5f6760a7e8ae863c465032602ab1062aeb007a0c00
+ languageName: node
+ linkType: hard
+
"@heroui/avatar@npm:2.2.21":
version: 2.2.21
resolution: "@heroui/avatar@npm:2.2.21"
@@ -4272,6 +4387,28 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/button@npm:2.2.26":
+ version: 2.2.26
+ resolution: "@heroui/button@npm:2.2.26"
+ dependencies:
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/ripple": "npm:2.2.19"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/spinner": "npm:2.2.23"
+ "@heroui/use-aria-button": "npm:2.2.19"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/056498f0def249a8a16abc15df20f9838e27fd17f6161038c3ea4e55ddbacba5dddebe7478780414183a02b343a908fbbef35d42293bed9c4cb8d605bd7c3662
+ languageName: node
+ linkType: hard
+
"@heroui/calendar@npm:2.2.25":
version: 2.2.25
resolution: "@heroui/calendar@npm:2.2.25"
@@ -4305,6 +4442,39 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/calendar@npm:2.2.26":
+ version: 2.2.26
+ resolution: "@heroui/calendar@npm:2.2.26"
+ dependencies:
+ "@heroui/button": "npm:2.2.26"
+ "@heroui/dom-animation": "npm:2.1.10"
+ "@heroui/framer-utils": "npm:2.1.22"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-icons": "npm:2.1.10"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-aria-button": "npm:2.2.19"
+ "@internationalized/date": "npm:3.9.0"
+ "@react-aria/calendar": "npm:3.9.1"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/i18n": "npm:3.12.12"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-aria/visually-hidden": "npm:3.8.27"
+ "@react-stately/calendar": "npm:3.8.4"
+ "@react-stately/utils": "npm:3.10.8"
+ "@react-types/button": "npm:3.14.0"
+ "@react-types/calendar": "npm:3.7.4"
+ "@react-types/shared": "npm:3.32.0"
+ scroll-into-view-if-needed: "npm:3.0.10"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/199d95ede266453c2a9da4bcd8ca2da6306d4b153f87d7428f7aadb1701c723e2a86b87987df6b11ff4e9abd4249aaf5e93acdb17d1c283c5ee71276a765a77e
+ languageName: node
+ linkType: hard
+
"@heroui/card@npm:2.2.24":
version: 2.2.24
resolution: "@heroui/card@npm:2.2.24"
@@ -4351,6 +4521,31 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/checkbox@npm:2.3.26":
+ version: 2.3.26
+ resolution: "@heroui/checkbox@npm:2.3.26"
+ dependencies:
+ "@heroui/form": "npm:2.1.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-callback-ref": "npm:2.1.8"
+ "@heroui/use-safe-layout-effect": "npm:2.1.8"
+ "@react-aria/checkbox": "npm:3.16.1"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-stately/checkbox": "npm:3.7.1"
+ "@react-stately/toggle": "npm:3.9.1"
+ "@react-types/checkbox": "npm:3.10.1"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/ae05352e70d0f2297ba481c96059391c0f118bdebcc006d2f04e80926351466729fd4d79d338a3c6616c287018a2c056cceae52952777cc3acceb457f13cdff0
+ languageName: node
+ linkType: hard
+
"@heroui/chip@npm:2.2.21":
version: 2.2.21
resolution: "@heroui/chip@npm:2.2.21"
@@ -4384,6 +4579,21 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/code@npm:2.2.20":
+ version: 2.2.20
+ resolution: "@heroui/code@npm:2.2.20"
+ dependencies:
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/system-rsc": "npm:2.3.19"
+ peerDependencies:
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/ca736c3e4c8a54faa1d45bda9a900227346bcf468176c58601a845d7e97a9455430d5304b49fa78934375cbbf4227f2240633030521607fb88382db3d9066290
+ languageName: node
+ linkType: hard
+
"@heroui/date-input@npm:2.3.25":
version: 2.3.25
resolution: "@heroui/date-input@npm:2.3.25"
@@ -4406,6 +4616,28 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/date-input@npm:2.3.26":
+ version: 2.3.26
+ resolution: "@heroui/date-input@npm:2.3.26"
+ dependencies:
+ "@heroui/form": "npm:2.1.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@internationalized/date": "npm:3.9.0"
+ "@react-aria/datepicker": "npm:3.15.1"
+ "@react-aria/i18n": "npm:3.12.12"
+ "@react-stately/datepicker": "npm:3.15.1"
+ "@react-types/datepicker": "npm:3.13.1"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/4d0370beed2909f38e697aa52de43683b90dfe637b87fe16eaf151df076f0a1f3d67f09d90345ba82ab04ff9484a43f1cdeaf8fdd4120161f68206acc7effb18
+ languageName: node
+ linkType: hard
+
"@heroui/date-picker@npm:2.3.26":
version: 2.3.26
resolution: "@heroui/date-picker@npm:2.3.26"
@@ -4436,6 +4668,36 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/date-picker@npm:2.3.27":
+ version: 2.3.27
+ resolution: "@heroui/date-picker@npm:2.3.27"
+ dependencies:
+ "@heroui/aria-utils": "npm:2.2.23"
+ "@heroui/button": "npm:2.2.26"
+ "@heroui/calendar": "npm:2.2.26"
+ "@heroui/date-input": "npm:2.3.26"
+ "@heroui/form": "npm:2.1.26"
+ "@heroui/popover": "npm:2.3.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-icons": "npm:2.1.10"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@internationalized/date": "npm:3.9.0"
+ "@react-aria/datepicker": "npm:3.15.1"
+ "@react-aria/i18n": "npm:3.12.12"
+ "@react-stately/datepicker": "npm:3.15.1"
+ "@react-stately/utils": "npm:3.10.8"
+ "@react-types/datepicker": "npm:3.13.1"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/c9e3be21ee999eda29397e6e1ee15050f363b7246787a2cd00914c9a3509711652ad5dcfc8eb9fd0f8781e09fd74c5b7819415b70fe3f33ff8edea53af7c4ccf
+ languageName: node
+ linkType: hard
+
"@heroui/divider@npm:2.2.18":
version: 2.2.18
resolution: "@heroui/divider@npm:2.2.18"
@@ -4451,6 +4713,21 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/divider@npm:2.2.19":
+ version: 2.2.19
+ resolution: "@heroui/divider@npm:2.2.19"
+ dependencies:
+ "@heroui/react-rsc-utils": "npm:2.1.9"
+ "@heroui/system-rsc": "npm:2.3.19"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/a8ca5c10a67d99570af8b8e01bdc5119237abc300ecc3365a0dfae31a0be842bb85fee81bc7af57e8e84ca277f2d2ecff1f1e325e3138d0391595b90bb78af99
+ languageName: node
+ linkType: hard
+
"@heroui/dom-animation@npm:2.1.10":
version: 2.1.10
resolution: "@heroui/dom-animation@npm:2.1.10"
@@ -4477,6 +4754,23 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/drawer@npm:2.2.23":
+ version: 2.2.23
+ resolution: "@heroui/drawer@npm:2.2.23"
+ dependencies:
+ "@heroui/framer-utils": "npm:2.1.22"
+ "@heroui/modal": "npm:2.2.23"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/5600e9fecda5b72c77a977651f6d98646ccf5a658e72d74860cd352144758d77eb7580cb3821c0a57e64d7f22619275aee061ae21eb16962f99e3d8699171071
+ languageName: node
+ linkType: hard
+
"@heroui/dropdown@npm:2.3.25":
version: 2.3.25
resolution: "@heroui/dropdown@npm:2.3.25"
@@ -4500,6 +4794,29 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/dropdown@npm:2.3.26":
+ version: 2.3.26
+ resolution: "@heroui/dropdown@npm:2.3.26"
+ dependencies:
+ "@heroui/aria-utils": "npm:2.2.23"
+ "@heroui/menu": "npm:2.2.25"
+ "@heroui/popover": "npm:2.3.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/menu": "npm:3.19.1"
+ "@react-stately/menu": "npm:3.9.7"
+ "@react-types/menu": "npm:3.10.4"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/5921722b23ae4904de6e20453327414aea2b3764bc4b10a66076a35233ee37585434ed8a82cbd57a02ef9e10ec49c038bd7ed7b0f52eea1be457cb2dbbf4f005
+ languageName: node
+ linkType: hard
+
"@heroui/form@npm:2.1.25":
version: 2.1.25
resolution: "@heroui/form@npm:2.1.25"
@@ -4519,6 +4836,25 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/form@npm:2.1.26":
+ version: 2.1.26
+ resolution: "@heroui/form@npm:2.1.26"
+ dependencies:
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/system": "npm:2.4.22"
+ "@heroui/theme": "npm:2.4.22"
+ "@react-stately/form": "npm:3.2.1"
+ "@react-types/form": "npm:3.7.15"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18"
+ react-dom: ">=18"
+ checksum: 10c0/9d48d78ed3e36f4d9da39d72261d3b131e7691b49abc3aaa65e1836f0f611423bd09cbf3fb738cedde17c38d23a4878c96a4898debeec0aa263500c43b2f0c0d
+ languageName: node
+ linkType: hard
+
"@heroui/framer-utils@npm:2.1.21":
version: 2.1.21
resolution: "@heroui/framer-utils@npm:2.1.21"
@@ -4533,6 +4869,20 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/framer-utils@npm:2.1.22":
+ version: 2.1.22
+ resolution: "@heroui/framer-utils@npm:2.1.22"
+ dependencies:
+ "@heroui/system": "npm:2.4.22"
+ "@heroui/use-measure": "npm:2.1.8"
+ peerDependencies:
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/d28143f51440849adca430c6a73cea6f40a9a38ccd0fffe7b565592c425f74b524d39d93d5a43b15804a59ee60164dbb0a0ebfd84869c1ad126c5d08f20f0179
+ languageName: node
+ linkType: hard
+
"@heroui/image@npm:2.2.16":
version: 2.2.16
resolution: "@heroui/image@npm:2.2.16"
@@ -4572,6 +4922,29 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/input-otp@npm:2.1.26":
+ version: 2.1.26
+ resolution: "@heroui/input-otp@npm:2.1.26"
+ dependencies:
+ "@heroui/form": "npm:2.1.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-form-reset": "npm:2.0.1"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/form": "npm:3.1.1"
+ "@react-stately/form": "npm:3.2.1"
+ "@react-stately/utils": "npm:3.10.8"
+ "@react-types/textfield": "npm:3.12.5"
+ input-otp: "npm:1.4.1"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18"
+ react-dom: ">=18"
+ checksum: 10c0/46d07f75acccbfe9a16e910b7f92ee2780b0abcd3c712fa708d2046fca439087c5f7795709e18dc988f5b7f2e7cec9bc6ee7820e467ceaea3d5273650806f3d8
+ languageName: node
+ linkType: hard
+
"@heroui/input@npm:2.4.26":
version: 2.4.26
resolution: "@heroui/input@npm:2.4.26"
@@ -4597,6 +4970,31 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/input@npm:2.4.27":
+ version: 2.4.27
+ resolution: "@heroui/input@npm:2.4.27"
+ dependencies:
+ "@heroui/form": "npm:2.1.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-icons": "npm:2.1.10"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-safe-layout-effect": "npm:2.1.8"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-aria/textfield": "npm:3.18.1"
+ "@react-stately/utils": "npm:3.10.8"
+ "@react-types/shared": "npm:3.32.0"
+ "@react-types/textfield": "npm:3.12.5"
+ react-textarea-autosize: "npm:^8.5.3"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.19"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/57f8bc5c264cd3a4a637417cf915bb92f7563c21f5bb695a338790ad7ecc5478172df2930220d4a981c7ebca03b556b6a30a3173c86007955efad3c24e75fe73
+ languageName: node
+ linkType: hard
+
"@heroui/kbd@npm:2.2.20":
version: 2.2.20
resolution: "@heroui/kbd@npm:2.2.20"
@@ -4612,6 +5010,21 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/kbd@npm:2.2.21":
+ version: 2.2.21
+ resolution: "@heroui/kbd@npm:2.2.21"
+ dependencies:
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/system-rsc": "npm:2.3.19"
+ peerDependencies:
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/7d2f8c6d7b5b60d2c94bacfdbf524cf49dd619cbbff8c92e5b84ad14262749c1ad2575aac1e5d45807535855a54a7b421bd0a9c936e3d7773f1aa7f81faf9a50
+ languageName: node
+ linkType: hard
+
"@heroui/link@npm:2.2.22":
version: 2.2.22
resolution: "@heroui/link@npm:2.2.22"
@@ -4655,6 +5068,30 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/listbox@npm:2.3.25":
+ version: 2.3.25
+ resolution: "@heroui/listbox@npm:2.3.25"
+ dependencies:
+ "@heroui/aria-utils": "npm:2.2.23"
+ "@heroui/divider": "npm:2.2.19"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-is-mobile": "npm:2.2.12"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-aria/listbox": "npm:3.14.8"
+ "@react-stately/list": "npm:3.13.0"
+ "@react-types/shared": "npm:3.32.0"
+ "@tanstack/react-virtual": "npm:3.11.3"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/a70e0e38178556a4676580a17c5b1cb212a490f7fc16d25e7bbcd110c989871918c7d7405474c2092d1377fa3402a33d8a6710a4dc716f383d271722504c739f
+ languageName: node
+ linkType: hard
+
"@heroui/menu@npm:2.2.24":
version: 2.2.24
resolution: "@heroui/menu@npm:2.2.24"
@@ -4679,6 +5116,30 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/menu@npm:2.2.25":
+ version: 2.2.25
+ resolution: "@heroui/menu@npm:2.2.25"
+ dependencies:
+ "@heroui/aria-utils": "npm:2.2.23"
+ "@heroui/divider": "npm:2.2.19"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-is-mobile": "npm:2.2.12"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-aria/menu": "npm:3.19.1"
+ "@react-stately/tree": "npm:3.9.2"
+ "@react-types/menu": "npm:3.10.4"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/73c141b03d5cb25c6560d77b5ed905b33b00fb8fec7dc219b5d91d90b044ee137654fda826689ab1e987beebfeac2d944c8a18a70f8526d1152b5ad2f252801b
+ languageName: node
+ linkType: hard
+
"@heroui/modal@npm:2.2.22":
version: 2.2.22
resolution: "@heroui/modal@npm:2.2.22"
@@ -4707,6 +5168,34 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/modal@npm:2.2.23":
+ version: 2.2.23
+ resolution: "@heroui/modal@npm:2.2.23"
+ dependencies:
+ "@heroui/dom-animation": "npm:2.1.10"
+ "@heroui/framer-utils": "npm:2.1.22"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-icons": "npm:2.1.10"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-aria-button": "npm:2.2.19"
+ "@heroui/use-aria-modal-overlay": "npm:2.2.18"
+ "@heroui/use-disclosure": "npm:2.2.16"
+ "@heroui/use-draggable": "npm:2.1.17"
+ "@heroui/use-viewport-size": "npm:2.0.1"
+ "@react-aria/dialog": "npm:3.5.29"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/overlays": "npm:3.29.0"
+ "@react-stately/overlays": "npm:3.6.19"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/622c5d7e6f10cbf84438e14c8c8dd6f318f8277e380f97f3fee6350e1871186feceb3a7a5b4fe8915f02388c055ef05ebab114b3ea479f0e82a99d7af8d632b9
+ languageName: node
+ linkType: hard
+
"@heroui/navbar@npm:2.2.23":
version: 2.2.23
resolution: "@heroui/navbar@npm:2.2.23"
@@ -4733,6 +5222,32 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/navbar@npm:2.2.24":
+ version: 2.2.24
+ resolution: "@heroui/navbar@npm:2.2.24"
+ dependencies:
+ "@heroui/dom-animation": "npm:2.1.10"
+ "@heroui/framer-utils": "npm:2.1.22"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-resize": "npm:2.1.8"
+ "@heroui/use-scroll-position": "npm:2.1.8"
+ "@react-aria/button": "npm:3.14.1"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-aria/overlays": "npm:3.29.0"
+ "@react-stately/toggle": "npm:3.9.1"
+ "@react-stately/utils": "npm:3.10.8"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/630a2f472faba5bff3b76430d256ea1d14d0e0e22726e12f09c8169c5f5c4e6cab32864235cdb0f93ad4482de8f2a1171da13aacf66f6073cd8857821b815717
+ languageName: node
+ linkType: hard
+
"@heroui/number-input@npm:2.0.16":
version: 2.0.16
resolution: "@heroui/number-input@npm:2.0.16"
@@ -4760,6 +5275,33 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/number-input@npm:2.0.17":
+ version: 2.0.17
+ resolution: "@heroui/number-input@npm:2.0.17"
+ dependencies:
+ "@heroui/button": "npm:2.2.26"
+ "@heroui/form": "npm:2.1.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-icons": "npm:2.1.10"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-safe-layout-effect": "npm:2.1.8"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/i18n": "npm:3.12.12"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-aria/numberfield": "npm:3.12.1"
+ "@react-stately/numberfield": "npm:3.10.1"
+ "@react-types/button": "npm:3.14.0"
+ "@react-types/numberfield": "npm:3.8.14"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.19"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/cc6852af673ac3c625559d25d577e336112430a62d4013a389bf962ce57ced346194493b937ef20c0cb7a086bdea515d9035c0ab4a4416705cb2270ccec39861
+ languageName: node
+ linkType: hard
+
"@heroui/pagination@npm:2.2.23":
version: 2.2.23
resolution: "@heroui/pagination@npm:2.2.23"
@@ -4811,6 +5353,34 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/popover@npm:2.3.26":
+ version: 2.3.26
+ resolution: "@heroui/popover@npm:2.3.26"
+ dependencies:
+ "@heroui/aria-utils": "npm:2.2.23"
+ "@heroui/button": "npm:2.2.26"
+ "@heroui/dom-animation": "npm:2.1.10"
+ "@heroui/framer-utils": "npm:2.1.22"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-aria-button": "npm:2.2.19"
+ "@heroui/use-aria-overlay": "npm:2.0.3"
+ "@heroui/use-safe-layout-effect": "npm:2.1.8"
+ "@react-aria/dialog": "npm:3.5.29"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/overlays": "npm:3.29.0"
+ "@react-stately/overlays": "npm:3.6.19"
+ "@react-types/overlays": "npm:3.9.1"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/00fec7294c8c1cab65e761c9355349c8d500369a009143d0cbc0b3e7515e03e30a613f65af2c7875e6f24750f6f0d4d6d000790ceb39c87a17a025057fa50d9e
+ languageName: node
+ linkType: hard
+
"@heroui/progress@npm:2.2.21":
version: 2.2.21
resolution: "@heroui/progress@npm:2.2.21"
@@ -4852,6 +5422,29 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/radio@npm:2.3.26":
+ version: 2.3.26
+ resolution: "@heroui/radio@npm:2.3.26"
+ dependencies:
+ "@heroui/form": "npm:2.1.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-aria/radio": "npm:3.12.1"
+ "@react-aria/visually-hidden": "npm:3.8.27"
+ "@react-stately/radio": "npm:3.11.1"
+ "@react-types/radio": "npm:3.9.1"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/ee3a59e6c27b8698126881702532c5b13dbe51d433770a29653b1545ebcdcf94c983fe7fdaf8e09a53e99b021f72f03ca74a049720e4ad2e0bf4b4de1ce06eb0
+ languageName: node
+ linkType: hard
+
"@heroui/react-rsc-utils@npm:2.1.9":
version: 2.1.9
resolution: "@heroui/react-rsc-utils@npm:2.1.9"
@@ -4935,6 +5528,68 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/react@npm:^2.8.4":
+ version: 2.8.4
+ resolution: "@heroui/react@npm:2.8.4"
+ dependencies:
+ "@heroui/accordion": "npm:2.2.23"
+ "@heroui/alert": "npm:2.2.26"
+ "@heroui/autocomplete": "npm:2.3.28"
+ "@heroui/avatar": "npm:2.2.21"
+ "@heroui/badge": "npm:2.2.16"
+ "@heroui/breadcrumbs": "npm:2.2.21"
+ "@heroui/button": "npm:2.2.26"
+ "@heroui/calendar": "npm:2.2.26"
+ "@heroui/card": "npm:2.2.24"
+ "@heroui/checkbox": "npm:2.3.26"
+ "@heroui/chip": "npm:2.2.21"
+ "@heroui/code": "npm:2.2.20"
+ "@heroui/date-input": "npm:2.3.26"
+ "@heroui/date-picker": "npm:2.3.27"
+ "@heroui/divider": "npm:2.2.19"
+ "@heroui/drawer": "npm:2.2.23"
+ "@heroui/dropdown": "npm:2.3.26"
+ "@heroui/form": "npm:2.1.26"
+ "@heroui/framer-utils": "npm:2.1.22"
+ "@heroui/image": "npm:2.2.16"
+ "@heroui/input": "npm:2.4.27"
+ "@heroui/input-otp": "npm:2.1.26"
+ "@heroui/kbd": "npm:2.2.21"
+ "@heroui/link": "npm:2.2.22"
+ "@heroui/listbox": "npm:2.3.25"
+ "@heroui/menu": "npm:2.2.25"
+ "@heroui/modal": "npm:2.2.23"
+ "@heroui/navbar": "npm:2.2.24"
+ "@heroui/number-input": "npm:2.0.17"
+ "@heroui/pagination": "npm:2.2.23"
+ "@heroui/popover": "npm:2.3.26"
+ "@heroui/progress": "npm:2.2.21"
+ "@heroui/radio": "npm:2.3.26"
+ "@heroui/ripple": "npm:2.2.19"
+ "@heroui/scroll-shadow": "npm:2.3.17"
+ "@heroui/select": "npm:2.4.27"
+ "@heroui/skeleton": "npm:2.2.16"
+ "@heroui/slider": "npm:2.4.23"
+ "@heroui/snippet": "npm:2.2.27"
+ "@heroui/spacer": "npm:2.2.20"
+ "@heroui/spinner": "npm:2.2.23"
+ "@heroui/switch": "npm:2.2.23"
+ "@heroui/system": "npm:2.4.22"
+ "@heroui/table": "npm:2.2.26"
+ "@heroui/tabs": "npm:2.2.23"
+ "@heroui/theme": "npm:2.4.22"
+ "@heroui/toast": "npm:2.0.16"
+ "@heroui/tooltip": "npm:2.2.23"
+ "@heroui/user": "npm:2.2.21"
+ "@react-aria/visually-hidden": "npm:3.8.27"
+ peerDependencies:
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/ecd204b0f0b887caaf21dfeaad4ce61b57ea45702e2ec8355ae1c59378aef3d3e623ff7e9a6731499a9ca33a6c4c6266093667a22c9ad72c39df50391532b0c6
+ languageName: node
+ linkType: hard
+
"@heroui/ripple@npm:2.2.19":
version: 2.2.19
resolution: "@heroui/ripple@npm:2.2.19"
@@ -5000,6 +5655,39 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/select@npm:2.4.27":
+ version: 2.4.27
+ resolution: "@heroui/select@npm:2.4.27"
+ dependencies:
+ "@heroui/aria-utils": "npm:2.2.23"
+ "@heroui/form": "npm:2.1.26"
+ "@heroui/listbox": "npm:2.3.25"
+ "@heroui/popover": "npm:2.3.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/scroll-shadow": "npm:2.3.17"
+ "@heroui/shared-icons": "npm:2.1.10"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/spinner": "npm:2.2.23"
+ "@heroui/use-aria-button": "npm:2.2.19"
+ "@heroui/use-aria-multiselect": "npm:2.4.18"
+ "@heroui/use-form-reset": "npm:2.0.1"
+ "@heroui/use-safe-layout-effect": "npm:2.1.8"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/form": "npm:3.1.1"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-aria/overlays": "npm:3.29.0"
+ "@react-aria/visually-hidden": "npm:3.8.27"
+ "@react-types/shared": "npm:3.32.0"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/90434afad3c539cad537f692173238be963783e93e5b3e340512178995fdcc1d0e5659499cef4d16a1632f4812830fa787cc4ab6247ccf305fb4184859010ea9
+ languageName: node
+ linkType: hard
+
"@heroui/shared-icons@npm:2.1.10":
version: 2.1.10
resolution: "@heroui/shared-icons@npm:2.1.10"
@@ -5052,6 +5740,28 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/slider@npm:2.4.23":
+ version: 2.4.23
+ resolution: "@heroui/slider@npm:2.4.23"
+ dependencies:
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/tooltip": "npm:2.2.23"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/i18n": "npm:3.12.12"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-aria/slider": "npm:3.8.1"
+ "@react-aria/visually-hidden": "npm:3.8.27"
+ "@react-stately/slider": "npm:3.7.1"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.19"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/4389e5d31c5180a226731bbbfebb0f22dceca9abd91ec17815b2b738da364560aa2473e4b737cb612060731714559d5e84e97af41326efcd54103bd5d3bfcd82
+ languageName: node
+ linkType: hard
+
"@heroui/snippet@npm:2.2.26":
version: 2.2.26
resolution: "@heroui/snippet@npm:2.2.26"
@@ -5073,6 +5783,27 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/snippet@npm:2.2.27":
+ version: 2.2.27
+ resolution: "@heroui/snippet@npm:2.2.27"
+ dependencies:
+ "@heroui/button": "npm:2.2.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-icons": "npm:2.1.10"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/tooltip": "npm:2.2.23"
+ "@heroui/use-clipboard": "npm:2.1.9"
+ "@react-aria/focus": "npm:3.21.1"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/a6ebc865c9c9b6153adf32f38f5dbc7eca1f65cb0a49108e5d88a5556b11be3488801e87adb62110112be91e4d5785b2730174716b9ae16947c41a6a9b5b07bb
+ languageName: node
+ linkType: hard
+
"@heroui/spacer@npm:2.2.19":
version: 2.2.19
resolution: "@heroui/spacer@npm:2.2.19"
@@ -5088,6 +5819,21 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/spacer@npm:2.2.20":
+ version: 2.2.20
+ resolution: "@heroui/spacer@npm:2.2.20"
+ dependencies:
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/system-rsc": "npm:2.3.19"
+ peerDependencies:
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/34eae1369d0502f09b1f84205098d50471db47c652b7eee654474c2b75b0712b785b07c2a68f683e26c1e6d6f3e48cbf3507380c9664fe8607e9c23cb46eb0dc
+ languageName: node
+ linkType: hard
+
"@heroui/spinner@npm:2.2.22":
version: 2.2.22
resolution: "@heroui/spinner@npm:2.2.22"
@@ -5103,6 +5849,21 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/spinner@npm:2.2.23":
+ version: 2.2.23
+ resolution: "@heroui/spinner@npm:2.2.23"
+ dependencies:
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/system": "npm:2.4.22"
+ "@heroui/system-rsc": "npm:2.3.19"
+ peerDependencies:
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/90d74fe2dd5c75aff0330cfefa866b3fee1a055780b19bab9a0cb3ea76be4b802b1a4d418d163b9de8d5947977b72a34199a611339f792c058653a5a95bf9279
+ languageName: node
+ linkType: hard
+
"@heroui/switch@npm:2.2.23":
version: 2.2.23
resolution: "@heroui/switch@npm:2.2.23"
@@ -5137,6 +5898,19 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/system-rsc@npm:2.3.19":
+ version: 2.3.19
+ resolution: "@heroui/system-rsc@npm:2.3.19"
+ dependencies:
+ "@react-types/shared": "npm:3.32.0"
+ clsx: "npm:^1.2.1"
+ peerDependencies:
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/eaf81d1fc288981bcf6059f2e1c60efcddda8564d45a35e3b0e30cd054c333f633aa512e6d2a253171a7e0d17ef7b938192a231f783cb889d16fe1945d296f2e
+ languageName: node
+ linkType: hard
+
"@heroui/system@npm:2.4.21":
version: 2.4.21
resolution: "@heroui/system@npm:2.4.21"
@@ -5154,6 +5928,23 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/system@npm:2.4.22":
+ version: 2.4.22
+ resolution: "@heroui/system@npm:2.4.22"
+ dependencies:
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/system-rsc": "npm:2.3.19"
+ "@react-aria/i18n": "npm:3.12.12"
+ "@react-aria/overlays": "npm:3.29.0"
+ "@react-aria/utils": "npm:3.30.1"
+ peerDependencies:
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/8ce88dc12c74c319380eeba8fea511472137416068cd47583671d9a92a8fe166ec5909d20a42bb45498a7a2696b051f46cbc1bdbfd9507b785e42589f4814b5d
+ languageName: node
+ linkType: hard
+
"@heroui/table@npm:2.2.25":
version: 2.2.25
resolution: "@heroui/table@npm:2.2.25"
@@ -5181,6 +5972,33 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/table@npm:2.2.26":
+ version: 2.2.26
+ resolution: "@heroui/table@npm:2.2.26"
+ dependencies:
+ "@heroui/checkbox": "npm:2.3.26"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-icons": "npm:2.1.10"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/spacer": "npm:2.2.20"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-aria/table": "npm:3.17.7"
+ "@react-aria/visually-hidden": "npm:3.8.27"
+ "@react-stately/table": "npm:3.15.0"
+ "@react-stately/virtualizer": "npm:4.4.3"
+ "@react-types/grid": "npm:3.3.5"
+ "@react-types/table": "npm:3.13.3"
+ "@tanstack/react-virtual": "npm:3.11.3"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/7ca9ab41851b3694e8f05bee80dd424ad7257d6f4cfd7f6f81930be49f252e68caf3872ab7450d0de254cd1b7595758209496b985b63e019b46d8e33fdd1fa49
+ languageName: node
+ linkType: hard
+
"@heroui/tabs@npm:2.2.22":
version: 2.2.22
resolution: "@heroui/tabs@npm:2.2.22"
@@ -5205,6 +6023,30 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/tabs@npm:2.2.23":
+ version: 2.2.23
+ resolution: "@heroui/tabs@npm:2.2.23"
+ dependencies:
+ "@heroui/aria-utils": "npm:2.2.23"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-is-mounted": "npm:2.1.8"
+ "@react-aria/focus": "npm:3.21.1"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-aria/tabs": "npm:3.10.7"
+ "@react-stately/tabs": "npm:3.8.5"
+ "@react-types/shared": "npm:3.32.0"
+ scroll-into-view-if-needed: "npm:3.0.10"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/db4724c2481d018a67e222dd54c7a4ec7b4b59357e855a17616d32c94c1d2f61eb9a89d48f80819360ab619e33ba354a1106ef23ce75b6878c79e138f4040266
+ languageName: node
+ linkType: hard
+
"@heroui/theme@npm:2.4.21":
version: 2.4.21
resolution: "@heroui/theme@npm:2.4.21"
@@ -5223,6 +6065,24 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/theme@npm:2.4.22":
+ version: 2.4.22
+ resolution: "@heroui/theme@npm:2.4.22"
+ dependencies:
+ "@heroui/shared-utils": "npm:2.1.11"
+ clsx: "npm:^1.2.1"
+ color: "npm:^4.2.3"
+ color2k: "npm:^2.0.3"
+ deepmerge: "npm:4.3.1"
+ flat: "npm:^5.0.2"
+ tailwind-merge: "npm:3.3.1"
+ tailwind-variants: "npm:3.1.1"
+ peerDependencies:
+ tailwindcss: ">=4.0.0"
+ checksum: 10c0/b8a29f83453b7511a3f8ec0fcd6958e382e502d5a6ddc9071f03c2061ba800320b3ed6eb19ff5ee994c2cbebc141fe1640b58a03ad01de8ad2ae2b4cbe65397c
+ languageName: node
+ linkType: hard
+
"@heroui/toast@npm:2.0.15":
version: 2.0.15
resolution: "@heroui/toast@npm:2.0.15"
@@ -5245,6 +6105,28 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/toast@npm:2.0.16":
+ version: 2.0.16
+ resolution: "@heroui/toast@npm:2.0.16"
+ dependencies:
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-icons": "npm:2.1.10"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/spinner": "npm:2.2.23"
+ "@heroui/use-is-mobile": "npm:2.2.12"
+ "@react-aria/interactions": "npm:3.25.5"
+ "@react-aria/toast": "npm:3.0.7"
+ "@react-stately/toast": "npm:3.1.2"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/4ff71cfa6c52c7504f382e83f116e52bf26255caa919c77c14bbb6faf10b45c14cbe1fe83e3dbf477df6a43081912892c052cf1e8b4bd9ae2d81dea986c1a82e
+ languageName: node
+ linkType: hard
+
"@heroui/tooltip@npm:2.2.22":
version: 2.2.22
resolution: "@heroui/tooltip@npm:2.2.22"
@@ -5271,6 +6153,32 @@ __metadata:
languageName: node
linkType: hard
+"@heroui/tooltip@npm:2.2.23":
+ version: 2.2.23
+ resolution: "@heroui/tooltip@npm:2.2.23"
+ dependencies:
+ "@heroui/aria-utils": "npm:2.2.23"
+ "@heroui/dom-animation": "npm:2.1.10"
+ "@heroui/framer-utils": "npm:2.1.22"
+ "@heroui/react-utils": "npm:2.1.13"
+ "@heroui/shared-utils": "npm:2.1.11"
+ "@heroui/use-aria-overlay": "npm:2.0.3"
+ "@heroui/use-safe-layout-effect": "npm:2.1.8"
+ "@react-aria/overlays": "npm:3.29.0"
+ "@react-aria/tooltip": "npm:3.8.7"
+ "@react-stately/tooltip": "npm:3.5.7"
+ "@react-types/overlays": "npm:3.9.1"
+ "@react-types/tooltip": "npm:3.4.20"
+ peerDependencies:
+ "@heroui/system": ">=2.4.18"
+ "@heroui/theme": ">=2.4.17"
+ framer-motion: ">=11.5.6 || >=12.0.0-alpha.1"
+ react: ">=18 || >=19.0.0-rc.0"
+ react-dom: ">=18 || >=19.0.0-rc.0"
+ checksum: 10c0/ae44af1a03036ae2d5dd7fcdf75e1beeb878db975f1353fad561c2059e70779fd723a75541b3b5dced74388ded1de9a28f4d832ad3209e9cbcb0dbad02194a8a
+ languageName: node
+ linkType: hard
+
"@heroui/use-aria-accordion@npm:2.2.17":
version: 2.2.17
resolution: "@heroui/use-aria-accordion@npm:2.2.17"
@@ -13237,6 +14145,7 @@ __metadata:
"@cherrystudio/embedjs-ollama": "npm:^0.1.31"
"@cherrystudio/embedjs-openai": "npm:^0.1.31"
"@cherrystudio/extension-table-plus": "workspace:^"
+ "@cherrystudio/ui": "workspace:*"
"@dnd-kit/core": "npm:^6.3.1"
"@dnd-kit/modifiers": "npm:^9.0.0"
"@dnd-kit/sortable": "npm:^10.0.0"
@@ -27395,6 +28304,19 @@ __metadata:
languageName: node
linkType: hard
+"tailwind-variants@npm:3.1.1":
+ version: 3.1.1
+ resolution: "tailwind-variants@npm:3.1.1"
+ peerDependencies:
+ tailwind-merge: ">=3.0.0"
+ tailwindcss: "*"
+ peerDependenciesMeta:
+ tailwind-merge:
+ optional: true
+ checksum: 10c0/58b4d50ac3d4abd67a8cb26cbae9ec83f3e4a48234aeedc0c9a0a23f7111495caad55c1641d4314dea242cd9aa71db2f0e6ceb2f914c393d570075d7f12a01ac
+ languageName: node
+ linkType: hard
+
"tailwindcss@npm:4.1.13, tailwindcss@npm:^4.1.13":
version: 4.1.13
resolution: "tailwindcss@npm:4.1.13"