@gntik-ai/chat 0.9.0 → 0.10.0
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.js +32 -38
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["s","s","s","s","doc","s","doc","s","doc","s","doc","s","doc","s","doc","s","doc","s","doc","doc","s","doc","s","doc","doc"],"sources":["../src/utils/i18n.ts","../src/AgentSurface/SurfaceFocusBoundary.tsx","../src/AgentSurface/pointer.ts","../src/AgentSurface/protocol.ts","../src/AgentSurface/stream.ts","../src/utils/useCopy.ts","../src/utils/focus.ts","../src/Markdown/markdown.variants.ts","../src/Markdown/CodeBlock.tsx","../src/Markdown/Markdown.tsx","../src/AgentSurface/model.ts","../src/AgentSurface/AgentSurface.tsx","../src/AgentSurface/catalog-components.tsx","../src/AgentSurface/catalog.ts","../src/AgentSurface/AgentSurface.doc.ts","../src/utils/format.ts","../src/Attachment/attachment.variants.ts","../src/Attachment/AttachmentChip.tsx","../src/Attachment/AttachmentList.tsx","../src/Attachment/validateFiles.ts","../src/Attachment/Attachment.doc.ts","../src/ChatComposer/chatComposer.variants.ts","../src/ChatComposer/ChatComposer.tsx","../src/ChatComposer/ChatComposer.doc.ts","../src/TypingIndicator/typingIndicator.variants.ts","../src/TypingIndicator/TypingIndicator.tsx","../src/TypingIndicator/TypingIndicator.doc.ts","../src/ChatMessage/chatMessage.variants.ts","../src/ChatMessage/ChatMessage.tsx","../src/ChatMessage/ChatAnnouncer.tsx","../src/ChatMessage/ChatMessage.doc.ts","../src/MessageFeedback/messageFeedback.variants.ts","../src/MessageFeedback/MessageFeedback.tsx","../src/MessageFeedback/MessageFeedback.doc.ts","../src/ModelPicker/modelPicker.variants.ts","../src/ModelPicker/ModelPicker.tsx","../src/ModelPicker/fixtures.ts","../src/ModelPicker/ModelPicker.doc.ts","../src/useChatScroll/useChatScroll.ts","../src/ChatLayout/chatLayout.variants.ts","../src/ChatLayout/ChatLayout.tsx","../src/ChatLayout/ChatLayout.doc.ts","../src/Citation/citation.variants.ts","../src/Citation/Citation.tsx","../src/Citation/Citation.doc.ts","../src/Markdown/Markdown.doc.ts","../src/SuggestionChips/suggestionChips.variants.ts","../src/SuggestionChips/SuggestionChips.tsx","../src/SuggestionChips/SuggestionChips.doc.ts","../src/ToolCallCard/toolCallCard.variants.ts","../src/ToolCallCard/JsonView.tsx","../src/ToolCallCard/ToolCallCard.tsx","../src/ToolCallCard/ToolCallCard.doc.ts","../src/ChatDemo/demoScript.ts","../src/ChatDemo/ChatDemo.tsx","../src/ChatDemo/ChatDemo.doc.ts"],"sourcesContent":["import { interpolate, useI18n, type MessageKey, type MessageVars } from '@gntik-ai/ui';\n\n/**\n * English fallbacks for the chat keys added after the first `@gntik-ai/ui` release. The\n * strings live in the ui catalogs (en + es); these keep the pack readable when it runs\n * against an older `@gntik-ai/ui` whose catalog does not have them yet.\n */\nconst FALLBACK = {\n 'chat.surfaceExampleTitle': 'Review your details',\n 'chat.surfaceExampleName': 'Name',\n 'chat.surfaceExampleSubmit': 'Submit',\n 'chat.surfaceExampleChoice': 'Language',\n 'chat.surfaceExampleEnglish': 'English',\n 'chat.surfaceExampleSpanish': 'Spanish',\n 'chat.surfaceExampleNotify': 'Send updates',\n 'chat.surfaceExampleBadge': 'Draft',\n 'chat.surfaceExampleNotice': 'Check the information before submitting.',\n 'chat.surfaceExampleStatus': 'Submitted for {name}',\n 'chat.surfaceExamplePatch': 'Update name',\n 'chat.surfaceExampleRemove': 'Remove content',\n 'chat.surfaceExampleReset': 'Reset',\n 'chat.surfaceExampleUnsupported': 'Show unsupported content',\n 'chat.surfaceExampleRejected': 'Unsupported content was rejected.',\n 'chat.surfaceExampleLink': 'Read the documentation',\n 'chat.surfaceUnsupported': 'This content cannot be shown',\n 'chat.surfaceAgentContent': 'Agent content',\n 'chat.typing': '{author} is typing',\n 'chat.feedback': 'Response feedback',\n 'chat.feedbackTitle': 'What went wrong?',\n 'chat.feedbackReason': 'Reason',\n 'chat.feedbackComment': 'Comment (optional)',\n 'chat.feedbackPlaceholder': 'Tell us more…',\n 'chat.feedbackSubmit': 'Send feedback',\n 'chat.feedbackThanks': 'Thanks for your feedback',\n 'chat.feedbackCleared': 'Feedback removed',\n 'chat.reasonInaccurate': 'Inaccurate',\n 'chat.reasonUnhelpful': 'Not helpful',\n 'chat.reasonIncomplete': 'Incomplete',\n 'chat.reasonUnsafe': 'Harmful or unsafe',\n 'chat.reasonOther': 'Other',\n 'chat.regenerate': 'Regenerate',\n 'chat.uploading': 'Uploading {name}',\n 'chat.uploadFailed': 'Upload failed',\n 'chat.retryUpload': 'Retry uploading {name}',\n 'chat.dropFiles': 'Drop files to attach',\n 'chat.fileTooLarge': '{name} is larger than {max}',\n 'chat.fileTypeNotAllowed': '{name} is not an allowed file type',\n 'chat.tooManyFiles': 'You can attach up to {max} files',\n 'chat.model': 'Model',\n 'chat.selectModel': 'Select a model',\n 'chat.capabilityVision': 'Vision',\n 'chat.capabilityTools': 'Tools',\n 'chat.capabilityReasoning': 'Reasoning',\n 'chat.capabilityFiles': 'Files',\n 'chat.capabilityWeb': 'Web search',\n 'chat.capabilityAudio': 'Audio',\n 'chat.contextWindow': '{size} context',\n 'chat.unavailable': 'Unavailable',\n} as const;\n\nexport type ChatMessageKey = keyof typeof FALLBACK;\n\n/** `useI18n()` plus `tc()`, a translator for the newer chat keys with English fallbacks. */\nexport function useChatI18n() {\n const i18n = useI18n();\n const tc = (key: ChatMessageKey, vars?: MessageVars) => {\n const out = i18n.t(key as MessageKey, vars);\n return out === key ? interpolate(FALLBACK[key], vars, i18n.locale) : out;\n };\n return { ...i18n, tc };\n}\n","import { Component, createRef, type ReactNode } from 'react';\n\nconst focusable = 'button, a[href], input, select, textarea, [tabindex], [contenteditable=\"true\"]';\nfunction candidates(element: Element): HTMLElement[] {\n return [element, ...element.querySelectorAll(focusable)].filter(\n (item): item is HTMLElement =>\n item instanceof HTMLElement &&\n item.matches(focusable) &&\n item.tabIndex >= 0 &&\n !item.matches(':disabled, [aria-disabled=\"true\"], input[type=\"hidden\"]') &&\n !item.closest('[hidden], [inert], [aria-hidden=\"true\"]') &&\n getComputedStyle(item).display !== 'none' &&\n getComputedStyle(item).visibility !== 'hidden',\n );\n}\ninterface Props {\n surfaceIds: ReadonlySet<string>;\n visible: boolean;\n label: string;\n children: ReactNode;\n}\ninterface FocusSnapshot {\n siblings: Element[];\n}\n\n/** Capture focus before React removes DOM; restore after all deleted surfaces are gone. */\nexport class SurfaceFocusBoundary extends Component<Props> {\n private host = createRef<HTMLDivElement>();\n\n getSnapshotBeforeUpdate(): FocusSnapshot | null {\n const host = this.host.current;\n const active = document.activeElement;\n if (!host || !(active instanceof HTMLElement)) return null;\n let frame = host.contains(active) ? active.closest<HTMLElement>('[data-agent-surface]') : null;\n // Base UI Select options live in a portal. aria-controls identifies their owning trigger.\n if (!frame) {\n for (const trigger of host.querySelectorAll('[aria-controls]')) {\n const ownsFocus = (trigger.getAttribute('aria-controls') ?? '')\n .split(/\\s+/)\n .some((id) => document.getElementById(id)?.contains(active));\n if (ownsFocus) {\n frame = trigger.closest<HTMLElement>('[data-agent-surface]');\n break;\n }\n }\n }\n if (!frame || this.props.surfaceIds.has(frame.dataset.agentSurface ?? '')) return null;\n const next: Element[] = [];\n // The next surface's controls, then the consumer's next focusable sibling.\n for (const start of [frame, host]) {\n let sibling = start.nextElementSibling;\n while (sibling) {\n next.push(sibling);\n sibling = sibling.nextElementSibling;\n }\n }\n return { siblings: next };\n }\n\n componentDidUpdate(_previous: Props, _state: unknown, snapshot: FocusSnapshot | null) {\n if (!snapshot) return;\n const restore = () => {\n // Resolve focusability after popup teardown has removed inert/aria-hidden markers.\n const next = snapshot.siblings.filter((element) => element.isConnected).flatMap(candidates);\n const composers = [...document.querySelectorAll('textarea')].flatMap(candidates);\n for (const target of [...next, ...composers, this.host.current]) {\n if (!target) continue;\n target.focus();\n if (document.activeElement === target) return;\n }\n };\n restore();\n queueMicrotask(() => {\n if (document.activeElement === document.body || document.activeElement === this.host.current) restore();\n });\n }\n\n render() {\n if (!this.props.visible) return null;\n return (\n <div\n ref={this.host}\n tabIndex={-1}\n role=\"group\"\n aria-label={this.props.label}\n className=\"space-y-3 outline-focus-ring\"\n >\n {this.props.children}\n </div>\n );\n }\n}\n","/** RFC 6901 paths. Throws on malformed paths rather than guessing a model key. */\nfunction segments(path: string): string[] {\n if (path === '') return [];\n if (!path.startsWith('/') || /~(?![01])/u.test(path)) throw new Error('Invalid JSON Pointer');\n const keys = path\n .slice(1)\n .split('/')\n .map((key) => key.replace(/~1/g, '/').replace(/~0/g, '~'));\n if (keys.length > 64 || keys.some((key) => ['__proto__', 'prototype', 'constructor'].includes(key))) {\n throw new Error('Unsafe JSON Pointer');\n }\n return keys;\n}\n\nfunction own(value: unknown, key: string): unknown {\n return value !== null && typeof value === 'object' && Object.hasOwn(value, key)\n ? (value as Record<string, unknown>)[key]\n : undefined;\n}\n\nexport function getPointer(model: unknown, path: string): unknown {\n return segments(path).reduce<unknown>(own, model);\n}\n\n/** Copy every ancestor; never mutate the model supplied by a consumer. */\nexport function setPointer(model: unknown, path: string, value: unknown): unknown {\n const keys = segments(path);\n function write(current: unknown, index: number): unknown {\n if (index === keys.length) return value;\n const key = keys[index]!;\n if (Array.isArray(current)) {\n if (!/^(0|[1-9]\\d*)$/.test(key) || Number(key) > current.length) throw new Error('Invalid array index');\n const copy: unknown[] = [...current];\n copy[Number(key)] = write(own(current, key), index + 1);\n return copy;\n }\n const copy: Record<string, unknown> = current && typeof current === 'object' ? { ...current } : {};\n copy[key] = write(own(current, key), index + 1);\n return copy;\n }\n return write(model, 0);\n}\n","/** Supported command envelope. No v0.8 adaptation is performed. */\nexport const A2UI_VERSION = 'v0.9' as const;\nexport interface AgentComponent {\n id: string;\n component: string;\n children?: string[];\n /** Catalog properties are flat, alongside id/component/children. */\n [property: string]: unknown;\n}\nexport interface AgentAction {\n name: string;\n surfaceId: string;\n context: Record<string, unknown>;\n}\nexport interface AgentSurfaceError {\n code: 'version' | 'message' | 'component' | 'props' | 'graph' | 'binding';\n surfaceId: string;\n componentId?: string;\n type?: string;\n}\ntype Envelope<T> = { version: typeof A2UI_VERSION } & T;\nexport type A2uiMessage =\n | Envelope<{ createSurface: { surfaceId: string; catalogId?: string } }>\n | Envelope<{ updateComponents: { surfaceId: string; components: AgentComponent[] } }>\n | Envelope<{ updateDataModel: { surfaceId: string; path?: string; value: unknown } }>\n | Envelope<{ deleteSurface: { surfaceId: string } }>;\n\nexport const MAX_COMPONENTS = 256;\nexport const MAX_DEPTH = 32;\nconst commands = ['createSurface', 'updateComponents', 'updateDataModel', 'deleteSurface'] as const;\nconst identifier = (value: unknown): value is string =>\n typeof value === 'string' && value.length > 0 && value.length <= 128;\nconst record = (value: unknown): value is Record<string, unknown> =>\n value !== null && typeof value === 'object' && !Array.isArray(value);\n\n/** JSON-only, bounded input. In particular, reject cyclic JS objects and prototype keys. */\nfunction validJson(value: unknown): boolean {\n let budget = 10000;\n const ancestors = new Set<object>();\n function visit(item: unknown, depth: number): boolean {\n if (--budget < 0 || depth > 64) return false;\n if (item === null || typeof item === 'boolean') return true;\n if (typeof item === 'number') return Number.isFinite(item);\n if (typeof item === 'string') return item.length <= 65536;\n if (typeof item !== 'object' || ancestors.has(item)) return false;\n if (!Array.isArray(item) && ![Object.prototype, null].includes(Object.getPrototypeOf(item))) return false;\n ancestors.add(item);\n const valid = Object.entries(item).every(\n ([key, child]) => !['__proto__', 'prototype', 'constructor'].includes(key) && visit(child, depth + 1),\n );\n ancestors.delete(item);\n return valid;\n }\n return visit(value, 0);\n}\n\nexport function parseMessage(input: unknown): { message: A2uiMessage } | { error: AgentSurfaceError } {\n const source = record(input) ? input : {};\n const declared = commands.filter((key) => Object.hasOwn(source, key));\n const command = declared[0];\n const payload = command && record(source[command]) ? source[command] : {};\n const surfaceId = identifier(payload.surfaceId) ? payload.surfaceId : '';\n const error = (code: AgentSurfaceError['code']) => ({ error: { code, surfaceId } });\n if (source.version !== A2UI_VERSION) return error('version');\n if (declared.length !== 1 || !surfaceId || !validJson(input)) return error('message');\n if (command === 'createSurface') {\n if (payload.catalogId !== undefined && !identifier(payload.catalogId)) return error('message');\n return {\n message: {\n version: A2UI_VERSION,\n createSurface: {\n surfaceId,\n ...(typeof payload.catalogId === 'string' ? { catalogId: payload.catalogId } : {}),\n },\n },\n };\n }\n if (command === 'deleteSurface') return { message: { version: A2UI_VERSION, deleteSurface: { surfaceId } } };\n if (command === 'updateDataModel') {\n if (!Object.hasOwn(payload, 'value') || (payload.path !== undefined && typeof payload.path !== 'string'))\n return error('message');\n return {\n message: {\n version: A2UI_VERSION,\n updateDataModel: {\n surfaceId,\n path: typeof payload.path === 'string' ? payload.path : '',\n value: payload.value,\n },\n },\n };\n }\n if (!Array.isArray(payload.components) || payload.components.length > MAX_COMPONENTS) return error('message');\n const nodes: AgentComponent[] = [];\n const ids = new Set<string>();\n for (const node of payload.components) {\n if (!record(node) || !identifier(node.id) || !identifier(node.component) || ids.has(node.id))\n return error('message');\n if (\n node.children !== undefined &&\n (!Array.isArray(node.children) || node.children.length > MAX_COMPONENTS || !node.children.every(identifier))\n )\n return error('message');\n ids.add(node.id);\n nodes.push(node as AgentComponent);\n }\n return { message: { version: A2UI_VERSION, updateComponents: { surfaceId, components: nodes } } };\n}\n\n/** Missing children are allowed while streaming; repeated parents, cycles and deep trees are not. */\nexport function validGraph(nodes: ReadonlyMap<string, AgentComponent>): boolean {\n if (nodes.size > MAX_COMPONENTS) return false;\n const parents = new Set<string>();\n for (const node of nodes.values()) {\n for (const child of node.children ?? []) {\n if (parents.has(child)) return false;\n parents.add(child);\n }\n }\n const visiting = new Set<string>();\n function visit(id: string, depth: number): boolean {\n if (depth > MAX_DEPTH || visiting.has(id)) return false;\n visiting.add(id);\n const valid = (nodes.get(id)?.children ?? []).every((child) => visit(child, depth + 1));\n visiting.delete(id);\n return valid;\n }\n return [...nodes.keys()].every((id) => visit(id, 0));\n}\n","import { setPointer } from './pointer';\nimport { parseMessage, validGraph, type A2uiMessage, type AgentComponent, type AgentSurfaceError } from './protocol';\n\nexport interface SurfaceState {\n nodes: Map<string, AgentComponent>;\n model: unknown;\n invalid?: boolean;\n}\nexport interface StreamState {\n messages: A2uiMessage[];\n surfaces: Map<string, SurfaceState>;\n deleted: boolean;\n blocked: Set<string>;\n errors: AgentSurfaceError[];\n}\nexport const emptyStream = (): StreamState => ({\n messages: [],\n deleted: false,\n surfaces: new Map(),\n blocked: new Set(),\n errors: [],\n});\n\nexport function consume(previous: StreamState, messages: A2uiMessage[]): StreamState {\n const append = previous.messages.every((message, index) => messages[index] === message);\n const base = append ? previous : emptyStream();\n const state = {\n messages,\n deleted: base.deleted,\n surfaces: new Map(base.surfaces),\n blocked: new Set(base.blocked),\n errors: [...base.errors],\n };\n for (const input of messages.slice(base.messages.length)) {\n const parsed = parseMessage(input);\n if ('error' in parsed) {\n if (parsed.error.code === 'version') {\n state.blocked.add(parsed.error.surfaceId);\n state.surfaces.delete(parsed.error.surfaceId);\n // Keep the focus fallback mounted only if this surface was previously rendered.\n if (previous.surfaces.has(parsed.error.surfaceId)) state.deleted = true;\n }\n state.errors.push(parsed.error);\n continue;\n }\n const message = parsed.message;\n const payload =\n 'createSurface' in message\n ? message.createSurface\n : 'updateComponents' in message\n ? message.updateComponents\n : 'updateDataModel' in message\n ? message.updateDataModel\n : message.deleteSurface;\n const { surfaceId } = payload;\n if (state.blocked.has(surfaceId)) continue;\n if ('createSurface' in message) {\n if (!state.surfaces.has(surfaceId)) {\n if (state.surfaces.size >= 32) state.errors.push({ code: 'message', surfaceId });\n else state.surfaces.set(surfaceId, { nodes: new Map(), model: {} });\n }\n continue;\n }\n const surface = state.surfaces.get(surfaceId);\n if (!surface) {\n state.errors.push({ code: 'message', surfaceId });\n continue;\n }\n if ('updateComponents' in message) {\n const nodes = new Map(surface.nodes);\n for (const node of message.updateComponents.components) {\n const old = nodes.get(node.id);\n nodes.set(node.id, { ...(old?.component === node.component ? old : {}), ...node });\n }\n const invalid = !validGraph(nodes);\n if (invalid) state.errors.push({ code: 'graph', surfaceId });\n state.surfaces.set(surfaceId, { ...surface, nodes: invalid ? surface.nodes : nodes, invalid });\n }\n if ('updateDataModel' in message) {\n try {\n const { path = '', value } = message.updateDataModel;\n state.surfaces.set(surfaceId, { ...surface, model: setPointer(surface.model, path, value) });\n } catch {\n state.errors.push({ code: 'binding', surfaceId });\n }\n }\n if ('deleteSurface' in message) {\n state.surfaces.delete(surfaceId);\n state.deleted = true;\n }\n }\n // An unsupported version suppresses all rendering and other diagnostics for that surface.\n state.errors = state.errors.filter((error) => !state.blocked.has(error.surfaceId) || error.code === 'version');\n return state;\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\n/**\n * Copies text to the clipboard and exposes a short-lived `copied` flag for the button label.\n * The reset timer is cleared on unmount and on every new copy.\n */\nexport function useCopy(resetMs = 1600) {\n const [copied, setCopied] = useState(false);\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n useEffect(() => () => clearTimeout(timer.current), []);\n\n const copy = useCallback(\n async (text: string) => {\n try {\n await navigator.clipboard?.writeText(text);\n } catch {\n // Clipboard can be denied (insecure context, permissions); the flag still gives feedback.\n }\n setCopied(true);\n clearTimeout(timer.current);\n timer.current = setTimeout(() => setCopied(false), resetMs);\n },\n [resetMs],\n );\n\n return { copied, copy };\n}\n","/** Focus ring shared by every interactive element in the pack (brand rule). */\nexport const focusRing = 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring';\n","import { focusRing } from '../utils/focus';\n\n/**\n * Blinking caret drawn after the last block while text streams in. Pure CSS (an ::after on the\n * last child), so it follows paragraphs, list items and code without extra DOM.\n */\nexport const streamingCaretClass = [\n '[&>:last-child]:after:ms-0.5 [&>:last-child]:after:inline-block [&>:last-child]:after:h-[1.05em] [&>:last-child]:after:w-[2px]',\n \"[&>:last-child]:after:translate-y-[2px] [&>:last-child]:after:bg-primary [&>:last-child]:after:content-['']\",\n '[&>:last-child]:after:animate-pulse motion-reduce:[&>:last-child]:after:animate-none',\n].join(' ');\n\n/** Element classes for Markdown (token colours only). */\nexport const markdownStyles = {\n root: 'min-w-0 text-[14px] leading-[1.7] text-foreground [overflow-wrap:anywhere] [&>:first-child]:mt-0 [&>:last-child]:mb-0',\n h1: 'mt-5 mb-2 text-[18px] font-semibold tracking-tight',\n h2: 'mt-5 mb-2 text-[16px] font-semibold tracking-tight',\n h3: 'mt-4 mb-1.5 text-[14.5px] font-semibold',\n h4: 'mt-4 mb-1.5 text-[13.5px] font-semibold text-muted-foreground',\n p: 'my-2.5',\n ul: 'my-2.5 list-disc space-y-1 ps-5 marker:text-muted-foreground',\n ol: 'my-2.5 list-decimal space-y-1 ps-5 marker:text-muted-foreground',\n li: 'ps-1 [&>ul]:my-1 [&>ol]:my-1 [&.task-list-item]:list-none [&.task-list-item]:-ms-5',\n blockquote: 'my-3 border-s-2 border-primary/50 ps-3.5 text-muted-foreground',\n hr: 'my-5 border-border',\n link: `rounded-sm font-medium text-primary-text underline decoration-primary/40 underline-offset-2 hover:decoration-primary ${focusRing}`,\n linkIcon: 'ms-0.5 inline-block align-[-1px]',\n inlineCode: 'rounded-md border border-border bg-secondary/60 px-1.5 py-px font-mono text-[12.5px]',\n tableWrap: 'my-3 overflow-x-auto rounded-lg border border-border',\n table: 'w-full border-collapse text-start text-[13px]',\n th: 'border-b border-border bg-secondary/50 px-3 py-2 font-semibold',\n td: 'border-b border-border px-3 py-2 align-top [tr:last-child_&]:border-b-0',\n checkbox: 'me-1.5 align-[-2px] accent-primary',\n image: 'text-muted-foreground italic',\n code: {\n root: 'my-3 overflow-hidden rounded-lg border border-border bg-secondary/40',\n header: 'flex h-9 items-center justify-between border-b border-border bg-secondary/50 ps-3 pe-1.5',\n lang: 'font-mono text-[11px] tracking-wide text-muted-foreground uppercase',\n pre: 'overflow-x-auto p-3 font-mono text-[12.5px] leading-6',\n },\n} as const;\n","import { Button, useI18n } from '@gntik-ai/ui';\nimport { Check, Copy } from 'lucide-react';\nimport { useCopy } from '../utils/useCopy';\nimport { markdownStyles } from './markdown.variants';\n\nconst s = markdownStyles.code;\n\nexport interface CodeBlockProps {\n /** Source text. */\n code: string;\n /** Language tag from the fence (```ts). */\n language?: string;\n className?: string;\n}\n\n/** Fenced code with a language label and a copy button. */\nexport function CodeBlock({ code, language, className }: CodeBlockProps) {\n const { copied, copy } = useCopy();\n const { t } = useI18n();\n return (\n <div className={className ? `${s.root} ${className}` : s.root} data-language={language}>\n <div className={s.header}>\n <span className={s.lang}>{language || 'text'}</span>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n icon={copied ? Check : Copy}\n aria-label={copied ? t('chat.copiedCode') : t('chat.copyCode')}\n className=\"h-7 px-2\"\n onClick={() => void copy(code)}\n >\n {copied ? t('common.copied') : t('common.copy')}\n </Button>\n </div>\n <pre className={s.pre}>\n <code>{code}</code>\n </pre>\n </div>\n );\n}\n","import { cn, useI18n } from '@gntik-ai/ui';\nimport { ExternalLink } from 'lucide-react';\nimport { Children, isValidElement, memo, type ReactNode } from 'react';\nimport ReactMarkdown, { defaultUrlTransform, type Components } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { CodeBlock } from './CodeBlock';\nimport { markdownStyles as s, streamingCaretClass } from './markdown.variants';\n\nexport interface MarkdownProps {\n /** Markdown source (GitHub-flavoured: tables, task lists, strikethrough, autolinks). */\n children: string;\n /** Text is still arriving: closes a dangling code fence and draws the caret. */\n streaming?: boolean;\n className?: string;\n}\n\nconst SAFE_PROTOCOL = /^(https?|mailto|tel):/i;\n\n/**\n * URL policy: relative URLs, anchors and http(s)/mailto/tel only. Everything else\n * (javascript:, data:, vbscript:, …) is dropped, on top of react-markdown's own transform.\n */\nexport function safeUrl(url: string): string {\n const cleaned = defaultUrlTransform(url);\n if (!cleaned) return '';\n // Ignore whitespace and control characters browsers skip (\"java\\tscript:\").\n const compact = Array.from(cleaned)\n .filter((c) => c.charCodeAt(0) > 0x20)\n .join('');\n if (/^[a-z][a-z0-9+.-]*:/i.test(compact) && !SAFE_PROTOCOL.test(compact)) return '';\n return cleaned;\n}\n\n/**\n * Makes partial streamed markdown render sanely: a fence that has opened but not closed is\n * closed at the end, so the tail renders as code instead of flashing as paragraphs.\n */\nexport function repairStreamingMarkdown(text: string): string {\n const fences = text.match(/^ {0,3}(`{3,}|~{3,})/gm) ?? [];\n if (fences.length % 2 === 0) return text;\n const opener = (fences[fences.length - 1] ?? '```').trim();\n return `${text}${text.endsWith('\\n') ? '' : '\\n'}${opener}`;\n}\n\nconst isExternal = (href: string) => /^https?:\\/\\//i.test(href);\n\n/** Drops react-markdown's `node` (hast) prop before spreading onto a DOM element. */\n/** Screen-reader note on links that open a new tab. */\nfunction NewTabHint() {\n const { t } = useI18n();\n return <span className=\"sr-only\"> {t('link.external')}</span>;\n}\n\n/** Remote images can track readers and break layout mid-stream: show them as links. */\nfunction ImageLink({ href, alt }: { href: string; alt?: string }) {\n const { t } = useI18n();\n const text = t('chat.image', { alt: alt || t('chat.untitled') });\n return href ? (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer nofollow\" className={s.link}>\n {text}\n <NewTabHint />\n </a>\n ) : (\n <span className={s.image}>{text}</span>\n );\n}\n\nfunction TaskCheckbox({ checked }: { checked: boolean }) {\n const { t } = useI18n();\n return (\n <input\n type=\"checkbox\"\n checked={checked}\n readOnly\n disabled\n aria-label={checked ? t('chat.taskDone') : t('chat.taskNotDone')}\n className={s.checkbox}\n />\n );\n}\n\nfunction omitNode<T extends { node?: unknown }>(props: T): Omit<T, 'node'> {\n const { node, ...rest } = props;\n void node;\n return rest;\n}\n\ntype CodeChildProps = { className?: string; children?: ReactNode };\n\nconst components: Components = {\n h1: (p) => <h1 {...omitNode(p)} className={s.h1} />,\n h2: (p) => <h2 {...omitNode(p)} className={s.h2} />,\n h3: (p) => <h3 {...omitNode(p)} className={s.h3} />,\n h4: (p) => <h4 {...omitNode(p)} className={s.h4} />,\n h5: (p) => <h4 {...omitNode(p)} className={s.h4} />,\n h6: (p) => <h4 {...omitNode(p)} className={s.h4} />,\n p: (p) => <p {...omitNode(p)} className={s.p} />,\n ul: (p) => <ul {...omitNode(p)} className={cn(s.ul, p.className === 'contains-task-list' && 'ps-1')} />,\n ol: (p) => <ol {...omitNode(p)} className={s.ol} />,\n li: (p) => <li {...omitNode(p)} className={cn(s.li, p.className)} />,\n blockquote: (p) => <blockquote {...omitNode(p)} className={s.blockquote} />,\n hr: () => <hr className={s.hr} />,\n table: (p) => (\n <div className={s.tableWrap}>\n <table {...omitNode(p)} className={s.table} />\n </div>\n ),\n th: (p) => <th {...omitNode(p)} className={s.th} />,\n td: (p) => <td {...omitNode(p)} className={s.td} />,\n a: (props) => {\n const { href, children, ...p } = omitNode(props);\n if (!href) return <span>{children}</span>;\n if (!isExternal(href)) {\n return (\n <a href={href} className={s.link} {...p}>\n {children}\n </a>\n );\n }\n return (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer nofollow\" className={s.link} {...p}>\n {children}\n <ExternalLink size={12} aria-hidden className={s.linkIcon} />\n <NewTabHint />\n </a>\n );\n },\n img: ({ src, alt }) => <ImageLink href={typeof src === 'string' ? src : ''} alt={alt} />,\n input: ({ checked, type }) => (type === 'checkbox' ? <TaskCheckbox checked={!!checked} /> : null),\n code: ({ className, children }) => <code className={cn(s.inlineCode, className)}>{children}</code>,\n pre: ({ children }) => {\n const child = Children.toArray(children)[0];\n if (!isValidElement<CodeChildProps>(child)) return <pre className={s.code.pre}>{children}</pre>;\n const language = /language-([\\w+#.-]+)/.exec(child.props.className ?? '')?.[1];\n const code = String(Children.toArray(child.props.children).join('')).replace(/\\n$/, '');\n return <CodeBlock code={code} language={language} />;\n },\n};\n\nconst remarkPlugins = [remarkGfm];\n\n/**\n * Safe markdown for model output: raw HTML is never rendered (skipped, not parsed), links are\n * restricted to http(s)/mailto/tel/relative, external links open in a new tab with a marker,\n * and fenced code gets a copy button. Partial input from a stream is tolerated.\n */\nexport const Markdown = memo(function Markdown({ children, streaming = false, className }: MarkdownProps) {\n const source = streaming ? repairStreamingMarkdown(children) : children;\n return (\n <div data-streaming={streaming || undefined} className={cn(s.root, streaming && streamingCaretClass, className)}>\n <ReactMarkdown remarkPlugins={remarkPlugins} components={components} skipHtml urlTransform={safeUrl}>\n {source}\n </ReactMarkdown>\n </div>\n );\n});\n","import { safeUrl } from '../Markdown/Markdown';\nimport { getPointer } from './pointer';\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n value !== null && typeof value === 'object' && !Array.isArray(value);\n\nexport function bindingPath(value: unknown): string | undefined {\n if (!isRecord(value) || !Object.hasOwn(value, 'path')) return undefined;\n if (typeof value.path !== 'string' || Object.keys(value).length !== 1) throw new Error('Invalid binding');\n // Validate even when the model has no value at this path yet.\n getPointer({}, value.path);\n return value.path;\n}\n\nexport function resolveValue(value: unknown, model: unknown): unknown {\n const path = bindingPath(value);\n if (path !== undefined) return getPointer(model, path);\n if (Array.isArray(value)) return value.map((item) => resolveValue(item, model));\n if (isRecord(value))\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, resolveValue(item, model)]));\n return value;\n}\n\n/** Remove executable/structural properties before even a host validator sees agent input. */\nexport function safeProperties(input: Readonly<Record<string, unknown>>, model: unknown): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(input)) {\n if (\n /^on/i.test(key) ||\n [\n 'id',\n 'component',\n 'children',\n 'className',\n 'style',\n 'dangerouslySetInnerHTML',\n 'ref',\n 'key',\n 'render',\n 'as',\n '__proto__',\n 'constructor',\n 'prototype',\n ].includes(key)\n )\n continue;\n const resolved = resolveValue(value, model);\n result[key] =\n /(?:href|src|url)$/i.test(key) && typeof resolved === 'string' ? safeUrl(resolved) || undefined : resolved;\n }\n return result;\n}\n\nexport function validAction(value: unknown): boolean {\n return (\n value === undefined ||\n (isRecord(value) &&\n typeof value.name === 'string' &&\n value.name.trim().length > 0 &&\n value.name.length <= 128 &&\n (value.context === undefined || isRecord(value.context)))\n );\n}\n","import { useEffect, useRef, useState, type ReactNode } from 'react';\nimport { useChatI18n } from '../utils/i18n';\nimport { SurfaceFocusBoundary } from './SurfaceFocusBoundary';\nimport { consume, emptyStream } from './stream';\nimport { bindingPath, isRecord, resolveValue, safeProperties, validAction } from './model';\nimport { setPointer } from './pointer';\nimport type { AgentCatalog } from './catalog';\nimport type { A2uiMessage, AgentComponent, AgentAction, AgentSurfaceError } from './protocol';\n\nexport interface AgentSurfaceProps {\n /** Immutable command log: append messages to update the rendered surfaces. */\n messages: A2uiMessage[];\n /** Trusted allow-list, created by the host rather than the agent. */\n catalog: AgentCatalog;\n onAction?: (action: AgentAction) => void;\n onError?: (error: AgentSurfaceError) => void;\n}\nexport function AgentSurface({ messages, catalog, onError, onAction }: AgentSurfaceProps) {\n const { tc } = useChatI18n();\n const reported = useRef(new Set<string>());\n const errors: AgentSurfaceError[] = [];\n const [state, setState] = useState(emptyStream);\n if (state.messages !== messages) setState(consume(state, messages));\n errors.push(...state.errors);\n function renderNode(surfaceId: string, nodes: Map<string, AgentComponent>, id: string): ReactNode {\n const node = nodes.get(id);\n if (!node) return null;\n const entry = Object.hasOwn(catalog, node.component) ? catalog[node.component] : undefined;\n const surface = state.surfaces.get(surfaceId)!;\n let props: Record<string, unknown> | null = null;\n try {\n const input = safeProperties(node, surface.model);\n if (validAction(input.action)) props = entry?.validate(input) ?? null;\n } catch {\n /* Invalid paths and validators produce the same neutral placeholder. */\n }\n if (!entry || !props) {\n errors.push({ code: entry ? 'props' : 'component', surfaceId, componentId: id, type: node.component });\n return (\n <p key={id} className=\"text-muted-foreground\">\n {tc('chat.surfaceUnsupported')}\n </p>\n );\n }\n const Component = entry.component;\n return (\n <Component\n key={id}\n props={props}\n onValueChange={(value) => {\n const path = bindingPath(node.value ?? node.checked);\n if (path === undefined) return;\n setState((current) => {\n const surface = current.surfaces.get(surfaceId);\n if (!surface) return current;\n const surfaces = new Map(current.surfaces);\n surfaces.set(surfaceId, { ...surface, model: setPointer(surface.model, path, value) });\n return { ...current, surfaces };\n });\n }}\n onAction={() => {\n if (!isRecord(node.action) || typeof node.action.name !== 'string') return;\n const context = resolveValue(node.action.context ?? {}, surface.model);\n if (isRecord(context)) onAction?.({ name: node.action.name, surfaceId, context });\n }}\n >\n {node.children?.map((child) => renderNode(surfaceId, nodes, child))}\n </Component>\n );\n }\n const content = [...state.surfaces].map(([id, surface]) => (\n <section\n key={id}\n data-agent-surface={id}\n role=\"group\"\n aria-label={tc('chat.surfaceAgentContent')}\n className=\"rounded-lg border border-border bg-background p-3\"\n >\n <p className=\"mb-3 text-xs font-semibold text-muted-foreground\">{tc('chat.surfaceAgentContent')}</p>\n <form onSubmit={(event) => event.preventDefault()}>\n {surface.invalid ? (\n <p className=\"text-muted-foreground\">{tc('chat.surfaceUnsupported')}</p>\n ) : (\n renderNode(id, surface.nodes, 'root')\n )}\n </form>\n </section>\n ));\n useEffect(() => {\n for (const error of errors) {\n const key = JSON.stringify(error);\n if (!reported.current.has(key)) {\n reported.current.add(key);\n onError?.(error);\n }\n }\n });\n return (\n <SurfaceFocusBoundary\n surfaceIds={new Set(state.surfaces.keys())}\n visible={state.surfaces.size > 0 || state.deleted}\n label={tc('chat.surfaceAgentContent')}\n >\n {content}\n </SurfaceFocusBoundary>\n );\n}\n","import {\n Alert,\n Badge,\n Button,\n Card,\n Checkbox,\n Heading,\n Input,\n Link,\n SimpleSelect,\n Stack,\n Text,\n type HeadingLevel,\n type SpaceScale,\n} from '@gntik-ai/ui';\nimport type { AgentCatalogRenderProps } from './catalog';\nimport { isRecord } from './model';\n\nconst text = (value: unknown) => (typeof value === 'string' ? value : '');\n\nexport function SurfaceText({ props }: AgentCatalogRenderProps) {\n return typeof props.href === 'string' && props.href ? (\n <Text>\n <Link href={props.href}>{text(props.text)}</Link>\n </Text>\n ) : (\n <Text>{text(props.text)}</Text>\n );\n}\nexport function SurfaceHeading({ props }: AgentCatalogRenderProps) {\n return (\n <Heading level={typeof props.level === 'number' ? (props.level as HeadingLevel) : 2}>{text(props.text)}</Heading>\n );\n}\nexport function SurfaceCard({ children }: AgentCatalogRenderProps) {\n return <Card className=\"space-y-3 p-4\">{children}</Card>;\n}\nexport function SurfaceStack({ props, children }: AgentCatalogRenderProps) {\n return (\n <Stack\n direction={props.direction === 'row' ? 'row' : 'column'}\n gap={typeof props.gap === 'number' ? (props.gap as SpaceScale) : 3}\n >\n {children}\n </Stack>\n );\n}\nexport function SurfaceButton({ props, onAction }: AgentCatalogRenderProps) {\n return (\n <Button\n type=\"submit\"\n className=\"motion-reduce:transition-none\"\n disabled={props.disabled === true}\n onClick={onAction}\n >\n {text(props.label)}\n </Button>\n );\n}\nexport function SurfaceInput({ props, onValueChange }: AgentCatalogRenderProps) {\n return (\n <label className=\"flex flex-col gap-2 text-sm text-foreground\">\n {text(props.label)}\n <Input type=\"text\" disabled={props.disabled === true} value={text(props.value)} onValueChange={onValueChange} />\n </label>\n );\n}\nexport function SurfaceSelect({ props, onValueChange }: AgentCatalogRenderProps) {\n const items = Array.isArray(props.options)\n ? props.options.filter(isRecord).map((item) => ({ value: text(item.value), label: text(item.label) }))\n : [];\n return (\n <SimpleSelect<string>\n label={text(props.label)}\n disabled={props.disabled === true}\n value={typeof props.value === 'string' ? props.value : null}\n items={items}\n onValueChange={onValueChange}\n />\n );\n}\nexport function SurfaceCheckbox({ props, onValueChange }: AgentCatalogRenderProps) {\n return (\n <Checkbox\n label={text(props.label)}\n disabled={props.disabled === true}\n checked={props.checked === true}\n onCheckedChange={onValueChange}\n />\n );\n}\nexport function SurfaceAlert({ props }: AgentCatalogRenderProps) {\n return <Alert title={text(props.title)} description={text(props.text)} />;\n}\nexport function SurfaceBadge({ props }: AgentCatalogRenderProps) {\n return <Badge>{text(props.text)}</Badge>;\n}\n","import type { ComponentType, ReactNode } from 'react';\nimport {\n SurfaceAlert,\n SurfaceBadge,\n SurfaceButton,\n SurfaceCard,\n SurfaceCheckbox,\n SurfaceHeading,\n SurfaceInput,\n SurfaceSelect,\n SurfaceStack,\n SurfaceText,\n} from './catalog-components';\nimport { isRecord } from './model';\n\n/** Trusted host code: render explicit properties; never spread the agent's input. */\nexport interface AgentCatalogRenderProps {\n props: Readonly<Record<string, unknown>>;\n children?: ReactNode;\n onValueChange: (value: unknown) => void;\n onAction: () => void;\n}\nexport interface AgentCatalogEntry {\n component: ComponentType<AgentCatalogRenderProps>;\n /** Return a fresh object of known properties, or null when invalid. */\n validate: (props: Readonly<Record<string, unknown>>) => Record<string, unknown> | null;\n}\nexport type AgentCatalog = Readonly<Record<string, AgentCatalogEntry>>;\nexport function defineAgentCatalog(entries: AgentCatalog): AgentCatalog {\n return Object.freeze(\n Object.fromEntries(Object.entries(entries).map(([name, entry]) => [name, Object.freeze({ ...entry })])),\n );\n}\n\ntype Rule = (value: unknown) => boolean;\nconst string: Rule = (value) => typeof value === 'string';\nconst label: Rule = (value) => typeof value === 'string' && value.trim().length > 0;\nconst optional =\n (rule: Rule): Rule =>\n (value) =>\n value === undefined || rule(value);\nconst boolean: Rule = (value) => typeof value === 'boolean';\nfunction fields(rules: Record<string, Rule>): AgentCatalogEntry['validate'] {\n return (input) => {\n const output: Record<string, unknown> = {};\n for (const [key, rule] of Object.entries(rules)) {\n if (!rule(input[key])) return null;\n if (input[key] !== undefined) output[key] = input[key];\n }\n return output;\n };\n}\nconst options: Rule = (value) =>\n Array.isArray(value) &&\n value.length <= 100 &&\n value.every((item) => isRecord(item) && label(item.value) && label(item.label)) &&\n new Set(value.map((item: unknown) => (isRecord(item) ? item.value : null))).size === value.length;\n\n/** Small text/form catalog. Password, payment and file controls are deliberately absent. */\nexport const defaultAgentCatalog = defineAgentCatalog({\n Text: { component: SurfaceText, validate: fields({ text: string, href: optional(string) }) },\n Heading: {\n component: SurfaceHeading,\n validate: fields({\n text: label,\n level: optional((v) => typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 6),\n }),\n },\n Card: { component: SurfaceCard, validate: fields({}) },\n Stack: {\n component: SurfaceStack,\n validate: fields({\n direction: optional((v) => v === 'row' || v === 'column'),\n gap: optional((v) => typeof v === 'number' && Number.isInteger(v) && v >= 0 && v <= 12),\n }),\n },\n Button: { component: SurfaceButton, validate: fields({ label, disabled: optional(boolean) }) },\n Input: {\n component: SurfaceInput,\n validate: fields({\n label,\n value: optional(string),\n disabled: optional(boolean),\n type: optional((v) => v === 'text'),\n }),\n },\n Select: {\n component: SurfaceSelect,\n validate: (input) => {\n const result = fields({\n label,\n value: optional((v) => v === null || typeof v === 'string'),\n options,\n disabled: optional(boolean),\n })(input);\n if (!result || !Array.isArray(result.options)) return null;\n return {\n ...result,\n options: result.options.filter(isRecord).map((item) => ({ value: item.value, label: item.label })),\n };\n },\n },\n Checkbox: {\n component: SurfaceCheckbox,\n validate: fields({ label, checked: optional(boolean), disabled: optional(boolean) }),\n },\n Alert: { component: SurfaceAlert, validate: fields({ title: label, text: optional(string) }) },\n Badge: { component: SurfaceBadge, validate: fields({ text: label }) },\n});\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'AgentSurface',\n group: 'Display',\n status: 'beta',\n description:\n 'Opt-in, placement-neutral renderer for allow-listed agent content. Accepts only A2UI v0.9 command envelopes (A2UI_VERSION). Pass an immutable messages log and a trusted catalog; append createSurface, updateComponents, updateDataModel and deleteSurface messages. Component records have id, component, optional children (child ids), and flat catalog properties; the root id is \"root\". Text/Heading/Badge use text; Text optionally accepts href; Heading accepts level 1–6. Card contains children; Stack accepts direction (row/column) and gap (0–12). Button uses label, optional disabled and action { name, context }; Input uses label, optional text value/disabled and only type text. Select uses label, options [{ value, label }], optional value/disabled; Checkbox uses label, optional checked/disabled. Alert uses title and optional text. { path: \"/user/name\" } reads a JSON Pointer; Input/Select value and Checkbox checked write back to that path. updateDataModel { surfaceId, path?, value } replaces the value at path (default: model root). Every default Button is a submit control: Enter in an Input can activate the first Button, so keep a safe primary action first and avoid destructive actions in that position. Buttons, keyboard activation and implicit form submission emit onAction { name, surfaceId, context } with the current bound values. Replacing the log replays it; keep existing message objects stable when appending. Runtime validation rejects unsupported versions, malformed JSON, prototype keys, cycles, shared children and excessive trees (256 nodes, depth 32, 32 surfaces). Missing child definitions may arrive later. Unknown components and invalid properties show a localized placeholder and report a deduplicated onError diagnostic. The visible, accessible agent-content frame cannot be relabelled by the agent. Deletion or version suppression of rendered content restores focus to the next surviving sibling control, the first focusable textarea in the document, or the labelled container. Place the chat composer as that first textarea or provide a focusable sibling after the renderer; another textarea can otherwise receive focus. defineAgentCatalog accepts trusted host wrappers { component, validate }; validate must return a fresh allow-list of known properties or null. Wrappers receive { props, children, onValueChange, onAction } and must assign explicit kit props. Never spread agent data into elements. Custom URL properties must have names ending in href, src or url (case-insensitive) to receive the Markdown safeUrl policy; text renders as React text nodes. Custom catalogs can reintroduce phishing and executable content: audit their wrappers and validators, never allow passwords, payments, file uploads, arbitrary markup or host-chrome styling. Transport, side-panel placement, v0.8 adapters and Markdown integration belong to consumers or future changes. The live example demonstrates every default entry, model patches, actions, rejection, deletion and reset.',\n primitive: 'Kit components (Base UI)',\n pattern: 'labelled group containing a form',\n keyboard: [\n ['Tab / Shift+Tab', 'Moves between enabled form controls and links'],\n ['Enter / Space', 'Activates a Button exactly once; Enter in an Input submits with the first Button'],\n ['Space', 'Toggles a Checkbox and updates its bound model path'],\n ['Enter / ArrowDown', 'Opens a Select; ArrowUp/ArrowDown navigates options'],\n ['Enter / Escape', 'Selects an option / closes a Select and returns focus'],\n ['Surface deletion', 'Moves focus to a surviving sibling control, the composer, or the labelled container'],\n ],\n tokens: ['background', 'card', 'border', 'foreground', 'muted-foreground', 'focus-ring'],\n};\n","/** \"840 ms\" below a second, \"2.4 s\" below a minute, \"1 m 05 s\" above. */\nexport function formatDuration(ms: number) {\n if (ms < 1000) return `${Math.round(ms)} ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(1)} s`;\n const m = Math.floor(ms / 60_000);\n const s = Math.round((ms % 60_000) / 1000);\n return `${m} m ${String(s).padStart(2, '0')} s`;\n}\n\n/** \"12 KB\", \"3.4 MB\". */\nexport function formatBytes(bytes: number) {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n/** Short local time (\"14:05\") for a message timestamp. */\nexport function formatTime(date: Date) {\n return date.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });\n}\n\n/** Pretty-prints any value as JSON; falls back to String() for cyclic or exotic values. */\nexport function toJson(value: unknown) {\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value, null, 2) ?? String(value);\n } catch {\n return String(value);\n }\n}\n","import { focusRing } from '../utils/focus';\n\n/** Slot classes for AttachmentChip / AttachmentList. */\nexport const attachmentStyles = {\n list: 'flex flex-wrap gap-1.5',\n item: 'min-w-0',\n chip: [\n 'relative inline-flex h-10 max-w-64 min-w-0 items-center gap-2 overflow-hidden rounded-md border border-border bg-secondary/50 ps-1.5 pe-1 text-[12px] text-foreground',\n 'data-[status=error]:border-destructive/60 data-[status=error]:bg-destructive/8',\n ].join(' '),\n tile: [\n 'relative flex w-28 flex-col overflow-hidden rounded-lg border border-border bg-card text-[12px] text-foreground',\n 'data-[status=error]:border-destructive/60',\n ].join(' '),\n media: 'grid size-7 shrink-0 place-items-center overflow-hidden rounded bg-background text-muted-foreground',\n mediaError: 'text-destructive-text',\n tileMedia: 'grid aspect-square w-full place-items-center overflow-hidden bg-secondary/50 text-muted-foreground',\n img: 'size-full object-cover',\n text: 'flex min-w-0 flex-1 flex-col leading-4',\n tileText: 'flex min-w-0 flex-col gap-0.5 px-2 py-1.5 leading-4',\n name: 'truncate font-medium',\n meta: 'truncate font-mono text-[10.5px] text-muted-foreground',\n metaError: 'truncate text-[11px] text-destructive-chip-text',\n button: `grid size-6 shrink-0 place-items-center rounded text-muted-foreground hover:bg-foreground/10 hover:text-foreground disabled:pointer-events-none disabled:opacity-50 ${focusRing}`,\n tileActions: 'absolute end-1 top-1 flex gap-0.5 rounded-md bg-card/90',\n track: 'absolute inset-x-0 bottom-0 h-0.5 bg-border',\n bar: 'h-full bg-primary transition-[width] duration-200 motion-reduce:transition-none',\n barIndeterminate: 'h-full w-1/3 bg-primary animate-pulse motion-reduce:animate-none',\n} as const;\n","import { cn, fileKind, type FileKind } from '@gntik-ai/ui';\nimport {\n AlertCircle,\n File,\n FileArchive,\n FileAudio,\n FileCode,\n FileImage,\n FileSpreadsheet,\n FileText,\n FileVideo,\n RotateCcw,\n X,\n type LucideIcon,\n} from 'lucide-react';\nimport type { Ref } from 'react';\nimport { formatBytes } from '../utils/format';\nimport { useChatI18n } from '../utils/i18n';\nimport { attachmentStyles as s } from './attachment.variants';\n\n/** A file attached to a message or waiting in the composer. */\nexport interface ChatAttachment {\n id: string;\n name: string;\n /** Size in bytes. */\n size?: number;\n /** MIME type; picks the icon (falls back to the extension). */\n type?: string;\n /** Image preview URL (e.g. from URL.createObjectURL); shown as a thumbnail for images. */\n previewUrl?: string;\n /** Upload progress 0–100 (`null` = indeterminate). Omit when not uploading. */\n progress?: number | null;\n /** Upload failed; a string replaces the default message. */\n error?: boolean | string;\n}\n\nexport type AttachmentStatus = 'idle' | 'uploading' | 'error';\n\nexport interface AttachmentChipProps {\n attachment: ChatAttachment;\n /** `chip` (composer, compact row) or `tile` (message, larger image preview). */\n variant?: 'chip' | 'tile';\n /** Shows the remove button. */\n onRemove?: (id: string) => void;\n /** Shows a retry button in the error state. */\n onRetry?: (id: string) => void;\n disabled?: boolean;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n}\n\nconst ICONS: Record<FileKind, LucideIcon> = {\n image: FileImage,\n video: FileVideo,\n audio: FileAudio,\n archive: FileArchive,\n code: FileCode,\n spreadsheet: FileSpreadsheet,\n document: FileText,\n file: File,\n};\n\n/** Status of an attachment from its progress and error fields. */\nexport function attachmentStatus(a: ChatAttachment): AttachmentStatus {\n if (a.error) return 'error';\n if (a.progress === null || (typeof a.progress === 'number' && a.progress < 100)) return 'uploading';\n return 'idle';\n}\n\n/**\n * One attached file: image thumbnail or file-type icon, name, size, upload progress\n * (a progressbar), error with retry, and a remove button.\n */\nexport function AttachmentChip({\n attachment: a,\n variant = 'chip',\n onRemove,\n onRetry,\n disabled = false,\n className,\n ref,\n}: AttachmentChipProps) {\n const { t, tc } = useChatI18n();\n const status = attachmentStatus(a);\n const kind = fileKind(a.name, a.type);\n const Icon = status === 'error' ? AlertCircle : ICONS[kind];\n const showImage = a.previewUrl !== undefined && kind === 'image' && status !== 'error';\n const tile = variant === 'tile';\n const pct = typeof a.progress === 'number' ? Math.max(0, Math.min(100, Math.round(a.progress))) : null;\n\n const media = (\n <span className={cn(tile ? s.tileMedia : s.media, status === 'error' && s.mediaError)}>\n {showImage ? <img src={a.previewUrl} alt=\"\" className={s.img} /> : <Icon size={tile ? 22 : 14} aria-hidden />}\n </span>\n );\n\n const meta =\n status === 'error' ? (\n <span className={s.metaError}>{typeof a.error === 'string' ? a.error : tc('chat.uploadFailed')}</span>\n ) : status === 'uploading' ? (\n <span className={s.meta}>{pct === null ? t('common.loading') : `${pct}%`}</span>\n ) : a.size !== undefined ? (\n <span className={s.meta}>{formatBytes(a.size)}</span>\n ) : null;\n\n const buttons = (\n <>\n {status === 'error' && onRetry && (\n <button\n type=\"button\"\n className={s.button}\n aria-label={tc('chat.retryUpload', { name: a.name })}\n disabled={disabled}\n onClick={() => onRetry(a.id)}\n >\n <RotateCcw size={12} aria-hidden />\n </button>\n )}\n {onRemove && (\n <button\n type=\"button\"\n className={s.button}\n aria-label={t('common.removeItem', { label: a.name })}\n disabled={disabled}\n onClick={() => onRemove(a.id)}\n >\n <X size={12} aria-hidden />\n </button>\n )}\n </>\n );\n\n return (\n <div ref={ref} data-status={status} data-kind={kind} className={cn(tile ? s.tile : s.chip, className)}>\n {media}\n <span className={tile ? s.tileText : s.text}>\n <span className={s.name} title={a.name}>\n {a.name}\n </span>\n {meta}\n </span>\n {tile\n ? (onRemove || (status === 'error' && onRetry)) && <span className={s.tileActions}>{buttons}</span>\n : buttons}\n {status === 'uploading' && (\n <span\n role=\"progressbar\"\n aria-label={tc('chat.uploading', { name: a.name })}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={pct ?? undefined}\n className={s.track}\n >\n <span\n className={pct === null ? s.barIndeterminate : s.bar}\n style={pct === null ? undefined : { width: `${pct}%` }}\n />\n </span>\n )}\n </div>\n );\n}\n","import { cn } from '@gntik-ai/ui';\nimport type { Ref } from 'react';\nimport { useChatI18n } from '../utils/i18n';\nimport { AttachmentChip, type ChatAttachment } from './AttachmentChip';\nimport { attachmentStyles as s } from './attachment.variants';\n\nexport interface AttachmentListProps {\n attachments: ChatAttachment[];\n /** `chip` for the composer, `tile` for larger image previews in a message. */\n variant?: 'chip' | 'tile';\n onRemove?: (id: string) => void;\n onRetry?: (id: string) => void;\n disabled?: boolean;\n /** Accessible name of the list. Default \"Attachments\". */\n label?: string;\n className?: string;\n ref?: Ref<HTMLUListElement>;\n}\n\n/** A labelled list of AttachmentChips. Renders nothing when empty. */\nexport function AttachmentList({\n attachments,\n variant = 'chip',\n onRemove,\n onRetry,\n disabled,\n label,\n className,\n ref,\n}: AttachmentListProps) {\n const { t } = useChatI18n();\n if (attachments.length === 0) return null;\n return (\n <ul ref={ref} aria-label={label ?? t('chat.attachments')} className={cn(s.list, className)}>\n {attachments.map((a) => (\n <li key={a.id} className={s.item}>\n <AttachmentChip attachment={a} variant={variant} onRemove={onRemove} onRetry={onRetry} disabled={disabled} />\n </li>\n ))}\n </ul>\n );\n}\n","export type AttachmentRejectionReason = 'type' | 'size' | 'count';\n\nexport interface AttachmentRejection {\n file: File;\n reason: AttachmentRejectionReason;\n /** Human-readable message (set by ChatComposer from the i18n catalog). */\n message: string;\n}\n\nexport interface ValidateFilesOptions {\n /** Same syntax as `<input accept>`: \".pdf,.csv,image/*,application/json\". */\n accept?: string;\n /** Largest allowed file, in bytes. */\n maxSize?: number;\n /** Most files allowed in total, counting `current`. */\n maxFiles?: number;\n /** Files already attached. */\n current?: number;\n}\n\n/** Whether a file matches an `accept` list (extensions, exact MIME types and `type/*`). */\nexport function matchesAccept(file: Pick<File, 'name' | 'type'>, accept?: string): boolean {\n if (!accept?.trim()) return true;\n const name = file.name.toLowerCase();\n const type = file.type.toLowerCase();\n return accept\n .split(',')\n .map((a) => a.trim().toLowerCase())\n .filter(Boolean)\n .some((rule) => {\n if (rule.startsWith('.')) return name.endsWith(rule);\n if (rule.endsWith('/*')) return type.startsWith(rule.slice(0, -1));\n return type === rule;\n });\n}\n\n/** Splits files into accepted ones and rejections (without messages) by type, size and count. */\nexport function validateFiles(files: File[], { accept, maxSize, maxFiles, current = 0 }: ValidateFilesOptions) {\n const accepted: File[] = [];\n const rejected: Array<{ file: File; reason: AttachmentRejectionReason }> = [];\n for (const file of files) {\n if (!matchesAccept(file, accept)) rejected.push({ file, reason: 'type' });\n else if (maxSize !== undefined && file.size > maxSize) rejected.push({ file, reason: 'size' });\n else if (maxFiles !== undefined && current + accepted.length >= maxFiles) rejected.push({ file, reason: 'count' });\n else accepted.push(file);\n }\n return { accepted, rejected };\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'AttachmentList',\n group: 'Display',\n status: 'beta',\n description:\n 'Files attached to a message or waiting in the composer. Each AttachmentChip shows an image thumbnail or a file-type icon, the name, the size, upload progress (a labelled progressbar; indeterminate holds still under reduced motion), an error with Retry, and a Remove button. `variant=\"tile\"` gives larger image previews inside a message. `validateFiles` / `matchesAccept` back the composer’s accept and max-size checks.',\n pattern: 'list',\n keyboard: [\n ['Tab', 'Moves through each chip’s Retry (on error) and Remove buttons'],\n ['Enter / Space', 'Activates the focused Retry or Remove button'],\n ],\n tokens: [\n 'secondary',\n 'card',\n 'border',\n 'muted-foreground',\n 'primary',\n 'destructive',\n 'destructive-text',\n 'focus-ring',\n ],\n};\n","import { focusRing } from '../utils/focus';\n\n/** Slot classes for ChatComposer (focus ring on the frame, like the legacy composer). */\nexport const chatComposerStyles = {\n root: [\n 'relative overflow-hidden rounded-xl border border-border bg-card shadow-sm transition-colors motion-reduce:transition-none',\n 'focus-within:border-primary/60 focus-within:ring-2 focus-within:ring-ring/25',\n 'data-[disabled]:opacity-60 data-[dragging]:border-primary/60',\n ].join(' '),\n dropOverlay:\n 'pointer-events-none absolute inset-0 z-10 flex items-center justify-center gap-2 rounded-xl border-2 border-dashed border-primary/60 bg-card/95 text-[13px] font-medium text-primary-text',\n errors:\n 'mx-3 mt-3 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/8 px-2.5 py-1.5 text-[12px] text-destructive-chip-text',\n errorList: 'flex min-w-0 flex-1 flex-col gap-0.5',\n errorDismiss: `-me-1 grid size-5 shrink-0 place-items-center rounded text-destructive-chip-text hover:bg-foreground/10 ${focusRing}`,\n attachments: 'flex flex-wrap gap-1.5 px-3 pt-3',\n /** @deprecated Chips render AttachmentChip (see attachmentStyles). */\n chip: 'inline-flex h-7 max-w-60 items-center gap-1.5 rounded-md border border-border bg-secondary/50 ps-2 pe-1 text-[12px] text-foreground',\n chipName: 'truncate font-medium',\n chipSize: 'shrink-0 font-mono text-[10.5px] text-muted-foreground',\n chipRemove: `grid size-5 shrink-0 place-items-center rounded text-muted-foreground hover:bg-foreground/10 hover:text-foreground ${focusRing}`,\n textarea: [\n 'block max-h-[220px] min-h-[52px] w-full resize-none bg-transparent px-3.5 py-3 text-[14px] leading-6 text-foreground',\n 'field-sizing-content placeholder:text-muted-foreground focus:outline-none disabled:cursor-not-allowed',\n ].join(' '),\n toolbar: 'flex items-center justify-between gap-2 px-2 pb-2',\n tools: 'flex min-w-0 items-center gap-1',\n end: 'flex shrink-0 items-center gap-2',\n count: 'font-mono text-[11px] text-muted-foreground tabular-nums',\n countOver: 'text-destructive-text',\n hint: 'mt-1.5 px-1 text-center text-[11.5px] text-muted-foreground',\n} as const;\n","import { Button, IconButton, cn } from '@gntik-ai/ui';\nimport { ArrowUp, Paperclip, Square, Upload, X } from 'lucide-react';\nimport {\n useId,\n useRef,\n useState,\n type ChangeEvent,\n type ClipboardEvent,\n type DragEvent,\n type FormEvent,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n} from 'react';\nimport { AttachmentList, validateFiles, type AttachmentRejection, type ChatAttachment } from '../Attachment';\nimport { formatBytes } from '../utils/format';\nimport { useChatI18n } from '../utils/i18n';\nimport { chatComposerStyles as s } from './chatComposer.variants';\n\n/** A file in the composer: name and size, plus optional type, preview, progress and error. */\nexport type ComposerAttachment = ChatAttachment;\n\nexport interface ChatComposerProps {\n /** Controlled text. Pair with `onValueChange`. */\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n /** Called with the trimmed text when the user sends. Uncontrolled composers clear themselves. */\n onSubmit: (text: string, attachments: ComposerAttachment[]) => void;\n /** A reply is streaming: Send turns into Stop, Enter no longer sends, Escape stops. */\n streaming?: boolean;\n onStop?: () => void;\n disabled?: boolean;\n placeholder?: string;\n /** Accessible name of the text box. */\n label?: string;\n /** Soft limit: shows a counter near the limit and blocks sending above it. */\n maxLength?: number;\n /** Attached files shown as removable chips (thumbnail, progress, error + retry). */\n attachments?: ComposerAttachment[];\n /**\n * Shows the attach button and enables paste and drag-and-drop of files; called with the\n * files that pass `accept`, `maxSize` and `maxFiles`.\n */\n onAttach?: (files: File[]) => void;\n onRemoveAttachment?: (id: string) => void;\n /** Shows Retry on attachments in the error state. */\n onRetryAttachment?: (id: string) => void;\n /** Allowed types, `<input accept>` syntax (e.g. \".pdf,.csv,image/*\"). Also checked on paste and drop. */\n accept?: string;\n /** Largest allowed file, in bytes. */\n maxSize?: number;\n /** Most files attached at once. */\n maxFiles?: number;\n /** Called with the files that failed validation (their messages are also shown under the box). */\n onReject?: (rejections: AttachmentRejection[]) => void;\n /** Slot left of the send button, e.g. a model Select. */\n modelPicker?: ReactNode;\n /** Extra tools after the attach button. */\n tools?: ReactNode;\n /** Small line under the box. Defaults to the keyboard hint; pass null to hide it. */\n hint?: ReactNode;\n className?: string;\n ref?: Ref<HTMLTextAreaElement>;\n}\n\n/**\n * Message box for a chat: grows with its content, Enter sends and Shift+Enter adds a line,\n * files (picked, pasted or dropped, validated against accept / maxSize / maxFiles) show as\n * removable chips with previews and upload progress, a model picker can sit in the toolbar, and while a reply\n * streams the send button becomes Stop (Escape also stops).\n */\nexport function ChatComposer({\n value,\n defaultValue = '',\n onValueChange,\n onSubmit,\n streaming = false,\n onStop,\n disabled = false,\n placeholder: placeholderProp,\n label: labelProp,\n maxLength,\n attachments = [],\n onAttach,\n onRemoveAttachment,\n onRetryAttachment,\n accept,\n maxSize,\n maxFiles,\n onReject,\n modelPicker,\n tools,\n hint,\n className,\n ref,\n}: ChatComposerProps) {\n const { t, tc } = useChatI18n();\n const placeholder = placeholderProp ?? t('chat.placeholder');\n const label = labelProp ?? t('chat.messageLabel');\n const id = useId();\n const [inner, setInner] = useState(defaultValue);\n const text = value ?? inner;\n const fileInput = useRef<HTMLInputElement>(null);\n const dragDepth = useRef(0);\n const [dragging, setDragging] = useState(false);\n const [errors, setErrors] = useState<string[]>([]);\n const canAttach = onAttach !== undefined && !disabled;\n\n const setText = (next: string) => {\n if (value === undefined) setInner(next);\n onValueChange?.(next);\n };\n\n const length = text.length;\n const over = maxLength !== undefined && length > maxLength;\n const showCount = maxLength !== undefined && length >= maxLength * 0.8;\n const canSend = !disabled && !streaming && !over && (text.trim().length > 0 || attachments.length > 0);\n\n const send = () => {\n if (!canSend) return;\n onSubmit(text.trim(), attachments);\n if (value === undefined) setInner('');\n };\n\n const onKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {\n e.preventDefault();\n send();\n } else if (e.key === 'Escape' && streaming && onStop) {\n e.preventDefault();\n onStop();\n }\n };\n\n const addFiles = (files: File[]) => {\n if (!onAttach || files.length === 0) return;\n const { accepted, rejected } = validateFiles(files, { accept, maxSize, maxFiles, current: attachments.length });\n const rejections: AttachmentRejection[] = rejected.map(({ file, reason }) => ({\n file,\n reason,\n message:\n reason === 'type'\n ? tc('chat.fileTypeNotAllowed', { name: file.name })\n : reason === 'size'\n ? tc('chat.fileTooLarge', { name: file.name, max: formatBytes(maxSize ?? 0) })\n : tc('chat.tooManyFiles', { max: maxFiles ?? 0 }),\n }));\n // One \"too many files\" line is enough.\n setErrors([...new Set(rejections.map((r) => r.message))]);\n if (rejections.length) onReject?.(rejections);\n if (accepted.length) onAttach(accepted);\n };\n\n const onFiles = (e: ChangeEvent<HTMLInputElement>) => {\n addFiles(Array.from(e.target.files ?? []));\n e.target.value = '';\n };\n\n const onPaste = (e: ClipboardEvent<HTMLTextAreaElement>) => {\n const files = Array.from(e.clipboardData?.files ?? []);\n if (!canAttach || files.length === 0) return;\n e.preventDefault();\n addFiles(files);\n };\n\n const hasFiles = (e: DragEvent) => Array.from(e.dataTransfer?.types ?? []).includes('Files');\n const dropHandlers = canAttach\n ? {\n onDragEnter: (e: DragEvent<HTMLFormElement>) => {\n if (!hasFiles(e)) return;\n e.preventDefault();\n dragDepth.current += 1;\n setDragging(true);\n },\n onDragOver: (e: DragEvent<HTMLFormElement>) => {\n if (!hasFiles(e)) return;\n e.preventDefault();\n if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy';\n },\n onDragLeave: () => {\n dragDepth.current = Math.max(0, dragDepth.current - 1);\n if (dragDepth.current === 0) setDragging(false);\n },\n onDrop: (e: DragEvent<HTMLFormElement>) => {\n e.preventDefault();\n dragDepth.current = 0;\n setDragging(false);\n addFiles(Array.from(e.dataTransfer?.files ?? []));\n },\n }\n : {};\n\n const hintNode =\n hint === undefined ? (\n <>\n <kbd className=\"font-sans\">{t('kbd.enter')}</kbd> {t('chat.hintSend')} ·{' '}\n <kbd className=\"font-sans\">{t('chat.shiftEnter')}</kbd> {t('chat.hintNewLine')}\n </>\n ) : (\n hint\n );\n\n return (\n <div className={className}>\n <form\n className={s.root}\n data-disabled={disabled || undefined}\n data-dragging={dragging || undefined}\n {...dropHandlers}\n onSubmit={(e: FormEvent) => {\n e.preventDefault();\n send();\n }}\n >\n {dragging && (\n <div aria-hidden className={s.dropOverlay}>\n <Upload size={16} />\n {tc('chat.dropFiles')}\n </div>\n )}\n <AttachmentList\n attachments={attachments}\n onRemove={onRemoveAttachment}\n onRetry={onRetryAttachment}\n disabled={disabled}\n className={s.attachments}\n />\n <div role=\"alert\" className={cn(errors.length > 0 && s.errors)}>\n {errors.length > 0 && (\n <>\n <ul className={s.errorList}>\n {errors.map((m) => (\n <li key={m}>{m}</li>\n ))}\n </ul>\n <button\n type=\"button\"\n className={s.errorDismiss}\n aria-label={t('common.dismiss')}\n onClick={() => setErrors([])}\n >\n <X size={12} aria-hidden />\n </button>\n </>\n )}\n </div>\n <textarea\n ref={ref}\n id={`${id}-input`}\n rows={1}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n disabled={disabled}\n placeholder={placeholder}\n aria-label={label}\n aria-invalid={over || undefined}\n aria-describedby={showCount ? `${id}-count` : undefined}\n className={s.textarea}\n />\n <div className={s.toolbar}>\n <div className={s.tools}>\n {onAttach && (\n <>\n <IconButton\n size=\"sm\"\n icon={Paperclip}\n label={t('chat.attach')}\n disabled={disabled}\n onClick={() => fileInput.current?.click()}\n />\n <input\n ref={fileInput}\n type=\"file\"\n multiple\n hidden\n accept={accept}\n aria-label={t('chat.attach')}\n onChange={onFiles}\n />\n </>\n )}\n {tools}\n </div>\n <div className={s.end}>\n {showCount && (\n <span id={`${id}-count`} className={cn(s.count, over && s.countOver)}>\n {length}/{maxLength}\n {over && <span className=\"sr-only\"> {t('chat.overLimit')}</span>}\n </span>\n )}\n {modelPicker}\n {streaming ? (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n icon={Square}\n aria-label={t('chat.stop')}\n onClick={onStop}\n disabled={!onStop}\n >\n {t('common.stop')}\n </Button>\n ) : (\n <IconButton\n size=\"sm\"\n variant=\"primary\"\n icon={ArrowUp}\n label={t('chat.send')}\n type=\"submit\"\n disabled={!canSend}\n />\n )}\n </div>\n </div>\n </form>\n {hintNode !== null && <p className={s.hint}>{hintNode}</p>}\n </div>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'ChatComposer',\n group: 'Forms',\n status: 'beta',\n description:\n 'Chat input: autosizing textarea, Enter sends and Shift+Enter adds a line, attachments (pick, paste or drag-and-drop files; `accept`, `maxSize` and `maxFiles` validation with messages in an alert; chips with image thumbnails, file-type icons, size, upload progress, error + Retry and Remove), a model-picker slot (e.g. a compact ModelPicker), a character counter near the limit, a disabled state, and a Stop button while a reply streams.',\n keyboard: [\n ['Enter', 'Sends the message (ignored while streaming or during IME composition)'],\n ['Shift+Enter', 'Inserts a new line'],\n ['Escape', 'While a reply streams: stops it'],\n [\n 'Tab',\n 'Moves through attachment Retry/Remove buttons, the text box, attach, tools, the model picker and Send/Stop',\n ],\n ['Ctrl/⌘+V', 'In the text box: pasted files are attached (validated) instead of inserted'],\n ],\n tokens: [\n 'card',\n 'destructive-chip-text',\n 'primary-text',\n 'border',\n 'primary',\n 'ring',\n 'secondary',\n 'muted-foreground',\n 'destructive-text',\n 'focus-ring',\n ],\n};\n","/** Slot classes for TypingIndicator. Dots pulse in sequence; static under reduced motion. */\nexport const typingIndicatorStyles = {\n root: 'inline-flex items-center gap-2 text-muted-foreground',\n dots: 'inline-flex h-6 items-center gap-1',\n dot: 'size-1.5 rounded-full bg-muted-foreground animate-pulse motion-reduce:animate-none',\n label: 'text-[12.5px]',\n size: {\n sm: { dots: 'h-4 gap-0.5', dot: 'size-1' },\n md: { dots: '', dot: '' },\n },\n} as const;\n\n/** Thin blinking caret after streamed plain text (static under reduced motion). */\nexport const streamingCaret =\n 'ms-0.5 inline-block h-[1.05em] w-[2px] translate-y-[2px] bg-primary animate-pulse motion-reduce:animate-none';\n","import { cn } from '@gntik-ai/ui';\nimport type { Ref } from 'react';\nimport { useChatI18n } from '../utils/i18n';\nimport { typingIndicatorStyles as s } from './typingIndicator.variants';\n\nexport interface TypingIndicatorProps {\n /** Who is typing; used in the accessible text (\"Assistant is typing\"). */\n author?: string;\n /** Show the text next to the dots instead of keeping it screen-reader only. */\n showLabel?: boolean;\n /** Overrides the text entirely. */\n label?: string;\n size?: 'sm' | 'md';\n /**\n * Announce the text through its own polite status region. Off by default: in a thread,\n * ChatAnnouncer already announces \"is responding\" once.\n */\n announce?: boolean;\n className?: string;\n ref?: Ref<HTMLSpanElement>;\n}\n\n/**\n * Three dots that pulse while a reply is being written. The dots are decorative; the text\n * (\"Assistant is typing\") is always in the accessibility tree. Under reduced motion the dots\n * hold still.\n */\nexport function TypingIndicator({\n author,\n showLabel = false,\n label,\n size = 'md',\n announce = false,\n className,\n ref,\n}: TypingIndicatorProps) {\n const { t, tc } = useChatI18n();\n const text = label ?? tc('chat.typing', { author: author ?? t('chat.assistant') });\n const sz = s.size[size];\n return (\n <span\n ref={ref}\n data-slot=\"typing-indicator\"\n role={announce ? 'status' : undefined}\n className={cn(s.root, className)}\n >\n <span aria-hidden className={cn(s.dots, sz.dots)}>\n <span className={cn(s.dot, sz.dot)} />\n <span className={cn(s.dot, sz.dot, '[animation-delay:150ms]')} />\n <span className={cn(s.dot, sz.dot, '[animation-delay:300ms]')} />\n </span>\n <span className={showLabel ? s.label : 'sr-only'}>{text}</span>\n </span>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'TypingIndicator',\n group: 'Feedback',\n status: 'beta',\n description:\n 'Three pulsing dots shown while a reply is being written, with the text \"Assistant is typing\" for screen readers (or visible with `showLabel`). The dots are decorative and hold still under reduced motion. ChatMessage renders it while a streaming turn is still empty.',\n keyboard: [],\n tokens: ['muted-foreground'],\n};\n","/** Slot classes for ChatMessage, per role. */\nexport const chatMessageStyles = {\n root: 'group/message relative flex gap-3 outline-none',\n avatar: 'mt-0.5 shrink-0',\n body: 'flex min-w-0 flex-1 flex-col gap-1',\n meta: 'flex items-baseline gap-2 text-[12px] leading-5',\n author: 'font-semibold text-foreground',\n time: 'font-mono text-[11px] text-muted-foreground',\n content: 'min-w-0 text-[14px] leading-[1.7] text-foreground',\n actions: [\n 'flex items-center gap-0.5 transition-opacity motion-reduce:transition-none',\n 'opacity-0 group-hover/message:opacity-100 group-focus-within/message:opacity-100 [@media(hover:none)]:opacity-100',\n ].join(' '),\n actionsVisible: 'opacity-100',\n /** @deprecated The empty streaming state renders TypingIndicator (see typingIndicatorStyles). */\n typing: 'inline-flex h-6 items-center gap-1',\n /** @deprecated See typingIndicatorStyles.dot. */\n typingDot: 'size-1.5 rounded-full bg-muted-foreground animate-pulse motion-reduce:animate-none',\n role: {\n user: {\n root: 'flex-row-reverse',\n body: 'items-end',\n meta: 'flex-row-reverse',\n content:\n 'max-w-[85%] rounded-2xl rounded-se-md bg-secondary px-4 py-2.5 whitespace-pre-wrap [overflow-wrap:anywhere]',\n },\n assistant: { root: '', body: '', meta: '', content: '' },\n participant: {\n root: '',\n body: 'items-start',\n meta: '',\n content:\n 'max-w-[85%] rounded-2xl rounded-ss-md border border-border bg-card px-4 py-2.5 whitespace-pre-wrap [overflow-wrap:anywhere]',\n },\n system: {\n root: 'justify-center',\n body: 'items-center',\n meta: 'sr-only',\n content:\n 'rounded-full border border-border bg-card px-3 py-1 text-center text-[12px] leading-5 text-muted-foreground',\n },\n tool: { root: '', body: '', meta: '', content: 'text-[13px]' },\n },\n} as const;\n","import { Avatar, IconButton, SimpleTooltip, cn, getInitials, useI18n, type MessageKey } from '@gntik-ai/ui';\nimport { Check, Copy, RotateCcw, Sparkles, ThumbsDown, ThumbsUp, Wrench } from 'lucide-react';\nimport { useId, type ReactNode, type Ref } from 'react';\nimport { TypingIndicator, streamingCaret } from '../TypingIndicator';\nimport { formatTime } from '../utils/format';\nimport { useCopy } from '../utils/useCopy';\nimport { chatMessageStyles as s } from './chatMessage.variants';\n\n/**\n * Who wrote a turn. `participant` is another person in the conversation (a teammate, an agent\n * handing over): not the current user and not the assistant.\n */\nexport type ChatRole = 'user' | 'assistant' | 'participant' | 'system' | 'tool';\nexport type ChatFeedback = 'up' | 'down' | null;\n\nexport interface ChatMessageProps {\n role: ChatRole;\n /** Display name; defaults per role (\"You\", \"Assistant\", \"Participant\", \"System\", \"Tool\"). Pass it for `participant`. */\n author?: string;\n /** Replaces the default avatar. Pass `null` to hide it. */\n avatar?: ReactNode;\n /** Image URL for the default avatar of `user` and `participant` turns (initials show while it loads or if it fails). */\n avatarSrc?: string;\n /** When the message was sent. A Date renders as a local short time. */\n timestamp?: Date | string;\n /** The body: a string, a <Markdown>, a ToolCallCard… */\n children?: ReactNode;\n /**\n * Text is still arriving: marks the message aria-busy, hides the actions, shows a\n * TypingIndicator while empty and a caret after plain-text children (a streaming\n * <Markdown> draws its own caret).\n */\n streaming?: boolean;\n /** Draw the caret after streamed plain-text children. Default true. */\n showCaret?: boolean;\n /** Plain text to copy; shows the Copy action. */\n copyText?: string;\n /** Shows the Retry action (assistant replies). */\n onRetry?: () => void;\n /** Current feedback (controlled). */\n feedback?: ChatFeedback;\n /** Shows the thumbs; called with the new value (clicking the active thumb clears it). */\n onFeedback?: (value: ChatFeedback) => void;\n /** Extra actions appended to the action group. */\n actions?: ReactNode;\n /** Keep the actions visible instead of revealing them on hover/focus. */\n alwaysShowActions?: boolean;\n className?: string;\n ref?: Ref<HTMLElement>;\n}\n\nconst DEFAULT_AUTHOR: Record<ChatRole, MessageKey> = {\n user: 'chat.you',\n assistant: 'chat.assistant',\n participant: 'chat.participant',\n system: 'chat.system',\n tool: 'chat.tool',\n};\n\nfunction DefaultAvatar({ role, author, src }: { role: ChatRole; author: string; src?: string }) {\n if (role === 'assistant') return <Avatar size=\"sm\" tone=\"primary\" fallback={<Sparkles size={15} aria-hidden />} />;\n if (role === 'tool') return <Avatar size=\"sm\" tone=\"secondary\" fallback={<Wrench size={14} aria-hidden />} />;\n // Decorative: the author name is already shown next to it.\n return (\n <Avatar size=\"sm\" tone={role === 'participant' ? 'accent' : 'secondary'} src={src} initials={getInitials(author)} />\n );\n}\n\n/**\n * One turn in a conversation. User turns are right-aligned bubbles, participant turns (another\n * person) are start-aligned outlined bubbles, assistant turns are full-width prose, system notes are centred pills and tool turns hold a ToolCallCard. Copy,\n * retry and feedback actions appear on hover or keyboard focus and are reachable with Tab.\n */\nexport function ChatMessage({\n role,\n author,\n avatar,\n avatarSrc,\n timestamp,\n children,\n streaming = false,\n showCaret = true,\n copyText,\n onRetry,\n feedback = null,\n onFeedback,\n actions,\n alwaysShowActions = false,\n className,\n ref,\n}: ChatMessageProps) {\n const id = useId();\n const { t } = useI18n();\n const name = author ?? t(DEFAULT_AUTHOR[role]);\n const v = s.role[role];\n const { copied, copy } = useCopy();\n const isEmpty = children === undefined || children === null || children === '';\n const time =\n timestamp instanceof Date ? (\n <time dateTime={timestamp.toISOString()} className={s.time}>\n {formatTime(timestamp)}\n </time>\n ) : timestamp ? (\n <span className={s.time}>{timestamp}</span>\n ) : null;\n const hasActions = !streaming && role !== 'system' && (copyText !== undefined || onRetry || onFeedback || actions);\n const showAvatar = role !== 'system' && avatar !== null;\n\n return (\n <article\n ref={ref}\n aria-labelledby={`${id}-author`}\n aria-busy={streaming || undefined}\n data-role={role}\n data-streaming={streaming || undefined}\n className={cn(s.root, v.root, className)}\n >\n {showAvatar && (\n <div className={s.avatar}>{avatar ?? <DefaultAvatar role={role} author={name} src={avatarSrc} />}</div>\n )}\n <div className={cn(s.body, v.body)}>\n <div className={cn(s.meta, v.meta)}>\n <span id={`${id}-author`} className={s.author}>\n {name}\n </span>\n {time}\n </div>\n <div className={cn(s.content, v.content)}>\n {streaming && isEmpty ? (\n <TypingIndicator author={name} />\n ) : streaming && showCaret && (typeof children === 'string' || typeof children === 'number') ? (\n <>\n {children}\n <span aria-hidden data-slot=\"streaming-caret\" className={streamingCaret} />\n </>\n ) : (\n children\n )}\n </div>\n {hasActions && (\n <div\n role=\"group\"\n aria-label={t('chat.actionsFor', { name })}\n className={cn(s.actions, alwaysShowActions && s.actionsVisible)}\n >\n {copyText !== undefined && (\n <SimpleTooltip content={copied ? t('common.copied') : t('common.copy')}>\n <IconButton\n size=\"sm\"\n icon={copied ? Check : Copy}\n label={copied ? t('common.copied') : t('chat.copyMessage')}\n onClick={() => void copy(copyText)}\n />\n </SimpleTooltip>\n )}\n {onRetry && (\n <SimpleTooltip content={t('common.retry')}>\n <IconButton size=\"sm\" icon={RotateCcw} label={t('common.retry')} onClick={onRetry} />\n </SimpleTooltip>\n )}\n {onFeedback && (\n <>\n <SimpleTooltip content={t('chat.goodResponse')}>\n <IconButton\n size=\"sm\"\n icon={ThumbsUp}\n label={t('chat.goodResponse')}\n aria-pressed={feedback === 'up'}\n className={cn(feedback === 'up' && 'text-primary-text')}\n onClick={() => onFeedback(feedback === 'up' ? null : 'up')}\n />\n </SimpleTooltip>\n <SimpleTooltip content={t('chat.badResponse')}>\n <IconButton\n size=\"sm\"\n icon={ThumbsDown}\n label={t('chat.badResponse')}\n aria-pressed={feedback === 'down'}\n className={cn(feedback === 'down' && 'text-destructive-text')}\n onClick={() => onFeedback(feedback === 'down' ? null : 'down')}\n />\n </SimpleTooltip>\n </>\n )}\n {actions}\n </div>\n )}\n </div>\n </article>\n );\n}\n","import { useI18n } from '@gntik-ai/ui';\n\nexport interface ChatAnnouncerProps {\n /** A reply is being generated. */\n streaming: boolean;\n /** Plain text of the latest completed reply (announced once, when streaming ends). */\n lastReply?: string;\n /** Who is replying, used in the \"is responding\" status. */\n author?: string;\n /** Max characters of the completed reply to announce. */\n maxLength?: number;\n}\n\n/**\n * Screen-reader strategy for streaming: the thread itself is not a live region (it would\n * re-announce every token). This single polite, atomic status says \"Assistant is responding…\"\n * when a stream starts and reads the finished reply once when it ends.\n */\nexport function ChatAnnouncer({ streaming, lastReply, author, maxLength = 600 }: ChatAnnouncerProps) {\n const { t } = useI18n();\n let text = '';\n if (streaming) text = t('chat.responding', { author: author ?? t('chat.assistant') });\n else if (lastReply) text = lastReply.length > maxLength ? `${lastReply.slice(0, maxLength)}…` : lastReply;\n return (\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {text}\n </div>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'ChatMessage',\n group: 'Display',\n status: 'beta',\n description:\n 'One conversation turn for the roles user (end-aligned bubble), participant (another person, e.g. a teammate: start-aligned outlined bubble with their name and avatar via `author` / `avatarSrc`), assistant, system and tool: avatar, author, timestamp, body and hover/focus actions (copy, retry, thumbs feedback). While streaming it is aria-busy, hides its actions and shows a TypingIndicator (\"Assistant is typing\") until text arrives and a caret after streamed plain text; ChatAnnouncer announces start and end once instead of every token.',\n pattern: 'article',\n keyboard: [\n ['Tab', 'Reaches each action in order (copy, retry, good, bad); focusing one reveals the action group'],\n ['Enter', 'Activates the focused action'],\n ['Space', 'Activates the focused action; thumbs toggle (aria-pressed)'],\n ],\n tokens: [\n 'foreground',\n 'muted-foreground',\n 'secondary',\n 'card',\n 'border',\n 'primary',\n 'primary-text',\n 'destructive-text',\n 'focus-ring',\n ],\n};\n","/** Slot classes for MessageFeedback. */\nexport const messageFeedbackStyles = {\n root: 'inline-flex items-center gap-0.5',\n up: 'text-primary-text',\n down: 'text-destructive-text',\n popup: 'w-80 max-w-[calc(100vw-2rem)]',\n form: 'flex flex-col gap-3',\n title: 'text-[13px] font-semibold text-foreground',\n label: 'mb-1.5 block text-[12.5px] font-medium text-foreground',\n footer: 'flex justify-end gap-2',\n} as const;\n","import {\n Button,\n IconButton,\n Popover,\n PopoverContent,\n PopoverTitle,\n PopoverTrigger,\n Radio,\n RadioGroup,\n SimpleTooltip,\n Textarea,\n cn,\n} from '@gntik-ai/ui';\nimport { Check, Copy, RefreshCw, ThumbsDown, ThumbsUp } from 'lucide-react';\nimport { useId, useState, type FormEvent, type Ref } from 'react';\nimport { useChatI18n, type ChatMessageKey } from '../utils/i18n';\nimport { useCopy } from '../utils/useCopy';\nimport { messageFeedbackStyles as s } from './messageFeedback.variants';\n\nexport type FeedbackRating = 'up' | 'down';\n\nexport interface FeedbackValue {\n /** `null` = no rating. */\n rating: FeedbackRating | null;\n /** Reason picked after a thumbs down (a `FeedbackReason.value`). */\n reason?: string;\n /** Free-text comment after a thumbs down. */\n comment?: string;\n}\n\nexport interface FeedbackReason {\n value: string;\n label: string;\n}\n\nexport interface MessageFeedbackProps {\n /** Current feedback (controlled). Uncontrolled when omitted. */\n value?: FeedbackValue;\n /**\n * Called on every change: `{ rating: 'up' }`, `{ rating: 'down' }` right away on thumbs down,\n * then `{ rating: 'down', reason, comment }` when the details form is sent, and\n * `{ rating: null }` when the active thumb is pressed again.\n */\n onFeedback?: (value: FeedbackValue) => void;\n /** Reasons offered after a thumbs down. Defaults to a generic list; `[]` hides the picker. */\n reasons?: FeedbackReason[];\n /** Open the reason/comment popover on thumbs down. Default true. */\n askDetails?: boolean;\n /** Plain text to copy; shows the Copy action. */\n copyText?: string;\n /** Shows the Regenerate action. */\n onRegenerate?: () => void;\n /** Accessible name of the group. Default \"Response feedback\". */\n label?: string;\n disabled?: boolean;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n}\n\nconst DEFAULT_REASONS: Array<{ value: string; key: ChatMessageKey }> = [\n { value: 'inaccurate', key: 'chat.reasonInaccurate' },\n { value: 'unhelpful', key: 'chat.reasonUnhelpful' },\n { value: 'incomplete', key: 'chat.reasonIncomplete' },\n { value: 'unsafe', key: 'chat.reasonUnsafe' },\n { value: 'other', key: 'chat.reasonOther' },\n];\n\nconst EMPTY: FeedbackValue = { rating: null };\n\n/**\n * Feedback for an assistant reply: thumbs up / down toggles (aria-pressed), and on thumbs down\n * a popover asking for a reason and an optional comment. Copy and Regenerate sit alongside.\n */\nexport function MessageFeedback({\n value: valueProp,\n onFeedback,\n reasons: reasonsProp,\n askDetails = true,\n copyText,\n onRegenerate,\n label,\n disabled = false,\n className,\n ref,\n}: MessageFeedbackProps) {\n const { t, tc } = useChatI18n();\n const id = useId();\n const [inner, setInner] = useState<FeedbackValue>(EMPTY);\n const value = valueProp ?? inner;\n const [open, setOpen] = useState(false);\n const [reason, setReason] = useState<string>('');\n const [comment, setComment] = useState('');\n const [announcement, setAnnouncement] = useState('');\n const { copied, copy } = useCopy();\n const reasons = reasonsProp ?? DEFAULT_REASONS.map((r) => ({ value: r.value, label: tc(r.key) }));\n\n const emit = (next: FeedbackValue) => {\n if (valueProp === undefined) setInner(next);\n onFeedback?.(next);\n };\n\n const pressUp = () => {\n setOpen(false);\n const next: FeedbackValue = value.rating === 'up' ? EMPTY : { rating: 'up' };\n emit(next);\n setAnnouncement(next.rating ? tc('chat.feedbackThanks') : tc('chat.feedbackCleared'));\n };\n\n const pressDown = () => {\n if (value.rating === 'down') {\n setOpen(false);\n emit(EMPTY);\n setAnnouncement(tc('chat.feedbackCleared'));\n return;\n }\n emit({ rating: 'down' });\n setReason('');\n setComment('');\n if (askDetails) setOpen(true);\n else setAnnouncement(tc('chat.feedbackThanks'));\n };\n\n const submit = (e: FormEvent) => {\n e.preventDefault();\n const trimmed = comment.trim();\n emit({ rating: 'down', ...(reason ? { reason } : {}), ...(trimmed ? { comment: trimmed } : {}) });\n setOpen(false);\n setAnnouncement(tc('chat.feedbackThanks'));\n };\n\n const upLabel = t('chat.goodResponse');\n const downLabel = t('chat.badResponse');\n\n return (\n <div ref={ref} role=\"group\" aria-label={label ?? tc('chat.feedback')} className={cn(s.root, className)}>\n {copyText !== undefined && (\n <SimpleTooltip content={copied ? t('common.copied') : t('common.copy')}>\n <IconButton\n size=\"sm\"\n icon={copied ? Check : Copy}\n label={copied ? t('common.copied') : t('chat.copyMessage')}\n disabled={disabled}\n onClick={() => void copy(copyText)}\n />\n </SimpleTooltip>\n )}\n {onRegenerate && (\n <SimpleTooltip content={tc('chat.regenerate')}>\n <IconButton\n size=\"sm\"\n icon={RefreshCw}\n label={tc('chat.regenerate')}\n disabled={disabled}\n onClick={onRegenerate}\n />\n </SimpleTooltip>\n )}\n <SimpleTooltip content={upLabel}>\n <IconButton\n size=\"sm\"\n icon={ThumbsUp}\n label={upLabel}\n aria-pressed={value.rating === 'up'}\n disabled={disabled}\n className={cn(value.rating === 'up' && s.up)}\n onClick={pressUp}\n />\n </SimpleTooltip>\n <Popover\n open={open}\n onOpenChange={(next) => {\n // Opening is driven by pressDown (so a second press clears instead of reopening).\n if (!next) setOpen(false);\n }}\n >\n <PopoverTrigger\n render={\n <IconButton\n size=\"sm\"\n icon={ThumbsDown}\n label={downLabel}\n aria-pressed={value.rating === 'down'}\n disabled={disabled}\n className={cn(value.rating === 'down' && s.down)}\n />\n }\n onClick={pressDown}\n />\n <PopoverContent side=\"top\" align=\"end\" className={s.popup}>\n <form className={s.form} onSubmit={submit}>\n <PopoverTitle id={`${id}-title`} className={s.title}>\n {tc('chat.feedbackTitle')}\n </PopoverTitle>\n {reasons.length > 0 && (\n <RadioGroup aria-labelledby={`${id}-title`} value={reason} onValueChange={(v) => setReason(String(v))}>\n {reasons.map((r) => (\n <Radio key={r.value} value={r.value} label={r.label} />\n ))}\n </RadioGroup>\n )}\n <div>\n <label htmlFor={`${id}-comment`} className={s.label}>\n {tc('chat.feedbackComment')}\n </label>\n <Textarea\n id={`${id}-comment`}\n rows={3}\n value={comment}\n onValueChange={setComment}\n placeholder={tc('chat.feedbackPlaceholder')}\n />\n </div>\n <div className={s.footer}>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => setOpen(false)}>\n {t('common.cancel')}\n </Button>\n <Button type=\"submit\" size=\"sm\">\n {tc('chat.feedbackSubmit')}\n </Button>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n <span role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {announcement}\n </span>\n </div>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'MessageFeedback',\n group: 'Actions',\n status: 'beta',\n description:\n 'Actions for an assistant reply: copy, regenerate and thumbs up / down toggles (aria-pressed). Thumbs down opens a popover with a reason picker and an optional comment. Controlled with `value` + `onFeedback`; pressing the active thumb clears it. A polite status confirms the feedback.',\n primitive: 'Popover',\n pattern: 'toggle button + dialog',\n keyboard: [\n ['Tab', 'Moves through copy, regenerate, good and bad'],\n ['Enter / Space', 'Toggles the focused thumb (aria-pressed); a second press clears it'],\n ['Enter / Space (on bad)', 'Also opens the details popover; focus moves into it'],\n ['Arrow keys', 'Inside the popover: move between reasons'],\n ['Escape', 'Closes the popover (the rating stays) and returns focus to the thumb'],\n ],\n tokens: ['muted-foreground', 'primary-text', 'destructive-text', 'popover', 'border', 'focus-ring'],\n};\n","/** Slot classes for ModelPicker. */\nexport const modelPickerStyles = {\n trigger: 'w-auto max-w-full min-w-0',\n compactTrigger:\n 'h-7 w-auto max-w-56 min-w-0 gap-1 border-transparent bg-transparent ps-2 pe-1.5 shadow-none hover:bg-secondary/70 hover:border-transparent',\n triggerValue: 'flex min-w-0 items-center gap-1.5',\n triggerIcon: 'shrink-0 text-muted-foreground',\n triggerName: 'truncate font-medium',\n triggerProvider: 'truncate text-muted-foreground',\n popup: 'w-80 max-w-[calc(100vw-2rem)]',\n item: 'items-start',\n itemBody: 'flex min-w-0 flex-col gap-1 py-0.5 whitespace-normal',\n itemName: 'font-medium text-foreground',\n itemDescription: 'text-[11.5px] leading-4 text-muted-foreground',\n badges: 'flex flex-wrap gap-1',\n reason: 'text-[11.5px] leading-4 text-muted-foreground italic',\n} as const;\n","import {\n Badge,\n Select,\n SelectContent,\n SelectGroup,\n SelectGroupLabel,\n SelectItem,\n SelectTrigger,\n cn,\n} from '@gntik-ai/ui';\nimport { Sparkles } from 'lucide-react';\nimport type { Ref } from 'react';\nimport { useChatI18n, type ChatMessageKey } from '../utils/i18n';\nimport { modelPickerStyles as s } from './modelPicker.variants';\n\nexport type ModelCapability = 'vision' | 'tools' | 'reasoning' | 'files' | 'web' | 'audio';\n\nexport interface ChatModel {\n /** Value reported by `onValueChange`. */\n id: string;\n name: string;\n /** Group heading, e.g. the provider or the deployment. Models are grouped in first-seen order. */\n provider: string;\n description?: string;\n capabilities?: ModelCapability[];\n /** Context window in tokens; shown as \"128K context\". */\n contextWindow?: number;\n disabled?: boolean;\n /** Why it is disabled (\"Needs an upgraded plan\"); shown under the name. */\n disabledReason?: string;\n}\n\nexport interface ModelPickerProps {\n models: ChatModel[];\n /** Selected model id (controlled). */\n value: string | null;\n onValueChange: (id: string) => void;\n /** Small borderless trigger with only the model name, for the composer toolbar. */\n compact?: boolean;\n /** Accessible name of the trigger. Default \"Model\". */\n label?: string;\n placeholder?: string;\n disabled?: boolean;\n /** Hide the provider next to the name in the full trigger. */\n hideProvider?: boolean;\n className?: string;\n ref?: Ref<HTMLButtonElement>;\n}\n\nconst CAPABILITY_KEY: Record<ModelCapability, ChatMessageKey> = {\n vision: 'chat.capabilityVision',\n tools: 'chat.capabilityTools',\n reasoning: 'chat.capabilityReasoning',\n files: 'chat.capabilityFiles',\n web: 'chat.capabilityWeb',\n audio: 'chat.capabilityAudio',\n};\n\n/** Models grouped by provider, keeping first-seen order. */\nexport function groupModels(models: ChatModel[]) {\n const groups = new Map<string, ChatModel[]>();\n for (const m of models) {\n const list = groups.get(m.provider);\n if (list) list.push(m);\n else groups.set(m.provider, [m]);\n }\n return [...groups.entries()].map(([provider, items]) => ({ provider, items }));\n}\n\n/**\n * Model / provider select for a chat: options grouped by provider with capability badges\n * (vision, tools, context size…) and disabled models that say why. `compact` renders a small\n * borderless trigger for the composer toolbar. Built on Select (Base UI).\n */\nexport function ModelPicker({\n models,\n value,\n onValueChange,\n compact = false,\n label,\n placeholder,\n disabled,\n hideProvider = false,\n className,\n ref,\n}: ModelPickerProps) {\n const { tc, formatNumber } = useChatI18n();\n const byId = new Map(models.map((m) => [m.id, m]));\n const items = models.map((m) => ({ value: m.id, label: m.name }));\n\n return (\n <Select<string>\n items={items}\n value={value}\n disabled={disabled}\n onValueChange={(next) => {\n if (next !== null) onValueChange(next);\n }}\n >\n <SelectTrigger\n ref={ref}\n size=\"sm\"\n aria-label={label ?? tc('chat.model')}\n placeholder={placeholder ?? tc('chat.selectModel')}\n className={cn(compact ? s.compactTrigger : s.trigger, className)}\n >\n {(id: string | null) => {\n const m = id === null ? undefined : byId.get(id);\n if (!m) return placeholder ?? tc('chat.selectModel');\n return (\n <span className={s.triggerValue}>\n <Sparkles size={13} aria-hidden className={s.triggerIcon} />\n <span className={s.triggerName}>{m.name}</span>\n {!compact && !hideProvider && <span className={s.triggerProvider}>· {m.provider}</span>}\n </span>\n );\n }}\n </SelectTrigger>\n <SelectContent className={s.popup} align={compact ? 'end' : 'start'}>\n {groupModels(models).map((g) => (\n <SelectGroup key={g.provider}>\n <SelectGroupLabel>{g.provider}</SelectGroupLabel>\n {g.items.map((m) => (\n <SelectItem key={m.id} value={m.id} disabled={m.disabled} label={m.name} className={s.item}>\n <span className={s.itemBody}>\n <span className={s.itemName}>{m.name}</span>\n {m.description && <span className={s.itemDescription}>{m.description}</span>}\n {(m.capabilities?.length || m.contextWindow) && (\n <span className={s.badges}>\n {m.capabilities?.map((c) => (\n <Badge key={c} size=\"sm\" tone=\"neutral\">\n {tc(CAPABILITY_KEY[c])}\n </Badge>\n ))}\n {m.contextWindow !== undefined && (\n <Badge size=\"sm\" tone=\"neutral\" variant=\"outline\">\n {tc('chat.contextWindow', {\n size: formatNumber(m.contextWindow, { notation: 'compact', maximumFractionDigits: 1 }),\n })}\n </Badge>\n )}\n </span>\n )}\n {m.disabled && <span className={s.reason}>{m.disabledReason ?? tc('chat.unavailable')}</span>}\n </span>\n </SelectItem>\n ))}\n </SelectGroup>\n ))}\n </SelectContent>\n </Select>\n );\n}\n","import type { ChatModel } from './ModelPicker';\n\n/** Generic, product-agnostic models for examples and the demo. */\nexport const DEMO_MODELS: ChatModel[] = [\n {\n id: 'swift',\n name: 'Swift',\n provider: 'Hosted',\n description: 'Fast answers for everyday questions.',\n capabilities: ['tools'],\n contextWindow: 128_000,\n },\n {\n id: 'balanced',\n name: 'Balanced',\n provider: 'Hosted',\n description: 'Good default for analysis and writing.',\n capabilities: ['vision', 'tools', 'files'],\n contextWindow: 200_000,\n },\n {\n id: 'deep',\n name: 'Deep reasoning',\n provider: 'Hosted',\n description: 'Plans multi-step work; slower.',\n capabilities: ['vision', 'tools', 'reasoning'],\n contextWindow: 1_000_000,\n disabled: true,\n disabledReason: 'Needs an upgraded plan',\n },\n {\n id: 'local-small',\n name: 'Local small',\n provider: 'Self-hosted',\n description: 'Runs in your own cluster.',\n contextWindow: 32_000,\n },\n {\n id: 'local-vision',\n name: 'Local vision',\n provider: 'Self-hosted',\n capabilities: ['vision'],\n contextWindow: 64_000,\n },\n];\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'ModelPicker',\n group: 'Forms',\n status: 'beta',\n description:\n 'Choose the model (and provider) for a conversation: options grouped by provider with a description, capability badges (vision, tools, reasoning, files, web, audio) and the context size; unavailable models stay listed, disabled, with the reason. `compact` gives a small borderless trigger for the ChatComposer toolbar. Controlled (`value` + `onValueChange`).',\n primitive: 'Select',\n pattern: 'select-only combobox',\n keyboard: [\n ['Enter / Space / ArrowDown', 'On the trigger: opens the list'],\n [\n 'ArrowDown / ArrowUp',\n 'Moves between models; a disabled one can be highlighted (its reason is read) but not selected',\n ],\n ['Type a character', 'Jumps to the model whose name starts with it'],\n ['Enter', 'Selects the highlighted model and closes'],\n ['Escape', 'Closes without changing; focus returns to the trigger'],\n ],\n tokens: ['background', 'popover', 'border', 'secondary', 'primary', 'primary-text', 'muted-foreground', 'focus-ring'],\n};\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseChatScrollOptions {\n /** Distance from the bottom (px) still treated as \"at the bottom\". */\n threshold?: number;\n}\n\nexport interface UseChatScrollResult {\n /** Callback ref for the scrolling element. */\n scrollRef: (el: HTMLElement | null) => void;\n /** Callback ref for the content inside it (watched for growth, e.g. streamed tokens). */\n contentRef: (el: HTMLElement | null) => void;\n /** True while the viewport is pinned to the latest message. */\n isAtBottom: boolean;\n /** Scrolls to the latest message and re-pins auto-scroll. */\n scrollToBottom: (behavior?: ScrollBehavior) => void;\n}\n\n/** Imperative DOM write kept outside the hook (state values must not be mutated in place). */\nfunction pinToBottom(el: HTMLElement) {\n el.scrollTop = el.scrollHeight;\n}\n\nfunction distanceFromBottom(el: HTMLElement) {\n return el.scrollHeight - el.scrollTop - el.clientHeight;\n}\n\n/**\n * Auto-scroll for a chat thread that respects the reader: new content keeps the view pinned\n * to the bottom only while the user is already there. Scrolling up unpins it (and\n * `isAtBottom` turns false, so a \"scroll to latest\" button can show); `scrollToBottom()`\n * pins it again.\n */\nexport function useChatScroll({ threshold = 48 }: UseChatScrollOptions = {}): UseChatScrollResult {\n const [scrollEl, setScrollEl] = useState<HTMLElement | null>(null);\n const [contentEl, setContentEl] = useState<HTMLElement | null>(null);\n const [isAtBottom, setIsAtBottom] = useState(true);\n const pinned = useRef(true);\n const lastTop = useRef(0);\n\n useEffect(() => {\n if (!scrollEl) return;\n lastTop.current = scrollEl.scrollTop;\n const onScroll = () => {\n const top = scrollEl.scrollTop;\n // Re-pin at the bottom; unpin only when the reader moves up (a smooth programmatic\n // scroll towards the bottom passes through \"not at bottom\" without unpinning).\n if (distanceFromBottom(scrollEl) <= threshold) pinned.current = true;\n else if (top < lastTop.current) pinned.current = false;\n lastTop.current = top;\n setIsAtBottom(pinned.current);\n };\n scrollEl.addEventListener('scroll', onScroll, { passive: true });\n return () => scrollEl.removeEventListener('scroll', onScroll);\n }, [scrollEl, threshold]);\n\n useEffect(() => {\n if (!scrollEl) return;\n const follow = () => {\n if (!pinned.current) return;\n pinToBottom(scrollEl);\n lastTop.current = scrollEl.scrollTop;\n };\n follow();\n const target = contentEl ?? scrollEl;\n const mo = new MutationObserver(follow);\n mo.observe(target, { childList: true, subtree: true, characterData: true });\n const ro = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(follow) : undefined;\n ro?.observe(target);\n return () => {\n mo.disconnect();\n ro?.disconnect();\n };\n }, [scrollEl, contentEl]);\n\n const scrollToBottom = useCallback(\n (behavior: ScrollBehavior = 'smooth') => {\n if (!scrollEl) return;\n pinned.current = true;\n setIsAtBottom(true);\n const reduce =\n typeof window.matchMedia === 'function' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n if (typeof scrollEl.scrollTo === 'function') {\n scrollEl.scrollTo({ top: scrollEl.scrollHeight, behavior: reduce ? 'auto' : behavior });\n } else {\n pinToBottom(scrollEl);\n }\n },\n [scrollEl],\n );\n\n return { scrollRef: setScrollEl, contentRef: setContentEl, isAtBottom, scrollToBottom };\n}\n","import { focusRing } from '../utils/focus';\n\n/** Slot classes for ChatLayout (plain strings: this package does not ship tailwind-variants). */\nexport const chatLayoutStyles = {\n root: 'flex h-full min-h-0 w-full bg-background text-foreground',\n thread: 'flex min-w-0 flex-1 flex-col',\n header: 'shrink-0 border-b border-border',\n viewport: 'relative min-h-0 flex-1',\n scroller: `h-full overflow-y-auto overscroll-contain ${focusRing} focus-visible:-outline-offset-2`,\n content: 'mx-auto flex w-full max-w-3xl flex-col gap-6 px-4 py-6 sm:px-6',\n jump: 'pointer-events-none absolute inset-x-0 bottom-3 flex justify-center',\n jumpButton: 'pointer-events-auto rounded-full shadow-md',\n composer: 'shrink-0 bg-background px-4 pb-4 pt-2 sm:px-6',\n composerInner: 'mx-auto w-full max-w-3xl',\n handle: [\n 'group relative w-1.5 shrink-0 cursor-col-resize touch-none bg-transparent',\n 'after:absolute after:inset-y-0 after:left-1/2 after:w-px after:-translate-x-1/2 after:bg-border',\n 'hover:after:w-0.5 hover:after:bg-primary/60 data-[dragging]:after:w-0.5 data-[dragging]:after:bg-primary',\n 'focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-focus-ring',\n ].join(' '),\n panel: 'flex min-h-0 shrink-0 flex-col overflow-hidden border-s border-border bg-card',\n} as const;\n","import { IconButton, cn, useI18n } from '@gntik-ai/ui';\nimport { ArrowDown } from 'lucide-react';\nimport { useRef, useState, type KeyboardEvent, type PointerEvent, type ReactNode, type Ref } from 'react';\nimport { useChatScroll } from '../useChatScroll';\nimport { chatLayoutStyles as s } from './chatLayout.variants';\n\nexport interface ChatLayoutProps {\n /** The messages (ChatMessage list, suggestions, …). */\n children?: ReactNode;\n /** Pinned at the bottom of the thread column, outside the scroll area (usually ChatComposer). */\n composer?: ReactNode;\n /** Optional header above the thread (title, model, actions). */\n header?: ReactNode;\n /** Optional side panel (artifact preview, details). Omit to hide it and its resize handle. */\n panel?: ReactNode;\n /** Accessible name of the side panel landmark. */\n panelLabel?: string;\n /** Initial panel width in px. */\n defaultPanelWidth?: number;\n minPanelWidth?: number;\n maxPanelWidth?: number;\n onPanelWidthChange?: (width: number) => void;\n /** Accessible name of the thread region. */\n label?: string;\n /** Label of the \"jump to latest\" button. */\n scrollButtonLabel?: string;\n /** Extra classes on the root. */\n className?: string;\n /** Extra classes on the centred content column. */\n contentClassName?: string;\n ref?: Ref<HTMLDivElement>;\n}\n\nconst clamp = (v: number, min: number, max: number) => Math.min(max, Math.max(min, v));\nconst isRtl = (el: Element) => getComputedStyle(el).direction === 'rtl';\n\n/**\n * Full-height chat frame: a scrollable thread with auto-scroll that respects scrolling up,\n * a \"jump to latest\" button, the composer pinned below, and an optional side panel that the\n * user can resize by dragging or with the arrow keys on its separator.\n */\nexport function ChatLayout({\n children,\n composer,\n header,\n panel,\n panelLabel: panelLabelProp,\n defaultPanelWidth = 380,\n minPanelWidth = 260,\n maxPanelWidth = 720,\n onPanelWidthChange,\n label: labelProp,\n scrollButtonLabel: scrollButtonLabelProp,\n className,\n contentClassName,\n ref,\n}: ChatLayoutProps) {\n const { t } = useI18n();\n const panelLabel = panelLabelProp ?? t('chat.details');\n const label = labelProp ?? t('chat.conversation');\n const scrollButtonLabel = scrollButtonLabelProp ?? t('chat.scrollToBottom');\n const { scrollRef, contentRef, isAtBottom, scrollToBottom } = useChatScroll();\n const [width, setWidth] = useState(() => clamp(defaultPanelWidth, minPanelWidth, maxPanelWidth));\n const [dragging, setDragging] = useState(false);\n const drag = useRef<{ x: number; width: number; sign: number } | null>(null);\n\n const resize = (next: number) => {\n const w = clamp(Math.round(next), minPanelWidth, maxPanelWidth);\n setWidth(w);\n onPanelWidthChange?.(w);\n };\n\n const onPointerDown = (e: PointerEvent<HTMLDivElement>) => {\n e.currentTarget.setPointerCapture?.(e.pointerId);\n drag.current = { x: e.clientX, width, sign: isRtl(e.currentTarget) ? -1 : 1 };\n setDragging(true);\n };\n const onPointerMove = (e: PointerEvent<HTMLDivElement>) => {\n if (!drag.current) return;\n // The panel sits on the inline end (right in LTR): dragging toward the thread widens it.\n resize(drag.current.width + (drag.current.x - e.clientX) * drag.current.sign);\n };\n const endDrag = () => {\n drag.current = null;\n setDragging(false);\n };\n const onHandleKey = (e: KeyboardEvent<HTMLDivElement>) => {\n const step = (e.shiftKey ? 64 : 16) * (isRtl(e.currentTarget) ? -1 : 1);\n const actions: Record<string, () => void> = {\n ArrowLeft: () => resize(width + step),\n ArrowRight: () => resize(width - step),\n Home: () => resize(maxPanelWidth),\n End: () => resize(minPanelWidth),\n };\n const action = actions[e.key];\n if (action) {\n e.preventDefault();\n action();\n }\n };\n\n return (\n <div ref={ref} className={cn(s.root, className)}>\n <section aria-label={label} className={s.thread}>\n {header && <div className={s.header}>{header}</div>}\n <div className={s.viewport}>\n <div ref={scrollRef} tabIndex={0} aria-label={t('chat.messages')} role=\"region\" className={s.scroller}>\n <div ref={contentRef} className={cn(s.content, contentClassName)}>\n {children}\n </div>\n </div>\n {!isAtBottom && (\n <div className={s.jump}>\n <IconButton\n icon={ArrowDown}\n label={scrollButtonLabel}\n variant=\"secondary\"\n size=\"sm\"\n className={s.jumpButton}\n onClick={() => scrollToBottom()}\n />\n </div>\n )}\n </div>\n {composer && (\n <div className={s.composer}>\n <div className={s.composerInner}>{composer}</div>\n </div>\n )}\n </section>\n {panel && (\n <>\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={t('chat.resizePanel', { panel: panelLabel.toLowerCase() })}\n aria-valuenow={width}\n aria-valuemin={minPanelWidth}\n aria-valuemax={maxPanelWidth}\n tabIndex={0}\n data-dragging={dragging || undefined}\n className={s.handle}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n onKeyDown={onHandleKey}\n />\n <aside aria-label={panelLabel} className={s.panel} style={{ width }}>\n {panel}\n </aside>\n </>\n )}\n </div>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'ChatLayout',\n group: 'Layout',\n status: 'beta',\n description:\n 'Full-height chat frame: scrollable thread with auto-scroll that respects scrolling up, a jump-to-latest button, a composer pinned below and an optional resizable side panel (artifact or details).',\n pattern: 'window splitter',\n keyboard: [\n ['Tab', 'Moves through the thread, the composer, the resize handle and the panel'],\n ['ArrowLeft', 'On the resize handle: widens the side panel (Shift for bigger steps)'],\n ['ArrowRight', 'On the resize handle: narrows the side panel'],\n ['Home', 'On the resize handle: panel to its maximum width'],\n ['End', 'On the resize handle: panel to its minimum width'],\n ],\n tokens: ['background', 'foreground', 'card', 'border', 'primary', 'focus-ring'],\n};\n","import { focusRing } from '../utils/focus';\n\n/** Slot classes for Citation and CitationList. */\nexport const citationStyles = {\n trigger: [\n 'mx-0.5 inline-flex h-[18px] min-w-[18px] -translate-y-px cursor-pointer items-center justify-center rounded-md px-1',\n 'bg-primary/14 align-baseline font-mono text-[10.5px] font-semibold leading-none text-primary-chip-text',\n `transition-colors hover:bg-primary/24 data-[popup-open]:bg-primary/24 motion-reduce:transition-none ${focusRing}`,\n ].join(' '),\n popup: 'w-80',\n head: 'flex items-center gap-2 text-[11.5px] text-muted-foreground',\n index:\n 'grid h-[18px] min-w-[18px] place-items-center rounded-md bg-secondary px-1 font-mono text-[10.5px] font-semibold text-foreground',\n title: 'mt-1.5 text-[13px] font-semibold leading-snug text-foreground',\n snippet: 'mt-1 line-clamp-4 text-[12.5px] leading-relaxed text-muted-foreground',\n open: `mt-2.5 inline-flex items-center gap-1 rounded-sm text-[12.5px] font-medium text-primary-text hover:underline ${focusRing}`,\n list: 'flex flex-col gap-1.5',\n heading: 'mb-1 text-[11.5px] font-semibold tracking-wide text-muted-foreground uppercase',\n item: 'flex gap-2.5 rounded-lg border border-border bg-card px-3 py-2.5',\n itemBody: 'min-w-0 flex-1',\n itemTitle: `rounded-sm text-[13px] font-medium text-foreground hover:text-primary-text hover:underline ${focusRing}`,\n itemHost: 'mt-0.5 truncate font-mono text-[11px] text-muted-foreground',\n} as const;\n","import { Popover, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, cn, useI18n } from '@gntik-ai/ui';\nimport { ExternalLink, Globe } from 'lucide-react';\nimport { useId, type ReactNode } from 'react';\nimport { citationStyles as s } from './citation.variants';\n\nexport interface CitationSource {\n /** Source title. */\n title: string;\n /** Where it lives; shown as its host name and linked. */\n url?: string;\n /** Short excerpt that supports the claim. */\n snippet?: string;\n /** Publisher or site name; defaults to the URL host. */\n publisher?: string;\n}\n\n/** Host name of a URL (\"docs.example.com\"), or undefined if it cannot be parsed. */\nexport function sourceHost(url?: string) {\n if (!url) return undefined;\n try {\n return new URL(url).host.replace(/^www\\./, '');\n } catch {\n return undefined;\n }\n}\n\n/** Only http(s) sources become links. */\nexport function safeSourceUrl(url?: string) {\n return url && /^https?:\\/\\//i.test(url) ? url : undefined;\n}\n\nexport interface CitationProps {\n /** 1-based number shown in the marker. */\n index: number;\n source: CitationSource;\n /** Hover delay before the preview opens (keyboard and click open it immediately). */\n delay?: number;\n className?: string;\n}\n\n/**\n * Inline numbered reference ([1]). Hovering, focusing + Enter or clicking opens a preview\n * card with the title, host, snippet and a link to the source.\n */\nexport function Citation({ index, source, delay = 200, className }: CitationProps) {\n const { t } = useI18n();\n const host = source.publisher ?? sourceHost(source.url);\n const href = safeSourceUrl(source.url);\n return (\n <Popover>\n <PopoverTrigger\n openOnHover\n delay={delay}\n aria-label={t('chat.source', { index, title: source.title })}\n className={cn(s.trigger, className)}\n >\n {index}\n </PopoverTrigger>\n <PopoverContent side=\"top\" align=\"start\" className={s.popup}>\n <div className={s.head}>\n <span className={s.index}>{index}</span>\n <Globe size={12} aria-hidden />\n {host && <span className=\"truncate\">{host}</span>}\n </div>\n <PopoverTitle className={s.title}>{source.title}</PopoverTitle>\n {source.snippet && <PopoverDescription className={s.snippet}>{source.snippet}</PopoverDescription>}\n {href && (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer nofollow\" className={s.open}>\n {t('chat.openSource')}\n <ExternalLink size={12} aria-hidden />\n <span className=\"sr-only\"> {t('link.external')}</span>\n </a>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n\nexport interface CitationListProps {\n sources: CitationSource[];\n /** Visible heading; also the list's accessible name. */\n heading?: ReactNode;\n className?: string;\n}\n\n/** Numbered list of the sources cited in a reply, matching the inline markers. */\nexport function CitationList({ sources, heading: headingProp, className }: CitationListProps) {\n const { t } = useI18n();\n const heading = headingProp ?? t('chat.sources');\n const headingId = useId();\n if (sources.length === 0) return null;\n return (\n <section aria-labelledby={headingId} className={className}>\n <h3 id={headingId} className={s.heading}>\n {heading}\n </h3>\n <ol className={s.list}>\n {sources.map((src, i) => {\n const href = safeSourceUrl(src.url);\n const host = src.publisher ?? sourceHost(src.url);\n return (\n <li key={`${i}-${src.title}`} className={s.item}>\n <span className={s.index} aria-hidden>\n {i + 1}\n </span>\n <div className={s.itemBody}>\n {href ? (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer nofollow\" className={s.itemTitle}>\n {src.title}\n <span className=\"sr-only\"> {t('link.external')}</span>\n </a>\n ) : (\n <span className=\"text-[13px] font-medium text-foreground\">{src.title}</span>\n )}\n {host && <div className={s.itemHost}>{host}</div>}\n </div>\n </li>\n );\n })}\n </ol>\n </section>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'Citation',\n group: 'Display',\n status: 'beta',\n description:\n 'Numbered source references for grounded answers: an inline [n] marker that previews the source (title, host, snippet, link) on hover, focus + Enter or click, and CitationList, the numbered list of sources under a reply. Only http(s) URLs become links.',\n primitive: '@base-ui/react/popover',\n pattern: 'dialog (non-modal)',\n keyboard: [\n ['Enter', 'On a marker: opens the source preview'],\n ['Space', 'On a marker: opens the source preview'],\n ['Escape', 'Closes the preview and returns focus to the marker'],\n ['Tab', 'Moves to the \"Open source\" link inside an open preview'],\n ],\n tokens: ['primary', 'primary-text', 'popover', 'secondary', 'card', 'border', 'muted-foreground', 'focus-ring'],\n};\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'Markdown',\n group: 'Display',\n status: 'beta',\n description:\n 'Safe, token-styled markdown for model output (react-markdown + remark-gfm): headings, lists, task lists, tables, blockquotes, inline and fenced code with a copy button, links with an external marker. Raw HTML is never rendered, unsafe URL schemes are stripped, and partial streamed input (unclosed fences) renders cleanly.',\n keyboard: [\n ['Tab', 'Moves through links and code-block copy buttons in reading order'],\n ['Enter', 'Follows a link or copies the focused code block'],\n ],\n tokens: ['foreground', 'muted-foreground', 'primary-text', 'secondary', 'border', 'focus-ring'],\n};\n","import { focusRing } from '../utils/focus';\n\n/** Slot classes for SuggestionChips. */\nexport const suggestionChipsStyles = {\n root: 'w-full',\n heading: 'mb-2.5 text-[12px] font-semibold tracking-wide text-muted-foreground uppercase',\n grid: 'grid gap-2 sm:grid-cols-2',\n row: 'flex flex-wrap gap-2',\n card: [\n 'group flex w-full cursor-pointer items-start gap-2.5 rounded-lg border border-border bg-card px-3.5 py-3 text-start shadow-sm',\n 'transition-colors hover:border-primary/40 hover:bg-secondary/40 motion-reduce:transition-none',\n 'disabled:pointer-events-none disabled:opacity-50',\n focusRing,\n ].join(' '),\n chip: [\n 'inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-full border border-border bg-card px-3 text-[12.5px] font-medium text-foreground',\n 'transition-colors hover:border-primary/40 hover:bg-secondary/40 motion-reduce:transition-none',\n 'disabled:pointer-events-none disabled:opacity-50',\n focusRing,\n ].join(' '),\n icon: 'mt-0.5 shrink-0 text-muted-foreground group-hover:text-primary-text',\n label: 'block text-[13px] font-medium text-foreground',\n description: 'mt-0.5 block text-[12px] leading-5 text-muted-foreground',\n} as const;\n","import { cn, useI18n } from '@gntik-ai/ui';\nimport { useId, type ComponentType, type ReactNode } from 'react';\nimport { suggestionChipsStyles as s } from './suggestionChips.variants';\n\ntype IconComponent = ComponentType<{ size?: number; className?: string; 'aria-hidden'?: boolean }>;\n\nexport interface Suggestion {\n /** Stable key; defaults to the label. */\n id?: string;\n /** Short title shown on the chip. */\n label: string;\n /** Second line (card layout only). */\n description?: string;\n /** Prompt sent when chosen; defaults to the label. */\n prompt?: string;\n icon?: IconComponent;\n}\n\nexport interface SuggestionChipsProps {\n suggestions: ReadonlyArray<Suggestion | string>;\n onSelect: (prompt: string, suggestion: Suggestion) => void;\n /** `cards` (two-column grid with descriptions) for an empty thread, `chips` (pills) for follow-ups. */\n layout?: 'cards' | 'chips';\n /** Heading above the group; also its accessible name. */\n heading?: ReactNode;\n /** Accessible name when there is no visible heading. */\n label?: string;\n disabled?: boolean;\n className?: string;\n}\n\nconst normalize = (x: Suggestion | string): Suggestion => (typeof x === 'string' ? { label: x } : x);\n\n/** Prompt suggestions for an empty conversation (cards) or as follow-ups after a reply (chips). */\nexport function SuggestionChips({\n suggestions,\n onSelect,\n layout = 'cards',\n heading,\n label: labelProp,\n disabled = false,\n className,\n}: SuggestionChipsProps) {\n const { t } = useI18n();\n const label = labelProp ?? t('chat.suggestions');\n const headingId = useId();\n const items = suggestions.map(normalize);\n return (\n <div\n role=\"group\"\n aria-labelledby={heading ? headingId : undefined}\n aria-label={heading ? undefined : label}\n className={cn(s.root, className)}\n >\n {heading && (\n <div id={headingId} className={s.heading}>\n {heading}\n </div>\n )}\n <div className={layout === 'cards' ? s.grid : s.row}>\n {items.map((item) => {\n const Icon = item.icon;\n const prompt = item.prompt ?? item.label;\n return (\n <button\n key={item.id ?? item.label}\n type=\"button\"\n disabled={disabled}\n className={layout === 'cards' ? s.card : s.chip}\n onClick={() => onSelect(prompt, item)}\n >\n {Icon && (\n <Icon\n size={layout === 'cards' ? 16 : 14}\n aria-hidden\n className={layout === 'cards' ? s.icon : 'shrink-0 text-muted-foreground'}\n />\n )}\n {layout === 'cards' ? (\n <span className=\"min-w-0\">\n <span className={s.label}>{item.label}</span>\n {item.description && <span className={s.description}>{item.description}</span>}\n </span>\n ) : (\n item.label\n )}\n </button>\n );\n })}\n </div>\n </div>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'SuggestionChips',\n group: 'Actions',\n status: 'beta',\n description:\n 'Prompt suggestions: a two-column grid of cards with descriptions for an empty conversation, or a row of pills for follow-ups after a reply. Choosing one calls onSelect with its prompt.',\n pattern: 'button group',\n keyboard: [\n ['Tab', 'Moves between suggestions'],\n ['Enter', 'Sends the focused suggestion'],\n ['Space', 'Sends the focused suggestion'],\n ],\n tokens: ['card', 'border', 'primary', 'primary-text', 'secondary', 'muted-foreground', 'focus-ring'],\n};\n","/** Slot classes for ToolCallCard and JsonView. */\nexport const toolCallCardStyles = {\n root: 'w-full overflow-hidden rounded-lg border border-border bg-card text-[13px]',\n trigger: [\n 'flex h-auto w-full min-w-0 justify-start gap-2.5 rounded-none px-3 py-2.5 text-start hover:bg-secondary/50',\n 'focus-visible:-outline-offset-2',\n ].join(' '),\n icon: 'grid size-6 shrink-0 place-items-center rounded-md bg-secondary text-muted-foreground',\n iconFailed: 'bg-destructive/15 text-destructive-chip-text',\n label: 'flex min-w-0 flex-1 items-baseline gap-1.5',\n verb: 'shrink-0 text-muted-foreground',\n name: 'truncate font-mono text-[12.5px] font-semibold text-foreground',\n meta: 'flex shrink-0 items-center gap-2',\n duration: 'font-mono text-[11px] text-muted-foreground tabular-nums',\n body: 'flex flex-col gap-2 border-t border-border px-3 pb-3 pt-1',\n error: 'rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-[12.5px] text-destructive-chip-text',\n json: {\n trigger: 'mx-0 h-7 px-1 text-[11.5px] font-semibold tracking-wide text-muted-foreground uppercase',\n content: 'pt-1',\n pre: 'max-h-64 overflow-auto rounded-md border border-border bg-secondary/40 p-2.5 font-mono text-[12px] leading-5 text-foreground',\n },\n} as const;\n","import { Collapsible, CollapsiblePanel, CollapsibleTrigger } from '@gntik-ai/ui';\nimport { toJson } from '../utils/format';\nimport { toolCallCardStyles } from './toolCallCard.variants';\n\nconst s = toolCallCardStyles.json;\n\nexport interface JsonViewProps {\n /** Section title (\"Arguments\", \"Result\"). */\n label: string;\n /** Any value: objects are pretty-printed, strings shown as-is. */\n value: unknown;\n defaultOpen?: boolean;\n}\n\n/** A small collapsible, scrollable JSON block. */\nexport function JsonView({ label, value, defaultOpen = true }: JsonViewProps) {\n return (\n <Collapsible defaultOpen={defaultOpen}>\n <CollapsibleTrigger className={s.trigger}>{label}</CollapsibleTrigger>\n <CollapsiblePanel className={s.content}>\n <pre tabIndex={0} aria-label={label} className={s.pre}>\n <code>{toJson(value)}</code>\n </pre>\n </CollapsiblePanel>\n </Collapsible>\n );\n}\n","import {\n Collapsible,\n CollapsiblePanel,\n CollapsibleTrigger,\n Spinner,\n StatusTag,\n cn,\n useI18n,\n type MessageKey,\n} from '@gntik-ai/ui';\nimport { CircleAlert, Wrench } from 'lucide-react';\nimport type { Ref } from 'react';\nimport { formatDuration } from '../utils/format';\nimport { JsonView } from './JsonView';\nimport { toolCallCardStyles as s } from './toolCallCard.variants';\n\nexport type ToolCallStatus = 'running' | 'succeeded' | 'failed';\n\nexport interface ToolCallCardProps {\n /** Tool / function name, e.g. \"search_invoices\". */\n name: string;\n status: ToolCallStatus;\n /** Elapsed time in ms. */\n durationMs?: number;\n /** Arguments the model passed. */\n args?: unknown;\n /** What the tool returned. */\n result?: unknown;\n /** Error message for a failed call. */\n error?: string;\n /** Start expanded. Failed calls open by default. */\n defaultOpen?: boolean;\n /** Controlled open state. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n}\n\nconst VERB: Record<ToolCallStatus, MessageKey> = {\n running: 'toolCall.calling',\n succeeded: 'toolCall.called',\n failed: 'toolCall.failed',\n};\n\n/**\n * A tool invocation inside an assistant turn: name, status, duration, and a collapsible body\n * with the arguments and the result (or error) as small JSON views.\n */\nexport function ToolCallCard({\n name,\n status,\n durationMs,\n args,\n result,\n error,\n defaultOpen,\n open,\n onOpenChange,\n className,\n ref,\n}: ToolCallCardProps) {\n const { t } = useI18n();\n const failed = status === 'failed';\n return (\n <Collapsible\n ref={ref}\n defaultOpen={defaultOpen ?? failed}\n open={open}\n onOpenChange={onOpenChange ? (o) => onOpenChange(o) : undefined}\n data-status={status}\n className={cn(s.root, className)}\n >\n <CollapsibleTrigger className={s.trigger}>\n <span className={cn(s.icon, failed && s.iconFailed)}>\n {status === 'running' ? (\n <Spinner size={13} />\n ) : failed ? (\n <CircleAlert size={13} aria-hidden />\n ) : (\n <Wrench size={13} aria-hidden />\n )}\n </span>\n <span className={s.label}>\n <span className={s.verb}>{t(VERB[status])}</span>\n <span className={s.name}>{name}</span>\n </span>\n <span className={s.meta}>\n {durationMs !== undefined && <span className={s.duration}>{formatDuration(durationMs)}</span>}\n <StatusTag status={status} size=\"sm\" />\n </span>\n </CollapsibleTrigger>\n <CollapsiblePanel className=\"pt-0\">\n <div className={s.body}>\n {args !== undefined && <JsonView label={t('toolCall.arguments')} value={args} />}\n {failed && error && (\n <p role=\"alert\" className={s.error}>\n {error}\n </p>\n )}\n {result !== undefined && <JsonView label={t('toolCall.result')} value={result} />}\n {status === 'running' && result === undefined && (\n <p className=\"text-[12.5px] text-muted-foreground\">{t('toolCall.waiting')}</p>\n )}\n </div>\n </CollapsiblePanel>\n </Collapsible>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'ToolCallCard',\n group: 'Display',\n status: 'beta',\n description:\n 'A tool invocation in an assistant turn: name, status (running, succeeded, failed), duration and a collapsible body with the arguments and the result or error as small collapsible JSON views. Failed calls open by default.',\n primitive: '@base-ui/react/collapsible',\n pattern: 'disclosure',\n keyboard: [\n ['Enter', 'Expands or collapses the card (or a JSON section)'],\n ['Space', 'Expands or collapses the card (or a JSON section)'],\n ['Tab', 'Moves to the JSON sections and their scrollable code'],\n ],\n tokens: [\n 'card',\n 'border',\n 'secondary',\n 'muted-foreground',\n 'success-text',\n 'destructive',\n 'destructive-text',\n 'focus-ring',\n ],\n};\n","import type { CitationSource } from '../Citation';\nimport type { Suggestion } from '../SuggestionChips';\n\n/** Fixtures for ChatDemo: generic workspace data, no product names. */\nexport const DEMO_SUGGESTIONS: Suggestion[] = [\n { label: 'Summarise deployments', description: 'What shipped this week across projects' },\n { label: 'Find unpaid invoices', description: 'Invoices still open from last month' },\n { label: 'Review member access', description: 'Who has admin rights' },\n { label: 'Explain a failed build', description: 'Likely cause and a fix' },\n];\n\nexport const DEMO_SOURCES: CitationSource[] = [\n {\n title: 'Deployment history · web-app',\n url: 'https://app.example.com/projects/web-app/deployments',\n snippet: '12 deployments in the last 7 days, 1 rolled back.',\n },\n {\n title: 'Rollback guide',\n url: 'https://docs.example.com/deployments/rollback',\n snippet: 'Roll back from the Deployments page or with the CLI.',\n },\n];\n\nexport const DEMO_TOOL = {\n name: 'list_deployments',\n args: { project: 'web-app', since: '7d' },\n result: { count: 12, succeeded: 11, rolledBack: 1, latest: 'v2.14.0' },\n durationMs: 640,\n};\n\nexport const DEMO_REPLY = `Here is the summary for **web-app** over the last 7 days:\n\n| Status | Count |\n| --- | --- |\n| Succeeded | 11 |\n| Rolled back | 1 |\n\nThe rollback was \\`v2.13.2\\`: a health check failed in one region, so traffic went back to the previous build.\n\nTo pin a release from the CLI:\n\n\\`\\`\\`bash\ndeploy pin --project web-app --version v2.14.0\n\\`\\`\\`\n\nSee the [rollback guide](https://docs.example.com/deployments/rollback) for the full steps.`;\n\n/** Splits text into small chunks to imitate token streaming. */\nexport function chunk(text: string, size = 6): string[] {\n const out: string[] = [];\n for (let i = 0; i < text.length; i += size) out.push(text.slice(i, i + size));\n return out;\n}\n","import { TooltipProvider, cn } from '@gntik-ai/ui';\nimport { useEffect, useRef, useState } from 'react';\nimport { AttachmentList, type ChatAttachment } from '../Attachment';\nimport { ChatAnnouncer, ChatMessage, type ChatRole } from '../ChatMessage';\nimport { ChatComposer } from '../ChatComposer';\nimport { MessageFeedback, type FeedbackValue } from '../MessageFeedback';\nimport { DEMO_MODELS, ModelPicker } from '../ModelPicker';\nimport { ChatLayout } from '../ChatLayout';\nimport { CitationList } from '../Citation';\nimport { Markdown } from '../Markdown';\nimport { SuggestionChips } from '../SuggestionChips';\nimport { ToolCallCard, type ToolCallStatus } from '../ToolCallCard';\nimport { DEMO_REPLY, DEMO_SOURCES, DEMO_SUGGESTIONS, DEMO_TOOL, chunk } from './demoScript';\n\ninterface DemoMessage {\n id: number;\n role: ChatRole;\n text: string;\n time: Date;\n streaming?: boolean;\n tool?: { status: ToolCallStatus; durationMs?: number };\n sources?: boolean;\n feedback?: FeedbackValue;\n attachments?: ChatAttachment[];\n}\n\nexport interface ChatDemoProps {\n /** Show the resizable details panel. */\n withPanel?: boolean;\n /** Milliseconds between streamed chunks. */\n tickMs?: number;\n className?: string;\n}\n\n/**\n * End-to-end example: suggestions, a user turn with attachments, a tool call, a streamed\n * markdown reply with sources, Stop, Regenerate and feedback, and a compact model picker. Streaming is mocked with timers that are cleared on\n * Stop and on unmount.\n */\nexport function ChatDemo({ withPanel = true, tickMs = 30, className }: ChatDemoProps) {\n const [messages, setMessages] = useState<DemoMessage[]>([]);\n const [streaming, setStreaming] = useState(false);\n const [model, setModel] = useState<string | null>('balanced');\n const [files, setFiles] = useState<ChatAttachment[]>([]);\n const nextId = useRef(1);\n const timers = useRef<Array<ReturnType<typeof setTimeout>>>([]);\n const objectUrls = useRef<string[]>([]);\n\n const clearTimers = () => {\n timers.current.forEach((t) => clearTimeout(t));\n timers.current = [];\n };\n useEffect(\n () => () => {\n clearTimers();\n objectUrls.current.forEach((u) => URL.revokeObjectURL(u));\n },\n [],\n );\n\n const attach = (picked: File[]) => {\n const added = picked.map((f): ChatAttachment => {\n let previewUrl: string | undefined;\n if (f.type.startsWith('image/') && typeof URL.createObjectURL === 'function') {\n previewUrl = URL.createObjectURL(f);\n objectUrls.current.push(previewUrl);\n }\n return { id: `file-${nextId.current++}`, name: f.name, size: f.size, type: f.type, previewUrl };\n });\n setFiles((all) => [...all, ...added]);\n };\n\n const patch = (id: number, fn: (m: DemoMessage) => DemoMessage) =>\n setMessages((ms) => ms.map((m) => (m.id === id ? fn(m) : m)));\n\n const respond = () => {\n clearTimers();\n const toolId = nextId.current++;\n const replyId = nextId.current++;\n const now = new Date();\n setStreaming(true);\n setMessages((ms) => [\n ...ms,\n { id: toolId, role: 'tool', text: '', time: now, tool: { status: 'running' } },\n { id: replyId, role: 'assistant', text: '', time: now, streaming: true },\n ]);\n const pieces = chunk(DEMO_REPLY);\n const startAt = DEMO_TOOL.durationMs;\n timers.current.push(\n setTimeout(\n () => patch(toolId, (m) => ({ ...m, tool: { status: 'succeeded', durationMs: DEMO_TOOL.durationMs } })),\n startAt,\n ),\n );\n pieces.forEach((piece, i) => {\n timers.current.push(\n setTimeout(() => patch(replyId, (m) => ({ ...m, text: m.text + piece })), startAt + (i + 1) * tickMs),\n );\n });\n timers.current.push(\n setTimeout(\n () => {\n patch(replyId, (m) => ({ ...m, streaming: false, sources: true }));\n setStreaming(false);\n },\n startAt + (pieces.length + 1) * tickMs,\n ),\n );\n };\n\n const send = (text: string, attachments: ChatAttachment[] = []) => {\n setMessages((ms) => [...ms, { id: nextId.current++, role: 'user', text, time: new Date(), attachments }]);\n setFiles([]);\n respond();\n };\n\n const stop = () => {\n clearTimers();\n setMessages((ms) =>\n ms.map((m) =>\n m.streaming\n ? { ...m, streaming: false }\n : m.tool?.status === 'running'\n ? { ...m, tool: { status: 'failed', durationMs: 0 } }\n : m,\n ),\n );\n setStreaming(false);\n };\n\n const retry = (id: number) => {\n setMessages((ms) => {\n const at = ms.findIndex((m) => m.id === id);\n // Drop the reply and the tool call that preceded it.\n const cut = at > 0 && ms[at - 1]?.role === 'tool' ? at - 1 : at;\n return ms.slice(0, cut);\n });\n respond();\n };\n\n const lastReply = [...messages].reverse().find((m) => m.role === 'assistant' && !m.streaming)?.text;\n\n return (\n <TooltipProvider>\n <div className={cn('h-[640px] overflow-hidden rounded-xl border border-border', className)}>\n <ChatLayout\n header={<div className=\"px-4 py-3 text-[13px] font-semibold text-foreground\">New conversation</div>}\n panel={\n withPanel ? (\n <div className=\"flex flex-col gap-4 p-4 text-[13px]\">\n <div>\n <h2 className=\"font-semibold text-foreground\">Details</h2>\n <p className=\"mt-1 text-muted-foreground\">\n Workspace assistant with read access to projects, deployments and invoices.\n </p>\n </div>\n <CitationList sources={DEMO_SOURCES} heading=\"Context sources\" />\n </div>\n ) : undefined\n }\n composer={\n <ChatComposer\n onSubmit={send}\n streaming={streaming}\n onStop={stop}\n maxLength={4000}\n attachments={files}\n onAttach={attach}\n onRemoveAttachment={(id) => setFiles((all) => all.filter((f) => f.id !== id))}\n accept=\".pdf,.csv,.md,.txt,.json,image/*\"\n maxSize={10 * 1024 * 1024}\n maxFiles={5}\n modelPicker={<ModelPicker compact models={DEMO_MODELS} value={model} onValueChange={setModel} />}\n />\n }\n >\n {messages.length === 0 && (\n <div className=\"flex flex-col gap-5 pt-10\">\n <h2 className=\"text-center text-[20px] font-semibold tracking-tight text-foreground\">How can I help?</h2>\n <SuggestionChips suggestions={DEMO_SUGGESTIONS} onSelect={(text) => send(text)} />\n </div>\n )}\n {messages.map((m) => {\n if (m.role === 'tool' && m.tool) {\n return (\n <ChatMessage key={m.id} role=\"tool\" author=\"Tool\" timestamp={m.time}>\n <ToolCallCard\n name={DEMO_TOOL.name}\n status={m.tool.status}\n durationMs={m.tool.durationMs}\n args={DEMO_TOOL.args}\n result={m.tool.status === 'succeeded' ? DEMO_TOOL.result : undefined}\n error={m.tool.status === 'failed' ? 'Stopped by the user.' : undefined}\n />\n </ChatMessage>\n );\n }\n if (m.role === 'assistant') {\n return (\n <ChatMessage\n key={m.id}\n role=\"assistant\"\n timestamp={m.time}\n streaming={m.streaming}\n alwaysShowActions={m.feedback?.rating === 'down'}\n actions={\n <MessageFeedback\n copyText={m.text}\n onRegenerate={streaming ? undefined : () => retry(m.id)}\n value={m.feedback ?? { rating: null }}\n onFeedback={(f) => patch(m.id, (x) => ({ ...x, feedback: f }))}\n />\n }\n >\n {m.text && <Markdown streaming={m.streaming}>{m.text}</Markdown>}\n {m.sources && <CitationList sources={DEMO_SOURCES} className=\"mt-3\" />}\n </ChatMessage>\n );\n }\n return (\n <ChatMessage key={m.id} role={m.role} timestamp={m.time}>\n {m.text}\n {m.attachments && m.attachments.length > 0 && (\n <AttachmentList attachments={m.attachments} variant=\"tile\" className=\"mt-2\" />\n )}\n </ChatMessage>\n );\n })}\n <ChatAnnouncer streaming={streaming} lastReply={lastReply} />\n </ChatLayout>\n </div>\n </TooltipProvider>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'ChatDemo',\n group: 'Layout',\n status: 'experimental',\n description:\n 'Reference composition of the chat pack: suggestions in the empty state, attachments (pick, paste or drop), a compact ModelPicker in the composer, a tool call, a streamed markdown reply with sources (TypingIndicator, caret), Stop, MessageFeedback (copy, regenerate, thumbs with reasons), and a resizable details panel. Streaming is mocked with timers that are cleaned up.',\n keyboard: [\n ['Enter', 'In the composer: sends; on a suggestion: sends it'],\n ['Escape', 'In the composer while streaming: stops the reply'],\n ],\n tokens: ['background', 'card', 'border', 'primary', 'focus-ring'],\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["s","s","s","s","doc","s","doc","s","doc","s","doc","s","doc","s","doc","s","doc","s","doc","doc","s","doc","s","doc","doc"],"sources":["../src/utils/i18n.ts","../src/AgentSurface/SurfaceFocusBoundary.tsx","../src/AgentSurface/pointer.ts","../src/AgentSurface/protocol.ts","../src/AgentSurface/stream.ts","../src/utils/useCopy.ts","../src/utils/focus.ts","../src/Markdown/markdown.variants.ts","../src/Markdown/CodeBlock.tsx","../src/Markdown/Markdown.tsx","../src/AgentSurface/model.ts","../src/AgentSurface/AgentSurface.tsx","../src/AgentSurface/catalog-components.tsx","../src/AgentSurface/catalog.ts","../src/AgentSurface/AgentSurface.doc.ts","../src/Attachment/attachment.variants.ts","../src/Attachment/AttachmentChip.tsx","../src/Attachment/AttachmentList.tsx","../src/Attachment/validateFiles.ts","../src/Attachment/Attachment.doc.ts","../src/ChatComposer/chatComposer.variants.ts","../src/ChatComposer/ChatComposer.tsx","../src/ChatComposer/ChatComposer.doc.ts","../src/TypingIndicator/typingIndicator.variants.ts","../src/TypingIndicator/TypingIndicator.tsx","../src/TypingIndicator/TypingIndicator.doc.ts","../src/utils/format.ts","../src/ChatMessage/chatMessage.variants.ts","../src/ChatMessage/ChatMessage.tsx","../src/ChatMessage/ChatAnnouncer.tsx","../src/ChatMessage/ChatMessage.doc.ts","../src/MessageFeedback/messageFeedback.variants.ts","../src/MessageFeedback/MessageFeedback.tsx","../src/MessageFeedback/MessageFeedback.doc.ts","../src/ModelPicker/modelPicker.variants.ts","../src/ModelPicker/ModelPicker.tsx","../src/ModelPicker/fixtures.ts","../src/ModelPicker/ModelPicker.doc.ts","../src/useChatScroll/useChatScroll.ts","../src/ChatLayout/chatLayout.variants.ts","../src/ChatLayout/ChatLayout.tsx","../src/ChatLayout/ChatLayout.doc.ts","../src/Citation/citation.variants.ts","../src/Citation/Citation.tsx","../src/Citation/Citation.doc.ts","../src/Markdown/Markdown.doc.ts","../src/SuggestionChips/suggestionChips.variants.ts","../src/SuggestionChips/SuggestionChips.tsx","../src/SuggestionChips/SuggestionChips.doc.ts","../src/ToolCallCard/toolCallCard.variants.ts","../src/ToolCallCard/JsonView.tsx","../src/ToolCallCard/ToolCallCard.tsx","../src/ToolCallCard/ToolCallCard.doc.ts","../src/ChatDemo/demoScript.ts","../src/ChatDemo/ChatDemo.tsx","../src/ChatDemo/ChatDemo.doc.ts"],"sourcesContent":["import { interpolate, useI18n, type MessageKey, type MessageVars } from '@gntik-ai/ui';\n\n/**\n * English fallbacks for the chat keys added after the first `@gntik-ai/ui` release. The\n * strings live in the ui catalogs (en + es); these keep the pack readable when it runs\n * against an older `@gntik-ai/ui` whose catalog does not have them yet.\n */\nconst FALLBACK = {\n 'chat.surfaceExampleTitle': 'Review your details',\n 'chat.surfaceExampleName': 'Name',\n 'chat.surfaceExampleSubmit': 'Submit',\n 'chat.surfaceExampleChoice': 'Language',\n 'chat.surfaceExampleEnglish': 'English',\n 'chat.surfaceExampleSpanish': 'Spanish',\n 'chat.surfaceExampleNotify': 'Send updates',\n 'chat.surfaceExampleBadge': 'Draft',\n 'chat.surfaceExampleNotice': 'Check the information before submitting.',\n 'chat.surfaceExampleStatus': 'Submitted for {name}',\n 'chat.surfaceExamplePatch': 'Update name',\n 'chat.surfaceExampleRemove': 'Remove content',\n 'chat.surfaceExampleReset': 'Reset',\n 'chat.surfaceExampleUnsupported': 'Show unsupported content',\n 'chat.surfaceExampleRejected': 'Unsupported content was rejected.',\n 'chat.surfaceExampleLink': 'Read the documentation',\n 'chat.surfaceUnsupported': 'This content cannot be shown',\n 'chat.surfaceAgentContent': 'Agent content',\n 'chat.typing': '{author} is typing',\n 'chat.feedback': 'Response feedback',\n 'chat.feedbackTitle': 'What went wrong?',\n 'chat.feedbackReason': 'Reason',\n 'chat.feedbackComment': 'Comment (optional)',\n 'chat.feedbackPlaceholder': 'Tell us more…',\n 'chat.feedbackSubmit': 'Send feedback',\n 'chat.feedbackThanks': 'Thanks for your feedback',\n 'chat.feedbackCleared': 'Feedback removed',\n 'chat.reasonInaccurate': 'Inaccurate',\n 'chat.reasonUnhelpful': 'Not helpful',\n 'chat.reasonIncomplete': 'Incomplete',\n 'chat.reasonUnsafe': 'Harmful or unsafe',\n 'chat.reasonOther': 'Other',\n 'chat.regenerate': 'Regenerate',\n 'chat.uploading': 'Uploading {name}',\n 'chat.uploadFailed': 'Upload failed',\n 'chat.retryUpload': 'Retry uploading {name}',\n 'chat.dropFiles': 'Drop files to attach',\n 'chat.fileTooLarge': '{name} is larger than {max}',\n 'chat.fileTypeNotAllowed': '{name} is not an allowed file type',\n 'chat.tooManyFiles': 'You can attach up to {max} files',\n 'chat.model': 'Model',\n 'chat.selectModel': 'Select a model',\n 'chat.capabilityVision': 'Vision',\n 'chat.capabilityTools': 'Tools',\n 'chat.capabilityReasoning': 'Reasoning',\n 'chat.capabilityFiles': 'Files',\n 'chat.capabilityWeb': 'Web search',\n 'chat.capabilityAudio': 'Audio',\n 'chat.contextWindow': '{size} context',\n 'chat.unavailable': 'Unavailable',\n} as const;\n\nexport type ChatMessageKey = keyof typeof FALLBACK;\n\n/** `useI18n()` plus `tc()`, a translator for the newer chat keys with English fallbacks. */\nexport function useChatI18n() {\n const i18n = useI18n();\n const tc = (key: ChatMessageKey, vars?: MessageVars) => {\n const out = i18n.t(key as MessageKey, vars);\n return out === key ? interpolate(FALLBACK[key], vars, i18n.locale) : out;\n };\n return { ...i18n, tc };\n}\n","import { Component, createRef, type ReactNode } from 'react';\n\nconst focusable = 'button, a[href], input, select, textarea, [tabindex], [contenteditable=\"true\"]';\nfunction candidates(element: Element): HTMLElement[] {\n return [element, ...element.querySelectorAll(focusable)].filter(\n (item): item is HTMLElement =>\n item instanceof HTMLElement &&\n item.matches(focusable) &&\n item.tabIndex >= 0 &&\n !item.matches(':disabled, [aria-disabled=\"true\"], input[type=\"hidden\"]') &&\n !item.closest('[hidden], [inert], [aria-hidden=\"true\"]') &&\n getComputedStyle(item).display !== 'none' &&\n getComputedStyle(item).visibility !== 'hidden',\n );\n}\ninterface Props {\n surfaceIds: ReadonlySet<string>;\n visible: boolean;\n label: string;\n children: ReactNode;\n}\ninterface FocusSnapshot {\n siblings: Element[];\n}\n\n/** Capture focus before React removes DOM; restore after all deleted surfaces are gone. */\nexport class SurfaceFocusBoundary extends Component<Props> {\n private host = createRef<HTMLDivElement>();\n\n getSnapshotBeforeUpdate(): FocusSnapshot | null {\n const host = this.host.current;\n const active = document.activeElement;\n if (!host || !(active instanceof HTMLElement)) return null;\n let frame = host.contains(active) ? active.closest<HTMLElement>('[data-agent-surface]') : null;\n // Base UI Select options live in a portal. aria-controls identifies their owning trigger.\n if (!frame) {\n for (const trigger of host.querySelectorAll('[aria-controls]')) {\n const ownsFocus = (trigger.getAttribute('aria-controls') ?? '')\n .split(/\\s+/)\n .some((id) => document.getElementById(id)?.contains(active));\n if (ownsFocus) {\n frame = trigger.closest<HTMLElement>('[data-agent-surface]');\n break;\n }\n }\n }\n if (!frame || this.props.surfaceIds.has(frame.dataset.agentSurface ?? '')) return null;\n const next: Element[] = [];\n // The next surface's controls, then the consumer's next focusable sibling.\n for (const start of [frame, host]) {\n let sibling = start.nextElementSibling;\n while (sibling) {\n next.push(sibling);\n sibling = sibling.nextElementSibling;\n }\n }\n return { siblings: next };\n }\n\n componentDidUpdate(_previous: Props, _state: unknown, snapshot: FocusSnapshot | null) {\n if (!snapshot) return;\n const restore = () => {\n // Resolve focusability after popup teardown has removed inert/aria-hidden markers.\n const next = snapshot.siblings.filter((element) => element.isConnected).flatMap(candidates);\n const composers = [...document.querySelectorAll('textarea')].flatMap(candidates);\n for (const target of [...next, ...composers, this.host.current]) {\n if (!target) continue;\n target.focus();\n if (document.activeElement === target) return;\n }\n };\n restore();\n queueMicrotask(() => {\n if (document.activeElement === document.body || document.activeElement === this.host.current) restore();\n });\n }\n\n render() {\n if (!this.props.visible) return null;\n return (\n <div\n ref={this.host}\n tabIndex={-1}\n role=\"group\"\n aria-label={this.props.label}\n className=\"space-y-3 outline-focus-ring\"\n >\n {this.props.children}\n </div>\n );\n }\n}\n","/** RFC 6901 paths. Throws on malformed paths rather than guessing a model key. */\nfunction segments(path: string): string[] {\n if (path === '') return [];\n if (!path.startsWith('/') || /~(?![01])/u.test(path)) throw new Error('Invalid JSON Pointer');\n const keys = path\n .slice(1)\n .split('/')\n .map((key) => key.replace(/~1/g, '/').replace(/~0/g, '~'));\n if (keys.length > 64 || keys.some((key) => ['__proto__', 'prototype', 'constructor'].includes(key))) {\n throw new Error('Unsafe JSON Pointer');\n }\n return keys;\n}\n\nfunction own(value: unknown, key: string): unknown {\n return value !== null && typeof value === 'object' && Object.hasOwn(value, key)\n ? (value as Record<string, unknown>)[key]\n : undefined;\n}\n\nexport function getPointer(model: unknown, path: string): unknown {\n return segments(path).reduce<unknown>(own, model);\n}\n\n/** Copy every ancestor; never mutate the model supplied by a consumer. */\nexport function setPointer(model: unknown, path: string, value: unknown): unknown {\n const keys = segments(path);\n function write(current: unknown, index: number): unknown {\n if (index === keys.length) return value;\n const key = keys[index]!;\n if (Array.isArray(current)) {\n if (!/^(0|[1-9]\\d*)$/.test(key) || Number(key) > current.length) throw new Error('Invalid array index');\n const copy: unknown[] = [...current];\n copy[Number(key)] = write(own(current, key), index + 1);\n return copy;\n }\n const copy: Record<string, unknown> = current && typeof current === 'object' ? { ...current } : {};\n copy[key] = write(own(current, key), index + 1);\n return copy;\n }\n return write(model, 0);\n}\n","/** Supported command envelope. No v0.8 adaptation is performed. */\nexport const A2UI_VERSION = 'v0.9' as const;\nexport interface AgentComponent {\n id: string;\n component: string;\n children?: string[];\n /** Catalog properties are flat, alongside id/component/children. */\n [property: string]: unknown;\n}\nexport interface AgentAction {\n name: string;\n surfaceId: string;\n context: Record<string, unknown>;\n}\nexport interface AgentSurfaceError {\n code: 'version' | 'message' | 'component' | 'props' | 'graph' | 'binding';\n surfaceId: string;\n componentId?: string;\n type?: string;\n}\ntype Envelope<T> = { version: typeof A2UI_VERSION } & T;\nexport type A2uiMessage =\n | Envelope<{ createSurface: { surfaceId: string; catalogId?: string } }>\n | Envelope<{ updateComponents: { surfaceId: string; components: AgentComponent[] } }>\n | Envelope<{ updateDataModel: { surfaceId: string; path?: string; value: unknown } }>\n | Envelope<{ deleteSurface: { surfaceId: string } }>;\n\nexport const MAX_COMPONENTS = 256;\nexport const MAX_DEPTH = 32;\nconst commands = ['createSurface', 'updateComponents', 'updateDataModel', 'deleteSurface'] as const;\nconst identifier = (value: unknown): value is string =>\n typeof value === 'string' && value.length > 0 && value.length <= 128;\nconst record = (value: unknown): value is Record<string, unknown> =>\n value !== null && typeof value === 'object' && !Array.isArray(value);\n\n/** JSON-only, bounded input. In particular, reject cyclic JS objects and prototype keys. */\nfunction validJson(value: unknown): boolean {\n let budget = 10000;\n const ancestors = new Set<object>();\n function visit(item: unknown, depth: number): boolean {\n if (--budget < 0 || depth > 64) return false;\n if (item === null || typeof item === 'boolean') return true;\n if (typeof item === 'number') return Number.isFinite(item);\n if (typeof item === 'string') return item.length <= 65536;\n if (typeof item !== 'object' || ancestors.has(item)) return false;\n if (!Array.isArray(item) && ![Object.prototype, null].includes(Object.getPrototypeOf(item))) return false;\n ancestors.add(item);\n const valid = Object.entries(item).every(\n ([key, child]) => !['__proto__', 'prototype', 'constructor'].includes(key) && visit(child, depth + 1),\n );\n ancestors.delete(item);\n return valid;\n }\n return visit(value, 0);\n}\n\nexport function parseMessage(input: unknown): { message: A2uiMessage } | { error: AgentSurfaceError } {\n const source = record(input) ? input : {};\n const declared = commands.filter((key) => Object.hasOwn(source, key));\n const command = declared[0];\n const payload = command && record(source[command]) ? source[command] : {};\n const surfaceId = identifier(payload.surfaceId) ? payload.surfaceId : '';\n const error = (code: AgentSurfaceError['code']) => ({ error: { code, surfaceId } });\n if (source.version !== A2UI_VERSION) return error('version');\n if (declared.length !== 1 || !surfaceId || !validJson(input)) return error('message');\n if (command === 'createSurface') {\n if (payload.catalogId !== undefined && !identifier(payload.catalogId)) return error('message');\n return {\n message: {\n version: A2UI_VERSION,\n createSurface: {\n surfaceId,\n ...(typeof payload.catalogId === 'string' ? { catalogId: payload.catalogId } : {}),\n },\n },\n };\n }\n if (command === 'deleteSurface') return { message: { version: A2UI_VERSION, deleteSurface: { surfaceId } } };\n if (command === 'updateDataModel') {\n if (!Object.hasOwn(payload, 'value') || (payload.path !== undefined && typeof payload.path !== 'string'))\n return error('message');\n return {\n message: {\n version: A2UI_VERSION,\n updateDataModel: {\n surfaceId,\n path: typeof payload.path === 'string' ? payload.path : '',\n value: payload.value,\n },\n },\n };\n }\n if (!Array.isArray(payload.components) || payload.components.length > MAX_COMPONENTS) return error('message');\n const nodes: AgentComponent[] = [];\n const ids = new Set<string>();\n for (const node of payload.components) {\n if (!record(node) || !identifier(node.id) || !identifier(node.component) || ids.has(node.id))\n return error('message');\n if (\n node.children !== undefined &&\n (!Array.isArray(node.children) || node.children.length > MAX_COMPONENTS || !node.children.every(identifier))\n )\n return error('message');\n ids.add(node.id);\n nodes.push(node as AgentComponent);\n }\n return { message: { version: A2UI_VERSION, updateComponents: { surfaceId, components: nodes } } };\n}\n\n/** Missing children are allowed while streaming; repeated parents, cycles and deep trees are not. */\nexport function validGraph(nodes: ReadonlyMap<string, AgentComponent>): boolean {\n if (nodes.size > MAX_COMPONENTS) return false;\n const parents = new Set<string>();\n for (const node of nodes.values()) {\n for (const child of node.children ?? []) {\n if (parents.has(child)) return false;\n parents.add(child);\n }\n }\n const visiting = new Set<string>();\n function visit(id: string, depth: number): boolean {\n if (depth > MAX_DEPTH || visiting.has(id)) return false;\n visiting.add(id);\n const valid = (nodes.get(id)?.children ?? []).every((child) => visit(child, depth + 1));\n visiting.delete(id);\n return valid;\n }\n return [...nodes.keys()].every((id) => visit(id, 0));\n}\n","import { setPointer } from './pointer';\nimport { parseMessage, validGraph, type A2uiMessage, type AgentComponent, type AgentSurfaceError } from './protocol';\n\nexport interface SurfaceState {\n nodes: Map<string, AgentComponent>;\n model: unknown;\n invalid?: boolean;\n}\nexport interface StreamState {\n messages: A2uiMessage[];\n surfaces: Map<string, SurfaceState>;\n deleted: boolean;\n blocked: Set<string>;\n errors: AgentSurfaceError[];\n}\nexport const emptyStream = (): StreamState => ({\n messages: [],\n deleted: false,\n surfaces: new Map(),\n blocked: new Set(),\n errors: [],\n});\n\nexport function consume(previous: StreamState, messages: A2uiMessage[]): StreamState {\n const append = previous.messages.every((message, index) => messages[index] === message);\n const base = append ? previous : emptyStream();\n const state = {\n messages,\n deleted: base.deleted,\n surfaces: new Map(base.surfaces),\n blocked: new Set(base.blocked),\n errors: [...base.errors],\n };\n for (const input of messages.slice(base.messages.length)) {\n const parsed = parseMessage(input);\n if ('error' in parsed) {\n if (parsed.error.code === 'version') {\n state.blocked.add(parsed.error.surfaceId);\n state.surfaces.delete(parsed.error.surfaceId);\n // Keep the focus fallback mounted only if this surface was previously rendered.\n if (previous.surfaces.has(parsed.error.surfaceId)) state.deleted = true;\n }\n state.errors.push(parsed.error);\n continue;\n }\n const message = parsed.message;\n const payload =\n 'createSurface' in message\n ? message.createSurface\n : 'updateComponents' in message\n ? message.updateComponents\n : 'updateDataModel' in message\n ? message.updateDataModel\n : message.deleteSurface;\n const { surfaceId } = payload;\n if (state.blocked.has(surfaceId)) continue;\n if ('createSurface' in message) {\n if (!state.surfaces.has(surfaceId)) {\n if (state.surfaces.size >= 32) state.errors.push({ code: 'message', surfaceId });\n else state.surfaces.set(surfaceId, { nodes: new Map(), model: {} });\n }\n continue;\n }\n const surface = state.surfaces.get(surfaceId);\n if (!surface) {\n state.errors.push({ code: 'message', surfaceId });\n continue;\n }\n if ('updateComponents' in message) {\n const nodes = new Map(surface.nodes);\n for (const node of message.updateComponents.components) {\n const old = nodes.get(node.id);\n nodes.set(node.id, { ...(old?.component === node.component ? old : {}), ...node });\n }\n const invalid = !validGraph(nodes);\n if (invalid) state.errors.push({ code: 'graph', surfaceId });\n state.surfaces.set(surfaceId, { ...surface, nodes: invalid ? surface.nodes : nodes, invalid });\n }\n if ('updateDataModel' in message) {\n try {\n const { path = '', value } = message.updateDataModel;\n state.surfaces.set(surfaceId, { ...surface, model: setPointer(surface.model, path, value) });\n } catch {\n state.errors.push({ code: 'binding', surfaceId });\n }\n }\n if ('deleteSurface' in message) {\n state.surfaces.delete(surfaceId);\n state.deleted = true;\n }\n }\n // An unsupported version suppresses all rendering and other diagnostics for that surface.\n state.errors = state.errors.filter((error) => !state.blocked.has(error.surfaceId) || error.code === 'version');\n return state;\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\n/**\n * Copies text to the clipboard and exposes a short-lived `copied` flag for the button label.\n * The reset timer is cleared on unmount and on every new copy.\n */\nexport function useCopy(resetMs = 1600) {\n const [copied, setCopied] = useState(false);\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n useEffect(() => () => clearTimeout(timer.current), []);\n\n const copy = useCallback(\n async (text: string) => {\n try {\n await navigator.clipboard?.writeText(text);\n } catch {\n // Clipboard can be denied (insecure context, permissions); the flag still gives feedback.\n }\n setCopied(true);\n clearTimeout(timer.current);\n timer.current = setTimeout(() => setCopied(false), resetMs);\n },\n [resetMs],\n );\n\n return { copied, copy };\n}\n","/** Focus ring shared by every interactive element in the pack (brand rule). */\nexport const focusRing = 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring';\n","import { focusRing } from '../utils/focus';\n\n/**\n * Blinking caret drawn after the last block while text streams in. Pure CSS (an ::after on the\n * last child), so it follows paragraphs, list items and code without extra DOM.\n */\nexport const streamingCaretClass = [\n '[&>:last-child]:after:ms-0.5 [&>:last-child]:after:inline-block [&>:last-child]:after:h-[1.05em] [&>:last-child]:after:w-[2px]',\n \"[&>:last-child]:after:translate-y-[2px] [&>:last-child]:after:bg-primary [&>:last-child]:after:content-['']\",\n '[&>:last-child]:after:animate-pulse motion-reduce:[&>:last-child]:after:animate-none',\n].join(' ');\n\n/** Element classes for Markdown (token colours only). */\nexport const markdownStyles = {\n root: 'min-w-0 text-[14px] leading-[1.7] text-foreground [overflow-wrap:anywhere] [&>:first-child]:mt-0 [&>:last-child]:mb-0',\n h1: 'mt-5 mb-2 text-[18px] font-semibold tracking-tight',\n h2: 'mt-5 mb-2 text-[16px] font-semibold tracking-tight',\n h3: 'mt-4 mb-1.5 text-[14.5px] font-semibold',\n h4: 'mt-4 mb-1.5 text-[13.5px] font-semibold text-muted-foreground',\n p: 'my-2.5',\n ul: 'my-2.5 list-disc space-y-1 ps-5 marker:text-muted-foreground',\n ol: 'my-2.5 list-decimal space-y-1 ps-5 marker:text-muted-foreground',\n li: 'ps-1 [&>ul]:my-1 [&>ol]:my-1 [&.task-list-item]:list-none [&.task-list-item]:-ms-5',\n blockquote: 'my-3 border-s-2 border-primary/50 ps-3.5 text-muted-foreground',\n hr: 'my-5 border-border',\n link: `rounded-sm font-medium text-primary-text underline decoration-primary/40 underline-offset-2 hover:decoration-primary ${focusRing}`,\n linkIcon: 'ms-0.5 inline-block align-[-1px]',\n inlineCode: 'rounded-md border border-border bg-secondary/60 px-1.5 py-px font-mono text-[12.5px]',\n tableWrap: 'my-3 overflow-x-auto rounded-lg border border-border',\n table: 'w-full border-collapse text-start text-[13px]',\n th: 'border-b border-border bg-secondary/50 px-3 py-2 font-semibold',\n td: 'border-b border-border px-3 py-2 align-top [tr:last-child_&]:border-b-0',\n checkbox: 'me-1.5 align-[-2px] accent-primary',\n image: 'text-muted-foreground italic',\n code: {\n root: 'my-3 overflow-hidden rounded-lg border border-border bg-secondary/40',\n header: 'flex h-9 items-center justify-between border-b border-border bg-secondary/50 ps-3 pe-1.5',\n lang: 'font-mono text-[11px] tracking-wide text-muted-foreground uppercase',\n pre: 'overflow-x-auto p-3 font-mono text-[12.5px] leading-6',\n },\n} as const;\n","import { Button, useI18n } from '@gntik-ai/ui';\nimport { Check, Copy } from 'lucide-react';\nimport { useCopy } from '../utils/useCopy';\nimport { markdownStyles } from './markdown.variants';\n\nconst s = markdownStyles.code;\n\nexport interface CodeBlockProps {\n /** Source text. */\n code: string;\n /** Language tag from the fence (```ts). */\n language?: string;\n className?: string;\n}\n\n/** Fenced code with a language label and a copy button. */\nexport function CodeBlock({ code, language, className }: CodeBlockProps) {\n const { copied, copy } = useCopy();\n const { t } = useI18n();\n return (\n <div className={className ? `${s.root} ${className}` : s.root} data-language={language}>\n <div className={s.header}>\n <span className={s.lang}>{language || 'text'}</span>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n icon={copied ? Check : Copy}\n aria-label={copied ? t('chat.copiedCode') : t('chat.copyCode')}\n className=\"h-7 px-2\"\n onClick={() => void copy(code)}\n >\n {copied ? t('common.copied') : t('common.copy')}\n </Button>\n </div>\n <pre className={s.pre}>\n <code>{code}</code>\n </pre>\n </div>\n );\n}\n","import { cn, useI18n } from '@gntik-ai/ui';\nimport { ExternalLink } from 'lucide-react';\nimport { Children, isValidElement, memo, type ReactNode } from 'react';\nimport ReactMarkdown, { defaultUrlTransform, type Components } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { CodeBlock } from './CodeBlock';\nimport { markdownStyles as s, streamingCaretClass } from './markdown.variants';\n\nexport interface MarkdownProps {\n /** Markdown source (GitHub-flavoured: tables, task lists, strikethrough, autolinks). */\n children: string;\n /** Text is still arriving: closes a dangling code fence and draws the caret. */\n streaming?: boolean;\n className?: string;\n}\n\nconst SAFE_PROTOCOL = /^(https?|mailto|tel):/i;\n\n/**\n * URL policy: relative URLs, anchors and http(s)/mailto/tel only. Everything else\n * (javascript:, data:, vbscript:, …) is dropped, on top of react-markdown's own transform.\n */\nexport function safeUrl(url: string): string {\n const cleaned = defaultUrlTransform(url);\n if (!cleaned) return '';\n // Ignore whitespace and control characters browsers skip (\"java\\tscript:\").\n const compact = Array.from(cleaned)\n .filter((c) => c.charCodeAt(0) > 0x20)\n .join('');\n if (/^[a-z][a-z0-9+.-]*:/i.test(compact) && !SAFE_PROTOCOL.test(compact)) return '';\n return cleaned;\n}\n\n/**\n * Makes partial streamed markdown render sanely: a fence that has opened but not closed is\n * closed at the end, so the tail renders as code instead of flashing as paragraphs.\n */\nexport function repairStreamingMarkdown(text: string): string {\n const fences = text.match(/^ {0,3}(`{3,}|~{3,})/gm) ?? [];\n if (fences.length % 2 === 0) return text;\n const opener = (fences[fences.length - 1] ?? '```').trim();\n return `${text}${text.endsWith('\\n') ? '' : '\\n'}${opener}`;\n}\n\nconst isExternal = (href: string) => /^https?:\\/\\//i.test(href);\n\n/** Drops react-markdown's `node` (hast) prop before spreading onto a DOM element. */\n/** Screen-reader note on links that open a new tab. */\nfunction NewTabHint() {\n const { t } = useI18n();\n return <span className=\"sr-only\"> {t('link.external')}</span>;\n}\n\n/** Remote images can track readers and break layout mid-stream: show them as links. */\nfunction ImageLink({ href, alt }: { href: string; alt?: string }) {\n const { t } = useI18n();\n const text = t('chat.image', { alt: alt || t('chat.untitled') });\n return href ? (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer nofollow\" className={s.link}>\n {text}\n <NewTabHint />\n </a>\n ) : (\n <span className={s.image}>{text}</span>\n );\n}\n\nfunction TaskCheckbox({ checked }: { checked: boolean }) {\n const { t } = useI18n();\n return (\n <input\n type=\"checkbox\"\n checked={checked}\n readOnly\n disabled\n aria-label={checked ? t('chat.taskDone') : t('chat.taskNotDone')}\n className={s.checkbox}\n />\n );\n}\n\nfunction omitNode<T extends { node?: unknown }>(props: T): Omit<T, 'node'> {\n const { node, ...rest } = props;\n void node;\n return rest;\n}\n\ntype CodeChildProps = { className?: string; children?: ReactNode };\n\nconst components: Components = {\n h1: (p) => <h1 {...omitNode(p)} className={s.h1} />,\n h2: (p) => <h2 {...omitNode(p)} className={s.h2} />,\n h3: (p) => <h3 {...omitNode(p)} className={s.h3} />,\n h4: (p) => <h4 {...omitNode(p)} className={s.h4} />,\n h5: (p) => <h4 {...omitNode(p)} className={s.h4} />,\n h6: (p) => <h4 {...omitNode(p)} className={s.h4} />,\n p: (p) => <p {...omitNode(p)} className={s.p} />,\n ul: (p) => <ul {...omitNode(p)} className={cn(s.ul, p.className === 'contains-task-list' && 'ps-1')} />,\n ol: (p) => <ol {...omitNode(p)} className={s.ol} />,\n li: (p) => <li {...omitNode(p)} className={cn(s.li, p.className)} />,\n blockquote: (p) => <blockquote {...omitNode(p)} className={s.blockquote} />,\n hr: () => <hr className={s.hr} />,\n table: (p) => (\n <div className={s.tableWrap}>\n <table {...omitNode(p)} className={s.table} />\n </div>\n ),\n th: (p) => <th {...omitNode(p)} className={s.th} />,\n td: (p) => <td {...omitNode(p)} className={s.td} />,\n a: (props) => {\n const { href, children, ...p } = omitNode(props);\n if (!href) return <span>{children}</span>;\n if (!isExternal(href)) {\n return (\n <a href={href} className={s.link} {...p}>\n {children}\n </a>\n );\n }\n return (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer nofollow\" className={s.link} {...p}>\n {children}\n <ExternalLink size={12} aria-hidden className={s.linkIcon} />\n <NewTabHint />\n </a>\n );\n },\n img: ({ src, alt }) => <ImageLink href={typeof src === 'string' ? src : ''} alt={alt} />,\n input: ({ checked, type }) => (type === 'checkbox' ? <TaskCheckbox checked={!!checked} /> : null),\n code: ({ className, children }) => <code className={cn(s.inlineCode, className)}>{children}</code>,\n pre: ({ children }) => {\n const child = Children.toArray(children)[0];\n if (!isValidElement<CodeChildProps>(child)) return <pre className={s.code.pre}>{children}</pre>;\n const language = /language-([\\w+#.-]+)/.exec(child.props.className ?? '')?.[1];\n const code = String(Children.toArray(child.props.children).join('')).replace(/\\n$/, '');\n return <CodeBlock code={code} language={language} />;\n },\n};\n\nconst remarkPlugins = [remarkGfm];\n\n/**\n * Safe markdown for model output: raw HTML is never rendered (skipped, not parsed), links are\n * restricted to http(s)/mailto/tel/relative, external links open in a new tab with a marker,\n * and fenced code gets a copy button. Partial input from a stream is tolerated.\n */\nexport const Markdown = memo(function Markdown({ children, streaming = false, className }: MarkdownProps) {\n const source = streaming ? repairStreamingMarkdown(children) : children;\n return (\n <div data-streaming={streaming || undefined} className={cn(s.root, streaming && streamingCaretClass, className)}>\n <ReactMarkdown remarkPlugins={remarkPlugins} components={components} skipHtml urlTransform={safeUrl}>\n {source}\n </ReactMarkdown>\n </div>\n );\n});\n","import { safeUrl } from '../Markdown/Markdown';\nimport { getPointer } from './pointer';\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n value !== null && typeof value === 'object' && !Array.isArray(value);\n\nexport function bindingPath(value: unknown): string | undefined {\n if (!isRecord(value) || !Object.hasOwn(value, 'path')) return undefined;\n if (typeof value.path !== 'string' || Object.keys(value).length !== 1) throw new Error('Invalid binding');\n // Validate even when the model has no value at this path yet.\n getPointer({}, value.path);\n return value.path;\n}\n\nexport function resolveValue(value: unknown, model: unknown): unknown {\n const path = bindingPath(value);\n if (path !== undefined) return getPointer(model, path);\n if (Array.isArray(value)) return value.map((item) => resolveValue(item, model));\n if (isRecord(value))\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, resolveValue(item, model)]));\n return value;\n}\n\n/** Remove executable/structural properties before even a host validator sees agent input. */\nexport function safeProperties(input: Readonly<Record<string, unknown>>, model: unknown): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(input)) {\n if (\n /^on/i.test(key) ||\n [\n 'id',\n 'component',\n 'children',\n 'className',\n 'style',\n 'dangerouslySetInnerHTML',\n 'ref',\n 'key',\n 'render',\n 'as',\n '__proto__',\n 'constructor',\n 'prototype',\n ].includes(key)\n )\n continue;\n const resolved = resolveValue(value, model);\n result[key] =\n /(?:href|src|url)$/i.test(key) && typeof resolved === 'string' ? safeUrl(resolved) || undefined : resolved;\n }\n return result;\n}\n\nexport function validAction(value: unknown): boolean {\n return (\n value === undefined ||\n (isRecord(value) &&\n typeof value.name === 'string' &&\n value.name.trim().length > 0 &&\n value.name.length <= 128 &&\n (value.context === undefined || isRecord(value.context)))\n );\n}\n","import { useEffect, useRef, useState, type ReactNode } from 'react';\nimport { useChatI18n } from '../utils/i18n';\nimport { SurfaceFocusBoundary } from './SurfaceFocusBoundary';\nimport { consume, emptyStream } from './stream';\nimport { bindingPath, isRecord, resolveValue, safeProperties, validAction } from './model';\nimport { setPointer } from './pointer';\nimport type { AgentCatalog } from './catalog';\nimport type { A2uiMessage, AgentComponent, AgentAction, AgentSurfaceError } from './protocol';\n\nexport interface AgentSurfaceProps {\n /** Immutable command log: append messages to update the rendered surfaces. */\n messages: A2uiMessage[];\n /** Trusted allow-list, created by the host rather than the agent. */\n catalog: AgentCatalog;\n onAction?: (action: AgentAction) => void;\n onError?: (error: AgentSurfaceError) => void;\n}\nexport function AgentSurface({ messages, catalog, onError, onAction }: AgentSurfaceProps) {\n const { tc } = useChatI18n();\n const reported = useRef(new Set<string>());\n const errors: AgentSurfaceError[] = [];\n const [state, setState] = useState(emptyStream);\n if (state.messages !== messages) setState(consume(state, messages));\n errors.push(...state.errors);\n function renderNode(surfaceId: string, nodes: Map<string, AgentComponent>, id: string): ReactNode {\n const node = nodes.get(id);\n if (!node) return null;\n const entry = Object.hasOwn(catalog, node.component) ? catalog[node.component] : undefined;\n const surface = state.surfaces.get(surfaceId)!;\n let props: Record<string, unknown> | null = null;\n try {\n const input = safeProperties(node, surface.model);\n if (validAction(input.action)) props = entry?.validate(input) ?? null;\n } catch {\n /* Invalid paths and validators produce the same neutral placeholder. */\n }\n if (!entry || !props) {\n errors.push({ code: entry ? 'props' : 'component', surfaceId, componentId: id, type: node.component });\n return (\n <p key={id} className=\"text-muted-foreground\">\n {tc('chat.surfaceUnsupported')}\n </p>\n );\n }\n const Component = entry.component;\n return (\n <Component\n key={id}\n props={props}\n onValueChange={(value) => {\n const path = bindingPath(node.value ?? node.checked);\n if (path === undefined) return;\n setState((current) => {\n const surface = current.surfaces.get(surfaceId);\n if (!surface) return current;\n const surfaces = new Map(current.surfaces);\n surfaces.set(surfaceId, { ...surface, model: setPointer(surface.model, path, value) });\n return { ...current, surfaces };\n });\n }}\n onAction={() => {\n if (!isRecord(node.action) || typeof node.action.name !== 'string') return;\n const context = resolveValue(node.action.context ?? {}, surface.model);\n if (isRecord(context)) onAction?.({ name: node.action.name, surfaceId, context });\n }}\n >\n {node.children?.map((child) => renderNode(surfaceId, nodes, child))}\n </Component>\n );\n }\n const content = [...state.surfaces].map(([id, surface]) => (\n <section\n key={id}\n data-agent-surface={id}\n role=\"group\"\n aria-label={tc('chat.surfaceAgentContent')}\n className=\"rounded-lg border border-border bg-background p-3\"\n >\n <p className=\"mb-3 text-xs font-semibold text-muted-foreground\">{tc('chat.surfaceAgentContent')}</p>\n <form onSubmit={(event) => event.preventDefault()}>\n {surface.invalid ? (\n <p className=\"text-muted-foreground\">{tc('chat.surfaceUnsupported')}</p>\n ) : (\n renderNode(id, surface.nodes, 'root')\n )}\n </form>\n </section>\n ));\n useEffect(() => {\n for (const error of errors) {\n const key = JSON.stringify(error);\n if (!reported.current.has(key)) {\n reported.current.add(key);\n onError?.(error);\n }\n }\n });\n return (\n <SurfaceFocusBoundary\n surfaceIds={new Set(state.surfaces.keys())}\n visible={state.surfaces.size > 0 || state.deleted}\n label={tc('chat.surfaceAgentContent')}\n >\n {content}\n </SurfaceFocusBoundary>\n );\n}\n","import {\n Alert,\n Badge,\n Button,\n Card,\n Checkbox,\n Heading,\n Input,\n Link,\n SimpleSelect,\n Stack,\n Text,\n type HeadingLevel,\n type SpaceScale,\n} from '@gntik-ai/ui';\nimport type { AgentCatalogRenderProps } from './catalog';\nimport { isRecord } from './model';\n\nconst text = (value: unknown) => (typeof value === 'string' ? value : '');\n\nexport function SurfaceText({ props }: AgentCatalogRenderProps) {\n return typeof props.href === 'string' && props.href ? (\n <Text>\n <Link href={props.href}>{text(props.text)}</Link>\n </Text>\n ) : (\n <Text>{text(props.text)}</Text>\n );\n}\nexport function SurfaceHeading({ props }: AgentCatalogRenderProps) {\n return (\n <Heading level={typeof props.level === 'number' ? (props.level as HeadingLevel) : 2}>{text(props.text)}</Heading>\n );\n}\nexport function SurfaceCard({ children }: AgentCatalogRenderProps) {\n return <Card className=\"space-y-3 p-4\">{children}</Card>;\n}\nexport function SurfaceStack({ props, children }: AgentCatalogRenderProps) {\n return (\n <Stack\n direction={props.direction === 'row' ? 'row' : 'column'}\n gap={typeof props.gap === 'number' ? (props.gap as SpaceScale) : 3}\n >\n {children}\n </Stack>\n );\n}\nexport function SurfaceButton({ props, onAction }: AgentCatalogRenderProps) {\n return (\n <Button\n type=\"submit\"\n className=\"motion-reduce:transition-none\"\n disabled={props.disabled === true}\n onClick={onAction}\n >\n {text(props.label)}\n </Button>\n );\n}\nexport function SurfaceInput({ props, onValueChange }: AgentCatalogRenderProps) {\n return (\n <label className=\"flex flex-col gap-2 text-sm text-foreground\">\n {text(props.label)}\n <Input type=\"text\" disabled={props.disabled === true} value={text(props.value)} onValueChange={onValueChange} />\n </label>\n );\n}\nexport function SurfaceSelect({ props, onValueChange }: AgentCatalogRenderProps) {\n const items = Array.isArray(props.options)\n ? props.options.filter(isRecord).map((item) => ({ value: text(item.value), label: text(item.label) }))\n : [];\n return (\n <SimpleSelect<string>\n label={text(props.label)}\n disabled={props.disabled === true}\n value={typeof props.value === 'string' ? props.value : null}\n items={items}\n onValueChange={onValueChange}\n />\n );\n}\nexport function SurfaceCheckbox({ props, onValueChange }: AgentCatalogRenderProps) {\n return (\n <Checkbox\n label={text(props.label)}\n disabled={props.disabled === true}\n checked={props.checked === true}\n onCheckedChange={onValueChange}\n />\n );\n}\nexport function SurfaceAlert({ props }: AgentCatalogRenderProps) {\n return <Alert title={text(props.title)} description={text(props.text)} />;\n}\nexport function SurfaceBadge({ props }: AgentCatalogRenderProps) {\n return <Badge>{text(props.text)}</Badge>;\n}\n","import type { ComponentType, ReactNode } from 'react';\nimport {\n SurfaceAlert,\n SurfaceBadge,\n SurfaceButton,\n SurfaceCard,\n SurfaceCheckbox,\n SurfaceHeading,\n SurfaceInput,\n SurfaceSelect,\n SurfaceStack,\n SurfaceText,\n} from './catalog-components';\nimport { isRecord } from './model';\n\n/** Trusted host code: render explicit properties; never spread the agent's input. */\nexport interface AgentCatalogRenderProps {\n props: Readonly<Record<string, unknown>>;\n children?: ReactNode;\n onValueChange: (value: unknown) => void;\n onAction: () => void;\n}\nexport interface AgentCatalogEntry {\n component: ComponentType<AgentCatalogRenderProps>;\n /** Return a fresh object of known properties, or null when invalid. */\n validate: (props: Readonly<Record<string, unknown>>) => Record<string, unknown> | null;\n}\nexport type AgentCatalog = Readonly<Record<string, AgentCatalogEntry>>;\nexport function defineAgentCatalog(entries: AgentCatalog): AgentCatalog {\n return Object.freeze(\n Object.fromEntries(Object.entries(entries).map(([name, entry]) => [name, Object.freeze({ ...entry })])),\n );\n}\n\ntype Rule = (value: unknown) => boolean;\nconst string: Rule = (value) => typeof value === 'string';\nconst label: Rule = (value) => typeof value === 'string' && value.trim().length > 0;\nconst optional =\n (rule: Rule): Rule =>\n (value) =>\n value === undefined || rule(value);\nconst boolean: Rule = (value) => typeof value === 'boolean';\nfunction fields(rules: Record<string, Rule>): AgentCatalogEntry['validate'] {\n return (input) => {\n const output: Record<string, unknown> = {};\n for (const [key, rule] of Object.entries(rules)) {\n if (!rule(input[key])) return null;\n if (input[key] !== undefined) output[key] = input[key];\n }\n return output;\n };\n}\nconst options: Rule = (value) =>\n Array.isArray(value) &&\n value.length <= 100 &&\n value.every((item) => isRecord(item) && label(item.value) && label(item.label)) &&\n new Set(value.map((item: unknown) => (isRecord(item) ? item.value : null))).size === value.length;\n\n/** Small text/form catalog. Password, payment and file controls are deliberately absent. */\nexport const defaultAgentCatalog = defineAgentCatalog({\n Text: { component: SurfaceText, validate: fields({ text: string, href: optional(string) }) },\n Heading: {\n component: SurfaceHeading,\n validate: fields({\n text: label,\n level: optional((v) => typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 6),\n }),\n },\n Card: { component: SurfaceCard, validate: fields({}) },\n Stack: {\n component: SurfaceStack,\n validate: fields({\n direction: optional((v) => v === 'row' || v === 'column'),\n gap: optional((v) => typeof v === 'number' && Number.isInteger(v) && v >= 0 && v <= 12),\n }),\n },\n Button: { component: SurfaceButton, validate: fields({ label, disabled: optional(boolean) }) },\n Input: {\n component: SurfaceInput,\n validate: fields({\n label,\n value: optional(string),\n disabled: optional(boolean),\n type: optional((v) => v === 'text'),\n }),\n },\n Select: {\n component: SurfaceSelect,\n validate: (input) => {\n const result = fields({\n label,\n value: optional((v) => v === null || typeof v === 'string'),\n options,\n disabled: optional(boolean),\n })(input);\n if (!result || !Array.isArray(result.options)) return null;\n return {\n ...result,\n options: result.options.filter(isRecord).map((item) => ({ value: item.value, label: item.label })),\n };\n },\n },\n Checkbox: {\n component: SurfaceCheckbox,\n validate: fields({ label, checked: optional(boolean), disabled: optional(boolean) }),\n },\n Alert: { component: SurfaceAlert, validate: fields({ title: label, text: optional(string) }) },\n Badge: { component: SurfaceBadge, validate: fields({ text: label }) },\n});\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'AgentSurface',\n group: 'Display',\n status: 'beta',\n description:\n 'Opt-in, placement-neutral renderer for allow-listed agent content. Accepts only A2UI v0.9 command envelopes (A2UI_VERSION). Pass an immutable messages log and a trusted catalog; append createSurface, updateComponents, updateDataModel and deleteSurface messages. Component records have id, component, optional children (child ids), and flat catalog properties; the root id is \"root\". Text/Heading/Badge use text; Text optionally accepts href; Heading accepts level 1–6. Card contains children; Stack accepts direction (row/column) and gap (0–12). Button uses label, optional disabled and action { name, context }; Input uses label, optional text value/disabled and only type text. Select uses label, options [{ value, label }], optional value/disabled; Checkbox uses label, optional checked/disabled. Alert uses title and optional text. { path: \"/user/name\" } reads a JSON Pointer; Input/Select value and Checkbox checked write back to that path. updateDataModel { surfaceId, path?, value } replaces the value at path (default: model root). Every default Button is a submit control: Enter in an Input can activate the first Button, so keep a safe primary action first and avoid destructive actions in that position. Buttons, keyboard activation and implicit form submission emit onAction { name, surfaceId, context } with the current bound values. Replacing the log replays it; keep existing message objects stable when appending. Runtime validation rejects unsupported versions, malformed JSON, prototype keys, cycles, shared children and excessive trees (256 nodes, depth 32, 32 surfaces). Missing child definitions may arrive later. Unknown components and invalid properties show a localized placeholder and report a deduplicated onError diagnostic. The visible, accessible agent-content frame cannot be relabelled by the agent. Deletion or version suppression of rendered content restores focus to the next surviving sibling control, the first focusable textarea in the document, or the labelled container. Place the chat composer as that first textarea or provide a focusable sibling after the renderer; another textarea can otherwise receive focus. defineAgentCatalog accepts trusted host wrappers { component, validate }; validate must return a fresh allow-list of known properties or null. Wrappers receive { props, children, onValueChange, onAction } and must assign explicit kit props. Never spread agent data into elements. Custom URL properties must have names ending in href, src or url (case-insensitive) to receive the Markdown safeUrl policy; text renders as React text nodes. Custom catalogs can reintroduce phishing and executable content: audit their wrappers and validators, never allow passwords, payments, file uploads, arbitrary markup or host-chrome styling. Transport, side-panel placement, v0.8 adapters and Markdown integration belong to consumers or future changes. The live example demonstrates every default entry, model patches, actions, rejection, deletion and reset.',\n primitive: 'Kit components (Base UI)',\n pattern: 'labelled group containing a form',\n keyboard: [\n ['Tab / Shift+Tab', 'Moves between enabled form controls and links'],\n ['Enter / Space', 'Activates a Button exactly once; Enter in an Input submits with the first Button'],\n ['Space', 'Toggles a Checkbox and updates its bound model path'],\n ['Enter / ArrowDown', 'Opens a Select; ArrowUp/ArrowDown navigates options'],\n ['Enter / Escape', 'Selects an option / closes a Select and returns focus'],\n ['Surface deletion', 'Moves focus to a surviving sibling control, the composer, or the labelled container'],\n ],\n tokens: ['background', 'card', 'border', 'foreground', 'muted-foreground', 'focus-ring'],\n};\n","import { focusRing } from '../utils/focus';\n\n/** Slot classes for AttachmentChip / AttachmentList. */\nexport const attachmentStyles = {\n list: 'flex flex-wrap gap-1.5',\n item: 'min-w-0',\n chip: [\n 'relative inline-flex h-10 max-w-64 min-w-0 items-center gap-2 overflow-hidden rounded-md border border-border bg-secondary/50 ps-1.5 pe-1 text-[12px] text-foreground',\n 'data-[status=error]:border-destructive/60 data-[status=error]:bg-destructive/8',\n ].join(' '),\n tile: [\n 'relative flex w-28 flex-col overflow-hidden rounded-lg border border-border bg-card text-[12px] text-foreground',\n 'data-[status=error]:border-destructive/60',\n ].join(' '),\n media: 'grid size-7 shrink-0 place-items-center overflow-hidden rounded bg-background text-muted-foreground',\n mediaError: 'text-destructive-text',\n tileMedia: 'grid aspect-square w-full place-items-center overflow-hidden bg-secondary/50 text-muted-foreground',\n img: 'size-full object-cover',\n text: 'flex min-w-0 flex-1 flex-col leading-4',\n tileText: 'flex min-w-0 flex-col gap-0.5 px-2 py-1.5 leading-4',\n name: 'truncate font-medium',\n meta: 'truncate font-mono text-[10.5px] text-muted-foreground',\n metaError: 'truncate text-[11px] text-destructive-chip-text',\n button: `grid size-6 shrink-0 place-items-center rounded text-muted-foreground hover:bg-foreground/10 hover:text-foreground disabled:pointer-events-none disabled:opacity-50 ${focusRing}`,\n tileActions: 'absolute end-1 top-1 flex gap-0.5 rounded-md bg-card/90',\n track: 'absolute inset-x-0 bottom-0 h-0.5 bg-border',\n bar: 'h-full bg-primary transition-[width] duration-200 motion-reduce:transition-none',\n barIndeterminate: 'h-full w-1/3 bg-primary animate-pulse motion-reduce:animate-none',\n} as const;\n","import { formatBytes, cn, fileKind, type FileKind } from '@gntik-ai/ui';\nimport {\n AlertCircle,\n File,\n FileArchive,\n FileAudio,\n FileCode,\n FileImage,\n FileSpreadsheet,\n FileText,\n FileVideo,\n RotateCcw,\n X,\n type LucideIcon,\n} from 'lucide-react';\nimport type { Ref } from 'react';\nimport { useChatI18n } from '../utils/i18n';\nimport { attachmentStyles as s } from './attachment.variants';\n\n/** A file attached to a message or waiting in the composer. */\nexport interface ChatAttachment {\n id: string;\n name: string;\n /** Size in bytes. */\n size?: number;\n /** MIME type; picks the icon (falls back to the extension). */\n type?: string;\n /** Image preview URL (e.g. from URL.createObjectURL); shown as a thumbnail for images. */\n previewUrl?: string;\n /** Upload progress 0–100 (`null` = indeterminate). Omit when not uploading. */\n progress?: number | null;\n /** Upload failed; a string replaces the default message. */\n error?: boolean | string;\n}\n\nexport type AttachmentStatus = 'idle' | 'uploading' | 'error';\n\nexport interface AttachmentChipProps {\n attachment: ChatAttachment;\n /** `chip` (composer, compact row) or `tile` (message, larger image preview). */\n variant?: 'chip' | 'tile';\n /** Shows the remove button. */\n onRemove?: (id: string) => void;\n /** Shows a retry button in the error state. */\n onRetry?: (id: string) => void;\n disabled?: boolean;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n}\n\nconst ICONS: Record<FileKind, LucideIcon> = {\n image: FileImage,\n video: FileVideo,\n audio: FileAudio,\n archive: FileArchive,\n code: FileCode,\n spreadsheet: FileSpreadsheet,\n document: FileText,\n file: File,\n};\n\n/** Status of an attachment from its progress and error fields. */\nexport function attachmentStatus(a: ChatAttachment): AttachmentStatus {\n if (a.error) return 'error';\n if (a.progress === null || (typeof a.progress === 'number' && a.progress < 100)) return 'uploading';\n return 'idle';\n}\n\n/**\n * One attached file: image thumbnail or file-type icon, name, size, upload progress\n * (a progressbar), error with retry, and a remove button.\n */\nexport function AttachmentChip({\n attachment: a,\n variant = 'chip',\n onRemove,\n onRetry,\n disabled = false,\n className,\n ref,\n}: AttachmentChipProps) {\n const { t, tc, locale } = useChatI18n();\n const status = attachmentStatus(a);\n const kind = fileKind(a.name, a.type);\n const Icon = status === 'error' ? AlertCircle : ICONS[kind];\n const showImage = a.previewUrl !== undefined && kind === 'image' && status !== 'error';\n const tile = variant === 'tile';\n const pct = typeof a.progress === 'number' ? Math.max(0, Math.min(100, Math.round(a.progress))) : null;\n\n const media = (\n <span className={cn(tile ? s.tileMedia : s.media, status === 'error' && s.mediaError)}>\n {showImage ? <img src={a.previewUrl} alt=\"\" className={s.img} /> : <Icon size={tile ? 22 : 14} aria-hidden />}\n </span>\n );\n\n const meta =\n status === 'error' ? (\n <span className={s.metaError}>{typeof a.error === 'string' ? a.error : tc('chat.uploadFailed')}</span>\n ) : status === 'uploading' ? (\n <span className={s.meta}>{pct === null ? t('common.loading') : `${pct}%`}</span>\n ) : a.size !== undefined ? (\n <span className={s.meta}>{formatBytes(a.size, locale)}</span>\n ) : null;\n\n const buttons = (\n <>\n {status === 'error' && onRetry && (\n <button\n type=\"button\"\n className={s.button}\n aria-label={tc('chat.retryUpload', { name: a.name })}\n disabled={disabled}\n onClick={() => onRetry(a.id)}\n >\n <RotateCcw size={12} aria-hidden />\n </button>\n )}\n {onRemove && (\n <button\n type=\"button\"\n className={s.button}\n aria-label={t('common.removeItem', { label: a.name })}\n disabled={disabled}\n onClick={() => onRemove(a.id)}\n >\n <X size={12} aria-hidden />\n </button>\n )}\n </>\n );\n\n return (\n <div ref={ref} data-status={status} data-kind={kind} className={cn(tile ? s.tile : s.chip, className)}>\n {media}\n <span className={tile ? s.tileText : s.text}>\n <span className={s.name} title={a.name}>\n {a.name}\n </span>\n {meta}\n </span>\n {tile\n ? (onRemove || (status === 'error' && onRetry)) && <span className={s.tileActions}>{buttons}</span>\n : buttons}\n {status === 'uploading' && (\n <span\n role=\"progressbar\"\n aria-label={tc('chat.uploading', { name: a.name })}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={pct ?? undefined}\n className={s.track}\n >\n <span\n className={pct === null ? s.barIndeterminate : s.bar}\n style={pct === null ? undefined : { width: `${pct}%` }}\n />\n </span>\n )}\n </div>\n );\n}\n","import { cn } from '@gntik-ai/ui';\nimport type { Ref } from 'react';\nimport { useChatI18n } from '../utils/i18n';\nimport { AttachmentChip, type ChatAttachment } from './AttachmentChip';\nimport { attachmentStyles as s } from './attachment.variants';\n\nexport interface AttachmentListProps {\n attachments: ChatAttachment[];\n /** `chip` for the composer, `tile` for larger image previews in a message. */\n variant?: 'chip' | 'tile';\n onRemove?: (id: string) => void;\n onRetry?: (id: string) => void;\n disabled?: boolean;\n /** Accessible name of the list. Default \"Attachments\". */\n label?: string;\n className?: string;\n ref?: Ref<HTMLUListElement>;\n}\n\n/** A labelled list of AttachmentChips. Renders nothing when empty. */\nexport function AttachmentList({\n attachments,\n variant = 'chip',\n onRemove,\n onRetry,\n disabled,\n label,\n className,\n ref,\n}: AttachmentListProps) {\n const { t } = useChatI18n();\n if (attachments.length === 0) return null;\n return (\n <ul ref={ref} aria-label={label ?? t('chat.attachments')} className={cn(s.list, className)}>\n {attachments.map((a) => (\n <li key={a.id} className={s.item}>\n <AttachmentChip attachment={a} variant={variant} onRemove={onRemove} onRetry={onRetry} disabled={disabled} />\n </li>\n ))}\n </ul>\n );\n}\n","export type AttachmentRejectionReason = 'type' | 'size' | 'count';\n\nexport interface AttachmentRejection {\n file: File;\n reason: AttachmentRejectionReason;\n /** Human-readable message (set by ChatComposer from the i18n catalog). */\n message: string;\n}\n\nexport interface ValidateFilesOptions {\n /** Same syntax as `<input accept>`: \".pdf,.csv,image/*,application/json\". */\n accept?: string;\n /** Largest allowed file, in bytes. */\n maxSize?: number;\n /** Most files allowed in total, counting `current`. */\n maxFiles?: number;\n /** Files already attached. */\n current?: number;\n}\n\n/** Whether a file matches an `accept` list (extensions, exact MIME types and `type/*`). */\nexport function matchesAccept(file: Pick<File, 'name' | 'type'>, accept?: string): boolean {\n if (!accept?.trim()) return true;\n const name = file.name.toLowerCase();\n const type = file.type.toLowerCase();\n return accept\n .split(',')\n .map((a) => a.trim().toLowerCase())\n .filter(Boolean)\n .some((rule) => {\n if (rule.startsWith('.')) return name.endsWith(rule);\n if (rule.endsWith('/*')) return type.startsWith(rule.slice(0, -1));\n return type === rule;\n });\n}\n\n/** Splits files into accepted ones and rejections (without messages) by type, size and count. */\nexport function validateFiles(files: File[], { accept, maxSize, maxFiles, current = 0 }: ValidateFilesOptions) {\n const accepted: File[] = [];\n const rejected: Array<{ file: File; reason: AttachmentRejectionReason }> = [];\n for (const file of files) {\n if (!matchesAccept(file, accept)) rejected.push({ file, reason: 'type' });\n else if (maxSize !== undefined && file.size > maxSize) rejected.push({ file, reason: 'size' });\n else if (maxFiles !== undefined && current + accepted.length >= maxFiles) rejected.push({ file, reason: 'count' });\n else accepted.push(file);\n }\n return { accepted, rejected };\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'AttachmentList',\n group: 'Display',\n status: 'beta',\n description:\n 'Files attached to a message or waiting in the composer. Each AttachmentChip shows an image thumbnail or a file-type icon, the name, the size, upload progress (a labelled progressbar; indeterminate holds still under reduced motion), an error with Retry, and a Remove button. `variant=\"tile\"` gives larger image previews inside a message. `validateFiles` / `matchesAccept` back the composer’s accept and max-size checks.',\n pattern: 'list',\n keyboard: [\n ['Tab', 'Moves through each chip’s Retry (on error) and Remove buttons'],\n ['Enter / Space', 'Activates the focused Retry or Remove button'],\n ],\n tokens: [\n 'secondary',\n 'card',\n 'border',\n 'muted-foreground',\n 'primary',\n 'destructive',\n 'destructive-text',\n 'focus-ring',\n ],\n};\n","import { focusRing } from '../utils/focus';\n\n/** Slot classes for ChatComposer (focus ring on the frame, like the legacy composer). */\nexport const chatComposerStyles = {\n root: [\n 'relative overflow-hidden rounded-xl border border-border bg-card shadow-sm transition-colors motion-reduce:transition-none',\n 'focus-within:border-primary/60 focus-within:ring-2 focus-within:ring-ring/25',\n 'data-[disabled]:opacity-60 data-[dragging]:border-primary/60',\n ].join(' '),\n dropOverlay:\n 'pointer-events-none absolute inset-0 z-10 flex items-center justify-center gap-2 rounded-xl border-2 border-dashed border-primary/60 bg-card/95 text-[13px] font-medium text-primary-text',\n errors:\n 'mx-3 mt-3 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/8 px-2.5 py-1.5 text-[12px] text-destructive-chip-text',\n errorList: 'flex min-w-0 flex-1 flex-col gap-0.5',\n errorDismiss: `-me-1 grid size-5 shrink-0 place-items-center rounded text-destructive-chip-text hover:bg-foreground/10 ${focusRing}`,\n attachments: 'flex flex-wrap gap-1.5 px-3 pt-3',\n /** @deprecated Chips render AttachmentChip (see attachmentStyles). */\n chip: 'inline-flex h-7 max-w-60 items-center gap-1.5 rounded-md border border-border bg-secondary/50 ps-2 pe-1 text-[12px] text-foreground',\n chipName: 'truncate font-medium',\n chipSize: 'shrink-0 font-mono text-[10.5px] text-muted-foreground',\n chipRemove: `grid size-5 shrink-0 place-items-center rounded text-muted-foreground hover:bg-foreground/10 hover:text-foreground ${focusRing}`,\n textarea: [\n 'block max-h-[220px] min-h-[52px] w-full resize-none bg-transparent px-3.5 py-3 text-[14px] leading-6 text-foreground',\n 'field-sizing-content placeholder:text-muted-foreground focus:outline-none disabled:cursor-not-allowed',\n ].join(' '),\n toolbar: 'flex items-center justify-between gap-2 px-2 pb-2',\n tools: 'flex min-w-0 items-center gap-1',\n end: 'flex shrink-0 items-center gap-2',\n count: 'font-mono text-[11px] text-muted-foreground tabular-nums',\n countOver: 'text-destructive-text',\n hint: 'mt-1.5 px-1 text-center text-[11.5px] text-muted-foreground',\n} as const;\n","import { formatBytes, Button, IconButton, cn } from '@gntik-ai/ui';\nimport { ArrowUp, Paperclip, Square, Upload, X } from 'lucide-react';\nimport {\n useId,\n useRef,\n useState,\n type ChangeEvent,\n type ClipboardEvent,\n type DragEvent,\n type FormEvent,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n} from 'react';\nimport { AttachmentList, validateFiles, type AttachmentRejection, type ChatAttachment } from '../Attachment';\nimport { useChatI18n } from '../utils/i18n';\nimport { chatComposerStyles as s } from './chatComposer.variants';\n\n/** A file in the composer: name and size, plus optional type, preview, progress and error. */\nexport type ComposerAttachment = ChatAttachment;\n\nexport interface ChatComposerProps {\n /** Controlled text. Pair with `onValueChange`. */\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n /** Called with the trimmed text when the user sends. Uncontrolled composers clear themselves. */\n onSubmit: (text: string, attachments: ComposerAttachment[]) => void;\n /** A reply is streaming: Send turns into Stop, Enter no longer sends, Escape stops. */\n streaming?: boolean;\n onStop?: () => void;\n disabled?: boolean;\n placeholder?: string;\n /** Accessible name of the text box. */\n label?: string;\n /** Soft limit: shows a counter near the limit and blocks sending above it. */\n maxLength?: number;\n /** Attached files shown as removable chips (thumbnail, progress, error + retry). */\n attachments?: ComposerAttachment[];\n /**\n * Shows the attach button and enables paste and drag-and-drop of files; called with the\n * files that pass `accept`, `maxSize` and `maxFiles`.\n */\n onAttach?: (files: File[]) => void;\n onRemoveAttachment?: (id: string) => void;\n /** Shows Retry on attachments in the error state. */\n onRetryAttachment?: (id: string) => void;\n /** Allowed types, `<input accept>` syntax (e.g. \".pdf,.csv,image/*\"). Also checked on paste and drop. */\n accept?: string;\n /** Largest allowed file, in bytes. */\n maxSize?: number;\n /** Most files attached at once. */\n maxFiles?: number;\n /** Called with the files that failed validation (their messages are also shown under the box). */\n onReject?: (rejections: AttachmentRejection[]) => void;\n /** Slot left of the send button, e.g. a model Select. */\n modelPicker?: ReactNode;\n /** Extra tools after the attach button. */\n tools?: ReactNode;\n /** Small line under the box. Defaults to the keyboard hint; pass null to hide it. */\n hint?: ReactNode;\n className?: string;\n ref?: Ref<HTMLTextAreaElement>;\n}\n\n/**\n * Message box for a chat: grows with its content, Enter sends and Shift+Enter adds a line,\n * files (picked, pasted or dropped, validated against accept / maxSize / maxFiles) show as\n * removable chips with previews and upload progress, a model picker can sit in the toolbar, and while a reply\n * streams the send button becomes Stop (Escape also stops).\n */\nexport function ChatComposer({\n value,\n defaultValue = '',\n onValueChange,\n onSubmit,\n streaming = false,\n onStop,\n disabled = false,\n placeholder: placeholderProp,\n label: labelProp,\n maxLength,\n attachments = [],\n onAttach,\n onRemoveAttachment,\n onRetryAttachment,\n accept,\n maxSize,\n maxFiles,\n onReject,\n modelPicker,\n tools,\n hint,\n className,\n ref,\n}: ChatComposerProps) {\n const { t, tc, locale } = useChatI18n();\n const placeholder = placeholderProp ?? t('chat.placeholder');\n const label = labelProp ?? t('chat.messageLabel');\n const id = useId();\n const [inner, setInner] = useState(defaultValue);\n const text = value ?? inner;\n const fileInput = useRef<HTMLInputElement>(null);\n const dragDepth = useRef(0);\n const [dragging, setDragging] = useState(false);\n const [errors, setErrors] = useState<string[]>([]);\n const canAttach = onAttach !== undefined && !disabled;\n\n const setText = (next: string) => {\n if (value === undefined) setInner(next);\n onValueChange?.(next);\n };\n\n const length = text.length;\n const over = maxLength !== undefined && length > maxLength;\n const showCount = maxLength !== undefined && length >= maxLength * 0.8;\n const canSend = !disabled && !streaming && !over && (text.trim().length > 0 || attachments.length > 0);\n\n const send = () => {\n if (!canSend) return;\n onSubmit(text.trim(), attachments);\n if (value === undefined) setInner('');\n };\n\n const onKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {\n e.preventDefault();\n send();\n } else if (e.key === 'Escape' && streaming && onStop) {\n e.preventDefault();\n onStop();\n }\n };\n\n const addFiles = (files: File[]) => {\n if (!onAttach || files.length === 0) return;\n const { accepted, rejected } = validateFiles(files, { accept, maxSize, maxFiles, current: attachments.length });\n const rejections: AttachmentRejection[] = rejected.map(({ file, reason }) => ({\n file,\n reason,\n message:\n reason === 'type'\n ? tc('chat.fileTypeNotAllowed', { name: file.name })\n : reason === 'size'\n ? tc('chat.fileTooLarge', { name: file.name, max: formatBytes(maxSize ?? 0, locale) })\n : tc('chat.tooManyFiles', { max: maxFiles ?? 0 }),\n }));\n // One \"too many files\" line is enough.\n setErrors([...new Set(rejections.map((r) => r.message))]);\n if (rejections.length) onReject?.(rejections);\n if (accepted.length) onAttach(accepted);\n };\n\n const onFiles = (e: ChangeEvent<HTMLInputElement>) => {\n addFiles(Array.from(e.target.files ?? []));\n e.target.value = '';\n };\n\n const onPaste = (e: ClipboardEvent<HTMLTextAreaElement>) => {\n const files = Array.from(e.clipboardData?.files ?? []);\n if (!canAttach || files.length === 0) return;\n e.preventDefault();\n addFiles(files);\n };\n\n const hasFiles = (e: DragEvent) => Array.from(e.dataTransfer?.types ?? []).includes('Files');\n const dropHandlers = canAttach\n ? {\n onDragEnter: (e: DragEvent<HTMLFormElement>) => {\n if (!hasFiles(e)) return;\n e.preventDefault();\n dragDepth.current += 1;\n setDragging(true);\n },\n onDragOver: (e: DragEvent<HTMLFormElement>) => {\n if (!hasFiles(e)) return;\n e.preventDefault();\n if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy';\n },\n onDragLeave: () => {\n dragDepth.current = Math.max(0, dragDepth.current - 1);\n if (dragDepth.current === 0) setDragging(false);\n },\n onDrop: (e: DragEvent<HTMLFormElement>) => {\n e.preventDefault();\n dragDepth.current = 0;\n setDragging(false);\n addFiles(Array.from(e.dataTransfer?.files ?? []));\n },\n }\n : {};\n\n const hintNode =\n hint === undefined ? (\n <>\n <kbd className=\"font-sans\">{t('kbd.enter')}</kbd> {t('chat.hintSend')} ·{' '}\n <kbd className=\"font-sans\">{t('chat.shiftEnter')}</kbd> {t('chat.hintNewLine')}\n </>\n ) : (\n hint\n );\n\n return (\n <div className={className}>\n <form\n className={s.root}\n data-disabled={disabled || undefined}\n data-dragging={dragging || undefined}\n {...dropHandlers}\n onSubmit={(e: FormEvent) => {\n e.preventDefault();\n send();\n }}\n >\n {dragging && (\n <div aria-hidden className={s.dropOverlay}>\n <Upload size={16} />\n {tc('chat.dropFiles')}\n </div>\n )}\n <AttachmentList\n attachments={attachments}\n onRemove={onRemoveAttachment}\n onRetry={onRetryAttachment}\n disabled={disabled}\n className={s.attachments}\n />\n <div role=\"alert\" className={cn(errors.length > 0 && s.errors)}>\n {errors.length > 0 && (\n <>\n <ul className={s.errorList}>\n {errors.map((m) => (\n <li key={m}>{m}</li>\n ))}\n </ul>\n <button\n type=\"button\"\n className={s.errorDismiss}\n aria-label={t('common.dismiss')}\n onClick={() => setErrors([])}\n >\n <X size={12} aria-hidden />\n </button>\n </>\n )}\n </div>\n <textarea\n ref={ref}\n id={`${id}-input`}\n rows={1}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n disabled={disabled}\n placeholder={placeholder}\n aria-label={label}\n aria-invalid={over || undefined}\n aria-describedby={showCount ? `${id}-count` : undefined}\n className={s.textarea}\n />\n <div className={s.toolbar}>\n <div className={s.tools}>\n {onAttach && (\n <>\n <IconButton\n size=\"sm\"\n icon={Paperclip}\n label={t('chat.attach')}\n disabled={disabled}\n onClick={() => fileInput.current?.click()}\n />\n <input\n ref={fileInput}\n type=\"file\"\n multiple\n hidden\n accept={accept}\n aria-label={t('chat.attach')}\n onChange={onFiles}\n />\n </>\n )}\n {tools}\n </div>\n <div className={s.end}>\n {showCount && (\n <span id={`${id}-count`} className={cn(s.count, over && s.countOver)}>\n {length}/{maxLength}\n {over && <span className=\"sr-only\"> {t('chat.overLimit')}</span>}\n </span>\n )}\n {modelPicker}\n {streaming ? (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n icon={Square}\n aria-label={t('chat.stop')}\n onClick={onStop}\n disabled={!onStop}\n >\n {t('common.stop')}\n </Button>\n ) : (\n <IconButton\n size=\"sm\"\n variant=\"primary\"\n icon={ArrowUp}\n label={t('chat.send')}\n type=\"submit\"\n disabled={!canSend}\n />\n )}\n </div>\n </div>\n </form>\n {hintNode !== null && <p className={s.hint}>{hintNode}</p>}\n </div>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'ChatComposer',\n group: 'Forms',\n status: 'beta',\n description:\n 'Chat input: autosizing textarea, Enter sends and Shift+Enter adds a line, attachments (pick, paste or drag-and-drop files; `accept`, `maxSize` and `maxFiles` validation with messages in an alert; chips with image thumbnails, file-type icons, size, upload progress, error + Retry and Remove), a model-picker slot (e.g. a compact ModelPicker), a character counter near the limit, a disabled state, and a Stop button while a reply streams.',\n keyboard: [\n ['Enter', 'Sends the message (ignored while streaming or during IME composition)'],\n ['Shift+Enter', 'Inserts a new line'],\n ['Escape', 'While a reply streams: stops it'],\n [\n 'Tab',\n 'Moves through attachment Retry/Remove buttons, the text box, attach, tools, the model picker and Send/Stop',\n ],\n ['Ctrl/⌘+V', 'In the text box: pasted files are attached (validated) instead of inserted'],\n ],\n tokens: [\n 'card',\n 'destructive-chip-text',\n 'primary-text',\n 'border',\n 'primary',\n 'ring',\n 'secondary',\n 'muted-foreground',\n 'destructive-text',\n 'focus-ring',\n ],\n};\n","/** Slot classes for TypingIndicator. Dots pulse in sequence; static under reduced motion. */\nexport const typingIndicatorStyles = {\n root: 'inline-flex items-center gap-2 text-muted-foreground',\n dots: 'inline-flex h-6 items-center gap-1',\n dot: 'size-1.5 rounded-full bg-muted-foreground animate-pulse motion-reduce:animate-none',\n label: 'text-[12.5px]',\n size: {\n sm: { dots: 'h-4 gap-0.5', dot: 'size-1' },\n md: { dots: '', dot: '' },\n },\n} as const;\n\n/** Thin blinking caret after streamed plain text (static under reduced motion). */\nexport const streamingCaret =\n 'ms-0.5 inline-block h-[1.05em] w-[2px] translate-y-[2px] bg-primary animate-pulse motion-reduce:animate-none';\n","import { cn } from '@gntik-ai/ui';\nimport type { Ref } from 'react';\nimport { useChatI18n } from '../utils/i18n';\nimport { typingIndicatorStyles as s } from './typingIndicator.variants';\n\nexport interface TypingIndicatorProps {\n /** Who is typing; used in the accessible text (\"Assistant is typing\"). */\n author?: string;\n /** Show the text next to the dots instead of keeping it screen-reader only. */\n showLabel?: boolean;\n /** Overrides the text entirely. */\n label?: string;\n size?: 'sm' | 'md';\n /**\n * Announce the text through its own polite status region. Off by default: in a thread,\n * ChatAnnouncer already announces \"is responding\" once.\n */\n announce?: boolean;\n className?: string;\n ref?: Ref<HTMLSpanElement>;\n}\n\n/**\n * Three dots that pulse while a reply is being written. The dots are decorative; the text\n * (\"Assistant is typing\") is always in the accessibility tree. Under reduced motion the dots\n * hold still.\n */\nexport function TypingIndicator({\n author,\n showLabel = false,\n label,\n size = 'md',\n announce = false,\n className,\n ref,\n}: TypingIndicatorProps) {\n const { t, tc } = useChatI18n();\n const text = label ?? tc('chat.typing', { author: author ?? t('chat.assistant') });\n const sz = s.size[size];\n return (\n <span\n ref={ref}\n data-slot=\"typing-indicator\"\n role={announce ? 'status' : undefined}\n className={cn(s.root, className)}\n >\n <span aria-hidden className={cn(s.dots, sz.dots)}>\n <span className={cn(s.dot, sz.dot)} />\n <span className={cn(s.dot, sz.dot, '[animation-delay:150ms]')} />\n <span className={cn(s.dot, sz.dot, '[animation-delay:300ms]')} />\n </span>\n <span className={showLabel ? s.label : 'sr-only'}>{text}</span>\n </span>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'TypingIndicator',\n group: 'Feedback',\n status: 'beta',\n description:\n 'Three pulsing dots shown while a reply is being written, with the text \"Assistant is typing\" for screen readers (or visible with `showLabel`). The dots are decorative and hold still under reduced motion. ChatMessage renders it while a streaming turn is still empty.',\n keyboard: [],\n tokens: ['muted-foreground'],\n};\n","/** \"840 ms\" below a second, \"2.4 s\" below a minute, \"1 m 05 s\" above. */\nexport function formatDuration(ms: number) {\n if (ms < 1000) return `${Math.round(ms)} ms`;\n if (ms < 60_000) return `${(ms / 1000).toFixed(1)} s`;\n const m = Math.floor(ms / 60_000);\n const s = Math.round((ms % 60_000) / 1000);\n return `${m} m ${String(s).padStart(2, '0')} s`;\n}\n\n/** Short local time (\"14:05\") for a message timestamp. */\nexport function formatTime(date: Date) {\n return date.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });\n}\n\n/** Pretty-prints any value as JSON; falls back to String() for cyclic or exotic values. */\nexport function toJson(value: unknown) {\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value, null, 2) ?? String(value);\n } catch {\n return String(value);\n }\n}\n","/** Slot classes for ChatMessage, per role. */\nexport const chatMessageStyles = {\n root: 'group/message relative flex gap-3 outline-none',\n avatar: 'mt-0.5 shrink-0',\n body: 'flex min-w-0 flex-1 flex-col gap-1',\n meta: 'flex items-baseline gap-2 text-[12px] leading-5',\n author: 'font-semibold text-foreground',\n time: 'font-mono text-[11px] text-muted-foreground',\n content: 'min-w-0 text-[14px] leading-[1.7] text-foreground',\n actions: [\n 'flex items-center gap-0.5 transition-opacity motion-reduce:transition-none',\n 'opacity-0 group-hover/message:opacity-100 group-focus-within/message:opacity-100 [@media(hover:none)]:opacity-100',\n ].join(' '),\n actionsVisible: 'opacity-100',\n /** @deprecated The empty streaming state renders TypingIndicator (see typingIndicatorStyles). */\n typing: 'inline-flex h-6 items-center gap-1',\n /** @deprecated See typingIndicatorStyles.dot. */\n typingDot: 'size-1.5 rounded-full bg-muted-foreground animate-pulse motion-reduce:animate-none',\n role: {\n user: {\n root: 'flex-row-reverse',\n body: 'items-end',\n meta: 'flex-row-reverse',\n content:\n 'max-w-[85%] rounded-2xl rounded-se-md bg-secondary px-4 py-2.5 whitespace-pre-wrap [overflow-wrap:anywhere]',\n },\n assistant: { root: '', body: '', meta: '', content: '' },\n participant: {\n root: '',\n body: 'items-start',\n meta: '',\n content:\n 'max-w-[85%] rounded-2xl rounded-ss-md border border-border bg-card px-4 py-2.5 whitespace-pre-wrap [overflow-wrap:anywhere]',\n },\n system: {\n root: 'justify-center',\n body: 'items-center',\n meta: 'sr-only',\n content:\n 'rounded-full border border-border bg-card px-3 py-1 text-center text-[12px] leading-5 text-muted-foreground',\n },\n tool: { root: '', body: '', meta: '', content: 'text-[13px]' },\n },\n} as const;\n","import { Avatar, IconButton, SimpleTooltip, cn, getInitials, useI18n, type MessageKey } from '@gntik-ai/ui';\nimport { Check, Copy, RotateCcw, Sparkles, ThumbsDown, ThumbsUp, Wrench } from 'lucide-react';\nimport { useId, type ReactNode, type Ref } from 'react';\nimport { TypingIndicator, streamingCaret } from '../TypingIndicator';\nimport { formatTime } from '../utils/format';\nimport { useCopy } from '../utils/useCopy';\nimport { chatMessageStyles as s } from './chatMessage.variants';\n\n/**\n * Who wrote a turn. `participant` is another person in the conversation (a teammate, an agent\n * handing over): not the current user and not the assistant.\n */\nexport type ChatRole = 'user' | 'assistant' | 'participant' | 'system' | 'tool';\nexport type ChatFeedback = 'up' | 'down' | null;\n\nexport interface ChatMessageProps {\n role: ChatRole;\n /** Display name; defaults per role (\"You\", \"Assistant\", \"Participant\", \"System\", \"Tool\"). Pass it for `participant`. */\n author?: string;\n /** Replaces the default avatar. Pass `null` to hide it. */\n avatar?: ReactNode;\n /** Image URL for the default avatar of `user` and `participant` turns (initials show while it loads or if it fails). */\n avatarSrc?: string;\n /** When the message was sent. A Date renders as a local short time. */\n timestamp?: Date | string;\n /** The body: a string, a <Markdown>, a ToolCallCard… */\n children?: ReactNode;\n /**\n * Text is still arriving: marks the message aria-busy, hides the actions, shows a\n * TypingIndicator while empty and a caret after plain-text children (a streaming\n * <Markdown> draws its own caret).\n */\n streaming?: boolean;\n /** Draw the caret after streamed plain-text children. Default true. */\n showCaret?: boolean;\n /** Plain text to copy; shows the Copy action. */\n copyText?: string;\n /** Shows the Retry action (assistant replies). */\n onRetry?: () => void;\n /** Current feedback (controlled). */\n feedback?: ChatFeedback;\n /** Shows the thumbs; called with the new value (clicking the active thumb clears it). */\n onFeedback?: (value: ChatFeedback) => void;\n /** Extra actions appended to the action group. */\n actions?: ReactNode;\n /** Keep the actions visible instead of revealing them on hover/focus. */\n alwaysShowActions?: boolean;\n className?: string;\n ref?: Ref<HTMLElement>;\n}\n\nconst DEFAULT_AUTHOR: Record<ChatRole, MessageKey> = {\n user: 'chat.you',\n assistant: 'chat.assistant',\n participant: 'chat.participant',\n system: 'chat.system',\n tool: 'chat.tool',\n};\n\nfunction DefaultAvatar({ role, author, src }: { role: ChatRole; author: string; src?: string }) {\n if (role === 'assistant') return <Avatar size=\"sm\" tone=\"primary\" fallback={<Sparkles size={15} aria-hidden />} />;\n if (role === 'tool') return <Avatar size=\"sm\" tone=\"secondary\" fallback={<Wrench size={14} aria-hidden />} />;\n // Decorative: the author name is already shown next to it.\n return (\n <Avatar size=\"sm\" tone={role === 'participant' ? 'accent' : 'secondary'} src={src} initials={getInitials(author)} />\n );\n}\n\n/**\n * One turn in a conversation. User turns are right-aligned bubbles, participant turns (another\n * person) are start-aligned outlined bubbles, assistant turns are full-width prose, system notes are centred pills and tool turns hold a ToolCallCard. Copy,\n * retry and feedback actions appear on hover or keyboard focus and are reachable with Tab.\n */\nexport function ChatMessage({\n role,\n author,\n avatar,\n avatarSrc,\n timestamp,\n children,\n streaming = false,\n showCaret = true,\n copyText,\n onRetry,\n feedback = null,\n onFeedback,\n actions,\n alwaysShowActions = false,\n className,\n ref,\n}: ChatMessageProps) {\n const id = useId();\n const { t } = useI18n();\n const name = author ?? t(DEFAULT_AUTHOR[role]);\n const v = s.role[role];\n const { copied, copy } = useCopy();\n const isEmpty = children === undefined || children === null || children === '';\n const time =\n timestamp instanceof Date ? (\n <time dateTime={timestamp.toISOString()} className={s.time}>\n {formatTime(timestamp)}\n </time>\n ) : timestamp ? (\n <span className={s.time}>{timestamp}</span>\n ) : null;\n const hasActions = !streaming && role !== 'system' && (copyText !== undefined || onRetry || onFeedback || actions);\n const showAvatar = role !== 'system' && avatar !== null;\n\n return (\n <article\n ref={ref}\n aria-labelledby={`${id}-author`}\n aria-busy={streaming || undefined}\n data-role={role}\n data-streaming={streaming || undefined}\n className={cn(s.root, v.root, className)}\n >\n {showAvatar && (\n <div className={s.avatar}>{avatar ?? <DefaultAvatar role={role} author={name} src={avatarSrc} />}</div>\n )}\n <div className={cn(s.body, v.body)}>\n <div className={cn(s.meta, v.meta)}>\n <span id={`${id}-author`} className={s.author}>\n {name}\n </span>\n {time}\n </div>\n <div className={cn(s.content, v.content)}>\n {streaming && isEmpty ? (\n <TypingIndicator author={name} />\n ) : streaming && showCaret && (typeof children === 'string' || typeof children === 'number') ? (\n <>\n {children}\n <span aria-hidden data-slot=\"streaming-caret\" className={streamingCaret} />\n </>\n ) : (\n children\n )}\n </div>\n {hasActions && (\n <div\n role=\"group\"\n aria-label={t('chat.actionsFor', { name })}\n className={cn(s.actions, alwaysShowActions && s.actionsVisible)}\n >\n {copyText !== undefined && (\n <SimpleTooltip content={copied ? t('common.copied') : t('common.copy')}>\n <IconButton\n size=\"sm\"\n icon={copied ? Check : Copy}\n label={copied ? t('common.copied') : t('chat.copyMessage')}\n onClick={() => void copy(copyText)}\n />\n </SimpleTooltip>\n )}\n {onRetry && (\n <SimpleTooltip content={t('common.retry')}>\n <IconButton size=\"sm\" icon={RotateCcw} label={t('common.retry')} onClick={onRetry} />\n </SimpleTooltip>\n )}\n {onFeedback && (\n <>\n <SimpleTooltip content={t('chat.goodResponse')}>\n <IconButton\n size=\"sm\"\n icon={ThumbsUp}\n label={t('chat.goodResponse')}\n aria-pressed={feedback === 'up'}\n className={cn(feedback === 'up' && 'text-primary-text')}\n onClick={() => onFeedback(feedback === 'up' ? null : 'up')}\n />\n </SimpleTooltip>\n <SimpleTooltip content={t('chat.badResponse')}>\n <IconButton\n size=\"sm\"\n icon={ThumbsDown}\n label={t('chat.badResponse')}\n aria-pressed={feedback === 'down'}\n className={cn(feedback === 'down' && 'text-destructive-text')}\n onClick={() => onFeedback(feedback === 'down' ? null : 'down')}\n />\n </SimpleTooltip>\n </>\n )}\n {actions}\n </div>\n )}\n </div>\n </article>\n );\n}\n","import { useI18n } from '@gntik-ai/ui';\n\nexport interface ChatAnnouncerProps {\n /** A reply is being generated. */\n streaming: boolean;\n /** Plain text of the latest completed reply (announced once, when streaming ends). */\n lastReply?: string;\n /** Who is replying, used in the \"is responding\" status. */\n author?: string;\n /** Max characters of the completed reply to announce. */\n maxLength?: number;\n}\n\n/**\n * Screen-reader strategy for streaming: the thread itself is not a live region (it would\n * re-announce every token). This single polite, atomic status says \"Assistant is responding…\"\n * when a stream starts and reads the finished reply once when it ends.\n */\nexport function ChatAnnouncer({ streaming, lastReply, author, maxLength = 600 }: ChatAnnouncerProps) {\n const { t } = useI18n();\n let text = '';\n if (streaming) text = t('chat.responding', { author: author ?? t('chat.assistant') });\n else if (lastReply) text = lastReply.length > maxLength ? `${lastReply.slice(0, maxLength)}…` : lastReply;\n return (\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {text}\n </div>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'ChatMessage',\n group: 'Display',\n status: 'beta',\n description:\n 'One conversation turn for the roles user (end-aligned bubble), participant (another person, e.g. a teammate: start-aligned outlined bubble with their name and avatar via `author` / `avatarSrc`), assistant, system and tool: avatar, author, timestamp, body and hover/focus actions (copy, retry, thumbs feedback). While streaming it is aria-busy, hides its actions and shows a TypingIndicator (\"Assistant is typing\") until text arrives and a caret after streamed plain text; ChatAnnouncer announces start and end once instead of every token.',\n pattern: 'article',\n keyboard: [\n ['Tab', 'Reaches each action in order (copy, retry, good, bad); focusing one reveals the action group'],\n ['Enter', 'Activates the focused action'],\n ['Space', 'Activates the focused action; thumbs toggle (aria-pressed)'],\n ],\n tokens: [\n 'foreground',\n 'muted-foreground',\n 'secondary',\n 'card',\n 'border',\n 'primary',\n 'primary-text',\n 'destructive-text',\n 'focus-ring',\n ],\n};\n","/** Slot classes for MessageFeedback. */\nexport const messageFeedbackStyles = {\n root: 'inline-flex items-center gap-0.5',\n up: 'text-primary-text',\n down: 'text-destructive-text',\n popup: 'w-80 max-w-[calc(100vw-2rem)]',\n form: 'flex flex-col gap-3',\n title: 'text-[13px] font-semibold text-foreground',\n label: 'mb-1.5 block text-[12.5px] font-medium text-foreground',\n footer: 'flex justify-end gap-2',\n} as const;\n","import {\n Button,\n IconButton,\n Popover,\n PopoverContent,\n PopoverTitle,\n PopoverTrigger,\n Radio,\n RadioGroup,\n SimpleTooltip,\n Textarea,\n cn,\n} from '@gntik-ai/ui';\nimport { Check, Copy, RefreshCw, ThumbsDown, ThumbsUp } from 'lucide-react';\nimport { useId, useState, type FormEvent, type Ref } from 'react';\nimport { useChatI18n, type ChatMessageKey } from '../utils/i18n';\nimport { useCopy } from '../utils/useCopy';\nimport { messageFeedbackStyles as s } from './messageFeedback.variants';\n\nexport type FeedbackRating = 'up' | 'down';\n\nexport interface FeedbackValue {\n /** `null` = no rating. */\n rating: FeedbackRating | null;\n /** Reason picked after a thumbs down (a `FeedbackReason.value`). */\n reason?: string;\n /** Free-text comment after a thumbs down. */\n comment?: string;\n}\n\nexport interface FeedbackReason {\n value: string;\n label: string;\n}\n\nexport interface MessageFeedbackProps {\n /** Current feedback (controlled). Uncontrolled when omitted. */\n value?: FeedbackValue;\n /**\n * Called on every change: `{ rating: 'up' }`, `{ rating: 'down' }` right away on thumbs down,\n * then `{ rating: 'down', reason, comment }` when the details form is sent, and\n * `{ rating: null }` when the active thumb is pressed again.\n */\n onFeedback?: (value: FeedbackValue) => void;\n /** Reasons offered after a thumbs down. Defaults to a generic list; `[]` hides the picker. */\n reasons?: FeedbackReason[];\n /** Open the reason/comment popover on thumbs down. Default true. */\n askDetails?: boolean;\n /** Plain text to copy; shows the Copy action. */\n copyText?: string;\n /** Shows the Regenerate action. */\n onRegenerate?: () => void;\n /** Accessible name of the group. Default \"Response feedback\". */\n label?: string;\n disabled?: boolean;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n}\n\nconst DEFAULT_REASONS: Array<{ value: string; key: ChatMessageKey }> = [\n { value: 'inaccurate', key: 'chat.reasonInaccurate' },\n { value: 'unhelpful', key: 'chat.reasonUnhelpful' },\n { value: 'incomplete', key: 'chat.reasonIncomplete' },\n { value: 'unsafe', key: 'chat.reasonUnsafe' },\n { value: 'other', key: 'chat.reasonOther' },\n];\n\nconst EMPTY: FeedbackValue = { rating: null };\n\n/**\n * Feedback for an assistant reply: thumbs up / down toggles (aria-pressed), and on thumbs down\n * a popover asking for a reason and an optional comment. Copy and Regenerate sit alongside.\n */\nexport function MessageFeedback({\n value: valueProp,\n onFeedback,\n reasons: reasonsProp,\n askDetails = true,\n copyText,\n onRegenerate,\n label,\n disabled = false,\n className,\n ref,\n}: MessageFeedbackProps) {\n const { t, tc } = useChatI18n();\n const id = useId();\n const [inner, setInner] = useState<FeedbackValue>(EMPTY);\n const value = valueProp ?? inner;\n const [open, setOpen] = useState(false);\n const [reason, setReason] = useState<string>('');\n const [comment, setComment] = useState('');\n const [announcement, setAnnouncement] = useState('');\n const { copied, copy } = useCopy();\n const reasons = reasonsProp ?? DEFAULT_REASONS.map((r) => ({ value: r.value, label: tc(r.key) }));\n\n const emit = (next: FeedbackValue) => {\n if (valueProp === undefined) setInner(next);\n onFeedback?.(next);\n };\n\n const pressUp = () => {\n setOpen(false);\n const next: FeedbackValue = value.rating === 'up' ? EMPTY : { rating: 'up' };\n emit(next);\n setAnnouncement(next.rating ? tc('chat.feedbackThanks') : tc('chat.feedbackCleared'));\n };\n\n const pressDown = () => {\n if (value.rating === 'down') {\n setOpen(false);\n emit(EMPTY);\n setAnnouncement(tc('chat.feedbackCleared'));\n return;\n }\n emit({ rating: 'down' });\n setReason('');\n setComment('');\n if (askDetails) setOpen(true);\n else setAnnouncement(tc('chat.feedbackThanks'));\n };\n\n const submit = (e: FormEvent) => {\n e.preventDefault();\n const trimmed = comment.trim();\n emit({ rating: 'down', ...(reason ? { reason } : {}), ...(trimmed ? { comment: trimmed } : {}) });\n setOpen(false);\n setAnnouncement(tc('chat.feedbackThanks'));\n };\n\n const upLabel = t('chat.goodResponse');\n const downLabel = t('chat.badResponse');\n\n return (\n <div ref={ref} role=\"group\" aria-label={label ?? tc('chat.feedback')} className={cn(s.root, className)}>\n {copyText !== undefined && (\n <SimpleTooltip content={copied ? t('common.copied') : t('common.copy')}>\n <IconButton\n size=\"sm\"\n icon={copied ? Check : Copy}\n label={copied ? t('common.copied') : t('chat.copyMessage')}\n disabled={disabled}\n onClick={() => void copy(copyText)}\n />\n </SimpleTooltip>\n )}\n {onRegenerate && (\n <SimpleTooltip content={tc('chat.regenerate')}>\n <IconButton\n size=\"sm\"\n icon={RefreshCw}\n label={tc('chat.regenerate')}\n disabled={disabled}\n onClick={onRegenerate}\n />\n </SimpleTooltip>\n )}\n <SimpleTooltip content={upLabel}>\n <IconButton\n size=\"sm\"\n icon={ThumbsUp}\n label={upLabel}\n aria-pressed={value.rating === 'up'}\n disabled={disabled}\n className={cn(value.rating === 'up' && s.up)}\n onClick={pressUp}\n />\n </SimpleTooltip>\n <Popover\n open={open}\n onOpenChange={(next) => {\n // Opening is driven by pressDown (so a second press clears instead of reopening).\n if (!next) setOpen(false);\n }}\n >\n <PopoverTrigger\n render={\n <IconButton\n size=\"sm\"\n icon={ThumbsDown}\n label={downLabel}\n aria-pressed={value.rating === 'down'}\n disabled={disabled}\n className={cn(value.rating === 'down' && s.down)}\n />\n }\n onClick={pressDown}\n />\n <PopoverContent side=\"top\" align=\"end\" className={s.popup}>\n <form className={s.form} onSubmit={submit}>\n <PopoverTitle id={`${id}-title`} className={s.title}>\n {tc('chat.feedbackTitle')}\n </PopoverTitle>\n {reasons.length > 0 && (\n <RadioGroup aria-labelledby={`${id}-title`} value={reason} onValueChange={(v) => setReason(String(v))}>\n {reasons.map((r) => (\n <Radio key={r.value} value={r.value} label={r.label} />\n ))}\n </RadioGroup>\n )}\n <div>\n <label htmlFor={`${id}-comment`} className={s.label}>\n {tc('chat.feedbackComment')}\n </label>\n <Textarea\n id={`${id}-comment`}\n rows={3}\n value={comment}\n onValueChange={setComment}\n placeholder={tc('chat.feedbackPlaceholder')}\n />\n </div>\n <div className={s.footer}>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => setOpen(false)}>\n {t('common.cancel')}\n </Button>\n <Button type=\"submit\" size=\"sm\">\n {tc('chat.feedbackSubmit')}\n </Button>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n <span role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {announcement}\n </span>\n </div>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'MessageFeedback',\n group: 'Actions',\n status: 'beta',\n description:\n 'Actions for an assistant reply: copy, regenerate and thumbs up / down toggles (aria-pressed). Thumbs down opens a popover with a reason picker and an optional comment. Controlled with `value` + `onFeedback`; pressing the active thumb clears it. A polite status confirms the feedback.',\n primitive: 'Popover',\n pattern: 'toggle button + dialog',\n keyboard: [\n ['Tab', 'Moves through copy, regenerate, good and bad'],\n ['Enter / Space', 'Toggles the focused thumb (aria-pressed); a second press clears it'],\n ['Enter / Space (on bad)', 'Also opens the details popover; focus moves into it'],\n ['Arrow keys', 'Inside the popover: move between reasons'],\n ['Escape', 'Closes the popover (the rating stays) and returns focus to the thumb'],\n ],\n tokens: ['muted-foreground', 'primary-text', 'destructive-text', 'popover', 'border', 'focus-ring'],\n};\n","/** Slot classes for ModelPicker. */\nexport const modelPickerStyles = {\n trigger: 'w-auto max-w-full min-w-0',\n compactTrigger:\n 'h-7 w-auto max-w-56 min-w-0 gap-1 border-transparent bg-transparent ps-2 pe-1.5 shadow-none hover:bg-secondary/70 hover:border-transparent',\n triggerValue: 'flex min-w-0 items-center gap-1.5',\n triggerIcon: 'shrink-0 text-muted-foreground',\n triggerName: 'truncate font-medium',\n triggerProvider: 'truncate text-muted-foreground',\n popup: 'w-80 max-w-[calc(100vw-2rem)]',\n item: 'items-start',\n itemBody: 'flex min-w-0 flex-col gap-1 py-0.5 whitespace-normal',\n itemName: 'font-medium text-foreground',\n itemDescription: 'text-[11.5px] leading-4 text-muted-foreground',\n badges: 'flex flex-wrap gap-1',\n reason: 'text-[11.5px] leading-4 text-muted-foreground italic',\n} as const;\n","import {\n Badge,\n Select,\n SelectContent,\n SelectGroup,\n SelectGroupLabel,\n SelectItem,\n SelectTrigger,\n cn,\n} from '@gntik-ai/ui';\nimport { Sparkles } from 'lucide-react';\nimport type { Ref } from 'react';\nimport { useChatI18n, type ChatMessageKey } from '../utils/i18n';\nimport { modelPickerStyles as s } from './modelPicker.variants';\n\nexport type ModelCapability = 'vision' | 'tools' | 'reasoning' | 'files' | 'web' | 'audio';\n\nexport interface ChatModel {\n /** Value reported by `onValueChange`. */\n id: string;\n name: string;\n /** Group heading, e.g. the provider or the deployment. Models are grouped in first-seen order. */\n provider: string;\n description?: string;\n capabilities?: ModelCapability[];\n /** Context window in tokens; shown as \"128K context\". */\n contextWindow?: number;\n disabled?: boolean;\n /** Why it is disabled (\"Needs an upgraded plan\"); shown under the name. */\n disabledReason?: string;\n}\n\nexport interface ModelPickerProps {\n models: ChatModel[];\n /** Selected model id (controlled). */\n value: string | null;\n onValueChange: (id: string) => void;\n /** Small borderless trigger with only the model name, for the composer toolbar. */\n compact?: boolean;\n /** Accessible name of the trigger. Default \"Model\". */\n label?: string;\n placeholder?: string;\n disabled?: boolean;\n /** Hide the provider next to the name in the full trigger. */\n hideProvider?: boolean;\n className?: string;\n ref?: Ref<HTMLButtonElement>;\n}\n\nconst CAPABILITY_KEY: Record<ModelCapability, ChatMessageKey> = {\n vision: 'chat.capabilityVision',\n tools: 'chat.capabilityTools',\n reasoning: 'chat.capabilityReasoning',\n files: 'chat.capabilityFiles',\n web: 'chat.capabilityWeb',\n audio: 'chat.capabilityAudio',\n};\n\n/** Models grouped by provider, keeping first-seen order. */\nexport function groupModels(models: ChatModel[]) {\n const groups = new Map<string, ChatModel[]>();\n for (const m of models) {\n const list = groups.get(m.provider);\n if (list) list.push(m);\n else groups.set(m.provider, [m]);\n }\n return [...groups.entries()].map(([provider, items]) => ({ provider, items }));\n}\n\n/**\n * Model / provider select for a chat: options grouped by provider with capability badges\n * (vision, tools, context size…) and disabled models that say why. `compact` renders a small\n * borderless trigger for the composer toolbar. Built on Select (Base UI).\n */\nexport function ModelPicker({\n models,\n value,\n onValueChange,\n compact = false,\n label,\n placeholder,\n disabled,\n hideProvider = false,\n className,\n ref,\n}: ModelPickerProps) {\n const { tc, formatNumber } = useChatI18n();\n const byId = new Map(models.map((m) => [m.id, m]));\n const items = models.map((m) => ({ value: m.id, label: m.name }));\n\n return (\n <Select<string>\n items={items}\n value={value}\n disabled={disabled}\n onValueChange={(next) => {\n if (next !== null) onValueChange(next);\n }}\n >\n <SelectTrigger\n ref={ref}\n size=\"sm\"\n aria-label={label ?? tc('chat.model')}\n placeholder={placeholder ?? tc('chat.selectModel')}\n className={cn(compact ? s.compactTrigger : s.trigger, className)}\n >\n {(id: string | null) => {\n const m = id === null ? undefined : byId.get(id);\n if (!m) return placeholder ?? tc('chat.selectModel');\n return (\n <span className={s.triggerValue}>\n <Sparkles size={13} aria-hidden className={s.triggerIcon} />\n <span className={s.triggerName}>{m.name}</span>\n {!compact && !hideProvider && <span className={s.triggerProvider}>· {m.provider}</span>}\n </span>\n );\n }}\n </SelectTrigger>\n <SelectContent className={s.popup} align={compact ? 'end' : 'start'}>\n {groupModels(models).map((g) => (\n <SelectGroup key={g.provider}>\n <SelectGroupLabel>{g.provider}</SelectGroupLabel>\n {g.items.map((m) => (\n <SelectItem key={m.id} value={m.id} disabled={m.disabled} label={m.name} className={s.item}>\n <span className={s.itemBody}>\n <span className={s.itemName}>{m.name}</span>\n {m.description && <span className={s.itemDescription}>{m.description}</span>}\n {(m.capabilities?.length || m.contextWindow) && (\n <span className={s.badges}>\n {m.capabilities?.map((c) => (\n <Badge key={c} size=\"sm\" tone=\"neutral\">\n {tc(CAPABILITY_KEY[c])}\n </Badge>\n ))}\n {m.contextWindow !== undefined && (\n <Badge size=\"sm\" tone=\"neutral\" variant=\"outline\">\n {tc('chat.contextWindow', {\n size: formatNumber(m.contextWindow, { notation: 'compact', maximumFractionDigits: 1 }),\n })}\n </Badge>\n )}\n </span>\n )}\n {m.disabled && <span className={s.reason}>{m.disabledReason ?? tc('chat.unavailable')}</span>}\n </span>\n </SelectItem>\n ))}\n </SelectGroup>\n ))}\n </SelectContent>\n </Select>\n );\n}\n","import type { ChatModel } from './ModelPicker';\n\n/** Generic, product-agnostic models for examples and the demo. */\nexport const DEMO_MODELS: ChatModel[] = [\n {\n id: 'swift',\n name: 'Swift',\n provider: 'Hosted',\n description: 'Fast answers for everyday questions.',\n capabilities: ['tools'],\n contextWindow: 128_000,\n },\n {\n id: 'balanced',\n name: 'Balanced',\n provider: 'Hosted',\n description: 'Good default for analysis and writing.',\n capabilities: ['vision', 'tools', 'files'],\n contextWindow: 200_000,\n },\n {\n id: 'deep',\n name: 'Deep reasoning',\n provider: 'Hosted',\n description: 'Plans multi-step work; slower.',\n capabilities: ['vision', 'tools', 'reasoning'],\n contextWindow: 1_000_000,\n disabled: true,\n disabledReason: 'Needs an upgraded plan',\n },\n {\n id: 'local-small',\n name: 'Local small',\n provider: 'Self-hosted',\n description: 'Runs in your own cluster.',\n contextWindow: 32_000,\n },\n {\n id: 'local-vision',\n name: 'Local vision',\n provider: 'Self-hosted',\n capabilities: ['vision'],\n contextWindow: 64_000,\n },\n];\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'ModelPicker',\n group: 'Forms',\n status: 'beta',\n description:\n 'Choose the model (and provider) for a conversation: options grouped by provider with a description, capability badges (vision, tools, reasoning, files, web, audio) and the context size; unavailable models stay listed, disabled, with the reason. `compact` gives a small borderless trigger for the ChatComposer toolbar. Controlled (`value` + `onValueChange`).',\n primitive: 'Select',\n pattern: 'select-only combobox',\n keyboard: [\n ['Enter / Space / ArrowDown', 'On the trigger: opens the list'],\n [\n 'ArrowDown / ArrowUp',\n 'Moves between models; a disabled one can be highlighted (its reason is read) but not selected',\n ],\n ['Type a character', 'Jumps to the model whose name starts with it'],\n ['Enter', 'Selects the highlighted model and closes'],\n ['Escape', 'Closes without changing; focus returns to the trigger'],\n ],\n tokens: ['background', 'popover', 'border', 'secondary', 'primary', 'primary-text', 'muted-foreground', 'focus-ring'],\n};\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseChatScrollOptions {\n /** Distance from the bottom (px) still treated as \"at the bottom\". */\n threshold?: number;\n}\n\nexport interface UseChatScrollResult {\n /** Callback ref for the scrolling element. */\n scrollRef: (el: HTMLElement | null) => void;\n /** Callback ref for the content inside it (watched for growth, e.g. streamed tokens). */\n contentRef: (el: HTMLElement | null) => void;\n /** True while the viewport is pinned to the latest message. */\n isAtBottom: boolean;\n /** Scrolls to the latest message and re-pins auto-scroll. */\n scrollToBottom: (behavior?: ScrollBehavior) => void;\n}\n\n/** Imperative DOM write kept outside the hook (state values must not be mutated in place). */\nfunction pinToBottom(el: HTMLElement) {\n el.scrollTop = el.scrollHeight;\n}\n\nfunction distanceFromBottom(el: HTMLElement) {\n return el.scrollHeight - el.scrollTop - el.clientHeight;\n}\n\n/**\n * Auto-scroll for a chat thread that respects the reader: new content keeps the view pinned\n * to the bottom only while the user is already there. Scrolling up unpins it (and\n * `isAtBottom` turns false, so a \"scroll to latest\" button can show); `scrollToBottom()`\n * pins it again.\n */\nexport function useChatScroll({ threshold = 48 }: UseChatScrollOptions = {}): UseChatScrollResult {\n const [scrollEl, setScrollEl] = useState<HTMLElement | null>(null);\n const [contentEl, setContentEl] = useState<HTMLElement | null>(null);\n const [isAtBottom, setIsAtBottom] = useState(true);\n const pinned = useRef(true);\n const lastTop = useRef(0);\n\n useEffect(() => {\n if (!scrollEl) return;\n lastTop.current = scrollEl.scrollTop;\n const onScroll = () => {\n const top = scrollEl.scrollTop;\n // Re-pin at the bottom; unpin only when the reader moves up (a smooth programmatic\n // scroll towards the bottom passes through \"not at bottom\" without unpinning).\n if (distanceFromBottom(scrollEl) <= threshold) pinned.current = true;\n else if (top < lastTop.current) pinned.current = false;\n lastTop.current = top;\n setIsAtBottom(pinned.current);\n };\n scrollEl.addEventListener('scroll', onScroll, { passive: true });\n return () => scrollEl.removeEventListener('scroll', onScroll);\n }, [scrollEl, threshold]);\n\n useEffect(() => {\n if (!scrollEl) return;\n const follow = () => {\n if (!pinned.current) return;\n pinToBottom(scrollEl);\n lastTop.current = scrollEl.scrollTop;\n };\n follow();\n const target = contentEl ?? scrollEl;\n const mo = new MutationObserver(follow);\n mo.observe(target, { childList: true, subtree: true, characterData: true });\n const ro = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(follow) : undefined;\n ro?.observe(target);\n return () => {\n mo.disconnect();\n ro?.disconnect();\n };\n }, [scrollEl, contentEl]);\n\n const scrollToBottom = useCallback(\n (behavior: ScrollBehavior = 'smooth') => {\n if (!scrollEl) return;\n pinned.current = true;\n setIsAtBottom(true);\n const reduce =\n typeof window.matchMedia === 'function' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n if (typeof scrollEl.scrollTo === 'function') {\n scrollEl.scrollTo({ top: scrollEl.scrollHeight, behavior: reduce ? 'auto' : behavior });\n } else {\n pinToBottom(scrollEl);\n }\n },\n [scrollEl],\n );\n\n return { scrollRef: setScrollEl, contentRef: setContentEl, isAtBottom, scrollToBottom };\n}\n","import { focusRing } from '../utils/focus';\n\n/** Slot classes for ChatLayout (plain strings: this package does not ship tailwind-variants). */\nexport const chatLayoutStyles = {\n root: 'flex h-full min-h-0 w-full bg-background text-foreground',\n thread: 'flex min-w-0 flex-1 flex-col',\n header: 'shrink-0 border-b border-border',\n viewport: 'relative min-h-0 flex-1',\n scroller: `h-full overflow-y-auto overscroll-contain ${focusRing} focus-visible:-outline-offset-2`,\n content: 'mx-auto flex w-full max-w-3xl flex-col gap-6 px-4 py-6 sm:px-6',\n jump: 'pointer-events-none absolute inset-x-0 bottom-3 flex justify-center',\n jumpButton: 'pointer-events-auto rounded-full shadow-md',\n composer: 'shrink-0 bg-background px-4 pb-4 pt-2 sm:px-6',\n composerInner: 'mx-auto w-full max-w-3xl',\n handle: [\n 'group relative w-1.5 shrink-0 cursor-col-resize touch-none bg-transparent',\n 'after:absolute after:inset-y-0 after:left-1/2 after:w-px after:-translate-x-1/2 after:bg-border',\n 'hover:after:w-0.5 hover:after:bg-primary/60 data-[dragging]:after:w-0.5 data-[dragging]:after:bg-primary',\n 'focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-focus-ring',\n ].join(' '),\n panel: 'flex min-h-0 shrink-0 flex-col overflow-hidden border-s border-border bg-card',\n} as const;\n","import { IconButton, cn, useI18n } from '@gntik-ai/ui';\nimport { ArrowDown } from 'lucide-react';\nimport { useRef, useState, type KeyboardEvent, type PointerEvent, type ReactNode, type Ref } from 'react';\nimport { useChatScroll } from '../useChatScroll';\nimport { chatLayoutStyles as s } from './chatLayout.variants';\n\nexport interface ChatLayoutProps {\n /** The messages (ChatMessage list, suggestions, …). */\n children?: ReactNode;\n /** Pinned at the bottom of the thread column, outside the scroll area (usually ChatComposer). */\n composer?: ReactNode;\n /** Optional header above the thread (title, model, actions). */\n header?: ReactNode;\n /** Optional side panel (artifact preview, details). Omit to hide it and its resize handle. */\n panel?: ReactNode;\n /** Accessible name of the side panel landmark. */\n panelLabel?: string;\n /** Initial panel width in px. */\n defaultPanelWidth?: number;\n minPanelWidth?: number;\n maxPanelWidth?: number;\n onPanelWidthChange?: (width: number) => void;\n /** Accessible name of the thread region. */\n label?: string;\n /** Label of the \"jump to latest\" button. */\n scrollButtonLabel?: string;\n /** Extra classes on the root. */\n className?: string;\n /** Extra classes on the centred content column. */\n contentClassName?: string;\n ref?: Ref<HTMLDivElement>;\n}\n\nconst clamp = (v: number, min: number, max: number) => Math.min(max, Math.max(min, v));\nconst isRtl = (el: Element) => getComputedStyle(el).direction === 'rtl';\n\n/**\n * Full-height chat frame: a scrollable thread with auto-scroll that respects scrolling up,\n * a \"jump to latest\" button, the composer pinned below, and an optional side panel that the\n * user can resize by dragging or with the arrow keys on its separator.\n */\nexport function ChatLayout({\n children,\n composer,\n header,\n panel,\n panelLabel: panelLabelProp,\n defaultPanelWidth = 380,\n minPanelWidth = 260,\n maxPanelWidth = 720,\n onPanelWidthChange,\n label: labelProp,\n scrollButtonLabel: scrollButtonLabelProp,\n className,\n contentClassName,\n ref,\n}: ChatLayoutProps) {\n const { t } = useI18n();\n const panelLabel = panelLabelProp ?? t('chat.details');\n const label = labelProp ?? t('chat.conversation');\n const scrollButtonLabel = scrollButtonLabelProp ?? t('chat.scrollToBottom');\n const { scrollRef, contentRef, isAtBottom, scrollToBottom } = useChatScroll();\n const [width, setWidth] = useState(() => clamp(defaultPanelWidth, minPanelWidth, maxPanelWidth));\n const [dragging, setDragging] = useState(false);\n const drag = useRef<{ x: number; width: number; sign: number } | null>(null);\n\n const resize = (next: number) => {\n const w = clamp(Math.round(next), minPanelWidth, maxPanelWidth);\n setWidth(w);\n onPanelWidthChange?.(w);\n };\n\n const onPointerDown = (e: PointerEvent<HTMLDivElement>) => {\n e.currentTarget.setPointerCapture?.(e.pointerId);\n drag.current = { x: e.clientX, width, sign: isRtl(e.currentTarget) ? -1 : 1 };\n setDragging(true);\n };\n const onPointerMove = (e: PointerEvent<HTMLDivElement>) => {\n if (!drag.current) return;\n // The panel sits on the inline end (right in LTR): dragging toward the thread widens it.\n resize(drag.current.width + (drag.current.x - e.clientX) * drag.current.sign);\n };\n const endDrag = () => {\n drag.current = null;\n setDragging(false);\n };\n const onHandleKey = (e: KeyboardEvent<HTMLDivElement>) => {\n const step = (e.shiftKey ? 64 : 16) * (isRtl(e.currentTarget) ? -1 : 1);\n const actions: Record<string, () => void> = {\n ArrowLeft: () => resize(width + step),\n ArrowRight: () => resize(width - step),\n Home: () => resize(maxPanelWidth),\n End: () => resize(minPanelWidth),\n };\n const action = actions[e.key];\n if (action) {\n e.preventDefault();\n action();\n }\n };\n\n return (\n <div ref={ref} className={cn(s.root, className)}>\n <section aria-label={label} className={s.thread}>\n {header && <div className={s.header}>{header}</div>}\n <div className={s.viewport}>\n <div ref={scrollRef} tabIndex={0} aria-label={t('chat.messages')} role=\"region\" className={s.scroller}>\n <div ref={contentRef} className={cn(s.content, contentClassName)}>\n {children}\n </div>\n </div>\n {!isAtBottom && (\n <div className={s.jump}>\n <IconButton\n icon={ArrowDown}\n label={scrollButtonLabel}\n variant=\"secondary\"\n size=\"sm\"\n className={s.jumpButton}\n onClick={() => scrollToBottom()}\n />\n </div>\n )}\n </div>\n {composer && (\n <div className={s.composer}>\n <div className={s.composerInner}>{composer}</div>\n </div>\n )}\n </section>\n {panel && (\n <>\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={t('chat.resizePanel', { panel: panelLabel.toLowerCase() })}\n aria-valuenow={width}\n aria-valuemin={minPanelWidth}\n aria-valuemax={maxPanelWidth}\n tabIndex={0}\n data-dragging={dragging || undefined}\n className={s.handle}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n onKeyDown={onHandleKey}\n />\n <aside aria-label={panelLabel} className={s.panel} style={{ width }}>\n {panel}\n </aside>\n </>\n )}\n </div>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'ChatLayout',\n group: 'Layout',\n status: 'beta',\n description:\n 'Full-height chat frame: scrollable thread with auto-scroll that respects scrolling up, a jump-to-latest button, a composer pinned below and an optional resizable side panel (artifact or details).',\n pattern: 'window splitter',\n keyboard: [\n ['Tab', 'Moves through the thread, the composer, the resize handle and the panel'],\n ['ArrowLeft', 'On the resize handle: widens the side panel (Shift for bigger steps)'],\n ['ArrowRight', 'On the resize handle: narrows the side panel'],\n ['Home', 'On the resize handle: panel to its maximum width'],\n ['End', 'On the resize handle: panel to its minimum width'],\n ],\n tokens: ['background', 'foreground', 'card', 'border', 'primary', 'focus-ring'],\n};\n","import { focusRing } from '../utils/focus';\n\n/** Slot classes for Citation and CitationList. */\nexport const citationStyles = {\n trigger: [\n 'mx-0.5 inline-flex h-[18px] min-w-[18px] -translate-y-px cursor-pointer items-center justify-center rounded-md px-1',\n 'bg-primary/14 align-baseline font-mono text-[10.5px] font-semibold leading-none text-primary-chip-text',\n `transition-colors hover:bg-primary/24 data-[popup-open]:bg-primary/24 motion-reduce:transition-none ${focusRing}`,\n ].join(' '),\n popup: 'w-80',\n head: 'flex items-center gap-2 text-[11.5px] text-muted-foreground',\n index:\n 'grid h-[18px] min-w-[18px] place-items-center rounded-md bg-secondary px-1 font-mono text-[10.5px] font-semibold text-foreground',\n title: 'mt-1.5 text-[13px] font-semibold leading-snug text-foreground',\n snippet: 'mt-1 line-clamp-4 text-[12.5px] leading-relaxed text-muted-foreground',\n open: `mt-2.5 inline-flex items-center gap-1 rounded-sm text-[12.5px] font-medium text-primary-text hover:underline ${focusRing}`,\n list: 'flex flex-col gap-1.5',\n heading: 'mb-1 text-[11.5px] font-semibold tracking-wide text-muted-foreground uppercase',\n item: 'flex gap-2.5 rounded-lg border border-border bg-card px-3 py-2.5',\n itemBody: 'min-w-0 flex-1',\n itemTitle: `rounded-sm text-[13px] font-medium text-foreground hover:text-primary-text hover:underline ${focusRing}`,\n itemHost: 'mt-0.5 truncate font-mono text-[11px] text-muted-foreground',\n} as const;\n","import { Popover, PopoverContent, PopoverDescription, PopoverTitle, PopoverTrigger, cn, useI18n } from '@gntik-ai/ui';\nimport { ExternalLink, Globe } from 'lucide-react';\nimport { useId, type ReactNode } from 'react';\nimport { citationStyles as s } from './citation.variants';\n\nexport interface CitationSource {\n /** Source title. */\n title: string;\n /** Where it lives; shown as its host name and linked. */\n url?: string;\n /** Short excerpt that supports the claim. */\n snippet?: string;\n /** Publisher or site name; defaults to the URL host. */\n publisher?: string;\n}\n\n/** Host name of a URL (\"docs.example.com\"), or undefined if it cannot be parsed. */\nexport function sourceHost(url?: string) {\n if (!url) return undefined;\n try {\n return new URL(url).host.replace(/^www\\./, '');\n } catch {\n return undefined;\n }\n}\n\n/** Only http(s) sources become links. */\nexport function safeSourceUrl(url?: string) {\n return url && /^https?:\\/\\//i.test(url) ? url : undefined;\n}\n\nexport interface CitationProps {\n /** 1-based number shown in the marker. */\n index: number;\n source: CitationSource;\n /** Hover delay before the preview opens (keyboard and click open it immediately). */\n delay?: number;\n className?: string;\n}\n\n/**\n * Inline numbered reference ([1]). Hovering, focusing + Enter or clicking opens a preview\n * card with the title, host, snippet and a link to the source.\n */\nexport function Citation({ index, source, delay = 200, className }: CitationProps) {\n const { t } = useI18n();\n const host = source.publisher ?? sourceHost(source.url);\n const href = safeSourceUrl(source.url);\n return (\n <Popover>\n <PopoverTrigger\n openOnHover\n delay={delay}\n aria-label={t('chat.source', { index, title: source.title })}\n className={cn(s.trigger, className)}\n >\n {index}\n </PopoverTrigger>\n <PopoverContent side=\"top\" align=\"start\" className={s.popup}>\n <div className={s.head}>\n <span className={s.index}>{index}</span>\n <Globe size={12} aria-hidden />\n {host && <span className=\"truncate\">{host}</span>}\n </div>\n <PopoverTitle className={s.title}>{source.title}</PopoverTitle>\n {source.snippet && <PopoverDescription className={s.snippet}>{source.snippet}</PopoverDescription>}\n {href && (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer nofollow\" className={s.open}>\n {t('chat.openSource')}\n <ExternalLink size={12} aria-hidden />\n <span className=\"sr-only\"> {t('link.external')}</span>\n </a>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n\nexport interface CitationListProps {\n sources: CitationSource[];\n /** Visible heading; also the list's accessible name. */\n heading?: ReactNode;\n className?: string;\n}\n\n/** Numbered list of the sources cited in a reply, matching the inline markers. */\nexport function CitationList({ sources, heading: headingProp, className }: CitationListProps) {\n const { t } = useI18n();\n const heading = headingProp ?? t('chat.sources');\n const headingId = useId();\n if (sources.length === 0) return null;\n return (\n <section aria-labelledby={headingId} className={className}>\n <h3 id={headingId} className={s.heading}>\n {heading}\n </h3>\n <ol className={s.list}>\n {sources.map((src, i) => {\n const href = safeSourceUrl(src.url);\n const host = src.publisher ?? sourceHost(src.url);\n return (\n <li key={`${i}-${src.title}`} className={s.item}>\n <span className={s.index} aria-hidden>\n {i + 1}\n </span>\n <div className={s.itemBody}>\n {href ? (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer nofollow\" className={s.itemTitle}>\n {src.title}\n <span className=\"sr-only\"> {t('link.external')}</span>\n </a>\n ) : (\n <span className=\"text-[13px] font-medium text-foreground\">{src.title}</span>\n )}\n {host && <div className={s.itemHost}>{host}</div>}\n </div>\n </li>\n );\n })}\n </ol>\n </section>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'Citation',\n group: 'Display',\n status: 'beta',\n description:\n 'Numbered source references for grounded answers: an inline [n] marker that previews the source (title, host, snippet, link) on hover, focus + Enter or click, and CitationList, the numbered list of sources under a reply. Only http(s) URLs become links.',\n primitive: '@base-ui/react/popover',\n pattern: 'dialog (non-modal)',\n keyboard: [\n ['Enter', 'On a marker: opens the source preview'],\n ['Space', 'On a marker: opens the source preview'],\n ['Escape', 'Closes the preview and returns focus to the marker'],\n ['Tab', 'Moves to the \"Open source\" link inside an open preview'],\n ],\n tokens: ['primary', 'primary-text', 'popover', 'secondary', 'card', 'border', 'muted-foreground', 'focus-ring'],\n};\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'Markdown',\n group: 'Display',\n status: 'beta',\n description:\n 'Safe, token-styled markdown for model output (react-markdown + remark-gfm): headings, lists, task lists, tables, blockquotes, inline and fenced code with a copy button, links with an external marker. Raw HTML is never rendered, unsafe URL schemes are stripped, and partial streamed input (unclosed fences) renders cleanly.',\n keyboard: [\n ['Tab', 'Moves through links and code-block copy buttons in reading order'],\n ['Enter', 'Follows a link or copies the focused code block'],\n ],\n tokens: ['foreground', 'muted-foreground', 'primary-text', 'secondary', 'border', 'focus-ring'],\n};\n","import { focusRing } from '../utils/focus';\n\n/** Slot classes for SuggestionChips. */\nexport const suggestionChipsStyles = {\n root: 'w-full',\n heading: 'mb-2.5 text-[12px] font-semibold tracking-wide text-muted-foreground uppercase',\n grid: 'grid gap-2 sm:grid-cols-2',\n row: 'flex flex-wrap gap-2',\n card: [\n 'group flex w-full cursor-pointer items-start gap-2.5 rounded-lg border border-border bg-card px-3.5 py-3 text-start shadow-sm',\n 'transition-colors hover:border-primary/40 hover:bg-secondary/40 motion-reduce:transition-none',\n 'disabled:pointer-events-none disabled:opacity-50',\n focusRing,\n ].join(' '),\n chip: [\n 'inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-full border border-border bg-card px-3 text-[12.5px] font-medium text-foreground',\n 'transition-colors hover:border-primary/40 hover:bg-secondary/40 motion-reduce:transition-none',\n 'disabled:pointer-events-none disabled:opacity-50',\n focusRing,\n ].join(' '),\n icon: 'mt-0.5 shrink-0 text-muted-foreground group-hover:text-primary-text',\n label: 'block text-[13px] font-medium text-foreground',\n description: 'mt-0.5 block text-[12px] leading-5 text-muted-foreground',\n} as const;\n","import { cn, useI18n } from '@gntik-ai/ui';\nimport { useId, type ComponentType, type ReactNode } from 'react';\nimport { suggestionChipsStyles as s } from './suggestionChips.variants';\n\ntype IconComponent = ComponentType<{ size?: number; className?: string; 'aria-hidden'?: boolean }>;\n\nexport interface Suggestion {\n /** Stable key; defaults to the label. */\n id?: string;\n /** Short title shown on the chip. */\n label: string;\n /** Second line (card layout only). */\n description?: string;\n /** Prompt sent when chosen; defaults to the label. */\n prompt?: string;\n icon?: IconComponent;\n}\n\nexport interface SuggestionChipsProps {\n suggestions: ReadonlyArray<Suggestion | string>;\n onSelect: (prompt: string, suggestion: Suggestion) => void;\n /** `cards` (two-column grid with descriptions) for an empty thread, `chips` (pills) for follow-ups. */\n layout?: 'cards' | 'chips';\n /** Heading above the group; also its accessible name. */\n heading?: ReactNode;\n /** Accessible name when there is no visible heading. */\n label?: string;\n disabled?: boolean;\n className?: string;\n}\n\nconst normalize = (x: Suggestion | string): Suggestion => (typeof x === 'string' ? { label: x } : x);\n\n/** Prompt suggestions for an empty conversation (cards) or as follow-ups after a reply (chips). */\nexport function SuggestionChips({\n suggestions,\n onSelect,\n layout = 'cards',\n heading,\n label: labelProp,\n disabled = false,\n className,\n}: SuggestionChipsProps) {\n const { t } = useI18n();\n const label = labelProp ?? t('chat.suggestions');\n const headingId = useId();\n const items = suggestions.map(normalize);\n return (\n <div\n role=\"group\"\n aria-labelledby={heading ? headingId : undefined}\n aria-label={heading ? undefined : label}\n className={cn(s.root, className)}\n >\n {heading && (\n <div id={headingId} className={s.heading}>\n {heading}\n </div>\n )}\n <div className={layout === 'cards' ? s.grid : s.row}>\n {items.map((item) => {\n const Icon = item.icon;\n const prompt = item.prompt ?? item.label;\n return (\n <button\n key={item.id ?? item.label}\n type=\"button\"\n disabled={disabled}\n className={layout === 'cards' ? s.card : s.chip}\n onClick={() => onSelect(prompt, item)}\n >\n {Icon && (\n <Icon\n size={layout === 'cards' ? 16 : 14}\n aria-hidden\n className={layout === 'cards' ? s.icon : 'shrink-0 text-muted-foreground'}\n />\n )}\n {layout === 'cards' ? (\n <span className=\"min-w-0\">\n <span className={s.label}>{item.label}</span>\n {item.description && <span className={s.description}>{item.description}</span>}\n </span>\n ) : (\n item.label\n )}\n </button>\n );\n })}\n </div>\n </div>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'SuggestionChips',\n group: 'Actions',\n status: 'beta',\n description:\n 'Prompt suggestions: a two-column grid of cards with descriptions for an empty conversation, or a row of pills for follow-ups after a reply. Choosing one calls onSelect with its prompt.',\n pattern: 'button group',\n keyboard: [\n ['Tab', 'Moves between suggestions'],\n ['Enter', 'Sends the focused suggestion'],\n ['Space', 'Sends the focused suggestion'],\n ],\n tokens: ['card', 'border', 'primary', 'primary-text', 'secondary', 'muted-foreground', 'focus-ring'],\n};\n","/** Slot classes for ToolCallCard and JsonView. */\nexport const toolCallCardStyles = {\n root: 'w-full overflow-hidden rounded-lg border border-border bg-card text-[13px]',\n trigger: [\n 'flex h-auto w-full min-w-0 justify-start gap-2.5 rounded-none px-3 py-2.5 text-start hover:bg-secondary/50',\n 'focus-visible:-outline-offset-2',\n ].join(' '),\n icon: 'grid size-6 shrink-0 place-items-center rounded-md bg-secondary text-muted-foreground',\n iconFailed: 'bg-destructive/15 text-destructive-chip-text',\n label: 'flex min-w-0 flex-1 items-baseline gap-1.5',\n verb: 'shrink-0 text-muted-foreground',\n name: 'truncate font-mono text-[12.5px] font-semibold text-foreground',\n meta: 'flex shrink-0 items-center gap-2',\n duration: 'font-mono text-[11px] text-muted-foreground tabular-nums',\n body: 'flex flex-col gap-2 border-t border-border px-3 pb-3 pt-1',\n error: 'rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-[12.5px] text-destructive-chip-text',\n json: {\n trigger: 'mx-0 h-7 px-1 text-[11.5px] font-semibold tracking-wide text-muted-foreground uppercase',\n content: 'pt-1',\n pre: 'max-h-64 overflow-auto rounded-md border border-border bg-secondary/40 p-2.5 font-mono text-[12px] leading-5 text-foreground',\n },\n} as const;\n","import { Collapsible, CollapsiblePanel, CollapsibleTrigger } from '@gntik-ai/ui';\nimport { toJson } from '../utils/format';\nimport { toolCallCardStyles } from './toolCallCard.variants';\n\nconst s = toolCallCardStyles.json;\n\nexport interface JsonViewProps {\n /** Section title (\"Arguments\", \"Result\"). */\n label: string;\n /** Any value: objects are pretty-printed, strings shown as-is. */\n value: unknown;\n defaultOpen?: boolean;\n}\n\n/** A small collapsible, scrollable JSON block. */\nexport function JsonView({ label, value, defaultOpen = true }: JsonViewProps) {\n return (\n <Collapsible defaultOpen={defaultOpen}>\n <CollapsibleTrigger className={s.trigger}>{label}</CollapsibleTrigger>\n <CollapsiblePanel className={s.content}>\n <pre tabIndex={0} aria-label={label} className={s.pre}>\n <code>{toJson(value)}</code>\n </pre>\n </CollapsiblePanel>\n </Collapsible>\n );\n}\n","import {\n Collapsible,\n CollapsiblePanel,\n CollapsibleTrigger,\n Spinner,\n StatusTag,\n cn,\n useI18n,\n type MessageKey,\n} from '@gntik-ai/ui';\nimport { CircleAlert, Wrench } from 'lucide-react';\nimport type { Ref } from 'react';\nimport { formatDuration } from '../utils/format';\nimport { JsonView } from './JsonView';\nimport { toolCallCardStyles as s } from './toolCallCard.variants';\n\nexport type ToolCallStatus = 'running' | 'succeeded' | 'failed';\n\nexport interface ToolCallCardProps {\n /** Tool / function name, e.g. \"search_invoices\". */\n name: string;\n status: ToolCallStatus;\n /** Elapsed time in ms. */\n durationMs?: number;\n /** Arguments the model passed. */\n args?: unknown;\n /** What the tool returned. */\n result?: unknown;\n /** Error message for a failed call. */\n error?: string;\n /** Start expanded. Failed calls open by default. */\n defaultOpen?: boolean;\n /** Controlled open state. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n}\n\nconst VERB: Record<ToolCallStatus, MessageKey> = {\n running: 'toolCall.calling',\n succeeded: 'toolCall.called',\n failed: 'toolCall.failed',\n};\n\n/**\n * A tool invocation inside an assistant turn: name, status, duration, and a collapsible body\n * with the arguments and the result (or error) as small JSON views.\n */\nexport function ToolCallCard({\n name,\n status,\n durationMs,\n args,\n result,\n error,\n defaultOpen,\n open,\n onOpenChange,\n className,\n ref,\n}: ToolCallCardProps) {\n const { t } = useI18n();\n const failed = status === 'failed';\n return (\n <Collapsible\n ref={ref}\n defaultOpen={defaultOpen ?? failed}\n open={open}\n onOpenChange={onOpenChange ? (o) => onOpenChange(o) : undefined}\n data-status={status}\n className={cn(s.root, className)}\n >\n <CollapsibleTrigger className={s.trigger}>\n <span className={cn(s.icon, failed && s.iconFailed)}>\n {status === 'running' ? (\n <Spinner size={13} />\n ) : failed ? (\n <CircleAlert size={13} aria-hidden />\n ) : (\n <Wrench size={13} aria-hidden />\n )}\n </span>\n <span className={s.label}>\n <span className={s.verb}>{t(VERB[status])}</span>\n <span className={s.name}>{name}</span>\n </span>\n <span className={s.meta}>\n {durationMs !== undefined && <span className={s.duration}>{formatDuration(durationMs)}</span>}\n <StatusTag status={status} size=\"sm\" />\n </span>\n </CollapsibleTrigger>\n <CollapsiblePanel className=\"pt-0\">\n <div className={s.body}>\n {args !== undefined && <JsonView label={t('toolCall.arguments')} value={args} />}\n {failed && error && (\n <p role=\"alert\" className={s.error}>\n {error}\n </p>\n )}\n {result !== undefined && <JsonView label={t('toolCall.result')} value={result} />}\n {status === 'running' && result === undefined && (\n <p className=\"text-[12.5px] text-muted-foreground\">{t('toolCall.waiting')}</p>\n )}\n </div>\n </CollapsiblePanel>\n </Collapsible>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'ToolCallCard',\n group: 'Display',\n status: 'beta',\n description:\n 'A tool invocation in an assistant turn: name, status (running, succeeded, failed), duration and a collapsible body with the arguments and the result or error as small collapsible JSON views. Failed calls open by default.',\n primitive: '@base-ui/react/collapsible',\n pattern: 'disclosure',\n keyboard: [\n ['Enter', 'Expands or collapses the card (or a JSON section)'],\n ['Space', 'Expands or collapses the card (or a JSON section)'],\n ['Tab', 'Moves to the JSON sections and their scrollable code'],\n ],\n tokens: [\n 'card',\n 'border',\n 'secondary',\n 'muted-foreground',\n 'success-text',\n 'destructive',\n 'destructive-text',\n 'focus-ring',\n ],\n};\n","import type { CitationSource } from '../Citation';\nimport type { Suggestion } from '../SuggestionChips';\n\n/** Fixtures for ChatDemo: generic workspace data, no product names. */\nexport const DEMO_SUGGESTIONS: Suggestion[] = [\n { label: 'Summarise deployments', description: 'What shipped this week across projects' },\n { label: 'Find unpaid invoices', description: 'Invoices still open from last month' },\n { label: 'Review member access', description: 'Who has admin rights' },\n { label: 'Explain a failed build', description: 'Likely cause and a fix' },\n];\n\nexport const DEMO_SOURCES: CitationSource[] = [\n {\n title: 'Deployment history · web-app',\n url: 'https://app.example.com/projects/web-app/deployments',\n snippet: '12 deployments in the last 7 days, 1 rolled back.',\n },\n {\n title: 'Rollback guide',\n url: 'https://docs.example.com/deployments/rollback',\n snippet: 'Roll back from the Deployments page or with the CLI.',\n },\n];\n\nexport const DEMO_TOOL = {\n name: 'list_deployments',\n args: { project: 'web-app', since: '7d' },\n result: { count: 12, succeeded: 11, rolledBack: 1, latest: 'v2.14.0' },\n durationMs: 640,\n};\n\nexport const DEMO_REPLY = `Here is the summary for **web-app** over the last 7 days:\n\n| Status | Count |\n| --- | --- |\n| Succeeded | 11 |\n| Rolled back | 1 |\n\nThe rollback was \\`v2.13.2\\`: a health check failed in one region, so traffic went back to the previous build.\n\nTo pin a release from the CLI:\n\n\\`\\`\\`bash\ndeploy pin --project web-app --version v2.14.0\n\\`\\`\\`\n\nSee the [rollback guide](https://docs.example.com/deployments/rollback) for the full steps.`;\n\n/** Splits text into small chunks to imitate token streaming. */\nexport function chunk(text: string, size = 6): string[] {\n const out: string[] = [];\n for (let i = 0; i < text.length; i += size) out.push(text.slice(i, i + size));\n return out;\n}\n","import { TooltipProvider, cn } from '@gntik-ai/ui';\nimport { useEffect, useRef, useState } from 'react';\nimport { AttachmentList, type ChatAttachment } from '../Attachment';\nimport { ChatAnnouncer, ChatMessage, type ChatRole } from '../ChatMessage';\nimport { ChatComposer } from '../ChatComposer';\nimport { MessageFeedback, type FeedbackValue } from '../MessageFeedback';\nimport { DEMO_MODELS, ModelPicker } from '../ModelPicker';\nimport { ChatLayout } from '../ChatLayout';\nimport { CitationList } from '../Citation';\nimport { Markdown } from '../Markdown';\nimport { SuggestionChips } from '../SuggestionChips';\nimport { ToolCallCard, type ToolCallStatus } from '../ToolCallCard';\nimport { DEMO_REPLY, DEMO_SOURCES, DEMO_SUGGESTIONS, DEMO_TOOL, chunk } from './demoScript';\n\ninterface DemoMessage {\n id: number;\n role: ChatRole;\n text: string;\n time: Date;\n streaming?: boolean;\n tool?: { status: ToolCallStatus; durationMs?: number };\n sources?: boolean;\n feedback?: FeedbackValue;\n attachments?: ChatAttachment[];\n}\n\nexport interface ChatDemoProps {\n /** Show the resizable details panel. */\n withPanel?: boolean;\n /** Milliseconds between streamed chunks. */\n tickMs?: number;\n className?: string;\n}\n\n/**\n * End-to-end example: suggestions, a user turn with attachments, a tool call, a streamed\n * markdown reply with sources, Stop, Regenerate and feedback, and a compact model picker. Streaming is mocked with timers that are cleared on\n * Stop and on unmount.\n */\nexport function ChatDemo({ withPanel = true, tickMs = 30, className }: ChatDemoProps) {\n const [messages, setMessages] = useState<DemoMessage[]>([]);\n const [streaming, setStreaming] = useState(false);\n const [model, setModel] = useState<string | null>('balanced');\n const [files, setFiles] = useState<ChatAttachment[]>([]);\n const nextId = useRef(1);\n const timers = useRef<Array<ReturnType<typeof setTimeout>>>([]);\n const objectUrls = useRef<string[]>([]);\n\n const clearTimers = () => {\n timers.current.forEach((t) => clearTimeout(t));\n timers.current = [];\n };\n useEffect(\n () => () => {\n clearTimers();\n objectUrls.current.forEach((u) => URL.revokeObjectURL(u));\n },\n [],\n );\n\n const attach = (picked: File[]) => {\n const added = picked.map((f): ChatAttachment => {\n let previewUrl: string | undefined;\n if (f.type.startsWith('image/') && typeof URL.createObjectURL === 'function') {\n previewUrl = URL.createObjectURL(f);\n objectUrls.current.push(previewUrl);\n }\n return { id: `file-${nextId.current++}`, name: f.name, size: f.size, type: f.type, previewUrl };\n });\n setFiles((all) => [...all, ...added]);\n };\n\n const patch = (id: number, fn: (m: DemoMessage) => DemoMessage) =>\n setMessages((ms) => ms.map((m) => (m.id === id ? fn(m) : m)));\n\n const respond = () => {\n clearTimers();\n const toolId = nextId.current++;\n const replyId = nextId.current++;\n const now = new Date();\n setStreaming(true);\n setMessages((ms) => [\n ...ms,\n { id: toolId, role: 'tool', text: '', time: now, tool: { status: 'running' } },\n { id: replyId, role: 'assistant', text: '', time: now, streaming: true },\n ]);\n const pieces = chunk(DEMO_REPLY);\n const startAt = DEMO_TOOL.durationMs;\n timers.current.push(\n setTimeout(\n () => patch(toolId, (m) => ({ ...m, tool: { status: 'succeeded', durationMs: DEMO_TOOL.durationMs } })),\n startAt,\n ),\n );\n pieces.forEach((piece, i) => {\n timers.current.push(\n setTimeout(() => patch(replyId, (m) => ({ ...m, text: m.text + piece })), startAt + (i + 1) * tickMs),\n );\n });\n timers.current.push(\n setTimeout(\n () => {\n patch(replyId, (m) => ({ ...m, streaming: false, sources: true }));\n setStreaming(false);\n },\n startAt + (pieces.length + 1) * tickMs,\n ),\n );\n };\n\n const send = (text: string, attachments: ChatAttachment[] = []) => {\n setMessages((ms) => [...ms, { id: nextId.current++, role: 'user', text, time: new Date(), attachments }]);\n setFiles([]);\n respond();\n };\n\n const stop = () => {\n clearTimers();\n setMessages((ms) =>\n ms.map((m) =>\n m.streaming\n ? { ...m, streaming: false }\n : m.tool?.status === 'running'\n ? { ...m, tool: { status: 'failed', durationMs: 0 } }\n : m,\n ),\n );\n setStreaming(false);\n };\n\n const retry = (id: number) => {\n setMessages((ms) => {\n const at = ms.findIndex((m) => m.id === id);\n // Drop the reply and the tool call that preceded it.\n const cut = at > 0 && ms[at - 1]?.role === 'tool' ? at - 1 : at;\n return ms.slice(0, cut);\n });\n respond();\n };\n\n const lastReply = [...messages].reverse().find((m) => m.role === 'assistant' && !m.streaming)?.text;\n\n return (\n <TooltipProvider>\n <div className={cn('h-[640px] overflow-hidden rounded-xl border border-border', className)}>\n <ChatLayout\n header={<div className=\"px-4 py-3 text-[13px] font-semibold text-foreground\">New conversation</div>}\n panel={\n withPanel ? (\n <div className=\"flex flex-col gap-4 p-4 text-[13px]\">\n <div>\n <h2 className=\"font-semibold text-foreground\">Details</h2>\n <p className=\"mt-1 text-muted-foreground\">\n Workspace assistant with read access to projects, deployments and invoices.\n </p>\n </div>\n <CitationList sources={DEMO_SOURCES} heading=\"Context sources\" />\n </div>\n ) : undefined\n }\n composer={\n <ChatComposer\n onSubmit={send}\n streaming={streaming}\n onStop={stop}\n maxLength={4000}\n attachments={files}\n onAttach={attach}\n onRemoveAttachment={(id) => setFiles((all) => all.filter((f) => f.id !== id))}\n accept=\".pdf,.csv,.md,.txt,.json,image/*\"\n maxSize={10_000_000}\n maxFiles={5}\n modelPicker={<ModelPicker compact models={DEMO_MODELS} value={model} onValueChange={setModel} />}\n />\n }\n >\n {messages.length === 0 && (\n <div className=\"flex flex-col gap-5 pt-10\">\n <h2 className=\"text-center text-[20px] font-semibold tracking-tight text-foreground\">How can I help?</h2>\n <SuggestionChips suggestions={DEMO_SUGGESTIONS} onSelect={(text) => send(text)} />\n </div>\n )}\n {messages.map((m) => {\n if (m.role === 'tool' && m.tool) {\n return (\n <ChatMessage key={m.id} role=\"tool\" author=\"Tool\" timestamp={m.time}>\n <ToolCallCard\n name={DEMO_TOOL.name}\n status={m.tool.status}\n durationMs={m.tool.durationMs}\n args={DEMO_TOOL.args}\n result={m.tool.status === 'succeeded' ? DEMO_TOOL.result : undefined}\n error={m.tool.status === 'failed' ? 'Stopped by the user.' : undefined}\n />\n </ChatMessage>\n );\n }\n if (m.role === 'assistant') {\n return (\n <ChatMessage\n key={m.id}\n role=\"assistant\"\n timestamp={m.time}\n streaming={m.streaming}\n alwaysShowActions={m.feedback?.rating === 'down'}\n actions={\n <MessageFeedback\n copyText={m.text}\n onRegenerate={streaming ? undefined : () => retry(m.id)}\n value={m.feedback ?? { rating: null }}\n onFeedback={(f) => patch(m.id, (x) => ({ ...x, feedback: f }))}\n />\n }\n >\n {m.text && <Markdown streaming={m.streaming}>{m.text}</Markdown>}\n {m.sources && <CitationList sources={DEMO_SOURCES} className=\"mt-3\" />}\n </ChatMessage>\n );\n }\n return (\n <ChatMessage key={m.id} role={m.role} timestamp={m.time}>\n {m.text}\n {m.attachments && m.attachments.length > 0 && (\n <AttachmentList attachments={m.attachments} variant=\"tile\" className=\"mt-2\" />\n )}\n </ChatMessage>\n );\n })}\n <ChatAnnouncer streaming={streaming} lastReply={lastReply} />\n </ChatLayout>\n </div>\n </TooltipProvider>\n );\n}\n","import type { ComponentDoc } from '@gntik-ai/ui';\n\nexport const doc: ComponentDoc = {\n name: 'ChatDemo',\n group: 'Layout',\n status: 'experimental',\n description:\n 'Reference composition of the chat pack: suggestions in the empty state, attachments (pick, paste or drop), a compact ModelPicker in the composer, a tool call, a streamed markdown reply with sources (TypingIndicator, caret), Stop, MessageFeedback (copy, regenerate, thumbs with reasons), and a resizable details panel. Streaming is mocked with timers that are cleaned up.',\n keyboard: [\n ['Enter', 'In the composer: sends; on a suggestion: sends it'],\n ['Escape', 'In the composer while streaming: stops the reply'],\n ],\n tokens: ['background', 'card', 'border', 'primary', 'focus-ring'],\n};\n"],"mappings":"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"}
|