@mordn/chat-widget 0.5.1 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +64 -2
- package/dist/index.d.ts +64 -2
- package/dist/index.js +485 -275
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +469 -259
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/ChatWidget.tsx","../src/ui/button.tsx","../src/utils/cn.ts","../src/components/conversation.tsx","../src/ui/avatar.tsx","../src/components/message.tsx","../src/ui/dropdown-menu.tsx","../src/ui/select.tsx","../src/ui/textarea.tsx","../src/components/prompt-input.tsx","../src/components/message-attachments.tsx","../src/components/interface.tsx","../src/components/response.tsx","../src/hooks/use-code-scroll.ts","../src/ui/collapsible.tsx","../src/components/sources.tsx","../src/components/reasoning.tsx","../src/components/loader.tsx","../src/ui/badge.tsx","../src/components/tool.tsx","../src/components/code-block.tsx","../src/components/suggestion2.tsx","../src/contexts/chat-storage-context.tsx","../src/utils/color.ts","../src/hooks/use-chat-theme.ts","../src/utils/models.ts","../src/ui/input.tsx","../src/ui/dialog.tsx"],"sourcesContent":["'use client';\n\n/**\n * @mordn/chat-widget\n *\n * A customizable AI chat widget for React applications.\n *\n * @example\n * ```tsx\n * import { ChatWidget } from '@mordn/chat-widget';\n * import '@mordn/chat-widget/styles.css';\n *\n * export default function App() {\n * return (\n * <ChatWidget\n * userId=\"user-123\"\n * theme={{ mode: 'dark' }}\n * display={{ width: '400px' }}\n * />\n * );\n * }\n * ```\n */\n\n// Main component\nexport { ChatWidget, default } from './ChatWidget';\n\n// Types\nexport type {\n ChatWidgetConfig,\n ThemeConfig,\n FeatureConfig,\n DisplayConfig,\n ChatWidgetSize,\n StarterPrompt,\n} from './types';\n\nexport type { ChatWidgetProps } from './ChatWidget';\n\n// Hooks\nexport * from './hooks/use-chat-theme';\n\n// Contexts\nexport { ChatStorageProvider, useChatStorageKey } from './contexts/chat-storage-context';\n\n// UI Components (for advanced customization)\nexport { Button } from './ui/button';\nexport { Input } from './ui/input';\nexport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from './ui/dialog';\n\n// Starter Messages Component\nexport { StarterMessages, StarterMessageItem } from './components/suggestion2';\n","'use client';\n\n/**\n * ChatWidget - Self-contained AI chat widget component\n *\n * This component can be embedded in any React application.\n * It handles its own state, styling, and API communication.\n *\n * Requirements:\n * - API routes must be set up at /api/chat/*\n * - userId must be provided for user identification\n *\n * Usage:\n * ```tsx\n * import { ChatWidget } from '@/components/chat-widget';\n *\n * export default function Page() {\n * return (\n * <ChatWidget\n * userId=\"user-123\"\n * theme={{ mode: 'dark', primaryColor: '#3b82f6' }}\n * display={{ size: 'default', resizable: true }}\n * />\n * );\n * }\n * ```\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport ChatInterface from './components/interface';\nimport { ChatWidgetConfig, ChatWidgetSize } from './types';\nimport { MessageCircle, X } from 'lucide-react';\nimport { ChatStorageProvider } from './contexts/chat-storage-context';\nimport { toHslTripletIfHex } from './utils/color';\n\nexport interface ChatWidgetProps extends ChatWidgetConfig {\n /**\n * CSS class name for custom styling\n */\n className?: string;\n\n /**\n * Widget ID (for loading config from hosted service later)\n */\n widgetId?: string;\n}\n\nexport function ChatWidget({\n userId,\n conversationId,\n initialMessages,\n className,\n model,\n systemPrompt,\n temperature,\n theme,\n features,\n display,\n starterPrompts,\n onClose,\n headerActions,\n open,\n onOpenChange,\n}: ChatWidgetProps) {\n const layout = display?.layout || 'popup';\n // Controlled mode: consumer provides `open` prop. We delegate state to\n // them and skip the built-in FAB so they can render their own trigger.\n const isControlled = open !== undefined;\n const showToggleButton = !isControlled && display?.showToggleButton !== false;\n // Resize only makes sense for the popup layout — inline/page take their\n // size from the parent container.\n const resizable = layout === 'popup' && display?.resizable !== false;\n const size = display?.size || 'default';\n\n // Open state is meaningful for popup layout only. Inline and page modes\n // are always \"open\" since they're embedded surfaces, not floating panels.\n const [internalIsOpen, setInternalIsOpen] = useState(\n layout !== 'popup' ? true : (display?.defaultOpen || false)\n );\n const isOpen = isControlled ? open : internalIsOpen;\n const setIsOpen = (next: boolean) => {\n if (isControlled) {\n onOpenChange?.(next);\n } else {\n setInternalIsOpen(next);\n }\n };\n const [isResizing, setIsResizing] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Build CSS custom properties from display + theme config.\n //\n // Theme handling: the widget's CSS expects `--chat-primary`, `--chat-background`\n // and `--chat-text` to be HSL TRIPLETS (e.g. \"0 0% 14.5%\") because they're\n // consumed inside `hsl(var(--chat-primary))`. Consumers naturally want to\n // pass hex colors though, so we convert when we can detect hex; anything\n // else is forwarded as-is on the assumption the caller knows what they're\n // doing (e.g. they passed an HSL triplet directly).\n const customStyles = useMemo(() => {\n const styles: Record<string, string> = {};\n\n if (display?.width) {\n styles['--chat-widget-width'] = display.width;\n }\n\n if (theme?.primaryColor) {\n styles['--chat-primary'] = toHslTripletIfHex(theme.primaryColor);\n }\n if (theme?.backgroundColor) {\n styles['--chat-background'] = toHslTripletIfHex(theme.backgroundColor);\n }\n if (theme?.textColor) {\n styles['--chat-text'] = toHslTripletIfHex(theme.textColor);\n }\n if (theme?.tokens) {\n // Tokens are advanced overrides — pass through unchanged. Caller is\n // responsible for the right format (HSL triplet vs full color value).\n Object.assign(styles, theme.tokens);\n }\n\n return styles;\n }, [display?.width, theme?.primaryColor, theme?.backgroundColor, theme?.textColor, theme?.tokens]);\n\n // Handle resize drag - updates CSS variable directly\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n if (!resizable) return;\n e.preventDefault();\n setIsResizing(true);\n document.body.style.cursor = 'ew-resize';\n document.body.style.userSelect = 'none';\n }, [resizable]);\n\n useEffect(() => {\n if (!isResizing) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!containerRef.current) return;\n\n // Calculate new width based on mouse position\n const newWidth = window.innerWidth - e.clientX;\n\n // Resize constraints (reasonable bounds for any chat widget)\n const minWidth = 300;\n const maxWidth = Math.min(800, window.innerWidth * 0.8);\n\n // Clamp to constraints\n const clampedWidth = Math.min(maxWidth, Math.max(minWidth, newWidth));\n\n // Update CSS variable directly on the element\n containerRef.current.style.setProperty('--chat-widget-width', `${clampedWidth}px`);\n };\n\n const handleMouseUp = () => {\n setIsResizing(false);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n };\n\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n };\n }, [isResizing]);\n\n const config = useMemo(() => ({\n userId,\n model,\n systemPrompt,\n temperature,\n theme,\n features,\n starterPrompts,\n }), [userId, model, systemPrompt, temperature, theme, features, starterPrompts]);\n\n const togglePosition = display?.toggleButtonPosition || { bottom: '24px', right: '24px' };\n\n // Common interface — same for all three layouts. The wrapper differs.\n const themeClass = theme?.mode === 'dark' ? 'dark' : '';\n\n // INLINE layout: render the chat interface in place inside the parent. No\n // toggle button, no fixed positioning, no resize. Caller owns sizing via\n // parent CSS (e.g. wrap in a div with h-[600px] w-full).\n if (layout === 'inline') {\n return (\n <ChatStorageProvider userId={userId}>\n <div\n ref={containerRef}\n className={`chat-widget-container chat-widget-inline chat-widget-content ${themeClass} ${className || ''}`}\n style={customStyles as React.CSSProperties}\n >\n <ChatInterface\n id={conversationId}\n initialMessages={initialMessages}\n config={config}\n onClose={onClose}\n headerActions={headerActions}\n />\n </div>\n </ChatStorageProvider>\n );\n }\n\n // PAGE layout: full-viewport chat surface. Same internal interface as\n // inline; the difference is only the wrapper CSS class which sets\n // height: 100dvh and provides a dedicated chat route experience.\n if (layout === 'page') {\n return (\n <ChatStorageProvider userId={userId}>\n <div\n ref={containerRef}\n className={`chat-widget-container chat-widget-page chat-widget-content ${themeClass} ${className || ''}`}\n style={customStyles as React.CSSProperties}\n >\n <ChatInterface\n id={conversationId}\n initialMessages={initialMessages}\n config={config}\n onClose={onClose}\n headerActions={headerActions}\n />\n </div>\n </ChatStorageProvider>\n );\n }\n\n // POPUP layout (default, backward compatible): floating side panel with\n // FAB toggle and slide-in animation.\n return (\n <ChatStorageProvider userId={userId}>\n {showToggleButton && !isOpen && (\n <button\n onClick={() => setIsOpen(true)}\n className=\"fixed z-50 rounded-full bg-primary text-primary-foreground shadow-lg hover:opacity-90 transition-all p-4\"\n style={togglePosition}\n aria-label=\"Open chat\"\n >\n <MessageCircle className=\"h-6 w-6\" />\n </button>\n )}\n\n {isOpen && (\n <div\n ref={containerRef}\n className={`chat-widget-container chat-widget-popup chat-widget-content ${themeClass} ${className || ''}`}\n data-size={size}\n data-resizing={isResizing}\n style={customStyles as React.CSSProperties}\n >\n {resizable && (\n <div\n onMouseDown={handleMouseDown}\n className=\"chat-widget-resize-handle\"\n aria-label=\"Resize chat widget\"\n />\n )}\n <div className=\"w-full h-full overflow-hidden\">\n <ChatInterface\n id={conversationId}\n initialMessages={initialMessages}\n config={config}\n // popup also closes its own panel; consumer's onClose still\n // fires for any cleanup they want (e.g. analytics).\n onClose={() => {\n setIsOpen(false);\n onClose?.();\n }}\n headerActions={headerActions}\n />\n </div>\n </div>\n )}\n </ChatStorageProvider>\n );\n}\n\n// Export ChatWidget as default\nexport default ChatWidget;\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../utils/cn\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\";\n\nimport { Button } from \"../ui/button\";\nimport { cn } from \"../utils/cn\";\nimport { ArrowDownIcon } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\nimport { useCallback } from \"react\";\nimport { StickToBottom, useStickToBottomContext } from \"use-stick-to-bottom\";\n\nexport type ConversationProps = ComponentProps<typeof StickToBottom>;\n\nexport const Conversation = ({ className, ...props }: ConversationProps) => (\n <StickToBottom\n className={cn(\"relative flex-1 overflow-y-auto\", className)}\n initial=\"smooth\"\n resize=\"smooth\"\n role=\"log\"\n {...props}\n />\n);\n\nexport type ConversationContentProps = ComponentProps<\n typeof StickToBottom.Content\n>;\n\nexport const ConversationContent = ({\n className,\n ...props\n}: ConversationContentProps) => (\n <StickToBottom.Content className={cn(\"p-4\", className)} {...props} />\n);\n\nexport type ConversationEmptyStateProps = ComponentProps<\"div\"> & {\n title?: string;\n description?: string;\n icon?: React.ReactNode;\n};\n\nexport const ConversationEmptyState = ({\n className,\n title = \"No messages yet\",\n description = \"Start a conversation to see messages here\",\n icon,\n children,\n ...props\n}: ConversationEmptyStateProps) => (\n <div\n className={cn(\n \"flex size-full flex-col items-center justify-center gap-3 p-8 text-center\",\n className\n )}\n {...props}\n >\n {children ?? (\n <>\n {icon && <div className=\"text-muted-foreground\">{icon}</div>}\n <div className=\"space-y-1\">\n <h3 className=\"font-medium text-sm\">{title}</h3>\n {description && (\n <p className=\"text-muted-foreground text-sm\">{description}</p>\n )}\n </div>\n </>\n )}\n </div>\n);\n\nexport type ConversationScrollButtonProps = ComponentProps<typeof Button>;\n\nexport const ConversationScrollButton = ({\n className,\n ...props\n}: ConversationScrollButtonProps) => {\n const { isAtBottom, scrollToBottom } = useStickToBottomContext();\n\n const handleScrollToBottom = useCallback(() => {\n scrollToBottom();\n }, [scrollToBottom]);\n\n return (\n !isAtBottom && (\n <Button\n className={cn(\n \"absolute bottom-4 left-[50%] translate-x-[-50%] rounded-full\",\n className\n )}\n onClick={handleScrollToBottom}\n size=\"icon\"\n type=\"button\"\n variant=\"outline\"\n {...props}\n >\n <ArrowDownIcon className=\"size-4\" />\n </Button>\n )\n );\n};\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\"\n\nimport { cn } from \"../utils/cn\"\n\nfunction Avatar({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n className={cn(\n \"relative flex size-8 shrink-0 overflow-hidden rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarImage({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\"aspect-square size-full\", className)}\n {...props}\n />\n )\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"bg-muted flex size-full items-center justify-center rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Avatar, AvatarImage, AvatarFallback }\n","import {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"../ui/avatar\";\nimport { cn } from \"../utils/cn\";\nimport type { UIMessage } from \"ai\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport type { ComponentProps, HTMLAttributes } from \"react\";\n\nexport type MessageProps = HTMLAttributes<HTMLDivElement> & {\n from: UIMessage[\"role\"];\n};\n\nexport const Message = ({ className, from, ...props }: MessageProps) => (\n <div\n className={cn(\n \"group flex w-full items-end justify-end gap-2\",\n from === \"user\" ? \"is-user\" : \"is-assistant flex-row-reverse justify-end\",\n className\n )}\n {...props}\n />\n);\n\nconst messageContentVariants = cva(\n \"flex flex-col gap-2 overflow-hidden leading-relaxed chat-message-content\",\n {\n variants: {\n variant: {\n contained: [\n // User messages: compact bubbles on the right (max 85% width)\n \"group-[.is-user]:max-w-[85%] group-[.is-user]:rounded-2xl group-[.is-user]:rounded-br-lg group-[.is-user]:shadow-sm group-[.is-user]:px-4 group-[.is-user]:py-3\",\n // Assistant messages: no bubble, just text on background (max 100% width)\n \"group-[.is-assistant]:max-w-full\",\n ],\n flat: [\n // User messages: compact on the right\n \"group-[.is-user]:max-w-[85%] group-[.is-user]:px-4 group-[.is-user]:py-3 group-[.is-user]:rounded-2xl group-[.is-user]:rounded-br-lg\",\n // Assistant messages: full width\n \"group-[.is-assistant]:max-w-full\",\n ],\n },\n },\n defaultVariants: {\n variant: \"contained\",\n },\n }\n);\n\nexport type MessageContentProps = HTMLAttributes<HTMLDivElement> &\n VariantProps<typeof messageContentVariants>;\n\nexport const MessageContent = ({\n children,\n className,\n variant,\n ...props\n}: MessageContentProps) => (\n <div\n className={cn(messageContentVariants({ variant, className }))}\n {...props}\n >\n {children}\n </div>\n);\n\nexport type MessageAvatarProps = ComponentProps<typeof Avatar> & {\n src: string;\n name?: string;\n};\n\nexport const MessageAvatar = ({\n src,\n name,\n className,\n ...props\n}: MessageAvatarProps) => (\n <Avatar className={cn(\"size-8 ring-1 ring-border\", className)} {...props}>\n <AvatarImage alt=\"\" className=\"mt-0 mb-0\" src={src} />\n <AvatarFallback>{name?.slice(0, 2) || \"ME\"}</AvatarFallback>\n </Avatar>\n);\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\"\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from \"lucide-react\"\n\nimport { cn } from \"../utils/cn\"\n\nfunction DropdownMenu({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n}\n\nfunction DropdownMenuPortal({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {\n return (\n <DropdownMenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />\n )\n}\n\nfunction DropdownMenuTrigger({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {\n return (\n <DropdownMenuPrimitive.Trigger\n data-slot=\"dropdown-menu-trigger\"\n {...props}\n />\n )\n}\n\nfunction DropdownMenuContent({\n className,\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md\",\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n )\n}\n\nfunction DropdownMenuGroup({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {\n return (\n <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n )\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean\n variant?: \"default\" | \"destructive\"\n}) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n )\n}\n\nfunction DropdownMenuRadioGroup({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {\n return (\n <DropdownMenuPrimitive.RadioGroup\n data-slot=\"dropdown-menu-radio-group\"\n {...props}\n />\n )\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {\n return (\n <DropdownMenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CircleIcon className=\"size-2 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n )\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean\n}) {\n return (\n <DropdownMenuPrimitive.Label\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\n \"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"bg-border -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\n \"text-muted-foreground ml-auto text-xs tracking-widest\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuSub({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {\n return <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean\n}) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto size-4\" />\n </DropdownMenuPrimitive.SubTrigger>\n )\n}\n\nfunction DropdownMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n return (\n <DropdownMenuPrimitive.SubContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n DropdownMenu,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as SelectPrimitive from \"@radix-ui/react-select\"\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\"\n\nimport { cn } from \"../utils/cn\"\n\nfunction Select({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />\n}\n\nfunction SelectGroup({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Group>) {\n return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />\n}\n\nfunction SelectValue({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Value>) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />\n}\n\nfunction SelectTrigger({\n className,\n size = \"default\",\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {\n size?: \"sm\" | \"default\"\n}) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n className={cn(\n \"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"size-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n )\n}\n\nfunction SelectContent({\n className,\n children,\n position = \"popper\",\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md\",\n position === \"popper\" &&\n \"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n className\n )}\n position={position}\n {...props}\n >\n <SelectPrimitive.Viewport\n className={cn(\n \"p-1 ai-assistant-scrollbar\",\n position === \"popper\" &&\n \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1\"\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n )\n}\n\nfunction SelectLabel({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Label>) {\n return (\n <SelectPrimitive.Label\n data-slot=\"select-label\"\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2\",\n className\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex size-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n )\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn(\"bg-border pointer-events-none -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectScrollUpButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n return (\n <SelectPrimitive.ScrollUpButton\n data-slot=\"select-scroll-up-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className\n )}\n {...props}\n >\n <ChevronUpIcon className=\"size-4\" />\n </SelectPrimitive.ScrollUpButton>\n )\n}\n\nfunction SelectScrollDownButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n return (\n <SelectPrimitive.ScrollDownButton\n data-slot=\"select-scroll-down-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className\n )}\n {...props}\n >\n <ChevronDownIcon className=\"size-4\" />\n </SelectPrimitive.ScrollDownButton>\n )\n}\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n}\n","import * as React from \"react\"\n\nimport { cn } from \"../utils/cn\"\n\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"border-input placeholder:text-muted-foreground focus-visible:border-ring aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-[14px] transition-colors outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Textarea }\n","\"use client\";\n\nimport { Button } from \"../ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"../ui/dropdown-menu\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../ui/select\";\nimport { Textarea } from \"../ui/textarea\";\nimport { cn } from \"../utils/cn\";\nimport type { ChatStatus, FileUIPart } from \"ai\";\nimport {\n ImageIcon,\n Loader2Icon,\n PaperclipIcon,\n PlusIcon,\n SendIcon,\n SquareIcon,\n XIcon,\n} from \"lucide-react\";\nimport { nanoid } from \"nanoid\";\nimport {\n type ChangeEventHandler,\n Children,\n ClipboardEventHandler,\n type ComponentProps,\n createContext,\n type FormEvent,\n type FormEventHandler,\n Fragment,\n type HTMLAttributes,\n type KeyboardEventHandler,\n type RefObject,\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\ntype AttachmentsContext = {\n files: (FileUIPart & { id: string })[];\n add: (files: File[] | FileList) => void;\n remove: (id: string) => void;\n clear: () => void;\n openFileDialog: () => void;\n fileInputRef: RefObject<HTMLInputElement | null>;\n};\n\nconst AttachmentsContext = createContext<AttachmentsContext | null>(null);\n\nexport const usePromptInputAttachments = () => {\n const context = useContext(AttachmentsContext);\n\n if (!context) {\n throw new Error(\n \"usePromptInputAttachments must be used within a PromptInput\"\n );\n }\n\n return context;\n};\n\nexport type PromptInputAttachmentProps = HTMLAttributes<HTMLDivElement> & {\n data: FileUIPart & { id: string };\n className?: string;\n};\n\nexport function PromptInputAttachment({\n data,\n className,\n ...props\n}: PromptInputAttachmentProps) {\n const attachments = usePromptInputAttachments();\n\n return (\n <div\n className={cn(\"group relative h-14 w-14 rounded-lg border\", className)}\n key={data.id}\n {...props}\n >\n {data.mediaType?.startsWith(\"image/\") && data.url ? (\n <img\n alt={data.filename || \"attachment\"}\n className=\"size-full rounded-lg object-cover\"\n height={56}\n src={data.url}\n width={56}\n />\n ) : (\n <div className=\"flex size-full items-center justify-center text-muted-foreground\">\n <PaperclipIcon className=\"size-4\" />\n </div>\n )}\n <Button\n aria-label=\"Remove attachment\"\n className=\"-right-1 -top-1 absolute h-4 w-4 rounded-full opacity-0 group-hover:opacity-100 p-0 [&_svg]:h-2 [&_svg]:w-2\"\n onClick={() => attachments.remove(data.id)}\n size=\"icon\"\n type=\"button\"\n variant=\"outline\"\n >\n <XIcon className=\"h-2 w-2 shrink-0\" />\n </Button>\n </div>\n );\n}\n\nexport type PromptInputAttachmentsProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n \"children\"\n> & {\n children: (attachment: FileUIPart & { id: string }) => React.ReactNode;\n};\n\nexport function PromptInputAttachments({\n className,\n children,\n ...props\n}: PromptInputAttachmentsProps) {\n const attachments = usePromptInputAttachments();\n const [height, setHeight] = useState(0);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (!el) {\n return;\n }\n const ro = new ResizeObserver(() => {\n setHeight(el.getBoundingClientRect().height);\n });\n ro.observe(el);\n setHeight(el.getBoundingClientRect().height);\n return () => ro.disconnect();\n }, []);\n\n return (\n <div\n aria-live=\"polite\"\n className={cn(\n \"overflow-hidden transition-[height] duration-200 ease-out\",\n className\n )}\n style={{ height: attachments.files.length ? height : 0 }}\n {...props}\n >\n <div className=\"flex flex-wrap gap-2 p-3 pt-3\" ref={contentRef}>\n {attachments.files.map((file) => (\n <Fragment key={file.id}>{children(file)}</Fragment>\n ))}\n </div>\n </div>\n );\n}\n\nexport type PromptInputActionAddAttachmentsProps = ComponentProps<\n typeof DropdownMenuItem\n> & {\n label?: string;\n};\n\nexport const PromptInputActionAddAttachments = ({\n label = \"Add photos or files\",\n ...props\n}: PromptInputActionAddAttachmentsProps) => {\n const attachments = usePromptInputAttachments();\n\n return (\n <DropdownMenuItem\n {...props}\n onSelect={(e) => {\n e.preventDefault();\n attachments.openFileDialog();\n }}\n >\n <ImageIcon className=\"mr-2 size-4\" /> {label}\n </DropdownMenuItem>\n );\n};\n\nexport type PromptInputMessage = {\n text?: string;\n files?: FileUIPart[];\n};\n\nexport type PromptInputProps = Omit<\n HTMLAttributes<HTMLFormElement>,\n \"onSubmit\"\n> & {\n accept?: string; // e.g., \"image/*\" or leave undefined for any\n multiple?: boolean;\n // When true, accepts drops anywhere on document. Default false (opt-in).\n globalDrop?: boolean;\n // Render a hidden input with given name and keep it in sync for native form posts. Default false.\n syncHiddenInput?: boolean;\n // Minimal constraints\n maxFiles?: number;\n maxFileSize?: number; // bytes\n onError?: (err: {\n code: \"max_files\" | \"max_file_size\" | \"accept\";\n message: string;\n }) => void;\n onSubmit: (\n message: PromptInputMessage,\n event: FormEvent<HTMLFormElement>\n ) => void;\n};\n\nexport const PromptInput = ({\n className,\n accept,\n multiple,\n globalDrop,\n syncHiddenInput,\n maxFiles,\n maxFileSize,\n onError,\n onSubmit,\n ...props\n}: PromptInputProps) => {\n const [items, setItems] = useState<(FileUIPart & { id: string })[]>([]);\n const inputRef = useRef<HTMLInputElement | null>(null);\n const anchorRef = useRef<HTMLSpanElement>(null);\n const formRef = useRef<HTMLFormElement | null>(null);\n\n // Find nearest form to scope drag & drop\n useEffect(() => {\n const root = anchorRef.current?.closest(\"form\");\n if (root instanceof HTMLFormElement) {\n formRef.current = root;\n }\n }, []);\n\n const openFileDialog = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n const matchesAccept = useCallback(\n (f: File) => {\n if (!accept || accept.trim() === \"\") {\n return true;\n }\n // Simple check: if accept includes \"image/*\", filter to images; otherwise allow.\n if (accept.includes(\"image/*\")) {\n return f.type.startsWith(\"image/\");\n }\n return true;\n },\n [accept]\n );\n\n const add = useCallback(\n (files: File[] | FileList) => {\n const incoming = Array.from(files);\n const accepted = incoming.filter((f) => matchesAccept(f));\n if (accepted.length === 0) {\n onError?.({\n code: \"accept\",\n message: \"No files match the accepted types.\",\n });\n return;\n }\n const withinSize = (f: File) =>\n maxFileSize ? f.size <= maxFileSize : true;\n const sized = accepted.filter(withinSize);\n if (sized.length === 0 && accepted.length > 0) {\n onError?.({\n code: \"max_file_size\",\n message: \"All files exceed the maximum size.\",\n });\n return;\n }\n setItems((prev) => {\n const capacity =\n typeof maxFiles === \"number\"\n ? Math.max(0, maxFiles - prev.length)\n : undefined;\n const capped =\n typeof capacity === \"number\" ? sized.slice(0, capacity) : sized;\n if (typeof capacity === \"number\" && sized.length > capacity) {\n onError?.({\n code: \"max_files\",\n message: \"Too many files. Some were not added.\",\n });\n }\n const next: (FileUIPart & { id: string })[] = [];\n for (const file of capped) {\n next.push({\n id: nanoid(),\n type: \"file\",\n url: URL.createObjectURL(file),\n mediaType: file.type,\n filename: file.name,\n });\n }\n return prev.concat(next);\n });\n },\n [matchesAccept, maxFiles, maxFileSize, onError]\n );\n\n const remove = useCallback((id: string) => {\n setItems((prev) => {\n const found = prev.find((file) => file.id === id);\n if (found?.url) {\n URL.revokeObjectURL(found.url);\n }\n return prev.filter((file) => file.id !== id);\n });\n }, []);\n\n const clear = useCallback(() => {\n setItems((prev) => {\n for (const file of prev) {\n if (file.url) {\n URL.revokeObjectURL(file.url);\n }\n }\n return [];\n });\n }, []);\n\n // Note: File input cannot be programmatically set for security reasons\n // The syncHiddenInput prop is no longer functional\n useEffect(() => {\n if (syncHiddenInput && inputRef.current) {\n // Clear the input when items are cleared\n if (items.length === 0) {\n inputRef.current.value = \"\";\n }\n }\n }, [items, syncHiddenInput]);\n\n // Attach drop handlers on nearest form and document (opt-in)\n useEffect(() => {\n const form = formRef.current;\n if (!form) {\n return;\n }\n const onDragOver = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) {\n e.preventDefault();\n }\n };\n const onDrop = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) {\n e.preventDefault();\n }\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {\n add(e.dataTransfer.files);\n }\n };\n form.addEventListener(\"dragover\", onDragOver);\n form.addEventListener(\"drop\", onDrop);\n return () => {\n form.removeEventListener(\"dragover\", onDragOver);\n form.removeEventListener(\"drop\", onDrop);\n };\n }, [add]);\n\n useEffect(() => {\n if (!globalDrop) {\n return;\n }\n const onDragOver = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) {\n e.preventDefault();\n }\n };\n const onDrop = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) {\n e.preventDefault();\n }\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {\n add(e.dataTransfer.files);\n }\n };\n document.addEventListener(\"dragover\", onDragOver);\n document.addEventListener(\"drop\", onDrop);\n return () => {\n document.removeEventListener(\"dragover\", onDragOver);\n document.removeEventListener(\"drop\", onDrop);\n };\n }, [add, globalDrop]);\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n if (event.currentTarget.files) {\n add(event.currentTarget.files);\n }\n };\n\n const handleSubmit: FormEventHandler<HTMLFormElement> = (event) => {\n event.preventDefault();\n\n const files: FileUIPart[] = items.map(({ ...item }) => ({\n ...item,\n }));\n\n onSubmit({ text: event.currentTarget.message.value, files }, event);\n \n // Clear files after submission\n clear();\n };\n\n const ctx = useMemo<AttachmentsContext>(\n () => ({\n files: items.map((item) => ({ ...item, id: item.id })),\n add,\n remove,\n clear,\n openFileDialog,\n fileInputRef: inputRef,\n }),\n [items, add, remove, clear, openFileDialog]\n );\n\n return (\n <AttachmentsContext.Provider value={ctx}>\n <span aria-hidden=\"true\" className=\"hidden\" ref={anchorRef} />\n <input\n accept={accept}\n className=\"hidden\"\n multiple={multiple}\n onChange={handleChange}\n ref={inputRef}\n type=\"file\"\n />\n <form\n className={cn(\n // The form border + horizontal divider colour both come from\n // the styles.src.css `.chat-widget-container form ...` rules so\n // there's a single token (--chat-divider) controlling both.\n // No utility classes for border colour here.\n \"w-full overflow-hidden rounded-xl bg-background transition-colors\",\n \"[&:focus-within]:shadow-none [&:focus]:shadow-none shadow-none\",\n className\n )}\n onSubmit={handleSubmit}\n style={{ boxShadow: 'none' }}\n {...props}\n />\n </AttachmentsContext.Provider>\n );\n};\n\nexport type PromptInputBodyProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputBody = ({\n className,\n ...props\n}: PromptInputBodyProps) => (\n <div className={cn(className, \"flex flex-col\")} {...props} />\n);\n\nexport type PromptInputTextareaProps = ComponentProps<typeof Textarea>;\n\nexport const PromptInputTextarea = ({\n onChange,\n className,\n placeholder = \"What would you like to know?\",\n ...props\n}: PromptInputTextareaProps) => {\n const attachments = usePromptInputAttachments();\n\n const handleKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (e) => {\n if (e.key === \"Enter\") {\n // Don't submit if IME composition is in progress\n if (e.nativeEvent.isComposing) {\n return;\n }\n\n if (e.shiftKey) {\n // Allow newline\n return;\n }\n\n // Submit on Enter (without Shift)\n e.preventDefault();\n const form = e.currentTarget.form;\n if (form) {\n form.requestSubmit();\n }\n }\n };\n\n const handlePaste: ClipboardEventHandler<HTMLTextAreaElement> = (event) => {\n const items = event.clipboardData?.items;\n \n if (!items) {\n return;\n }\n\n const files: File[] = [];\n \n for (const item of items) {\n if (item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) {\n files.push(file);\n }\n }\n }\n\n if (files.length > 0) {\n event.preventDefault();\n attachments.add(files);\n }\n };\n\n return (\n <Textarea\n className={cn(\n \"w-full resize-none rounded-none border-none p-3 shadow-none outline-none ring-0\",\n \"field-sizing-content\",\n \"max-h-48 min-h-16\",\n \"focus-visible:ring-0 focus-visible:shadow-none focus:ring-0 focus:shadow-none\",\n className\n )}\n name=\"message\"\n onChange={(e) => {\n onChange?.(e);\n }}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={placeholder}\n {...props}\n />\n );\n};\n\nexport type PromptInputToolbarProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputToolbar = ({\n className,\n ...props\n}: PromptInputToolbarProps) => (\n <div\n className={cn(\"flex items-center justify-between p-1\", className)}\n {...props}\n />\n);\n\nexport type PromptInputToolsProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputTools = ({\n className,\n ...props\n}: PromptInputToolsProps) => (\n <div\n className={cn(\n \"flex items-center gap-1\",\n \"[&_button:first-child]:rounded-bl-xl\",\n className\n )}\n {...props}\n />\n);\n\nexport type PromptInputButtonProps = ComponentProps<typeof Button>;\n\nexport const PromptInputButton = ({\n variant = \"ghost\",\n className,\n size,\n ...props\n}: PromptInputButtonProps) => {\n const newSize =\n (size ?? Children.count(props.children) > 1) ? \"default\" : \"icon\";\n\n return (\n <Button\n className={cn(\n \"shrink-0 gap-1.5 rounded-lg\",\n variant === \"ghost\" && \"text-muted-foreground\",\n newSize === \"default\" && \"px-3\",\n className\n )}\n size={newSize}\n type=\"button\"\n variant={variant}\n {...props}\n />\n );\n};\n\nexport type PromptInputActionMenuProps = ComponentProps<typeof DropdownMenu>;\nexport const PromptInputActionMenu = (props: PromptInputActionMenuProps) => (\n <DropdownMenu {...props} />\n);\n\nexport type PromptInputActionMenuTriggerProps = ComponentProps<\n typeof Button\n> & {};\nexport const PromptInputActionMenuTrigger = ({\n className,\n children,\n ...props\n}: PromptInputActionMenuTriggerProps) => (\n <DropdownMenuTrigger asChild>\n <PromptInputButton className={className} {...props}>\n {children ?? <PlusIcon className=\"size-4\" />}\n </PromptInputButton>\n </DropdownMenuTrigger>\n);\n\nexport type PromptInputActionMenuContentProps = ComponentProps<\n typeof DropdownMenuContent\n>;\nexport const PromptInputActionMenuContent = ({\n className,\n ...props\n}: PromptInputActionMenuContentProps) => (\n <DropdownMenuContent align=\"start\" className={cn(className)} {...props} />\n);\n\nexport type PromptInputActionMenuItemProps = ComponentProps<\n typeof DropdownMenuItem\n>;\nexport const PromptInputActionMenuItem = ({\n className,\n ...props\n}: PromptInputActionMenuItemProps) => (\n <DropdownMenuItem className={cn(className)} {...props} />\n);\n\n// Note: Actions that perform side-effects (like opening a file dialog)\n// are provided in opt-in modules (e.g., prompt-input-attachments).\n\nexport type PromptInputSubmitProps = ComponentProps<typeof Button> & {\n status?: ChatStatus;\n};\n\nexport const PromptInputSubmit = ({\n className,\n variant = \"default\",\n size = \"icon\",\n status,\n children,\n ...props\n}: PromptInputSubmitProps) => {\n let Icon = <SendIcon className=\"size-4\" />;\n\n if (status === \"submitted\") {\n Icon = <Loader2Icon className=\"size-4 animate-spin\" />;\n } else if (status === \"streaming\") {\n Icon = <SquareIcon className=\"size-4\" />;\n } else if (status === \"error\") {\n Icon = <XIcon className=\"size-4\" />;\n }\n\n return (\n <Button\n className={cn(\"gap-1.5 rounded-lg\", className)}\n size={size}\n type=\"submit\"\n variant={variant}\n {...props}\n >\n {children ?? Icon}\n </Button>\n );\n};\n\nexport type PromptInputModelSelectProps = ComponentProps<typeof Select>;\n\nexport const PromptInputModelSelect = (props: PromptInputModelSelectProps) => (\n <Select {...props} />\n);\n\nexport type PromptInputModelSelectTriggerProps = ComponentProps<\n typeof SelectTrigger\n>;\n\nexport const PromptInputModelSelectTrigger = ({\n className,\n ...props\n}: PromptInputModelSelectTriggerProps) => (\n <SelectTrigger\n className={cn(\n \"border-none bg-transparent font-medium text-muted-foreground shadow-none transition-colors\",\n 'hover:bg-accent hover:text-foreground [&[aria-expanded=\"true\"]]:bg-accent [&[aria-expanded=\"true\"]]:text-foreground',\n className\n )}\n {...props}\n />\n);\n\nexport type PromptInputModelSelectContentProps = ComponentProps<\n typeof SelectContent\n>;\n\nexport const PromptInputModelSelectContent = ({\n className,\n ...props\n}: PromptInputModelSelectContentProps) => (\n <SelectContent className={cn(className)} {...props} />\n);\n\nexport type PromptInputModelSelectItemProps = ComponentProps<typeof SelectItem>;\n\nexport const PromptInputModelSelectItem = ({\n className,\n ...props\n}: PromptInputModelSelectItemProps) => (\n <SelectItem className={cn(className)} {...props} />\n);\n\nexport type PromptInputModelSelectValueProps = ComponentProps<\n typeof SelectValue\n>;\n\nexport const PromptInputModelSelectValue = ({\n className,\n ...props\n}: PromptInputModelSelectValueProps) => (\n <SelectValue className={cn(className)} {...props} />\n);\n","import { cn } from \"../utils/cn\";\nimport { PaperclipIcon, DownloadIcon } from \"lucide-react\";\nimport { Button } from \"../ui/button\";\n\nexport type MessageAttachment = {\n filename: string;\n mediaType: string;\n url: string;\n size?: number;\n};\n\nexport type MessageAttachmentsProps = {\n attachments: MessageAttachment[];\n className?: string;\n};\n\nexport function MessageAttachments({ attachments, className }: MessageAttachmentsProps) {\n if (!attachments || attachments.length === 0) {\n return null;\n }\n\n const handleAttachmentClick = (attachment: MessageAttachment) => {\n // Handle different URL types\n if (attachment.url.startsWith('data:')) {\n // For data URLs, create a new window with the image\n const newWindow = window.open('', '_blank');\n if (newWindow) {\n newWindow.document.write(`\n <html>\n <head><title>${attachment.filename}</title></head>\n <body style=\"margin:0; padding:20px; background:#f5f5f5; display:flex; justify-content:center; align-items:center; min-height:100vh;\">\n <img src=\"${attachment.url}\" alt=\"${attachment.filename}\" style=\"max-width:100%; max-height:100%; object-fit:contain; border-radius:8px; box-shadow:0 4px 12px rgba(0,0,0,0.15);\" />\n </body>\n </html>\n `);\n newWindow.document.close();\n }\n } else if (attachment.url.startsWith('blob:')) {\n // For blob URLs, try to open directly\n window.open(attachment.url, '_blank');\n } else if (attachment.url.startsWith('http')) {\n // For HTTP URLs (like Supabase storage), open directly\n window.open(attachment.url, '_blank');\n } else {\n // Fallback: try to open anyway\n window.open(attachment.url, '_blank');\n }\n };\n\n return (\n <div className={cn(\"flex flex-wrap gap-2\", className)}>\n {attachments.map((attachment, index) => (\n <div\n key={index}\n className=\"group relative h-14 w-14 rounded-lg\"\n >\n {attachment.mediaType.startsWith('image/') ? (\n <img\n src={attachment.url}\n alt={attachment.filename}\n className=\"size-full rounded-lg object-cover cursor-pointer hover:opacity-80 transition-opacity\"\n onClick={() => handleAttachmentClick(attachment)}\n />\n ) : (\n <div\n className=\"flex size-full items-center justify-center text-muted-foreground cursor-pointer hover:bg-secondary/50 rounded-lg transition-colors\"\n onClick={() => handleAttachmentClick(attachment)}\n >\n <PaperclipIcon className=\"size-4\" />\n </div>\n )}\n </div>\n ))}\n </div>\n );\n}\n","'use client';\n\nimport {\n Conversation,\n ConversationContent,\n ConversationScrollButton,\n} from './conversation';\nimport { Message, MessageContent } from './message';\nimport {\n PromptInput,\n PromptInputAttachment,\n PromptInputAttachments,\n PromptInputBody,\n PromptInputButton,\n type PromptInputMessage,\n PromptInputModelSelect,\n PromptInputModelSelectContent,\n PromptInputModelSelectItem,\n PromptInputModelSelectTrigger,\n PromptInputModelSelectValue,\n PromptInputSubmit,\n PromptInputTextarea,\n PromptInputToolbar,\n PromptInputTools,\n usePromptInputAttachments,\n} from './prompt-input';\nimport {\n Actions,\n Action,\n} from './actions';\nimport { MessageAttachments } from './message-attachments';\nimport { useState, useEffect, useRef, useMemo, useCallback } from 'react';\nimport { HistoryIcon, MessageSquareIcon, SearchIcon, ChevronRightIcon, PlusIcon, XIcon } from 'lucide-react';\nimport { cn } from '../utils/cn';\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\nimport { Fragment } from 'react';\nimport { useChat } from '@ai-sdk/react';\nimport { DefaultChatTransport } from 'ai';\nimport { Response } from './response';\nimport { GlobeIcon, RefreshCcwIcon, CopyIcon } from 'lucide-react';\nimport {\n Source,\n Sources,\n SourcesContent,\n SourcesTrigger,\n} from './sources';\nimport {\n Reasoning,\n ReasoningContent,\n ReasoningTrigger,\n} from './reasoning';\nimport { Loader } from './loader';\nimport {\n Tool,\n ToolContent,\n ToolHeader,\n ToolInput,\n ToolOutput,\n} from './tool';\nimport {\n Suggestion,\n Suggestions,\n} from './suggestion';\nimport { StarterMessages } from './suggestion2';\nimport { useChatStorageKey } from '../contexts/chat-storage-context';\n\ntype Conversation = {\n id: string;\n title: string;\n model: string;\n created_at: string;\n updated_at: string;\n message_count: number;\n metadata?: any;\n};\n\ntype ChatTab = {\n id: string;\n title: string;\n isActive: boolean;\n};\n\nexport default function ChatInterface({ id, initialMessages, config, onClose, headerActions }: { id?: string; initialMessages?: any[]; config?: any; onClose?: () => void; headerActions?: React.ReactNode } = {}) {\n // Get storage key prefix from context to scope localStorage keys per user/deployment\n const { storageKeyPrefix } = useChatStorageKey();\n const storageKey = (key: string) => storageKeyPrefix ? `chat-${storageKeyPrefix}-${key}` : `chat-${key}`;\n\n // Get theme mode from config (defaults to 'light')\n const themeMode = config?.theme?.mode || 'light';\n\n const [input, setInput] = useState('');\n const [showHistory, setShowHistory] = useState(false);\n const [conversations, setConversations] = useState<Conversation[]>([]);\n const [loadingHistory, setLoadingHistory] = useState(false);\n const [historyLoaded, setHistoryLoaded] = useState(false);\n const [searchQuery, setSearchQuery] = useState('');\n const [uploadError, setUploadError] = useState<string | null>(null);\n\n // Auto-dismiss upload errors after 5 seconds\n useEffect(() => {\n if (uploadError) {\n const timeoutId = setTimeout(() => setUploadError(null), 5000);\n return () => clearTimeout(timeoutId);\n }\n }, [uploadError]);\n\n // Tab management\n const [tabs, setTabs] = useState<ChatTab[]>([]);\n const [activeTabId, setActiveTabId] = useState<string>('');\n const [initialTabCreated, setInitialTabCreated] = useState(false);\n const [isInitializing, setIsInitializing] = useState(true);\n // True while switching tabs and the new tab's messages are mid-fetch.\n // Distinct from isInitializing (which only covers first mount) so the\n // empty-state gate stays closed during tab switches too.\n const [isLoadingMessages, setIsLoadingMessages] = useState(false);\n\n // Track last synced tab to prevent infinite loops\n const lastSyncedTabId = useRef<string>('');\n\n // Ref-based initialization guard to ensure initialization runs only once\n const hasInitialized = useRef(false);\n\n const { messages, sendMessage, status, setMessages } = useChat({\n id: activeTabId || 'temp-id',\n transport: new DefaultChatTransport({\n api: '/api/chat',\n headers: {\n 'X-User-Id': config?.userId || '',\n },\n }),\n // Throttle UI updates to 200ms to prevent hanging during streaming\n experimental_throttle: 200,\n });\n\n const handleSubmit = async (message: PromptInputMessage) => {\n const hasText = Boolean(message.text);\n const hasAttachments = Boolean(message.files?.length);\n\n if (!(hasText || hasAttachments)) {\n return;\n }\n\n // Upload files to Supabase first if there are attachments\n let uploadedFiles: any[] = [];\n if (message.files && message.files.length > 0) {\n try {\n // Upload all files in parallel for better performance\n const uploadPromises = message.files.map(async (file) => {\n try {\n // Convert blob URL back to File object\n const response = await fetch(file.url);\n const blob = await response.blob();\n const fileObj = new File([blob], file.filename || 'unknown', { type: file.mediaType });\n \n // Upload to our API\n const formData = new FormData();\n formData.append('file', fileObj);\n formData.append('conversationId', activeTabId || 'default');\n formData.append('userId', config?.userId || 'demo-user');\n\n const uploadResponse = await fetch('/api/chat/upload', {\n method: 'POST',\n body: formData\n });\n \n if (!uploadResponse.ok) {\n const errorText = await uploadResponse.text();\n console.error(`Upload failed for ${file.filename}:`, errorText);\n return null; // Return null for failed uploads\n }\n \n const uploadResult = await uploadResponse.json();\n return {\n id: (file as any).id || 'unknown',\n type: 'file',\n url: uploadResult.url,\n filename: uploadResult.filename,\n mediaType: uploadResult.mediaType,\n size: uploadResult.size\n };\n } catch (error) {\n console.error(`Error uploading ${file.filename}:`, error);\n return null; // Return null for failed uploads\n }\n });\n\n // Wait for all uploads to complete\n const results = await Promise.all(uploadPromises);\n \n // Filter out null results (failed uploads)\n uploadedFiles = results.filter(result => result !== null);\n\n // If no files uploaded successfully, show error to user\n if (uploadedFiles.length === 0) {\n const errorMsg = 'All file uploads failed. Please try again.';\n setUploadError(errorMsg);\n console.error(errorMsg);\n return;\n }\n\n // If only some files uploaded, show warning to user\n if (uploadedFiles.length < message.files.length) {\n const warnMsg = `Warning: Only ${uploadedFiles.length} of ${message.files.length} files uploaded successfully.`;\n setUploadError(warnMsg);\n console.warn(warnMsg);\n }\n\n } catch (error) {\n const errorMsg = 'Error uploading files. Please try again.';\n setUploadError(errorMsg);\n console.error('Error in file upload process:', error);\n return;\n }\n }\n\n sendMessage({\n text: message.text || 'Sent with attachments',\n files: uploadedFiles\n });\n // Model and webSearch are sent via transport's prepareSendMessagesRequest using refs\n\n // Update tab title if this is the first message (title is still \"New Chat\")\n const activeTab = tabs.find(tab => tab.id === activeTabId);\n if (activeTab && activeTab.title === 'New Chat' && message.text) {\n const newTitle = message.text.slice(0, 100);\n setTabs(prevTabs =>\n prevTabs.map(tab =>\n tab.id === activeTabId\n ? { ...tab, title: newTitle }\n : tab\n )\n );\n }\n\n setInput('');\n // StickToBottom handles scrolling automatically\n };\n\n // Attachment button component that uses the attachments context\n const AttachButton = () => {\n const attachments = usePromptInputAttachments();\n return (\n <PromptInputButton\n variant=\"ghost\"\n onClick={() => attachments.openFileDialog()}\n >\n <PlusIcon className=\"size-4\" />\n </PromptInputButton>\n );\n };\n\n // Centralized function to load a conversation's messages\n const loadConversation = async (conversationId: string) => {\n if (!config?.userId) {\n console.log('Cannot load conversation - no userId');\n return;\n }\n\n try {\n const response = await fetch(`/api/chat/history/${conversationId}?userId=${config.userId}`);\n if (response.ok) {\n const data = await response.json();\n const loadedMessages = data.messages || [];\n\n // Set messages after ensuring activeTabId state has updated\n setTimeout(() => {\n setMessages(loadedMessages);\n }, 0);\n } else if (response.status === 404) {\n // Conversation doesn't exist yet - this is normal for new chats\n console.log('Conversation not found in database yet (new chat)');\n // Clear messages for new chat\n setMessages([]);\n } else {\n console.error('Error loading messages:', response.status, response.statusText);\n }\n } catch (error) {\n console.error('Error loading conversation:', error);\n }\n };\n\n // Tab management functions\n // Generate unique tab ID with better collision avoidance\n const generateUniqueTabId = (): string => {\n let newTabId: string;\n let attempts = 0;\n do {\n newTabId = `chat-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n attempts++;\n } while (tabs.find(tab => tab.id === newTabId) && attempts < 10);\n \n if (attempts >= 10) {\n throw new Error('Unable to generate unique tab ID');\n }\n \n return newTabId;\n };\n\n const createNewTab = useCallback(() => {\n // Additional safeguard: prevent creating tabs if we're still loading\n if (!initialTabCreated) {\n console.warn('Cannot create new tab while initializing');\n return;\n }\n\n // Generate a unique ID for the new tab\n const newTabId = generateUniqueTabId();\n\n setTabs(prevTabs => {\n // Check if tab with this ID already exists using prevTabs (current state)\n const existingTab = prevTabs.find(tab => tab.id === newTabId);\n if (existingTab) {\n console.warn('Tab with ID already exists:', newTabId);\n return prevTabs; // Return unchanged\n }\n\n const newTab: ChatTab = {\n id: newTabId,\n title: 'New Chat',\n isActive: true,\n };\n\n // Save current tab's state before switching\n const updatedTabs = prevTabs.map(tab => ({\n ...tab,\n isActive: false,\n }));\n\n return [...updatedTabs, newTab];\n });\n\n setActiveTabId(newTabId);\n setMessages([]);\n setInput('');\n }, [initialTabCreated]);\n\n const startNewConversation = useCallback(() => {\n createNewTab();\n }, [createNewTab]);\n\n // Clear tabs from localStorage when component unmounts (optional cleanup)\n useEffect(() => {\n return () => {\n // Optional: Clear localStorage on unmount if needed\n // localStorage.removeItem('chat-tabs');\n // localStorage.removeItem('active-tab-id');\n };\n }, []);\n\n const switchToTab = async (tabId: string) => {\n const targetTab = tabs.find(tab => tab.id === tabId);\n if (!targetTab) return;\n\n // Update active tab (metadata only)\n setTabs(prevTabs =>\n prevTabs.map(tab => ({\n ...tab,\n isActive: tab.id === tabId,\n }))\n );\n\n // Change active tab - useChat will reinitialize with new ID. Setting\n // isLoadingMessages immediately gates the starter-prompt empty state\n // so we don't flash it during the API fetch below.\n setActiveTabId(tabId);\n setIsLoadingMessages(true);\n try {\n await loadConversation(tabId);\n } finally {\n setIsLoadingMessages(false);\n }\n };\n\n const closeTab = (tabId: string) => {\n if (tabs.length <= 1) return; // Don't close the last tab\n\n const filteredTabs = tabs.filter(tab => tab.id !== tabId);\n\n // If we're closing the active tab, switch to another tab\n if (tabId === activeTabId && filteredTabs.length > 0) {\n const newActiveTab = filteredTabs[0];\n\n // Update tabs first\n setTabs(filteredTabs.map(tab => ({\n ...tab,\n isActive: tab.id === newActiveTab.id\n })));\n\n // Then switch to the new active tab (this will load messages)\n switchToTab(newActiveTab.id);\n } else {\n // Just remove the tab\n setTabs(filteredTabs);\n }\n\n // Update localStorage immediately when tab is closed\n if (filteredTabs.length > 0) {\n localStorage.setItem(storageKey('tabs'), JSON.stringify(filteredTabs));\n if (tabId === activeTabId) {\n const newActiveTab = filteredTabs[0];\n localStorage.setItem(storageKey('active-tab-id'), newActiveTab.id);\n }\n }\n };\n\n const fetchConversations = async () => {\n if (historyLoaded) return; // Don't reload if already loaded\n if (!config?.userId) {\n return; // Wait for real userId\n }\n\n setLoadingHistory(true);\n try {\n const response = await fetch(`/api/chat/history?userId=${config.userId}`);\n\n if (response.ok) {\n const data = await response.json();\n setConversations(data.conversations || []);\n setHistoryLoaded(true);\n } else {\n console.error('[ChatInterface] Failed to fetch chat history, status:', response.status);\n const errorText = await response.text();\n console.error('[ChatInterface] Error response:', errorText);\n }\n } catch (error) {\n console.error('[ChatInterface] Error fetching chat history:', error);\n } finally {\n setLoadingHistory(false);\n }\n };\n\n useEffect(() => {\n if (showHistory && !historyLoaded && config?.userId) {\n fetchConversations();\n }\n }, [showHistory, historyLoaded, config?.userId]);\n\n // Load conversations on component mount (only when we have a userId)\n useEffect(() => {\n if (!historyLoaded && config?.userId) {\n fetchConversations();\n }\n }, [historyLoaded, config?.userId]);\n\n // Note: Message loading is now handled in switchToTab function\n // useChat will automatically manage messages when activeTabId changes\n\n // Conversation component (StickToBottom) handles auto-scroll automatically during streaming\n\n // Tab Persistence: Save tabs to localStorage with debouncing\n // Only saves metadata (id, title, model, webSearch) - no messages\n useEffect(() => {\n if (tabs.length > 0) {\n const timeoutId = setTimeout(() => {\n localStorage.setItem(storageKey('tabs'), JSON.stringify(tabs));\n localStorage.setItem(storageKey('active-tab-id'), activeTabId);\n }, 500); // Debounce 500ms\n\n return () => clearTimeout(timeoutId);\n }\n }, [tabs, activeTabId, storageKey]);\n\n // Tab Persistence: Load tabs from localStorage on component mount (ONLY ONCE)\n useEffect(() => {\n // Ref-based guard to absolutely ensure this only runs once\n if (hasInitialized.current) return;\n\n const loadInitialTabs = () => {\n const savedTabs = localStorage.getItem(storageKey('tabs'));\n const savedActiveTabId = localStorage.getItem(storageKey('active-tab-id'));\n\n if (savedTabs && savedTabs !== '[]') {\n // Restore saved tabs. Don't flip isInitializing yet — the\n // separate message-load effect below owns that, so the empty\n // state stays gated until we know whether there are messages\n // to render.\n const parsedTabs = JSON.parse(savedTabs);\n setTabs(parsedTabs);\n const activeId = savedActiveTabId || parsedTabs[0]?.id;\n setActiveTabId(activeId);\n setInitialTabCreated(true);\n } else if (!initialTabCreated && tabs.length === 0) {\n // Clean start (no saved tabs) — create one empty tab and finish\n // hydration immediately. There's no remote conversation to wait on.\n const initialTabId = `chat-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n setTabs([{ id: initialTabId, title: 'New Chat', isActive: true }]);\n setActiveTabId(initialTabId);\n setInitialTabCreated(true);\n setIsInitializing(false);\n }\n };\n\n try {\n loadInitialTabs();\n } catch (err) {\n // localStorage parse failure or similar — never leave the widget\n // stuck on the loader; fall back to a clean state.\n console.error('[chat-widget] init failed, falling back to clean start:', err);\n setIsInitializing(false);\n }\n hasInitialized.current = true;\n }, []); // Empty dependency array - run only once on mount\n\n // Load messages for active tab when userId becomes available (on initialization)\n const hasLoadedInitialMessages = useRef(false);\n useEffect(() => {\n if (hasLoadedInitialMessages.current) return; // Only run once\n if (!config?.userId) return; // Wait for userId\n if (!activeTabId) return; // Wait for activeTabId to be set\n\n // Load the conversation messages, then flip isInitializing false. This\n // keeps the empty-state gate closed until the saved messages render —\n // otherwise the starter prompts flash for the duration of the fetch.\n (async () => {\n try {\n await loadConversation(activeTabId);\n } finally {\n hasLoadedInitialMessages.current = true;\n setIsInitializing(false);\n }\n })();\n }, [config?.userId, activeTabId]);\n\n // Handle state updates when active tab changes\n // Messages are loaded in switchToTab function, not here\n useEffect(() => {\n if (isInitializing) return; // Don't sync during initialization\n\n if (activeTabId && tabs.length > 0 && activeTabId !== lastSyncedTabId.current) {\n lastSyncedTabId.current = activeTabId;\n setInput('');\n }\n }, [activeTabId, isInitializing, tabs.length]); // Only depend on activeTabId\n\n // Keep tab titles as default for now\n // Tab title updates removed to fix chat flow\n\n // Group and filter conversations\n const groupedConversations = useMemo(() => {\n const filtered = conversations.filter(conv =>\n searchQuery === '' ||\n conv.title.toLowerCase().includes(searchQuery.toLowerCase())\n );\n\n const groups: { [key: string]: Conversation[] } = {};\n const now = new Date();\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const yesterday = new Date(today);\n yesterday.setDate(yesterday.getDate() - 1);\n\n filtered.forEach(conv => {\n const convDate = new Date(conv.updated_at);\n const diffTime = now.getTime() - convDate.getTime();\n const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));\n const diffWeeks = Math.floor(diffDays / 7);\n const diffMonths = Math.floor(diffDays / 30);\n\n let groupKey: string;\n\n if (convDate >= today) {\n groupKey = 'Today';\n } else if (convDate >= yesterday) {\n groupKey = 'Yesterday';\n } else if (diffDays <= 7) {\n // Show individual days for the past week\n groupKey = `${diffDays}d ago`;\n } else if (diffWeeks <= 4) {\n // Show weeks for the past month\n groupKey = `${diffWeeks}w ago`;\n } else if (diffMonths <= 12) {\n // Show months for the past year\n groupKey = `${diffMonths}mo ago`;\n } else {\n // Show years for older\n const diffYears = Math.floor(diffMonths / 12);\n groupKey = `${diffYears}y ago`;\n }\n\n if (!groups[groupKey]) {\n groups[groupKey] = [];\n }\n groups[groupKey].push(conv);\n });\n\n // Sort group keys in chronological order\n const sortedGroups = Object.entries(groups).sort((a, b) => {\n const order = ['Today', 'Yesterday'];\n const aIndex = order.indexOf(a[0]);\n const bIndex = order.indexOf(b[0]);\n\n if (aIndex !== -1 && bIndex !== -1) return aIndex - bIndex;\n if (aIndex !== -1) return -1;\n if (bIndex !== -1) return 1;\n\n // Extract numbers for comparison\n const aMatch = a[0].match(/(\\d+)([dw]|mo|y)/);\n const bMatch = b[0].match(/(\\d+)([dw]|mo|y)/);\n\n if (aMatch && bMatch) {\n const aNum = parseInt(aMatch[1]);\n const bNum = parseInt(bMatch[1]);\n const aUnit = aMatch[2];\n const bUnit = bMatch[2];\n\n // Convert to days for comparison\n const unitToDays: { [key: string]: number } = { 'd': 1, 'w': 7, 'mo': 30, 'y': 365 };\n const aDays = aNum * unitToDays[aUnit];\n const bDays = bNum * unitToDays[bUnit];\n\n return aDays - bDays;\n }\n\n return 0;\n });\n\n return sortedGroups;\n }, [conversations, searchQuery]);\n\n // Render messages directly - AI SDK Elements components handle optimization\n const renderMessages = () => messages.map((message, index) => {\n // Pre-filter parts once to avoid redundant filtering on every render\n const sourceParts = message.parts?.filter((part) => part.type === 'source-url') || [];\n const fileParts = message.parts?.filter((part) => part.type === 'file') || [];\n\n return (\n <div key={message.id} className={index > 0 ? \"mt-6\" : \"\"}>\n {/* Render sources if available */}\n {message.role === 'assistant' && sourceParts.length > 0 && (\n <Sources>\n <SourcesTrigger count={sourceParts.length} />\n {sourceParts.map((part, i) => (\n <SourcesContent key={`${message.id}-${i}`}>\n <Source\n key={`${message.id}-${i}`}\n href={part.url}\n title={part.url}\n />\n </SourcesContent>\n ))}\n </Sources>\n )}\n\n {/* Render file attachments above the message */}\n {fileParts.length > 0 && (\n <div className={cn(\n \"flex mb-1\",\n message.role === 'user' ? 'justify-end' : 'justify-start'\n )}>\n <MessageAttachments\n attachments={fileParts.map(part => ({\n filename: part.filename || 'unknown',\n mediaType: part.mediaType,\n url: part.url,\n size: (part as any).size || 0\n }))}\n />\n </div>\n )}\n\n {/* Handle messages with parts array */}\n {message.parts ? (\n <div className=\"space-y-2\">\n {message.parts.map((part, i) => {\n switch (part.type) {\n case 'text':\n const isTextStreaming = status === 'streaming' && i === message.parts.length - 1 && message.id === messages.at(-1)?.id;\n return (\n <Fragment key={`${message.id}-${i}`}>\n <Message from={message.role}>\n <MessageContent>\n <Response isStreaming={isTextStreaming}>\n {part.text}\n </Response>\n </MessageContent>\n </Message>\n </Fragment>\n );\n case 'reasoning':\n const isCurrentlyStreaming = status === 'streaming' && i === message.parts.length - 1 && message.id === messages.at(-1)?.id;\n // Show open while streaming, closed when done (users can still manually reopen)\n return (\n <Reasoning\n key={`${message.id}-${i}`}\n className=\"w-full\"\n isStreaming={isCurrentlyStreaming}\n defaultOpen={false}\n open={isCurrentlyStreaming ? true : undefined}\n >\n <ReasoningTrigger />\n <ReasoningContent>{part.text}</ReasoningContent>\n </Reasoning>\n );\n default:\n // Handle tool calls\n if (part.type.startsWith('tool-') || part.type === 'dynamic-tool') {\n const toolPart = part as any; // ToolUIPart | DynamicToolUIPart\n return (\n <Tool key={`${message.id}-${i}`}>\n <ToolHeader\n type={part.type as any}\n toolName={toolPart.toolName}\n state={toolPart.state}\n />\n <ToolContent>\n <ToolInput input={toolPart.input} />\n <ToolOutput output={toolPart.output} errorText={toolPart.errorText} />\n </ToolContent>\n </Tool>\n );\n }\n return null;\n }\n })}\n </div>\n ) : (\n /* Handle standard AI SDK messages with content or text property */\n <Fragment key={`${message.id}-content`}>\n <Message from={message.role}>\n <MessageContent>\n <Response>\n {(message as any).content || (message as any).text}\n </Response>\n </MessageContent>\n </Message>\n </Fragment>\n )}\n </div>\n );\n });\n\n const handleSelectConversation = async (selectedConversationId: string, conversationTitle: string) => {\n if (!config?.userId) return; // Wait for userId\n\n try {\n // Check if this conversation is already open in a tab\n const existingTab = tabs.find(tab => tab.id === selectedConversationId);\n\n if (existingTab) {\n // Just switch to the existing tab\n switchToTab(selectedConversationId);\n setShowHistory(false);\n return;\n }\n\n // Create a new tab with the loaded conversation metadata\n const newTab: ChatTab = {\n id: selectedConversationId,\n title: conversationTitle,\n isActive: true,\n };\n\n setTabs(prevTabs => {\n // Save current tab's metadata before switching\n const updatedTabs = prevTabs.map(tab => ({\n ...tab,\n isActive: false,\n }));\n return [...updatedTabs, newTab];\n });\n\n setActiveTabId(selectedConversationId);\n\n // Load messages using centralized function\n await loadConversation(selectedConversationId);\n\n // Close the history dropdown\n setShowHistory(false);\n } catch (error) {\n console.error('Error loading conversation:', error);\n }\n };\n\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setShowHistory(false);\n }\n };\n\n if (showHistory) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [showHistory]);\n\n return (\n <div className={cn(\"w-full h-full flex flex-col bg-white dark:bg-gray-900 overflow-hidden ring-1 ring-black/[0.02] dark:ring-white/[0.03]\", themeMode === 'dark' && 'dark')}>\n <div\n className={cn(\n \"flex flex-col h-full w-full overflow-hidden relative chat-widget-container\",\n themeMode === 'dark' && 'dark'\n )}\n >\n {/* Header Section with Tabs */}\n <div className=\"flex items-center gap-2 px-3 py-2 border-b backdrop-blur-sm relative z-20\" style={{\n borderColor: 'var(--chat-divider)',\n backgroundColor: 'var(--chat-header-bg)'\n }}>\n {/* Tabs Container with Scroll */}\n <div className=\"flex items-center gap-1 flex-1 min-w-0 overflow-x-auto scrollbar-hide py-0.5 scroll-smooth\">\n {/* Apple-style Tab Pills */}\n {tabs.map((tab, index) => (\n <div\n key={tab.id}\n className=\"relative flex items-center gap-1.5 px-3 py-1.5 rounded-lg cursor-pointer transition-all duration-150 group flex-shrink-0 min-w-0\"\n style={{\n backgroundColor: tab.isActive\n ? ('hsl(var(--chat-surface))')\n : 'transparent',\n color: tab.isActive\n ? ('hsl(var(--chat-text))')\n : ('hsl(var(--chat-text-muted))')\n }}\n onMouseEnter={(e) => {\n if (!tab.isActive) {\n e.currentTarget.style.backgroundColor = 'var(--chat-hover-bg)';\n }\n }}\n onMouseLeave={(e) => {\n if (!tab.isActive) {\n e.currentTarget.style.backgroundColor = 'transparent';\n }\n }}\n onClick={(e) => {\n e.stopPropagation();\n switchToTab(tab.id);\n }}\n >\n {/* Tab Title */}\n <span className=\"truncate max-w-28 text-[13px] font-medium transition-colors\">\n {tab.title}\n </span>\n\n {/* Close Button */}\n {tabs.length > 1 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n closeTab(tab.id);\n }}\n className=\"rounded-lg p-1 transition-all duration-150 flex-shrink-0 -mr-1\"\n style={{\n opacity: tab.isActive ? 0.6 : 0\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.opacity = '1';\n e.currentTarget.style.backgroundColor = 'hsl(var(--chat-surface-hover))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.opacity = tab.isActive ? '0.6' : '0';\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n >\n <XIcon className=\"h-3 w-3\" strokeWidth={2.5} />\n </button>\n )}\n </div>\n ))}\n </div>\n\n {/* Fixed Action Buttons */}\n <div className=\"flex items-center gap-0.5 flex-shrink-0\">\n {/* Plus Icon */}\n <button\n onClick={createNewTab}\n className=\"flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150\"\n style={{\n color: 'hsl(var(--chat-text-muted))'\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.color = 'hsl(var(--chat-text))';\n e.currentTarget.style.backgroundColor = 'hsl(var(--chat-surface))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.color = 'hsl(var(--chat-text-muted))';\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n title=\"New Chat\"\n >\n <PlusIcon className=\"h-4 w-4\" strokeWidth={2} />\n </button>\n\n {/* History Icon */}\n <div className=\"relative\" ref={dropdownRef}>\n <button\n onClick={() => setShowHistory(!showHistory)}\n className=\"flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150\"\n style={{\n color: showHistory\n ? ('hsl(var(--chat-text))')\n : ('hsl(var(--chat-text-muted))'),\n backgroundColor: showHistory\n ? ('hsl(var(--chat-surface))')\n : 'transparent'\n }}\n onMouseEnter={(e) => {\n if (!showHistory) {\n e.currentTarget.style.color = 'hsl(var(--chat-text))';\n e.currentTarget.style.backgroundColor = 'hsl(var(--chat-surface))';\n }\n }}\n onMouseLeave={(e) => {\n if (!showHistory) {\n e.currentTarget.style.color = 'hsl(var(--chat-text-muted))';\n e.currentTarget.style.backgroundColor = 'transparent';\n }\n }}\n title=\"Chat History\"\n >\n <HistoryIcon className=\"h-4 w-4\" strokeWidth={2} />\n </button>\n\n {/* Chat History Dropdown */}\n {showHistory && (\n <div className=\"absolute right-0 top-full mt-1.5 w-72 rounded-xl shadow-[0_4px_24px_rgba(0,0,0,0.08)] dark:shadow-[0_4px_24px_rgba(0,0,0,0.3)] z-50 animate-in fade-in slide-in-from-top-1 duration-150 overflow-hidden\" style={{\n backgroundColor: 'hsl(var(--chat-background))',\n border: `1px solid ${'var(--chat-divider)'}`\n }}>\n {/* Search Header */}\n <div className=\"p-2.5 border-b\" style={{\n borderColor: 'var(--chat-divider)',\n backgroundColor: 'var(--chat-overlay)'\n }}>\n <div className=\"relative\">\n <input\n type=\"text\"\n placeholder=\"Search\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full h-7 px-2.5 text-[13px] rounded-lg focus:outline-none transition-all\"\n style={{\n backgroundColor: 'hsl(var(--chat-surface-deep))',\n border: `1px solid ${'var(--chat-divider)'}`,\n color: 'hsl(var(--chat-text))'\n }}\n />\n </div>\n </div>\n\n {/* Content Area */}\n <div className=\"max-h-[300px] overflow-y-auto ai-assistant-scrollbar\">\n {loadingHistory ? (\n <div className=\"flex items-center justify-center py-12\">\n <div className=\"text-[13px]\" style={{ color: 'hsl(var(--chat-text-muted))' }}>Loading...</div>\n </div>\n ) : conversations.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-12 px-4 text-center\">\n <div className=\"w-12 h-12 rounded-full flex items-center justify-center mb-3\" style={{\n backgroundColor: 'hsl(var(--chat-surface))'\n }}>\n <MessageSquareIcon className=\"h-5 w-5\" style={{ color: 'hsl(var(--chat-text-subtle))' }} strokeWidth={2} />\n </div>\n <p className=\"text-[13px] font-medium mb-0.5\" style={{ color: 'hsl(var(--chat-text))' }}>No Conversations</p>\n <p className=\"text-[12px]\" style={{ color: 'hsl(var(--chat-text-muted))' }}>Start a new chat to begin</p>\n </div>\n ) : groupedConversations.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-12 px-4 text-center\">\n <div className=\"w-12 h-12 rounded-full flex items-center justify-center mb-3\" style={{\n backgroundColor: 'hsl(var(--chat-surface))'\n }}>\n <SearchIcon className=\"h-5 w-5\" style={{ color: 'hsl(var(--chat-text-subtle))' }} strokeWidth={2} />\n </div>\n <p className=\"text-[13px] font-medium mb-0.5\" style={{ color: 'hsl(var(--chat-text))' }}>No Results</p>\n <p className=\"text-[12px]\" style={{ color: 'hsl(var(--chat-text-muted))' }}>Try a different search</p>\n </div>\n ) : (\n <div className=\"py-0.5\">\n {groupedConversations.map(([groupName, groupConversations]) => (\n <div key={groupName} className=\"mb-0.5\">\n {/* Group Header */}\n <div className=\"px-2.5 py-1 sticky top-0 backdrop-blur-sm z-10\" style={{\n backgroundColor: 'var(--chat-header-bg-strong)'\n }}>\n <h3 className=\"text-[10px] font-semibold uppercase tracking-wide\" style={{ color: 'hsl(var(--chat-text-muted))' }}>{groupName}</h3>\n </div>\n\n {/* Conversation Items */}\n <div className=\"px-1 space-y-0.5\">\n {groupConversations.map((conversation) => {\n const isActiveConversation = activeTabId === conversation.id;\n return (\n <button\n key={conversation.id}\n className=\"w-full px-2 py-1 rounded-md transition-all duration-150 text-left group relative\"\n style={{\n backgroundColor: isActiveConversation\n ? ('hsl(var(--chat-surface))')\n : 'transparent'\n }}\n onMouseEnter={(e) => {\n if (!isActiveConversation) {\n e.currentTarget.style.backgroundColor = 'var(--chat-hover-bg)';\n }\n }}\n onMouseLeave={(e) => {\n if (!isActiveConversation) {\n e.currentTarget.style.backgroundColor = 'transparent';\n }\n }}\n onClick={() => handleSelectConversation(conversation.id, conversation.title)}\n >\n <div className=\"flex items-center gap-1.5\">\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-[12px] line-clamp-1 transition-colors leading-tight\" style={{\n fontWeight: isActiveConversation ? 500 : 400,\n color: isActiveConversation\n ? ('hsl(var(--chat-text))')\n : ('hsl(var(--chat-text-strong))')\n }}>\n {conversation.title}\n </p>\n </div>\n <ChevronRightIcon\n className=\"h-3 w-3 transition-all duration-150 flex-shrink-0\"\n style={{\n color: 'hsl(var(--chat-text-subtle))',\n opacity: isActiveConversation ? 1 : 0\n }}\n strokeWidth={2}\n />\n </div>\n </button>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n\n {/* Consumer-supplied header actions (expand, settings, etc.)\n rendered before the close button so they sit to its left. */}\n {headerActions}\n\n {/* Close Chat Widget Button */}\n {onClose && (\n <button\n onClick={onClose}\n className=\"flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150\"\n style={{\n color: 'hsl(var(--chat-text-muted))'\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.color = 'hsl(var(--chat-text))';\n e.currentTarget.style.backgroundColor = 'hsl(var(--chat-surface))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.color = 'hsl(var(--chat-text-muted))';\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n title=\"Close Chat\"\n >\n <XIcon className=\"h-4 w-4\" strokeWidth={2} />\n </button>\n )}\n </div>\n </div>\n\n <Conversation className=\"flex-1 max-w-full ai-assistant-scrollbar\">\n <ConversationContent className=\"max-w-[96%] mx-auto py-6\">\n {renderMessages()}\n {status === 'submitted' && (\n <div className=\"mt-6\">\n <Message from=\"assistant\">\n <MessageContent>\n <Loader size={16} />\n </MessageContent>\n </Message>\n </div>\n )}\n </ConversationContent>\n <ConversationScrollButton />\n </Conversation>\n\n <div className=\"px-5 pb-5\">\n {/* Upload Error Display */}\n {uploadError && (\n <div className=\"mb-3 px-4 py-3 bg-red-50 dark:bg-red-900/20 border border-red-200/60 dark:border-red-800/60 rounded-2xl text-sm text-red-700 dark:text-red-400 shadow-sm\">\n {uploadError}\n </div>\n )}\n\n {/* While we're still hydrating tabs from localStorage and the\n active tab from the API, hold render so we don't briefly flash\n the starter prompts before the previous conversation arrives.\n Once initialised, either show prompts (if truly empty) or the\n messages above this block. */}\n {(isInitializing || isLoadingMessages) ? (\n <div className=\"flex items-center justify-center py-8\" role=\"status\" aria-label=\"Loading conversation\">\n <div className=\"h-4 w-4 rounded-full border-2 border-current border-t-transparent animate-spin\" style={{ color: 'hsl(var(--chat-text-muted))' }} />\n </div>\n ) : (\n messages.length === 0 && status !== 'submitted' && config?.starterPrompts && (\n <StarterMessages\n prompts={config.starterPrompts}\n onPromptSelect={(prompt) => {\n handleSubmit({ text: prompt.title });\n }}\n />\n )\n )}\n\n <PromptInput onSubmit={handleSubmit} globalDrop multiple accept=\"image/*\">\n <PromptInputBody>\n <PromptInputAttachments>\n {(attachment) => <PromptInputAttachment data={attachment} />}\n </PromptInputAttachments>\n <PromptInputTextarea\n onChange={(e) => setInput(e.target.value)}\n value={input}\n />\n </PromptInputBody>\n <PromptInputToolbar>\n <PromptInputTools>\n {config?.features?.fileUpload === true && <AttachButton />}\n </PromptInputTools>\n <PromptInputSubmit disabled={!input} status={status} />\n </PromptInputToolbar>\n </PromptInput>\n </div>\n </div>\n </div>\n );\n}","\"use client\";\n\nimport { cn } from \"../utils/cn\";\nimport { type ComponentProps, memo } from \"react\";\nimport { Streamdown } from \"streamdown\";\nimport { useCodeBlockAutoScroll } from \"../hooks/use-code-scroll\";\n\ntype ResponseProps = ComponentProps<typeof Streamdown> & {\n isStreaming?: boolean;\n};\n\nexport const Response = memo(\n ({ className, isStreaming = false, ...props }: ResponseProps) => {\n const containerRef = useCodeBlockAutoScroll(isStreaming);\n\n return (\n <div ref={containerRef}>\n <Streamdown\n className={cn(\n \"size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0\",\n className\n )}\n {...props}\n />\n </div>\n );\n },\n (prevProps, nextProps) => prevProps.children === nextProps.children\n);\n\nResponse.displayName = \"Response\";\n","import { useEffect, useRef } from \"react\";\n\nexport function useCodeBlockAutoScroll(isStreaming: boolean) {\n const observerRef = useRef<MutationObserver | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!isStreaming || !containerRef.current) {\n // Clean up observer when not streaming\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n return;\n }\n\n // Create observer only when streaming starts\n observerRef.current = new MutationObserver(() => {\n if (!containerRef.current) return;\n\n const codeBlocks = containerRef.current.querySelectorAll(\"pre\");\n codeBlocks.forEach((pre) => {\n pre.scrollTop = pre.scrollHeight;\n });\n });\n\n // Observe the container for changes\n observerRef.current.observe(containerRef.current, {\n childList: true,\n subtree: true,\n characterData: true,\n });\n\n return () => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n }\n };\n }, [isStreaming]);\n\n return containerRef;\n}\n","\"use client\"\n\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\"\n\nfunction Collapsible({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />\n}\n\nfunction CollapsibleTrigger({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {\n return (\n <CollapsiblePrimitive.CollapsibleTrigger\n data-slot=\"collapsible-trigger\"\n {...props}\n />\n )\n}\n\nfunction CollapsibleContent({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {\n return (\n <CollapsiblePrimitive.CollapsibleContent\n data-slot=\"collapsible-content\"\n {...props}\n />\n )\n}\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent }\n","\"use client\";\n\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../ui/collapsible\";\nimport { cn } from \"../utils/cn\";\nimport { BookIcon, ChevronDownIcon } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\n\nexport type SourcesProps = ComponentProps<\"div\">;\n\nexport const Sources = ({ className, ...props }: SourcesProps) => (\n <Collapsible\n className={cn(\"not-prose mb-4 text-primary text-xs\", className)}\n {...props}\n />\n);\n\nexport type SourcesTriggerProps = ComponentProps<typeof CollapsibleTrigger> & {\n count: number;\n};\n\nexport const SourcesTrigger = ({\n className,\n count,\n children,\n ...props\n}: SourcesTriggerProps) => (\n <CollapsibleTrigger\n className={cn(\"flex items-center gap-2\", className)}\n {...props}\n >\n {children ?? (\n <>\n <p className=\"font-medium\">Used {count} sources</p>\n <ChevronDownIcon className=\"h-4 w-4\" />\n </>\n )}\n </CollapsibleTrigger>\n);\n\nexport type SourcesContentProps = ComponentProps<typeof CollapsibleContent>;\n\nexport const SourcesContent = ({\n className,\n ...props\n}: SourcesContentProps) => (\n <CollapsibleContent\n className={cn(\n \"mt-3 flex w-fit flex-col gap-2\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className\n )}\n {...props}\n />\n);\n\nexport type SourceProps = ComponentProps<\"a\">;\n\nexport const Source = ({ href, title, children, ...props }: SourceProps) => (\n <a\n className=\"flex items-center gap-2\"\n href={href}\n rel=\"noreferrer\"\n target=\"_blank\"\n {...props}\n >\n {children ?? (\n <>\n <BookIcon className=\"h-4 w-4\" />\n <span className=\"block font-medium\">{title}</span>\n </>\n )}\n </a>\n);\n","\"use client\";\n\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../ui/collapsible\";\nimport { cn } from \"../utils/cn\";\nimport { BrainIcon, ChevronDownIcon } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\nimport { createContext, memo, useContext, useEffect, useState } from \"react\";\nimport { Response } from \"./response\";\n\ntype ReasoningContextValue = {\n isStreaming: boolean;\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n duration: number;\n};\n\nconst ReasoningContext = createContext<ReasoningContextValue | null>(null);\n\nconst useReasoning = () => {\n const context = useContext(ReasoningContext);\n if (!context) {\n throw new Error(\"Reasoning components must be used within Reasoning\");\n }\n return context;\n};\n\nexport type ReasoningProps = ComponentProps<typeof Collapsible> & {\n isStreaming?: boolean;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n duration?: number;\n};\n\nconst AUTO_CLOSE_DELAY = 1000;\nconst MS_IN_S = 1000;\n\nexport const Reasoning = memo(\n ({\n className,\n isStreaming = false,\n open,\n defaultOpen = true,\n onOpenChange,\n duration: durationProp,\n children,\n ...props\n }: ReasoningProps) => {\n const [isOpen, setIsOpen] = useControllableState({\n prop: open,\n defaultProp: defaultOpen,\n onChange: onOpenChange,\n });\n const [duration, setDuration] = useControllableState({\n prop: durationProp,\n defaultProp: undefined,\n });\n\n const [hasAutoClosed, setHasAutoClosed] = useState(false);\n const [startTime, setStartTime] = useState<number | null>(null);\n\n // Track duration when streaming starts and ends\n useEffect(() => {\n if (isStreaming) {\n if (startTime === null) {\n setStartTime(Date.now());\n }\n } else if (startTime !== null) {\n setDuration(Math.ceil((Date.now() - startTime) / MS_IN_S));\n setStartTime(null);\n }\n }, [isStreaming, startTime, setDuration]);\n\n // Auto-open when streaming starts, auto-close when streaming ends (once only)\n // For loaded chats (durationProp is undefined and not streaming), don't auto-close\n useEffect(() => {\n if (defaultOpen && !isStreaming && isOpen && !hasAutoClosed && durationProp !== undefined) {\n // Add a small delay before closing to allow user to see the content\n const timer = setTimeout(() => {\n setIsOpen(false);\n setHasAutoClosed(true);\n }, AUTO_CLOSE_DELAY);\n\n return () => clearTimeout(timer);\n }\n }, [isStreaming, isOpen, defaultOpen, setIsOpen, hasAutoClosed, durationProp]);\n\n const handleOpenChange = (newOpen: boolean) => {\n setIsOpen(newOpen);\n };\n\n return (\n <ReasoningContext.Provider\n value={{ isStreaming, isOpen, setIsOpen, duration }}\n >\n <Collapsible\n className={cn(\"not-prose\", className)}\n onOpenChange={handleOpenChange}\n open={isOpen}\n {...props}\n >\n {children}\n </Collapsible>\n </ReasoningContext.Provider>\n );\n }\n);\n\nexport type ReasoningTriggerProps = ComponentProps<typeof CollapsibleTrigger>;\n\nconst getThinkingMessage = (isStreaming: boolean, duration?: number) => {\n if (isStreaming) {\n return <>Thinking...</>;\n }\n if (duration === undefined) {\n return <>Thought process</>;\n }\n if (duration === 0) {\n return <>Thought process</>;\n }\n return <>Thought for {duration} seconds</>;\n};\n\nexport const ReasoningTrigger = memo(\n ({ className, children, ...props }: ReasoningTriggerProps) => {\n const { isStreaming, isOpen, duration } = useReasoning();\n\n return (\n <CollapsibleTrigger\n className={cn(\n \"flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground\",\n className\n )}\n {...props}\n >\n {children ?? (\n <>\n <BrainIcon className=\"size-4 flex-shrink-0\" />\n {getThinkingMessage(isStreaming, duration)}\n <ChevronDownIcon\n className={cn(\n \"size-4 flex-shrink-0 transition-transform ml-1\",\n isOpen ? \"rotate-180\" : \"rotate-0\"\n )}\n />\n </>\n )}\n </CollapsibleTrigger>\n );\n }\n);\n\nexport type ReasoningContentProps = ComponentProps<\n typeof CollapsibleContent\n> & {\n children: string;\n};\n\nexport const ReasoningContent = memo(\n ({ className, children, ...props }: ReasoningContentProps) => (\n <CollapsibleContent\n className={cn(\n \"mt-4 text-sm\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className\n )}\n {...props}\n >\n <Response className=\"grid gap-2\">{children}</Response>\n </CollapsibleContent>\n )\n);\n\nReasoning.displayName = \"Reasoning\";\nReasoningTrigger.displayName = \"ReasoningTrigger\";\nReasoningContent.displayName = \"ReasoningContent\";\n","import { cn } from \"../utils/cn\";\nimport type { HTMLAttributes } from \"react\";\n\ntype LoaderIconProps = {\n size?: number;\n};\n\nconst LoaderIcon = ({ size = 16 }: LoaderIconProps) => (\n <svg\n height={size}\n strokeLinejoin=\"round\"\n style={{ color: \"currentcolor\" }}\n viewBox=\"0 0 16 16\"\n width={size}\n >\n <title>Loader</title>\n <g clipPath=\"url(#clip0_2393_1490)\">\n <path d=\"M8 0V4\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path\n d=\"M8 16V12\"\n opacity=\"0.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M3.29773 1.52783L5.64887 4.7639\"\n opacity=\"0.9\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M12.7023 1.52783L10.3511 4.7639\"\n opacity=\"0.1\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M12.7023 14.472L10.3511 11.236\"\n opacity=\"0.4\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M3.29773 14.472L5.64887 11.236\"\n opacity=\"0.6\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M15.6085 5.52783L11.8043 6.7639\"\n opacity=\"0.2\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M0.391602 10.472L4.19583 9.23598\"\n opacity=\"0.7\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M15.6085 10.4722L11.8043 9.2361\"\n opacity=\"0.3\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M0.391602 5.52783L4.19583 6.7639\"\n opacity=\"0.8\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n </g>\n <defs>\n <clipPath id=\"clip0_2393_1490\">\n <rect fill=\"white\" height=\"16\" width=\"16\" />\n </clipPath>\n </defs>\n </svg>\n);\n\nexport type LoaderProps = HTMLAttributes<HTMLDivElement> & {\n size?: number;\n};\n\nexport const Loader = ({ className, size = 16, ...props }: LoaderProps) => (\n <div\n className={cn(\n \"inline-flex animate-spin items-center justify-center\",\n className\n )}\n {...props}\n >\n <LoaderIcon size={size} />\n </div>\n);\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../utils/cn\"\n\nconst badgeVariants = cva(\n \"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden\",\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Badge({\n className,\n variant,\n asChild = false,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"span\"\n\n return (\n <Comp\n data-slot=\"badge\"\n className={cn(badgeVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nexport { Badge, badgeVariants }\n","\"use client\";\n\nimport { Badge } from \"../ui/badge\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../ui/collapsible\";\nimport { cn } from \"../utils/cn\";\nimport type { ToolUIPart } from \"ai\";\nimport {\n CheckCircleIcon,\n ChevronDownIcon,\n CircleIcon,\n ClockIcon,\n WrenchIcon,\n XCircleIcon,\n} from \"lucide-react\";\nimport type { ComponentProps, ReactNode } from \"react\";\nimport { isValidElement } from \"react\";\nimport { CodeBlock } from \"./code-block\";\n\nexport type ToolProps = ComponentProps<typeof Collapsible>;\n\nexport const Tool = ({ className, ...props }: ToolProps) => (\n <Collapsible\n className={cn(\"not-prose w-full rounded-md border border-[var(--chat-divider)]\", className)}\n {...props}\n />\n);\n\nexport type ToolHeaderProps = {\n title?: string;\n type: ToolUIPart[\"type\"] | \"dynamic-tool\";\n /**\n * Set when the part is a `dynamic-tool` UIPart (MCP / `dynamicTool()`).\n * For these the `type` is always `\"dynamic-tool\"`, so the actual tool\n * identity lives in `toolName`. When provided, it wins over the parsed\n * type fragment so the header shows e.g. `get_financials` instead of\n * the generic `tool`.\n */\n toolName?: string;\n state: ToolUIPart[\"state\"];\n className?: string;\n};\n\nconst getStatusBadge = (status: ToolUIPart[\"state\"]) => {\n const labels = {\n \"input-streaming\": \"Pending\",\n \"input-available\": \"Running\",\n \"output-available\": \"Completed\",\n \"output-error\": \"Error\",\n } as const;\n\n const icons = {\n \"input-streaming\": <CircleIcon className=\"size-4\" />,\n \"input-available\": <ClockIcon className=\"size-4 animate-pulse\" />,\n \"output-available\": <CheckCircleIcon className=\"size-4 text-green-600\" />,\n \"output-error\": <XCircleIcon className=\"size-4 text-red-600\" />,\n } as const;\n\n return (\n <Badge className=\"gap-1.5 rounded-full text-xs\" variant=\"secondary\">\n {icons[status]}\n {labels[status]}\n </Badge>\n );\n};\n\nexport const ToolHeader = ({\n className,\n title,\n type,\n toolName,\n state,\n ...props\n}: ToolHeaderProps) => (\n <CollapsibleTrigger\n className={cn(\n \"flex w-full items-center justify-between gap-4 p-2\",\n className\n )}\n {...props}\n >\n <div className=\"flex items-center gap-2\">\n <WrenchIcon className=\"size-4 text-muted-foreground\" />\n <span className=\"font-medium text-sm\">\n {title ?? toolName ?? type.split(\"-\").slice(1).join(\"-\")}\n </span>\n {getStatusBadge(state)}\n </div>\n <ChevronDownIcon className=\"size-4 text-muted-foreground transition-transform group-data-[state=open]:rotate-180\" />\n </CollapsibleTrigger>\n);\n\nexport type ToolContentProps = ComponentProps<typeof CollapsibleContent>;\n\nexport const ToolContent = ({ className, ...props }: ToolContentProps) => (\n <CollapsibleContent\n className={cn(\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className\n )}\n {...props}\n />\n);\n\nexport type ToolInputProps = ComponentProps<\"div\"> & {\n input: ToolUIPart[\"input\"];\n};\n\nexport const ToolInput = ({ className, input, ...props }: ToolInputProps) => (\n <div className={cn(\"space-y-2 overflow-hidden p-2\", className)} {...props}>\n <h4 className=\"font-medium text-muted-foreground text-xs uppercase tracking-wide\">\n Parameters\n </h4>\n <div className=\"rounded-md bg-muted/50\">\n <CodeBlock code={JSON.stringify(input, null, 2)} language=\"json\" />\n </div>\n </div>\n);\n\nexport type ToolOutputProps = ComponentProps<\"div\"> & {\n output: ToolUIPart[\"output\"];\n errorText: ToolUIPart[\"errorText\"];\n};\n\nexport const ToolOutput = ({\n className,\n output,\n errorText,\n ...props\n}: ToolOutputProps) => {\n if (!(output || errorText)) {\n return null;\n }\n\n let Output = <div>{output as ReactNode}</div>;\n\n if (typeof output === \"object\" && !isValidElement(output)) {\n Output = (\n <CodeBlock code={JSON.stringify(output, null, 2)} language=\"json\" />\n );\n } else if (typeof output === \"string\") {\n Output = <CodeBlock code={output} language=\"json\" />;\n }\n\n return (\n <div className={cn(\"space-y-2 p-2\", className)} {...props}>\n <h4 className=\"font-medium text-muted-foreground text-xs uppercase tracking-wide\">\n {errorText ? \"Error\" : \"Result\"}\n </h4>\n <div\n className={cn(\n \"overflow-x-auto rounded-md text-xs [&_table]:w-full\",\n errorText\n ? \"bg-destructive/10 text-destructive\"\n : \"bg-muted/50 text-foreground\"\n )}\n >\n {errorText && <div>{errorText}</div>}\n {Output}\n </div>\n </div>\n );\n};\n","\"use client\";\n\nimport { Button } from \"../ui/button\";\nimport { cn } from \"../utils/cn\";\nimport { CheckIcon, CopyIcon } from \"lucide-react\";\nimport type { ComponentProps, HTMLAttributes, ReactNode } from \"react\";\nimport { createContext, useContext, useState } from \"react\";\nimport { Prism as SyntaxHighlighter } from \"react-syntax-highlighter\";\nimport {\n oneDark,\n oneLight,\n} from \"react-syntax-highlighter/dist/esm/styles/prism\";\n\ntype CodeBlockContextType = {\n code: string;\n};\n\nconst CodeBlockContext = createContext<CodeBlockContextType>({\n code: \"\",\n});\n\nexport type CodeBlockProps = HTMLAttributes<HTMLDivElement> & {\n code: string;\n language: string;\n showLineNumbers?: boolean;\n children?: ReactNode;\n};\n\nexport const CodeBlock = ({\n code,\n language,\n showLineNumbers = false,\n className,\n children,\n ...props\n}: CodeBlockProps) => (\n <CodeBlockContext.Provider value={{ code }}>\n <div\n className={cn(\n \"relative w-full overflow-hidden rounded-lg bg-[hsl(var(--chat-text)/0.03)] border border-[var(--chat-divider)]\",\n className\n )}\n {...props}\n >\n <div className=\"relative max-h-96 overflow-y-auto\">\n <SyntaxHighlighter\n className=\"overflow-hidden dark:hidden\"\n codeTagProps={{\n className: \"font-mono text-sm\",\n }}\n customStyle={{\n margin: 0,\n padding: \"1rem\",\n fontSize: \"0.875rem\",\n background: \"transparent\",\n color: \"hsl(var(--chat-text))\",\n border: \"none\",\n }}\n language={language}\n lineNumberStyle={{\n color: \"hsl(var(--chat-text) / 0.4)\",\n paddingRight: \"1rem\",\n minWidth: \"2.5rem\",\n }}\n showLineNumbers={showLineNumbers}\n style={oneLight}\n >\n {code}\n </SyntaxHighlighter>\n <SyntaxHighlighter\n className=\"hidden overflow-hidden dark:block\"\n codeTagProps={{\n className: \"font-mono text-sm\",\n }}\n customStyle={{\n margin: 0,\n padding: \"1rem\",\n fontSize: \"0.875rem\",\n background: \"transparent\",\n color: \"hsl(var(--chat-text))\",\n border: \"none\",\n }}\n language={language}\n lineNumberStyle={{\n color: \"hsl(var(--chat-text) / 0.4)\",\n paddingRight: \"1rem\",\n minWidth: \"2.5rem\",\n }}\n showLineNumbers={showLineNumbers}\n style={oneDark}\n >\n {code}\n </SyntaxHighlighter>\n {children && (\n <div className=\"absolute top-2 right-2 flex items-center gap-2\">\n {children}\n </div>\n )}\n </div>\n </div>\n </CodeBlockContext.Provider>\n);\n\nexport type CodeBlockCopyButtonProps = ComponentProps<typeof Button> & {\n onCopy?: () => void;\n onError?: (error: Error) => void;\n timeout?: number;\n};\n\nexport const CodeBlockCopyButton = ({\n onCopy,\n onError,\n timeout = 2000,\n children,\n className,\n ...props\n}: CodeBlockCopyButtonProps) => {\n const [isCopied, setIsCopied] = useState(false);\n const { code } = useContext(CodeBlockContext);\n\n const copyToClipboard = async () => {\n if (typeof window === \"undefined\" || !navigator.clipboard.writeText) {\n onError?.(new Error(\"Clipboard API not available\"));\n return;\n }\n\n try {\n await navigator.clipboard.writeText(code);\n setIsCopied(true);\n onCopy?.();\n setTimeout(() => setIsCopied(false), timeout);\n } catch (error) {\n onError?.(error as Error);\n }\n };\n\n const Icon = isCopied ? CheckIcon : CopyIcon;\n\n return (\n <Button\n className={cn(\"shrink-0\", className)}\n onClick={copyToClipboard}\n size=\"icon\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <Icon size={14} />}\n </Button>\n );\n};\n","\"use client\";\n\nimport { cn } from \"../utils/cn\";\nimport { type HTMLAttributes } from \"react\";\nimport type { StarterPrompt } from \"../types\";\n\nexport type { StarterPrompt };\n\nexport type StarterMessagesProps = Omit<HTMLAttributes<HTMLDivElement>, 'onSelect'> & {\n prompts: StarterPrompt[];\n onPromptSelect: (prompt: StarterPrompt) => void;\n};\n\nexport function StarterMessages({\n className,\n prompts,\n onPromptSelect,\n ...props\n}: StarterMessagesProps) {\n if (prompts.length === 0) return null;\n\n return (\n <div\n className={cn(\n \"mb-3\",\n className\n )}\n {...props}\n >\n {prompts.map((prompt, index) => (\n <div key={index}>\n <StarterMessageItem\n prompt={prompt}\n onClick={() => onPromptSelect(prompt)}\n />\n {index < prompts.length - 1 && (\n // 1px-tall element used as a divider — same --chat-divider token\n // every other separator in the widget uses, so consumers only\n // need to override one variable to recolour all of them.\n <div className=\"h-px mx-3\" style={{ backgroundColor: 'var(--chat-divider)' }} />\n )}\n </div>\n ))}\n </div>\n );\n}\n\nexport type StarterMessageItemProps = HTMLAttributes<HTMLButtonElement> & {\n prompt: StarterPrompt;\n};\n\nexport function StarterMessageItem({\n className,\n prompt,\n onClick,\n ...props\n}: StarterMessageItemProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n \"w-full text-left px-3 py-2.5 rounded-lg\",\n \"bg-transparent\",\n \"hover:bg-[hsl(var(--chat-text)/0.03)]\",\n \"transition-colors duration-150 ease-out\",\n \"cursor-pointer\",\n className\n )}\n {...props}\n >\n <span className=\"text-[13px] text-[hsl(var(--chat-text)/0.7)]\">\n {prompt.title}\n </span>\n {prompt.subtitle && (\n <span className=\"block text-[11px] text-[hsl(var(--chat-text)/0.4)] mt-0.5\">\n {prompt.subtitle}\n </span>\n )}\n </button>\n );\n}\n","'use client';\n\nimport { createContext, useContext, ReactNode } from 'react';\n\ninterface ChatStorageContextValue {\n storageKeyPrefix: string;\n}\n\nconst ChatStorageContext = createContext<ChatStorageContextValue>({\n storageKeyPrefix: '',\n});\n\nexport function ChatStorageProvider({\n children,\n userId,\n}: {\n children: ReactNode;\n userId?: string;\n}) {\n // Use userId as the storage key prefix to isolate data between users/deployments\n const storageKeyPrefix = userId || '';\n\n return (\n <ChatStorageContext.Provider value={{ storageKeyPrefix }}>\n {children}\n </ChatStorageContext.Provider>\n );\n}\n\nexport function useChatStorageKey() {\n return useContext(ChatStorageContext);\n}\n","/**\n * Convert a `#rrggbb` hex color into the space-separated HSL triplet format\n * the widget's CSS variables consume (e.g. `\"215 20% 25%\"` — used inside\n * `hsl(var(--chat-primary))`). Non-hex inputs (named, rgb(), already-triplet)\n * are returned unchanged so callers can opt out by passing a triplet directly.\n *\n * Kept tiny on purpose: this is the only place hex/rgb conversion happens at\n * runtime. The widget's settings panel has its own copy in use-chat-theme.ts\n * because that path runs before ChatWidget mounts.\n */\nexport function toHslTripletIfHex(value: string): string {\n const trimmed = value.trim();\n const hexMatch = /^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.exec(trimmed);\n if (!hexMatch) return value;\n\n let hex = hexMatch[1];\n if (hex.length === 3) {\n hex = hex.split('').map((c) => c + c).join('');\n }\n\n const r = parseInt(hex.substring(0, 2), 16) / 255;\n const g = parseInt(hex.substring(2, 4), 16) / 255;\n const b = parseInt(hex.substring(4, 6), 16) / 255;\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n\n let h = 0;\n let s = 0;\n if (max !== min) {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r:\n h = ((g - b) / d + (g < b ? 6 : 0)) / 6;\n break;\n case g:\n h = ((b - r) / d + 2) / 6;\n break;\n case b:\n h = ((r - g) / d + 4) / 6;\n break;\n }\n }\n\n return `${Math.round(h * 360)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;\n}\n","import { useState, useEffect } from 'react';\nimport { DEFAULT_MODEL } from '../utils/models';\nimport { useChatStorageKey } from '../contexts/chat-storage-context';\n\n// Helper function to convert HEX to HSL format that Tailwind expects\n// Tailwind expects HSL in format: \"0 0% 0%\" (no hsl() wrapper, space-separated)\nfunction hexToHSL(hex: string): string {\n // Remove # if present\n hex = hex.replace('#', '');\n\n // Convert hex to RGB\n const r = parseInt(hex.substring(0, 2), 16) / 255;\n const g = parseInt(hex.substring(2, 4), 16) / 255;\n const b = parseInt(hex.substring(4, 6), 16) / 255;\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n let h = 0;\n let s = 0;\n const l = (max + min) / 2;\n\n if (max !== min) {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n\n switch (max) {\n case r:\n h = ((g - b) / d + (g < b ? 6 : 0)) / 6;\n break;\n case g:\n h = ((b - r) / d + 2) / 6;\n break;\n case b:\n h = ((r - g) / d + 4) / 6;\n break;\n }\n }\n\n // Convert to Tailwind format: \"hue saturation% lightness%\"\n return `${Math.round(h * 360)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;\n}\n\nexport interface ChatTheme {\n // Light mode colors\n lightPrimary: string; // Primary color (buttons, user messages, accents)\n lightSecondary: string; // Secondary color (backgrounds, surfaces)\n lightText: string; // Text color\n\n // Dark mode colors\n darkPrimary: string; // Primary color in dark mode\n darkSecondary: string; // Secondary color in dark mode\n darkText: string; // Text color in dark mode\n\n // Typography\n fontFamily: string; // Font family for chat text\n fontSize: number; // Font size in pixels (12-18)\n}\n\nexport type ThemeMode = 'light' | 'dark';\n\nexport interface ConversationStarter {\n text: string;\n enabled: boolean;\n}\n\n// Default theme with sensible light and dark mode colors\nconst defaultTheme: ChatTheme = {\n // Light mode\n lightPrimary: '#3b82f6', // Blue\n lightSecondary: '#f5f5f5', // Light gray\n lightText: '#0a0a0a', // Near black\n\n // Dark mode\n darkPrimary: '#3b82f6', // Blue (same as light)\n darkSecondary: '#262626', // Dark gray\n darkText: '#ffffff', // White\n\n // Typography\n fontFamily: 'system-ui',\n fontSize: 14,\n};\n\n// Font options\nexport const fontOptions = [\n { value: 'system-ui', label: 'System Default' },\n { value: 'Inter, sans-serif', label: 'Inter' },\n { value: 'Roboto, sans-serif', label: 'Roboto' },\n { value: 'Open Sans, sans-serif', label: 'Open Sans' },\n { value: 'Lato, sans-serif', label: 'Lato' },\n { value: 'Poppins, sans-serif', label: 'Poppins' },\n { value: 'Montserrat, sans-serif', label: 'Montserrat' },\n { value: 'Georgia, serif', label: 'Georgia' },\n { value: 'ui-monospace, monospace', label: 'Monospace' },\n];\nconst defaultConversationStarters: ConversationStarter[] = [\n { text: 'How can I help you today?', enabled: true },\n { text: 'What features does this product offer?', enabled: true },\n { text: 'Tell me about your capabilities', enabled: true },\n];\nconst defaultModel = DEFAULT_MODEL;\nconst defaultSystemPrompt = 'You are a helpful AI assistant.';\nconst defaultTemperature = 0.7;\nconst defaultThemeMode: ThemeMode = 'light';\n\nexport function useChatTheme() {\n // Get storage key prefix from context to scope localStorage keys per user/deployment\n const { storageKeyPrefix } = useChatStorageKey();\n const keyPrefix = storageKeyPrefix ? `chat-${storageKeyPrefix}-` : 'chat-';\n\n const [theme, setTheme] = useState<ChatTheme>(defaultTheme);\n const [conversationStarters, setConversationStarters] = useState<ConversationStarter[]>(defaultConversationStarters);\n const [model, setModel] = useState<string>(defaultModel);\n const [systemPrompt, setSystemPrompt] = useState<string>(defaultSystemPrompt);\n const [temperature, setTemperature] = useState<number>(defaultTemperature);\n const [themeMode, setThemeMode] = useState<ThemeMode>(defaultThemeMode);\n\n // Load theme from localStorage on mount\n useEffect(() => {\n const savedTheme = localStorage.getItem(`${keyPrefix}theme`);\n if (savedTheme) {\n try {\n setTheme(JSON.parse(savedTheme));\n } catch (error) {\n console.error('Error loading theme:', error);\n }\n }\n\n const savedStarters = localStorage.getItem(`${keyPrefix}conversation-starters`);\n if (savedStarters) {\n try {\n setConversationStarters(JSON.parse(savedStarters));\n } catch (error) {\n console.error('Error loading conversation starters:', error);\n }\n }\n\n const savedModel = localStorage.getItem(`${keyPrefix}model`);\n if (savedModel) {\n try {\n setModel(savedModel);\n } catch (error) {\n console.error('Error loading model:', error);\n }\n }\n\n const savedSystemPrompt = localStorage.getItem(`${keyPrefix}system-prompt`);\n if (savedSystemPrompt) {\n try {\n setSystemPrompt(savedSystemPrompt);\n } catch (error) {\n console.error('Error loading system prompt:', error);\n }\n }\n\n const savedTemperature = localStorage.getItem(`${keyPrefix}temperature`);\n if (savedTemperature) {\n try {\n setTemperature(parseFloat(savedTemperature));\n } catch (error) {\n console.error('Error loading temperature:', error);\n }\n }\n\n const savedThemeMode = localStorage.getItem(`${keyPrefix}theme-mode`);\n if (savedThemeMode) {\n try {\n setThemeMode(savedThemeMode as ThemeMode);\n } catch (error) {\n console.error('Error loading theme mode:', error);\n }\n }\n\n // Listen for changes from other components (same page via custom events)\n const handleThemeChange = (e: Event) => {\n const customEvent = e as CustomEvent;\n setTheme(customEvent.detail);\n };\n\n const handleStartersChange = (e: Event) => {\n const customEvent = e as CustomEvent;\n setConversationStarters(customEvent.detail);\n };\n\n const handleSystemPromptChange = (e: Event) => {\n const customEvent = e as CustomEvent;\n setSystemPrompt(customEvent.detail);\n };\n\n const handleModelChange = (e: Event) => {\n const customEvent = e as CustomEvent;\n setModel(customEvent.detail);\n };\n\n const handleTemperatureChange = (e: Event) => {\n const customEvent = e as CustomEvent;\n setTemperature(customEvent.detail);\n };\n\n const handleThemeModeChange = (e: Event) => {\n const customEvent = e as CustomEvent;\n setThemeMode(customEvent.detail);\n };\n\n window.addEventListener('chat-theme-change', handleThemeChange);\n window.addEventListener('chat-starters-change', handleStartersChange);\n window.addEventListener('chat-model-change', handleModelChange);\n window.addEventListener('chat-system-prompt-change', handleSystemPromptChange);\n window.addEventListener('chat-temperature-change', handleTemperatureChange);\n window.addEventListener('chat-theme-mode-change', handleThemeModeChange);\n\n return () => {\n window.removeEventListener('chat-theme-change', handleThemeChange);\n window.removeEventListener('chat-starters-change', handleStartersChange);\n window.removeEventListener('chat-model-change', handleModelChange);\n window.removeEventListener('chat-system-prompt-change', handleSystemPromptChange);\n window.removeEventListener('chat-temperature-change', handleTemperatureChange);\n window.removeEventListener('chat-theme-mode-change', handleThemeModeChange);\n };\n }, [keyPrefix]);\n\n // Save theme to localStorage whenever it changes\n useEffect(() => {\n localStorage.setItem(`${keyPrefix}theme`, JSON.stringify(theme));\n\n // Apply CSS variables to the document\n const root = document.documentElement;\n\n // Apply the appropriate colors based on theme mode\n // Convert HEX to HSL format that Tailwind expects\n if (themeMode === 'light') {\n root.style.setProperty('--chat-primary', hexToHSL(theme.lightPrimary));\n root.style.setProperty('--chat-secondary', hexToHSL(theme.lightSecondary));\n root.style.setProperty('--chat-text', hexToHSL(theme.lightText));\n } else {\n root.style.setProperty('--chat-primary', hexToHSL(theme.darkPrimary));\n root.style.setProperty('--chat-secondary', hexToHSL(theme.darkSecondary));\n root.style.setProperty('--chat-text', hexToHSL(theme.darkText));\n }\n\n // Typography (same for both modes)\n root.style.setProperty('--chat-font-family', theme.fontFamily);\n root.style.setProperty('--chat-font-size', `${theme.fontSize}px`);\n\n // Dispatch custom event for same-page sync\n window.dispatchEvent(new CustomEvent('chat-theme-change', { detail: theme }));\n }, [theme, themeMode, keyPrefix]);\n\n // Save conversation starters to localStorage whenever they change\n useEffect(() => {\n localStorage.setItem(`${keyPrefix}conversation-starters`, JSON.stringify(conversationStarters));\n\n // Dispatch custom event for same-page sync\n window.dispatchEvent(new CustomEvent('chat-starters-change', { detail: conversationStarters }));\n }, [conversationStarters, keyPrefix]);\n\n // Save model to localStorage whenever it changes\n useEffect(() => {\n localStorage.setItem(`${keyPrefix}model`, model);\n\n // Dispatch custom event for same-page sync\n window.dispatchEvent(new CustomEvent('chat-model-change', { detail: model }));\n }, [model, keyPrefix]);\n\n // Save system prompt to localStorage whenever it changes\n useEffect(() => {\n localStorage.setItem(`${keyPrefix}system-prompt`, systemPrompt);\n\n // Dispatch custom event for same-page sync\n window.dispatchEvent(new CustomEvent('chat-system-prompt-change', { detail: systemPrompt }));\n }, [systemPrompt, keyPrefix]);\n\n // Save temperature to localStorage whenever it changes\n useEffect(() => {\n localStorage.setItem(`${keyPrefix}temperature`, temperature.toString());\n\n // Dispatch custom event for same-page sync\n window.dispatchEvent(new CustomEvent('chat-temperature-change', { detail: temperature }));\n }, [temperature, keyPrefix]);\n\n // Save theme mode to localStorage whenever it changes\n useEffect(() => {\n localStorage.setItem(`${keyPrefix}theme-mode`, themeMode);\n\n // Dispatch custom event for same-page sync\n window.dispatchEvent(new CustomEvent('chat-theme-mode-change', { detail: themeMode }));\n }, [themeMode, keyPrefix]);\n\n const updateColor = (key: keyof ChatTheme, value: string | number) => {\n setTheme(prev => ({ ...prev, [key]: value }));\n };\n\n const updateLightColors = (colors: { primary?: string; secondary?: string; text?: string }) => {\n setTheme(prev => ({\n ...prev,\n ...(colors.primary && { lightPrimary: colors.primary }),\n ...(colors.secondary && { lightSecondary: colors.secondary }),\n ...(colors.text && { lightText: colors.text }),\n }));\n };\n\n const updateDarkColors = (colors: { primary?: string; secondary?: string; text?: string }) => {\n setTheme(prev => ({\n ...prev,\n ...(colors.primary && { darkPrimary: colors.primary }),\n ...(colors.secondary && { darkSecondary: colors.secondary }),\n ...(colors.text && { darkText: colors.text }),\n }));\n };\n\n const resetTheme = () => {\n setTheme(defaultTheme);\n };\n\n const updateFontSize = (size: number) => {\n setTheme(prev => ({ ...prev, fontSize: size }));\n };\n\n const updateFontFamily = (family: string) => {\n setTheme(prev => ({ ...prev, fontFamily: family }));\n };\n\n const updateConversationStarters = (starters: ConversationStarter[]) => {\n setConversationStarters(starters);\n };\n\n const updateSystemPrompt = (prompt: string) => {\n setSystemPrompt(prompt);\n };\n\n const updateModel = (selectedModel: string) => {\n setModel(selectedModel);\n };\n\n const updateTemperature = (temp: number) => {\n setTemperature(temp);\n };\n\n const updateThemeMode = (mode: ThemeMode) => {\n setThemeMode(mode);\n };\n\n return {\n theme,\n updateColor,\n updateLightColors,\n updateDarkColors,\n resetTheme,\n updateFontSize,\n updateFontFamily,\n conversationStarters,\n updateConversationStarters,\n model,\n updateModel,\n systemPrompt,\n updateSystemPrompt,\n temperature,\n updateTemperature,\n themeMode,\n updateThemeMode,\n };\n}\n","export const MODELS = [\n {\n name: 'GPT-5 Nano',\n value: 'openai/gpt-5-nano'\n },\n // Anthropic models\n {\n name: 'Claude Sonnet 4.5',\n value: 'anthropic/claude-sonnet-4-5',\n },\n {\n name: 'Claude Sonnet 4',\n value: 'anthropic/claude-sonnet-4-0',\n },\n {\n name: 'Claude Haiku 3.5',\n value: 'anthropic/claude-3-5-haiku-latest',\n },\n // OpenAI models\n {\n name: 'GPT-5',\n value: 'openai/gpt-5',\n },\n {\n name: 'GPT-OSS-120B',\n value: 'openai/gpt-oss-120b',\n },\n {\n name: 'GPT 4o',\n value: 'openai/gpt-4o',\n },\n // Google models\n {\n name: 'Gemini 2.5 Flash Lite',\n value: 'google/gemini-2.5-flash-lite',\n },\n {\n name: 'Gemini 2.5 Flash',\n value: 'google/gemini-2.5-flash',\n },\n {\n name: 'Gemini 2.5 Pro',\n value: 'google/gemini-2.5-pro',\n }\n];\n\nexport const DEFAULT_MODEL = MODELS[0].value;\n","import * as React from \"react\"\n\nimport { cn } from \"../utils/cn\"\n\nexport interface InputProps\n extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n \"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nInput.displayName = \"Input\"\n\nexport { Input }\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\"\nimport { XIcon } from \"lucide-react\"\n\nimport { cn } from \"../utils/cn\"\n\nfunction Dialog({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\nfunction DialogTrigger({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\nfunction DialogPortal({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />\n}\n\nfunction DialogClose({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n showCloseButton?: boolean\n}) {\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\"\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_jsx_runtime","import_class_variance_authority","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_lucide_react","import_react","import_jsx_runtime","Icon","import_lucide_react","import_jsx_runtime","import_react","import_lucide_react","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","CollapsibleTrigger","CollapsibleContent","import_lucide_react","import_jsx_runtime","CollapsibleTrigger","CollapsibleContent","import_lucide_react","import_react","import_jsx_runtime","CollapsibleTrigger","CollapsibleContent","import_jsx_runtime","import_react_slot","import_class_variance_authority","import_jsx_runtime","import_lucide_react","import_react","import_lucide_react","import_react","import_jsx_runtime","SyntaxHighlighter","import_jsx_runtime","CollapsibleTrigger","CollapsibleContent","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/ChatWidget.tsx","../src/ui/button.tsx","../src/utils/cn.ts","../src/components/conversation.tsx","../src/ui/avatar.tsx","../src/components/message.tsx","../src/ui/dropdown-menu.tsx","../src/ui/select.tsx","../src/ui/textarea.tsx","../src/components/prompt-input.tsx","../src/components/message-attachments.tsx","../src/components/input-plugin-popover.tsx","../src/components/interface.tsx","../src/components/response.tsx","../src/hooks/use-code-scroll.ts","../src/ui/collapsible.tsx","../src/components/sources.tsx","../src/components/reasoning.tsx","../src/components/loader.tsx","../src/ui/badge.tsx","../src/components/tool.tsx","../src/components/code-block.tsx","../src/components/suggestion2.tsx","../src/contexts/chat-storage-context.tsx","../src/utils/color.ts","../src/hooks/use-chat-theme.ts","../src/utils/models.ts","../src/ui/input.tsx","../src/ui/dialog.tsx"],"sourcesContent":["'use client';\n\n/**\n * @mordn/chat-widget\n *\n * A customizable AI chat widget for React applications.\n *\n * @example\n * ```tsx\n * import { ChatWidget } from '@mordn/chat-widget';\n * import '@mordn/chat-widget/styles.css';\n *\n * export default function App() {\n * return (\n * <ChatWidget\n * userId=\"user-123\"\n * theme={{ mode: 'dark' }}\n * display={{ width: '400px' }}\n * />\n * );\n * }\n * ```\n */\n\n// Main component\nexport { ChatWidget, default } from './ChatWidget';\n\n// Types\nexport type {\n ChatWidgetConfig,\n ThemeConfig,\n FeatureConfig,\n DisplayConfig,\n ChatWidgetSize,\n StarterPrompt,\n InputPlugin,\n InputPluginItem,\n} from './types';\n\nexport type { ChatWidgetProps } from './ChatWidget';\n\n// Hooks\nexport * from './hooks/use-chat-theme';\n\n// Contexts\nexport { ChatStorageProvider, useChatStorageKey } from './contexts/chat-storage-context';\n\n// UI Components (for advanced customization)\nexport { Button } from './ui/button';\nexport { Input } from './ui/input';\nexport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from './ui/dialog';\n\n// Starter Messages Component\nexport { StarterMessages, StarterMessageItem } from './components/suggestion2';\n","'use client';\n\n/**\n * ChatWidget - Self-contained AI chat widget component\n *\n * This component can be embedded in any React application.\n * It handles its own state, styling, and API communication.\n *\n * Requirements:\n * - API routes must be set up at /api/chat/*\n * - userId must be provided for user identification\n *\n * Usage:\n * ```tsx\n * import { ChatWidget } from '@/components/chat-widget';\n *\n * export default function Page() {\n * return (\n * <ChatWidget\n * userId=\"user-123\"\n * theme={{ mode: 'dark', primaryColor: '#3b82f6' }}\n * display={{ size: 'default', resizable: true }}\n * />\n * );\n * }\n * ```\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport ChatInterface from './components/interface';\nimport { ChatWidgetConfig, ChatWidgetSize } from './types';\nimport { MessageCircle, X } from 'lucide-react';\nimport { ChatStorageProvider } from './contexts/chat-storage-context';\nimport { toHslTripletIfHex } from './utils/color';\n\nexport interface ChatWidgetProps extends ChatWidgetConfig {\n /**\n * CSS class name for custom styling\n */\n className?: string;\n\n /**\n * Widget ID (for loading config from hosted service later)\n */\n widgetId?: string;\n}\n\nexport function ChatWidget({\n userId,\n conversationId,\n initialMessages,\n className,\n model,\n systemPrompt,\n temperature,\n theme,\n features,\n display,\n starterPrompts,\n onClose,\n headerActions,\n open,\n onOpenChange,\n inputPlugins,\n}: ChatWidgetProps) {\n const layout = display?.layout || 'popup';\n // Controlled mode: consumer provides `open` prop. We delegate state to\n // them and skip the built-in FAB so they can render their own trigger.\n const isControlled = open !== undefined;\n const showToggleButton = !isControlled && display?.showToggleButton !== false;\n // Resize only makes sense for the popup layout — inline/page take their\n // size from the parent container.\n const resizable = layout === 'popup' && display?.resizable !== false;\n const size = display?.size || 'default';\n\n // Open state is meaningful for popup layout only. Inline and page modes\n // are always \"open\" since they're embedded surfaces, not floating panels.\n const [internalIsOpen, setInternalIsOpen] = useState(\n layout !== 'popup' ? true : (display?.defaultOpen || false)\n );\n const isOpen = isControlled ? open : internalIsOpen;\n const setIsOpen = (next: boolean) => {\n if (isControlled) {\n onOpenChange?.(next);\n } else {\n setInternalIsOpen(next);\n }\n };\n const [isResizing, setIsResizing] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Build CSS custom properties from display + theme config.\n //\n // Theme handling: the widget's CSS expects `--chat-primary`, `--chat-background`\n // and `--chat-text` to be HSL TRIPLETS (e.g. \"0 0% 14.5%\") because they're\n // consumed inside `hsl(var(--chat-primary))`. Consumers naturally want to\n // pass hex colors though, so we convert when we can detect hex; anything\n // else is forwarded as-is on the assumption the caller knows what they're\n // doing (e.g. they passed an HSL triplet directly).\n const customStyles = useMemo(() => {\n const styles: Record<string, string> = {};\n\n if (display?.width) {\n styles['--chat-widget-width'] = display.width;\n }\n\n if (theme?.primaryColor) {\n styles['--chat-primary'] = toHslTripletIfHex(theme.primaryColor);\n }\n if (theme?.backgroundColor) {\n styles['--chat-background'] = toHslTripletIfHex(theme.backgroundColor);\n }\n if (theme?.textColor) {\n styles['--chat-text'] = toHslTripletIfHex(theme.textColor);\n }\n if (theme?.tokens) {\n // Tokens are advanced overrides — pass through unchanged. Caller is\n // responsible for the right format (HSL triplet vs full color value).\n Object.assign(styles, theme.tokens);\n }\n\n return styles;\n }, [display?.width, theme?.primaryColor, theme?.backgroundColor, theme?.textColor, theme?.tokens]);\n\n // Handle resize drag - updates CSS variable directly\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n if (!resizable) return;\n e.preventDefault();\n setIsResizing(true);\n document.body.style.cursor = 'ew-resize';\n document.body.style.userSelect = 'none';\n }, [resizable]);\n\n useEffect(() => {\n if (!isResizing) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!containerRef.current) return;\n\n // Calculate new width based on mouse position\n const newWidth = window.innerWidth - e.clientX;\n\n // Resize constraints (reasonable bounds for any chat widget)\n const minWidth = 300;\n const maxWidth = Math.min(800, window.innerWidth * 0.8);\n\n // Clamp to constraints\n const clampedWidth = Math.min(maxWidth, Math.max(minWidth, newWidth));\n\n // Update CSS variable directly on the element\n containerRef.current.style.setProperty('--chat-widget-width', `${clampedWidth}px`);\n };\n\n const handleMouseUp = () => {\n setIsResizing(false);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n };\n\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n };\n }, [isResizing]);\n\n const config = useMemo(() => ({\n userId,\n model,\n systemPrompt,\n temperature,\n theme,\n features,\n starterPrompts,\n inputPlugins,\n }), [userId, model, systemPrompt, temperature, theme, features, starterPrompts, inputPlugins]);\n\n const togglePosition = display?.toggleButtonPosition || { bottom: '24px', right: '24px' };\n\n // Common interface — same for all three layouts. The wrapper differs.\n const themeClass = theme?.mode === 'dark' ? 'dark' : '';\n\n // INLINE layout: render the chat interface in place inside the parent. No\n // toggle button, no fixed positioning, no resize. Caller owns sizing via\n // parent CSS (e.g. wrap in a div with h-[600px] w-full).\n if (layout === 'inline') {\n return (\n <ChatStorageProvider userId={userId}>\n <div\n ref={containerRef}\n className={`chat-widget-container chat-widget-inline chat-widget-content ${themeClass} ${className || ''}`}\n style={customStyles as React.CSSProperties}\n >\n <ChatInterface\n id={conversationId}\n initialMessages={initialMessages}\n config={config}\n onClose={onClose}\n headerActions={headerActions}\n />\n </div>\n </ChatStorageProvider>\n );\n }\n\n // PAGE layout: full-viewport chat surface. Same internal interface as\n // inline; the difference is only the wrapper CSS class which sets\n // height: 100dvh and provides a dedicated chat route experience.\n if (layout === 'page') {\n return (\n <ChatStorageProvider userId={userId}>\n <div\n ref={containerRef}\n className={`chat-widget-container chat-widget-page chat-widget-content ${themeClass} ${className || ''}`}\n style={customStyles as React.CSSProperties}\n >\n <ChatInterface\n id={conversationId}\n initialMessages={initialMessages}\n config={config}\n onClose={onClose}\n headerActions={headerActions}\n />\n </div>\n </ChatStorageProvider>\n );\n }\n\n // POPUP layout (default, backward compatible): floating side panel with\n // FAB toggle and slide-in animation.\n return (\n <ChatStorageProvider userId={userId}>\n {showToggleButton && !isOpen && (\n <button\n onClick={() => setIsOpen(true)}\n className=\"fixed z-50 rounded-full bg-primary text-primary-foreground shadow-lg hover:opacity-90 transition-all p-4\"\n style={togglePosition}\n aria-label=\"Open chat\"\n >\n <MessageCircle className=\"h-6 w-6\" />\n </button>\n )}\n\n {isOpen && (\n <div\n ref={containerRef}\n className={`chat-widget-container chat-widget-popup chat-widget-content ${themeClass} ${className || ''}`}\n data-size={size}\n data-resizing={isResizing}\n style={customStyles as React.CSSProperties}\n >\n {resizable && (\n <div\n onMouseDown={handleMouseDown}\n className=\"chat-widget-resize-handle\"\n aria-label=\"Resize chat widget\"\n />\n )}\n <div className=\"w-full h-full overflow-hidden\">\n <ChatInterface\n id={conversationId}\n initialMessages={initialMessages}\n config={config}\n // popup also closes its own panel; consumer's onClose still\n // fires for any cleanup they want (e.g. analytics).\n onClose={() => {\n setIsOpen(false);\n onClose?.();\n }}\n headerActions={headerActions}\n />\n </div>\n </div>\n )}\n </ChatStorageProvider>\n );\n}\n\n// Export ChatWidget as default\nexport default ChatWidget;\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../utils/cn\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\";\n\nimport { Button } from \"../ui/button\";\nimport { cn } from \"../utils/cn\";\nimport { ArrowDownIcon } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\nimport { useCallback } from \"react\";\nimport { StickToBottom, useStickToBottomContext } from \"use-stick-to-bottom\";\n\nexport type ConversationProps = ComponentProps<typeof StickToBottom>;\n\nexport const Conversation = ({ className, ...props }: ConversationProps) => (\n <StickToBottom\n className={cn(\"relative flex-1 overflow-y-auto\", className)}\n initial=\"smooth\"\n resize=\"smooth\"\n role=\"log\"\n {...props}\n />\n);\n\nexport type ConversationContentProps = ComponentProps<\n typeof StickToBottom.Content\n>;\n\nexport const ConversationContent = ({\n className,\n ...props\n}: ConversationContentProps) => (\n <StickToBottom.Content className={cn(\"p-4\", className)} {...props} />\n);\n\nexport type ConversationEmptyStateProps = ComponentProps<\"div\"> & {\n title?: string;\n description?: string;\n icon?: React.ReactNode;\n};\n\nexport const ConversationEmptyState = ({\n className,\n title = \"No messages yet\",\n description = \"Start a conversation to see messages here\",\n icon,\n children,\n ...props\n}: ConversationEmptyStateProps) => (\n <div\n className={cn(\n \"flex size-full flex-col items-center justify-center gap-3 p-8 text-center\",\n className\n )}\n {...props}\n >\n {children ?? (\n <>\n {icon && <div className=\"text-muted-foreground\">{icon}</div>}\n <div className=\"space-y-1\">\n <h3 className=\"font-medium text-sm\">{title}</h3>\n {description && (\n <p className=\"text-muted-foreground text-sm\">{description}</p>\n )}\n </div>\n </>\n )}\n </div>\n);\n\nexport type ConversationScrollButtonProps = ComponentProps<typeof Button>;\n\nexport const ConversationScrollButton = ({\n className,\n ...props\n}: ConversationScrollButtonProps) => {\n const { isAtBottom, scrollToBottom } = useStickToBottomContext();\n\n const handleScrollToBottom = useCallback(() => {\n scrollToBottom();\n }, [scrollToBottom]);\n\n return (\n !isAtBottom && (\n <Button\n className={cn(\n \"absolute bottom-4 left-[50%] translate-x-[-50%] rounded-full\",\n className\n )}\n onClick={handleScrollToBottom}\n size=\"icon\"\n type=\"button\"\n variant=\"outline\"\n {...props}\n >\n <ArrowDownIcon className=\"size-4\" />\n </Button>\n )\n );\n};\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\"\n\nimport { cn } from \"../utils/cn\"\n\nfunction Avatar({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n className={cn(\n \"relative flex size-8 shrink-0 overflow-hidden rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarImage({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\"aspect-square size-full\", className)}\n {...props}\n />\n )\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"bg-muted flex size-full items-center justify-center rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Avatar, AvatarImage, AvatarFallback }\n","import {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"../ui/avatar\";\nimport { cn } from \"../utils/cn\";\nimport type { UIMessage } from \"ai\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport type { ComponentProps, HTMLAttributes } from \"react\";\n\nexport type MessageProps = HTMLAttributes<HTMLDivElement> & {\n from: UIMessage[\"role\"];\n};\n\nexport const Message = ({ className, from, ...props }: MessageProps) => (\n <div\n className={cn(\n \"group flex w-full items-end justify-end gap-2\",\n from === \"user\" ? \"is-user\" : \"is-assistant flex-row-reverse justify-end\",\n className\n )}\n {...props}\n />\n);\n\nconst messageContentVariants = cva(\n \"flex flex-col gap-2 overflow-hidden leading-relaxed chat-message-content\",\n {\n variants: {\n variant: {\n contained: [\n // User messages: compact bubbles on the right (max 85% width)\n \"group-[.is-user]:max-w-[85%] group-[.is-user]:rounded-2xl group-[.is-user]:rounded-br-lg group-[.is-user]:shadow-sm group-[.is-user]:px-4 group-[.is-user]:py-3\",\n // Assistant messages: no bubble, just text on background (max 100% width)\n \"group-[.is-assistant]:max-w-full\",\n ],\n flat: [\n // User messages: compact on the right\n \"group-[.is-user]:max-w-[85%] group-[.is-user]:px-4 group-[.is-user]:py-3 group-[.is-user]:rounded-2xl group-[.is-user]:rounded-br-lg\",\n // Assistant messages: full width\n \"group-[.is-assistant]:max-w-full\",\n ],\n },\n },\n defaultVariants: {\n variant: \"contained\",\n },\n }\n);\n\nexport type MessageContentProps = HTMLAttributes<HTMLDivElement> &\n VariantProps<typeof messageContentVariants>;\n\nexport const MessageContent = ({\n children,\n className,\n variant,\n ...props\n}: MessageContentProps) => (\n <div\n className={cn(messageContentVariants({ variant, className }))}\n {...props}\n >\n {children}\n </div>\n);\n\nexport type MessageAvatarProps = ComponentProps<typeof Avatar> & {\n src: string;\n name?: string;\n};\n\nexport const MessageAvatar = ({\n src,\n name,\n className,\n ...props\n}: MessageAvatarProps) => (\n <Avatar className={cn(\"size-8 ring-1 ring-border\", className)} {...props}>\n <AvatarImage alt=\"\" className=\"mt-0 mb-0\" src={src} />\n <AvatarFallback>{name?.slice(0, 2) || \"ME\"}</AvatarFallback>\n </Avatar>\n);\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\"\nimport { CheckIcon, ChevronRightIcon, CircleIcon } from \"lucide-react\"\n\nimport { cn } from \"../utils/cn\"\n\nfunction DropdownMenu({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n}\n\nfunction DropdownMenuPortal({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {\n return (\n <DropdownMenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />\n )\n}\n\nfunction DropdownMenuTrigger({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {\n return (\n <DropdownMenuPrimitive.Trigger\n data-slot=\"dropdown-menu-trigger\"\n {...props}\n />\n )\n}\n\nfunction DropdownMenuContent({\n className,\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md\",\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n )\n}\n\nfunction DropdownMenuGroup({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {\n return (\n <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n )\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean\n variant?: \"default\" | \"destructive\"\n}) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n )\n}\n\nfunction DropdownMenuRadioGroup({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {\n return (\n <DropdownMenuPrimitive.RadioGroup\n data-slot=\"dropdown-menu-radio-group\"\n {...props}\n />\n )\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {\n return (\n <DropdownMenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CircleIcon className=\"size-2 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n )\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean\n}) {\n return (\n <DropdownMenuPrimitive.Label\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\n \"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"bg-border -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\n \"text-muted-foreground ml-auto text-xs tracking-widest\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuSub({\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {\n return <DropdownMenuPrimitive.Sub data-slot=\"dropdown-menu-sub\" {...props} />\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean\n}) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto size-4\" />\n </DropdownMenuPrimitive.SubTrigger>\n )\n}\n\nfunction DropdownMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n return (\n <DropdownMenuPrimitive.SubContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n DropdownMenu,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as SelectPrimitive from \"@radix-ui/react-select\"\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\"\n\nimport { cn } from \"../utils/cn\"\n\nfunction Select({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />\n}\n\nfunction SelectGroup({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Group>) {\n return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />\n}\n\nfunction SelectValue({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Value>) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />\n}\n\nfunction SelectTrigger({\n className,\n size = \"default\",\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {\n size?: \"sm\" | \"default\"\n}) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n className={cn(\n \"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"size-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n )\n}\n\nfunction SelectContent({\n className,\n children,\n position = \"popper\",\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md\",\n position === \"popper\" &&\n \"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n className\n )}\n position={position}\n {...props}\n >\n <SelectPrimitive.Viewport\n className={cn(\n \"p-1 ai-assistant-scrollbar\",\n position === \"popper\" &&\n \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1\"\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n )\n}\n\nfunction SelectLabel({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Label>) {\n return (\n <SelectPrimitive.Label\n data-slot=\"select-label\"\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2\",\n className\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex size-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n )\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn(\"bg-border pointer-events-none -mx-1 my-1 h-px\", className)}\n {...props}\n />\n )\n}\n\nfunction SelectScrollUpButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n return (\n <SelectPrimitive.ScrollUpButton\n data-slot=\"select-scroll-up-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className\n )}\n {...props}\n >\n <ChevronUpIcon className=\"size-4\" />\n </SelectPrimitive.ScrollUpButton>\n )\n}\n\nfunction SelectScrollDownButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n return (\n <SelectPrimitive.ScrollDownButton\n data-slot=\"select-scroll-down-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className\n )}\n {...props}\n >\n <ChevronDownIcon className=\"size-4\" />\n </SelectPrimitive.ScrollDownButton>\n )\n}\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n}\n","import * as React from \"react\"\n\nimport { cn } from \"../utils/cn\"\n\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"border-input placeholder:text-muted-foreground focus-visible:border-ring aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-[14px] transition-colors outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Textarea }\n","\"use client\";\n\nimport { Button } from \"../ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"../ui/dropdown-menu\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../ui/select\";\nimport { Textarea } from \"../ui/textarea\";\nimport { cn } from \"../utils/cn\";\nimport type { ChatStatus, FileUIPart } from \"ai\";\nimport {\n ImageIcon,\n Loader2Icon,\n PaperclipIcon,\n PlusIcon,\n SendIcon,\n SquareIcon,\n XIcon,\n} from \"lucide-react\";\nimport { nanoid } from \"nanoid\";\nimport React, {\n type ChangeEventHandler,\n Children,\n ClipboardEventHandler,\n type ComponentProps,\n createContext,\n type FormEvent,\n type FormEventHandler,\n Fragment,\n type HTMLAttributes,\n type KeyboardEventHandler,\n type RefObject,\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\ntype AttachmentsContext = {\n files: (FileUIPart & { id: string })[];\n add: (files: File[] | FileList) => void;\n remove: (id: string) => void;\n clear: () => void;\n openFileDialog: () => void;\n fileInputRef: RefObject<HTMLInputElement | null>;\n};\n\nconst AttachmentsContext = createContext<AttachmentsContext | null>(null);\n\nexport const usePromptInputAttachments = () => {\n const context = useContext(AttachmentsContext);\n\n if (!context) {\n throw new Error(\n \"usePromptInputAttachments must be used within a PromptInput\"\n );\n }\n\n return context;\n};\n\nexport type PromptInputAttachmentProps = HTMLAttributes<HTMLDivElement> & {\n data: FileUIPart & { id: string };\n className?: string;\n};\n\nexport function PromptInputAttachment({\n data,\n className,\n ...props\n}: PromptInputAttachmentProps) {\n const attachments = usePromptInputAttachments();\n\n return (\n <div\n className={cn(\"group relative h-14 w-14 rounded-lg border\", className)}\n key={data.id}\n {...props}\n >\n {data.mediaType?.startsWith(\"image/\") && data.url ? (\n <img\n alt={data.filename || \"attachment\"}\n className=\"size-full rounded-lg object-cover\"\n height={56}\n src={data.url}\n width={56}\n />\n ) : (\n <div className=\"flex size-full items-center justify-center text-muted-foreground\">\n <PaperclipIcon className=\"size-4\" />\n </div>\n )}\n <Button\n aria-label=\"Remove attachment\"\n className=\"-right-1 -top-1 absolute h-4 w-4 rounded-full opacity-0 group-hover:opacity-100 p-0 [&_svg]:h-2 [&_svg]:w-2\"\n onClick={() => attachments.remove(data.id)}\n size=\"icon\"\n type=\"button\"\n variant=\"outline\"\n >\n <XIcon className=\"h-2 w-2 shrink-0\" />\n </Button>\n </div>\n );\n}\n\nexport type PromptInputAttachmentsProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n \"children\"\n> & {\n children: (attachment: FileUIPart & { id: string }) => React.ReactNode;\n};\n\nexport function PromptInputAttachments({\n className,\n children,\n ...props\n}: PromptInputAttachmentsProps) {\n const attachments = usePromptInputAttachments();\n const [height, setHeight] = useState(0);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (!el) {\n return;\n }\n const ro = new ResizeObserver(() => {\n setHeight(el.getBoundingClientRect().height);\n });\n ro.observe(el);\n setHeight(el.getBoundingClientRect().height);\n return () => ro.disconnect();\n }, []);\n\n return (\n <div\n aria-live=\"polite\"\n className={cn(\n \"overflow-hidden transition-[height] duration-200 ease-out\",\n className\n )}\n style={{ height: attachments.files.length ? height : 0 }}\n {...props}\n >\n <div className=\"flex flex-wrap gap-2 p-3 pt-3\" ref={contentRef}>\n {attachments.files.map((file) => (\n <Fragment key={file.id}>{children(file)}</Fragment>\n ))}\n </div>\n </div>\n );\n}\n\nexport type PromptInputActionAddAttachmentsProps = ComponentProps<\n typeof DropdownMenuItem\n> & {\n label?: string;\n};\n\nexport const PromptInputActionAddAttachments = ({\n label = \"Add photos or files\",\n ...props\n}: PromptInputActionAddAttachmentsProps) => {\n const attachments = usePromptInputAttachments();\n\n return (\n <DropdownMenuItem\n {...props}\n onSelect={(e) => {\n e.preventDefault();\n attachments.openFileDialog();\n }}\n >\n <ImageIcon className=\"mr-2 size-4\" /> {label}\n </DropdownMenuItem>\n );\n};\n\nexport type PromptInputMessage = {\n text?: string;\n files?: FileUIPart[];\n};\n\nexport type PromptInputProps = Omit<\n HTMLAttributes<HTMLFormElement>,\n \"onSubmit\"\n> & {\n accept?: string; // e.g., \"image/*\" or leave undefined for any\n multiple?: boolean;\n // When true, accepts drops anywhere on document. Default false (opt-in).\n globalDrop?: boolean;\n // Render a hidden input with given name and keep it in sync for native form posts. Default false.\n syncHiddenInput?: boolean;\n // Minimal constraints\n maxFiles?: number;\n maxFileSize?: number; // bytes\n onError?: (err: {\n code: \"max_files\" | \"max_file_size\" | \"accept\";\n message: string;\n }) => void;\n onSubmit: (\n message: PromptInputMessage,\n event: FormEvent<HTMLFormElement>\n ) => void;\n};\n\nexport const PromptInput = ({\n className,\n accept,\n multiple,\n globalDrop,\n syncHiddenInput,\n maxFiles,\n maxFileSize,\n onError,\n onSubmit,\n ...props\n}: PromptInputProps) => {\n const [items, setItems] = useState<(FileUIPart & { id: string })[]>([]);\n const inputRef = useRef<HTMLInputElement | null>(null);\n const anchorRef = useRef<HTMLSpanElement>(null);\n const formRef = useRef<HTMLFormElement | null>(null);\n\n // Find nearest form to scope drag & drop\n useEffect(() => {\n const root = anchorRef.current?.closest(\"form\");\n if (root instanceof HTMLFormElement) {\n formRef.current = root;\n }\n }, []);\n\n const openFileDialog = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n const matchesAccept = useCallback(\n (f: File) => {\n if (!accept || accept.trim() === \"\") {\n return true;\n }\n // Simple check: if accept includes \"image/*\", filter to images; otherwise allow.\n if (accept.includes(\"image/*\")) {\n return f.type.startsWith(\"image/\");\n }\n return true;\n },\n [accept]\n );\n\n const add = useCallback(\n (files: File[] | FileList) => {\n const incoming = Array.from(files);\n const accepted = incoming.filter((f) => matchesAccept(f));\n if (accepted.length === 0) {\n onError?.({\n code: \"accept\",\n message: \"No files match the accepted types.\",\n });\n return;\n }\n const withinSize = (f: File) =>\n maxFileSize ? f.size <= maxFileSize : true;\n const sized = accepted.filter(withinSize);\n if (sized.length === 0 && accepted.length > 0) {\n onError?.({\n code: \"max_file_size\",\n message: \"All files exceed the maximum size.\",\n });\n return;\n }\n setItems((prev) => {\n const capacity =\n typeof maxFiles === \"number\"\n ? Math.max(0, maxFiles - prev.length)\n : undefined;\n const capped =\n typeof capacity === \"number\" ? sized.slice(0, capacity) : sized;\n if (typeof capacity === \"number\" && sized.length > capacity) {\n onError?.({\n code: \"max_files\",\n message: \"Too many files. Some were not added.\",\n });\n }\n const next: (FileUIPart & { id: string })[] = [];\n for (const file of capped) {\n next.push({\n id: nanoid(),\n type: \"file\",\n url: URL.createObjectURL(file),\n mediaType: file.type,\n filename: file.name,\n });\n }\n return prev.concat(next);\n });\n },\n [matchesAccept, maxFiles, maxFileSize, onError]\n );\n\n const remove = useCallback((id: string) => {\n setItems((prev) => {\n const found = prev.find((file) => file.id === id);\n if (found?.url) {\n URL.revokeObjectURL(found.url);\n }\n return prev.filter((file) => file.id !== id);\n });\n }, []);\n\n const clear = useCallback(() => {\n setItems((prev) => {\n for (const file of prev) {\n if (file.url) {\n URL.revokeObjectURL(file.url);\n }\n }\n return [];\n });\n }, []);\n\n // Note: File input cannot be programmatically set for security reasons\n // The syncHiddenInput prop is no longer functional\n useEffect(() => {\n if (syncHiddenInput && inputRef.current) {\n // Clear the input when items are cleared\n if (items.length === 0) {\n inputRef.current.value = \"\";\n }\n }\n }, [items, syncHiddenInput]);\n\n // Attach drop handlers on nearest form and document (opt-in)\n useEffect(() => {\n const form = formRef.current;\n if (!form) {\n return;\n }\n const onDragOver = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) {\n e.preventDefault();\n }\n };\n const onDrop = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) {\n e.preventDefault();\n }\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {\n add(e.dataTransfer.files);\n }\n };\n form.addEventListener(\"dragover\", onDragOver);\n form.addEventListener(\"drop\", onDrop);\n return () => {\n form.removeEventListener(\"dragover\", onDragOver);\n form.removeEventListener(\"drop\", onDrop);\n };\n }, [add]);\n\n useEffect(() => {\n if (!globalDrop) {\n return;\n }\n const onDragOver = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) {\n e.preventDefault();\n }\n };\n const onDrop = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) {\n e.preventDefault();\n }\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {\n add(e.dataTransfer.files);\n }\n };\n document.addEventListener(\"dragover\", onDragOver);\n document.addEventListener(\"drop\", onDrop);\n return () => {\n document.removeEventListener(\"dragover\", onDragOver);\n document.removeEventListener(\"drop\", onDrop);\n };\n }, [add, globalDrop]);\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n if (event.currentTarget.files) {\n add(event.currentTarget.files);\n }\n };\n\n const handleSubmit: FormEventHandler<HTMLFormElement> = (event) => {\n event.preventDefault();\n\n const files: FileUIPart[] = items.map(({ ...item }) => ({\n ...item,\n }));\n\n onSubmit({ text: event.currentTarget.message.value, files }, event);\n \n // Clear files after submission\n clear();\n };\n\n const ctx = useMemo<AttachmentsContext>(\n () => ({\n files: items.map((item) => ({ ...item, id: item.id })),\n add,\n remove,\n clear,\n openFileDialog,\n fileInputRef: inputRef,\n }),\n [items, add, remove, clear, openFileDialog]\n );\n\n return (\n <AttachmentsContext.Provider value={ctx}>\n <span aria-hidden=\"true\" className=\"hidden\" ref={anchorRef} />\n <input\n accept={accept}\n className=\"hidden\"\n multiple={multiple}\n onChange={handleChange}\n ref={inputRef}\n type=\"file\"\n />\n <form\n className={cn(\n // The form border + horizontal divider colour both come from\n // the styles.src.css `.chat-widget-container form ...` rules so\n // there's a single token (--chat-divider) controlling both.\n // No utility classes for border colour here.\n \"w-full overflow-hidden rounded-xl bg-background transition-colors\",\n \"[&:focus-within]:shadow-none [&:focus]:shadow-none shadow-none\",\n className\n )}\n onSubmit={handleSubmit}\n style={{ boxShadow: 'none' }}\n {...props}\n />\n </AttachmentsContext.Provider>\n );\n};\n\nexport type PromptInputBodyProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputBody = ({\n className,\n ...props\n}: PromptInputBodyProps) => (\n <div className={cn(className, \"flex flex-col\")} {...props} />\n);\n\nexport type PromptInputTextareaProps = ComponentProps<typeof Textarea>;\n\nexport const PromptInputTextarea = React.forwardRef<\n HTMLTextAreaElement,\n PromptInputTextareaProps\n>(({\n onChange,\n onKeyDown: externalOnKeyDown,\n className,\n placeholder = \"What would you like to know?\",\n ...props\n}, ref) => {\n const attachments = usePromptInputAttachments();\n\n const handleKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (e) => {\n // Let external handlers (e.g. inputPlugins popover navigation) run\n // first. If they call preventDefault we skip the built-in\n // Enter-to-submit behaviour entirely.\n externalOnKeyDown?.(e);\n if (e.defaultPrevented) return;\n\n if (e.key === \"Enter\") {\n // Don't submit if IME composition is in progress\n if (e.nativeEvent.isComposing) {\n return;\n }\n\n if (e.shiftKey) {\n // Allow newline\n return;\n }\n\n // Submit on Enter (without Shift)\n e.preventDefault();\n const form = e.currentTarget.form;\n if (form) {\n form.requestSubmit();\n }\n }\n };\n\n const handlePaste: ClipboardEventHandler<HTMLTextAreaElement> = (event) => {\n const items = event.clipboardData?.items;\n \n if (!items) {\n return;\n }\n\n const files: File[] = [];\n \n for (const item of items) {\n if (item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) {\n files.push(file);\n }\n }\n }\n\n if (files.length > 0) {\n event.preventDefault();\n attachments.add(files);\n }\n };\n\n return (\n <Textarea\n ref={ref}\n className={cn(\n \"w-full resize-none rounded-none border-none p-3 shadow-none outline-none ring-0\",\n \"field-sizing-content\",\n \"max-h-48 min-h-16\",\n \"focus-visible:ring-0 focus-visible:shadow-none focus:ring-0 focus:shadow-none\",\n className\n )}\n name=\"message\"\n onChange={(e) => {\n onChange?.(e);\n }}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={placeholder}\n {...props}\n />\n );\n});\nPromptInputTextarea.displayName = \"PromptInputTextarea\";\n\nexport type PromptInputToolbarProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputToolbar = ({\n className,\n ...props\n}: PromptInputToolbarProps) => (\n <div\n className={cn(\"flex items-center justify-between p-1\", className)}\n {...props}\n />\n);\n\nexport type PromptInputToolsProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputTools = ({\n className,\n ...props\n}: PromptInputToolsProps) => (\n <div\n className={cn(\n \"flex items-center gap-1\",\n \"[&_button:first-child]:rounded-bl-xl\",\n className\n )}\n {...props}\n />\n);\n\nexport type PromptInputButtonProps = ComponentProps<typeof Button>;\n\nexport const PromptInputButton = ({\n variant = \"ghost\",\n className,\n size,\n ...props\n}: PromptInputButtonProps) => {\n const newSize =\n (size ?? Children.count(props.children) > 1) ? \"default\" : \"icon\";\n\n return (\n <Button\n className={cn(\n \"shrink-0 gap-1.5 rounded-lg\",\n variant === \"ghost\" && \"text-muted-foreground\",\n newSize === \"default\" && \"px-3\",\n className\n )}\n size={newSize}\n type=\"button\"\n variant={variant}\n {...props}\n />\n );\n};\n\nexport type PromptInputActionMenuProps = ComponentProps<typeof DropdownMenu>;\nexport const PromptInputActionMenu = (props: PromptInputActionMenuProps) => (\n <DropdownMenu {...props} />\n);\n\nexport type PromptInputActionMenuTriggerProps = ComponentProps<\n typeof Button\n> & {};\nexport const PromptInputActionMenuTrigger = ({\n className,\n children,\n ...props\n}: PromptInputActionMenuTriggerProps) => (\n <DropdownMenuTrigger asChild>\n <PromptInputButton className={className} {...props}>\n {children ?? <PlusIcon className=\"size-4\" />}\n </PromptInputButton>\n </DropdownMenuTrigger>\n);\n\nexport type PromptInputActionMenuContentProps = ComponentProps<\n typeof DropdownMenuContent\n>;\nexport const PromptInputActionMenuContent = ({\n className,\n ...props\n}: PromptInputActionMenuContentProps) => (\n <DropdownMenuContent align=\"start\" className={cn(className)} {...props} />\n);\n\nexport type PromptInputActionMenuItemProps = ComponentProps<\n typeof DropdownMenuItem\n>;\nexport const PromptInputActionMenuItem = ({\n className,\n ...props\n}: PromptInputActionMenuItemProps) => (\n <DropdownMenuItem className={cn(className)} {...props} />\n);\n\n// Note: Actions that perform side-effects (like opening a file dialog)\n// are provided in opt-in modules (e.g., prompt-input-attachments).\n\nexport type PromptInputSubmitProps = ComponentProps<typeof Button> & {\n status?: ChatStatus;\n};\n\nexport const PromptInputSubmit = ({\n className,\n variant = \"default\",\n size = \"icon\",\n status,\n children,\n ...props\n}: PromptInputSubmitProps) => {\n let Icon = <SendIcon className=\"size-4\" />;\n\n if (status === \"submitted\") {\n Icon = <Loader2Icon className=\"size-4 animate-spin\" />;\n } else if (status === \"streaming\") {\n Icon = <SquareIcon className=\"size-4\" />;\n } else if (status === \"error\") {\n Icon = <XIcon className=\"size-4\" />;\n }\n\n return (\n <Button\n className={cn(\"gap-1.5 rounded-lg\", className)}\n size={size}\n type=\"submit\"\n variant={variant}\n {...props}\n >\n {children ?? Icon}\n </Button>\n );\n};\n\nexport type PromptInputModelSelectProps = ComponentProps<typeof Select>;\n\nexport const PromptInputModelSelect = (props: PromptInputModelSelectProps) => (\n <Select {...props} />\n);\n\nexport type PromptInputModelSelectTriggerProps = ComponentProps<\n typeof SelectTrigger\n>;\n\nexport const PromptInputModelSelectTrigger = ({\n className,\n ...props\n}: PromptInputModelSelectTriggerProps) => (\n <SelectTrigger\n className={cn(\n \"border-none bg-transparent font-medium text-muted-foreground shadow-none transition-colors\",\n 'hover:bg-accent hover:text-foreground [&[aria-expanded=\"true\"]]:bg-accent [&[aria-expanded=\"true\"]]:text-foreground',\n className\n )}\n {...props}\n />\n);\n\nexport type PromptInputModelSelectContentProps = ComponentProps<\n typeof SelectContent\n>;\n\nexport const PromptInputModelSelectContent = ({\n className,\n ...props\n}: PromptInputModelSelectContentProps) => (\n <SelectContent className={cn(className)} {...props} />\n);\n\nexport type PromptInputModelSelectItemProps = ComponentProps<typeof SelectItem>;\n\nexport const PromptInputModelSelectItem = ({\n className,\n ...props\n}: PromptInputModelSelectItemProps) => (\n <SelectItem className={cn(className)} {...props} />\n);\n\nexport type PromptInputModelSelectValueProps = ComponentProps<\n typeof SelectValue\n>;\n\nexport const PromptInputModelSelectValue = ({\n className,\n ...props\n}: PromptInputModelSelectValueProps) => (\n <SelectValue className={cn(className)} {...props} />\n);\n","import { cn } from \"../utils/cn\";\nimport { PaperclipIcon, DownloadIcon } from \"lucide-react\";\nimport { Button } from \"../ui/button\";\n\nexport type MessageAttachment = {\n filename: string;\n mediaType: string;\n url: string;\n size?: number;\n};\n\nexport type MessageAttachmentsProps = {\n attachments: MessageAttachment[];\n className?: string;\n};\n\nexport function MessageAttachments({ attachments, className }: MessageAttachmentsProps) {\n if (!attachments || attachments.length === 0) {\n return null;\n }\n\n const handleAttachmentClick = (attachment: MessageAttachment) => {\n // Handle different URL types\n if (attachment.url.startsWith('data:')) {\n // For data URLs, create a new window with the image\n const newWindow = window.open('', '_blank');\n if (newWindow) {\n newWindow.document.write(`\n <html>\n <head><title>${attachment.filename}</title></head>\n <body style=\"margin:0; padding:20px; background:#f5f5f5; display:flex; justify-content:center; align-items:center; min-height:100vh;\">\n <img src=\"${attachment.url}\" alt=\"${attachment.filename}\" style=\"max-width:100%; max-height:100%; object-fit:contain; border-radius:8px; box-shadow:0 4px 12px rgba(0,0,0,0.15);\" />\n </body>\n </html>\n `);\n newWindow.document.close();\n }\n } else if (attachment.url.startsWith('blob:')) {\n // For blob URLs, try to open directly\n window.open(attachment.url, '_blank');\n } else if (attachment.url.startsWith('http')) {\n // For HTTP URLs (like Supabase storage), open directly\n window.open(attachment.url, '_blank');\n } else {\n // Fallback: try to open anyway\n window.open(attachment.url, '_blank');\n }\n };\n\n return (\n <div className={cn(\"flex flex-wrap gap-2\", className)}>\n {attachments.map((attachment, index) => (\n <div\n key={index}\n className=\"group relative h-14 w-14 rounded-lg\"\n >\n {attachment.mediaType.startsWith('image/') ? (\n <img\n src={attachment.url}\n alt={attachment.filename}\n className=\"size-full rounded-lg object-cover cursor-pointer hover:opacity-80 transition-opacity\"\n onClick={() => handleAttachmentClick(attachment)}\n />\n ) : (\n <div\n className=\"flex size-full items-center justify-center text-muted-foreground cursor-pointer hover:bg-secondary/50 rounded-lg transition-colors\"\n onClick={() => handleAttachmentClick(attachment)}\n >\n <PaperclipIcon className=\"size-4\" />\n </div>\n )}\n </div>\n ))}\n </div>\n );\n}\n","\"use client\";\n\n/**\n * Trigger-driven autocomplete for the chat input. Generic: knows nothing\n * about portfolios, stocks, slash commands, etc. The host app passes an\n * array of InputPlugin definitions to ChatWidget; this component wires\n * them up to the textarea.\n *\n * Behaviour:\n * - User types a trigger char (e.g. '@'). We capture the offset and\n * start tracking the query.\n * - As the user keeps typing, we extract the substring from the\n * trigger to the cursor and (debounced) call `plugin.fetch(query)`.\n * - Results render in an absolute-positioned popover anchored under\n * the textarea. ArrowUp/Down navigate, Enter selects, Escape closes.\n * - On select, we replace the trigger+query span with the plugin's\n * `onSelect(item)` text.\n *\n * Edge cases handled:\n * - Trigger only fires when preceded by whitespace or beginning of\n * input (so an email address \"foo@bar\" doesn't open the popover).\n * - Whitespace inside the query closes the popover (matches Slack /\n * Linear behaviour — mention names can't contain spaces from the\n * keyboard; multi-word names come from the picker).\n * - Backspacing past the trigger char closes the popover.\n * - External value changes (e.g. clicking a starter prompt) reset\n * the active state.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport type { InputPlugin, InputPluginItem } from \"../types\";\n\ninterface ActiveSession {\n plugin: InputPlugin;\n /** Index of the trigger character within the textarea value. */\n triggerIndex: number;\n}\n\ninterface UseInputPluginsOptions {\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\n value: string;\n setValue: (next: string) => void;\n plugins?: InputPlugin[];\n}\n\nconst FETCH_DEBOUNCE_MS = 120;\n\nexport function useInputPlugins({ textareaRef, value, setValue, plugins }: UseInputPluginsOptions) {\n const [active, setActive] = useState<ActiveSession | null>(null);\n const [items, setItems] = useState<InputPluginItem[]>([]);\n const [highlight, setHighlight] = useState(0);\n const [loading, setLoading] = useState(false);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const requestIdRef = useRef(0);\n\n // Map trigger character → plugin, so a single keystroke lookup is\n // O(1) even if the host registers many plugins.\n const pluginsByTrigger = useMemo(() => {\n const map = new Map<string, InputPlugin>();\n for (const p of plugins ?? []) {\n if (p.trigger.length === 1) map.set(p.trigger, p);\n }\n return map;\n }, [plugins]);\n\n // Derived: what has the user typed after the trigger char?\n const query = useMemo(() => {\n if (!active) return \"\";\n const ta = textareaRef.current;\n if (!ta) return \"\";\n const cursor = ta.selectionEnd ?? value.length;\n if (cursor <= active.triggerIndex) return \"\";\n return value.slice(active.triggerIndex + 1, cursor);\n }, [active, value, textareaRef]);\n\n // Close the active session if the user backspaced past the trigger,\n // or inserted whitespace (which terminates a mention).\n useEffect(() => {\n if (!active) return;\n const ta = textareaRef.current;\n if (!ta) return;\n // The trigger character itself disappeared.\n if (value[active.triggerIndex] !== active.plugin.trigger) {\n setActive(null);\n return;\n }\n // Whitespace breaks out of the picker.\n if (/\\s/.test(query)) {\n setActive(null);\n }\n }, [active, value, query, textareaRef]);\n\n // Debounced fetch. Each invocation bumps a requestId; stale responses\n // (e.g. user typed past us) drop their results on the floor.\n useEffect(() => {\n if (!active) {\n setItems([]);\n setLoading(false);\n return;\n }\n if (debounceRef.current) clearTimeout(debounceRef.current);\n setLoading(true);\n const reqId = ++requestIdRef.current;\n debounceRef.current = setTimeout(async () => {\n try {\n const result = await active.plugin.fetch(query);\n if (reqId !== requestIdRef.current) return;\n setItems(result);\n setHighlight(0);\n } catch (err) {\n console.error(\"[input-plugin] fetch failed:\", err);\n if (reqId !== requestIdRef.current) return;\n setItems([]);\n } finally {\n if (reqId === requestIdRef.current) setLoading(false);\n }\n }, FETCH_DEBOUNCE_MS);\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n };\n }, [active, query]);\n\n const close = useCallback(() => {\n setActive(null);\n setItems([]);\n setHighlight(0);\n }, []);\n\n const selectItem = useCallback(\n (item: InputPluginItem) => {\n if (!active) return;\n const ta = textareaRef.current;\n const cursor = ta?.selectionEnd ?? value.length;\n const replacement = active.plugin.onSelect(item);\n const before = value.slice(0, active.triggerIndex);\n const after = value.slice(cursor);\n const next = `${before}${replacement}${after}`;\n setValue(next);\n // Refocus + place cursor right after the inserted text on the\n // next tick (after React has flushed the new value).\n const newCursor = before.length + replacement.length;\n setTimeout(() => {\n const t = textareaRef.current;\n if (!t) return;\n t.focus();\n try {\n t.setSelectionRange(newCursor, newCursor);\n } catch {\n // Some browsers throw on setSelectionRange for non-text input\n // states (e.g. mid-IME). Safe to ignore.\n }\n }, 0);\n close();\n },\n [active, value, setValue, close, textareaRef],\n );\n\n // Detect a fresh trigger keystroke. Called from the textarea onKeyDown\n // BEFORE the value updates — that way we capture the cursor index\n // accurately even during an IME composition.\n const onKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n // 1. Popover-open navigation (intercept before the textarea's\n // Enter-to-submit handler runs).\n if (active) {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setHighlight((h) => (items.length === 0 ? 0 : (h + 1) % items.length));\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setHighlight((h) => (items.length === 0 ? 0 : (h - 1 + items.length) % items.length));\n return;\n }\n if (e.key === \"Enter\") {\n if (items.length > 0) {\n e.preventDefault();\n selectItem(items[highlight]);\n }\n return;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n close();\n return;\n }\n }\n // 2. Detect a new trigger keystroke. We only open when the trigger\n // is at the start of input or follows whitespace — avoids\n // \"foo@bar\" eating the picker.\n if (e.key.length === 1 && pluginsByTrigger.has(e.key) && !e.metaKey && !e.ctrlKey && !e.altKey) {\n const ta = e.currentTarget;\n const cursor = ta.selectionStart ?? value.length;\n const prevChar = cursor > 0 ? value[cursor - 1] : \"\";\n if (cursor === 0 || /\\s/.test(prevChar)) {\n // The trigger character itself will land at index `cursor`\n // once the keypress is processed.\n const plugin = pluginsByTrigger.get(e.key)!;\n setActive({ plugin, triggerIndex: cursor });\n // Don't preventDefault — let the character actually type into\n // the textarea so the user sees @ appear.\n }\n }\n },\n [active, items, highlight, selectItem, close, pluginsByTrigger, value],\n );\n\n // Reset on unrelated value changes (e.g. user pasted, or starter\n // prompt populated the input). If the trigger char is still where we\n // expect it the session survives; otherwise we close.\n useEffect(() => {\n if (!active) return;\n if (value[active.triggerIndex] !== active.plugin.trigger) {\n close();\n }\n }, [value, active, close]);\n\n // Popover element. Rendered at the body of the input area; positioning\n // is handled by the parent (we expect to be placed inside a\n // position:relative ancestor that wraps the textarea).\n const popover =\n active && (loading || items.length > 0 || active.plugin.emptyText) ? (\n <PluginPopover\n plugin={active.plugin}\n items={items}\n loading={loading}\n highlight={highlight}\n onHover={setHighlight}\n onSelect={selectItem}\n />\n ) : null;\n\n return { onKeyDown, popover, isOpen: !!active };\n}\n\ninterface PluginPopoverProps {\n plugin: InputPlugin;\n items: InputPluginItem[];\n loading: boolean;\n highlight: number;\n onHover: (idx: number) => void;\n onSelect: (item: InputPluginItem) => void;\n}\n\nfunction PluginPopover({ plugin, items, loading, highlight, onHover, onSelect }: PluginPopoverProps) {\n return (\n <div\n role=\"listbox\"\n className={cn(\n \"absolute bottom-full left-0 right-0 mb-2 z-30\",\n \"rounded-md border border-border bg-popover text-popover-foreground shadow-md\",\n \"max-h-64 overflow-y-auto\",\n )}\n // Don't steal focus from the textarea on mousedown.\n onMouseDown={(e) => e.preventDefault()}\n >\n {plugin.heading && (\n <div className=\"px-3 py-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground border-b border-border\">\n {plugin.heading}\n </div>\n )}\n {loading && items.length === 0 && (\n <div className=\"px-3 py-2 text-xs text-muted-foreground\">Loading…</div>\n )}\n {!loading && items.length === 0 && (\n <div className=\"px-3 py-2 text-xs text-muted-foreground\">\n {plugin.emptyText ?? \"No results\"}\n </div>\n )}\n {items.map((item, idx) => (\n <button\n key={item.id}\n type=\"button\"\n role=\"option\"\n aria-selected={idx === highlight}\n onMouseEnter={() => onHover(idx)}\n onClick={() => onSelect(item)}\n className={cn(\n \"w-full text-left px-3 py-2 text-sm transition-colors\",\n \"flex flex-col gap-0.5\",\n idx === highlight ? \"bg-accent text-accent-foreground\" : \"hover:bg-muted\",\n )}\n >\n <span className=\"font-medium leading-tight\">{item.label}</span>\n {item.sublabel && (\n <span className=\"text-[11px] text-muted-foreground leading-tight\">{item.sublabel}</span>\n )}\n </button>\n ))}\n </div>\n );\n}\n","'use client';\n\nimport {\n Conversation,\n ConversationContent,\n ConversationScrollButton,\n} from './conversation';\nimport { Message, MessageContent } from './message';\nimport {\n PromptInput,\n PromptInputAttachment,\n PromptInputAttachments,\n PromptInputBody,\n PromptInputButton,\n type PromptInputMessage,\n PromptInputModelSelect,\n PromptInputModelSelectContent,\n PromptInputModelSelectItem,\n PromptInputModelSelectTrigger,\n PromptInputModelSelectValue,\n PromptInputSubmit,\n PromptInputTextarea,\n PromptInputToolbar,\n PromptInputTools,\n usePromptInputAttachments,\n} from './prompt-input';\nimport {\n Actions,\n Action,\n} from './actions';\nimport { MessageAttachments } from './message-attachments';\nimport { useInputPlugins } from './input-plugin-popover';\nimport { useState, useEffect, useRef, useMemo, useCallback } from 'react';\nimport { HistoryIcon, MessageSquareIcon, SearchIcon, ChevronRightIcon, PlusIcon, XIcon } from 'lucide-react';\nimport { cn } from '../utils/cn';\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\nimport { Fragment } from 'react';\nimport { useChat } from '@ai-sdk/react';\nimport { DefaultChatTransport } from 'ai';\nimport { Response } from './response';\nimport { GlobeIcon, RefreshCcwIcon, CopyIcon } from 'lucide-react';\nimport {\n Source,\n Sources,\n SourcesContent,\n SourcesTrigger,\n} from './sources';\nimport {\n Reasoning,\n ReasoningContent,\n ReasoningTrigger,\n} from './reasoning';\nimport { Loader } from './loader';\nimport {\n Tool,\n ToolContent,\n ToolHeader,\n ToolInput,\n ToolOutput,\n} from './tool';\nimport {\n Suggestion,\n Suggestions,\n} from './suggestion';\nimport { StarterMessages } from './suggestion2';\nimport { useChatStorageKey } from '../contexts/chat-storage-context';\n\ntype Conversation = {\n id: string;\n title: string;\n model: string;\n created_at: string;\n updated_at: string;\n message_count: number;\n metadata?: any;\n};\n\ntype ChatTab = {\n id: string;\n title: string;\n isActive: boolean;\n};\n\nexport default function ChatInterface({ id, initialMessages, config, onClose, headerActions }: { id?: string; initialMessages?: any[]; config?: any; onClose?: () => void; headerActions?: React.ReactNode } = {}) {\n // Get storage key prefix from context to scope localStorage keys per user/deployment\n const { storageKeyPrefix } = useChatStorageKey();\n const storageKey = (key: string) => storageKeyPrefix ? `chat-${storageKeyPrefix}-${key}` : `chat-${key}`;\n\n // Get theme mode from config (defaults to 'light')\n const themeMode = config?.theme?.mode || 'light';\n\n const [input, setInput] = useState('');\n const inputRef = useRef<HTMLTextAreaElement | null>(null);\n const inputPlugins = useInputPlugins({\n textareaRef: inputRef,\n value: input,\n setValue: setInput,\n plugins: config?.inputPlugins,\n });\n const [showHistory, setShowHistory] = useState(false);\n const [conversations, setConversations] = useState<Conversation[]>([]);\n const [loadingHistory, setLoadingHistory] = useState(false);\n const [historyLoaded, setHistoryLoaded] = useState(false);\n const [searchQuery, setSearchQuery] = useState('');\n const [uploadError, setUploadError] = useState<string | null>(null);\n\n // Auto-dismiss upload errors after 5 seconds\n useEffect(() => {\n if (uploadError) {\n const timeoutId = setTimeout(() => setUploadError(null), 5000);\n return () => clearTimeout(timeoutId);\n }\n }, [uploadError]);\n\n // Tab management\n const [tabs, setTabs] = useState<ChatTab[]>([]);\n const [activeTabId, setActiveTabId] = useState<string>('');\n const [initialTabCreated, setInitialTabCreated] = useState(false);\n const [isInitializing, setIsInitializing] = useState(true);\n // True while switching tabs and the new tab's messages are mid-fetch.\n // Distinct from isInitializing (which only covers first mount) so the\n // empty-state gate stays closed during tab switches too.\n const [isLoadingMessages, setIsLoadingMessages] = useState(false);\n\n // Track last synced tab to prevent infinite loops\n const lastSyncedTabId = useRef<string>('');\n\n // Ref-based initialization guard to ensure initialization runs only once\n const hasInitialized = useRef(false);\n\n const { messages, sendMessage, status, setMessages } = useChat({\n id: activeTabId || 'temp-id',\n transport: new DefaultChatTransport({\n api: '/api/chat',\n headers: {\n 'X-User-Id': config?.userId || '',\n },\n }),\n // Throttle UI updates to 200ms to prevent hanging during streaming\n experimental_throttle: 200,\n });\n\n const handleSubmit = async (message: PromptInputMessage) => {\n const hasText = Boolean(message.text);\n const hasAttachments = Boolean(message.files?.length);\n\n if (!(hasText || hasAttachments)) {\n return;\n }\n\n // Upload files to Supabase first if there are attachments\n let uploadedFiles: any[] = [];\n if (message.files && message.files.length > 0) {\n try {\n // Upload all files in parallel for better performance\n const uploadPromises = message.files.map(async (file) => {\n try {\n // Convert blob URL back to File object\n const response = await fetch(file.url);\n const blob = await response.blob();\n const fileObj = new File([blob], file.filename || 'unknown', { type: file.mediaType });\n \n // Upload to our API\n const formData = new FormData();\n formData.append('file', fileObj);\n formData.append('conversationId', activeTabId || 'default');\n formData.append('userId', config?.userId || 'demo-user');\n\n const uploadResponse = await fetch('/api/chat/upload', {\n method: 'POST',\n body: formData\n });\n \n if (!uploadResponse.ok) {\n const errorText = await uploadResponse.text();\n console.error(`Upload failed for ${file.filename}:`, errorText);\n return null; // Return null for failed uploads\n }\n \n const uploadResult = await uploadResponse.json();\n return {\n id: (file as any).id || 'unknown',\n type: 'file',\n url: uploadResult.url,\n filename: uploadResult.filename,\n mediaType: uploadResult.mediaType,\n size: uploadResult.size\n };\n } catch (error) {\n console.error(`Error uploading ${file.filename}:`, error);\n return null; // Return null for failed uploads\n }\n });\n\n // Wait for all uploads to complete\n const results = await Promise.all(uploadPromises);\n \n // Filter out null results (failed uploads)\n uploadedFiles = results.filter(result => result !== null);\n\n // If no files uploaded successfully, show error to user\n if (uploadedFiles.length === 0) {\n const errorMsg = 'All file uploads failed. Please try again.';\n setUploadError(errorMsg);\n console.error(errorMsg);\n return;\n }\n\n // If only some files uploaded, show warning to user\n if (uploadedFiles.length < message.files.length) {\n const warnMsg = `Warning: Only ${uploadedFiles.length} of ${message.files.length} files uploaded successfully.`;\n setUploadError(warnMsg);\n console.warn(warnMsg);\n }\n\n } catch (error) {\n const errorMsg = 'Error uploading files. Please try again.';\n setUploadError(errorMsg);\n console.error('Error in file upload process:', error);\n return;\n }\n }\n\n sendMessage({\n text: message.text || 'Sent with attachments',\n files: uploadedFiles\n });\n // Model and webSearch are sent via transport's prepareSendMessagesRequest using refs\n\n // Update tab title if this is the first message (title is still \"New Chat\")\n const activeTab = tabs.find(tab => tab.id === activeTabId);\n if (activeTab && activeTab.title === 'New Chat' && message.text) {\n const newTitle = message.text.slice(0, 100);\n setTabs(prevTabs =>\n prevTabs.map(tab =>\n tab.id === activeTabId\n ? { ...tab, title: newTitle }\n : tab\n )\n );\n }\n\n setInput('');\n // StickToBottom handles scrolling automatically\n };\n\n // Attachment button component that uses the attachments context\n const AttachButton = () => {\n const attachments = usePromptInputAttachments();\n return (\n <PromptInputButton\n variant=\"ghost\"\n onClick={() => attachments.openFileDialog()}\n >\n <PlusIcon className=\"size-4\" />\n </PromptInputButton>\n );\n };\n\n // Centralized function to load a conversation's messages\n const loadConversation = async (conversationId: string) => {\n if (!config?.userId) {\n console.log('Cannot load conversation - no userId');\n return;\n }\n\n try {\n const response = await fetch(`/api/chat/history/${conversationId}?userId=${config.userId}`);\n if (response.ok) {\n const data = await response.json();\n const loadedMessages = data.messages || [];\n\n // Set messages after ensuring activeTabId state has updated\n setTimeout(() => {\n setMessages(loadedMessages);\n }, 0);\n } else if (response.status === 404) {\n // Conversation doesn't exist yet - this is normal for new chats\n console.log('Conversation not found in database yet (new chat)');\n // Clear messages for new chat\n setMessages([]);\n } else {\n console.error('Error loading messages:', response.status, response.statusText);\n }\n } catch (error) {\n console.error('Error loading conversation:', error);\n }\n };\n\n // Tab management functions\n // Generate unique tab ID with better collision avoidance\n const generateUniqueTabId = (): string => {\n let newTabId: string;\n let attempts = 0;\n do {\n newTabId = `chat-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n attempts++;\n } while (tabs.find(tab => tab.id === newTabId) && attempts < 10);\n \n if (attempts >= 10) {\n throw new Error('Unable to generate unique tab ID');\n }\n \n return newTabId;\n };\n\n const createNewTab = useCallback(() => {\n // Additional safeguard: prevent creating tabs if we're still loading\n if (!initialTabCreated) {\n console.warn('Cannot create new tab while initializing');\n return;\n }\n\n // Generate a unique ID for the new tab\n const newTabId = generateUniqueTabId();\n\n setTabs(prevTabs => {\n // Check if tab with this ID already exists using prevTabs (current state)\n const existingTab = prevTabs.find(tab => tab.id === newTabId);\n if (existingTab) {\n console.warn('Tab with ID already exists:', newTabId);\n return prevTabs; // Return unchanged\n }\n\n const newTab: ChatTab = {\n id: newTabId,\n title: 'New Chat',\n isActive: true,\n };\n\n // Save current tab's state before switching\n const updatedTabs = prevTabs.map(tab => ({\n ...tab,\n isActive: false,\n }));\n\n return [...updatedTabs, newTab];\n });\n\n setActiveTabId(newTabId);\n setMessages([]);\n setInput('');\n }, [initialTabCreated]);\n\n const startNewConversation = useCallback(() => {\n createNewTab();\n }, [createNewTab]);\n\n // Clear tabs from localStorage when component unmounts (optional cleanup)\n useEffect(() => {\n return () => {\n // Optional: Clear localStorage on unmount if needed\n // localStorage.removeItem('chat-tabs');\n // localStorage.removeItem('active-tab-id');\n };\n }, []);\n\n const switchToTab = async (tabId: string) => {\n const targetTab = tabs.find(tab => tab.id === tabId);\n if (!targetTab) return;\n\n // Update active tab (metadata only)\n setTabs(prevTabs =>\n prevTabs.map(tab => ({\n ...tab,\n isActive: tab.id === tabId,\n }))\n );\n\n // Change active tab - useChat will reinitialize with new ID. Setting\n // isLoadingMessages immediately gates the starter-prompt empty state\n // so we don't flash it during the API fetch below.\n setActiveTabId(tabId);\n setIsLoadingMessages(true);\n try {\n await loadConversation(tabId);\n } finally {\n setIsLoadingMessages(false);\n }\n };\n\n const closeTab = (tabId: string) => {\n if (tabs.length <= 1) return; // Don't close the last tab\n\n const filteredTabs = tabs.filter(tab => tab.id !== tabId);\n\n // If we're closing the active tab, switch to another tab\n if (tabId === activeTabId && filteredTabs.length > 0) {\n const newActiveTab = filteredTabs[0];\n\n // Update tabs first\n setTabs(filteredTabs.map(tab => ({\n ...tab,\n isActive: tab.id === newActiveTab.id\n })));\n\n // Then switch to the new active tab (this will load messages)\n switchToTab(newActiveTab.id);\n } else {\n // Just remove the tab\n setTabs(filteredTabs);\n }\n\n // Update localStorage immediately when tab is closed\n if (filteredTabs.length > 0) {\n localStorage.setItem(storageKey('tabs'), JSON.stringify(filteredTabs));\n if (tabId === activeTabId) {\n const newActiveTab = filteredTabs[0];\n localStorage.setItem(storageKey('active-tab-id'), newActiveTab.id);\n }\n }\n };\n\n const fetchConversations = async () => {\n if (historyLoaded) return; // Don't reload if already loaded\n if (!config?.userId) {\n return; // Wait for real userId\n }\n\n setLoadingHistory(true);\n try {\n const response = await fetch(`/api/chat/history?userId=${config.userId}`);\n\n if (response.ok) {\n const data = await response.json();\n setConversations(data.conversations || []);\n setHistoryLoaded(true);\n } else {\n console.error('[ChatInterface] Failed to fetch chat history, status:', response.status);\n const errorText = await response.text();\n console.error('[ChatInterface] Error response:', errorText);\n }\n } catch (error) {\n console.error('[ChatInterface] Error fetching chat history:', error);\n } finally {\n setLoadingHistory(false);\n }\n };\n\n useEffect(() => {\n if (showHistory && !historyLoaded && config?.userId) {\n fetchConversations();\n }\n }, [showHistory, historyLoaded, config?.userId]);\n\n // Load conversations on component mount (only when we have a userId)\n useEffect(() => {\n if (!historyLoaded && config?.userId) {\n fetchConversations();\n }\n }, [historyLoaded, config?.userId]);\n\n // Note: Message loading is now handled in switchToTab function\n // useChat will automatically manage messages when activeTabId changes\n\n // Conversation component (StickToBottom) handles auto-scroll automatically during streaming\n\n // Tab Persistence: Save tabs to localStorage with debouncing\n // Only saves metadata (id, title, model, webSearch) - no messages\n useEffect(() => {\n if (tabs.length > 0) {\n const timeoutId = setTimeout(() => {\n localStorage.setItem(storageKey('tabs'), JSON.stringify(tabs));\n localStorage.setItem(storageKey('active-tab-id'), activeTabId);\n }, 500); // Debounce 500ms\n\n return () => clearTimeout(timeoutId);\n }\n }, [tabs, activeTabId, storageKey]);\n\n // Tab Persistence: Load tabs from localStorage on component mount (ONLY ONCE)\n useEffect(() => {\n // Ref-based guard to absolutely ensure this only runs once\n if (hasInitialized.current) return;\n\n const loadInitialTabs = () => {\n const savedTabs = localStorage.getItem(storageKey('tabs'));\n const savedActiveTabId = localStorage.getItem(storageKey('active-tab-id'));\n\n if (savedTabs && savedTabs !== '[]') {\n // Restore saved tabs. Don't flip isInitializing yet — the\n // separate message-load effect below owns that, so the empty\n // state stays gated until we know whether there are messages\n // to render.\n const parsedTabs = JSON.parse(savedTabs);\n setTabs(parsedTabs);\n const activeId = savedActiveTabId || parsedTabs[0]?.id;\n setActiveTabId(activeId);\n setInitialTabCreated(true);\n } else if (!initialTabCreated && tabs.length === 0) {\n // Clean start (no saved tabs) — create one empty tab and finish\n // hydration immediately. There's no remote conversation to wait on.\n const initialTabId = `chat-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n setTabs([{ id: initialTabId, title: 'New Chat', isActive: true }]);\n setActiveTabId(initialTabId);\n setInitialTabCreated(true);\n setIsInitializing(false);\n }\n };\n\n try {\n loadInitialTabs();\n } catch (err) {\n // localStorage parse failure or similar — never leave the widget\n // stuck on the loader; fall back to a clean state.\n console.error('[chat-widget] init failed, falling back to clean start:', err);\n setIsInitializing(false);\n }\n hasInitialized.current = true;\n }, []); // Empty dependency array - run only once on mount\n\n // Load messages for active tab when userId becomes available (on initialization)\n const hasLoadedInitialMessages = useRef(false);\n useEffect(() => {\n if (hasLoadedInitialMessages.current) return; // Only run once\n if (!config?.userId) return; // Wait for userId\n if (!activeTabId) return; // Wait for activeTabId to be set\n\n // Load the conversation messages, then flip isInitializing false. This\n // keeps the empty-state gate closed until the saved messages render —\n // otherwise the starter prompts flash for the duration of the fetch.\n (async () => {\n try {\n await loadConversation(activeTabId);\n } finally {\n hasLoadedInitialMessages.current = true;\n setIsInitializing(false);\n }\n })();\n }, [config?.userId, activeTabId]);\n\n // Handle state updates when active tab changes\n // Messages are loaded in switchToTab function, not here\n useEffect(() => {\n if (isInitializing) return; // Don't sync during initialization\n\n if (activeTabId && tabs.length > 0 && activeTabId !== lastSyncedTabId.current) {\n lastSyncedTabId.current = activeTabId;\n setInput('');\n }\n }, [activeTabId, isInitializing, tabs.length]); // Only depend on activeTabId\n\n // Keep tab titles as default for now\n // Tab title updates removed to fix chat flow\n\n // Group and filter conversations\n const groupedConversations = useMemo(() => {\n const filtered = conversations.filter(conv =>\n searchQuery === '' ||\n conv.title.toLowerCase().includes(searchQuery.toLowerCase())\n );\n\n const groups: { [key: string]: Conversation[] } = {};\n const now = new Date();\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const yesterday = new Date(today);\n yesterday.setDate(yesterday.getDate() - 1);\n\n filtered.forEach(conv => {\n const convDate = new Date(conv.updated_at);\n const diffTime = now.getTime() - convDate.getTime();\n const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));\n const diffWeeks = Math.floor(diffDays / 7);\n const diffMonths = Math.floor(diffDays / 30);\n\n let groupKey: string;\n\n if (convDate >= today) {\n groupKey = 'Today';\n } else if (convDate >= yesterday) {\n groupKey = 'Yesterday';\n } else if (diffDays <= 7) {\n // Show individual days for the past week\n groupKey = `${diffDays}d ago`;\n } else if (diffWeeks <= 4) {\n // Show weeks for the past month\n groupKey = `${diffWeeks}w ago`;\n } else if (diffMonths <= 12) {\n // Show months for the past year\n groupKey = `${diffMonths}mo ago`;\n } else {\n // Show years for older\n const diffYears = Math.floor(diffMonths / 12);\n groupKey = `${diffYears}y ago`;\n }\n\n if (!groups[groupKey]) {\n groups[groupKey] = [];\n }\n groups[groupKey].push(conv);\n });\n\n // Sort group keys in chronological order\n const sortedGroups = Object.entries(groups).sort((a, b) => {\n const order = ['Today', 'Yesterday'];\n const aIndex = order.indexOf(a[0]);\n const bIndex = order.indexOf(b[0]);\n\n if (aIndex !== -1 && bIndex !== -1) return aIndex - bIndex;\n if (aIndex !== -1) return -1;\n if (bIndex !== -1) return 1;\n\n // Extract numbers for comparison\n const aMatch = a[0].match(/(\\d+)([dw]|mo|y)/);\n const bMatch = b[0].match(/(\\d+)([dw]|mo|y)/);\n\n if (aMatch && bMatch) {\n const aNum = parseInt(aMatch[1]);\n const bNum = parseInt(bMatch[1]);\n const aUnit = aMatch[2];\n const bUnit = bMatch[2];\n\n // Convert to days for comparison\n const unitToDays: { [key: string]: number } = { 'd': 1, 'w': 7, 'mo': 30, 'y': 365 };\n const aDays = aNum * unitToDays[aUnit];\n const bDays = bNum * unitToDays[bUnit];\n\n return aDays - bDays;\n }\n\n return 0;\n });\n\n return sortedGroups;\n }, [conversations, searchQuery]);\n\n // Render messages directly - AI SDK Elements components handle optimization\n const renderMessages = () => messages.map((message, index) => {\n // Pre-filter parts once to avoid redundant filtering on every render\n const sourceParts = message.parts?.filter((part) => part.type === 'source-url') || [];\n const fileParts = message.parts?.filter((part) => part.type === 'file') || [];\n\n return (\n <div key={message.id} className={index > 0 ? \"mt-6\" : \"\"}>\n {/* Render sources if available */}\n {message.role === 'assistant' && sourceParts.length > 0 && (\n <Sources>\n <SourcesTrigger count={sourceParts.length} />\n {sourceParts.map((part, i) => (\n <SourcesContent key={`${message.id}-${i}`}>\n <Source\n key={`${message.id}-${i}`}\n href={part.url}\n title={part.url}\n />\n </SourcesContent>\n ))}\n </Sources>\n )}\n\n {/* Render file attachments above the message */}\n {fileParts.length > 0 && (\n <div className={cn(\n \"flex mb-1\",\n message.role === 'user' ? 'justify-end' : 'justify-start'\n )}>\n <MessageAttachments\n attachments={fileParts.map(part => ({\n filename: part.filename || 'unknown',\n mediaType: part.mediaType,\n url: part.url,\n size: (part as any).size || 0\n }))}\n />\n </div>\n )}\n\n {/* Handle messages with parts array */}\n {message.parts ? (\n <div className=\"space-y-2\">\n {message.parts.map((part, i) => {\n switch (part.type) {\n case 'text':\n const isTextStreaming = status === 'streaming' && i === message.parts.length - 1 && message.id === messages.at(-1)?.id;\n return (\n <Fragment key={`${message.id}-${i}`}>\n <Message from={message.role}>\n <MessageContent>\n <Response isStreaming={isTextStreaming}>\n {part.text}\n </Response>\n </MessageContent>\n </Message>\n </Fragment>\n );\n case 'reasoning':\n const isCurrentlyStreaming = status === 'streaming' && i === message.parts.length - 1 && message.id === messages.at(-1)?.id;\n // Show open while streaming, closed when done (users can still manually reopen)\n return (\n <Reasoning\n key={`${message.id}-${i}`}\n className=\"w-full\"\n isStreaming={isCurrentlyStreaming}\n defaultOpen={false}\n open={isCurrentlyStreaming ? true : undefined}\n >\n <ReasoningTrigger />\n <ReasoningContent>{part.text}</ReasoningContent>\n </Reasoning>\n );\n default:\n // Handle tool calls\n if (part.type.startsWith('tool-') || part.type === 'dynamic-tool') {\n const toolPart = part as any; // ToolUIPart | DynamicToolUIPart\n return (\n <Tool key={`${message.id}-${i}`}>\n <ToolHeader\n type={part.type as any}\n toolName={toolPart.toolName}\n state={toolPart.state}\n />\n <ToolContent>\n <ToolInput input={toolPart.input} />\n <ToolOutput output={toolPart.output} errorText={toolPart.errorText} />\n </ToolContent>\n </Tool>\n );\n }\n return null;\n }\n })}\n </div>\n ) : (\n /* Handle standard AI SDK messages with content or text property */\n <Fragment key={`${message.id}-content`}>\n <Message from={message.role}>\n <MessageContent>\n <Response>\n {(message as any).content || (message as any).text}\n </Response>\n </MessageContent>\n </Message>\n </Fragment>\n )}\n </div>\n );\n });\n\n const handleSelectConversation = async (selectedConversationId: string, conversationTitle: string) => {\n if (!config?.userId) return; // Wait for userId\n\n try {\n // Check if this conversation is already open in a tab\n const existingTab = tabs.find(tab => tab.id === selectedConversationId);\n\n if (existingTab) {\n // Just switch to the existing tab\n switchToTab(selectedConversationId);\n setShowHistory(false);\n return;\n }\n\n // Create a new tab with the loaded conversation metadata\n const newTab: ChatTab = {\n id: selectedConversationId,\n title: conversationTitle,\n isActive: true,\n };\n\n setTabs(prevTabs => {\n // Save current tab's metadata before switching\n const updatedTabs = prevTabs.map(tab => ({\n ...tab,\n isActive: false,\n }));\n return [...updatedTabs, newTab];\n });\n\n setActiveTabId(selectedConversationId);\n\n // Load messages using centralized function\n await loadConversation(selectedConversationId);\n\n // Close the history dropdown\n setShowHistory(false);\n } catch (error) {\n console.error('Error loading conversation:', error);\n }\n };\n\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setShowHistory(false);\n }\n };\n\n if (showHistory) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [showHistory]);\n\n return (\n <div className={cn(\"w-full h-full flex flex-col bg-white dark:bg-gray-900 overflow-hidden ring-1 ring-black/[0.02] dark:ring-white/[0.03]\", themeMode === 'dark' && 'dark')}>\n <div\n className={cn(\n \"flex flex-col h-full w-full overflow-hidden relative chat-widget-container\",\n themeMode === 'dark' && 'dark'\n )}\n >\n {/* Header Section with Tabs */}\n <div className=\"flex items-center gap-2 px-3 py-2 border-b backdrop-blur-sm relative z-20\" style={{\n borderColor: 'var(--chat-divider)',\n backgroundColor: 'var(--chat-header-bg)'\n }}>\n {/* Tabs Container with Scroll */}\n <div className=\"flex items-center gap-1 flex-1 min-w-0 overflow-x-auto scrollbar-hide py-0.5 scroll-smooth\">\n {/* Apple-style Tab Pills */}\n {tabs.map((tab, index) => (\n <div\n key={tab.id}\n className=\"relative flex items-center gap-1.5 px-3 py-1.5 rounded-lg cursor-pointer transition-all duration-150 group flex-shrink-0 min-w-0\"\n style={{\n backgroundColor: tab.isActive\n ? ('hsl(var(--chat-surface))')\n : 'transparent',\n color: tab.isActive\n ? ('hsl(var(--chat-text))')\n : ('hsl(var(--chat-text-muted))')\n }}\n onMouseEnter={(e) => {\n if (!tab.isActive) {\n e.currentTarget.style.backgroundColor = 'var(--chat-hover-bg)';\n }\n }}\n onMouseLeave={(e) => {\n if (!tab.isActive) {\n e.currentTarget.style.backgroundColor = 'transparent';\n }\n }}\n onClick={(e) => {\n e.stopPropagation();\n switchToTab(tab.id);\n }}\n >\n {/* Tab Title */}\n <span className=\"truncate max-w-28 text-[13px] font-medium transition-colors\">\n {tab.title}\n </span>\n\n {/* Close Button */}\n {tabs.length > 1 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n closeTab(tab.id);\n }}\n className=\"rounded-lg p-1 transition-all duration-150 flex-shrink-0 -mr-1\"\n style={{\n opacity: tab.isActive ? 0.6 : 0\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.opacity = '1';\n e.currentTarget.style.backgroundColor = 'hsl(var(--chat-surface-hover))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.opacity = tab.isActive ? '0.6' : '0';\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n >\n <XIcon className=\"h-3 w-3\" strokeWidth={2.5} />\n </button>\n )}\n </div>\n ))}\n </div>\n\n {/* Fixed Action Buttons */}\n <div className=\"flex items-center gap-0.5 flex-shrink-0\">\n {/* Plus Icon */}\n <button\n onClick={createNewTab}\n className=\"flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150\"\n style={{\n color: 'hsl(var(--chat-text-muted))'\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.color = 'hsl(var(--chat-text))';\n e.currentTarget.style.backgroundColor = 'hsl(var(--chat-surface))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.color = 'hsl(var(--chat-text-muted))';\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n title=\"New Chat\"\n >\n <PlusIcon className=\"h-4 w-4\" strokeWidth={2} />\n </button>\n\n {/* History Icon */}\n <div className=\"relative\" ref={dropdownRef}>\n <button\n onClick={() => setShowHistory(!showHistory)}\n className=\"flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150\"\n style={{\n color: showHistory\n ? ('hsl(var(--chat-text))')\n : ('hsl(var(--chat-text-muted))'),\n backgroundColor: showHistory\n ? ('hsl(var(--chat-surface))')\n : 'transparent'\n }}\n onMouseEnter={(e) => {\n if (!showHistory) {\n e.currentTarget.style.color = 'hsl(var(--chat-text))';\n e.currentTarget.style.backgroundColor = 'hsl(var(--chat-surface))';\n }\n }}\n onMouseLeave={(e) => {\n if (!showHistory) {\n e.currentTarget.style.color = 'hsl(var(--chat-text-muted))';\n e.currentTarget.style.backgroundColor = 'transparent';\n }\n }}\n title=\"Chat History\"\n >\n <HistoryIcon className=\"h-4 w-4\" strokeWidth={2} />\n </button>\n\n {/* Chat History Dropdown */}\n {showHistory && (\n <div className=\"absolute right-0 top-full mt-1.5 w-72 rounded-xl shadow-[0_4px_24px_rgba(0,0,0,0.08)] dark:shadow-[0_4px_24px_rgba(0,0,0,0.3)] z-50 animate-in fade-in slide-in-from-top-1 duration-150 overflow-hidden\" style={{\n backgroundColor: 'hsl(var(--chat-background))',\n border: `1px solid ${'var(--chat-divider)'}`\n }}>\n {/* Search Header */}\n <div className=\"p-2.5 border-b\" style={{\n borderColor: 'var(--chat-divider)',\n backgroundColor: 'var(--chat-overlay)'\n }}>\n <div className=\"relative\">\n <input\n type=\"text\"\n placeholder=\"Search\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full h-7 px-2.5 text-[13px] rounded-lg focus:outline-none transition-all\"\n style={{\n backgroundColor: 'hsl(var(--chat-surface-deep))',\n border: `1px solid ${'var(--chat-divider)'}`,\n color: 'hsl(var(--chat-text))'\n }}\n />\n </div>\n </div>\n\n {/* Content Area */}\n <div className=\"max-h-[300px] overflow-y-auto ai-assistant-scrollbar\">\n {loadingHistory ? (\n <div className=\"flex items-center justify-center py-12\">\n <div className=\"text-[13px]\" style={{ color: 'hsl(var(--chat-text-muted))' }}>Loading...</div>\n </div>\n ) : conversations.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-12 px-4 text-center\">\n <div className=\"w-12 h-12 rounded-full flex items-center justify-center mb-3\" style={{\n backgroundColor: 'hsl(var(--chat-surface))'\n }}>\n <MessageSquareIcon className=\"h-5 w-5\" style={{ color: 'hsl(var(--chat-text-subtle))' }} strokeWidth={2} />\n </div>\n <p className=\"text-[13px] font-medium mb-0.5\" style={{ color: 'hsl(var(--chat-text))' }}>No Conversations</p>\n <p className=\"text-[12px]\" style={{ color: 'hsl(var(--chat-text-muted))' }}>Start a new chat to begin</p>\n </div>\n ) : groupedConversations.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-12 px-4 text-center\">\n <div className=\"w-12 h-12 rounded-full flex items-center justify-center mb-3\" style={{\n backgroundColor: 'hsl(var(--chat-surface))'\n }}>\n <SearchIcon className=\"h-5 w-5\" style={{ color: 'hsl(var(--chat-text-subtle))' }} strokeWidth={2} />\n </div>\n <p className=\"text-[13px] font-medium mb-0.5\" style={{ color: 'hsl(var(--chat-text))' }}>No Results</p>\n <p className=\"text-[12px]\" style={{ color: 'hsl(var(--chat-text-muted))' }}>Try a different search</p>\n </div>\n ) : (\n <div className=\"py-0.5\">\n {groupedConversations.map(([groupName, groupConversations]) => (\n <div key={groupName} className=\"mb-0.5\">\n {/* Group Header */}\n <div className=\"px-2.5 py-1 sticky top-0 backdrop-blur-sm z-10\" style={{\n backgroundColor: 'var(--chat-header-bg-strong)'\n }}>\n <h3 className=\"text-[10px] font-semibold uppercase tracking-wide\" style={{ color: 'hsl(var(--chat-text-muted))' }}>{groupName}</h3>\n </div>\n\n {/* Conversation Items */}\n <div className=\"px-1 space-y-0.5\">\n {groupConversations.map((conversation) => {\n const isActiveConversation = activeTabId === conversation.id;\n return (\n <button\n key={conversation.id}\n className=\"w-full px-2 py-1 rounded-md transition-all duration-150 text-left group relative\"\n style={{\n backgroundColor: isActiveConversation\n ? ('hsl(var(--chat-surface))')\n : 'transparent'\n }}\n onMouseEnter={(e) => {\n if (!isActiveConversation) {\n e.currentTarget.style.backgroundColor = 'var(--chat-hover-bg)';\n }\n }}\n onMouseLeave={(e) => {\n if (!isActiveConversation) {\n e.currentTarget.style.backgroundColor = 'transparent';\n }\n }}\n onClick={() => handleSelectConversation(conversation.id, conversation.title)}\n >\n <div className=\"flex items-center gap-1.5\">\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-[12px] line-clamp-1 transition-colors leading-tight\" style={{\n fontWeight: isActiveConversation ? 500 : 400,\n color: isActiveConversation\n ? ('hsl(var(--chat-text))')\n : ('hsl(var(--chat-text-strong))')\n }}>\n {conversation.title}\n </p>\n </div>\n <ChevronRightIcon\n className=\"h-3 w-3 transition-all duration-150 flex-shrink-0\"\n style={{\n color: 'hsl(var(--chat-text-subtle))',\n opacity: isActiveConversation ? 1 : 0\n }}\n strokeWidth={2}\n />\n </div>\n </button>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n\n {/* Consumer-supplied header actions (expand, settings, etc.)\n rendered before the close button so they sit to its left. */}\n {headerActions}\n\n {/* Close Chat Widget Button */}\n {onClose && (\n <button\n onClick={onClose}\n className=\"flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150\"\n style={{\n color: 'hsl(var(--chat-text-muted))'\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.color = 'hsl(var(--chat-text))';\n e.currentTarget.style.backgroundColor = 'hsl(var(--chat-surface))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.color = 'hsl(var(--chat-text-muted))';\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n title=\"Close Chat\"\n >\n <XIcon className=\"h-4 w-4\" strokeWidth={2} />\n </button>\n )}\n </div>\n </div>\n\n <Conversation className=\"flex-1 max-w-full ai-assistant-scrollbar\">\n <ConversationContent className=\"max-w-[96%] mx-auto py-6\">\n {renderMessages()}\n {status === 'submitted' && (\n <div className=\"mt-6\">\n <Message from=\"assistant\">\n <MessageContent>\n <Loader size={16} />\n </MessageContent>\n </Message>\n </div>\n )}\n </ConversationContent>\n <ConversationScrollButton />\n </Conversation>\n\n <div className=\"px-5 pb-5\">\n {/* Upload Error Display */}\n {uploadError && (\n <div className=\"mb-3 px-4 py-3 bg-red-50 dark:bg-red-900/20 border border-red-200/60 dark:border-red-800/60 rounded-2xl text-sm text-red-700 dark:text-red-400 shadow-sm\">\n {uploadError}\n </div>\n )}\n\n {/* While we're still hydrating tabs from localStorage and the\n active tab from the API, hold render so we don't briefly flash\n the starter prompts before the previous conversation arrives.\n Once initialised, either show prompts (if truly empty) or the\n messages above this block. */}\n {(isInitializing || isLoadingMessages) ? (\n <div className=\"flex items-center justify-center py-8\" role=\"status\" aria-label=\"Loading conversation\">\n <div className=\"h-4 w-4 rounded-full border-2 border-current border-t-transparent animate-spin\" style={{ color: 'hsl(var(--chat-text-muted))' }} />\n </div>\n ) : (\n messages.length === 0 && status !== 'submitted' && config?.starterPrompts && (\n <StarterMessages\n prompts={config.starterPrompts}\n onPromptSelect={(prompt) => {\n handleSubmit({ text: prompt.title });\n }}\n />\n )\n )}\n\n <PromptInput onSubmit={handleSubmit} globalDrop multiple accept=\"image/*\">\n <PromptInputBody>\n <PromptInputAttachments>\n {(attachment) => <PromptInputAttachment data={attachment} />}\n </PromptInputAttachments>\n <div className=\"relative\">\n <PromptInputTextarea\n ref={inputRef}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={inputPlugins.onKeyDown}\n value={input}\n />\n {inputPlugins.popover}\n </div>\n </PromptInputBody>\n <PromptInputToolbar>\n <PromptInputTools>\n {config?.features?.fileUpload === true && <AttachButton />}\n </PromptInputTools>\n <PromptInputSubmit disabled={!input} status={status} />\n </PromptInputToolbar>\n </PromptInput>\n </div>\n </div>\n </div>\n );\n}","\"use client\";\n\nimport { cn } from \"../utils/cn\";\nimport { type ComponentProps, memo } from \"react\";\nimport { Streamdown } from \"streamdown\";\nimport { useCodeBlockAutoScroll } from \"../hooks/use-code-scroll\";\n\ntype ResponseProps = ComponentProps<typeof Streamdown> & {\n isStreaming?: boolean;\n};\n\nexport const Response = memo(\n ({ className, isStreaming = false, ...props }: ResponseProps) => {\n const containerRef = useCodeBlockAutoScroll(isStreaming);\n\n return (\n <div ref={containerRef}>\n <Streamdown\n className={cn(\n \"size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0\",\n className\n )}\n {...props}\n />\n </div>\n );\n },\n (prevProps, nextProps) => prevProps.children === nextProps.children\n);\n\nResponse.displayName = \"Response\";\n","import { useEffect, useRef } from \"react\";\n\nexport function useCodeBlockAutoScroll(isStreaming: boolean) {\n const observerRef = useRef<MutationObserver | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!isStreaming || !containerRef.current) {\n // Clean up observer when not streaming\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n return;\n }\n\n // Create observer only when streaming starts\n observerRef.current = new MutationObserver(() => {\n if (!containerRef.current) return;\n\n const codeBlocks = containerRef.current.querySelectorAll(\"pre\");\n codeBlocks.forEach((pre) => {\n pre.scrollTop = pre.scrollHeight;\n });\n });\n\n // Observe the container for changes\n observerRef.current.observe(containerRef.current, {\n childList: true,\n subtree: true,\n characterData: true,\n });\n\n return () => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n }\n };\n }, [isStreaming]);\n\n return containerRef;\n}\n","\"use client\"\n\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\"\n\nfunction Collapsible({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />\n}\n\nfunction CollapsibleTrigger({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {\n return (\n <CollapsiblePrimitive.CollapsibleTrigger\n data-slot=\"collapsible-trigger\"\n {...props}\n />\n )\n}\n\nfunction CollapsibleContent({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {\n return (\n <CollapsiblePrimitive.CollapsibleContent\n data-slot=\"collapsible-content\"\n {...props}\n />\n )\n}\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent }\n","\"use client\";\n\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../ui/collapsible\";\nimport { cn } from \"../utils/cn\";\nimport { BookIcon, ChevronDownIcon } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\n\nexport type SourcesProps = ComponentProps<\"div\">;\n\nexport const Sources = ({ className, ...props }: SourcesProps) => (\n <Collapsible\n className={cn(\"not-prose mb-4 text-primary text-xs\", className)}\n {...props}\n />\n);\n\nexport type SourcesTriggerProps = ComponentProps<typeof CollapsibleTrigger> & {\n count: number;\n};\n\nexport const SourcesTrigger = ({\n className,\n count,\n children,\n ...props\n}: SourcesTriggerProps) => (\n <CollapsibleTrigger\n className={cn(\"flex items-center gap-2\", className)}\n {...props}\n >\n {children ?? (\n <>\n <p className=\"font-medium\">Used {count} sources</p>\n <ChevronDownIcon className=\"h-4 w-4\" />\n </>\n )}\n </CollapsibleTrigger>\n);\n\nexport type SourcesContentProps = ComponentProps<typeof CollapsibleContent>;\n\nexport const SourcesContent = ({\n className,\n ...props\n}: SourcesContentProps) => (\n <CollapsibleContent\n className={cn(\n \"mt-3 flex w-fit flex-col gap-2\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className\n )}\n {...props}\n />\n);\n\nexport type SourceProps = ComponentProps<\"a\">;\n\nexport const Source = ({ href, title, children, ...props }: SourceProps) => (\n <a\n className=\"flex items-center gap-2\"\n href={href}\n rel=\"noreferrer\"\n target=\"_blank\"\n {...props}\n >\n {children ?? (\n <>\n <BookIcon className=\"h-4 w-4\" />\n <span className=\"block font-medium\">{title}</span>\n </>\n )}\n </a>\n);\n","\"use client\";\n\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../ui/collapsible\";\nimport { cn } from \"../utils/cn\";\nimport { BrainIcon, ChevronDownIcon } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\nimport { createContext, memo, useContext, useEffect, useState } from \"react\";\nimport { Response } from \"./response\";\n\ntype ReasoningContextValue = {\n isStreaming: boolean;\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n duration: number;\n};\n\nconst ReasoningContext = createContext<ReasoningContextValue | null>(null);\n\nconst useReasoning = () => {\n const context = useContext(ReasoningContext);\n if (!context) {\n throw new Error(\"Reasoning components must be used within Reasoning\");\n }\n return context;\n};\n\nexport type ReasoningProps = ComponentProps<typeof Collapsible> & {\n isStreaming?: boolean;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n duration?: number;\n};\n\nconst AUTO_CLOSE_DELAY = 1000;\nconst MS_IN_S = 1000;\n\nexport const Reasoning = memo(\n ({\n className,\n isStreaming = false,\n open,\n defaultOpen = true,\n onOpenChange,\n duration: durationProp,\n children,\n ...props\n }: ReasoningProps) => {\n const [isOpen, setIsOpen] = useControllableState({\n prop: open,\n defaultProp: defaultOpen,\n onChange: onOpenChange,\n });\n const [duration, setDuration] = useControllableState({\n prop: durationProp,\n defaultProp: undefined,\n });\n\n const [hasAutoClosed, setHasAutoClosed] = useState(false);\n const [startTime, setStartTime] = useState<number | null>(null);\n\n // Track duration when streaming starts and ends\n useEffect(() => {\n if (isStreaming) {\n if (startTime === null) {\n setStartTime(Date.now());\n }\n } else if (startTime !== null) {\n setDuration(Math.ceil((Date.now() - startTime) / MS_IN_S));\n setStartTime(null);\n }\n }, [isStreaming, startTime, setDuration]);\n\n // Auto-open when streaming starts, auto-close when streaming ends (once only)\n // For loaded chats (durationProp is undefined and not streaming), don't auto-close\n useEffect(() => {\n if (defaultOpen && !isStreaming && isOpen && !hasAutoClosed && durationProp !== undefined) {\n // Add a small delay before closing to allow user to see the content\n const timer = setTimeout(() => {\n setIsOpen(false);\n setHasAutoClosed(true);\n }, AUTO_CLOSE_DELAY);\n\n return () => clearTimeout(timer);\n }\n }, [isStreaming, isOpen, defaultOpen, setIsOpen, hasAutoClosed, durationProp]);\n\n const handleOpenChange = (newOpen: boolean) => {\n setIsOpen(newOpen);\n };\n\n return (\n <ReasoningContext.Provider\n value={{ isStreaming, isOpen, setIsOpen, duration }}\n >\n <Collapsible\n className={cn(\"not-prose\", className)}\n onOpenChange={handleOpenChange}\n open={isOpen}\n {...props}\n >\n {children}\n </Collapsible>\n </ReasoningContext.Provider>\n );\n }\n);\n\nexport type ReasoningTriggerProps = ComponentProps<typeof CollapsibleTrigger>;\n\nconst getThinkingMessage = (isStreaming: boolean, duration?: number) => {\n if (isStreaming) {\n return <>Thinking...</>;\n }\n if (duration === undefined) {\n return <>Thought process</>;\n }\n if (duration === 0) {\n return <>Thought process</>;\n }\n return <>Thought for {duration} seconds</>;\n};\n\nexport const ReasoningTrigger = memo(\n ({ className, children, ...props }: ReasoningTriggerProps) => {\n const { isStreaming, isOpen, duration } = useReasoning();\n\n return (\n <CollapsibleTrigger\n className={cn(\n \"flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground\",\n className\n )}\n {...props}\n >\n {children ?? (\n <>\n <BrainIcon className=\"size-4 flex-shrink-0\" />\n {getThinkingMessage(isStreaming, duration)}\n <ChevronDownIcon\n className={cn(\n \"size-4 flex-shrink-0 transition-transform ml-1\",\n isOpen ? \"rotate-180\" : \"rotate-0\"\n )}\n />\n </>\n )}\n </CollapsibleTrigger>\n );\n }\n);\n\nexport type ReasoningContentProps = ComponentProps<\n typeof CollapsibleContent\n> & {\n children: string;\n};\n\nexport const ReasoningContent = memo(\n ({ className, children, ...props }: ReasoningContentProps) => (\n <CollapsibleContent\n className={cn(\n \"mt-4 text-sm\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className\n )}\n {...props}\n >\n <Response className=\"grid gap-2\">{children}</Response>\n </CollapsibleContent>\n )\n);\n\nReasoning.displayName = \"Reasoning\";\nReasoningTrigger.displayName = \"ReasoningTrigger\";\nReasoningContent.displayName = \"ReasoningContent\";\n","import { cn } from \"../utils/cn\";\nimport type { HTMLAttributes } from \"react\";\n\ntype LoaderIconProps = {\n size?: number;\n};\n\nconst LoaderIcon = ({ size = 16 }: LoaderIconProps) => (\n <svg\n height={size}\n strokeLinejoin=\"round\"\n style={{ color: \"currentcolor\" }}\n viewBox=\"0 0 16 16\"\n width={size}\n >\n <title>Loader</title>\n <g clipPath=\"url(#clip0_2393_1490)\">\n <path d=\"M8 0V4\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path\n d=\"M8 16V12\"\n opacity=\"0.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M3.29773 1.52783L5.64887 4.7639\"\n opacity=\"0.9\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M12.7023 1.52783L10.3511 4.7639\"\n opacity=\"0.1\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M12.7023 14.472L10.3511 11.236\"\n opacity=\"0.4\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M3.29773 14.472L5.64887 11.236\"\n opacity=\"0.6\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M15.6085 5.52783L11.8043 6.7639\"\n opacity=\"0.2\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M0.391602 10.472L4.19583 9.23598\"\n opacity=\"0.7\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M15.6085 10.4722L11.8043 9.2361\"\n opacity=\"0.3\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M0.391602 5.52783L4.19583 6.7639\"\n opacity=\"0.8\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n </g>\n <defs>\n <clipPath id=\"clip0_2393_1490\">\n <rect fill=\"white\" height=\"16\" width=\"16\" />\n </clipPath>\n </defs>\n </svg>\n);\n\nexport type LoaderProps = HTMLAttributes<HTMLDivElement> & {\n size?: number;\n};\n\nexport const Loader = ({ className, size = 16, ...props }: LoaderProps) => (\n <div\n className={cn(\n \"inline-flex animate-spin items-center justify-center\",\n className\n )}\n {...props}\n >\n <LoaderIcon size={size} />\n </div>\n);\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../utils/cn\"\n\nconst badgeVariants = cva(\n \"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden\",\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Badge({\n className,\n variant,\n asChild = false,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"span\"\n\n return (\n <Comp\n data-slot=\"badge\"\n className={cn(badgeVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nexport { Badge, badgeVariants }\n","\"use client\";\n\nimport { Badge } from \"../ui/badge\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../ui/collapsible\";\nimport { cn } from \"../utils/cn\";\nimport type { ToolUIPart } from \"ai\";\nimport {\n CheckCircleIcon,\n ChevronDownIcon,\n CircleIcon,\n ClockIcon,\n WrenchIcon,\n XCircleIcon,\n} from \"lucide-react\";\nimport type { ComponentProps, ReactNode } from \"react\";\nimport { isValidElement } from \"react\";\nimport { CodeBlock } from \"./code-block\";\n\nexport type ToolProps = ComponentProps<typeof Collapsible>;\n\nexport const Tool = ({ className, ...props }: ToolProps) => (\n <Collapsible\n className={cn(\"not-prose w-full rounded-md border border-[var(--chat-divider)]\", className)}\n {...props}\n />\n);\n\nexport type ToolHeaderProps = {\n title?: string;\n type: ToolUIPart[\"type\"] | \"dynamic-tool\";\n /**\n * Set when the part is a `dynamic-tool` UIPart (MCP / `dynamicTool()`).\n * For these the `type` is always `\"dynamic-tool\"`, so the actual tool\n * identity lives in `toolName`. When provided, it wins over the parsed\n * type fragment so the header shows e.g. `get_financials` instead of\n * the generic `tool`.\n */\n toolName?: string;\n state: ToolUIPart[\"state\"];\n className?: string;\n};\n\nconst getStatusBadge = (status: ToolUIPart[\"state\"]) => {\n const labels = {\n \"input-streaming\": \"Pending\",\n \"input-available\": \"Running\",\n \"output-available\": \"Completed\",\n \"output-error\": \"Error\",\n } as const;\n\n const icons = {\n \"input-streaming\": <CircleIcon className=\"size-4\" />,\n \"input-available\": <ClockIcon className=\"size-4 animate-pulse\" />,\n \"output-available\": <CheckCircleIcon className=\"size-4 text-green-600\" />,\n \"output-error\": <XCircleIcon className=\"size-4 text-red-600\" />,\n } as const;\n\n return (\n <Badge className=\"gap-1.5 rounded-full text-xs\" variant=\"secondary\">\n {icons[status]}\n {labels[status]}\n </Badge>\n );\n};\n\nexport const ToolHeader = ({\n className,\n title,\n type,\n toolName,\n state,\n ...props\n}: ToolHeaderProps) => (\n <CollapsibleTrigger\n className={cn(\n \"flex w-full items-center justify-between gap-4 p-2\",\n className\n )}\n {...props}\n >\n <div className=\"flex items-center gap-2\">\n <WrenchIcon className=\"size-4 text-muted-foreground\" />\n <span className=\"font-medium text-sm\">\n {title ?? toolName ?? type.split(\"-\").slice(1).join(\"-\")}\n </span>\n {getStatusBadge(state)}\n </div>\n <ChevronDownIcon className=\"size-4 text-muted-foreground transition-transform group-data-[state=open]:rotate-180\" />\n </CollapsibleTrigger>\n);\n\nexport type ToolContentProps = ComponentProps<typeof CollapsibleContent>;\n\nexport const ToolContent = ({ className, ...props }: ToolContentProps) => (\n <CollapsibleContent\n className={cn(\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className\n )}\n {...props}\n />\n);\n\nexport type ToolInputProps = ComponentProps<\"div\"> & {\n input: ToolUIPart[\"input\"];\n};\n\nexport const ToolInput = ({ className, input, ...props }: ToolInputProps) => (\n <div className={cn(\"space-y-2 overflow-hidden p-2\", className)} {...props}>\n <h4 className=\"font-medium text-muted-foreground text-xs uppercase tracking-wide\">\n Parameters\n </h4>\n <div className=\"rounded-md bg-muted/50\">\n <CodeBlock code={JSON.stringify(input, null, 2)} language=\"json\" />\n </div>\n </div>\n);\n\nexport type ToolOutputProps = ComponentProps<\"div\"> & {\n output: ToolUIPart[\"output\"];\n errorText: ToolUIPart[\"errorText\"];\n};\n\nexport const ToolOutput = ({\n className,\n output,\n errorText,\n ...props\n}: ToolOutputProps) => {\n if (!(output || errorText)) {\n return null;\n }\n\n let Output = <div>{output as ReactNode}</div>;\n\n if (typeof output === \"object\" && !isValidElement(output)) {\n Output = (\n <CodeBlock code={JSON.stringify(output, null, 2)} language=\"json\" />\n );\n } else if (typeof output === \"string\") {\n Output = <CodeBlock code={output} language=\"json\" />;\n }\n\n return (\n <div className={cn(\"space-y-2 p-2\", className)} {...props}>\n <h4 className=\"font-medium text-muted-foreground text-xs uppercase tracking-wide\">\n {errorText ? \"Error\" : \"Result\"}\n </h4>\n <div\n className={cn(\n \"overflow-x-auto rounded-md text-xs [&_table]:w-full\",\n errorText\n ? \"bg-destructive/10 text-destructive\"\n : \"bg-muted/50 text-foreground\"\n )}\n >\n {errorText && <div>{errorText}</div>}\n {Output}\n </div>\n </div>\n );\n};\n","\"use client\";\n\nimport { Button } from \"../ui/button\";\nimport { cn } from \"../utils/cn\";\nimport { CheckIcon, CopyIcon } from \"lucide-react\";\nimport type { ComponentProps, HTMLAttributes, ReactNode } from \"react\";\nimport { createContext, useContext, useState } from \"react\";\nimport { Prism as SyntaxHighlighter } from \"react-syntax-highlighter\";\nimport {\n oneDark,\n oneLight,\n} from \"react-syntax-highlighter/dist/esm/styles/prism\";\n\ntype CodeBlockContextType = {\n code: string;\n};\n\nconst CodeBlockContext = createContext<CodeBlockContextType>({\n code: \"\",\n});\n\nexport type CodeBlockProps = HTMLAttributes<HTMLDivElement> & {\n code: string;\n language: string;\n showLineNumbers?: boolean;\n children?: ReactNode;\n};\n\nexport const CodeBlock = ({\n code,\n language,\n showLineNumbers = false,\n className,\n children,\n ...props\n}: CodeBlockProps) => (\n <CodeBlockContext.Provider value={{ code }}>\n <div\n className={cn(\n \"relative w-full overflow-hidden rounded-lg bg-[hsl(var(--chat-text)/0.03)] border border-[var(--chat-divider)]\",\n className\n )}\n {...props}\n >\n <div className=\"relative max-h-96 overflow-y-auto\">\n <SyntaxHighlighter\n className=\"overflow-hidden dark:hidden\"\n codeTagProps={{\n className: \"font-mono text-sm\",\n }}\n customStyle={{\n margin: 0,\n padding: \"1rem\",\n fontSize: \"0.875rem\",\n background: \"transparent\",\n color: \"hsl(var(--chat-text))\",\n border: \"none\",\n }}\n language={language}\n lineNumberStyle={{\n color: \"hsl(var(--chat-text) / 0.4)\",\n paddingRight: \"1rem\",\n minWidth: \"2.5rem\",\n }}\n showLineNumbers={showLineNumbers}\n style={oneLight}\n >\n {code}\n </SyntaxHighlighter>\n <SyntaxHighlighter\n className=\"hidden overflow-hidden dark:block\"\n codeTagProps={{\n className: \"font-mono text-sm\",\n }}\n customStyle={{\n margin: 0,\n padding: \"1rem\",\n fontSize: \"0.875rem\",\n background: \"transparent\",\n color: \"hsl(var(--chat-text))\",\n border: \"none\",\n }}\n language={language}\n lineNumberStyle={{\n color: \"hsl(var(--chat-text) / 0.4)\",\n paddingRight: \"1rem\",\n minWidth: \"2.5rem\",\n }}\n showLineNumbers={showLineNumbers}\n style={oneDark}\n >\n {code}\n </SyntaxHighlighter>\n {children && (\n <div className=\"absolute top-2 right-2 flex items-center gap-2\">\n {children}\n </div>\n )}\n </div>\n </div>\n </CodeBlockContext.Provider>\n);\n\nexport type CodeBlockCopyButtonProps = ComponentProps<typeof Button> & {\n onCopy?: () => void;\n onError?: (error: Error) => void;\n timeout?: number;\n};\n\nexport const CodeBlockCopyButton = ({\n onCopy,\n onError,\n timeout = 2000,\n children,\n className,\n ...props\n}: CodeBlockCopyButtonProps) => {\n const [isCopied, setIsCopied] = useState(false);\n const { code } = useContext(CodeBlockContext);\n\n const copyToClipboard = async () => {\n if (typeof window === \"undefined\" || !navigator.clipboard.writeText) {\n onError?.(new Error(\"Clipboard API not available\"));\n return;\n }\n\n try {\n await navigator.clipboard.writeText(code);\n setIsCopied(true);\n onCopy?.();\n setTimeout(() => setIsCopied(false), timeout);\n } catch (error) {\n onError?.(error as Error);\n }\n };\n\n const Icon = isCopied ? CheckIcon : CopyIcon;\n\n return (\n <Button\n className={cn(\"shrink-0\", className)}\n onClick={copyToClipboard}\n size=\"icon\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <Icon size={14} />}\n </Button>\n );\n};\n","\"use client\";\n\nimport { cn } from \"../utils/cn\";\nimport { type HTMLAttributes } from \"react\";\nimport type { StarterPrompt } from \"../types\";\n\nexport type { StarterPrompt };\n\nexport type StarterMessagesProps = Omit<HTMLAttributes<HTMLDivElement>, 'onSelect'> & {\n prompts: StarterPrompt[];\n onPromptSelect: (prompt: StarterPrompt) => void;\n};\n\nexport function StarterMessages({\n className,\n prompts,\n onPromptSelect,\n ...props\n}: StarterMessagesProps) {\n if (prompts.length === 0) return null;\n\n return (\n <div\n className={cn(\n \"mb-3\",\n className\n )}\n {...props}\n >\n {prompts.map((prompt, index) => (\n <div key={index}>\n <StarterMessageItem\n prompt={prompt}\n onClick={() => onPromptSelect(prompt)}\n />\n {index < prompts.length - 1 && (\n // 1px-tall element used as a divider — same --chat-divider token\n // every other separator in the widget uses, so consumers only\n // need to override one variable to recolour all of them.\n <div className=\"h-px mx-3\" style={{ backgroundColor: 'var(--chat-divider)' }} />\n )}\n </div>\n ))}\n </div>\n );\n}\n\nexport type StarterMessageItemProps = HTMLAttributes<HTMLButtonElement> & {\n prompt: StarterPrompt;\n};\n\nexport function StarterMessageItem({\n className,\n prompt,\n onClick,\n ...props\n}: StarterMessageItemProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n \"w-full text-left px-3 py-2.5 rounded-lg\",\n \"bg-transparent\",\n \"hover:bg-[hsl(var(--chat-text)/0.03)]\",\n \"transition-colors duration-150 ease-out\",\n \"cursor-pointer\",\n className\n )}\n {...props}\n >\n <span className=\"text-[13px] text-[hsl(var(--chat-text)/0.7)]\">\n {prompt.title}\n </span>\n {prompt.subtitle && (\n <span className=\"block text-[11px] text-[hsl(var(--chat-text)/0.4)] mt-0.5\">\n {prompt.subtitle}\n </span>\n )}\n </button>\n );\n}\n","'use client';\n\nimport { createContext, useContext, ReactNode } from 'react';\n\ninterface ChatStorageContextValue {\n storageKeyPrefix: string;\n}\n\nconst ChatStorageContext = createContext<ChatStorageContextValue>({\n storageKeyPrefix: '',\n});\n\nexport function ChatStorageProvider({\n children,\n userId,\n}: {\n children: ReactNode;\n userId?: string;\n}) {\n // Use userId as the storage key prefix to isolate data between users/deployments\n const storageKeyPrefix = userId || '';\n\n return (\n <ChatStorageContext.Provider value={{ storageKeyPrefix }}>\n {children}\n </ChatStorageContext.Provider>\n );\n}\n\nexport function useChatStorageKey() {\n return useContext(ChatStorageContext);\n}\n","/**\n * Convert a `#rrggbb` hex color into the space-separated HSL triplet format\n * the widget's CSS variables consume (e.g. `\"215 20% 25%\"` — used inside\n * `hsl(var(--chat-primary))`). Non-hex inputs (named, rgb(), already-triplet)\n * are returned unchanged so callers can opt out by passing a triplet directly.\n *\n * Kept tiny on purpose: this is the only place hex/rgb conversion happens at\n * runtime. The widget's settings panel has its own copy in use-chat-theme.ts\n * because that path runs before ChatWidget mounts.\n */\nexport function toHslTripletIfHex(value: string): string {\n const trimmed = value.trim();\n const hexMatch = /^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.exec(trimmed);\n if (!hexMatch) return value;\n\n let hex = hexMatch[1];\n if (hex.length === 3) {\n hex = hex.split('').map((c) => c + c).join('');\n }\n\n const r = parseInt(hex.substring(0, 2), 16) / 255;\n const g = parseInt(hex.substring(2, 4), 16) / 255;\n const b = parseInt(hex.substring(4, 6), 16) / 255;\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n\n let h = 0;\n let s = 0;\n if (max !== min) {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r:\n h = ((g - b) / d + (g < b ? 6 : 0)) / 6;\n break;\n case g:\n h = ((b - r) / d + 2) / 6;\n break;\n case b:\n h = ((r - g) / d + 4) / 6;\n break;\n }\n }\n\n return `${Math.round(h * 360)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;\n}\n","import { useState, useEffect } from 'react';\nimport { DEFAULT_MODEL } from '../utils/models';\nimport { useChatStorageKey } from '../contexts/chat-storage-context';\n\n// Helper function to convert HEX to HSL format that Tailwind expects\n// Tailwind expects HSL in format: \"0 0% 0%\" (no hsl() wrapper, space-separated)\nfunction hexToHSL(hex: string): string {\n // Remove # if present\n hex = hex.replace('#', '');\n\n // Convert hex to RGB\n const r = parseInt(hex.substring(0, 2), 16) / 255;\n const g = parseInt(hex.substring(2, 4), 16) / 255;\n const b = parseInt(hex.substring(4, 6), 16) / 255;\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n let h = 0;\n let s = 0;\n const l = (max + min) / 2;\n\n if (max !== min) {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n\n switch (max) {\n case r:\n h = ((g - b) / d + (g < b ? 6 : 0)) / 6;\n break;\n case g:\n h = ((b - r) / d + 2) / 6;\n break;\n case b:\n h = ((r - g) / d + 4) / 6;\n break;\n }\n }\n\n // Convert to Tailwind format: \"hue saturation% lightness%\"\n return `${Math.round(h * 360)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;\n}\n\nexport interface ChatTheme {\n // Light mode colors\n lightPrimary: string; // Primary color (buttons, user messages, accents)\n lightSecondary: string; // Secondary color (backgrounds, surfaces)\n lightText: string; // Text color\n\n // Dark mode colors\n darkPrimary: string; // Primary color in dark mode\n darkSecondary: string; // Secondary color in dark mode\n darkText: string; // Text color in dark mode\n\n // Typography\n fontFamily: string; // Font family for chat text\n fontSize: number; // Font size in pixels (12-18)\n}\n\nexport type ThemeMode = 'light' | 'dark';\n\nexport interface ConversationStarter {\n text: string;\n enabled: boolean;\n}\n\n// Default theme with sensible light and dark mode colors\nconst defaultTheme: ChatTheme = {\n // Light mode\n lightPrimary: '#3b82f6', // Blue\n lightSecondary: '#f5f5f5', // Light gray\n lightText: '#0a0a0a', // Near black\n\n // Dark mode\n darkPrimary: '#3b82f6', // Blue (same as light)\n darkSecondary: '#262626', // Dark gray\n darkText: '#ffffff', // White\n\n // Typography\n fontFamily: 'system-ui',\n fontSize: 14,\n};\n\n// Font options\nexport const fontOptions = [\n { value: 'system-ui', label: 'System Default' },\n { value: 'Inter, sans-serif', label: 'Inter' },\n { value: 'Roboto, sans-serif', label: 'Roboto' },\n { value: 'Open Sans, sans-serif', label: 'Open Sans' },\n { value: 'Lato, sans-serif', label: 'Lato' },\n { value: 'Poppins, sans-serif', label: 'Poppins' },\n { value: 'Montserrat, sans-serif', label: 'Montserrat' },\n { value: 'Georgia, serif', label: 'Georgia' },\n { value: 'ui-monospace, monospace', label: 'Monospace' },\n];\nconst defaultConversationStarters: ConversationStarter[] = [\n { text: 'How can I help you today?', enabled: true },\n { text: 'What features does this product offer?', enabled: true },\n { text: 'Tell me about your capabilities', enabled: true },\n];\nconst defaultModel = DEFAULT_MODEL;\nconst defaultSystemPrompt = 'You are a helpful AI assistant.';\nconst defaultTemperature = 0.7;\nconst defaultThemeMode: ThemeMode = 'light';\n\nexport function useChatTheme() {\n // Get storage key prefix from context to scope localStorage keys per user/deployment\n const { storageKeyPrefix } = useChatStorageKey();\n const keyPrefix = storageKeyPrefix ? `chat-${storageKeyPrefix}-` : 'chat-';\n\n const [theme, setTheme] = useState<ChatTheme>(defaultTheme);\n const [conversationStarters, setConversationStarters] = useState<ConversationStarter[]>(defaultConversationStarters);\n const [model, setModel] = useState<string>(defaultModel);\n const [systemPrompt, setSystemPrompt] = useState<string>(defaultSystemPrompt);\n const [temperature, setTemperature] = useState<number>(defaultTemperature);\n const [themeMode, setThemeMode] = useState<ThemeMode>(defaultThemeMode);\n\n // Load theme from localStorage on mount\n useEffect(() => {\n const savedTheme = localStorage.getItem(`${keyPrefix}theme`);\n if (savedTheme) {\n try {\n setTheme(JSON.parse(savedTheme));\n } catch (error) {\n console.error('Error loading theme:', error);\n }\n }\n\n const savedStarters = localStorage.getItem(`${keyPrefix}conversation-starters`);\n if (savedStarters) {\n try {\n setConversationStarters(JSON.parse(savedStarters));\n } catch (error) {\n console.error('Error loading conversation starters:', error);\n }\n }\n\n const savedModel = localStorage.getItem(`${keyPrefix}model`);\n if (savedModel) {\n try {\n setModel(savedModel);\n } catch (error) {\n console.error('Error loading model:', error);\n }\n }\n\n const savedSystemPrompt = localStorage.getItem(`${keyPrefix}system-prompt`);\n if (savedSystemPrompt) {\n try {\n setSystemPrompt(savedSystemPrompt);\n } catch (error) {\n console.error('Error loading system prompt:', error);\n }\n }\n\n const savedTemperature = localStorage.getItem(`${keyPrefix}temperature`);\n if (savedTemperature) {\n try {\n setTemperature(parseFloat(savedTemperature));\n } catch (error) {\n console.error('Error loading temperature:', error);\n }\n }\n\n const savedThemeMode = localStorage.getItem(`${keyPrefix}theme-mode`);\n if (savedThemeMode) {\n try {\n setThemeMode(savedThemeMode as ThemeMode);\n } catch (error) {\n console.error('Error loading theme mode:', error);\n }\n }\n\n // Listen for changes from other components (same page via custom events)\n const handleThemeChange = (e: Event) => {\n const customEvent = e as CustomEvent;\n setTheme(customEvent.detail);\n };\n\n const handleStartersChange = (e: Event) => {\n const customEvent = e as CustomEvent;\n setConversationStarters(customEvent.detail);\n };\n\n const handleSystemPromptChange = (e: Event) => {\n const customEvent = e as CustomEvent;\n setSystemPrompt(customEvent.detail);\n };\n\n const handleModelChange = (e: Event) => {\n const customEvent = e as CustomEvent;\n setModel(customEvent.detail);\n };\n\n const handleTemperatureChange = (e: Event) => {\n const customEvent = e as CustomEvent;\n setTemperature(customEvent.detail);\n };\n\n const handleThemeModeChange = (e: Event) => {\n const customEvent = e as CustomEvent;\n setThemeMode(customEvent.detail);\n };\n\n window.addEventListener('chat-theme-change', handleThemeChange);\n window.addEventListener('chat-starters-change', handleStartersChange);\n window.addEventListener('chat-model-change', handleModelChange);\n window.addEventListener('chat-system-prompt-change', handleSystemPromptChange);\n window.addEventListener('chat-temperature-change', handleTemperatureChange);\n window.addEventListener('chat-theme-mode-change', handleThemeModeChange);\n\n return () => {\n window.removeEventListener('chat-theme-change', handleThemeChange);\n window.removeEventListener('chat-starters-change', handleStartersChange);\n window.removeEventListener('chat-model-change', handleModelChange);\n window.removeEventListener('chat-system-prompt-change', handleSystemPromptChange);\n window.removeEventListener('chat-temperature-change', handleTemperatureChange);\n window.removeEventListener('chat-theme-mode-change', handleThemeModeChange);\n };\n }, [keyPrefix]);\n\n // Save theme to localStorage whenever it changes\n useEffect(() => {\n localStorage.setItem(`${keyPrefix}theme`, JSON.stringify(theme));\n\n // Apply CSS variables to the document\n const root = document.documentElement;\n\n // Apply the appropriate colors based on theme mode\n // Convert HEX to HSL format that Tailwind expects\n if (themeMode === 'light') {\n root.style.setProperty('--chat-primary', hexToHSL(theme.lightPrimary));\n root.style.setProperty('--chat-secondary', hexToHSL(theme.lightSecondary));\n root.style.setProperty('--chat-text', hexToHSL(theme.lightText));\n } else {\n root.style.setProperty('--chat-primary', hexToHSL(theme.darkPrimary));\n root.style.setProperty('--chat-secondary', hexToHSL(theme.darkSecondary));\n root.style.setProperty('--chat-text', hexToHSL(theme.darkText));\n }\n\n // Typography (same for both modes)\n root.style.setProperty('--chat-font-family', theme.fontFamily);\n root.style.setProperty('--chat-font-size', `${theme.fontSize}px`);\n\n // Dispatch custom event for same-page sync\n window.dispatchEvent(new CustomEvent('chat-theme-change', { detail: theme }));\n }, [theme, themeMode, keyPrefix]);\n\n // Save conversation starters to localStorage whenever they change\n useEffect(() => {\n localStorage.setItem(`${keyPrefix}conversation-starters`, JSON.stringify(conversationStarters));\n\n // Dispatch custom event for same-page sync\n window.dispatchEvent(new CustomEvent('chat-starters-change', { detail: conversationStarters }));\n }, [conversationStarters, keyPrefix]);\n\n // Save model to localStorage whenever it changes\n useEffect(() => {\n localStorage.setItem(`${keyPrefix}model`, model);\n\n // Dispatch custom event for same-page sync\n window.dispatchEvent(new CustomEvent('chat-model-change', { detail: model }));\n }, [model, keyPrefix]);\n\n // Save system prompt to localStorage whenever it changes\n useEffect(() => {\n localStorage.setItem(`${keyPrefix}system-prompt`, systemPrompt);\n\n // Dispatch custom event for same-page sync\n window.dispatchEvent(new CustomEvent('chat-system-prompt-change', { detail: systemPrompt }));\n }, [systemPrompt, keyPrefix]);\n\n // Save temperature to localStorage whenever it changes\n useEffect(() => {\n localStorage.setItem(`${keyPrefix}temperature`, temperature.toString());\n\n // Dispatch custom event for same-page sync\n window.dispatchEvent(new CustomEvent('chat-temperature-change', { detail: temperature }));\n }, [temperature, keyPrefix]);\n\n // Save theme mode to localStorage whenever it changes\n useEffect(() => {\n localStorage.setItem(`${keyPrefix}theme-mode`, themeMode);\n\n // Dispatch custom event for same-page sync\n window.dispatchEvent(new CustomEvent('chat-theme-mode-change', { detail: themeMode }));\n }, [themeMode, keyPrefix]);\n\n const updateColor = (key: keyof ChatTheme, value: string | number) => {\n setTheme(prev => ({ ...prev, [key]: value }));\n };\n\n const updateLightColors = (colors: { primary?: string; secondary?: string; text?: string }) => {\n setTheme(prev => ({\n ...prev,\n ...(colors.primary && { lightPrimary: colors.primary }),\n ...(colors.secondary && { lightSecondary: colors.secondary }),\n ...(colors.text && { lightText: colors.text }),\n }));\n };\n\n const updateDarkColors = (colors: { primary?: string; secondary?: string; text?: string }) => {\n setTheme(prev => ({\n ...prev,\n ...(colors.primary && { darkPrimary: colors.primary }),\n ...(colors.secondary && { darkSecondary: colors.secondary }),\n ...(colors.text && { darkText: colors.text }),\n }));\n };\n\n const resetTheme = () => {\n setTheme(defaultTheme);\n };\n\n const updateFontSize = (size: number) => {\n setTheme(prev => ({ ...prev, fontSize: size }));\n };\n\n const updateFontFamily = (family: string) => {\n setTheme(prev => ({ ...prev, fontFamily: family }));\n };\n\n const updateConversationStarters = (starters: ConversationStarter[]) => {\n setConversationStarters(starters);\n };\n\n const updateSystemPrompt = (prompt: string) => {\n setSystemPrompt(prompt);\n };\n\n const updateModel = (selectedModel: string) => {\n setModel(selectedModel);\n };\n\n const updateTemperature = (temp: number) => {\n setTemperature(temp);\n };\n\n const updateThemeMode = (mode: ThemeMode) => {\n setThemeMode(mode);\n };\n\n return {\n theme,\n updateColor,\n updateLightColors,\n updateDarkColors,\n resetTheme,\n updateFontSize,\n updateFontFamily,\n conversationStarters,\n updateConversationStarters,\n model,\n updateModel,\n systemPrompt,\n updateSystemPrompt,\n temperature,\n updateTemperature,\n themeMode,\n updateThemeMode,\n };\n}\n","export const MODELS = [\n {\n name: 'GPT-5 Nano',\n value: 'openai/gpt-5-nano'\n },\n // Anthropic models\n {\n name: 'Claude Sonnet 4.5',\n value: 'anthropic/claude-sonnet-4-5',\n },\n {\n name: 'Claude Sonnet 4',\n value: 'anthropic/claude-sonnet-4-0',\n },\n {\n name: 'Claude Haiku 3.5',\n value: 'anthropic/claude-3-5-haiku-latest',\n },\n // OpenAI models\n {\n name: 'GPT-5',\n value: 'openai/gpt-5',\n },\n {\n name: 'GPT-OSS-120B',\n value: 'openai/gpt-oss-120b',\n },\n {\n name: 'GPT 4o',\n value: 'openai/gpt-4o',\n },\n // Google models\n {\n name: 'Gemini 2.5 Flash Lite',\n value: 'google/gemini-2.5-flash-lite',\n },\n {\n name: 'Gemini 2.5 Flash',\n value: 'google/gemini-2.5-flash',\n },\n {\n name: 'Gemini 2.5 Pro',\n value: 'google/gemini-2.5-pro',\n }\n];\n\nexport const DEFAULT_MODEL = MODELS[0].value;\n","import * as React from \"react\"\n\nimport { cn } from \"../utils/cn\"\n\nexport interface InputProps\n extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n \"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nInput.displayName = \"Input\"\n\nexport { Input }\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\"\nimport { XIcon } from \"lucide-react\"\n\nimport { cn } from \"../utils/cn\"\n\nfunction Dialog({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\nfunction DialogTrigger({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\nfunction DialogPortal({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />\n}\n\nfunction DialogClose({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n showCloseButton?: boolean\n}) {\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className=\"ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\"\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_jsx_runtime","import_class_variance_authority","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_lucide_react","import_react","import_jsx_runtime","React","Icon","import_lucide_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_lucide_react","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","CollapsibleTrigger","CollapsibleContent","import_lucide_react","import_jsx_runtime","CollapsibleTrigger","CollapsibleContent","import_lucide_react","import_react","import_jsx_runtime","CollapsibleTrigger","CollapsibleContent","import_jsx_runtime","import_react_slot","import_class_variance_authority","import_jsx_runtime","import_lucide_react","import_react","import_lucide_react","import_react","import_jsx_runtime","SyntaxHighlighter","import_jsx_runtime","CollapsibleTrigger","CollapsibleContent","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_react","React","import_jsx_runtime","import_lucide_react","import_jsx_runtime"]}
|