@schandlergarcia/sf-web-components 1.8.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.
Files changed (82) hide show
  1. package/dist/components/library/cards/SemanticTableCard.d.ts +1 -1
  2. package/dist/components/library/chat/ChatBar.d.ts +14 -11
  3. package/dist/components/library/chat/ChatBar.js +2 -3
  4. package/dist/components/library/chat/ChatBar.js.map +1 -1
  5. package/dist/components/library/chat/ChatInput.d.ts +9 -8
  6. package/dist/components/library/chat/ChatInput.js.map +1 -1
  7. package/dist/components/library/chat/ChatMessage.d.ts +18 -4
  8. package/dist/components/library/chat/ChatMessage.js.map +1 -1
  9. package/dist/components/library/chat/ChatMessageList.d.ts +11 -8
  10. package/dist/components/library/chat/ChatMessageList.js.map +1 -1
  11. package/dist/components/library/chat/ChatPanel.d.ts +16 -12
  12. package/dist/components/library/chat/ChatPanel.js +8 -9
  13. package/dist/components/library/chat/ChatPanel.js.map +1 -1
  14. package/dist/components/library/chat/ChatSuggestions.d.ts +5 -4
  15. package/dist/components/library/chat/ChatSuggestions.js +2 -3
  16. package/dist/components/library/chat/ChatSuggestions.js.map +1 -1
  17. package/dist/components/library/chat/ChatToolCall.d.ts +11 -3
  18. package/dist/components/library/chat/ChatToolCall.js.map +1 -1
  19. package/dist/components/library/chat/ChatTypingIndicator.d.ts +4 -3
  20. package/dist/components/library/chat/ChatTypingIndicator.js +2 -3
  21. package/dist/components/library/chat/ChatTypingIndicator.js.map +1 -1
  22. package/dist/components/library/chat/ChatWelcome.d.ts +9 -7
  23. package/dist/components/library/chat/ChatWelcome.js +6 -7
  24. package/dist/components/library/chat/ChatWelcome.js.map +1 -1
  25. package/dist/components/library/chat/index.d.ts +10 -0
  26. package/dist/components/library/chat/useChatState.d.ts +37 -11
  27. package/dist/components/library/chat/useChatState.js +63 -46
  28. package/dist/components/library/chat/useChatState.js.map +1 -1
  29. package/dist/components/library/data/DataModeProvider.d.ts +15 -11
  30. package/dist/components/library/data/DataModeProvider.js +1 -1
  31. package/dist/components/library/data/DataModeProvider.js.map +1 -1
  32. package/dist/components/library/data/DataModeToggle.d.ts +4 -3
  33. package/dist/components/library/data/DataModeToggle.js +4 -5
  34. package/dist/components/library/data/DataModeToggle.js.map +1 -1
  35. package/dist/components/library/data/chartDataProvider.d.ts +41 -3
  36. package/dist/components/library/data/filterUtils.d.ts +38 -9
  37. package/dist/components/library/data/filterUtils.js.map +1 -1
  38. package/dist/components/library/data/useDataSource.d.ts +6 -4
  39. package/dist/components/library/data/useDataSource.js.map +1 -1
  40. package/dist/components/library/data/usePageFilters.d.ts +31 -5
  41. package/dist/components/library/data/usePageFilters.js +6 -2
  42. package/dist/components/library/data/usePageFilters.js.map +1 -1
  43. package/dist/components/library/index.d.ts +92 -73
  44. package/dist/components/library/index.js +25 -25
  45. package/dist/components/library/index.js.map +1 -1
  46. package/dist/components/library/skeletons/CardSkeleton.d.ts +5 -4
  47. package/dist/components/library/skeletons/CardSkeleton.js +2 -3
  48. package/dist/components/library/skeletons/CardSkeleton.js.map +1 -1
  49. package/dist/components/library/theme/AppThemeProvider.d.ts +13 -50
  50. package/dist/components/library/theme/AppThemeProvider.js.map +1 -1
  51. package/dist/components/library/theme/tokens.d.ts +45 -44
  52. package/dist/components/library/theme/tokens.js.map +1 -1
  53. package/dist/components/workspace/ComponentRegistry.d.ts +116 -140
  54. package/dist/components/workspace/ComponentRegistry.js +43 -43
  55. package/dist/components/workspace/ComponentRegistry.js.map +1 -1
  56. package/package.json +2 -2
  57. package/src/components/library/cards/SemanticMetricCard.tsx +1 -1
  58. package/src/components/library/cards/SemanticTableCard.tsx +3 -3
  59. package/src/components/library/chat/{ChatBar.jsx → ChatBar.tsx} +19 -8
  60. package/src/components/library/chat/{ChatInput.jsx → ChatInput.tsx} +13 -11
  61. package/src/components/library/chat/{ChatMessage.jsx → ChatMessage.tsx} +23 -10
  62. package/src/components/library/chat/{ChatMessageList.jsx → ChatMessageList.tsx} +13 -11
  63. package/src/components/library/chat/{ChatPanel.jsx → ChatPanel.tsx} +16 -13
  64. package/src/components/library/chat/{ChatSuggestions.jsx → ChatSuggestions.tsx} +6 -5
  65. package/src/components/library/chat/{ChatToolCall.jsx → ChatToolCall.tsx} +14 -4
  66. package/src/components/library/chat/{ChatTypingIndicator.jsx → ChatTypingIndicator.tsx} +5 -2
  67. package/src/components/library/chat/{ChatWelcome.jsx → ChatWelcome.tsx} +9 -7
  68. package/src/components/library/chat/index.tsx +26 -0
  69. package/src/components/library/chat/useChatState.tsx +182 -0
  70. package/src/components/library/data/{DataModeProvider.jsx → DataModeProvider.tsx} +25 -8
  71. package/src/components/library/data/{DataModeToggle.jsx → DataModeToggle.tsx} +5 -2
  72. package/src/components/library/data/{chartDataProvider.jsx → chartDataProvider.tsx} +49 -5
  73. package/src/components/library/data/{filterUtils.jsx → filterUtils.tsx} +58 -12
  74. package/src/components/library/data/{useDataSource.jsx → useDataSource.tsx} +9 -2
  75. package/src/components/library/data/{usePageFilters.jsx → usePageFilters.tsx} +49 -9
  76. package/src/components/library/{index.jsx → index.ts} +14 -14
  77. package/src/components/library/skeletons/{CardSkeleton.jsx → CardSkeleton.tsx} +5 -4
  78. package/src/components/library/theme/{AppThemeProvider.jsx → AppThemeProvider.tsx} +20 -7
  79. package/src/components/library/theme/{tokens.jsx → tokens.tsx} +37 -3
  80. package/src/components/workspace/{ComponentRegistry.jsx → ComponentRegistry.tsx} +137 -32
  81. package/src/components/library/chat/index.jsx +0 -10
  82. package/src/components/library/chat/useChatState.jsx +0 -130
@@ -1,7 +1,7 @@
1
1
  import { TableCardProps, TableColumn } from "./TableCard";
2
2
  export interface SemanticTableCardProps extends Omit<TableCardProps, "data" | "columns"> {
3
3
  semanticId: string;
4
- dataOverride?: unknown[];
4
+ dataOverride?: Record<string, unknown>[];
5
5
  columnsOverride?: TableColumn[];
6
6
  compact?: boolean;
7
7
  striped?: boolean;
@@ -1,3 +1,16 @@
1
+ import React from "react";
2
+ import { UseChatStateOptions, ChatMessage } from "./useChatState";
3
+ import { ChatMessageData } from "./ChatMessage";
4
+ export interface ChatBarProps {
5
+ onSend?: UseChatStateOptions["onSend"];
6
+ suggestions?: string[];
7
+ placeholder?: string;
8
+ title?: string;
9
+ initialMessages?: UseChatStateOptions["initialMessages"];
10
+ className?: string;
11
+ renderAvatar?: (message: ChatMessageData) => React.ReactNode;
12
+ onOpenInTab?: (messages: ChatMessage[]) => void;
13
+ }
1
14
  /**
2
15
  * Command-palette style AI chat bar.
3
16
  *
@@ -8,14 +21,4 @@
8
21
  * Activate: click the bar, press ⌘K / Ctrl+K, or click a suggestion chip.
9
22
  * Dismiss: Escape or click the backdrop.
10
23
  */
11
- export default function ChatBar({ onSend, suggestions, placeholder, title, initialMessages, className, panelHeight, renderAvatar, onOpenInTab, }: {
12
- onSend: any;
13
- suggestions?: never[] | undefined;
14
- placeholder?: string | undefined;
15
- title?: string | undefined;
16
- initialMessages?: never[] | undefined;
17
- className?: string | undefined;
18
- panelHeight: any;
19
- renderAvatar: any;
20
- onOpenInTab: any;
21
- }): import("react/jsx-runtime").JSX.Element;
24
+ export default function ChatBar({ onSend, suggestions, placeholder, title, initialMessages, className, renderAvatar, onOpenInTab, }: ChatBarProps): import("react/jsx-runtime").JSX.Element;
@@ -20,14 +20,13 @@ const z = {
20
20
  },
21
21
  exit: { opacity: 0, y: 10, scale: 0.97, transition: { duration: 0.12 } }
22
22
  };
23
- function Y({
23
+ function W({
24
24
  onSend: p,
25
25
  suggestions: c = [],
26
26
  placeholder: h = "Ask a question…",
27
27
  title: g = "AI Assistant",
28
28
  initialMessages: k = [],
29
29
  className: v = "",
30
- panelHeight: H,
31
30
  renderAvatar: y,
32
31
  onOpenInTab: u
33
32
  }) {
@@ -189,6 +188,6 @@ function Y({
189
188
  ] });
190
189
  }
191
190
  export {
192
- Y as default
191
+ W as default
193
192
  };
194
193
  //# sourceMappingURL=ChatBar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatBar.js","sources":["../../../../src/components/library/chat/ChatBar.jsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport {\n SparklesIcon,\n XMarkIcon,\n TrashIcon,\n ArrowTopRightOnSquareIcon,\n} from \"@heroicons/react/24/outline\";\nimport ChatMessageList from \"./ChatMessageList\";\nimport ChatInput from \"./ChatInput\";\nimport useChatState from \"./useChatState\";\n\nconst BACKDROP_VARIANTS = {\n hidden: { opacity: 0 },\n visible: { opacity: 1, transition: { duration: 0.15 } },\n exit: { opacity: 0, transition: { duration: 0.12 } },\n};\n\nconst PANEL_VARIANTS = {\n hidden: { opacity: 0, y: 20, scale: 0.97 },\n visible: {\n opacity: 1,\n y: 0,\n scale: 1,\n transition: { type: \"spring\", damping: 28, stiffness: 380 },\n },\n exit: { opacity: 0, y: 10, scale: 0.97, transition: { duration: 0.12 } },\n};\n\n/**\n * Command-palette style AI chat bar.\n *\n * Collapsed: a slim, clickable input strip with sparkle icon and ⌘K hint.\n * Expanded: a centered floating overlay (portal) with backdrop, full chat,\n * suggestions, and message history. No layout shift.\n *\n * Activate: click the bar, press ⌘K / Ctrl+K, or click a suggestion chip.\n * Dismiss: Escape or click the backdrop.\n */\nexport default function ChatBar({\n onSend,\n suggestions = [],\n placeholder = \"Ask a question\\u2026\",\n title = \"AI Assistant\",\n initialMessages = [],\n className = \"\",\n panelHeight,\n renderAvatar,\n onOpenInTab,\n}) {\n const [open, setOpen] = useState(false);\n const [portalVisible, setPortalVisible] = useState(false);\n const panelRef = useRef(null);\n const chat = useChatState({ initialMessages, onSend });\n const isEmpty = chat.messages.length === 0;\n\n const close = useCallback(() => setOpen(false), []);\n\n useEffect(() => {\n if (open) setPortalVisible(true);\n }, [open]);\n\n useEffect(() => {\n function onKey(e) {\n if ((e.metaKey || e.ctrlKey) && e.key === \"k\") {\n e.preventDefault();\n setOpen((prev) => !prev);\n }\n if (e.key === \"Escape\" && open) close();\n }\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, close]);\n\n useEffect(() => {\n if (open) document.body.style.overflow = \"hidden\";\n else document.body.style.overflow = \"\";\n return () => { document.body.style.overflow = \"\"; };\n }, [open]);\n\n function handleSend(content) {\n if (!open) setOpen(true);\n chat.sendMessage(content);\n }\n\n const [shortcutLabel, setShortcutLabel] = useState(\"⌘K\");\n useEffect(() => {\n setShortcutLabel(/Mac|iPhone|iPad/.test(navigator.userAgent) ? \"⌘K\" : \"Ctrl K\");\n }, []);\n\n const overlay =\n typeof document !== \"undefined\" && portalVisible\n ? createPortal(\n <AnimatePresence onExitComplete={() => setPortalVisible(false)}>\n {open && (\n <>\n {/* Backdrop */}\n <motion.div\n variants={BACKDROP_VARIANTS}\n initial=\"hidden\"\n animate=\"visible\"\n exit=\"exit\"\n className=\"fixed inset-0 z-50 bg-black/30 backdrop-blur-sm\"\n onClick={close}\n aria-hidden=\"true\"\n />\n\n {/* Centered panel */}\n <motion.div\n ref={panelRef}\n variants={PANEL_VARIANTS}\n initial=\"hidden\"\n animate=\"visible\"\n exit=\"exit\"\n className=\"fixed inset-x-0 top-[10vh] z-50 mx-auto flex w-full max-w-4xl flex-col overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-2xl dark:border-slate-700 dark:bg-slate-900\"\n style={{ maxHeight: \"75vh\" }}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-slate-100 px-4 py-2.5 dark:border-slate-800\">\n <div className=\"flex items-center gap-2\">\n <SparklesIcon className=\"h-4 w-4 text-brand-500\" />\n <h3 className=\"text-sm font-semibold text-slate-900 dark:text-slate-50\">\n {title}\n </h3>\n </div>\n <div className=\"flex items-center gap-1\">\n {onOpenInTab ? (\n <button\n type=\"button\"\n onClick={() => {\n setOpen(false);\n setPortalVisible(false);\n document.body.style.overflow = \"\";\n onOpenInTab(chat.messages);\n }}\n className=\"rounded p-1 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:text-slate-500 dark:hover:bg-slate-800 dark:hover:text-slate-300\"\n aria-label=\"Open in new tab\"\n title=\"Open in new tab\"\n >\n <ArrowTopRightOnSquareIcon className=\"h-4 w-4\" />\n </button>\n ) : null}\n {chat.messages.length > 0 ? (\n <button\n type=\"button\"\n onClick={chat.clearMessages}\n className=\"rounded p-1 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:text-slate-500 dark:hover:bg-slate-800 dark:hover:text-slate-300\"\n aria-label=\"Clear chat\"\n >\n <TrashIcon className=\"h-4 w-4\" />\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={close}\n className=\"rounded p-1 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:text-slate-500 dark:hover:bg-slate-800 dark:hover:text-slate-300\"\n aria-label=\"Close\"\n >\n <XMarkIcon className=\"h-4 w-4\" />\n </button>\n <kbd className=\"ml-1 hidden rounded border border-slate-200 bg-slate-50 px-1.5 py-0.5 text-[10px] font-medium text-slate-400 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-500 sm:inline-block\">\n esc\n </kbd>\n </div>\n </div>\n\n {/* Body — messages or empty state */}\n <div className=\"min-h-0 flex-1\">\n {isEmpty ? (\n <div className=\"flex h-full min-h-[200px] flex-col items-center justify-center gap-4 px-6 py-8\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-full bg-brand-50 dark:bg-brand-950/30\">\n <SparklesIcon className=\"h-5 w-5 text-brand-500\" />\n </div>\n <p className=\"text-sm text-slate-500 dark:text-slate-400\">\n Ask me anything about your data.\n </p>\n {suggestions.length > 0 ? (\n <div className=\"flex flex-wrap justify-center gap-2\">\n {suggestions.map((text) => (\n <button\n key={text}\n type=\"button\"\n onClick={() => handleSend(text)}\n className=\"inline-flex items-center gap-1.5 rounded-full border border-slate-200 bg-white px-3 py-1.5 text-xs font-medium text-slate-600 shadow-sm transition hover:border-brand-300 hover:bg-brand-50 hover:text-brand-700 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-300 dark:hover:border-brand-700 dark:hover:bg-brand-950/30 dark:hover:text-brand-300\"\n >\n <SparklesIcon\n className=\"h-3 w-3\"\n aria-hidden=\"true\"\n />\n {text}\n </button>\n ))}\n </div>\n ) : null}\n </div>\n ) : (\n <ChatMessageList\n messages={chat.messages}\n isLoading={chat.isLoading}\n isStreaming={chat.isStreaming}\n suggestions={suggestions}\n onSuggestion={(text) => chat.sendMessage(text)}\n renderAvatar={renderAvatar}\n />\n )}\n </div>\n\n {/* Input */}\n <div className=\"border-t border-slate-100 p-3 dark:border-slate-800\">\n <ChatInput\n onSend={(content) => chat.sendMessage(content)}\n disabled={chat.isLoading}\n isLoading={chat.isLoading}\n placeholder={placeholder}\n />\n </div>\n </motion.div>\n </>\n )}\n </AnimatePresence>,\n document.body\n )\n : null;\n\n return (\n <>\n {overlay}\n\n {/* Trigger bar */}\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className={[\n \"group flex w-full items-center gap-3 rounded-xl border border-slate-200 bg-white px-4 py-2.5 text-left shadow-sm transition-all hover:border-brand-300 hover:shadow-md focus:outline-none focus:ring-2 focus:ring-brand-500/20 dark:border-slate-800 dark:bg-slate-900 dark:hover:border-brand-700\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n <SparklesIcon className=\"h-5 w-5 shrink-0 text-brand-500\" />\n <span className=\"flex-1 text-sm text-slate-400 dark:text-slate-500\">\n {placeholder}\n </span>\n {chat.messages.length > 0 ? (\n <span className=\"rounded-full bg-brand-50 px-2 py-0.5 text-xs font-medium text-brand-600 dark:bg-brand-950/30 dark:text-brand-400\">\n {chat.messages.length} msgs\n </span>\n ) : null}\n <kbd className=\"hidden rounded border border-slate-200 bg-slate-50 px-1.5 py-0.5 text-[10px] font-medium text-slate-400 group-hover:border-brand-200 group-hover:text-brand-500 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-500 sm:inline-block\">\n {shortcutLabel}\n </kbd>\n </button>\n </>\n );\n}\n"],"names":["BACKDROP_VARIANTS","PANEL_VARIANTS","ChatBar","onSend","suggestions","placeholder","title","initialMessages","className","panelHeight","renderAvatar","onOpenInTab","open","setOpen","useState","portalVisible","setPortalVisible","panelRef","useRef","chat","useChatState","isEmpty","close","useCallback","useEffect","onKey","e","prev","handleSend","content","shortcutLabel","setShortcutLabel","overlay","createPortal","jsx","AnimatePresence","jsxs","Fragment","motion","SparklesIcon","ArrowTopRightOnSquareIcon","TrashIcon","XMarkIcon","text","ChatMessageList","ChatInput"],"mappings":"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"}
1
+ {"version":3,"file":"ChatBar.js","sources":["../../../../src/components/library/chat/ChatBar.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport {\n SparklesIcon,\n XMarkIcon,\n TrashIcon,\n ArrowTopRightOnSquareIcon,\n} from \"@heroicons/react/24/outline\";\nimport ChatMessageList from \"./ChatMessageList\";\nimport ChatInput from \"./ChatInput\";\nimport useChatState, { UseChatStateOptions, ChatMessage } from \"./useChatState\";\nimport { ChatMessageData } from \"./ChatMessage\";\n\nconst BACKDROP_VARIANTS = {\n hidden: { opacity: 0 },\n visible: { opacity: 1, transition: { duration: 0.15 } },\n exit: { opacity: 0, transition: { duration: 0.12 } },\n};\n\nconst PANEL_VARIANTS = {\n hidden: { opacity: 0, y: 20, scale: 0.97 },\n visible: {\n opacity: 1,\n y: 0,\n scale: 1,\n transition: { type: \"spring\" as const, damping: 28, stiffness: 380 },\n },\n exit: { opacity: 0, y: 10, scale: 0.97, transition: { duration: 0.12 } },\n};\n\nexport interface ChatBarProps {\n onSend?: UseChatStateOptions[\"onSend\"];\n suggestions?: string[];\n placeholder?: string;\n title?: string;\n initialMessages?: UseChatStateOptions[\"initialMessages\"];\n className?: string;\n renderAvatar?: (message: ChatMessageData) => React.ReactNode;\n onOpenInTab?: (messages: ChatMessage[]) => void;\n}\n\n/**\n * Command-palette style AI chat bar.\n *\n * Collapsed: a slim, clickable input strip with sparkle icon and ⌘K hint.\n * Expanded: a centered floating overlay (portal) with backdrop, full chat,\n * suggestions, and message history. No layout shift.\n *\n * Activate: click the bar, press ⌘K / Ctrl+K, or click a suggestion chip.\n * Dismiss: Escape or click the backdrop.\n */\nexport default function ChatBar({\n onSend,\n suggestions = [],\n placeholder = \"Ask a question…\",\n title = \"AI Assistant\",\n initialMessages = [],\n className = \"\",\n renderAvatar,\n onOpenInTab,\n}: ChatBarProps) {\n const [open, setOpen] = useState(false);\n const [portalVisible, setPortalVisible] = useState(false);\n const panelRef = useRef<HTMLDivElement>(null);\n const chat = useChatState({ initialMessages, onSend });\n const isEmpty = chat.messages.length === 0;\n\n const close = useCallback(() => setOpen(false), []);\n\n useEffect(() => {\n if (open) setPortalVisible(true);\n }, [open]);\n\n useEffect(() => {\n function onKey(e: KeyboardEvent) {\n if ((e.metaKey || e.ctrlKey) && e.key === \"k\") {\n e.preventDefault();\n setOpen((prev) => !prev);\n }\n if (e.key === \"Escape\" && open) close();\n }\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, close]);\n\n useEffect(() => {\n if (open) document.body.style.overflow = \"hidden\";\n else document.body.style.overflow = \"\";\n return () => { document.body.style.overflow = \"\"; };\n }, [open]);\n\n function handleSend(content: string) {\n if (!open) setOpen(true);\n chat.sendMessage(content);\n }\n\n const [shortcutLabel, setShortcutLabel] = useState(\"⌘K\");\n useEffect(() => {\n setShortcutLabel(/Mac|iPhone|iPad/.test(navigator.userAgent) ? \"⌘K\" : \"Ctrl K\");\n }, []);\n\n const overlay =\n typeof document !== \"undefined\" && portalVisible\n ? createPortal(\n <AnimatePresence onExitComplete={() => setPortalVisible(false)}>\n {open && (\n <>\n {/* Backdrop */}\n <motion.div\n variants={BACKDROP_VARIANTS}\n initial=\"hidden\"\n animate=\"visible\"\n exit=\"exit\"\n className=\"fixed inset-0 z-50 bg-black/30 backdrop-blur-sm\"\n onClick={close}\n aria-hidden=\"true\"\n />\n\n {/* Centered panel */}\n <motion.div\n ref={panelRef}\n variants={PANEL_VARIANTS}\n initial=\"hidden\"\n animate=\"visible\"\n exit=\"exit\"\n className=\"fixed inset-x-0 top-[10vh] z-50 mx-auto flex w-full max-w-4xl flex-col overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-2xl dark:border-slate-700 dark:bg-slate-900\"\n style={{ maxHeight: \"75vh\" }}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-slate-100 px-4 py-2.5 dark:border-slate-800\">\n <div className=\"flex items-center gap-2\">\n <SparklesIcon className=\"h-4 w-4 text-brand-500\" />\n <h3 className=\"text-sm font-semibold text-slate-900 dark:text-slate-50\">\n {title}\n </h3>\n </div>\n <div className=\"flex items-center gap-1\">\n {onOpenInTab ? (\n <button\n type=\"button\"\n onClick={() => {\n setOpen(false);\n setPortalVisible(false);\n document.body.style.overflow = \"\";\n onOpenInTab(chat.messages);\n }}\n className=\"rounded p-1 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:text-slate-500 dark:hover:bg-slate-800 dark:hover:text-slate-300\"\n aria-label=\"Open in new tab\"\n title=\"Open in new tab\"\n >\n <ArrowTopRightOnSquareIcon className=\"h-4 w-4\" />\n </button>\n ) : null}\n {chat.messages.length > 0 ? (\n <button\n type=\"button\"\n onClick={chat.clearMessages}\n className=\"rounded p-1 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:text-slate-500 dark:hover:bg-slate-800 dark:hover:text-slate-300\"\n aria-label=\"Clear chat\"\n >\n <TrashIcon className=\"h-4 w-4\" />\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={close}\n className=\"rounded p-1 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:text-slate-500 dark:hover:bg-slate-800 dark:hover:text-slate-300\"\n aria-label=\"Close\"\n >\n <XMarkIcon className=\"h-4 w-4\" />\n </button>\n <kbd className=\"ml-1 hidden rounded border border-slate-200 bg-slate-50 px-1.5 py-0.5 text-[10px] font-medium text-slate-400 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-500 sm:inline-block\">\n esc\n </kbd>\n </div>\n </div>\n\n {/* Body — messages or empty state */}\n <div className=\"min-h-0 flex-1\">\n {isEmpty ? (\n <div className=\"flex h-full min-h-[200px] flex-col items-center justify-center gap-4 px-6 py-8\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-full bg-brand-50 dark:bg-brand-950/30\">\n <SparklesIcon className=\"h-5 w-5 text-brand-500\" />\n </div>\n <p className=\"text-sm text-slate-500 dark:text-slate-400\">\n Ask me anything about your data.\n </p>\n {suggestions.length > 0 ? (\n <div className=\"flex flex-wrap justify-center gap-2\">\n {suggestions.map((text) => (\n <button\n key={text}\n type=\"button\"\n onClick={() => handleSend(text)}\n className=\"inline-flex items-center gap-1.5 rounded-full border border-slate-200 bg-white px-3 py-1.5 text-xs font-medium text-slate-600 shadow-sm transition hover:border-brand-300 hover:bg-brand-50 hover:text-brand-700 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-300 dark:hover:border-brand-700 dark:hover:bg-brand-950/30 dark:hover:text-brand-300\"\n >\n <SparklesIcon\n className=\"h-3 w-3\"\n aria-hidden=\"true\"\n />\n {text}\n </button>\n ))}\n </div>\n ) : null}\n </div>\n ) : (\n <ChatMessageList\n messages={chat.messages}\n isLoading={chat.isLoading}\n isStreaming={chat.isStreaming}\n suggestions={suggestions}\n onSuggestion={(text) => chat.sendMessage(text)}\n renderAvatar={renderAvatar}\n />\n )}\n </div>\n\n {/* Input */}\n <div className=\"border-t border-slate-100 p-3 dark:border-slate-800\">\n <ChatInput\n onSend={(content) => chat.sendMessage(content)}\n disabled={chat.isLoading}\n isLoading={chat.isLoading}\n placeholder={placeholder}\n />\n </div>\n </motion.div>\n </>\n )}\n </AnimatePresence>,\n document.body\n )\n : null;\n\n return (\n <>\n {overlay}\n\n {/* Trigger bar */}\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className={[\n \"group flex w-full items-center gap-3 rounded-xl border border-slate-200 bg-white px-4 py-2.5 text-left shadow-sm transition-all hover:border-brand-300 hover:shadow-md focus:outline-none focus:ring-2 focus:ring-brand-500/20 dark:border-slate-800 dark:bg-slate-900 dark:hover:border-brand-700\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n <SparklesIcon className=\"h-5 w-5 shrink-0 text-brand-500\" />\n <span className=\"flex-1 text-sm text-slate-400 dark:text-slate-500\">\n {placeholder}\n </span>\n {chat.messages.length > 0 ? (\n <span className=\"rounded-full bg-brand-50 px-2 py-0.5 text-xs font-medium text-brand-600 dark:bg-brand-950/30 dark:text-brand-400\">\n {chat.messages.length} msgs\n </span>\n ) : null}\n <kbd className=\"hidden rounded border border-slate-200 bg-slate-50 px-1.5 py-0.5 text-[10px] font-medium text-slate-400 group-hover:border-brand-200 group-hover:text-brand-500 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-500 sm:inline-block\">\n {shortcutLabel}\n </kbd>\n </button>\n </>\n );\n}\n"],"names":["BACKDROP_VARIANTS","PANEL_VARIANTS","ChatBar","onSend","suggestions","placeholder","title","initialMessages","className","renderAvatar","onOpenInTab","open","setOpen","useState","portalVisible","setPortalVisible","panelRef","useRef","chat","useChatState","isEmpty","close","useCallback","useEffect","onKey","e","prev","handleSend","content","shortcutLabel","setShortcutLabel","overlay","createPortal","jsx","AnimatePresence","jsxs","Fragment","motion","SparklesIcon","ArrowTopRightOnSquareIcon","TrashIcon","XMarkIcon","text","ChatMessageList","ChatInput"],"mappings":"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"}
@@ -1,12 +1,13 @@
1
+ export interface ChatInputProps {
2
+ onSend?: (content: string) => void;
3
+ disabled?: boolean;
4
+ isLoading?: boolean;
5
+ onStop?: () => void;
6
+ placeholder?: string;
7
+ maxRows?: number;
8
+ }
1
9
  /**
2
10
  * Chat input with auto-resize textarea, Send button, and keyboard shortcuts.
3
11
  * Enter sends, Shift+Enter inserts newline.
4
- *
5
- * @param {Function} onSend — (content: string) => void
6
- * @param {boolean} disabled — disable input while agent is processing
7
- * @param {boolean} isLoading — show stop button instead of send
8
- * @param {Function} onStop — optional: called when stop is clicked
9
- * @param {string} placeholder
10
- * @param {number} maxRows — max visible rows before scroll (default 6)
11
12
  */
12
- export default function ChatInput({ onSend, disabled, isLoading, onStop, placeholder, maxRows, }: Function): import("react/jsx-runtime").JSX.Element;
13
+ export default function ChatInput({ onSend, disabled, isLoading, onStop, placeholder, maxRows, }: ChatInputProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"ChatInput.js","sources":["../../../../src/components/library/chat/ChatInput.jsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from \"react\";\nimport { PaperAirplaneIcon, StopCircleIcon } from \"@heroicons/react/24/solid\";\n\n/**\n * Chat input with auto-resize textarea, Send button, and keyboard shortcuts.\n * Enter sends, Shift+Enter inserts newline.\n *\n * @param {Function} onSend (content: string) => void\n * @param {boolean} disabled — disable input while agent is processing\n * @param {boolean} isLoading show stop button instead of send\n * @param {Function} onStop optional: called when stop is clicked\n * @param {string} placeholder\n * @param {number} maxRows — max visible rows before scroll (default 6)\n */\nexport default function ChatInput({\n onSend,\n disabled = false,\n isLoading = false,\n onStop,\n placeholder = \"Type a message…\",\n maxRows = 6,\n}) {\n const [value, setValue] = useState(\"\");\n const textareaRef = useRef(null);\n\n useEffect(() => {\n const ta = textareaRef.current;\n if (!ta) return;\n ta.style.height = \"auto\";\n const lineHeight = 22;\n const maxHeight = lineHeight * maxRows;\n ta.style.height = `${Math.min(ta.scrollHeight, maxHeight)}px`;\n }, [value, maxRows]);\n\n function handleSend() {\n if (!value.trim() || disabled) return;\n onSend?.(value);\n setValue(\"\");\n if (textareaRef.current) {\n textareaRef.current.style.height = \"auto\";\n }\n }\n\n function handleKeyDown(e) {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n }\n\n const canSend = value.trim().length > 0 && !disabled;\n\n return (\n <div className=\"flex items-end gap-2 rounded-xl border border-slate-200 bg-white p-2 shadow-sm transition-colors focus-within:border-brand-300 focus-within:ring-2 focus-within:ring-brand-500/20 dark:border-slate-700 dark:bg-slate-900 dark:focus-within:border-brand-700 dark:focus-within:ring-brand-400/20\">\n <textarea\n ref={textareaRef}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n rows={1}\n className=\"max-h-36 min-h-[22px] flex-1 resize-none bg-transparent px-2 py-1.5 text-sm text-slate-900 placeholder:text-slate-400 focus:outline-none disabled:cursor-not-allowed disabled:opacity-60 dark:text-slate-50 dark:placeholder:text-slate-500\"\n aria-label=\"Chat message input\"\n />\n\n {isLoading && onStop ? (\n <button\n type=\"button\"\n onClick={onStop}\n className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:text-slate-500 dark:hover:bg-slate-800 dark:hover:text-slate-300\"\n aria-label=\"Stop generating\"\n >\n <StopCircleIcon className=\"h-5 w-5\" />\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleSend}\n disabled={!canSend}\n className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-brand-600 text-white transition hover:bg-brand-500 disabled:cursor-not-allowed disabled:opacity-40 dark:bg-brand-500 dark:hover:bg-brand-400\"\n aria-label=\"Send message\"\n >\n <PaperAirplaneIcon className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n );\n}\n"],"names":["ChatInput","onSend","disabled","isLoading","onStop","placeholder","maxRows","value","setValue","useState","textareaRef","useRef","useEffect","ta","maxHeight","handleSend","handleKeyDown","canSend","jsxs","jsx","StopCircleIcon","PaperAirplaneIcon"],"mappings":";;;AAcA,SAAwBA,EAAU;AAAA,EAChC,QAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,WAAAC,IAAY;AAAA,EACZ,QAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,SAAAC,IAAU;AACZ,GAAG;AACD,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAAS,EAAE,GAC/BC,IAAcC,EAAO,IAAI;AAE/B,EAAAC,EAAU,MAAM;AACd,UAAMC,IAAKH,EAAY;AACvB,QAAI,CAACG,EAAI;AACT,IAAAA,EAAG,MAAM,SAAS;AAElB,UAAMC,IADa,KACYR;AAC/B,IAAAO,EAAG,MAAM,SAAS,GAAG,KAAK,IAAIA,EAAG,cAAcC,CAAS,CAAC;AAAA,EAC3D,GAAG,CAACP,GAAOD,CAAO,CAAC;AAEnB,WAASS,IAAa;AACpB,IAAI,CAACR,EAAM,KAAA,KAAUL,MACrBD,IAASM,CAAK,GACdC,EAAS,EAAE,GACPE,EAAY,YACdA,EAAY,QAAQ,MAAM,SAAS;AAAA,EAEvC;AAEA,WAASM,EAAc,GAAG;AACxB,IAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,aAC1B,EAAE,eAAA,GACFD,EAAA;AAAA,EAEJ;AAEA,QAAME,IAAUV,EAAM,KAAA,EAAO,SAAS,KAAK,CAACL;AAE5C,SACE,gBAAAgB,EAAC,OAAA,EAAI,WAAU,oSACb,UAAA;AAAA,IAAA,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKT;AAAA,QACL,OAAAH;AAAA,QACA,UAAU,CAAC,MAAMC,EAAS,EAAE,OAAO,KAAK;AAAA,QACxC,WAAWQ;AAAA,QACX,aAAAX;AAAA,QACA,UAAAH;AAAA,QACA,MAAM;AAAA,QACN,WAAU;AAAA,QACV,cAAW;AAAA,MAAA;AAAA,IAAA;AAAA,IAGZC,KAAaC,IACZ,gBAAAe;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAASf;AAAA,QACT,WAAU;AAAA,QACV,cAAW;AAAA,QAEX,UAAA,gBAAAe,EAACC,GAAA,EAAe,WAAU,UAAA,CAAU;AAAA,MAAA;AAAA,IAAA,IAGtC,gBAAAD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAASJ;AAAA,QACT,UAAU,CAACE;AAAA,QACX,WAAU;AAAA,QACV,cAAW;AAAA,QAEX,UAAA,gBAAAE,EAACE,GAAA,EAAkB,WAAU,UAAA,CAAU;AAAA,MAAA;AAAA,IAAA;AAAA,EACzC,GAEJ;AAEJ;"}
1
+ {"version":3,"file":"ChatInput.js","sources":["../../../../src/components/library/chat/ChatInput.tsx"],"sourcesContent":["import { useState, useRef, useEffect } from \"react\";\nimport { PaperAirplaneIcon, StopCircleIcon } from \"@heroicons/react/24/solid\";\n\nexport interface ChatInputProps {\n onSend?: (content: string) => void;\n disabled?: boolean;\n isLoading?: boolean;\n onStop?: () => void;\n placeholder?: string;\n maxRows?: number;\n}\n\n/**\n * Chat input with auto-resize textarea, Send button, and keyboard shortcuts.\n * Enter sends, Shift+Enter inserts newline.\n */\nexport default function ChatInput({\n onSend,\n disabled = false,\n isLoading = false,\n onStop,\n placeholder = \"Type a message…\",\n maxRows = 6,\n}: ChatInputProps) {\n const [value, setValue] = useState(\"\");\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n const ta = textareaRef.current;\n if (!ta) return;\n ta.style.height = \"auto\";\n const lineHeight = 22;\n const maxHeight = lineHeight * maxRows;\n ta.style.height = `${Math.min(ta.scrollHeight, maxHeight)}px`;\n }, [value, maxRows]);\n\n function handleSend() {\n if (!value.trim() || disabled) return;\n onSend?.(value);\n setValue(\"\");\n if (textareaRef.current) {\n textareaRef.current.style.height = \"auto\";\n }\n }\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n }\n\n const canSend = value.trim().length > 0 && !disabled;\n\n return (\n <div className=\"flex items-end gap-2 rounded-xl border border-slate-200 bg-white p-2 shadow-sm transition-colors focus-within:border-brand-300 focus-within:ring-2 focus-within:ring-brand-500/20 dark:border-slate-700 dark:bg-slate-900 dark:focus-within:border-brand-700 dark:focus-within:ring-brand-400/20\">\n <textarea\n ref={textareaRef}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n rows={1}\n className=\"max-h-36 min-h-[22px] flex-1 resize-none bg-transparent px-2 py-1.5 text-sm text-slate-900 placeholder:text-slate-400 focus:outline-none disabled:cursor-not-allowed disabled:opacity-60 dark:text-slate-50 dark:placeholder:text-slate-500\"\n aria-label=\"Chat message input\"\n />\n\n {isLoading && onStop ? (\n <button\n type=\"button\"\n onClick={onStop}\n className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:text-slate-500 dark:hover:bg-slate-800 dark:hover:text-slate-300\"\n aria-label=\"Stop generating\"\n >\n <StopCircleIcon className=\"h-5 w-5\" />\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleSend}\n disabled={!canSend}\n className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-brand-600 text-white transition hover:bg-brand-500 disabled:cursor-not-allowed disabled:opacity-40 dark:bg-brand-500 dark:hover:bg-brand-400\"\n aria-label=\"Send message\"\n >\n <PaperAirplaneIcon className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n );\n}\n"],"names":["ChatInput","onSend","disabled","isLoading","onStop","placeholder","maxRows","value","setValue","useState","textareaRef","useRef","useEffect","ta","maxHeight","handleSend","handleKeyDown","canSend","jsxs","jsx","StopCircleIcon","PaperAirplaneIcon"],"mappings":";;;AAgBA,SAAwBA,EAAU;AAAA,EAChC,QAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,WAAAC,IAAY;AAAA,EACZ,QAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,SAAAC,IAAU;AACZ,GAAmB;AACjB,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAAS,EAAE,GAC/BC,IAAcC,EAA4B,IAAI;AAEpD,EAAAC,EAAU,MAAM;AACd,UAAMC,IAAKH,EAAY;AACvB,QAAI,CAACG,EAAI;AACT,IAAAA,EAAG,MAAM,SAAS;AAElB,UAAMC,IADa,KACYR;AAC/B,IAAAO,EAAG,MAAM,SAAS,GAAG,KAAK,IAAIA,EAAG,cAAcC,CAAS,CAAC;AAAA,EAC3D,GAAG,CAACP,GAAOD,CAAO,CAAC;AAEnB,WAASS,IAAa;AACpB,IAAI,CAACR,EAAM,KAAA,KAAUL,MACrBD,IAASM,CAAK,GACdC,EAAS,EAAE,GACPE,EAAY,YACdA,EAAY,QAAQ,MAAM,SAAS;AAAA,EAEvC;AAEA,WAASM,EAAc,GAA6C;AAClE,IAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,aAC1B,EAAE,eAAA,GACFD,EAAA;AAAA,EAEJ;AAEA,QAAME,IAAUV,EAAM,KAAA,EAAO,SAAS,KAAK,CAACL;AAE5C,SACE,gBAAAgB,EAAC,OAAA,EAAI,WAAU,oSACb,UAAA;AAAA,IAAA,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKT;AAAA,QACL,OAAAH;AAAA,QACA,UAAU,CAAC,MAAMC,EAAS,EAAE,OAAO,KAAK;AAAA,QACxC,WAAWQ;AAAA,QACX,aAAAX;AAAA,QACA,UAAAH;AAAA,QACA,MAAM;AAAA,QACN,WAAU;AAAA,QACV,cAAW;AAAA,MAAA;AAAA,IAAA;AAAA,IAGZC,KAAaC,IACZ,gBAAAe;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAASf;AAAA,QACT,WAAU;AAAA,QACV,cAAW;AAAA,QAEX,UAAA,gBAAAe,EAACC,GAAA,EAAe,WAAU,UAAA,CAAU;AAAA,MAAA;AAAA,IAAA,IAGtC,gBAAAD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAASJ;AAAA,QACT,UAAU,CAACE;AAAA,QACX,WAAU;AAAA,QACV,cAAW;AAAA,QAEX,UAAA,gBAAAE,EAACE,GAAA,EAAkB,WAAU,UAAA,CAAU;AAAA,MAAA;AAAA,IAAA;AAAA,EACzC,GAEJ;AAEJ;"}
@@ -1,7 +1,21 @@
1
+ import React from "react";
2
+ import { type SchemaComponent } from "@/components/workspace/ComponentRegistry";
3
+ import { ToolCall } from "./ChatToolCall";
4
+ export interface ChatMessageData {
5
+ id: string;
6
+ role: "user" | "assistant" | "system";
7
+ content?: string;
8
+ components?: SchemaComponent[];
9
+ toolCalls?: ToolCall[];
10
+ isError?: boolean;
11
+ isStreaming?: boolean;
12
+ timestamp?: string;
13
+ }
14
+ export interface ChatMessageProps {
15
+ message: ChatMessageData;
16
+ avatar?: React.ReactNode;
17
+ }
1
18
  /**
2
19
  * Renders a single chat message.
3
- *
4
- * @param {Object} message — { id, role, content, components?, toolCalls?, isError?, isStreaming?, timestamp? }
5
- * @param {React.ReactNode} avatar — custom avatar override
6
20
  */
7
- export default function ChatMessage({ message, avatar }: Object): import("react/jsx-runtime").JSX.Element;
21
+ export default function ChatMessage({ message, avatar }: ChatMessageProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"ChatMessage.js","sources":["../../../../src/components/library/chat/ChatMessage.jsx"],"sourcesContent":["import React from \"react\";\nimport { renderSchemaComponent } from \"@/components/workspace/ComponentRegistry\";\nimport ChatToolCall from \"./ChatToolCall\";\nimport { UserCircleIcon, CpuChipIcon } from \"@heroicons/react/24/solid\";\n\nfunction cx(...classes) {\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) {\n if (!text) return null;\n const parts = [];\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) {\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\n/**\n * Renders a single chat message.\n *\n * @param {Object} message — { id, role, content, components?, toolCalls?, isError?, isStreaming?, timestamp? }\n * @param {React.ReactNode} avatar custom avatar override\n */\nexport default function ChatMessage({ message, avatar }) {\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,11 +1,14 @@
1
+ import React from "react";
2
+ import { ChatMessageData } from "./ChatMessage";
3
+ export interface ChatMessageListProps {
4
+ messages?: ChatMessageData[];
5
+ isLoading?: boolean;
6
+ isStreaming?: boolean;
7
+ suggestions?: string[];
8
+ onSuggestion?: (text: string) => void;
9
+ renderAvatar?: (message: ChatMessageData) => React.ReactNode;
10
+ }
1
11
  /**
2
12
  * Scrollable message area with auto-scroll to latest message.
3
- *
4
- * @param {Array} messages — array of message objects
5
- * @param {boolean} isLoading — show typing indicator
6
- * @param {boolean} isStreaming — agent is streaming (show different indicator text)
7
- * @param {string[]} suggestions — follow-up suggestions shown after last assistant message
8
- * @param {Function} onSuggestion — (text) => void
9
- * @param {Function} renderAvatar — (message) => ReactNode, optional per-message avatar
10
13
  */
11
- export default function ChatMessageList({ messages, isLoading, isStreaming, suggestions, onSuggestion, renderAvatar, }: any[]): import("react/jsx-runtime").JSX.Element;
14
+ export default function ChatMessageList({ messages, isLoading, isStreaming, suggestions, onSuggestion, renderAvatar, }: ChatMessageListProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"ChatMessageList.js","sources":["../../../../src/components/library/chat/ChatMessageList.jsx"],"sourcesContent":["import React, { useRef, useEffect } from \"react\";\nimport ChatMessage from \"./ChatMessage\";\nimport ChatTypingIndicator from \"./ChatTypingIndicator\";\nimport ChatSuggestions from \"./ChatSuggestions\";\n\n/**\n * Scrollable message area with auto-scroll to latest message.\n *\n * @param {Array} messages — array of message objects\n * @param {boolean} isLoading — show typing indicator\n * @param {boolean} isStreaming — agent is streaming (show different indicator text)\n * @param {string[]} suggestions follow-up suggestions shown after last assistant message\n * @param {Function} onSuggestion (text) => void\n * @param {Function} renderAvatar (message) => ReactNode, optional per-message avatar\n */\nexport default function ChatMessageList({\n messages = [],\n isLoading = false,\n isStreaming = false,\n suggestions = [],\n onSuggestion,\n renderAvatar,\n}) {\n const bottomRef = useRef(null);\n const containerRef = useRef(null);\n\n useEffect(() => {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [messages.length, isLoading, isStreaming]);\n\n const lastMessage = messages[messages.length - 1];\n const showSuggestions =\n suggestions.length > 0 &&\n !isLoading &&\n !isStreaming &&\n lastMessage?.role === \"assistant\";\n\n return (\n <div\n ref={containerRef}\n className=\"flex-1 overflow-y-auto px-4 py-4\"\n >\n <div className=\"mx-auto max-w-3xl space-y-4\">\n {messages.map((msg) => (\n <ChatMessage\n key={msg.id}\n message={msg}\n avatar={renderAvatar?.(msg)}\n />\n ))}\n\n {showSuggestions ? (\n <div className=\"pl-10\">\n <ChatSuggestions\n suggestions={suggestions}\n onSelect={onSuggestion}\n />\n </div>\n ) : null}\n\n {isLoading && !isStreaming ? (\n <ChatTypingIndicator label=\"Thinking\" />\n ) : null}\n\n {isStreaming ? (\n <ChatTypingIndicator label=\"Generating\" />\n ) : null}\n\n <div ref={bottomRef} />\n </div>\n </div>\n );\n}\n"],"names":["ChatMessageList","messages","isLoading","isStreaming","suggestions","onSuggestion","renderAvatar","bottomRef","useRef","containerRef","useEffect","lastMessage","showSuggestions","jsx","jsxs","msg","ChatMessage","ChatSuggestions","ChatTypingIndicator"],"mappings":";;;;;AAeA,SAAwBA,EAAgB;AAAA,EACtC,UAAAC,IAAW,CAAA;AAAA,EACX,WAAAC,IAAY;AAAA,EACZ,aAAAC,IAAc;AAAA,EACd,aAAAC,IAAc,CAAA;AAAA,EACd,cAAAC;AAAA,EACA,cAAAC;AACF,GAAG;AACD,QAAMC,IAAYC,EAAO,IAAI,GACvBC,IAAeD,EAAO,IAAI;AAEhC,EAAAE,EAAU,MAAM;AACd,IAAAH,EAAU,SAAS,eAAe,EAAE,UAAU,UAAU;AAAA,EAC1D,GAAG,CAACN,EAAS,QAAQC,GAAWC,CAAW,CAAC;AAE5C,QAAMQ,IAAcV,EAASA,EAAS,SAAS,CAAC,GAC1CW,IACJR,EAAY,SAAS,KACrB,CAACF,KACD,CAACC,KACDQ,GAAa,SAAS;AAExB,SACE,gBAAAE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKJ;AAAA,MACL,WAAU;AAAA,MAEV,UAAA,gBAAAK,EAAC,OAAA,EAAI,WAAU,+BACZ,UAAA;AAAA,QAAAb,EAAS,IAAI,CAACc,MACb,gBAAAF;AAAA,UAACG;AAAA,UAAA;AAAA,YAEC,SAASD;AAAA,YACT,QAAQT,IAAeS,CAAG;AAAA,UAAA;AAAA,UAFrBA,EAAI;AAAA,QAAA,CAIZ;AAAA,QAEAH,IACC,gBAAAC,EAAC,OAAA,EAAI,WAAU,SACb,UAAA,gBAAAA;AAAA,UAACI;AAAA,UAAA;AAAA,YACC,aAAAb;AAAA,YACA,UAAUC;AAAA,UAAA;AAAA,QAAA,GAEd,IACE;AAAA,QAEHH,KAAa,CAACC,sBACZe,GAAA,EAAoB,OAAM,YAAW,IACpC;AAAA,QAEHf,IACC,gBAAAU,EAACK,GAAA,EAAoB,OAAM,cAAa,IACtC;AAAA,QAEJ,gBAAAL,EAAC,OAAA,EAAI,KAAKN,EAAA,CAAW;AAAA,MAAA,EAAA,CACvB;AAAA,IAAA;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"ChatMessageList.js","sources":["../../../../src/components/library/chat/ChatMessageList.tsx"],"sourcesContent":["import React, { useRef, useEffect } from \"react\";\nimport ChatMessage, { ChatMessageData } from \"./ChatMessage\";\nimport ChatTypingIndicator from \"./ChatTypingIndicator\";\nimport ChatSuggestions from \"./ChatSuggestions\";\n\nexport interface ChatMessageListProps {\n messages?: ChatMessageData[];\n isLoading?: boolean;\n isStreaming?: boolean;\n suggestions?: string[];\n onSuggestion?: (text: string) => void;\n renderAvatar?: (message: ChatMessageData) => React.ReactNode;\n}\n\n/**\n * Scrollable message area with auto-scroll to latest message.\n */\nexport default function ChatMessageList({\n messages = [],\n isLoading = false,\n isStreaming = false,\n suggestions = [],\n onSuggestion,\n renderAvatar,\n}: ChatMessageListProps) {\n const bottomRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [messages.length, isLoading, isStreaming]);\n\n const lastMessage = messages[messages.length - 1];\n const showSuggestions =\n suggestions.length > 0 &&\n !isLoading &&\n !isStreaming &&\n lastMessage?.role === \"assistant\";\n\n return (\n <div\n ref={containerRef}\n className=\"flex-1 overflow-y-auto px-4 py-4\"\n >\n <div className=\"mx-auto max-w-3xl space-y-4\">\n {messages.map((msg) => (\n <ChatMessage\n key={msg.id}\n message={msg}\n avatar={renderAvatar?.(msg)}\n />\n ))}\n\n {showSuggestions ? (\n <div className=\"pl-10\">\n <ChatSuggestions\n suggestions={suggestions}\n onSelect={onSuggestion}\n />\n </div>\n ) : null}\n\n {isLoading && !isStreaming ? (\n <ChatTypingIndicator label=\"Thinking\" />\n ) : null}\n\n {isStreaming ? (\n <ChatTypingIndicator label=\"Generating\" />\n ) : null}\n\n <div ref={bottomRef} />\n </div>\n </div>\n );\n}\n"],"names":["ChatMessageList","messages","isLoading","isStreaming","suggestions","onSuggestion","renderAvatar","bottomRef","useRef","containerRef","useEffect","lastMessage","showSuggestions","jsx","jsxs","msg","ChatMessage","ChatSuggestions","ChatTypingIndicator"],"mappings":";;;;;AAiBA,SAAwBA,EAAgB;AAAA,EACtC,UAAAC,IAAW,CAAA;AAAA,EACX,WAAAC,IAAY;AAAA,EACZ,aAAAC,IAAc;AAAA,EACd,aAAAC,IAAc,CAAA;AAAA,EACd,cAAAC;AAAA,EACA,cAAAC;AACF,GAAyB;AACvB,QAAMC,IAAYC,EAAuB,IAAI,GACvCC,IAAeD,EAAuB,IAAI;AAEhD,EAAAE,EAAU,MAAM;AACd,IAAAH,EAAU,SAAS,eAAe,EAAE,UAAU,UAAU;AAAA,EAC1D,GAAG,CAACN,EAAS,QAAQC,GAAWC,CAAW,CAAC;AAE5C,QAAMQ,IAAcV,EAASA,EAAS,SAAS,CAAC,GAC1CW,IACJR,EAAY,SAAS,KACrB,CAACF,KACD,CAACC,KACDQ,GAAa,SAAS;AAExB,SACE,gBAAAE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKJ;AAAA,MACL,WAAU;AAAA,MAEV,UAAA,gBAAAK,EAAC,OAAA,EAAI,WAAU,+BACZ,UAAA;AAAA,QAAAb,EAAS,IAAI,CAACc,MACb,gBAAAF;AAAA,UAACG;AAAA,UAAA;AAAA,YAEC,SAASD;AAAA,YACT,QAAQT,IAAeS,CAAG;AAAA,UAAA;AAAA,UAFrBA,EAAI;AAAA,QAAA,CAIZ;AAAA,QAEAH,IACC,gBAAAC,EAAC,OAAA,EAAI,WAAU,SACb,UAAA,gBAAAA;AAAA,UAACI;AAAA,UAAA;AAAA,YACC,aAAAb;AAAA,YACA,UAAUC;AAAA,UAAA;AAAA,QAAA,GAEd,IACE;AAAA,QAEHH,KAAa,CAACC,sBACZe,GAAA,EAAoB,OAAM,YAAW,IACpC;AAAA,QAEHf,IACC,gBAAAU,EAACK,GAAA,EAAoB,OAAM,cAAa,IACtC;AAAA,QAEJ,gBAAAL,EAAC,OAAA,EAAI,KAAKN,EAAA,CAAW;AAAA,MAAA,EAAA,CACvB;AAAA,IAAA;AAAA,EAAA;AAGN;"}
@@ -1,16 +1,20 @@
1
+ import React from "react";
2
+ import { UseChatStateOptions } from "./useChatState";
3
+ import { ChatMessageData } from "./ChatMessage";
4
+ export interface ChatPanelProps {
5
+ title?: string;
6
+ onSend?: UseChatStateOptions["onSend"];
7
+ initialMessages?: UseChatStateOptions["initialMessages"];
8
+ welcomeTitle?: string;
9
+ welcomeSubtitle?: string;
10
+ suggestions?: string[];
11
+ placeholder?: string;
12
+ className?: string;
13
+ renderAvatar?: (message: ChatMessageData) => React.ReactNode;
14
+ showHeader?: boolean;
15
+ }
1
16
  /**
2
17
  * All-in-one chat panel. Composes ChatMessageList, ChatInput, ChatWelcome,
3
18
  * and useChatState into a single drop-in component.
4
- *
5
- * @param {string} title — panel header title
6
- * @param {Function} onSend — async (userMessage, history, helpers) => assistantMessage?
7
- * @param {Array} initialMessages — seed messages
8
- * @param {string} welcomeTitle — welcome screen heading
9
- * @param {string} welcomeSubtitle — welcome screen description
10
- * @param {string[]} suggestions — starter and follow-up prompts
11
- * @param {string} placeholder — input placeholder
12
- * @param {string} className — additional classes on the root container
13
- * @param {Function} renderAvatar — (message) => ReactNode
14
- * @param {boolean} showHeader — show the title bar (default true)
15
19
  */
16
- export default function ChatPanel({ title, onSend, initialMessages, welcomeTitle, welcomeSubtitle, suggestions, placeholder, className, renderAvatar, showHeader, }: string): import("react/jsx-runtime").JSX.Element;
20
+ export default function ChatPanel({ title, onSend, initialMessages, welcomeTitle, welcomeSubtitle, suggestions, placeholder, className, renderAvatar, showHeader, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
@@ -1,11 +1,10 @@
1
1
  import { jsxs as r, jsx as t } from "react/jsx-runtime";
2
- import "react";
3
2
  import f from "./ChatMessageList.js";
4
- import p from "./ChatInput.js";
5
- import u from "./ChatWelcome.js";
6
- import x from "./useChatState.js";
3
+ import u from "./ChatInput.js";
4
+ import x from "./ChatWelcome.js";
5
+ import p from "./useChatState.js";
7
6
  import { TrashIcon as k } from "@heroicons/react/24/outline";
8
- function w({
7
+ function j({
9
8
  title: o = "AI Assistant",
10
9
  onSend: l,
11
10
  initialMessages: i = [],
@@ -17,7 +16,7 @@ function w({
17
16
  renderAvatar: h,
18
17
  showHeader: c = !0
19
18
  }) {
20
- const e = x({ initialMessages: i, onSend: l }), b = e.messages.length === 0;
19
+ const e = p({ initialMessages: i, onSend: l }), b = e.messages.length === 0;
21
20
  return /* @__PURE__ */ r(
22
21
  "div",
23
22
  {
@@ -40,7 +39,7 @@ function w({
40
39
  ) : null
41
40
  ] }) : null,
42
41
  b ? /* @__PURE__ */ t(
43
- u,
42
+ x,
44
43
  {
45
44
  title: n,
46
45
  subtitle: d,
@@ -59,7 +58,7 @@ function w({
59
58
  }
60
59
  ),
61
60
  /* @__PURE__ */ t("div", { className: "border-t border-slate-100 p-3 dark:border-slate-800", children: /* @__PURE__ */ t(
62
- p,
61
+ u,
63
62
  {
64
63
  onSend: (s) => e.sendMessage(s),
65
64
  disabled: e.isLoading,
@@ -72,6 +71,6 @@ function w({
72
71
  );
73
72
  }
74
73
  export {
75
- w as default
74
+ j as default
76
75
  };
77
76
  //# sourceMappingURL=ChatPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatPanel.js","sources":["../../../../src/components/library/chat/ChatPanel.jsx"],"sourcesContent":["import React from \"react\";\nimport ChatMessageList from \"./ChatMessageList\";\nimport ChatInput from \"./ChatInput\";\nimport ChatWelcome from \"./ChatWelcome\";\nimport useChatState from \"./useChatState\";\nimport { TrashIcon } from \"@heroicons/react/24/outline\";\n\n/**\n * All-in-one chat panel. Composes ChatMessageList, ChatInput, ChatWelcome,\n * and useChatState into a single drop-in component.\n *\n * @param {string} title — panel header title\n * @param {Function} onSend — async (userMessage, history, helpers) => assistantMessage?\n * @param {Array} initialMessages — seed messages\n * @param {string} welcomeTitle — welcome screen heading\n * @param {string} welcomeSubtitle — welcome screen description\n * @param {string[]} suggestions — starter and follow-up prompts\n * @param {string} placeholder — input placeholder\n * @param {string} className additional classes on the root container\n * @param {Function} renderAvatar (message) => ReactNode\n * @param {boolean} showHeader show the title bar (default true)\n */\nexport default function ChatPanel({\n title = \"AI Assistant\",\n onSend,\n initialMessages = [],\n welcomeTitle,\n welcomeSubtitle,\n suggestions = [],\n placeholder,\n className = \"\",\n renderAvatar,\n showHeader = true,\n}) {\n const chat = useChatState({ initialMessages, onSend });\n\n const isEmpty = chat.messages.length === 0;\n\n return (\n <div\n className={[\n \"flex flex-col overflow-hidden rounded-xl border border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {/* Header */}\n {showHeader ? (\n <div className=\"flex items-center justify-between border-b border-slate-100 px-4 py-3 dark:border-slate-800\">\n <h3 className=\"text-sm font-semibold text-slate-900 dark:text-slate-50\">\n {title}\n </h3>\n {chat.messages.length > 0 ? (\n <button\n type=\"button\"\n onClick={chat.clearMessages}\n className=\"rounded p-1 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:text-slate-500 dark:hover:bg-slate-800 dark:hover:text-slate-300\"\n aria-label=\"Clear chat\"\n >\n <TrashIcon className=\"h-4 w-4\" />\n </button>\n ) : null}\n </div>\n ) : null}\n\n {/* Messages or welcome */}\n {isEmpty ? (\n <ChatWelcome\n title={welcomeTitle}\n subtitle={welcomeSubtitle}\n suggestions={suggestions}\n onSuggestion={(text) => chat.sendMessage(text)}\n />\n ) : (\n <ChatMessageList\n messages={chat.messages}\n isLoading={chat.isLoading}\n isStreaming={chat.isStreaming}\n suggestions={suggestions}\n onSuggestion={(text) => chat.sendMessage(text)}\n renderAvatar={renderAvatar}\n />\n )}\n\n {/* Input */}\n <div className=\"border-t border-slate-100 p-3 dark:border-slate-800\">\n <ChatInput\n onSend={(content) => chat.sendMessage(content)}\n disabled={chat.isLoading}\n isLoading={chat.isLoading}\n placeholder={placeholder}\n />\n </div>\n </div>\n );\n}\n"],"names":["ChatPanel","title","onSend","initialMessages","welcomeTitle","welcomeSubtitle","suggestions","placeholder","className","renderAvatar","showHeader","chat","useChatState","isEmpty","jsxs","jsx","TrashIcon","ChatWelcome","text","ChatMessageList","ChatInput","content"],"mappings":";;;;;;;AAsBA,SAAwBA,EAAU;AAAA,EAChC,OAAAC,IAAQ;AAAA,EACR,QAAAC;AAAA,EACA,iBAAAC,IAAkB,CAAA;AAAA,EAClB,cAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,aAAAC,IAAc,CAAA;AAAA,EACd,aAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,cAAAC;AAAA,EACA,YAAAC,IAAa;AACf,GAAG;AACD,QAAMC,IAAOC,EAAa,EAAE,iBAAAT,GAAiB,QAAAD,GAAQ,GAE/CW,IAAUF,EAAK,SAAS,WAAW;AAEzC,SACE,gBAAAG;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACAN;AAAA,MAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,MAGV,UAAA;AAAA,QAAAE,IACC,gBAAAI,EAAC,OAAA,EAAI,WAAU,+FACb,UAAA;AAAA,UAAA,gBAAAC,EAAC,MAAA,EAAG,WAAU,2DACX,UAAAd,GACH;AAAA,UACCU,EAAK,SAAS,SAAS,IACtB,gBAAAI;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAASJ,EAAK;AAAA,cACd,WAAU;AAAA,cACV,cAAW;AAAA,cAEX,UAAA,gBAAAI,EAACC,GAAA,EAAU,WAAU,UAAA,CAAU;AAAA,YAAA;AAAA,UAAA,IAE/B;AAAA,QAAA,EAAA,CACN,IACE;AAAA,QAGHH,IACC,gBAAAE;AAAA,UAACE;AAAA,UAAA;AAAA,YACC,OAAOb;AAAA,YACP,UAAUC;AAAA,YACV,aAAAC;AAAA,YACA,cAAc,CAACY,MAASP,EAAK,YAAYO,CAAI;AAAA,UAAA;AAAA,QAAA,IAG/C,gBAAAH;AAAA,UAACI;AAAA,UAAA;AAAA,YACC,UAAUR,EAAK;AAAA,YACf,WAAWA,EAAK;AAAA,YAChB,aAAaA,EAAK;AAAA,YAClB,aAAAL;AAAA,YACA,cAAc,CAACY,MAASP,EAAK,YAAYO,CAAI;AAAA,YAC7C,cAAAT;AAAA,UAAA;AAAA,QAAA;AAAA,QAKJ,gBAAAM,EAAC,OAAA,EAAI,WAAU,uDACb,UAAA,gBAAAA;AAAA,UAACK;AAAA,UAAA;AAAA,YACC,QAAQ,CAACC,MAAYV,EAAK,YAAYU,CAAO;AAAA,YAC7C,UAAUV,EAAK;AAAA,YACf,WAAWA,EAAK;AAAA,YAChB,aAAAJ;AAAA,UAAA;AAAA,QAAA,EACF,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"ChatPanel.js","sources":["../../../../src/components/library/chat/ChatPanel.tsx"],"sourcesContent":["import React from \"react\";\nimport ChatMessageList from \"./ChatMessageList\";\nimport ChatInput from \"./ChatInput\";\nimport ChatWelcome from \"./ChatWelcome\";\nimport useChatState, { UseChatStateOptions } from \"./useChatState\";\nimport { ChatMessageData } from \"./ChatMessage\";\nimport { TrashIcon } from \"@heroicons/react/24/outline\";\n\nexport interface ChatPanelProps {\n title?: string;\n onSend?: UseChatStateOptions[\"onSend\"];\n initialMessages?: UseChatStateOptions[\"initialMessages\"];\n welcomeTitle?: string;\n welcomeSubtitle?: string;\n suggestions?: string[];\n placeholder?: string;\n className?: string;\n renderAvatar?: (message: ChatMessageData) => React.ReactNode;\n showHeader?: boolean;\n}\n\n/**\n * All-in-one chat panel. Composes ChatMessageList, ChatInput, ChatWelcome,\n * and useChatState into a single drop-in component.\n */\nexport default function ChatPanel({\n title = \"AI Assistant\",\n onSend,\n initialMessages = [],\n welcomeTitle,\n welcomeSubtitle,\n suggestions = [],\n placeholder,\n className = \"\",\n renderAvatar,\n showHeader = true,\n}: ChatPanelProps) {\n const chat = useChatState({ initialMessages, onSend });\n\n const isEmpty = chat.messages.length === 0;\n\n return (\n <div\n className={[\n \"flex flex-col overflow-hidden rounded-xl border border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {/* Header */}\n {showHeader ? (\n <div className=\"flex items-center justify-between border-b border-slate-100 px-4 py-3 dark:border-slate-800\">\n <h3 className=\"text-sm font-semibold text-slate-900 dark:text-slate-50\">\n {title}\n </h3>\n {chat.messages.length > 0 ? (\n <button\n type=\"button\"\n onClick={chat.clearMessages}\n className=\"rounded p-1 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 dark:text-slate-500 dark:hover:bg-slate-800 dark:hover:text-slate-300\"\n aria-label=\"Clear chat\"\n >\n <TrashIcon className=\"h-4 w-4\" />\n </button>\n ) : null}\n </div>\n ) : null}\n\n {/* Messages or welcome */}\n {isEmpty ? (\n <ChatWelcome\n title={welcomeTitle}\n subtitle={welcomeSubtitle}\n suggestions={suggestions}\n onSuggestion={(text) => chat.sendMessage(text)}\n />\n ) : (\n <ChatMessageList\n messages={chat.messages}\n isLoading={chat.isLoading}\n isStreaming={chat.isStreaming}\n suggestions={suggestions}\n onSuggestion={(text) => chat.sendMessage(text)}\n renderAvatar={renderAvatar}\n />\n )}\n\n {/* Input */}\n <div className=\"border-t border-slate-100 p-3 dark:border-slate-800\">\n <ChatInput\n onSend={(content) => chat.sendMessage(content)}\n disabled={chat.isLoading}\n isLoading={chat.isLoading}\n placeholder={placeholder}\n />\n </div>\n </div>\n );\n}\n"],"names":["ChatPanel","title","onSend","initialMessages","welcomeTitle","welcomeSubtitle","suggestions","placeholder","className","renderAvatar","showHeader","chat","useChatState","isEmpty","jsxs","jsx","TrashIcon","ChatWelcome","text","ChatMessageList","ChatInput","content"],"mappings":";;;;;;AAyBA,SAAwBA,EAAU;AAAA,EAChC,OAAAC,IAAQ;AAAA,EACR,QAAAC;AAAA,EACA,iBAAAC,IAAkB,CAAA;AAAA,EAClB,cAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,aAAAC,IAAc,CAAA;AAAA,EACd,aAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,cAAAC;AAAA,EACA,YAAAC,IAAa;AACf,GAAmB;AACjB,QAAMC,IAAOC,EAAa,EAAE,iBAAAT,GAAiB,QAAAD,GAAQ,GAE/CW,IAAUF,EAAK,SAAS,WAAW;AAEzC,SACE,gBAAAG;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACAN;AAAA,MAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,MAGV,UAAA;AAAA,QAAAE,IACC,gBAAAI,EAAC,OAAA,EAAI,WAAU,+FACb,UAAA;AAAA,UAAA,gBAAAC,EAAC,MAAA,EAAG,WAAU,2DACX,UAAAd,GACH;AAAA,UACCU,EAAK,SAAS,SAAS,IACtB,gBAAAI;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAASJ,EAAK;AAAA,cACd,WAAU;AAAA,cACV,cAAW;AAAA,cAEX,UAAA,gBAAAI,EAACC,GAAA,EAAU,WAAU,UAAA,CAAU;AAAA,YAAA;AAAA,UAAA,IAE/B;AAAA,QAAA,EAAA,CACN,IACE;AAAA,QAGHH,IACC,gBAAAE;AAAA,UAACE;AAAA,UAAA;AAAA,YACC,OAAOb;AAAA,YACP,UAAUC;AAAA,YACV,aAAAC;AAAA,YACA,cAAc,CAACY,MAASP,EAAK,YAAYO,CAAI;AAAA,UAAA;AAAA,QAAA,IAG/C,gBAAAH;AAAA,UAACI;AAAA,UAAA;AAAA,YACC,UAAUR,EAAK;AAAA,YACf,WAAWA,EAAK;AAAA,YAChB,aAAaA,EAAK;AAAA,YAClB,aAAAL;AAAA,YACA,cAAc,CAACY,MAASP,EAAK,YAAYO,CAAI;AAAA,YAC7C,cAAAT;AAAA,UAAA;AAAA,QAAA;AAAA,QAKJ,gBAAAM,EAAC,OAAA,EAAI,WAAU,uDACb,UAAA,gBAAAA;AAAA,UAACK;AAAA,UAAA;AAAA,YACC,QAAQ,CAACC,MAAYV,EAAK,YAAYU,CAAO;AAAA,YAC7C,UAAUV,EAAK;AAAA,YACf,WAAWA,EAAK;AAAA,YAChB,aAAAJ;AAAA,UAAA;AAAA,QAAA,EACF,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;"}
@@ -1,7 +1,8 @@
1
+ export interface ChatSuggestionsProps {
2
+ suggestions?: string[];
3
+ onSelect?: (suggestion: string) => void;
4
+ }
1
5
  /**
2
6
  * Quick-action prompt buttons. Place above the input or after an assistant message.
3
- *
4
- * @param {string[]} suggestions — prompt strings
5
- * @param {Function} onSelect — (suggestion) => void
6
7
  */
7
- export default function ChatSuggestions({ suggestions, onSelect }: string[]): import("react/jsx-runtime").JSX.Element | null;
8
+ export default function ChatSuggestions({ suggestions, onSelect }: ChatSuggestionsProps): import("react/jsx-runtime").JSX.Element | null;
@@ -1,7 +1,6 @@
1
1
  import { jsx as a, jsxs as d } from "react/jsx-runtime";
2
- import "react";
3
2
  import { SparklesIcon as n } from "@heroicons/react/24/outline";
4
- function i({ suggestions: e = [], onSelect: t }) {
3
+ function s({ suggestions: e = [], onSelect: t }) {
5
4
  return e.length ? /* @__PURE__ */ a("div", { className: "flex flex-wrap gap-2", children: e.map((r) => /* @__PURE__ */ d(
6
5
  "button",
7
6
  {
@@ -17,6 +16,6 @@ function i({ suggestions: e = [], onSelect: t }) {
17
16
  )) }) : null;
18
17
  }
19
18
  export {
20
- i as default
19
+ s as default
21
20
  };
22
21
  //# sourceMappingURL=ChatSuggestions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatSuggestions.js","sources":["../../../../src/components/library/chat/ChatSuggestions.jsx"],"sourcesContent":["import React from \"react\";\nimport { SparklesIcon } from \"@heroicons/react/24/outline\";\n\n/**\n * Quick-action prompt buttons. Place above the input or after an assistant message.\n *\n * @param {string[]} suggestions — prompt strings\n * @param {Function} onSelect — (suggestion) => void\n */\nexport default function ChatSuggestions({ suggestions = [], onSelect }) {\n if (!suggestions.length) return null;\n\n return (\n <div className=\"flex flex-wrap gap-2\">\n {suggestions.map((text) => (\n <button\n key={text}\n type=\"button\"\n onClick={() => onSelect?.(text)}\n className=\"inline-flex items-center gap-1.5 rounded-full border border-slate-200 bg-white px-3 py-1.5 text-xs font-medium text-slate-600 shadow-sm transition hover:border-brand-300 hover:bg-brand-50 hover:text-brand-700 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-300 dark:hover:border-brand-700 dark:hover:bg-brand-950/30 dark:hover:text-brand-300\"\n >\n <SparklesIcon className=\"h-3 w-3\" aria-hidden=\"true\" />\n {text}\n </button>\n ))}\n </div>\n );\n}\n"],"names":["ChatSuggestions","suggestions","onSelect","text","jsxs","jsx","SparklesIcon"],"mappings":";;;AASA,SAAwBA,EAAgB,EAAE,aAAAC,IAAc,CAAA,GAAI,UAAAC,KAAY;AACtE,SAAKD,EAAY,2BAGd,OAAA,EAAI,WAAU,wBACZ,UAAAA,EAAY,IAAI,CAACE,MAChB,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MAEC,MAAK;AAAA,MACL,SAAS,MAAMF,IAAWC,CAAI;AAAA,MAC9B,WAAU;AAAA,MAEV,UAAA;AAAA,QAAA,gBAAAE,EAACC,GAAA,EAAa,WAAU,WAAU,eAAY,QAAO;AAAA,QACpDH;AAAA,MAAA;AAAA,IAAA;AAAA,IANIA;AAAA,EAAA,CAQR,GACH,IAf8B;AAiBlC;"}
1
+ {"version":3,"file":"ChatSuggestions.js","sources":["../../../../src/components/library/chat/ChatSuggestions.tsx"],"sourcesContent":["import { SparklesIcon } from \"@heroicons/react/24/outline\";\n\nexport interface ChatSuggestionsProps {\n suggestions?: string[];\n onSelect?: (suggestion: string) => void;\n}\n\n/**\n * Quick-action prompt buttons. Place above the input or after an assistant message.\n */\nexport default function ChatSuggestions({ suggestions = [], onSelect }: ChatSuggestionsProps) {\n if (!suggestions.length) return null;\n\n return (\n <div className=\"flex flex-wrap gap-2\">\n {suggestions.map((text) => (\n <button\n key={text}\n type=\"button\"\n onClick={() => onSelect?.(text)}\n className=\"inline-flex items-center gap-1.5 rounded-full border border-slate-200 bg-white px-3 py-1.5 text-xs font-medium text-slate-600 shadow-sm transition hover:border-brand-300 hover:bg-brand-50 hover:text-brand-700 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-300 dark:hover:border-brand-700 dark:hover:bg-brand-950/30 dark:hover:text-brand-300\"\n >\n <SparklesIcon className=\"h-3 w-3\" aria-hidden=\"true\" />\n {text}\n </button>\n ))}\n </div>\n );\n}\n"],"names":["ChatSuggestions","suggestions","onSelect","text","jsxs","jsx","SparklesIcon"],"mappings":";;AAUA,SAAwBA,EAAgB,EAAE,aAAAC,IAAc,CAAA,GAAI,UAAAC,KAAkC;AAC5F,SAAKD,EAAY,2BAGd,OAAA,EAAI,WAAU,wBACZ,UAAAA,EAAY,IAAI,CAACE,MAChB,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MAEC,MAAK;AAAA,MACL,SAAS,MAAMF,IAAWC,CAAI;AAAA,MAC9B,WAAU;AAAA,MAEV,UAAA;AAAA,QAAA,gBAAAE,EAACC,GAAA,EAAa,WAAU,WAAU,eAAY,QAAO;AAAA,QACpDH;AAAA,MAAA;AAAA,IAAA;AAAA,IANIA;AAAA,EAAA,CAQR,GACH,IAf8B;AAiBlC;"}
@@ -1,6 +1,14 @@
1
+ export interface ToolCall {
2
+ id?: string;
3
+ name: string;
4
+ args?: unknown;
5
+ status: "running" | "complete" | "error";
6
+ result?: unknown;
7
+ }
8
+ export interface ChatToolCallProps {
9
+ toolCall: ToolCall;
10
+ }
1
11
  /**
2
12
  * Displays an agent tool call / function execution step.
3
- *
4
- * @param {Object} toolCall — { id?, name, args?, status: "running"|"complete"|"error", result? }
5
13
  */
6
- export default function ChatToolCall({ toolCall }: Object): import("react/jsx-runtime").JSX.Element;
14
+ export default function ChatToolCall({ toolCall }: ChatToolCallProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"ChatToolCall.js","sources":["../../../../src/components/library/chat/ChatToolCall.jsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport Spinner from \"../ui/Spinner\";\nimport {\n WrenchScrewdriverIcon,\n CheckCircleIcon,\n XCircleIcon,\n ChevronDownIcon,\n} from \"@heroicons/react/24/outline\";\n\nconst STATUS_CONFIG = {\n running: {\n icon: <Spinner size=\"xs\" tone=\"brand\" label=\"Running\" />,\n text: \"text-brand-600 dark:text-brand-400\",\n bg: \"bg-brand-50 border-brand-100 dark:bg-brand-950/20 dark:border-brand-900/30\",\n label: \"Running\",\n },\n complete: {\n icon: <CheckCircleIcon className=\"h-3.5 w-3.5 text-emerald-500\" />,\n text: \"text-emerald-700 dark:text-emerald-300\",\n bg: \"bg-emerald-50 border-emerald-100 dark:bg-emerald-950/20 dark:border-emerald-900/30\",\n label: \"Complete\",\n },\n error: {\n icon: <XCircleIcon className=\"h-3.5 w-3.5 text-red-500\" />,\n text: \"text-red-700 dark:text-red-300\",\n bg: \"bg-red-50 border-red-100 dark:bg-red-950/20 dark:border-red-900/30\",\n label: \"Failed\",\n },\n};\n\n/**\n * Displays an agent tool call / function execution step.\n *\n * @param {Object} toolCall — { id?, name, args?, status: \"running\"|\"complete\"|\"error\", result? }\n */\nexport default function ChatToolCall({ toolCall }) {\n const [expanded, setExpanded] = useState(false);\n const config = STATUS_CONFIG[toolCall.status] ?? STATUS_CONFIG.running;\n const hasDetails = toolCall.args || toolCall.result;\n\n return (\n <div\n className={[\n \"rounded-lg border text-xs\",\n config.bg,\n ].join(\" \")}\n >\n <button\n type=\"button\"\n onClick={() => hasDetails && setExpanded(!expanded)}\n className={[\n \"flex w-full items-center gap-2 px-3 py-1.5\",\n hasDetails ? \"cursor-pointer\" : \"cursor-default\",\n ].join(\" \")}\n >\n {config.icon}\n <WrenchScrewdriverIcon className=\"h-3 w-3 text-slate-400 dark:text-slate-500\" />\n <span className={[\"font-medium\", config.text].join(\" \")}>\n {toolCall.name}\n </span>\n <span className=\"text-slate-400 dark:text-slate-500\">\n — {config.label}\n </span>\n {hasDetails ? (\n <ChevronDownIcon\n className={[\n \"ml-auto h-3 w-3 text-slate-400 transition-transform dark:text-slate-500\",\n expanded ? \"rotate-180\" : \"\",\n ].join(\" \")}\n />\n ) : null}\n </button>\n\n {expanded && hasDetails ? (\n <div className=\"border-t border-inherit px-3 py-2 font-mono text-[11px] leading-relaxed text-slate-600 dark:text-slate-300\">\n {toolCall.args ? (\n <div className=\"mb-1\">\n <span className=\"font-sans font-semibold text-slate-500 dark:text-slate-400\">\n Args:{\" \"}\n </span>\n {typeof toolCall.args === \"string\"\n ? toolCall.args\n : JSON.stringify(toolCall.args, null, 2)}\n </div>\n ) : null}\n {toolCall.result ? (\n <div>\n <span className=\"font-sans font-semibold text-slate-500 dark:text-slate-400\">\n Result:{\" \"}\n </span>\n {typeof toolCall.result === \"string\"\n ? toolCall.result\n : JSON.stringify(toolCall.result, null, 2)}\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n );\n}\n"],"names":["STATUS_CONFIG","Spinner","jsx","CheckCircleIcon","XCircleIcon","ChatToolCall","toolCall","expanded","setExpanded","useState","config","hasDetails","jsxs","WrenchScrewdriverIcon","ChevronDownIcon"],"mappings":";;;;AASA,MAAMA,IAAgB;AAAA,EACpB,SAAS;AAAA,IACP,wBAAOC,GAAA,EAAQ,MAAK,MAAK,MAAK,SAAQ,OAAM,WAAU;AAAA,IACtD,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EAAA;AAAA,EAET,UAAU;AAAA,IACR,MAAM,gBAAAC,EAACC,GAAA,EAAgB,WAAU,+BAAA,CAA+B;AAAA,IAChE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EAAA;AAAA,EAET,OAAO;AAAA,IACL,MAAM,gBAAAD,EAACE,GAAA,EAAY,WAAU,2BAAA,CAA2B;AAAA,IACxD,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EAAA;AAEX;AAOA,SAAwBC,EAAa,EAAE,UAAAC,KAAY;AACjD,QAAM,CAACC,GAAUC,CAAW,IAAIC,EAAS,EAAK,GACxCC,IAASV,EAAcM,EAAS,MAAM,KAAKN,EAAc,SACzDW,IAAaL,EAAS,QAAQA,EAAS;AAE7C,SACE,gBAAAM;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACAF,EAAO;AAAA,MAAA,EACP,KAAK,GAAG;AAAA,MAEV,UAAA;AAAA,QAAA,gBAAAE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAMD,KAAcH,EAAY,CAACD,CAAQ;AAAA,YAClD,WAAW;AAAA,cACT;AAAA,cACAI,IAAa,mBAAmB;AAAA,YAAA,EAChC,KAAK,GAAG;AAAA,YAET,UAAA;AAAA,cAAAD,EAAO;AAAA,cACR,gBAAAR,EAACW,GAAA,EAAsB,WAAU,6CAAA,CAA6C;AAAA,cAC9E,gBAAAX,EAAC,QAAA,EAAK,WAAW,CAAC,eAAeQ,EAAO,IAAI,EAAE,KAAK,GAAG,GACnD,UAAAJ,EAAS,KAAA,CACZ;AAAA,cACA,gBAAAM,EAAC,QAAA,EAAK,WAAU,sCAAqC,UAAA;AAAA,gBAAA;AAAA,gBAChDF,EAAO;AAAA,cAAA,GACZ;AAAA,cACCC,IACC,gBAAAT;AAAA,gBAACY;AAAA,gBAAA;AAAA,kBACC,WAAW;AAAA,oBACT;AAAA,oBACAP,IAAW,eAAe;AAAA,kBAAA,EAC1B,KAAK,GAAG;AAAA,gBAAA;AAAA,cAAA,IAEV;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAGLA,KAAYI,IACX,gBAAAC,EAAC,OAAA,EAAI,WAAU,8GACZ,UAAA;AAAA,UAAAN,EAAS,OACR,gBAAAM,EAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,8DAA6D,UAAA;AAAA,cAAA;AAAA,cACrE;AAAA,YAAA,GACR;AAAA,YACC,OAAON,EAAS,QAAS,WACtBA,EAAS,OACT,KAAK,UAAUA,EAAS,MAAM,MAAM,CAAC;AAAA,UAAA,EAAA,CAC3C,IACE;AAAA,UACHA,EAAS,SACR,gBAAAM,EAAC,OAAA,EACC,UAAA;AAAA,YAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,8DAA6D,UAAA;AAAA,cAAA;AAAA,cACnE;AAAA,YAAA,GACV;AAAA,YACC,OAAON,EAAS,UAAW,WACxBA,EAAS,SACT,KAAK,UAAUA,EAAS,QAAQ,MAAM,CAAC;AAAA,UAAA,EAAA,CAC7C,IACE;AAAA,QAAA,EAAA,CACN,IACE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;"}
1
+ {"version":3,"file":"ChatToolCall.js","sources":["../../../../src/components/library/chat/ChatToolCall.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport Spinner from \"../ui/Spinner\";\nimport {\n WrenchScrewdriverIcon,\n CheckCircleIcon,\n XCircleIcon,\n ChevronDownIcon,\n} from \"@heroicons/react/24/outline\";\n\nexport interface ToolCall {\n id?: string;\n name: string;\n args?: unknown;\n status: \"running\" | \"complete\" | \"error\";\n result?: unknown;\n}\n\nexport interface ChatToolCallProps {\n toolCall: ToolCall;\n}\n\nconst STATUS_CONFIG = {\n running: {\n icon: <Spinner size=\"xs\" tone=\"brand\" label=\"Running\" />,\n text: \"text-brand-600 dark:text-brand-400\",\n bg: \"bg-brand-50 border-brand-100 dark:bg-brand-950/20 dark:border-brand-900/30\",\n label: \"Running\",\n },\n complete: {\n icon: <CheckCircleIcon className=\"h-3.5 w-3.5 text-emerald-500\" />,\n text: \"text-emerald-700 dark:text-emerald-300\",\n bg: \"bg-emerald-50 border-emerald-100 dark:bg-emerald-950/20 dark:border-emerald-900/30\",\n label: \"Complete\",\n },\n error: {\n icon: <XCircleIcon className=\"h-3.5 w-3.5 text-red-500\" />,\n text: \"text-red-700 dark:text-red-300\",\n bg: \"bg-red-50 border-red-100 dark:bg-red-950/20 dark:border-red-900/30\",\n label: \"Failed\",\n },\n};\n\n/**\n * Displays an agent tool call / function execution step.\n */\nexport default function ChatToolCall({ toolCall }: ChatToolCallProps) {\n const [expanded, setExpanded] = useState(false);\n const config = STATUS_CONFIG[toolCall.status] ?? STATUS_CONFIG.running;\n const hasDetails = toolCall.args || toolCall.result;\n\n return (\n <div\n className={[\n \"rounded-lg border text-xs\",\n config.bg,\n ].join(\" \")}\n >\n <button\n type=\"button\"\n onClick={() => hasDetails && setExpanded(!expanded)}\n className={[\n \"flex w-full items-center gap-2 px-3 py-1.5\",\n hasDetails ? \"cursor-pointer\" : \"cursor-default\",\n ].join(\" \")}\n >\n {config.icon}\n <WrenchScrewdriverIcon className=\"h-3 w-3 text-slate-400 dark:text-slate-500\" />\n <span className={[\"font-medium\", config.text].join(\" \")}>\n {toolCall.name}\n </span>\n <span className=\"text-slate-400 dark:text-slate-500\">\n — {config.label}\n </span>\n {hasDetails ? (\n <ChevronDownIcon\n className={[\n \"ml-auto h-3 w-3 text-slate-400 transition-transform dark:text-slate-500\",\n expanded ? \"rotate-180\" : \"\",\n ].join(\" \")}\n />\n ) : null}\n </button>\n\n {expanded && hasDetails ? (\n <div className=\"border-t border-inherit px-3 py-2 font-mono text-[11px] leading-relaxed text-slate-600 dark:text-slate-300\">\n {toolCall.args ? (\n <div className=\"mb-1\">\n <span className=\"font-sans font-semibold text-slate-500 dark:text-slate-400\">\n Args:{\" \"}\n </span>\n {typeof toolCall.args === \"string\"\n ? toolCall.args\n : JSON.stringify(toolCall.args, null, 2)}\n </div>\n ) : null}\n {toolCall.result ? (\n <div>\n <span className=\"font-sans font-semibold text-slate-500 dark:text-slate-400\">\n Result:{\" \"}\n </span>\n {typeof toolCall.result === \"string\"\n ? toolCall.result\n : JSON.stringify(toolCall.result, null, 2)}\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n );\n}\n"],"names":["STATUS_CONFIG","Spinner","jsx","CheckCircleIcon","XCircleIcon","ChatToolCall","toolCall","expanded","setExpanded","useState","config","hasDetails","jsxs","WrenchScrewdriverIcon","ChevronDownIcon"],"mappings":";;;;AAqBA,MAAMA,IAAgB;AAAA,EACpB,SAAS;AAAA,IACP,wBAAOC,GAAA,EAAQ,MAAK,MAAK,MAAK,SAAQ,OAAM,WAAU;AAAA,IACtD,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EAAA;AAAA,EAET,UAAU;AAAA,IACR,MAAM,gBAAAC,EAACC,GAAA,EAAgB,WAAU,+BAAA,CAA+B;AAAA,IAChE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EAAA;AAAA,EAET,OAAO;AAAA,IACL,MAAM,gBAAAD,EAACE,GAAA,EAAY,WAAU,2BAAA,CAA2B;AAAA,IACxD,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EAAA;AAEX;AAKA,SAAwBC,EAAa,EAAE,UAAAC,KAA+B;AACpE,QAAM,CAACC,GAAUC,CAAW,IAAIC,EAAS,EAAK,GACxCC,IAASV,EAAcM,EAAS,MAAM,KAAKN,EAAc,SACzDW,IAAaL,EAAS,QAAQA,EAAS;AAE7C,SACE,gBAAAM;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACAF,EAAO;AAAA,MAAA,EACP,KAAK,GAAG;AAAA,MAEV,UAAA;AAAA,QAAA,gBAAAE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAMD,KAAcH,EAAY,CAACD,CAAQ;AAAA,YAClD,WAAW;AAAA,cACT;AAAA,cACAI,IAAa,mBAAmB;AAAA,YAAA,EAChC,KAAK,GAAG;AAAA,YAET,UAAA;AAAA,cAAAD,EAAO;AAAA,cACR,gBAAAR,EAACW,GAAA,EAAsB,WAAU,6CAAA,CAA6C;AAAA,cAC9E,gBAAAX,EAAC,QAAA,EAAK,WAAW,CAAC,eAAeQ,EAAO,IAAI,EAAE,KAAK,GAAG,GACnD,UAAAJ,EAAS,KAAA,CACZ;AAAA,cACA,gBAAAM,EAAC,QAAA,EAAK,WAAU,sCAAqC,UAAA;AAAA,gBAAA;AAAA,gBAChDF,EAAO;AAAA,cAAA,GACZ;AAAA,cACCC,IACC,gBAAAT;AAAA,gBAACY;AAAA,gBAAA;AAAA,kBACC,WAAW;AAAA,oBACT;AAAA,oBACAP,IAAW,eAAe;AAAA,kBAAA,EAC1B,KAAK,GAAG;AAAA,gBAAA;AAAA,cAAA,IAEV;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAGLA,KAAYI,IACX,gBAAAC,EAAC,OAAA,EAAI,WAAU,8GACZ,UAAA;AAAA,UAAAN,EAAS,OACR,gBAAAM,EAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,8DAA6D,UAAA;AAAA,cAAA;AAAA,cACrE;AAAA,YAAA,GACR;AAAA,YACC,OAAON,EAAS,QAAS,WACtBA,EAAS,OACT,KAAK,UAAUA,EAAS,MAAM,MAAM,CAAC;AAAA,UAAA,EAAA,CAC3C,IACE;AAAA,UACHA,EAAS,SACR,gBAAAM,EAAC,OAAA,EACC,UAAA;AAAA,YAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,8DAA6D,UAAA;AAAA,cAAA;AAAA,cACnE;AAAA,YAAA,GACV;AAAA,YACC,OAAON,EAAS,UAAW,WACxBA,EAAS,SACT,KAAK,UAAUA,EAAS,QAAQ,MAAM,CAAC;AAAA,UAAA,EAAA,CAC7C,IACE;AAAA,QAAA,EAAA,CACN,IACE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;"}
@@ -1,6 +1,7 @@
1
+ export interface ChatTypingIndicatorProps {
2
+ label?: string;
3
+ }
1
4
  /**
2
5
  * Animated typing indicator shown while the agent is processing.
3
6
  */
4
- export default function ChatTypingIndicator({ label }: {
5
- label?: string | undefined;
6
- }): import("react/jsx-runtime").JSX.Element;
7
+ export default function ChatTypingIndicator({ label }: ChatTypingIndicatorProps): import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,6 @@
1
1
  import { jsxs as e, jsx as a } from "react/jsx-runtime";
2
- import "react";
3
2
  import { CpuChipIcon as t } from "@heroicons/react/24/solid";
4
- function r({ label: s = "Thinking" }) {
3
+ function d({ label: s = "Thinking" }) {
5
4
  return /* @__PURE__ */ e("div", { className: "flex items-start gap-3", children: [
6
5
  /* @__PURE__ */ a("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-brand-100 dark:bg-brand-900/40", children: /* @__PURE__ */ a(t, { className: "h-4 w-4 text-brand-600 dark:text-brand-400" }) }),
7
6
  /* @__PURE__ */ e("div", { className: "flex items-center gap-2 rounded-2xl rounded-tl-md bg-slate-100 px-4 py-3 dark:bg-slate-800", children: [
@@ -15,6 +14,6 @@ function r({ label: s = "Thinking" }) {
15
14
  ] });
16
15
  }
17
16
  export {
18
- r as default
17
+ d as default
19
18
  };
20
19
  //# sourceMappingURL=ChatTypingIndicator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatTypingIndicator.js","sources":["../../../../src/components/library/chat/ChatTypingIndicator.jsx"],"sourcesContent":["import React from \"react\";\nimport { CpuChipIcon } from \"@heroicons/react/24/solid\";\n\n/**\n * Animated typing indicator shown while the agent is processing.\n */\nexport default function ChatTypingIndicator({ label = \"Thinking\" }) {\n return (\n <div className=\"flex items-start gap-3\">\n <div className=\"flex h-7 w-7 shrink-0 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 <div className=\"flex items-center gap-2 rounded-2xl rounded-tl-md bg-slate-100 px-4 py-3 dark:bg-slate-800\">\n <div className=\"flex gap-1\">\n <span className=\"h-1.5 w-1.5 animate-bounce rounded-full bg-slate-400 dark:bg-slate-500 [animation-delay:0ms]\" />\n <span className=\"h-1.5 w-1.5 animate-bounce rounded-full bg-slate-400 dark:bg-slate-500 [animation-delay:150ms]\" />\n <span className=\"h-1.5 w-1.5 animate-bounce rounded-full bg-slate-400 dark:bg-slate-500 [animation-delay:300ms]\" />\n </div>\n <span className=\"text-xs text-slate-400 dark:text-slate-500\">{label}</span>\n </div>\n </div>\n );\n}\n"],"names":["ChatTypingIndicator","label","jsxs","jsx","CpuChipIcon"],"mappings":";;;AAMA,SAAwBA,EAAoB,EAAE,OAAAC,IAAQ,cAAc;AAClE,SACE,gBAAAC,EAAC,OAAA,EAAI,WAAU,0BACb,UAAA;AAAA,IAAA,gBAAAC,EAAC,SAAI,WAAU,kGACb,4BAACC,GAAA,EAAY,WAAU,8CAA6C,EAAA,CACtE;AAAA,IACA,gBAAAF,EAAC,OAAA,EAAI,WAAU,8FACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,QAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,+FAAA,CAA+F;AAAA,QAC/G,gBAAAA,EAAC,QAAA,EAAK,WAAU,iGAAA,CAAiG;AAAA,QACjH,gBAAAA,EAAC,QAAA,EAAK,WAAU,iGAAA,CAAiG;AAAA,MAAA,GACnH;AAAA,MACA,gBAAAA,EAAC,QAAA,EAAK,WAAU,8CAA8C,UAAAF,EAAA,CAAM;AAAA,IAAA,EAAA,CACtE;AAAA,EAAA,GACF;AAEJ;"}
1
+ {"version":3,"file":"ChatTypingIndicator.js","sources":["../../../../src/components/library/chat/ChatTypingIndicator.tsx"],"sourcesContent":["import { CpuChipIcon } from \"@heroicons/react/24/solid\";\n\nexport interface ChatTypingIndicatorProps {\n label?: string;\n}\n\n/**\n * Animated typing indicator shown while the agent is processing.\n */\nexport default function ChatTypingIndicator({ label = \"Thinking\" }: ChatTypingIndicatorProps) {\n return (\n <div className=\"flex items-start gap-3\">\n <div className=\"flex h-7 w-7 shrink-0 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 <div className=\"flex items-center gap-2 rounded-2xl rounded-tl-md bg-slate-100 px-4 py-3 dark:bg-slate-800\">\n <div className=\"flex gap-1\">\n <span className=\"h-1.5 w-1.5 animate-bounce rounded-full bg-slate-400 dark:bg-slate-500 [animation-delay:0ms]\" />\n <span className=\"h-1.5 w-1.5 animate-bounce rounded-full bg-slate-400 dark:bg-slate-500 [animation-delay:150ms]\" />\n <span className=\"h-1.5 w-1.5 animate-bounce rounded-full bg-slate-400 dark:bg-slate-500 [animation-delay:300ms]\" />\n </div>\n <span className=\"text-xs text-slate-400 dark:text-slate-500\">{label}</span>\n </div>\n </div>\n );\n}\n"],"names":["ChatTypingIndicator","label","jsxs","jsx","CpuChipIcon"],"mappings":";;AASA,SAAwBA,EAAoB,EAAE,OAAAC,IAAQ,cAAwC;AAC5F,SACE,gBAAAC,EAAC,OAAA,EAAI,WAAU,0BACb,UAAA;AAAA,IAAA,gBAAAC,EAAC,SAAI,WAAU,kGACb,4BAACC,GAAA,EAAY,WAAU,8CAA6C,EAAA,CACtE;AAAA,IACA,gBAAAF,EAAC,OAAA,EAAI,WAAU,8FACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,QAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,+FAAA,CAA+F;AAAA,QAC/G,gBAAAA,EAAC,QAAA,EAAK,WAAU,iGAAA,CAAiG;AAAA,QACjH,gBAAAA,EAAC,QAAA,EAAK,WAAU,iGAAA,CAAiG;AAAA,MAAA,GACnH;AAAA,MACA,gBAAAA,EAAC,QAAA,EAAK,WAAU,8CAA8C,UAAAF,EAAA,CAAM;AAAA,IAAA,EAAA,CACtE;AAAA,EAAA,GACF;AAEJ;"}