@schandlergarcia/sf-web-components 1.9.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/library/chat/ChatMessage.d.ts +2 -1
- package/dist/components/library/chat/ChatMessage.js.map +1 -1
- package/dist/components/library/chat/useChatState.d.ts +2 -1
- package/dist/components/library/chat/useChatState.js.map +1 -1
- package/dist/components/workspace/ComponentRegistry.d.ts +116 -140
- package/dist/components/workspace/ComponentRegistry.js +43 -43
- package/dist/components/workspace/ComponentRegistry.js.map +1 -1
- package/package.json +2 -2
- package/src/components/library/chat/ChatMessage.tsx +2 -2
- package/src/components/library/chat/useChatState.tsx +2 -1
- package/src/components/workspace/{ComponentRegistry.jsx → ComponentRegistry.tsx} +137 -32
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { type SchemaComponent } from "@/components/workspace/ComponentRegistry";
|
|
2
3
|
import { ToolCall } from "./ChatToolCall";
|
|
3
4
|
export interface ChatMessageData {
|
|
4
5
|
id: string;
|
|
5
6
|
role: "user" | "assistant" | "system";
|
|
6
7
|
content?: string;
|
|
7
|
-
components?:
|
|
8
|
+
components?: SchemaComponent[];
|
|
8
9
|
toolCalls?: ToolCall[];
|
|
9
10
|
isError?: boolean;
|
|
10
11
|
isStreaming?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatMessage.js","sources":["../../../../src/components/library/chat/ChatMessage.tsx"],"sourcesContent":["import React from \"react\";\nimport { renderSchemaComponent } from \"@/components/workspace/ComponentRegistry\";\nimport ChatToolCall, { ToolCall } from \"./ChatToolCall\";\nimport { UserCircleIcon, CpuChipIcon } from \"@heroicons/react/24/solid\";\n\nfunction cx(...classes: (string | boolean | undefined)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n\n/**\n * Lightweight inline formatter for assistant messages.\n * Handles code blocks, inline code, bold, italic, and line breaks.\n */\nfunction formatContent(text: string): React.ReactNode {\n if (!text) return null;\n const parts: React.ReactNode[] = [];\n let key = 0;\n\n const codeBlockRegex = /```(\\w*)\\n?([\\s\\S]*?)```/g;\n let lastIndex = 0;\n let match;\n\n while ((match = codeBlockRegex.exec(text)) !== null) {\n if (match.index > lastIndex) {\n parts.push(\n <span key={key++}>{formatInline(text.slice(lastIndex, match.index))}</span>\n );\n }\n parts.push(\n <pre\n key={key++}\n className=\"my-2 overflow-x-auto rounded-lg border border-slate-200 bg-slate-50 p-3 text-xs leading-relaxed dark:border-slate-700 dark:bg-slate-800/50\"\n >\n <code>{match[2]}</code>\n </pre>\n );\n lastIndex = match.index + match[0].length;\n }\n\n if (lastIndex < text.length) {\n parts.push(\n <span key={key++}>{formatInline(text.slice(lastIndex))}</span>\n );\n }\n\n return parts;\n}\n\nfunction formatInline(text: string): React.ReactNode {\n const tokens = text.split(/(`[^`]+`|\\*\\*[^*]+\\*\\*|\\*[^*]+\\*)/g);\n return tokens.map((token, i) => {\n if (token.startsWith(\"**\") && token.endsWith(\"**\")) {\n return <strong key={i} className=\"font-semibold\">{token.slice(2, -2)}</strong>;\n }\n if (token.startsWith(\"*\") && token.endsWith(\"*\")) {\n return <em key={i}>{token.slice(1, -1)}</em>;\n }\n if (token.startsWith(\"`\") && token.endsWith(\"`\")) {\n return (\n <code\n key={i}\n className=\"rounded bg-slate-100 px-1 py-0.5 text-xs font-mono dark:bg-slate-800\"\n >\n {token.slice(1, -1)}\n </code>\n );\n }\n return token.split(\"\\n\").map((line, j, arr) => (\n <React.Fragment key={`${i}-${j}`}>\n {line}\n {j < arr.length - 1 ? <br /> : null}\n </React.Fragment>\n ));\n });\n}\n\nexport interface ChatMessageData {\n id: string;\n role: \"user\" | \"assistant\" | \"system\";\n content?: string;\n components?:
|
|
1
|
+
{"version":3,"file":"ChatMessage.js","sources":["../../../../src/components/library/chat/ChatMessage.tsx"],"sourcesContent":["import React from \"react\";\nimport { renderSchemaComponent, type SchemaComponent } from \"@/components/workspace/ComponentRegistry\";\nimport ChatToolCall, { ToolCall } from \"./ChatToolCall\";\nimport { UserCircleIcon, CpuChipIcon } from \"@heroicons/react/24/solid\";\n\nfunction cx(...classes: (string | boolean | undefined)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n\n/**\n * Lightweight inline formatter for assistant messages.\n * Handles code blocks, inline code, bold, italic, and line breaks.\n */\nfunction formatContent(text: string): React.ReactNode {\n if (!text) return null;\n const parts: React.ReactNode[] = [];\n let key = 0;\n\n const codeBlockRegex = /```(\\w*)\\n?([\\s\\S]*?)```/g;\n let lastIndex = 0;\n let match;\n\n while ((match = codeBlockRegex.exec(text)) !== null) {\n if (match.index > lastIndex) {\n parts.push(\n <span key={key++}>{formatInline(text.slice(lastIndex, match.index))}</span>\n );\n }\n parts.push(\n <pre\n key={key++}\n className=\"my-2 overflow-x-auto rounded-lg border border-slate-200 bg-slate-50 p-3 text-xs leading-relaxed dark:border-slate-700 dark:bg-slate-800/50\"\n >\n <code>{match[2]}</code>\n </pre>\n );\n lastIndex = match.index + match[0].length;\n }\n\n if (lastIndex < text.length) {\n parts.push(\n <span key={key++}>{formatInline(text.slice(lastIndex))}</span>\n );\n }\n\n return parts;\n}\n\nfunction formatInline(text: string): React.ReactNode {\n const tokens = text.split(/(`[^`]+`|\\*\\*[^*]+\\*\\*|\\*[^*]+\\*)/g);\n return tokens.map((token, i) => {\n if (token.startsWith(\"**\") && token.endsWith(\"**\")) {\n return <strong key={i} className=\"font-semibold\">{token.slice(2, -2)}</strong>;\n }\n if (token.startsWith(\"*\") && token.endsWith(\"*\")) {\n return <em key={i}>{token.slice(1, -1)}</em>;\n }\n if (token.startsWith(\"`\") && token.endsWith(\"`\")) {\n return (\n <code\n key={i}\n className=\"rounded bg-slate-100 px-1 py-0.5 text-xs font-mono dark:bg-slate-800\"\n >\n {token.slice(1, -1)}\n </code>\n );\n }\n return token.split(\"\\n\").map((line, j, arr) => (\n <React.Fragment key={`${i}-${j}`}>\n {line}\n {j < arr.length - 1 ? <br /> : null}\n </React.Fragment>\n ));\n });\n}\n\nexport interface ChatMessageData {\n id: string;\n role: \"user\" | \"assistant\" | \"system\";\n content?: string;\n components?: SchemaComponent[];\n toolCalls?: ToolCall[];\n isError?: boolean;\n isStreaming?: boolean;\n timestamp?: string;\n}\n\nexport interface ChatMessageProps {\n message: ChatMessageData;\n avatar?: React.ReactNode;\n}\n\n/**\n * Renders a single chat message.\n */\nexport default function ChatMessage({ message, avatar }: ChatMessageProps) {\n const isUser = message.role === \"user\";\n const isSystem = message.role === \"system\";\n const isAssistant = message.role === \"assistant\";\n\n const defaultAvatar = isUser ? (\n <UserCircleIcon className=\"h-7 w-7 text-slate-400 dark:text-slate-500\" />\n ) : (\n <div className=\"flex h-7 w-7 items-center justify-center rounded-lg bg-brand-100 dark:bg-brand-900/40\">\n <CpuChipIcon className=\"h-4 w-4 text-brand-600 dark:text-brand-400\" />\n </div>\n );\n\n if (isSystem) {\n return (\n <div\n className={cx(\n \"mx-auto max-w-lg rounded-lg px-4 py-2 text-center text-xs\",\n message.isError\n ? \"bg-red-50 text-red-600 dark:bg-red-950/30 dark:text-red-400\"\n : \"text-slate-400 dark:text-slate-500\"\n )}\n >\n {message.content}\n </div>\n );\n }\n\n return (\n <div\n className={cx(\n \"flex gap-3\",\n isUser ? \"flex-row-reverse\" : \"flex-row\"\n )}\n >\n {/* Avatar */}\n <div className=\"shrink-0 pt-0.5\">{avatar ?? defaultAvatar}</div>\n\n {/* Bubble */}\n <div\n className={cx(\n \"max-w-[80%] space-y-2\",\n isUser ? \"items-end\" : \"items-start\"\n )}\n >\n {/* Text content */}\n {message.content ? (\n <div\n className={cx(\n \"rounded-2xl px-4 py-2.5 text-sm leading-relaxed\",\n isUser\n ? \"rounded-tr-md bg-brand-600 text-white dark:bg-brand-500\"\n : \"rounded-tl-md bg-slate-100 text-slate-800 dark:bg-slate-800 dark:text-slate-100\",\n message.isStreaming && \"animate-pulse\"\n )}\n >\n {isAssistant ? formatContent(message.content) : message.content}\n </div>\n ) : null}\n\n {/* Tool calls */}\n {message.toolCalls?.length ? (\n <div className=\"space-y-1.5 pl-1\">\n {message.toolCalls.map((tc, idx) => (\n <ChatToolCall key={tc.id ?? idx} toolCall={tc} />\n ))}\n </div>\n ) : null}\n\n {/* Inline components — render real command center components */}\n {message.components?.length ? (\n <div className=\"w-full space-y-3 pt-1\">\n {message.components.map((comp, idx) =>\n renderSchemaComponent(comp, idx)\n )}\n </div>\n ) : null}\n\n {/* Timestamp */}\n {message.timestamp ? (\n <div\n className={cx(\n \"px-1 text-[10px] text-slate-400 dark:text-slate-500\",\n isUser ? \"text-right\" : \"text-left\"\n )}\n >\n {new Date(message.timestamp).toLocaleTimeString([], {\n hour: \"2-digit\",\n minute: \"2-digit\",\n })}\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n"],"names":["cx","classes","formatContent","text","parts","key","codeBlockRegex","lastIndex","match","jsx","formatInline","token","i","line","j","arr","jsxs","React","ChatMessage","message","avatar","isUser","isSystem","isAssistant","defaultAvatar","UserCircleIcon","CpuChipIcon","tc","idx","ChatToolCall","comp","renderSchemaComponent"],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { ToolCall } from "./ChatToolCall";
|
|
2
|
+
import type { SchemaComponent } from "@/components/workspace/ComponentRegistry";
|
|
2
3
|
export interface ChatMessage {
|
|
3
4
|
id: string;
|
|
4
5
|
role: "user" | "assistant" | "system";
|
|
5
6
|
content?: string;
|
|
6
7
|
timestamp: string;
|
|
7
|
-
components?:
|
|
8
|
+
components?: SchemaComponent[];
|
|
8
9
|
toolCalls?: ToolCall[];
|
|
9
10
|
isError?: boolean;
|
|
10
11
|
isStreaming?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChatState.js","sources":["../../../../src/components/library/chat/useChatState.tsx"],"sourcesContent":["import { useState, useCallback, useRef } from \"react\";\nimport { ToolCall } from \"./ChatToolCall\";\n\nlet _nextId = 1;\nfunction uid(): string {\n return `msg-${Date.now()}-${_nextId++}`;\n}\n\nexport interface ChatMessage {\n id: string;\n role: \"user\" | \"assistant\" | \"system\";\n content?: string;\n timestamp: string;\n components?:
|
|
1
|
+
{"version":3,"file":"useChatState.js","sources":["../../../../src/components/library/chat/useChatState.tsx"],"sourcesContent":["import { useState, useCallback, useRef } from \"react\";\nimport { ToolCall } from \"./ChatToolCall\";\nimport type { SchemaComponent } from \"@/components/workspace/ComponentRegistry\";\n\nlet _nextId = 1;\nfunction uid(): string {\n return `msg-${Date.now()}-${_nextId++}`;\n}\n\nexport interface ChatMessage {\n id: string;\n role: \"user\" | \"assistant\" | \"system\";\n content?: string;\n timestamp: string;\n components?: SchemaComponent[];\n toolCalls?: ToolCall[];\n isError?: boolean;\n isStreaming?: boolean;\n}\n\nexport interface ChatStateHelpers {\n addMessage: (msg: Partial<ChatMessage>) => string;\n updateMessage: (id: string, updates: Partial<ChatMessage>) => void;\n appendChunk: (id: string, chunk: string) => void;\n setStreaming: (streaming: boolean) => void;\n}\n\nexport interface UseChatStateOptions {\n initialMessages?: Partial<ChatMessage>[];\n onSend?: (\n userMessage: ChatMessage,\n allMessages: ChatMessage[],\n helpers: ChatStateHelpers\n ) => Promise<Partial<ChatMessage> | void>;\n}\n\nexport interface UseChatStateReturn {\n messages: ChatMessage[];\n isLoading: boolean;\n isStreaming: boolean;\n error: string | null;\n sendMessage: (content: string, extra?: Partial<ChatMessage>) => Promise<void>;\n addMessage: (msg: Partial<ChatMessage>) => string;\n updateMessage: (id: string, updates: Partial<ChatMessage>) => void;\n appendChunk: (id: string, chunk: string) => void;\n removeMessage: (id: string) => void;\n clearMessages: () => void;\n retryLast: () => void;\n setError: (error: string | null) => void;\n}\n\n/**\n * Core state management hook for AI chat.\n *\n * @example\n * const chat = useChatState({\n * onSend: async (msg, history) => {\n * const res = await fetch(\"/api/chat\", { method: \"POST\", body: JSON.stringify({ messages: history }) });\n * const data = await res.json();\n * return { role: \"assistant\", content: data.reply, components: data.components };\n * },\n * });\n */\nexport default function useChatState({ initialMessages = [], onSend }: UseChatStateOptions = {}): UseChatStateReturn {\n const [messages, setMessages] = useState<ChatMessage[]>(() =>\n initialMessages.map((m) => ({\n id: uid(),\n timestamp: new Date().toISOString(),\n role: m.role || \"user\",\n ...m\n } as ChatMessage))\n );\n const [isLoading, setIsLoading] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const onSendRef = useRef(onSend);\n onSendRef.current = onSend;\n\n const addMessage = useCallback((msg: Partial<ChatMessage>): string => {\n const full: ChatMessage = {\n id: uid(),\n timestamp: new Date().toISOString(),\n role: msg.role || \"assistant\",\n ...msg\n } as ChatMessage;\n setMessages((prev) => [...prev, full]);\n return full.id;\n }, []);\n\n const updateMessage = useCallback((id: string, updates: Partial<ChatMessage>) => {\n setMessages((prev) =>\n prev.map((m) => (m.id === id ? { ...m, ...updates } : m))\n );\n }, []);\n\n const appendChunk = useCallback((id: string, chunk: string) => {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === id ? { ...m, content: (m.content ?? \"\") + chunk } : m\n )\n );\n }, []);\n\n const removeMessage = useCallback((id: string) => {\n setMessages((prev) => prev.filter((m) => m.id !== id));\n }, []);\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n setError(null);\n }, []);\n\n const sendMessage = useCallback(\n async (content: string, extra: Partial<ChatMessage> = {}) => {\n if (!content?.trim()) return;\n setError(null);\n\n const userMsg: ChatMessage = {\n role: \"user\",\n content: content.trim(),\n ...extra,\n id: uid(),\n timestamp: new Date().toISOString()\n } as ChatMessage;\n\n setMessages((prev) => [...prev, userMsg]);\n setIsLoading(true);\n\n try {\n const allMsgs = [...messages, userMsg];\n const result = await onSendRef.current?.(userMsg, allMsgs, {\n addMessage,\n updateMessage,\n appendChunk,\n setStreaming: setIsStreaming,\n });\n\n if (result && typeof result === \"object\" && result.role) {\n addMessage(result);\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Failed to send message\";\n setError(errorMessage);\n addMessage({\n role: \"system\",\n content: err instanceof Error ? err.message : \"Something went wrong. Please try again.\",\n isError: true,\n });\n } finally {\n setIsLoading(false);\n setIsStreaming(false);\n }\n },\n [messages, addMessage, updateMessage, appendChunk]\n );\n\n const retryLast = useCallback(() => {\n const lastUser = [...messages].reverse().find((m) => m.role === \"user\");\n if (!lastUser) return;\n\n const idx = messages.lastIndexOf(lastUser);\n setMessages(messages.slice(0, idx));\n setError(null);\n\n sendMessage(lastUser.content || \"\");\n }, [messages, sendMessage]);\n\n return {\n messages,\n isLoading,\n isStreaming,\n error,\n sendMessage,\n addMessage,\n updateMessage,\n appendChunk,\n removeMessage,\n clearMessages,\n retryLast,\n setError,\n };\n}\n"],"names":["_nextId","uid","useChatState","initialMessages","onSend","messages","setMessages","useState","m","isLoading","setIsLoading","isStreaming","setIsStreaming","error","setError","onSendRef","useRef","addMessage","useCallback","msg","full","prev","updateMessage","id","updates","appendChunk","chunk","removeMessage","clearMessages","sendMessage","content","extra","userMsg","allMsgs","result","err","errorMessage","retryLast","lastUser","idx"],"mappings":"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"}
|
|
@@ -1,143 +1,119 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface Metric {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string | number;
|
|
5
|
+
trend?: string | number | null;
|
|
6
|
+
}
|
|
7
|
+
export interface MetricsStripProps {
|
|
8
|
+
metrics?: Metric[];
|
|
9
|
+
title?: string;
|
|
10
|
+
collapsible?: boolean;
|
|
11
|
+
collapsed?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface ListItem {
|
|
14
|
+
id?: string;
|
|
15
|
+
title?: string;
|
|
16
|
+
name?: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
status?: "critical" | "warning" | string;
|
|
19
|
+
actions?: Array<string | {
|
|
20
|
+
label: string;
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
export interface ItemListProps {
|
|
24
|
+
items?: ListItem[];
|
|
25
|
+
title?: string;
|
|
26
|
+
onItemClick?: (item: ListItem) => void;
|
|
27
|
+
}
|
|
28
|
+
export interface TableColumn {
|
|
29
|
+
key: string;
|
|
30
|
+
label: string;
|
|
31
|
+
}
|
|
32
|
+
export interface DataTableProps {
|
|
33
|
+
title?: string;
|
|
34
|
+
subtitle?: string;
|
|
35
|
+
columns?: TableColumn[];
|
|
36
|
+
data?: any[];
|
|
37
|
+
rows?: any[];
|
|
38
|
+
searchable?: boolean;
|
|
39
|
+
sortable?: boolean;
|
|
40
|
+
paginated?: boolean;
|
|
41
|
+
pageSize?: number;
|
|
42
|
+
}
|
|
43
|
+
export interface DataPoint {
|
|
44
|
+
x: number;
|
|
45
|
+
y: number;
|
|
46
|
+
[key: string]: any;
|
|
47
|
+
}
|
|
48
|
+
export interface DataChartProps {
|
|
49
|
+
title?: string;
|
|
50
|
+
subtitle?: string;
|
|
51
|
+
chartType?: string;
|
|
52
|
+
data?: DataPoint[];
|
|
53
|
+
height?: number;
|
|
54
|
+
}
|
|
55
|
+
export interface MetricCardComponentProps {
|
|
56
|
+
title?: string;
|
|
57
|
+
label?: string;
|
|
58
|
+
value?: string | number;
|
|
59
|
+
trend?: string | number;
|
|
60
|
+
change?: string | number;
|
|
61
|
+
changeType?: string;
|
|
62
|
+
color?: string;
|
|
63
|
+
icon?: React.ReactNode;
|
|
64
|
+
description?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface StatusCardComponentProps {
|
|
67
|
+
title?: string;
|
|
68
|
+
subtitle?: string;
|
|
69
|
+
status?: string;
|
|
70
|
+
items?: any[];
|
|
71
|
+
layout?: string;
|
|
72
|
+
showProgress?: boolean;
|
|
73
|
+
showTimestamp?: boolean;
|
|
74
|
+
}
|
|
75
|
+
export interface ActionListProps {
|
|
76
|
+
actions?: Array<string | {
|
|
77
|
+
label: string;
|
|
78
|
+
}>;
|
|
79
|
+
title?: string;
|
|
80
|
+
onAction?: (action: string | {
|
|
81
|
+
label: string;
|
|
82
|
+
}) => void;
|
|
83
|
+
}
|
|
84
|
+
export interface CalloutCardProps {
|
|
85
|
+
title?: string;
|
|
86
|
+
message?: string;
|
|
87
|
+
tone?: "neutral" | "success" | "warning" | "danger";
|
|
88
|
+
}
|
|
89
|
+
export interface SpacerProps {
|
|
90
|
+
size?: "sm" | "md" | "lg";
|
|
91
|
+
}
|
|
92
|
+
export interface NarrativeSummaryProps {
|
|
93
|
+
summary?: string;
|
|
94
|
+
title?: string;
|
|
95
|
+
}
|
|
96
|
+
export interface SchemaComponent {
|
|
97
|
+
id?: string;
|
|
98
|
+
type: string;
|
|
99
|
+
props?: Record<string, any>;
|
|
100
|
+
}
|
|
101
|
+
declare const BUILTIN_COMPONENTS: {
|
|
102
|
+
NarrativeSummary({ summary, title }: NarrativeSummaryProps): import("react/jsx-runtime").JSX.Element;
|
|
103
|
+
MetricsStrip({ metrics, title, collapsible, collapsed: initialCollapsed }: MetricsStripProps): import("react/jsx-runtime").JSX.Element;
|
|
104
|
+
ItemList({ items, title, onItemClick }: ItemListProps): import("react/jsx-runtime").JSX.Element;
|
|
105
|
+
DataTable({ title, subtitle, columns, data, rows, searchable, sortable, paginated, pageSize }: DataTableProps): import("react/jsx-runtime").JSX.Element;
|
|
106
|
+
DataChart({ title, subtitle, chartType, data, height }: DataChartProps): import("react/jsx-runtime").JSX.Element;
|
|
107
|
+
MetricCard({ title, label, value, trend, change, changeType, color, icon, description }: MetricCardComponentProps): import("react/jsx-runtime").JSX.Element;
|
|
108
|
+
StatusCard({ title, subtitle, status, items, layout, showProgress, showTimestamp }: StatusCardComponentProps): import("react/jsx-runtime").JSX.Element;
|
|
109
|
+
ActionList({ actions, title, onAction }: ActionListProps): import("react/jsx-runtime").JSX.Element;
|
|
110
|
+
CalloutCard({ title, message, tone }: CalloutCardProps): import("react/jsx-runtime").JSX.Element;
|
|
65
111
|
Divider(): import("react/jsx-runtime").JSX.Element;
|
|
66
|
-
Spacer({ size }:
|
|
67
|
-
size?: string | undefined;
|
|
68
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
112
|
+
Spacer({ size }: SpacerProps): import("react/jsx-runtime").JSX.Element;
|
|
69
113
|
};
|
|
70
|
-
export function
|
|
71
|
-
export function
|
|
72
|
-
export function
|
|
73
|
-
export function
|
|
114
|
+
export declare function getComponentRegistry(): Record<string, React.ComponentType<any>>;
|
|
115
|
+
export declare function registerComponent(type: string, Component: React.ComponentType<any>): void;
|
|
116
|
+
export declare function registerComponents(map: Record<string, React.ComponentType<any>>): void;
|
|
117
|
+
export declare function renderSchemaComponent(component: SchemaComponent, index: number): React.ReactElement;
|
|
118
|
+
export declare function renderSchema(components?: SchemaComponent[]): React.ReactElement[];
|
|
74
119
|
export default BUILTIN_COMPONENTS;
|
|
75
|
-
declare namespace BUILTIN_COMPONENTS {
|
|
76
|
-
function NarrativeSummary({ summary, title }: {
|
|
77
|
-
summary: any;
|
|
78
|
-
title: any;
|
|
79
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
80
|
-
function MetricsStrip({ metrics, title, collapsible, collapsed: initialCollapsed }: {
|
|
81
|
-
metrics?: never[] | undefined;
|
|
82
|
-
title: any;
|
|
83
|
-
collapsible?: boolean | undefined;
|
|
84
|
-
collapsed?: boolean | undefined;
|
|
85
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
86
|
-
function ItemList({ items, title, onItemClick }: {
|
|
87
|
-
items?: never[] | undefined;
|
|
88
|
-
title: any;
|
|
89
|
-
onItemClick: any;
|
|
90
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
91
|
-
function DataTable({ title, subtitle, columns, data, rows, searchable, sortable, paginated, pageSize }: {
|
|
92
|
-
title: any;
|
|
93
|
-
subtitle: any;
|
|
94
|
-
columns?: never[] | undefined;
|
|
95
|
-
data?: never[] | undefined;
|
|
96
|
-
rows: any;
|
|
97
|
-
searchable?: boolean | undefined;
|
|
98
|
-
sortable?: boolean | undefined;
|
|
99
|
-
paginated?: boolean | undefined;
|
|
100
|
-
pageSize?: number | undefined;
|
|
101
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
102
|
-
function DataChart({ title, subtitle, chartType, data, height }: {
|
|
103
|
-
title: any;
|
|
104
|
-
subtitle: any;
|
|
105
|
-
chartType?: string | undefined;
|
|
106
|
-
data?: never[] | undefined;
|
|
107
|
-
height?: number | undefined;
|
|
108
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
109
|
-
function MetricCard({ title, label, value, trend, change, changeType, color, icon, description }: {
|
|
110
|
-
title: any;
|
|
111
|
-
label: any;
|
|
112
|
-
value: any;
|
|
113
|
-
trend: any;
|
|
114
|
-
change: any;
|
|
115
|
-
changeType: any;
|
|
116
|
-
color: any;
|
|
117
|
-
icon: any;
|
|
118
|
-
description: any;
|
|
119
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
120
|
-
function StatusCard({ title, subtitle, status, items, layout, showProgress, showTimestamp }: {
|
|
121
|
-
title: any;
|
|
122
|
-
subtitle: any;
|
|
123
|
-
status: any;
|
|
124
|
-
items: any;
|
|
125
|
-
layout: any;
|
|
126
|
-
showProgress: any;
|
|
127
|
-
showTimestamp: any;
|
|
128
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
129
|
-
function ActionList({ actions, title, onAction }: {
|
|
130
|
-
actions?: never[] | undefined;
|
|
131
|
-
title: any;
|
|
132
|
-
onAction: any;
|
|
133
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
134
|
-
function CalloutCard({ title, message, tone }: {
|
|
135
|
-
title: any;
|
|
136
|
-
message: any;
|
|
137
|
-
tone?: string | undefined;
|
|
138
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
139
|
-
function Divider(): import("react/jsx-runtime").JSX.Element;
|
|
140
|
-
function Spacer({ size }: {
|
|
141
|
-
size?: string | undefined;
|
|
142
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
143
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs as i, jsx as e } from "react/jsx-runtime";
|
|
2
|
-
import b from "react";
|
|
2
|
+
import * as b from "react";
|
|
3
3
|
import "../library/theme/AppThemeProvider.js";
|
|
4
4
|
import u from "../library/ui/UIButton.js";
|
|
5
5
|
import p from "../library/ui/Chip.js";
|
|
@@ -18,14 +18,14 @@ import "react-dom";
|
|
|
18
18
|
import "../library/data/DataModeProvider.js";
|
|
19
19
|
import "@heroicons/react/24/solid";
|
|
20
20
|
const y = {
|
|
21
|
-
NarrativeSummary({ summary:
|
|
21
|
+
NarrativeSummary({ summary: r, title: a }) {
|
|
22
22
|
return /* @__PURE__ */ i("div", { className: "text-sm text-slate-600 dark:text-slate-300", children: [
|
|
23
23
|
a && /* @__PURE__ */ e("div", { className: "mb-1 font-medium text-slate-900 dark:text-slate-50", children: a }),
|
|
24
|
-
|
|
24
|
+
r
|
|
25
25
|
] });
|
|
26
26
|
},
|
|
27
|
-
MetricsStrip({ metrics:
|
|
28
|
-
const [o, s] = b.useState(l), n =
|
|
27
|
+
MetricsStrip({ metrics: r = [], title: a, collapsible: d = !1, collapsed: l = !1 }) {
|
|
28
|
+
const [o, s] = b.useState(l), n = r.length ? r : [
|
|
29
29
|
{ label: "Metric A", value: "—", trend: null },
|
|
30
30
|
{ label: "Metric B", value: "—", trend: null },
|
|
31
31
|
{ label: "Metric C", value: "—", trend: null }
|
|
@@ -40,7 +40,7 @@ const y = {
|
|
|
40
40
|
/* @__PURE__ */ i("span", { children: [
|
|
41
41
|
a ?? "Metrics",
|
|
42
42
|
": ",
|
|
43
|
-
n.map((
|
|
43
|
+
n.map((t) => `${t.label} ${t.value}`).join(" · ")
|
|
44
44
|
] }),
|
|
45
45
|
/* @__PURE__ */ e("span", { children: "▸" })
|
|
46
46
|
]
|
|
@@ -58,26 +58,26 @@ const y = {
|
|
|
58
58
|
}
|
|
59
59
|
)
|
|
60
60
|
] }),
|
|
61
|
-
/* @__PURE__ */ e("div", { className: "flex flex-wrap gap-4", children: n.map((
|
|
62
|
-
/* @__PURE__ */ e("div", { className: "text-xs text-slate-400 dark:text-slate-500", children:
|
|
61
|
+
/* @__PURE__ */ e("div", { className: "flex flex-wrap gap-4", children: n.map((t) => /* @__PURE__ */ i("div", { className: "min-w-[80px]", children: [
|
|
62
|
+
/* @__PURE__ */ e("div", { className: "text-xs text-slate-400 dark:text-slate-500", children: t.label }),
|
|
63
63
|
/* @__PURE__ */ i("div", { className: "flex items-baseline gap-1.5", children: [
|
|
64
|
-
/* @__PURE__ */ e("span", { className: "text-sm font-semibold text-slate-700 dark:text-slate-200", children:
|
|
65
|
-
|
|
64
|
+
/* @__PURE__ */ e("span", { className: "text-sm font-semibold text-slate-700 dark:text-slate-200", children: t.value }),
|
|
65
|
+
t.trend && /* @__PURE__ */ e("span", { className: `text-xs ${String(t.trend).startsWith?.("+") || typeof t.trend == "number" && t.trend > 0 ? "text-red-500" : "text-emerald-500"}`, children: typeof t.trend == "number" && t.trend > 0 ? `+${t.trend}` : t.trend })
|
|
66
66
|
] })
|
|
67
|
-
] },
|
|
67
|
+
] }, t.label)) })
|
|
68
68
|
] });
|
|
69
69
|
},
|
|
70
|
-
ItemList({ items:
|
|
70
|
+
ItemList({ items: r = [], title: a, onItemClick: d }) {
|
|
71
71
|
const [l, o] = b.useState(null);
|
|
72
|
-
return
|
|
72
|
+
return r.length ? /* @__PURE__ */ i("div", { className: "space-y-2", children: [
|
|
73
73
|
a && /* @__PURE__ */ i("div", { className: "flex items-center justify-between", children: [
|
|
74
74
|
/* @__PURE__ */ e("span", { className: "text-sm font-medium text-slate-900 dark:text-slate-50", children: a }),
|
|
75
75
|
/* @__PURE__ */ i("span", { className: "text-xs text-slate-400 dark:text-slate-500", children: [
|
|
76
|
-
|
|
76
|
+
r.length,
|
|
77
77
|
" items"
|
|
78
78
|
] })
|
|
79
79
|
] }),
|
|
80
|
-
/* @__PURE__ */ e("div", { className: "space-y-1.5", children:
|
|
80
|
+
/* @__PURE__ */ e("div", { className: "space-y-1.5", children: r.map((s, n) => /* @__PURE__ */ i("div", { className: "rounded-xl border border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900", children: [
|
|
81
81
|
/* @__PURE__ */ e(
|
|
82
82
|
"button",
|
|
83
83
|
{
|
|
@@ -95,19 +95,19 @@ const y = {
|
|
|
95
95
|
] })
|
|
96
96
|
}
|
|
97
97
|
),
|
|
98
|
-
l === (s.id ?? n) && s.actions && /* @__PURE__ */ e("div", { className: "border-t border-slate-100 px-3 py-2 dark:border-slate-800", children: /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1.5", children: s.actions.map((
|
|
98
|
+
l === (s.id ?? n) && s.actions && /* @__PURE__ */ e("div", { className: "border-t border-slate-100 px-3 py-2 dark:border-slate-800", children: /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1.5", children: s.actions.map((t, m) => /* @__PURE__ */ e(
|
|
99
99
|
"button",
|
|
100
100
|
{
|
|
101
101
|
type: "button",
|
|
102
102
|
className: `rounded-md px-2.5 py-1 text-xs font-medium transition-colors ${m === 0 ? "bg-slate-900 text-white hover:bg-slate-800 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-200" : "bg-slate-100 text-slate-700 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-700"}`,
|
|
103
|
-
children: typeof
|
|
103
|
+
children: typeof t == "string" ? t : t.label
|
|
104
104
|
},
|
|
105
|
-
typeof
|
|
105
|
+
typeof t == "string" ? t : t.label
|
|
106
106
|
)) }) })
|
|
107
107
|
] }, s.id ?? n)) })
|
|
108
108
|
] }) : /* @__PURE__ */ e("div", { className: "text-sm text-slate-500 dark:text-slate-400", children: "No items." });
|
|
109
109
|
},
|
|
110
|
-
DataTable({ title:
|
|
110
|
+
DataTable({ title: r, subtitle: a, columns: d = [], data: l = [], rows: o, searchable: s = !0, sortable: n = !0, paginated: t = !0, pageSize: m = 5 }) {
|
|
111
111
|
const c = l.length ? l : o ?? [], x = d.length ? d : [
|
|
112
112
|
{ key: "name", label: "Name" },
|
|
113
113
|
{ key: "status", label: "Status" },
|
|
@@ -116,23 +116,23 @@ const y = {
|
|
|
116
116
|
return /* @__PURE__ */ e(
|
|
117
117
|
k,
|
|
118
118
|
{
|
|
119
|
-
title:
|
|
119
|
+
title: r ?? "Data",
|
|
120
120
|
subtitle: a,
|
|
121
121
|
columns: x,
|
|
122
122
|
data: c,
|
|
123
123
|
searchable: s,
|
|
124
124
|
sortable: n,
|
|
125
|
-
paginated:
|
|
125
|
+
paginated: t,
|
|
126
126
|
pageSize: m
|
|
127
127
|
}
|
|
128
128
|
);
|
|
129
129
|
},
|
|
130
|
-
DataChart({ title:
|
|
131
|
-
const s = l.length ? l : Array.from({ length: 12 }, (n,
|
|
130
|
+
DataChart({ title: r, subtitle: a, chartType: d = "line", data: l = [], height: o = 200 }) {
|
|
131
|
+
const s = l.length ? l : Array.from({ length: 12 }, (n, t) => ({ x: t, y: Math.random() * 100 }));
|
|
132
132
|
return /* @__PURE__ */ e(
|
|
133
133
|
h,
|
|
134
134
|
{
|
|
135
|
-
title:
|
|
135
|
+
title: r ?? "Trend",
|
|
136
136
|
subtitle: a ?? "Data visualization",
|
|
137
137
|
chartType: d,
|
|
138
138
|
height: o,
|
|
@@ -142,34 +142,34 @@ const y = {
|
|
|
142
142
|
data: s,
|
|
143
143
|
responsive: !0,
|
|
144
144
|
height: o,
|
|
145
|
-
ariaLabel:
|
|
146
|
-
renderChart: (n,
|
|
145
|
+
ariaLabel: r,
|
|
146
|
+
renderChart: (n, t, m, c) => N.lineChart(n, t, m, c),
|
|
147
147
|
options: { xKey: "x", yKey: "y", showGrid: !0, showAxes: !0 }
|
|
148
148
|
}
|
|
149
149
|
)
|
|
150
150
|
}
|
|
151
151
|
);
|
|
152
152
|
},
|
|
153
|
-
MetricCard({ title:
|
|
153
|
+
MetricCard({ title: r, label: a, value: d, trend: l, change: o, changeType: s, color: n, icon: t, description: m }) {
|
|
154
154
|
return /* @__PURE__ */ e(
|
|
155
155
|
g,
|
|
156
156
|
{
|
|
157
|
-
title:
|
|
157
|
+
title: r ?? a,
|
|
158
158
|
value: d ?? "—",
|
|
159
159
|
trend: l,
|
|
160
160
|
change: o,
|
|
161
161
|
changeType: s,
|
|
162
162
|
color: n,
|
|
163
|
-
icon:
|
|
164
|
-
|
|
163
|
+
icon: t,
|
|
164
|
+
subtitle: m
|
|
165
165
|
}
|
|
166
166
|
);
|
|
167
167
|
},
|
|
168
|
-
StatusCard({ title:
|
|
168
|
+
StatusCard({ title: r, subtitle: a, status: d, items: l, layout: o, showProgress: s, showTimestamp: n }) {
|
|
169
169
|
return /* @__PURE__ */ e(
|
|
170
170
|
f,
|
|
171
171
|
{
|
|
172
|
-
title:
|
|
172
|
+
title: r,
|
|
173
173
|
subtitle: a,
|
|
174
174
|
status: d,
|
|
175
175
|
items: l,
|
|
@@ -179,10 +179,10 @@ const y = {
|
|
|
179
179
|
}
|
|
180
180
|
);
|
|
181
181
|
},
|
|
182
|
-
ActionList({ actions:
|
|
182
|
+
ActionList({ actions: r = [], title: a, onAction: d }) {
|
|
183
183
|
return /* @__PURE__ */ i("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-900", children: [
|
|
184
184
|
a && /* @__PURE__ */ e("div", { className: "mb-3 text-sm font-medium text-slate-900 dark:text-slate-50", children: a }),
|
|
185
|
-
/* @__PURE__ */ e("div", { className: "flex flex-wrap gap-2", children:
|
|
185
|
+
/* @__PURE__ */ e("div", { className: "flex flex-wrap gap-2", children: r.map((l, o) => /* @__PURE__ */ e(
|
|
186
186
|
u,
|
|
187
187
|
{
|
|
188
188
|
size: "sm",
|
|
@@ -194,7 +194,7 @@ const y = {
|
|
|
194
194
|
)) })
|
|
195
195
|
] });
|
|
196
196
|
},
|
|
197
|
-
CalloutCard({ title:
|
|
197
|
+
CalloutCard({ title: r, message: a, tone: d = "neutral" }) {
|
|
198
198
|
const l = {
|
|
199
199
|
neutral: "border-slate-200 bg-slate-50 text-slate-700 dark:border-slate-800 dark:bg-slate-950/30 dark:text-slate-200",
|
|
200
200
|
success: "border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900/40 dark:bg-emerald-950/20 dark:text-emerald-200",
|
|
@@ -202,31 +202,31 @@ const y = {
|
|
|
202
202
|
danger: "border-rose-200 bg-rose-50 text-rose-800 dark:border-rose-900/40 dark:bg-rose-950/20 dark:text-rose-200"
|
|
203
203
|
};
|
|
204
204
|
return /* @__PURE__ */ i("div", { className: `rounded-xl border p-4 ${l[d] ?? l.neutral}`, children: [
|
|
205
|
-
|
|
205
|
+
r && /* @__PURE__ */ e("div", { className: "mb-1 text-sm font-semibold", children: r }),
|
|
206
206
|
/* @__PURE__ */ e("div", { className: "text-sm", children: a })
|
|
207
207
|
] });
|
|
208
208
|
},
|
|
209
209
|
Divider() {
|
|
210
210
|
return /* @__PURE__ */ e("div", { className: "h-px bg-slate-200 dark:bg-slate-800" });
|
|
211
211
|
},
|
|
212
|
-
Spacer({ size:
|
|
212
|
+
Spacer({ size: r = "md" }) {
|
|
213
213
|
const a = { sm: "h-2", md: "h-4", lg: "h-6" };
|
|
214
|
-
return /* @__PURE__ */ e("div", { className: a[
|
|
214
|
+
return /* @__PURE__ */ e("div", { className: a[r] ?? a.md });
|
|
215
215
|
}
|
|
216
216
|
};
|
|
217
217
|
let C = { ...y };
|
|
218
218
|
function w() {
|
|
219
219
|
return C;
|
|
220
220
|
}
|
|
221
|
-
function
|
|
222
|
-
const l = w()[
|
|
223
|
-
return l ? /* @__PURE__ */ e(l, { ...
|
|
221
|
+
function P(r, a) {
|
|
222
|
+
const l = w()[r.type];
|
|
223
|
+
return l ? /* @__PURE__ */ e(l, { ...r.props ?? {} }, r.id ?? a) : /* @__PURE__ */ i("div", { className: "rounded-lg border border-dashed border-slate-300 p-3 text-xs text-slate-500 dark:border-slate-700", children: [
|
|
224
224
|
"Unknown component: ",
|
|
225
|
-
|
|
225
|
+
r.type
|
|
226
226
|
] }, a);
|
|
227
227
|
}
|
|
228
228
|
export {
|
|
229
229
|
w as getComponentRegistry,
|
|
230
|
-
|
|
230
|
+
P as renderSchemaComponent
|
|
231
231
|
};
|
|
232
232
|
//# sourceMappingURL=ComponentRegistry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComponentRegistry.js","sources":["../../../src/components/workspace/ComponentRegistry.jsx"],"sourcesContent":["import React from \"react\";\nimport {\n BaseCard,\n MetricCard,\n TableCard,\n ChartCard,\n D3Chart,\n D3ChartTemplates,\n StatusCard,\n ListCard,\n UIButton,\n UIChip,\n UIText\n} from \"@/components/library\";\n\nconst BUILTIN_COMPONENTS = {\n NarrativeSummary({ summary, title }) {\n return (\n <div className=\"text-sm text-slate-600 dark:text-slate-300\">\n {title && <div className=\"mb-1 font-medium text-slate-900 dark:text-slate-50\">{title}</div>}\n {summary}\n </div>\n );\n },\n\n MetricsStrip({ metrics = [], title, collapsible = false, collapsed: initialCollapsed = false }) {\n const [collapsed, setCollapsed] = React.useState(initialCollapsed);\n\n const items = metrics.length ? metrics : [\n { label: \"Metric A\", value: \"—\", trend: null },\n { label: \"Metric B\", value: \"—\", trend: null },\n { label: \"Metric C\", value: \"—\", trend: null }\n ];\n\n if (collapsible && collapsed) {\n return (\n <button\n type=\"button\"\n onClick={() => setCollapsed(false)}\n className=\"flex w-full items-center justify-between rounded-lg border border-slate-200 bg-white px-3 py-2 text-left text-xs text-slate-500 hover:bg-slate-50 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-400 dark:hover:bg-slate-800\"\n >\n <span>{title ?? \"Metrics\"}: {items.map(m => `${m.label} ${m.value}`).join(\" · \")}</span>\n <span>▸</span>\n </button>\n );\n }\n\n return (\n <div className=\"rounded-xl border border-slate-200 bg-white p-3 dark:border-slate-800 dark:bg-slate-900\">\n {(title || collapsible) && (\n <div className=\"mb-2 flex items-center justify-between\">\n <span className=\"text-xs font-medium text-slate-500 dark:text-slate-400\">{title ?? \"Metrics\"}</span>\n {collapsible && (\n <button\n type=\"button\"\n onClick={() => setCollapsed(true)}\n className=\"text-xs text-slate-400 hover:text-slate-600 dark:text-slate-500 dark:hover:text-slate-300\"\n >\n Collapse\n </button>\n )}\n </div>\n )}\n <div className=\"flex flex-wrap gap-4\">\n {items.map((m) => (\n <div key={m.label} className=\"min-w-[80px]\">\n <div className=\"text-xs text-slate-400 dark:text-slate-500\">{m.label}</div>\n <div className=\"flex items-baseline gap-1.5\">\n <span className=\"text-sm font-semibold text-slate-700 dark:text-slate-200\">{m.value}</span>\n {m.trend && (\n <span className={`text-xs ${String(m.trend).startsWith?.(\"+\") || m.trend > 0 ? \"text-red-500\" : \"text-emerald-500\"}`}>\n {typeof m.trend === \"number\" ? (m.trend > 0 ? `+${m.trend}` : m.trend) : m.trend}\n </span>\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n },\n\n ItemList({ items = [], title, onItemClick }) {\n const [expanded, setExpanded] = React.useState(null);\n if (!items.length) {\n return <div className=\"text-sm text-slate-500 dark:text-slate-400\">No items.</div>;\n }\n return (\n <div className=\"space-y-2\">\n {title && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium text-slate-900 dark:text-slate-50\">{title}</span>\n <span className=\"text-xs text-slate-400 dark:text-slate-500\">{items.length} items</span>\n </div>\n )}\n <div className=\"space-y-1.5\">\n {items.map((item, idx) => (\n <div key={item.id ?? idx} className=\"rounded-xl border border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900\">\n <button\n type=\"button\"\n onClick={() => {\n setExpanded(expanded === (item.id ?? idx) ? null : (item.id ?? idx));\n onItemClick?.(item);\n }}\n className=\"flex w-full items-start justify-between gap-3 p-3 text-left\"\n >\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"text-sm font-medium text-slate-900 dark:text-slate-50\">\n {item.title ?? item.name ?? `Item ${idx + 1}`}\n </div>\n {item.status && (\n <UIChip tone={item.status === \"critical\" ? \"danger\" : item.status === \"warning\" ? \"warning\" : \"neutral\"} className=\"shrink-0\">\n {item.status}\n </UIChip>\n )}\n </div>\n {item.description && (\n <div className=\"mt-1 text-xs text-slate-500 dark:text-slate-400\">{item.description}</div>\n )}\n </div>\n </button>\n {expanded === (item.id ?? idx) && item.actions && (\n <div className=\"border-t border-slate-100 px-3 py-2 dark:border-slate-800\">\n <div className=\"flex flex-wrap gap-1.5\">\n {item.actions.map((action, i) => (\n <button\n key={typeof action === \"string\" ? action : action.label}\n type=\"button\"\n className={`rounded-md px-2.5 py-1 text-xs font-medium transition-colors ${\n i === 0\n ? \"bg-slate-900 text-white hover:bg-slate-800 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-200\"\n : \"bg-slate-100 text-slate-700 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-700\"\n }`}\n >\n {typeof action === \"string\" ? action : action.label}\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n );\n },\n\n DataTable({ title, subtitle, columns = [], data = [], rows, searchable = true, sortable = true, paginated = true, pageSize = 5 }) {\n const tableData = data.length ? data : (rows ?? []);\n const cols = columns.length ? columns : [\n { key: \"name\", label: \"Name\" },\n { key: \"status\", label: \"Status\" },\n { key: \"value\", label: \"Value\" }\n ];\n return (\n <TableCard\n title={title ?? \"Data\"}\n subtitle={subtitle}\n columns={cols}\n data={tableData}\n searchable={searchable}\n sortable={sortable}\n paginated={paginated}\n pageSize={pageSize}\n />\n );\n },\n\n DataChart({ title, subtitle, chartType = \"line\", data = [], height = 200 }) {\n const series = data.length ? data : Array.from({ length: 12 }, (_, i) => ({ x: i, y: Math.random() * 100 }));\n return (\n <ChartCard\n title={title ?? \"Trend\"}\n subtitle={subtitle ?? \"Data visualization\"}\n chartType={chartType}\n height={height}\n chart={\n <D3Chart\n data={series}\n responsive\n height={height}\n ariaLabel={title}\n renderChart={(svg, d, dims, opts) => D3ChartTemplates.lineChart(svg, d, dims, opts)}\n options={{ xKey: \"x\", yKey: \"y\", showGrid: true, showAxes: true }}\n />\n }\n />\n );\n },\n\n MetricCard({ title, label, value, trend, change, changeType, color, icon, description }) {\n return (\n <MetricCard\n title={title ?? label}\n value={value ?? \"—\"}\n trend={trend}\n change={change}\n changeType={changeType}\n color={color}\n icon={icon}\n description={description}\n />\n );\n },\n\n StatusCard({ title, subtitle, status, items, layout, showProgress, showTimestamp }) {\n return (\n <StatusCard\n title={title}\n subtitle={subtitle}\n status={status}\n items={items}\n layout={layout}\n showProgress={showProgress}\n showTimestamp={showTimestamp}\n />\n );\n },\n\n ActionList({ actions = [], title, onAction }) {\n return (\n <div className=\"rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-900\">\n {title && <div className=\"mb-3 text-sm font-medium text-slate-900 dark:text-slate-50\">{title}</div>}\n <div className=\"flex flex-wrap gap-2\">\n {actions.map((action, i) => (\n <UIButton\n key={i}\n size=\"sm\"\n variant={i === 0 ? \"primary\" : \"outline\"}\n onClick={() => onAction?.(action)}\n >\n {typeof action === \"string\" ? action : action.label}\n </UIButton>\n ))}\n </div>\n </div>\n );\n },\n\n CalloutCard({ title, message, tone = \"neutral\" }) {\n const toneClasses = {\n neutral: \"border-slate-200 bg-slate-50 text-slate-700 dark:border-slate-800 dark:bg-slate-950/30 dark:text-slate-200\",\n success: \"border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900/40 dark:bg-emerald-950/20 dark:text-emerald-200\",\n warning: \"border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900/40 dark:bg-amber-950/20 dark:text-amber-200\",\n danger: \"border-rose-200 bg-rose-50 text-rose-800 dark:border-rose-900/40 dark:bg-rose-950/20 dark:text-rose-200\"\n };\n return (\n <div className={`rounded-xl border p-4 ${toneClasses[tone] ?? toneClasses.neutral}`}>\n {title && <div className=\"mb-1 text-sm font-semibold\">{title}</div>}\n <div className=\"text-sm\">{message}</div>\n </div>\n );\n },\n\n Divider() {\n return <div className=\"h-px bg-slate-200 dark:bg-slate-800\" />;\n },\n\n Spacer({ size = \"md\" }) {\n const heights = { sm: \"h-2\", md: \"h-4\", lg: \"h-6\" };\n return <div className={heights[size] ?? heights.md} />;\n }\n};\n\nlet _registry = { ...BUILTIN_COMPONENTS };\n\nexport function getComponentRegistry() {\n return _registry;\n}\n\nexport function registerComponent(type, Component) {\n _registry = { ..._registry, [type]: Component };\n}\n\nexport function registerComponents(map) {\n _registry = { ..._registry, ...map };\n}\n\nexport function renderSchemaComponent(component, index) {\n const registry = getComponentRegistry();\n const Component = registry[component.type];\n if (!Component) {\n return (\n <div key={index} className=\"rounded-lg border border-dashed border-slate-300 p-3 text-xs text-slate-500 dark:border-slate-700\">\n Unknown component: {component.type}\n </div>\n );\n }\n return <Component key={component.id ?? index} {...(component.props ?? {})} />;\n}\n\nexport function renderSchema(components = []) {\n return components.map((c, i) => renderSchemaComponent(c, i));\n}\n\nexport default BUILTIN_COMPONENTS;\n"],"names":["BUILTIN_COMPONENTS","summary","title","jsxs","jsx","metrics","collapsible","initialCollapsed","collapsed","setCollapsed","React","items","m","onItemClick","expanded","setExpanded","item","idx","UIChip","action","i","subtitle","columns","data","rows","searchable","sortable","paginated","pageSize","tableData","cols","TableCard","chartType","height","series","_","ChartCard","D3Chart","svg","d","dims","opts","D3ChartTemplates","label","value","trend","change","changeType","color","icon","description","MetricCard","status","layout","showProgress","showTimestamp","StatusCard","actions","onAction","UIButton","message","tone","toneClasses","size","heights","_registry","getComponentRegistry","renderSchemaComponent","component","index","Component"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ComponentRegistry.js","sources":["../../../src/components/workspace/ComponentRegistry.tsx"],"sourcesContent":["import * as React from \"react\";\nimport {\n MetricCard,\n TableCard,\n ChartCard,\n D3Chart,\n D3ChartTemplates,\n StatusCard,\n UIButton,\n UIChip\n} from \"@/components/library\";\n\nexport interface Metric {\n label: string;\n value: string | number;\n trend?: string | number | null;\n}\n\nexport interface MetricsStripProps {\n metrics?: Metric[];\n title?: string;\n collapsible?: boolean;\n collapsed?: boolean;\n}\n\nexport interface ListItem {\n id?: string;\n title?: string;\n name?: string;\n description?: string;\n status?: \"critical\" | \"warning\" | string;\n actions?: Array<string | { label: string }>;\n}\n\nexport interface ItemListProps {\n items?: ListItem[];\n title?: string;\n onItemClick?: (item: ListItem) => void;\n}\n\nexport interface TableColumn {\n key: string;\n label: string;\n}\n\nexport interface DataTableProps {\n title?: string;\n subtitle?: string;\n columns?: TableColumn[];\n data?: any[];\n rows?: any[];\n searchable?: boolean;\n sortable?: boolean;\n paginated?: boolean;\n pageSize?: number;\n}\n\nexport interface DataPoint {\n x: number;\n y: number;\n [key: string]: any;\n}\n\nexport interface DataChartProps {\n title?: string;\n subtitle?: string;\n chartType?: string;\n data?: DataPoint[];\n height?: number;\n}\n\nexport interface MetricCardComponentProps {\n title?: string;\n label?: string;\n value?: string | number;\n trend?: string | number;\n change?: string | number;\n changeType?: string;\n color?: string;\n icon?: React.ReactNode;\n description?: string;\n}\n\nexport interface StatusCardComponentProps {\n title?: string;\n subtitle?: string;\n status?: string;\n items?: any[];\n layout?: string;\n showProgress?: boolean;\n showTimestamp?: boolean;\n}\n\nexport interface ActionListProps {\n actions?: Array<string | { label: string }>;\n title?: string;\n onAction?: (action: string | { label: string }) => void;\n}\n\nexport interface CalloutCardProps {\n title?: string;\n message?: string;\n tone?: \"neutral\" | \"success\" | \"warning\" | \"danger\";\n}\n\nexport interface SpacerProps {\n size?: \"sm\" | \"md\" | \"lg\";\n}\n\nexport interface NarrativeSummaryProps {\n summary?: string;\n title?: string;\n}\n\nexport interface SchemaComponent {\n id?: string;\n type: string;\n props?: Record<string, any>;\n}\n\nconst BUILTIN_COMPONENTS = {\n NarrativeSummary({ summary, title }: NarrativeSummaryProps) {\n return (\n <div className=\"text-sm text-slate-600 dark:text-slate-300\">\n {title && <div className=\"mb-1 font-medium text-slate-900 dark:text-slate-50\">{title}</div>}\n {summary}\n </div>\n );\n },\n\n MetricsStrip({ metrics = [], title, collapsible = false, collapsed: initialCollapsed = false }: MetricsStripProps) {\n const [collapsed, setCollapsed] = React.useState(initialCollapsed);\n\n const items = metrics.length ? metrics : [\n { label: \"Metric A\", value: \"—\", trend: null },\n { label: \"Metric B\", value: \"—\", trend: null },\n { label: \"Metric C\", value: \"—\", trend: null }\n ];\n\n if (collapsible && collapsed) {\n return (\n <button\n type=\"button\"\n onClick={() => setCollapsed(false)}\n className=\"flex w-full items-center justify-between rounded-lg border border-slate-200 bg-white px-3 py-2 text-left text-xs text-slate-500 hover:bg-slate-50 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-400 dark:hover:bg-slate-800\"\n >\n <span>{title ?? \"Metrics\"}: {items.map(m => `${m.label} ${m.value}`).join(\" · \")}</span>\n <span>▸</span>\n </button>\n );\n }\n\n return (\n <div className=\"rounded-xl border border-slate-200 bg-white p-3 dark:border-slate-800 dark:bg-slate-900\">\n {(title || collapsible) && (\n <div className=\"mb-2 flex items-center justify-between\">\n <span className=\"text-xs font-medium text-slate-500 dark:text-slate-400\">{title ?? \"Metrics\"}</span>\n {collapsible && (\n <button\n type=\"button\"\n onClick={() => setCollapsed(true)}\n className=\"text-xs text-slate-400 hover:text-slate-600 dark:text-slate-500 dark:hover:text-slate-300\"\n >\n Collapse\n </button>\n )}\n </div>\n )}\n <div className=\"flex flex-wrap gap-4\">\n {items.map((m) => (\n <div key={m.label} className=\"min-w-[80px]\">\n <div className=\"text-xs text-slate-400 dark:text-slate-500\">{m.label}</div>\n <div className=\"flex items-baseline gap-1.5\">\n <span className=\"text-sm font-semibold text-slate-700 dark:text-slate-200\">{m.value}</span>\n {m.trend && (\n <span className={`text-xs ${String(m.trend).startsWith?.(\"+\") || (typeof m.trend === \"number\" && m.trend > 0) ? \"text-red-500\" : \"text-emerald-500\"}`}>\n {typeof m.trend === \"number\" ? (m.trend > 0 ? `+${m.trend}` : m.trend) : m.trend}\n </span>\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n },\n\n ItemList({ items = [], title, onItemClick }: ItemListProps) {\n const [expanded, setExpanded] = React.useState<string | number | null>(null);\n if (!items.length) {\n return <div className=\"text-sm text-slate-500 dark:text-slate-400\">No items.</div>;\n }\n return (\n <div className=\"space-y-2\">\n {title && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium text-slate-900 dark:text-slate-50\">{title}</span>\n <span className=\"text-xs text-slate-400 dark:text-slate-500\">{items.length} items</span>\n </div>\n )}\n <div className=\"space-y-1.5\">\n {items.map((item, idx) => (\n <div key={item.id ?? idx} className=\"rounded-xl border border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900\">\n <button\n type=\"button\"\n onClick={() => {\n setExpanded(expanded === (item.id ?? idx) ? null : (item.id ?? idx));\n onItemClick?.(item);\n }}\n className=\"flex w-full items-start justify-between gap-3 p-3 text-left\"\n >\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"text-sm font-medium text-slate-900 dark:text-slate-50\">\n {item.title ?? item.name ?? `Item ${idx + 1}`}\n </div>\n {item.status && (\n <UIChip tone={item.status === \"critical\" ? \"danger\" : item.status === \"warning\" ? \"warning\" : \"neutral\"} className=\"shrink-0\">\n {item.status}\n </UIChip>\n )}\n </div>\n {item.description && (\n <div className=\"mt-1 text-xs text-slate-500 dark:text-slate-400\">{item.description}</div>\n )}\n </div>\n </button>\n {expanded === (item.id ?? idx) && item.actions && (\n <div className=\"border-t border-slate-100 px-3 py-2 dark:border-slate-800\">\n <div className=\"flex flex-wrap gap-1.5\">\n {item.actions.map((action, i) => (\n <button\n key={typeof action === \"string\" ? action : action.label}\n type=\"button\"\n className={`rounded-md px-2.5 py-1 text-xs font-medium transition-colors ${\n i === 0\n ? \"bg-slate-900 text-white hover:bg-slate-800 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-200\"\n : \"bg-slate-100 text-slate-700 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-700\"\n }`}\n >\n {typeof action === \"string\" ? action : action.label}\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n );\n },\n\n DataTable({ title, subtitle, columns = [], data = [], rows, searchable = true, sortable = true, paginated = true, pageSize = 5 }: DataTableProps) {\n const tableData = data.length ? data : (rows ?? []);\n const cols = columns.length ? columns : [\n { key: \"name\", label: \"Name\" },\n { key: \"status\", label: \"Status\" },\n { key: \"value\", label: \"Value\" }\n ];\n return (\n <TableCard\n title={title ?? \"Data\"}\n subtitle={subtitle}\n columns={cols}\n data={tableData}\n searchable={searchable}\n sortable={sortable}\n paginated={paginated}\n pageSize={pageSize}\n />\n );\n },\n\n DataChart({ title, subtitle, chartType = \"line\", data = [], height = 200 }: DataChartProps) {\n const series = data.length ? data : Array.from({ length: 12 }, (_, i) => ({ x: i, y: Math.random() * 100 }));\n return (\n <ChartCard\n title={title ?? \"Trend\"}\n subtitle={subtitle ?? \"Data visualization\"}\n chartType={chartType}\n height={height}\n chart={\n <D3Chart\n data={series as any}\n responsive\n height={height}\n ariaLabel={title}\n renderChart={(svg, d, dims, opts) => D3ChartTemplates.lineChart(svg, d as any, dims, opts)}\n options={{ xKey: \"x\", yKey: \"y\", showGrid: true, showAxes: true }}\n />\n }\n />\n );\n },\n\n MetricCard({ title, label, value, trend, change, changeType, color, icon, description }: MetricCardComponentProps) {\n return (\n <MetricCard\n title={(title ?? label) as any}\n value={value ?? \"—\"}\n trend={trend as any}\n change={change as any}\n changeType={changeType as any}\n color={color as any}\n icon={icon}\n subtitle={description}\n />\n );\n },\n\n StatusCard({ title, subtitle, status, items, layout, showProgress, showTimestamp }: StatusCardComponentProps) {\n return (\n <StatusCard\n title={title}\n subtitle={subtitle}\n status={status}\n items={items}\n layout={layout as any}\n showProgress={showProgress}\n showTimestamp={showTimestamp}\n />\n );\n },\n\n ActionList({ actions = [], title, onAction }: ActionListProps) {\n return (\n <div className=\"rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-900\">\n {title && <div className=\"mb-3 text-sm font-medium text-slate-900 dark:text-slate-50\">{title}</div>}\n <div className=\"flex flex-wrap gap-2\">\n {actions.map((action, i) => (\n <UIButton\n key={i}\n size=\"sm\"\n variant={i === 0 ? \"primary\" : \"outline\"}\n onClick={() => onAction?.(action)}\n >\n {typeof action === \"string\" ? action : action.label}\n </UIButton>\n ))}\n </div>\n </div>\n );\n },\n\n CalloutCard({ title, message, tone = \"neutral\" }: CalloutCardProps) {\n const toneClasses = {\n neutral: \"border-slate-200 bg-slate-50 text-slate-700 dark:border-slate-800 dark:bg-slate-950/30 dark:text-slate-200\",\n success: \"border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900/40 dark:bg-emerald-950/20 dark:text-emerald-200\",\n warning: \"border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900/40 dark:bg-amber-950/20 dark:text-amber-200\",\n danger: \"border-rose-200 bg-rose-50 text-rose-800 dark:border-rose-900/40 dark:bg-rose-950/20 dark:text-rose-200\"\n };\n return (\n <div className={`rounded-xl border p-4 ${toneClasses[tone] ?? toneClasses.neutral}`}>\n {title && <div className=\"mb-1 text-sm font-semibold\">{title}</div>}\n <div className=\"text-sm\">{message}</div>\n </div>\n );\n },\n\n Divider() {\n return <div className=\"h-px bg-slate-200 dark:bg-slate-800\" />;\n },\n\n Spacer({ size = \"md\" }: SpacerProps) {\n const heights = { sm: \"h-2\", md: \"h-4\", lg: \"h-6\" };\n return <div className={heights[size] ?? heights.md} />;\n }\n};\n\nlet _registry: Record<string, React.ComponentType<any>> = { ...BUILTIN_COMPONENTS };\n\nexport function getComponentRegistry(): Record<string, React.ComponentType<any>> {\n return _registry;\n}\n\nexport function registerComponent(type: string, Component: React.ComponentType<any>): void {\n _registry = { ..._registry, [type]: Component };\n}\n\nexport function registerComponents(map: Record<string, React.ComponentType<any>>): void {\n _registry = { ..._registry, ...map };\n}\n\nexport function renderSchemaComponent(component: SchemaComponent, index: number): React.ReactElement {\n const registry = getComponentRegistry();\n const Component = registry[component.type];\n if (!Component) {\n return (\n <div key={index} className=\"rounded-lg border border-dashed border-slate-300 p-3 text-xs text-slate-500 dark:border-slate-700\">\n Unknown component: {component.type}\n </div>\n );\n }\n return <Component key={component.id ?? index} {...(component.props ?? {})} />;\n}\n\nexport function renderSchema(components: SchemaComponent[] = []): React.ReactElement[] {\n return components.map((c, i) => renderSchemaComponent(c, i));\n}\n\nexport default BUILTIN_COMPONENTS;\n"],"names":["BUILTIN_COMPONENTS","summary","title","jsxs","jsx","metrics","collapsible","initialCollapsed","collapsed","setCollapsed","React","items","m","onItemClick","expanded","setExpanded","item","idx","UIChip","action","i","subtitle","columns","data","rows","searchable","sortable","paginated","pageSize","tableData","cols","TableCard","chartType","height","series","_","ChartCard","D3Chart","svg","d","dims","opts","D3ChartTemplates","label","value","trend","change","changeType","color","icon","description","MetricCard","status","layout","showProgress","showTimestamp","StatusCard","actions","onAction","UIButton","message","tone","toneClasses","size","heights","_registry","getComponentRegistry","renderSchemaComponent","component","index","Component"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schandlergarcia/sf-web-components",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "Reusable Salesforce web components library with Tailwind CSS v4 and shadcn/ui",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"world-atlas": "^2.0.0"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@schandlergarcia/sf-web-components": "^1.
|
|
67
|
+
"@schandlergarcia/sf-web-components": "^1.9.0",
|
|
68
68
|
"class-variance-authority": "^0.7.1",
|
|
69
69
|
"clsx": "^2.1.1",
|
|
70
70
|
"glob": "^11.0.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { renderSchemaComponent } from "@/components/workspace/ComponentRegistry";
|
|
2
|
+
import { renderSchemaComponent, type SchemaComponent } from "@/components/workspace/ComponentRegistry";
|
|
3
3
|
import ChatToolCall, { ToolCall } from "./ChatToolCall";
|
|
4
4
|
import { UserCircleIcon, CpuChipIcon } from "@heroicons/react/24/solid";
|
|
5
5
|
|
|
@@ -78,7 +78,7 @@ export interface ChatMessageData {
|
|
|
78
78
|
id: string;
|
|
79
79
|
role: "user" | "assistant" | "system";
|
|
80
80
|
content?: string;
|
|
81
|
-
components?:
|
|
81
|
+
components?: SchemaComponent[];
|
|
82
82
|
toolCalls?: ToolCall[];
|
|
83
83
|
isError?: boolean;
|
|
84
84
|
isStreaming?: boolean;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useRef } from "react";
|
|
2
2
|
import { ToolCall } from "./ChatToolCall";
|
|
3
|
+
import type { SchemaComponent } from "@/components/workspace/ComponentRegistry";
|
|
3
4
|
|
|
4
5
|
let _nextId = 1;
|
|
5
6
|
function uid(): string {
|
|
@@ -11,7 +12,7 @@ export interface ChatMessage {
|
|
|
11
12
|
role: "user" | "assistant" | "system";
|
|
12
13
|
content?: string;
|
|
13
14
|
timestamp: string;
|
|
14
|
-
components?:
|
|
15
|
+
components?: SchemaComponent[];
|
|
15
16
|
toolCalls?: ToolCall[];
|
|
16
17
|
isError?: boolean;
|
|
17
18
|
isStreaming?: boolean;
|
|
@@ -1,20 +1,125 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import * as React from "react";
|
|
2
2
|
import {
|
|
3
|
-
BaseCard,
|
|
4
3
|
MetricCard,
|
|
5
4
|
TableCard,
|
|
6
5
|
ChartCard,
|
|
7
6
|
D3Chart,
|
|
8
7
|
D3ChartTemplates,
|
|
9
8
|
StatusCard,
|
|
10
|
-
ListCard,
|
|
11
9
|
UIButton,
|
|
12
|
-
UIChip
|
|
13
|
-
UIText
|
|
10
|
+
UIChip
|
|
14
11
|
} from "@/components/library";
|
|
15
12
|
|
|
13
|
+
export interface Metric {
|
|
14
|
+
label: string;
|
|
15
|
+
value: string | number;
|
|
16
|
+
trend?: string | number | null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface MetricsStripProps {
|
|
20
|
+
metrics?: Metric[];
|
|
21
|
+
title?: string;
|
|
22
|
+
collapsible?: boolean;
|
|
23
|
+
collapsed?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ListItem {
|
|
27
|
+
id?: string;
|
|
28
|
+
title?: string;
|
|
29
|
+
name?: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
status?: "critical" | "warning" | string;
|
|
32
|
+
actions?: Array<string | { label: string }>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ItemListProps {
|
|
36
|
+
items?: ListItem[];
|
|
37
|
+
title?: string;
|
|
38
|
+
onItemClick?: (item: ListItem) => void;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface TableColumn {
|
|
42
|
+
key: string;
|
|
43
|
+
label: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface DataTableProps {
|
|
47
|
+
title?: string;
|
|
48
|
+
subtitle?: string;
|
|
49
|
+
columns?: TableColumn[];
|
|
50
|
+
data?: any[];
|
|
51
|
+
rows?: any[];
|
|
52
|
+
searchable?: boolean;
|
|
53
|
+
sortable?: boolean;
|
|
54
|
+
paginated?: boolean;
|
|
55
|
+
pageSize?: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface DataPoint {
|
|
59
|
+
x: number;
|
|
60
|
+
y: number;
|
|
61
|
+
[key: string]: any;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface DataChartProps {
|
|
65
|
+
title?: string;
|
|
66
|
+
subtitle?: string;
|
|
67
|
+
chartType?: string;
|
|
68
|
+
data?: DataPoint[];
|
|
69
|
+
height?: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface MetricCardComponentProps {
|
|
73
|
+
title?: string;
|
|
74
|
+
label?: string;
|
|
75
|
+
value?: string | number;
|
|
76
|
+
trend?: string | number;
|
|
77
|
+
change?: string | number;
|
|
78
|
+
changeType?: string;
|
|
79
|
+
color?: string;
|
|
80
|
+
icon?: React.ReactNode;
|
|
81
|
+
description?: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface StatusCardComponentProps {
|
|
85
|
+
title?: string;
|
|
86
|
+
subtitle?: string;
|
|
87
|
+
status?: string;
|
|
88
|
+
items?: any[];
|
|
89
|
+
layout?: string;
|
|
90
|
+
showProgress?: boolean;
|
|
91
|
+
showTimestamp?: boolean;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface ActionListProps {
|
|
95
|
+
actions?: Array<string | { label: string }>;
|
|
96
|
+
title?: string;
|
|
97
|
+
onAction?: (action: string | { label: string }) => void;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface CalloutCardProps {
|
|
101
|
+
title?: string;
|
|
102
|
+
message?: string;
|
|
103
|
+
tone?: "neutral" | "success" | "warning" | "danger";
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface SpacerProps {
|
|
107
|
+
size?: "sm" | "md" | "lg";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface NarrativeSummaryProps {
|
|
111
|
+
summary?: string;
|
|
112
|
+
title?: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface SchemaComponent {
|
|
116
|
+
id?: string;
|
|
117
|
+
type: string;
|
|
118
|
+
props?: Record<string, any>;
|
|
119
|
+
}
|
|
120
|
+
|
|
16
121
|
const BUILTIN_COMPONENTS = {
|
|
17
|
-
NarrativeSummary({ summary, title }) {
|
|
122
|
+
NarrativeSummary({ summary, title }: NarrativeSummaryProps) {
|
|
18
123
|
return (
|
|
19
124
|
<div className="text-sm text-slate-600 dark:text-slate-300">
|
|
20
125
|
{title && <div className="mb-1 font-medium text-slate-900 dark:text-slate-50">{title}</div>}
|
|
@@ -23,7 +128,7 @@ const BUILTIN_COMPONENTS = {
|
|
|
23
128
|
);
|
|
24
129
|
},
|
|
25
130
|
|
|
26
|
-
MetricsStrip({ metrics = [], title, collapsible = false, collapsed: initialCollapsed = false }) {
|
|
131
|
+
MetricsStrip({ metrics = [], title, collapsible = false, collapsed: initialCollapsed = false }: MetricsStripProps) {
|
|
27
132
|
const [collapsed, setCollapsed] = React.useState(initialCollapsed);
|
|
28
133
|
|
|
29
134
|
const items = metrics.length ? metrics : [
|
|
@@ -68,7 +173,7 @@ const BUILTIN_COMPONENTS = {
|
|
|
68
173
|
<div className="flex items-baseline gap-1.5">
|
|
69
174
|
<span className="text-sm font-semibold text-slate-700 dark:text-slate-200">{m.value}</span>
|
|
70
175
|
{m.trend && (
|
|
71
|
-
<span className={`text-xs ${String(m.trend).startsWith?.("+") || m.trend > 0 ? "text-red-500" : "text-emerald-500"}`}>
|
|
176
|
+
<span className={`text-xs ${String(m.trend).startsWith?.("+") || (typeof m.trend === "number" && m.trend > 0) ? "text-red-500" : "text-emerald-500"}`}>
|
|
72
177
|
{typeof m.trend === "number" ? (m.trend > 0 ? `+${m.trend}` : m.trend) : m.trend}
|
|
73
178
|
</span>
|
|
74
179
|
)}
|
|
@@ -80,8 +185,8 @@ const BUILTIN_COMPONENTS = {
|
|
|
80
185
|
);
|
|
81
186
|
},
|
|
82
187
|
|
|
83
|
-
ItemList({ items = [], title, onItemClick }) {
|
|
84
|
-
const [expanded, setExpanded] = React.useState(null);
|
|
188
|
+
ItemList({ items = [], title, onItemClick }: ItemListProps) {
|
|
189
|
+
const [expanded, setExpanded] = React.useState<string | number | null>(null);
|
|
85
190
|
if (!items.length) {
|
|
86
191
|
return <div className="text-sm text-slate-500 dark:text-slate-400">No items.</div>;
|
|
87
192
|
}
|
|
@@ -146,7 +251,7 @@ const BUILTIN_COMPONENTS = {
|
|
|
146
251
|
);
|
|
147
252
|
},
|
|
148
253
|
|
|
149
|
-
DataTable({ title, subtitle, columns = [], data = [], rows, searchable = true, sortable = true, paginated = true, pageSize = 5 }) {
|
|
254
|
+
DataTable({ title, subtitle, columns = [], data = [], rows, searchable = true, sortable = true, paginated = true, pageSize = 5 }: DataTableProps) {
|
|
150
255
|
const tableData = data.length ? data : (rows ?? []);
|
|
151
256
|
const cols = columns.length ? columns : [
|
|
152
257
|
{ key: "name", label: "Name" },
|
|
@@ -167,7 +272,7 @@ const BUILTIN_COMPONENTS = {
|
|
|
167
272
|
);
|
|
168
273
|
},
|
|
169
274
|
|
|
170
|
-
DataChart({ title, subtitle, chartType = "line", data = [], height = 200 }) {
|
|
275
|
+
DataChart({ title, subtitle, chartType = "line", data = [], height = 200 }: DataChartProps) {
|
|
171
276
|
const series = data.length ? data : Array.from({ length: 12 }, (_, i) => ({ x: i, y: Math.random() * 100 }));
|
|
172
277
|
return (
|
|
173
278
|
<ChartCard
|
|
@@ -177,11 +282,11 @@ const BUILTIN_COMPONENTS = {
|
|
|
177
282
|
height={height}
|
|
178
283
|
chart={
|
|
179
284
|
<D3Chart
|
|
180
|
-
data={series}
|
|
285
|
+
data={series as any}
|
|
181
286
|
responsive
|
|
182
287
|
height={height}
|
|
183
288
|
ariaLabel={title}
|
|
184
|
-
renderChart={(svg, d, dims, opts) => D3ChartTemplates.lineChart(svg, d, dims, opts)}
|
|
289
|
+
renderChart={(svg, d, dims, opts) => D3ChartTemplates.lineChart(svg, d as any, dims, opts)}
|
|
185
290
|
options={{ xKey: "x", yKey: "y", showGrid: true, showAxes: true }}
|
|
186
291
|
/>
|
|
187
292
|
}
|
|
@@ -189,36 +294,36 @@ const BUILTIN_COMPONENTS = {
|
|
|
189
294
|
);
|
|
190
295
|
},
|
|
191
296
|
|
|
192
|
-
MetricCard({ title, label, value, trend, change, changeType, color, icon, description }) {
|
|
297
|
+
MetricCard({ title, label, value, trend, change, changeType, color, icon, description }: MetricCardComponentProps) {
|
|
193
298
|
return (
|
|
194
299
|
<MetricCard
|
|
195
|
-
title={title ?? label}
|
|
300
|
+
title={(title ?? label) as any}
|
|
196
301
|
value={value ?? "—"}
|
|
197
|
-
trend={trend}
|
|
198
|
-
change={change}
|
|
199
|
-
changeType={changeType}
|
|
200
|
-
color={color}
|
|
302
|
+
trend={trend as any}
|
|
303
|
+
change={change as any}
|
|
304
|
+
changeType={changeType as any}
|
|
305
|
+
color={color as any}
|
|
201
306
|
icon={icon}
|
|
202
|
-
|
|
307
|
+
subtitle={description}
|
|
203
308
|
/>
|
|
204
309
|
);
|
|
205
310
|
},
|
|
206
311
|
|
|
207
|
-
StatusCard({ title, subtitle, status, items, layout, showProgress, showTimestamp }) {
|
|
312
|
+
StatusCard({ title, subtitle, status, items, layout, showProgress, showTimestamp }: StatusCardComponentProps) {
|
|
208
313
|
return (
|
|
209
314
|
<StatusCard
|
|
210
315
|
title={title}
|
|
211
316
|
subtitle={subtitle}
|
|
212
317
|
status={status}
|
|
213
318
|
items={items}
|
|
214
|
-
layout={layout}
|
|
319
|
+
layout={layout as any}
|
|
215
320
|
showProgress={showProgress}
|
|
216
321
|
showTimestamp={showTimestamp}
|
|
217
322
|
/>
|
|
218
323
|
);
|
|
219
324
|
},
|
|
220
325
|
|
|
221
|
-
ActionList({ actions = [], title, onAction }) {
|
|
326
|
+
ActionList({ actions = [], title, onAction }: ActionListProps) {
|
|
222
327
|
return (
|
|
223
328
|
<div className="rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-900">
|
|
224
329
|
{title && <div className="mb-3 text-sm font-medium text-slate-900 dark:text-slate-50">{title}</div>}
|
|
@@ -238,7 +343,7 @@ const BUILTIN_COMPONENTS = {
|
|
|
238
343
|
);
|
|
239
344
|
},
|
|
240
345
|
|
|
241
|
-
CalloutCard({ title, message, tone = "neutral" }) {
|
|
346
|
+
CalloutCard({ title, message, tone = "neutral" }: CalloutCardProps) {
|
|
242
347
|
const toneClasses = {
|
|
243
348
|
neutral: "border-slate-200 bg-slate-50 text-slate-700 dark:border-slate-800 dark:bg-slate-950/30 dark:text-slate-200",
|
|
244
349
|
success: "border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900/40 dark:bg-emerald-950/20 dark:text-emerald-200",
|
|
@@ -257,27 +362,27 @@ const BUILTIN_COMPONENTS = {
|
|
|
257
362
|
return <div className="h-px bg-slate-200 dark:bg-slate-800" />;
|
|
258
363
|
},
|
|
259
364
|
|
|
260
|
-
Spacer({ size = "md" }) {
|
|
365
|
+
Spacer({ size = "md" }: SpacerProps) {
|
|
261
366
|
const heights = { sm: "h-2", md: "h-4", lg: "h-6" };
|
|
262
367
|
return <div className={heights[size] ?? heights.md} />;
|
|
263
368
|
}
|
|
264
369
|
};
|
|
265
370
|
|
|
266
|
-
let _registry = { ...BUILTIN_COMPONENTS };
|
|
371
|
+
let _registry: Record<string, React.ComponentType<any>> = { ...BUILTIN_COMPONENTS };
|
|
267
372
|
|
|
268
|
-
export function getComponentRegistry() {
|
|
373
|
+
export function getComponentRegistry(): Record<string, React.ComponentType<any>> {
|
|
269
374
|
return _registry;
|
|
270
375
|
}
|
|
271
376
|
|
|
272
|
-
export function registerComponent(type, Component) {
|
|
377
|
+
export function registerComponent(type: string, Component: React.ComponentType<any>): void {
|
|
273
378
|
_registry = { ..._registry, [type]: Component };
|
|
274
379
|
}
|
|
275
380
|
|
|
276
|
-
export function registerComponents(map) {
|
|
381
|
+
export function registerComponents(map: Record<string, React.ComponentType<any>>): void {
|
|
277
382
|
_registry = { ..._registry, ...map };
|
|
278
383
|
}
|
|
279
384
|
|
|
280
|
-
export function renderSchemaComponent(component, index) {
|
|
385
|
+
export function renderSchemaComponent(component: SchemaComponent, index: number): React.ReactElement {
|
|
281
386
|
const registry = getComponentRegistry();
|
|
282
387
|
const Component = registry[component.type];
|
|
283
388
|
if (!Component) {
|
|
@@ -290,7 +395,7 @@ export function renderSchemaComponent(component, index) {
|
|
|
290
395
|
return <Component key={component.id ?? index} {...(component.props ?? {})} />;
|
|
291
396
|
}
|
|
292
397
|
|
|
293
|
-
export function renderSchema(components = []) {
|
|
398
|
+
export function renderSchema(components: SchemaComponent[] = []): React.ReactElement[] {
|
|
294
399
|
return components.map((c, i) => renderSchemaComponent(c, i));
|
|
295
400
|
}
|
|
296
401
|
|