@schandlergarcia/sf-web-components 1.9.0 → 1.9.2

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.
@@ -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?: unknown[];
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?: unknown[];\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
+ {"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?: unknown[];
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?: unknown[];\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
+ {"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
- export function getComponentRegistry(): {
2
- NarrativeSummary({ summary, title }: {
3
- summary: any;
4
- title: any;
5
- }): import("react/jsx-runtime").JSX.Element;
6
- MetricsStrip({ metrics, title, collapsible, collapsed: initialCollapsed }: {
7
- metrics?: never[] | undefined;
8
- title: any;
9
- collapsible?: boolean | undefined;
10
- collapsed?: boolean | undefined;
11
- }): import("react/jsx-runtime").JSX.Element;
12
- ItemList({ items, title, onItemClick }: {
13
- items?: never[] | undefined;
14
- title: any;
15
- onItemClick: any;
16
- }): import("react/jsx-runtime").JSX.Element;
17
- DataTable({ title, subtitle, columns, data, rows, searchable, sortable, paginated, pageSize }: {
18
- title: any;
19
- subtitle: any;
20
- columns?: never[] | undefined;
21
- data?: never[] | undefined;
22
- rows: any;
23
- searchable?: boolean | undefined;
24
- sortable?: boolean | undefined;
25
- paginated?: boolean | undefined;
26
- pageSize?: number | undefined;
27
- }): import("react/jsx-runtime").JSX.Element;
28
- DataChart({ title, subtitle, chartType, data, height }: {
29
- title: any;
30
- subtitle: any;
31
- chartType?: string | undefined;
32
- data?: never[] | undefined;
33
- height?: number | undefined;
34
- }): import("react/jsx-runtime").JSX.Element;
35
- MetricCard({ title, label, value, trend, change, changeType, color, icon, description }: {
36
- title: any;
37
- label: any;
38
- value: any;
39
- trend: any;
40
- change: any;
41
- changeType: any;
42
- color: any;
43
- icon: any;
44
- description: any;
45
- }): import("react/jsx-runtime").JSX.Element;
46
- StatusCard({ title, subtitle, status, items, layout, showProgress, showTimestamp }: {
47
- title: any;
48
- subtitle: any;
49
- status: any;
50
- items: any;
51
- layout: any;
52
- showProgress: any;
53
- showTimestamp: any;
54
- }): import("react/jsx-runtime").JSX.Element;
55
- ActionList({ actions, title, onAction }: {
56
- actions?: never[] | undefined;
57
- title: any;
58
- onAction: any;
59
- }): import("react/jsx-runtime").JSX.Element;
60
- CalloutCard({ title, message, tone }: {
61
- title: any;
62
- message: any;
63
- tone?: string | undefined;
64
- }): import("react/jsx-runtime").JSX.Element;
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 registerComponent(type: any, Component: any): void;
71
- export function registerComponents(map: any): void;
72
- export function renderSchemaComponent(component: any, index: any): import("react/jsx-runtime").JSX.Element;
73
- export function renderSchema(components?: any[]): import("react/jsx-runtime").JSX.Element[];
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: t, title: a }) {
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
- t
24
+ r
25
25
  ] });
26
26
  },
27
- MetricsStrip({ metrics: t = [], title: a, collapsible: d = !1, collapsed: l = !1 }) {
28
- const [o, s] = b.useState(l), n = t.length ? t : [
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((r) => `${r.label} ${r.value}`).join(" · ")
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((r) => /* @__PURE__ */ i("div", { className: "min-w-[80px]", children: [
62
- /* @__PURE__ */ e("div", { className: "text-xs text-slate-400 dark:text-slate-500", children: r.label }),
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: r.value }),
65
- r.trend && /* @__PURE__ */ e("span", { className: `text-xs ${String(r.trend).startsWith?.("+") || r.trend > 0 ? "text-red-500" : "text-emerald-500"}`, children: typeof r.trend == "number" && r.trend > 0 ? `+${r.trend}` : r.trend })
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
- ] }, r.label)) })
67
+ ] }, t.label)) })
68
68
  ] });
69
69
  },
70
- ItemList({ items: t = [], title: a, onItemClick: d }) {
70
+ ItemList({ items: r = [], title: a, onItemClick: d }) {
71
71
  const [l, o] = b.useState(null);
72
- return t.length ? /* @__PURE__ */ i("div", { className: "space-y-2", children: [
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
- t.length,
76
+ r.length,
77
77
  " items"
78
78
  ] })
79
79
  ] }),
80
- /* @__PURE__ */ e("div", { className: "space-y-1.5", children: t.map((s, n) => /* @__PURE__ */ i("div", { className: "rounded-xl border border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900", 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((r, m) => /* @__PURE__ */ e(
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 r == "string" ? r : r.label
103
+ children: typeof t == "string" ? t : t.label
104
104
  },
105
- typeof r == "string" ? r : r.label
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: t, subtitle: a, columns: d = [], data: l = [], rows: o, searchable: s = !0, sortable: n = !0, paginated: r = !0, pageSize: m = 5 }) {
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: t ?? "Data",
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: r,
125
+ paginated: t,
126
126
  pageSize: m
127
127
  }
128
128
  );
129
129
  },
130
- DataChart({ title: t, subtitle: a, chartType: d = "line", data: l = [], height: o = 200 }) {
131
- const s = l.length ? l : Array.from({ length: 12 }, (n, r) => ({ x: r, y: Math.random() * 100 }));
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: t ?? "Trend",
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: t,
146
- renderChart: (n, r, m, c) => N.lineChart(n, r, m, c),
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: t, label: a, value: d, trend: l, change: o, changeType: s, color: n, icon: r, description: m }) {
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: t ?? a,
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: r,
164
- description: m
163
+ icon: t,
164
+ subtitle: m
165
165
  }
166
166
  );
167
167
  },
168
- StatusCard({ title: t, subtitle: a, status: d, items: l, layout: o, showProgress: s, showTimestamp: n }) {
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: t,
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: t = [], title: a, onAction: d }) {
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: t.map((l, o) => /* @__PURE__ */ e(
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: t, message: a, tone: d = "neutral" }) {
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
- t && /* @__PURE__ */ e("div", { className: "mb-1 text-sm font-semibold", children: t }),
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: t = "md" }) {
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[t] ?? a.md });
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 V(t, a) {
222
- const l = w()[t.type];
223
- return l ? /* @__PURE__ */ e(l, { ...t.props ?? {} }, t.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: [
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
- t.type
225
+ r.type
226
226
  ] }, a);
227
227
  }
228
228
  export {
229
229
  w as getComponentRegistry,
230
- V as renderSchemaComponent
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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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Type definitions for Agentforce Conversation Client
3
+ */
4
+ export interface ResolvedEmbedOptions {
5
+ salesforceOrigin?: string;
6
+ frontdoorUrl?: string;
7
+ }
8
+ export interface RenderingConfig {
9
+ mode?: 'inline' | 'modal' | 'sidebar';
10
+ theme?: 'light' | 'dark' | 'auto';
11
+ width?: string | number;
12
+ height?: string | number;
13
+ }
14
+ export interface AgentforceClientConfig {
15
+ agentId?: string;
16
+ devName?: string;
17
+ renderingConfig?: RenderingConfig;
18
+ locale?: string;
19
+ [key: string]: any;
20
+ }
21
+ export interface AgentforceConversationClientProps {
22
+ agentforceClientConfig?: AgentforceClientConfig;
23
+ salesforceOrigin?: string;
24
+ frontdoorUrl?: string;
25
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schandlergarcia/sf-web-components",
3
- "version": "1.9.0",
3
+ "version": "1.9.2",
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",
@@ -30,6 +30,7 @@
30
30
  "src/templates",
31
31
  "src/components",
32
32
  "src/lib",
33
+ "src/types",
33
34
  "README.md",
34
35
  ".a4drules"
35
36
  ],
@@ -64,7 +65,7 @@
64
65
  "world-atlas": "^2.0.0"
65
66
  },
66
67
  "dependencies": {
67
- "@schandlergarcia/sf-web-components": "^1.1.1",
68
+ "@schandlergarcia/sf-web-components": "^1.9.0",
68
69
  "class-variance-authority": "^0.7.1",
69
70
  "clsx": "^2.1.1",
70
71
  "glob": "^11.0.0",
@@ -82,6 +82,15 @@ if (fs.existsSync(sourceLibDir)) {
82
82
  console.log(` ✓ Copied ${libFilesCopied} lib files\n`);
83
83
  }
84
84
 
85
+ // Copy types directory
86
+ const sourceTypesDir = path.join(packageRoot, 'src/types');
87
+ const targetTypesDir = path.join(cwd, 'src/types');
88
+
89
+ if (fs.existsSync(sourceTypesDir)) {
90
+ const typesFilesCopied = copyDirectoryRecursive(sourceTypesDir, targetTypesDir);
91
+ console.log(` ✓ Copied ${typesFilesCopied} type files\n`);
92
+ }
93
+
85
94
  // Copy workspace directory (ComponentRegistry, etc.)
86
95
  const sourceWorkspaceDir = path.join(packageRoot, 'src/components/workspace');
87
96
  const targetWorkspaceDir = path.join(cwd, 'src/components/workspace');
@@ -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?: unknown[];
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?: unknown[];
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
- description={description}
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
 
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ import { RocketLaunchIcon } from "@heroicons/react/24/outline";
3
+ import { EmptyState } from "@/components/library";
4
+
5
+ export default function BlankDashboard() {
6
+ return (
7
+ <div className="flex min-h-screen items-center justify-center bg-slate-50 dark:bg-slate-950 transition-colors">
8
+ <EmptyState
9
+ size="lg"
10
+ icon={<RocketLaunchIcon className="h-14 w-14" />}
11
+ heading="Bespoke App Template"
12
+ body="Component library loaded and ready to go."
13
+ />
14
+ </div>
15
+ );
16
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Type definitions for Agentforce Conversation Client
3
+ */
4
+
5
+ export interface ResolvedEmbedOptions {
6
+ salesforceOrigin?: string;
7
+ frontdoorUrl?: string;
8
+ }
9
+
10
+ export interface RenderingConfig {
11
+ mode?: 'inline' | 'modal' | 'sidebar';
12
+ theme?: 'light' | 'dark' | 'auto';
13
+ width?: string | number;
14
+ height?: string | number;
15
+ }
16
+
17
+ export interface AgentforceClientConfig {
18
+ agentId?: string;
19
+ devName?: string;
20
+ renderingConfig?: RenderingConfig;
21
+ locale?: string;
22
+ [key: string]: any;
23
+ }
24
+
25
+ export interface AgentforceConversationClientProps {
26
+ agentforceClientConfig?: AgentforceClientConfig;
27
+ salesforceOrigin?: string;
28
+ frontdoorUrl?: string;
29
+ }