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"