| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- /**
- * Catalog 定义 - 使用 Zod schemas 定义组件 props
- */
- import { z } from 'zod';
- import { defineSchema, defineCatalog } from '@json-render/core';
- // 使用 defineSchema 定义 schema
- const schema = defineSchema((s) => ({
- spec: s.object({
- type: s.ref('catalog.components'),
- props: s.propsOf('catalog.components'),
- }),
- catalog: s.object({
- components: s.map({
- props: s.zod(),
- description: s.string(),
- }),
- }),
- }));
- // 组件 props Zod schemas
- export const CardProps = z.object({
- title: z.string().optional(),
- variant: z.enum(['default', 'outlined', 'elevated']).optional(),
- className: z.string().optional(),
- });
- export const StackProps = z.object({
- direction: z.enum(['row', 'column']).optional(),
- spacing: z.number().optional(),
- align: z.enum(['start', 'center', 'end', 'stretch']).optional(),
- className: z.string().optional(),
- });
- export const HeadingProps = z.object({
- text: z.string(),
- level: z.enum(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']).optional(),
- className: z.string().optional(),
- });
- export const TextProps = z.object({
- text: z.string(),
- size: z.enum(['xs', 'sm', 'md', 'lg', 'xl']).optional(),
- color: z.enum(['default', 'muted', 'primary', 'success', 'warning', 'destructive']).optional(),
- className: z.string().optional(),
- });
- export const ButtonProps = z.object({
- label: z.string(),
- variant: z.enum(['default', 'primary', 'secondary', 'outline', 'ghost', 'destructive']).optional(),
- onClick: z.string().optional(),
- disabled: z.boolean().optional(),
- className: z.string().optional(),
- });
- export const BadgeProps = z.object({
- text: z.string(),
- variant: z.enum(['default', 'primary', 'secondary', 'success', 'warning', 'destructive']).optional(),
- className: z.string().optional(),
- });
- export const SeparatorProps = z.object({
- orientation: z.enum(['horizontal', 'vertical']).optional(),
- className: z.string().optional(),
- });
- export const InputProps = z.object({
- placeholder: z.string().optional(),
- type: z.enum(['text', 'password', 'email', 'number']).optional(),
- disabled: z.boolean().optional(),
- className: z.string().optional(),
- });
- export const TextAreaProps = z.object({
- placeholder: z.string().optional(),
- rows: z.number().optional(),
- disabled: z.boolean().optional(),
- className: z.string().optional(),
- });
- export const DataTableProps = z.object({
- columns: z.array(z.object({
- key: z.string(),
- label: z.string(),
- })).optional(),
- data: z.array(z.record(z.string(), z.any())).optional(),
- className: z.string().optional(),
- });
- // MCP 专用组件 props
- export const TranslationResultProps = z.object({
- original: z.string().optional(),
- translated: z.string(),
- termsUsed: z.array(z.string()).optional(),
- className: z.string().optional(),
- });
- export const NovelListProps = z.object({
- novels: z.array(z.object({
- id: z.union([z.string(), z.number()]),
- title: z.string(),
- author: z.string().optional(),
- description: z.string().optional(),
- chapterCount: z.number().optional(),
- tags: z.array(z.string()).optional(),
- })),
- className: z.string().optional(),
- });
- export const ChapterReaderProps = z.object({
- novelTitle: z.string().optional(),
- chapterTitle: z.string().optional(),
- content: z.string(),
- chapterNumber: z.number().optional(),
- totalChapters: z.number().optional(),
- className: z.string().optional(),
- });
- export const CodeBlockProps = z.object({
- code: z.string(),
- language: z.string().optional(),
- className: z.string().optional(),
- });
- export const ToolCallProps = z.object({
- toolName: z.string(),
- status: z.enum(['pending', 'running', 'success', 'error']).optional(),
- result: z.any().optional(),
- className: z.string().optional(),
- });
- export const LoginPanelProps = z.object({
- serverName: z.string().optional(),
- onLogin: z.string().optional(),
- className: z.string().optional(),
- });
- export const McpStatusProps = z.object({
- serverId: z.string(),
- connected: z.boolean(),
- className: z.string().optional(),
- });
- export const SuggestionButtonsProps = z.object({
- suggestions: z.array(z.object({
- label: z.string(),
- message: z.string().optional(),
- icon: z.string().optional(),
- })),
- className: z.string().optional(),
- });
- // 创建 catalog
- const catalog = defineCatalog(schema, {
- components: {
- card: {
- props: CardProps,
- description: '卡片容器组件,用于包装内容区块',
- },
- stack: {
- props: StackProps,
- description: '布局容器组件,支持水平和垂直排列',
- },
- heading: {
- props: HeadingProps,
- description: '标题组件',
- },
- text: {
- props: TextProps,
- description: '文本组件',
- },
- button: {
- props: ButtonProps,
- description: '按钮组件',
- },
- badge: {
- props: BadgeProps,
- description: '徽章组件,用于标签和状态标识',
- },
- separator: {
- props: SeparatorProps,
- description: '分隔线组件',
- },
- input: {
- props: InputProps,
- description: '输入框组件',
- },
- 'text-area': {
- props: TextAreaProps,
- description: '多行文本输入组件',
- },
- 'data-table': {
- props: DataTableProps,
- description: '数据表格组件',
- },
- 'translation-result': {
- props: TranslationResultProps,
- description: '翻译结果展示组件',
- },
- 'novel-list': {
- props: NovelListProps,
- description: '小说列表组件',
- },
- 'chapter-reader': {
- props: ChapterReaderProps,
- description: '章节阅读器组件',
- },
- 'code-block': {
- props: CodeBlockProps,
- description: '代码块组件,支持语法高亮',
- },
- 'tool-call': {
- props: ToolCallProps,
- description: 'MCP 工具调用状态组件',
- },
- 'login-panel': {
- props: LoginPanelProps,
- description: 'MCP 登录面板组件',
- },
- 'mcp-status': {
- props: McpStatusProps,
- description: 'MCP 服务器状态组件',
- },
- 'suggestion-buttons': {
- props: SuggestionButtonsProps,
- description: '建议按钮组组件,用于快速选择预定义消息',
- },
- },
- });
- export default catalog;
- export { schema };
- // 兼容旧的导出
- export interface GetCatalogPromptOptions {
- mode?: 'standalone' | 'inline';
- }
- export function getCatalogPrompt(options?: GetCatalogPromptOptions): string {
- return catalog.prompt({ mode: options?.mode ?? 'inline' });
- }
|