@cognite/aura 1.46752.0 → 1.46768.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.
@@ -41,8 +41,8 @@ export function plainPreMarkup(code) {
41
41
  return `<pre><code>${escapeHtml(code)}</code></pre>`;
42
42
  }
43
43
  const CODE_BLOCK_EXPANDED_MAX_HEIGHT_CSS = 'min(60vh, 32rem)';
44
- const codeHtmlInnerClassName = 'dark:hidden [&>pre]:m-0 [&>pre]:min-h-10 [&>pre]:bg-card-background [&>pre]:p-2 [&>pre]:text-medium-foreground [&>pre]:leading-[18px] [&>pre]:tracking-[-0.08px] [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm [&>pre]:overflow-x-auto';
45
- const codeHtmlInnerDarkClassName = 'hidden dark:block [&>pre]:m-0 [&>pre]:min-h-10 [&>pre]:bg-card-background [&>pre]:p-2 [&>pre]:text-medium-foreground [&>pre]:leading-[18px] [&>pre]:tracking-[-0.08px] [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm [&>pre]:overflow-x-auto';
44
+ const codeHtmlInnerClassName = 'dark:hidden [&>pre]:m-0 [&>pre]:bg-card-background [&>pre]:p-2 [&>pre]:text-medium-foreground [&>pre]:leading-[18px] [&>pre]:tracking-[-0.08px] [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm [&>pre]:overflow-x-auto';
45
+ const codeHtmlInnerDarkClassName = 'hidden dark:block [&>pre]:m-0 [&>pre]:bg-card-background [&>pre]:p-2 [&>pre]:text-medium-foreground [&>pre]:leading-[18px] [&>pre]:tracking-[-0.08px] [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm [&>pre]:overflow-x-auto';
46
46
  const CodeBlock = /*#__PURE__*/ forwardRef(({ code, copyText, language, showLineNumbers = false, collapsed = false, className, children, style: styleFromProps, ...props }, ref)=>{
47
47
  const [html, setHtml] = useState('');
48
48
  const [darkHtml, setDarkHtml] = useState('');
@@ -121,17 +121,18 @@ const CodeBlock = /*#__PURE__*/ forwardRef(({ code, copyText, language, showLine
121
121
  isCollapsed,
122
122
  lineCount
123
123
  ]);
124
+ const preMinHeightClassName = children != null ? '[&>pre]:min-h-17' : '[&>pre]:min-h-10';
124
125
  const codeBody = /*#__PURE__*/ _jsxs("div", {
125
126
  className: "relative",
126
127
  children: [
127
128
  /*#__PURE__*/ _jsx("div", {
128
- className: cn(codeHtmlInnerClassName, showCollapsedChrome && 'max-h-26 overflow-y-hidden'),
129
+ className: cn(codeHtmlInnerClassName, preMinHeightClassName, showCollapsedChrome && 'max-h-26 overflow-y-hidden'),
129
130
  dangerouslySetInnerHTML: {
130
131
  __html: isStorybookTestEnv ? storybookMarkup : html
131
132
  }
132
133
  }),
133
134
  /*#__PURE__*/ _jsx("div", {
134
- className: cn(codeHtmlInnerDarkClassName, showCollapsedChrome && 'max-h-26 overflow-y-hidden'),
135
+ className: cn(codeHtmlInnerDarkClassName, preMinHeightClassName, showCollapsedChrome && 'max-h-26 overflow-y-hidden'),
135
136
  dangerouslySetInnerHTML: {
136
137
  __html: isStorybookTestEnv ? storybookMarkup : darkHtml
137
138
  }
@@ -143,7 +144,7 @@ const CodeBlock = /*#__PURE__*/ forwardRef(({ code, copyText, language, showLine
143
144
  });
144
145
  const actions = children != null ? /*#__PURE__*/ _jsx("div", {
145
146
  "data-slot": "code-block-actions",
146
- className: cn(/* Sibling of scroll inner: pinned while code scrolls; even inset from top/right (scrollbar gutter on inner) */ 'pointer-events-none absolute top-5 right-5 z-20 flex items-center gap-1 bg-transparent p-0 shadow-none ring-0 outline-none', 'opacity-0 transition-opacity', 'group-hover/code-block:pointer-events-auto group-hover/code-block:opacity-100', 'group-focus-within/code-block:pointer-events-auto group-focus-within/code-block:opacity-100', isStorybookTestEnv && 'pointer-events-auto opacity-100'),
147
+ className: cn(/* Sibling of scroll inner: pinned while code scrolls; right inset clears the scrollbar gutter on inner. Inner pre min-h-17 (68px) keeps top-5 + size-7 buttons (48px) plus a 20px bottom inset inside the root overflow-hidden on single-line blocks */ 'pointer-events-none absolute top-5 right-5 z-20 flex items-center gap-1 bg-transparent p-0 shadow-none ring-0 outline-none', 'opacity-0 transition-opacity', 'group-hover/code-block:pointer-events-auto group-hover/code-block:opacity-100', 'group-focus-within/code-block:pointer-events-auto group-focus-within/code-block:opacity-100', isStorybookTestEnv && 'pointer-events-auto opacity-100'),
147
148
  children: children
148
149
  }) : null;
149
150
  return /*#__PURE__*/ _jsx(CodeBlockContext.Provider, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/components/ui/core/code-block/code-block.tsx"],"sourcesContent":["/* eslint-disable @eslint-react/dom/no-dangerously-set-innerhtml */\nimport {\n type ComponentProps,\n type ComponentRef,\n type ForwardRefExoticComponent,\n type HTMLAttributes,\n type RefAttributes,\n createContext,\n forwardRef,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react';\n\nimport {\n IconCheck,\n IconCopy,\n IconDownload,\n IconSelector,\n} from '@tabler/icons-react';\n\nimport {\n highlightCode,\n type CodeLanguage,\n} from '../../../../lib/highlight-code';\nimport { cn, isStorybookTestEnv } from '../../../../lib/utils';\nimport { Button } from '../button/button';\n\ntype CodeBlockProps = HTMLAttributes<HTMLDivElement> & {\n code: string;\n copyText?: string;\n collapsed?: boolean;\n language: CodeLanguage;\n showLineNumbers?: boolean;\n};\n\ntype CodeBlockContextType = {\n code: string;\n copyText: string;\n isCollapsed: boolean;\n setIsCollapsed: (collapsed: boolean) => void;\n lineCount: number;\n};\n\nconst CodeBlockContext = createContext<CodeBlockContextType>({\n code: '',\n copyText: '',\n isCollapsed: false,\n setIsCollapsed: () => undefined,\n lineCount: 0,\n});\n\nconst escapeHtml = (value: string): string =>\n value\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#39;');\n\n/** Collapsed \"large\" preview: only this much is committed to the DOM (plain text, no Shiki spans). */\nconst PREVIEW_MAX_LINES = 14;\nconst PREVIEW_MAX_CHARS = 8_000;\n\n/** Beyond this size we do not run Shiki in expanded mode (plain &lt;pre&gt; only). */\nconst MAX_LINES_FULL_SHIKI = 400;\nconst MAX_CHARS_FULL_SHIKI = 16_384;\n\nconst CODE_BLOCK_COLLAPSIBLE_MIN_LINES = 1;\n\nexport function getCollapsedPreviewDisplay(code: string): string {\n const lines = code.split('\\n');\n let truncated = false;\n let slice = lines.slice(0, PREVIEW_MAX_LINES).join('\\n');\n if (lines.length > PREVIEW_MAX_LINES) {\n truncated = true;\n }\n if (slice.length > PREVIEW_MAX_CHARS) {\n slice = slice.slice(0, PREVIEW_MAX_CHARS);\n truncated = true;\n }\n const body = slice.length === 0 ? ' ' : slice;\n return truncated ? `${body}\\n…` : body;\n}\n\nexport function isContentLargerThanPreview(code: string): boolean {\n return (\n code.split('\\n').length > PREVIEW_MAX_LINES ||\n code.length > PREVIEW_MAX_CHARS\n );\n}\n\nexport function shouldUsePlainTextInsteadOfShiki(\n code: string,\n lineCount: number\n): boolean {\n return lineCount > MAX_LINES_FULL_SHIKI || code.length > MAX_CHARS_FULL_SHIKI;\n}\n\nexport function plainPreMarkup(code: string): string {\n return `<pre><code>${escapeHtml(code)}</code></pre>`;\n}\n\nconst CODE_BLOCK_EXPANDED_MAX_HEIGHT_CSS = 'min(60vh, 32rem)';\n\nconst codeHtmlInnerClassName =\n 'dark:hidden [&>pre]:m-0 [&>pre]:min-h-10 [&>pre]:bg-card-background [&>pre]:p-2 [&>pre]:text-medium-foreground [&>pre]:leading-[18px] [&>pre]:tracking-[-0.08px] [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm [&>pre]:overflow-x-auto';\n\nconst codeHtmlInnerDarkClassName =\n 'hidden dark:block [&>pre]:m-0 [&>pre]:min-h-10 [&>pre]:bg-card-background [&>pre]:p-2 [&>pre]:text-medium-foreground [&>pre]:leading-[18px] [&>pre]:tracking-[-0.08px] [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm [&>pre]:overflow-x-auto';\n\nconst CodeBlock: ForwardRefExoticComponent<\n HTMLAttributes<HTMLDivElement> & {\n code: string;\n copyText?: string;\n collapsed?: boolean;\n language: CodeLanguage;\n showLineNumbers?: boolean;\n } & RefAttributes<HTMLDivElement>\n> = forwardRef<ComponentRef<'div'>, CodeBlockProps>(\n (\n {\n code,\n copyText,\n language,\n showLineNumbers = false,\n collapsed = false,\n className,\n children,\n style: styleFromProps,\n ...props\n },\n ref\n ) => {\n const [html, setHtml] = useState<string>('');\n const [darkHtml, setDarkHtml] = useState<string>('');\n const [isCollapsed, setIsCollapsed] = useState(collapsed);\n\n const codeForRender = code.length === 0 ? ' ' : code;\n const lineCount = code.split('\\n').length;\n const isCollapsible = lineCount > CODE_BLOCK_COLLAPSIBLE_MIN_LINES;\n const showCollapsedChrome = isCollapsed && isCollapsible;\n const textToCopy = copyText ?? code;\n\n const storybookMarkup = useMemo(\n () =>\n isStorybookTestEnv\n ? `<pre><code>${escapeHtml(codeForRender)}</code></pre>`\n : '',\n [codeForRender]\n );\n\n useEffect(() => {\n if (isStorybookTestEnv) return;\n\n let isCancelled = false;\n\n const applyPlain = (source: string) => {\n if (!isCancelled) {\n const markup = plainPreMarkup(source);\n setHtml(markup);\n setDarkHtml(markup);\n }\n };\n\n // Collapsed + large: Shiki only on the truncated preview source (not the full blob).\n if (isCollapsed && isContentLargerThanPreview(codeForRender)) {\n const previewSource = getCollapsedPreviewDisplay(codeForRender);\n highlightCode(previewSource, language, showLineNumbers)\n .then(([light, dark]) => {\n if (!isCancelled) {\n setHtml(light);\n setDarkHtml(dark);\n }\n })\n .catch((error: unknown) => {\n console.error('Failed to highlight code:', error);\n applyPlain(previewSource);\n });\n return () => {\n isCancelled = true;\n };\n }\n\n // Expanded + very large: full plain text (no tokenized spans).\n if (\n !isCollapsed &&\n shouldUsePlainTextInsteadOfShiki(codeForRender, lineCount)\n ) {\n queueMicrotask(() => {\n applyPlain(codeForRender);\n });\n return () => {\n isCancelled = true;\n };\n }\n\n highlightCode(codeForRender, language, showLineNumbers)\n .then(([light, dark]) => {\n if (!isCancelled) {\n setHtml(light);\n setDarkHtml(dark);\n }\n })\n .catch((error: unknown) => {\n console.error('Failed to highlight code:', error);\n applyPlain(codeForRender);\n });\n\n return () => {\n isCancelled = true;\n };\n }, [codeForRender, language, showLineNumbers, isCollapsed, lineCount]);\n\n const contextValue = useMemo(\n () => ({\n code,\n copyText: textToCopy,\n isCollapsed,\n setIsCollapsed,\n lineCount,\n }),\n [code, textToCopy, isCollapsed, lineCount]\n );\n\n const codeBody = (\n <div className=\"relative\">\n <div\n className={cn(\n codeHtmlInnerClassName,\n showCollapsedChrome && 'max-h-26 overflow-y-hidden'\n )}\n dangerouslySetInnerHTML={{\n __html: isStorybookTestEnv ? storybookMarkup : html,\n }}\n />\n <div\n className={cn(\n codeHtmlInnerDarkClassName,\n showCollapsedChrome && 'max-h-26 overflow-y-hidden'\n )}\n dangerouslySetInnerHTML={{\n __html: isStorybookTestEnv ? storybookMarkup : darkHtml,\n }}\n />\n {showCollapsedChrome && (\n <div className=\"pointer-events-none absolute bottom-0 left-0 right-0 h-3/4 bg-linear-to-b from-transparent via-card-background/70 to-card-background\" />\n )}\n </div>\n );\n\n const actions =\n children != null ? (\n <div\n data-slot=\"code-block-actions\"\n className={cn(\n /* Sibling of scroll inner: pinned while code scrolls; even inset from top/right (scrollbar gutter on inner) */\n 'pointer-events-none absolute top-5 right-5 z-20 flex items-center gap-1 bg-transparent p-0 shadow-none ring-0 outline-none',\n 'opacity-0 transition-opacity',\n 'group-hover/code-block:pointer-events-auto group-hover/code-block:opacity-100',\n 'group-focus-within/code-block:pointer-events-auto group-focus-within/code-block:opacity-100',\n isStorybookTestEnv && 'pointer-events-auto opacity-100'\n )}\n >\n {children}\n </div>\n ) : null;\n\n return (\n <CodeBlockContext.Provider value={contextValue}>\n <div\n ref={ref}\n data-slot=\"code-block\"\n className={cn(\n 'group/code-block relative w-full rounded-xl bg-card-background text-medium-foreground',\n showCollapsedChrome\n ? 'overflow-hidden'\n : /* Expanded: flex + clip so actions overlay without a reserved top row */\n 'flex min-h-0 max-h-[min(60vh,_32rem)] flex-col overflow-hidden',\n className\n )}\n style={{\n ...(!showCollapsedChrome\n ? {\n maxHeight: CODE_BLOCK_EXPANDED_MAX_HEIGHT_CSS,\n minHeight: 0,\n }\n : {}),\n ...styleFromProps,\n }}\n {...props}\n >\n <div\n className={cn(\n /* Match <pre> card tone so transparent actions are not over root bg-background */\n 'relative min-h-0 bg-card-background',\n !showCollapsedChrome &&\n 'min-h-0 flex-1 overflow-x-auto overflow-y-auto [scrollbar-gutter:stable]'\n )}\n >\n {codeBody}\n </div>\n {actions}\n </div>\n </CodeBlockContext.Provider>\n );\n }\n);\nCodeBlock.displayName = 'CodeBlock';\n\ntype CodeBlockCopyButtonProps = ComponentProps<typeof Button> & {\n onCopy?: () => void;\n onError?: (error: Error) => void;\n timeout?: number;\n};\n\nconst CodeBlockCopyButton: ForwardRefExoticComponent<\n Omit<CodeBlockCopyButtonProps, 'ref'> & RefAttributes<HTMLElement>\n> = forwardRef<ComponentRef<typeof Button>, CodeBlockCopyButtonProps>(\n ({ onCopy, onError, timeout = 2000, children, className, ...props }, ref) => {\n const [isCopied, setIsCopied] = useState(false);\n const { copyText } = useContext(CodeBlockContext);\n\n const copyToClipboard = async () => {\n if (typeof window === 'undefined' || !navigator?.clipboard?.writeText) {\n onError?.(new Error('Clipboard API not available'));\n return;\n }\n\n try {\n await navigator.clipboard.writeText(copyText);\n setIsCopied(true);\n onCopy?.();\n setTimeout(() => setIsCopied(false), timeout);\n } catch (error: unknown) {\n console.warn('Clipboard write failed:', error);\n onError?.(\n error instanceof Error ? error : new Error('Clipboard write failed')\n );\n }\n };\n\n const Icon = isCopied ? IconCheck : IconCopy;\n\n return (\n <Button\n ref={ref}\n data-slot=\"code-block-copy-button\"\n className={cn('shrink-0', className)}\n onClick={copyToClipboard}\n size=\"icon-sm\"\n variant=\"secondary\"\n {...props}\n >\n {children ?? <Icon size={14} />}\n </Button>\n );\n }\n);\nCodeBlockCopyButton.displayName = 'CodeBlockCopyButton';\n\ntype CodeBlockCollapseButtonProps = ComponentProps<typeof Button>;\n\nconst CodeBlockCollapseButton: ForwardRefExoticComponent<\n Omit<ComponentProps<typeof Button>, 'ref'> & RefAttributes<HTMLElement>\n> = forwardRef<ComponentRef<typeof Button>, CodeBlockCollapseButtonProps>(\n ({ children, className, ...props }, ref) => {\n const { isCollapsed, setIsCollapsed, lineCount } =\n useContext(CodeBlockContext);\n\n if (lineCount <= CODE_BLOCK_COLLAPSIBLE_MIN_LINES) {\n return null;\n }\n\n return (\n <Button\n ref={ref}\n data-slot=\"code-block-collapse-button\"\n className={cn('shrink-0', className)}\n onClick={() => setIsCollapsed(!isCollapsed)}\n size=\"icon-sm\"\n variant=\"secondary\"\n {...props}\n >\n {children ?? <IconSelector size={14} />}\n </Button>\n );\n }\n);\nCodeBlockCollapseButton.displayName = 'CodeBlockCollapseButton';\n\ntype CodeBlockDownloadButtonProps = ComponentProps<typeof Button> & {\n fileName?: string;\n mimeType?: string;\n onDownload?: () => void;\n onError?: (error: Error) => void;\n};\n\nconst CodeBlockDownloadButton: ForwardRefExoticComponent<\n Omit<CodeBlockDownloadButtonProps, 'ref'> & RefAttributes<HTMLElement>\n> = forwardRef<ComponentRef<typeof Button>, CodeBlockDownloadButtonProps>(\n (\n {\n fileName = 'code.txt',\n mimeType = 'text/plain;charset=utf-8',\n onDownload,\n onError,\n children,\n className,\n ...props\n },\n ref\n ) => {\n const { code } = useContext(CodeBlockContext);\n\n const download = () => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n onError?.(new Error('Download not available'));\n return;\n }\n\n try {\n const blob = new Blob([code], { type: mimeType });\n const url = URL.createObjectURL(blob);\n\n const a = document.createElement('a');\n a.href = url;\n a.download = fileName;\n a.rel = 'noopener';\n a.click();\n\n URL.revokeObjectURL(url);\n onDownload?.();\n } catch (error: unknown) {\n onError?.(\n error instanceof Error ? error : new Error('Download failed')\n );\n }\n };\n\n return (\n <Button\n ref={ref}\n data-slot=\"code-block-download-button\"\n className={cn('shrink-0', className)}\n onClick={download}\n size=\"icon-sm\"\n variant=\"secondary\"\n {...props}\n >\n {children ?? <IconDownload size={14} />}\n </Button>\n );\n }\n);\nCodeBlockDownloadButton.displayName = 'CodeBlockDownloadButton';\n\nexport {\n CodeBlock,\n CodeBlockCollapseButton,\n CodeBlockCopyButton,\n CodeBlockDownloadButton,\n};\n"],"names":["createContext","forwardRef","useContext","useEffect","useMemo","useState","IconCheck","IconCopy","IconDownload","IconSelector","highlightCode","cn","isStorybookTestEnv","Button","CodeBlockContext","code","copyText","isCollapsed","setIsCollapsed","undefined","lineCount","escapeHtml","value","replaceAll","PREVIEW_MAX_LINES","PREVIEW_MAX_CHARS","MAX_LINES_FULL_SHIKI","MAX_CHARS_FULL_SHIKI","CODE_BLOCK_COLLAPSIBLE_MIN_LINES","getCollapsedPreviewDisplay","lines","split","truncated","slice","join","length","body","isContentLargerThanPreview","shouldUsePlainTextInsteadOfShiki","plainPreMarkup","CODE_BLOCK_EXPANDED_MAX_HEIGHT_CSS","codeHtmlInnerClassName","codeHtmlInnerDarkClassName","CodeBlock","language","showLineNumbers","collapsed","className","children","style","styleFromProps","props","ref","html","setHtml","darkHtml","setDarkHtml","codeForRender","isCollapsible","showCollapsedChrome","textToCopy","storybookMarkup","isCancelled","applyPlain","source","markup","previewSource","then","light","dark","catch","error","console","queueMicrotask","contextValue","codeBody","div","dangerouslySetInnerHTML","__html","actions","data-slot","Provider","maxHeight","minHeight","displayName","CodeBlockCopyButton","onCopy","onError","timeout","isCopied","setIsCopied","copyToClipboard","window","navigator","clipboard","writeText","Error","setTimeout","warn","Icon","onClick","size","variant","CodeBlockCollapseButton","CodeBlockDownloadButton","fileName","mimeType","onDownload","download","document","blob","Blob","type","url","URL","createObjectURL","a","createElement","href","rel","click","revokeObjectURL"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/components/ui/core/code-block/code-block.tsx"],"sourcesContent":["/* eslint-disable @eslint-react/dom/no-dangerously-set-innerhtml */\nimport {\n type ComponentProps,\n type ComponentRef,\n type ForwardRefExoticComponent,\n type HTMLAttributes,\n type RefAttributes,\n createContext,\n forwardRef,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react';\n\nimport {\n IconCheck,\n IconCopy,\n IconDownload,\n IconSelector,\n} from '@tabler/icons-react';\n\nimport {\n highlightCode,\n type CodeLanguage,\n} from '../../../../lib/highlight-code';\nimport { cn, isStorybookTestEnv } from '../../../../lib/utils';\nimport { Button } from '../button/button';\n\ntype CodeBlockProps = HTMLAttributes<HTMLDivElement> & {\n code: string;\n copyText?: string;\n collapsed?: boolean;\n language: CodeLanguage;\n showLineNumbers?: boolean;\n};\n\ntype CodeBlockContextType = {\n code: string;\n copyText: string;\n isCollapsed: boolean;\n setIsCollapsed: (collapsed: boolean) => void;\n lineCount: number;\n};\n\nconst CodeBlockContext = createContext<CodeBlockContextType>({\n code: '',\n copyText: '',\n isCollapsed: false,\n setIsCollapsed: () => undefined,\n lineCount: 0,\n});\n\nconst escapeHtml = (value: string): string =>\n value\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#39;');\n\n/** Collapsed \"large\" preview: only this much is committed to the DOM (plain text, no Shiki spans). */\nconst PREVIEW_MAX_LINES = 14;\nconst PREVIEW_MAX_CHARS = 8_000;\n\n/** Beyond this size we do not run Shiki in expanded mode (plain &lt;pre&gt; only). */\nconst MAX_LINES_FULL_SHIKI = 400;\nconst MAX_CHARS_FULL_SHIKI = 16_384;\n\nconst CODE_BLOCK_COLLAPSIBLE_MIN_LINES = 1;\n\nexport function getCollapsedPreviewDisplay(code: string): string {\n const lines = code.split('\\n');\n let truncated = false;\n let slice = lines.slice(0, PREVIEW_MAX_LINES).join('\\n');\n if (lines.length > PREVIEW_MAX_LINES) {\n truncated = true;\n }\n if (slice.length > PREVIEW_MAX_CHARS) {\n slice = slice.slice(0, PREVIEW_MAX_CHARS);\n truncated = true;\n }\n const body = slice.length === 0 ? ' ' : slice;\n return truncated ? `${body}\\n…` : body;\n}\n\nexport function isContentLargerThanPreview(code: string): boolean {\n return (\n code.split('\\n').length > PREVIEW_MAX_LINES ||\n code.length > PREVIEW_MAX_CHARS\n );\n}\n\nexport function shouldUsePlainTextInsteadOfShiki(\n code: string,\n lineCount: number\n): boolean {\n return lineCount > MAX_LINES_FULL_SHIKI || code.length > MAX_CHARS_FULL_SHIKI;\n}\n\nexport function plainPreMarkup(code: string): string {\n return `<pre><code>${escapeHtml(code)}</code></pre>`;\n}\n\nconst CODE_BLOCK_EXPANDED_MAX_HEIGHT_CSS = 'min(60vh, 32rem)';\n\nconst codeHtmlInnerClassName =\n 'dark:hidden [&>pre]:m-0 [&>pre]:bg-card-background [&>pre]:p-2 [&>pre]:text-medium-foreground [&>pre]:leading-[18px] [&>pre]:tracking-[-0.08px] [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm [&>pre]:overflow-x-auto';\n\nconst codeHtmlInnerDarkClassName =\n 'hidden dark:block [&>pre]:m-0 [&>pre]:bg-card-background [&>pre]:p-2 [&>pre]:text-medium-foreground [&>pre]:leading-[18px] [&>pre]:tracking-[-0.08px] [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm [&>pre]:overflow-x-auto';\n\nconst CodeBlock: ForwardRefExoticComponent<\n HTMLAttributes<HTMLDivElement> & {\n code: string;\n copyText?: string;\n collapsed?: boolean;\n language: CodeLanguage;\n showLineNumbers?: boolean;\n } & RefAttributes<HTMLDivElement>\n> = forwardRef<ComponentRef<'div'>, CodeBlockProps>(\n (\n {\n code,\n copyText,\n language,\n showLineNumbers = false,\n collapsed = false,\n className,\n children,\n style: styleFromProps,\n ...props\n },\n ref\n ) => {\n const [html, setHtml] = useState<string>('');\n const [darkHtml, setDarkHtml] = useState<string>('');\n const [isCollapsed, setIsCollapsed] = useState(collapsed);\n\n const codeForRender = code.length === 0 ? ' ' : code;\n const lineCount = code.split('\\n').length;\n const isCollapsible = lineCount > CODE_BLOCK_COLLAPSIBLE_MIN_LINES;\n const showCollapsedChrome = isCollapsed && isCollapsible;\n const textToCopy = copyText ?? code;\n\n const storybookMarkup = useMemo(\n () =>\n isStorybookTestEnv\n ? `<pre><code>${escapeHtml(codeForRender)}</code></pre>`\n : '',\n [codeForRender]\n );\n\n useEffect(() => {\n if (isStorybookTestEnv) return;\n\n let isCancelled = false;\n\n const applyPlain = (source: string) => {\n if (!isCancelled) {\n const markup = plainPreMarkup(source);\n setHtml(markup);\n setDarkHtml(markup);\n }\n };\n\n // Collapsed + large: Shiki only on the truncated preview source (not the full blob).\n if (isCollapsed && isContentLargerThanPreview(codeForRender)) {\n const previewSource = getCollapsedPreviewDisplay(codeForRender);\n highlightCode(previewSource, language, showLineNumbers)\n .then(([light, dark]) => {\n if (!isCancelled) {\n setHtml(light);\n setDarkHtml(dark);\n }\n })\n .catch((error: unknown) => {\n console.error('Failed to highlight code:', error);\n applyPlain(previewSource);\n });\n return () => {\n isCancelled = true;\n };\n }\n\n // Expanded + very large: full plain text (no tokenized spans).\n if (\n !isCollapsed &&\n shouldUsePlainTextInsteadOfShiki(codeForRender, lineCount)\n ) {\n queueMicrotask(() => {\n applyPlain(codeForRender);\n });\n return () => {\n isCancelled = true;\n };\n }\n\n highlightCode(codeForRender, language, showLineNumbers)\n .then(([light, dark]) => {\n if (!isCancelled) {\n setHtml(light);\n setDarkHtml(dark);\n }\n })\n .catch((error: unknown) => {\n console.error('Failed to highlight code:', error);\n applyPlain(codeForRender);\n });\n\n return () => {\n isCancelled = true;\n };\n }, [codeForRender, language, showLineNumbers, isCollapsed, lineCount]);\n\n const contextValue = useMemo(\n () => ({\n code,\n copyText: textToCopy,\n isCollapsed,\n setIsCollapsed,\n lineCount,\n }),\n [code, textToCopy, isCollapsed, lineCount]\n );\n\n const preMinHeightClassName =\n children != null ? '[&>pre]:min-h-17' : '[&>pre]:min-h-10';\n\n const codeBody = (\n <div className=\"relative\">\n <div\n className={cn(\n codeHtmlInnerClassName,\n preMinHeightClassName,\n showCollapsedChrome && 'max-h-26 overflow-y-hidden'\n )}\n dangerouslySetInnerHTML={{\n __html: isStorybookTestEnv ? storybookMarkup : html,\n }}\n />\n <div\n className={cn(\n codeHtmlInnerDarkClassName,\n preMinHeightClassName,\n showCollapsedChrome && 'max-h-26 overflow-y-hidden'\n )}\n dangerouslySetInnerHTML={{\n __html: isStorybookTestEnv ? storybookMarkup : darkHtml,\n }}\n />\n {showCollapsedChrome && (\n <div className=\"pointer-events-none absolute bottom-0 left-0 right-0 h-3/4 bg-linear-to-b from-transparent via-card-background/70 to-card-background\" />\n )}\n </div>\n );\n\n const actions =\n children != null ? (\n <div\n data-slot=\"code-block-actions\"\n className={cn(\n /* Sibling of scroll inner: pinned while code scrolls; right inset clears the scrollbar gutter on inner. Inner pre min-h-17 (68px) keeps top-5 + size-7 buttons (48px) plus a 20px bottom inset inside the root overflow-hidden on single-line blocks */\n 'pointer-events-none absolute top-5 right-5 z-20 flex items-center gap-1 bg-transparent p-0 shadow-none ring-0 outline-none',\n 'opacity-0 transition-opacity',\n 'group-hover/code-block:pointer-events-auto group-hover/code-block:opacity-100',\n 'group-focus-within/code-block:pointer-events-auto group-focus-within/code-block:opacity-100',\n isStorybookTestEnv && 'pointer-events-auto opacity-100'\n )}\n >\n {children}\n </div>\n ) : null;\n\n return (\n <CodeBlockContext.Provider value={contextValue}>\n <div\n ref={ref}\n data-slot=\"code-block\"\n className={cn(\n 'group/code-block relative w-full rounded-xl bg-card-background text-medium-foreground',\n showCollapsedChrome\n ? 'overflow-hidden'\n : /* Expanded: flex + clip so actions overlay without a reserved top row */\n 'flex min-h-0 max-h-[min(60vh,_32rem)] flex-col overflow-hidden',\n className\n )}\n style={{\n ...(!showCollapsedChrome\n ? {\n maxHeight: CODE_BLOCK_EXPANDED_MAX_HEIGHT_CSS,\n minHeight: 0,\n }\n : {}),\n ...styleFromProps,\n }}\n {...props}\n >\n <div\n className={cn(\n /* Match <pre> card tone so transparent actions are not over root bg-background */\n 'relative min-h-0 bg-card-background',\n !showCollapsedChrome &&\n 'min-h-0 flex-1 overflow-x-auto overflow-y-auto [scrollbar-gutter:stable]'\n )}\n >\n {codeBody}\n </div>\n {actions}\n </div>\n </CodeBlockContext.Provider>\n );\n }\n);\nCodeBlock.displayName = 'CodeBlock';\n\ntype CodeBlockCopyButtonProps = ComponentProps<typeof Button> & {\n onCopy?: () => void;\n onError?: (error: Error) => void;\n timeout?: number;\n};\n\nconst CodeBlockCopyButton: ForwardRefExoticComponent<\n Omit<CodeBlockCopyButtonProps, 'ref'> & RefAttributes<HTMLElement>\n> = forwardRef<ComponentRef<typeof Button>, CodeBlockCopyButtonProps>(\n ({ onCopy, onError, timeout = 2000, children, className, ...props }, ref) => {\n const [isCopied, setIsCopied] = useState(false);\n const { copyText } = useContext(CodeBlockContext);\n\n const copyToClipboard = async () => {\n if (typeof window === 'undefined' || !navigator?.clipboard?.writeText) {\n onError?.(new Error('Clipboard API not available'));\n return;\n }\n\n try {\n await navigator.clipboard.writeText(copyText);\n setIsCopied(true);\n onCopy?.();\n setTimeout(() => setIsCopied(false), timeout);\n } catch (error: unknown) {\n console.warn('Clipboard write failed:', error);\n onError?.(\n error instanceof Error ? error : new Error('Clipboard write failed')\n );\n }\n };\n\n const Icon = isCopied ? IconCheck : IconCopy;\n\n return (\n <Button\n ref={ref}\n data-slot=\"code-block-copy-button\"\n className={cn('shrink-0', className)}\n onClick={copyToClipboard}\n size=\"icon-sm\"\n variant=\"secondary\"\n {...props}\n >\n {children ?? <Icon size={14} />}\n </Button>\n );\n }\n);\nCodeBlockCopyButton.displayName = 'CodeBlockCopyButton';\n\ntype CodeBlockCollapseButtonProps = ComponentProps<typeof Button>;\n\nconst CodeBlockCollapseButton: ForwardRefExoticComponent<\n Omit<ComponentProps<typeof Button>, 'ref'> & RefAttributes<HTMLElement>\n> = forwardRef<ComponentRef<typeof Button>, CodeBlockCollapseButtonProps>(\n ({ children, className, ...props }, ref) => {\n const { isCollapsed, setIsCollapsed, lineCount } =\n useContext(CodeBlockContext);\n\n if (lineCount <= CODE_BLOCK_COLLAPSIBLE_MIN_LINES) {\n return null;\n }\n\n return (\n <Button\n ref={ref}\n data-slot=\"code-block-collapse-button\"\n className={cn('shrink-0', className)}\n onClick={() => setIsCollapsed(!isCollapsed)}\n size=\"icon-sm\"\n variant=\"secondary\"\n {...props}\n >\n {children ?? <IconSelector size={14} />}\n </Button>\n );\n }\n);\nCodeBlockCollapseButton.displayName = 'CodeBlockCollapseButton';\n\ntype CodeBlockDownloadButtonProps = ComponentProps<typeof Button> & {\n fileName?: string;\n mimeType?: string;\n onDownload?: () => void;\n onError?: (error: Error) => void;\n};\n\nconst CodeBlockDownloadButton: ForwardRefExoticComponent<\n Omit<CodeBlockDownloadButtonProps, 'ref'> & RefAttributes<HTMLElement>\n> = forwardRef<ComponentRef<typeof Button>, CodeBlockDownloadButtonProps>(\n (\n {\n fileName = 'code.txt',\n mimeType = 'text/plain;charset=utf-8',\n onDownload,\n onError,\n children,\n className,\n ...props\n },\n ref\n ) => {\n const { code } = useContext(CodeBlockContext);\n\n const download = () => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n onError?.(new Error('Download not available'));\n return;\n }\n\n try {\n const blob = new Blob([code], { type: mimeType });\n const url = URL.createObjectURL(blob);\n\n const a = document.createElement('a');\n a.href = url;\n a.download = fileName;\n a.rel = 'noopener';\n a.click();\n\n URL.revokeObjectURL(url);\n onDownload?.();\n } catch (error: unknown) {\n onError?.(\n error instanceof Error ? error : new Error('Download failed')\n );\n }\n };\n\n return (\n <Button\n ref={ref}\n data-slot=\"code-block-download-button\"\n className={cn('shrink-0', className)}\n onClick={download}\n size=\"icon-sm\"\n variant=\"secondary\"\n {...props}\n >\n {children ?? <IconDownload size={14} />}\n </Button>\n );\n }\n);\nCodeBlockDownloadButton.displayName = 'CodeBlockDownloadButton';\n\nexport {\n CodeBlock,\n CodeBlockCollapseButton,\n CodeBlockCopyButton,\n CodeBlockDownloadButton,\n};\n"],"names":["createContext","forwardRef","useContext","useEffect","useMemo","useState","IconCheck","IconCopy","IconDownload","IconSelector","highlightCode","cn","isStorybookTestEnv","Button","CodeBlockContext","code","copyText","isCollapsed","setIsCollapsed","undefined","lineCount","escapeHtml","value","replaceAll","PREVIEW_MAX_LINES","PREVIEW_MAX_CHARS","MAX_LINES_FULL_SHIKI","MAX_CHARS_FULL_SHIKI","CODE_BLOCK_COLLAPSIBLE_MIN_LINES","getCollapsedPreviewDisplay","lines","split","truncated","slice","join","length","body","isContentLargerThanPreview","shouldUsePlainTextInsteadOfShiki","plainPreMarkup","CODE_BLOCK_EXPANDED_MAX_HEIGHT_CSS","codeHtmlInnerClassName","codeHtmlInnerDarkClassName","CodeBlock","language","showLineNumbers","collapsed","className","children","style","styleFromProps","props","ref","html","setHtml","darkHtml","setDarkHtml","codeForRender","isCollapsible","showCollapsedChrome","textToCopy","storybookMarkup","isCancelled","applyPlain","source","markup","previewSource","then","light","dark","catch","error","console","queueMicrotask","contextValue","preMinHeightClassName","codeBody","div","dangerouslySetInnerHTML","__html","actions","data-slot","Provider","maxHeight","minHeight","displayName","CodeBlockCopyButton","onCopy","onError","timeout","isCopied","setIsCopied","copyToClipboard","window","navigator","clipboard","writeText","Error","setTimeout","warn","Icon","onClick","size","variant","CodeBlockCollapseButton","CodeBlockDownloadButton","fileName","mimeType","onDownload","download","document","blob","Blob","type","url","URL","createObjectURL","a","createElement","href","rel","click","revokeObjectURL"],"mappings":"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"}
@@ -2,10 +2,9 @@ import type { ControlsConfig } from "streamdown";
2
2
  /**
3
3
  * Default Streamdown `controls` for assistant markdown (`MessageResponse`).
4
4
  *
5
- * - **Mermaid:** Enables copy, download, and pan/zoom (AX-117, AX-118). Fullscreen is
6
- * disabled: it uses a portal to `document.body`, which breaks scoped / prefixed CSS in
7
- * micro-frontend hosts until upstream supports a configurable portal root.
8
- * - **Code / table:** Off so chat keeps a simpler surface; callers may override via the
9
- * `controls` prop on `MessageResponse`.
5
+ * - **Mermaid:** Copy, download, pan/zoom and fullscreen are on (AX-117, AX-118, KCIH-1232).
6
+ * Fullscreen renders into the Aura portal container so it stays inside the Aura style scope.
7
+ * - **Code / table:** Off so chat keeps a simpler surface.
8
+ * Callers may override via the `controls` prop on `MessageResponse`.
10
9
  */
11
10
  export declare const MESSAGE_RESPONSE_DEFAULT_STREAMDOWN_CONTROLS: Exclude<ControlsConfig, boolean>;
@@ -1,18 +1,17 @@
1
1
  /**
2
2
  * Default Streamdown `controls` for assistant markdown (`MessageResponse`).
3
3
  *
4
- * - **Mermaid:** Enables copy, download, and pan/zoom (AX-117, AX-118). Fullscreen is
5
- * disabled: it uses a portal to `document.body`, which breaks scoped / prefixed CSS in
6
- * micro-frontend hosts until upstream supports a configurable portal root.
7
- * - **Code / table:** Off so chat keeps a simpler surface; callers may override via the
8
- * `controls` prop on `MessageResponse`.
4
+ * - **Mermaid:** Copy, download, pan/zoom and fullscreen are on (AX-117, AX-118, KCIH-1232).
5
+ * Fullscreen renders into the Aura portal container so it stays inside the Aura style scope.
6
+ * - **Code / table:** Off so chat keeps a simpler surface.
7
+ * Callers may override via the `controls` prop on `MessageResponse`.
9
8
  */ export const MESSAGE_RESPONSE_DEFAULT_STREAMDOWN_CONTROLS = {
10
9
  code: false,
11
10
  table: false,
12
11
  mermaid: {
13
12
  copy: true,
14
13
  download: true,
15
- fullscreen: false,
14
+ fullscreen: true,
16
15
  panZoom: true
17
16
  }
18
17
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/components/ui/core/message/message-response-default-streamdown-controls.ts"],"sourcesContent":["import type { ControlsConfig } from 'streamdown';\n\n/**\n * Default Streamdown `controls` for assistant markdown (`MessageResponse`).\n *\n * - **Mermaid:** Enables copy, download, and pan/zoom (AX-117, AX-118). Fullscreen is\n * disabled: it uses a portal to `document.body`, which breaks scoped / prefixed CSS in\n * micro-frontend hosts until upstream supports a configurable portal root.\n * - **Code / table:** Off so chat keeps a simpler surface; callers may override via the\n * `controls` prop on `MessageResponse`.\n */\nexport const MESSAGE_RESPONSE_DEFAULT_STREAMDOWN_CONTROLS: Exclude<\n ControlsConfig,\n boolean\n> = {\n code: false,\n table: false,\n mermaid: {\n copy: true,\n download: true,\n fullscreen: false,\n panZoom: true,\n },\n};\n"],"names":["MESSAGE_RESPONSE_DEFAULT_STREAMDOWN_CONTROLS","code","table","mermaid","copy","download","fullscreen","panZoom"],"mappings":"AAEA;;;;;;;;CAQC,GACD,OAAO,MAAMA,+CAGT;IACFC,MAAM;IACNC,OAAO;IACPC,SAAS;QACPC,MAAM;QACNC,UAAU;QACVC,YAAY;QACZC,SAAS;IACX;AACF,EAAE"}
1
+ {"version":3,"sources":["../../../../../src/components/ui/core/message/message-response-default-streamdown-controls.ts"],"sourcesContent":["import type { ControlsConfig } from 'streamdown';\n\n/**\n * Default Streamdown `controls` for assistant markdown (`MessageResponse`).\n *\n * - **Mermaid:** Copy, download, pan/zoom and fullscreen are on (AX-117, AX-118, KCIH-1232).\n * Fullscreen renders into the Aura portal container so it stays inside the Aura style scope.\n * - **Code / table:** Off so chat keeps a simpler surface.\n * Callers may override via the `controls` prop on `MessageResponse`.\n */\nexport const MESSAGE_RESPONSE_DEFAULT_STREAMDOWN_CONTROLS: Exclude<\n ControlsConfig,\n boolean\n> = {\n code: false,\n table: false,\n mermaid: {\n copy: true,\n download: true,\n fullscreen: true,\n panZoom: true,\n },\n};\n"],"names":["MESSAGE_RESPONSE_DEFAULT_STREAMDOWN_CONTROLS","code","table","mermaid","copy","download","fullscreen","panZoom"],"mappings":"AAEA;;;;;;;CAOC,GACD,OAAO,MAAMA,+CAGT;IACFC,MAAM;IACNC,OAAO;IACPC,SAAS;QACPC,MAAM;QACNC,UAAU;QACVC,YAAY;QACZC,SAAS;IACX;AACF,EAAE"}
@@ -3,6 +3,7 @@ import { createContext, useCallback, useContext, useEffect, useMemo, useState }
3
3
  import { mermaid as mermaidPlugin } from "@streamdown/mermaid";
4
4
  import { IconChevronLeft, IconChevronRight, IconPaperclip, IconX } from "@tabler/icons-react";
5
5
  import { Streamdown } from "streamdown";
6
+ import { usePortalContainer } from "../../../../lib/portal-container-context.js";
6
7
  import { cn, getInitials } from "../../../../lib/utils.js";
7
8
  import { Avatar, AvatarFallback, AvatarIcon, AvatarImage } from "../avatar/avatar.js";
8
9
  import { Button } from "../button/button.js";
@@ -317,7 +318,9 @@ const messageResponseComponents = {
317
318
  children: children
318
319
  })
319
320
  };
320
- const MessageResponseMarkdown = ({ className, components, plugins, controls, ...props })=>/*#__PURE__*/ _jsx(Streamdown, {
321
+ const MessageResponseMarkdown = ({ className, components, plugins, controls, portal, ...props })=>{
322
+ const portalContainer = usePortalContainer();
323
+ return /*#__PURE__*/ _jsx(Streamdown, {
321
324
  className: cn('size-full', // Blockquote paragraph overrides
322
325
  '[&_blockquote_p]:text-sm', '[&_blockquote_p]:tracking-tight', // Inline code
323
326
  '[&_code]:relative', '[&_code]:rounded', '[&_code]:bg-muted-background', '[&_code]:px-[0.3rem]', '[&_code]:py-[0.2rem]', '[&_code]:font-mono', '[&_code]:text-sm', '[&_code]:font-semibold', // Code blocks (Streamdown container)
@@ -343,8 +346,10 @@ const MessageResponseMarkdown = ({ className, components, plugins, controls, ...
343
346
  ...plugins,
344
347
  mermaid: mermaidPlugin
345
348
  },
349
+ portal: portal ?? portalContainer,
346
350
  ...props
347
351
  });
352
+ };
348
353
  const MessageResponse = ({ id, role, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, 'data-testid': dataTestId, ...props })=>/*#__PURE__*/ _jsx("div", {
349
354
  "data-slot": "message-response",
350
355
  id: id,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/components/ui/core/message/message.tsx"],"sourcesContent":["import type {\n ComponentProps,\n HTMLAttributes,\n ReactElement,\n ReactNode,\n} from 'react';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react';\n\nimport { mermaid as mermaidPlugin } from '@streamdown/mermaid';\nimport {\n IconChevronLeft,\n IconChevronRight,\n IconPaperclip,\n IconX,\n} from '@tabler/icons-react';\nimport type { JSX } from 'react/jsx-runtime';\nimport type { Components, ExtraProps } from 'streamdown';\nimport { Streamdown } from 'streamdown';\n\nimport type { FileUIPart, UIMessage } from '../../../../lib/ai/types';\nimport { cn, getInitials } from '../../../../lib/utils';\nimport {\n Avatar,\n AvatarFallback,\n AvatarIcon,\n AvatarImage,\n} from '../avatar/avatar';\nimport { Button } from '../button/button';\nimport { ButtonGroup, ButtonGroupText } from '../button-group/button-group';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip/tooltip';\n\nimport { MESSAGE_RESPONSE_DEFAULT_STREAMDOWN_CONTROLS } from './message-response-default-streamdown-controls';\n\ntype MessageProps = HTMLAttributes<HTMLDivElement> & {\n isResponse?: boolean;\n};\n\nconst Message = ({\n className,\n isResponse = false,\n ...props\n}: MessageProps): ReactNode => (\n <div\n data-slot=\"message\"\n className={cn(\n 'group flex w-full items-start justify-start gap-3 mb-0 py-3',\n isResponse ? 'is-assistant items-start' : 'is-user flex-row-reverse',\n className\n )}\n {...props}\n />\n);\n\ntype MessageContentProps = HTMLAttributes<HTMLDivElement>;\n\nconst MessageContent = ({\n children,\n className,\n ...props\n}: MessageContentProps): ReactNode => (\n <div\n data-slot=\"message-content\"\n className={cn(\n 'is-user:dark flex flex-col gap-4 rounded-md text-base leading-tight tracking-tightest',\n 'max-w-4/5',\n 'group-[.is-user]:overflow-hidden group-[.is-user]:bg-medium-background group-[.is-user]:p-2 group-[.is-user]:text-base-foreground',\n 'group-[.is-assistant]:text-base-foreground group-[.is-assistant]:pt-1',\n className\n )}\n {...props}\n >\n {children}\n </div>\n);\n\ntype MessageAvatarProps = ComponentProps<typeof Avatar> & {\n avatarUrl?: string;\n name?: string;\n};\n\nconst MessageAvatar = ({\n avatarUrl,\n name,\n className,\n children,\n variant,\n sizes,\n ...props\n}: MessageAvatarProps): ReactNode => {\n const fallbackText = name ? getInitials(name) : 'ME';\n\n return (\n <Avatar\n data-slot=\"message-avatar\"\n className={cn('size-7 group-[.is-user]:mt-1', className)}\n variant={variant}\n sizes={sizes}\n {...props}\n >\n {children || (\n <>\n {avatarUrl && (\n <AvatarImage\n alt={name || ''}\n className=\"mt-0 mb-0\"\n src={avatarUrl}\n />\n )}\n <AvatarFallback>{fallbackText}</AvatarFallback>\n </>\n )}\n </Avatar>\n );\n};\n\ntype MessageAvatarIconProps = ComponentProps<typeof AvatarIcon>;\n\nconst MessageAvatarIcon = (props: MessageAvatarIconProps): ReactNode => (\n <AvatarIcon data-slot=\"message-avatar-icon\" {...props} />\n);\n\ntype MessageActionsProps = ComponentProps<'div'>;\n\nconst MessageActions = ({\n className,\n children,\n ...props\n}: MessageActionsProps): ReactNode => (\n <div\n data-slot=\"message-actions\"\n className={cn('flex items-center gap-2 pt-2', className)}\n {...props}\n >\n {children}\n </div>\n);\n\ntype MessageActionProps = ComponentProps<typeof Button> & {\n tooltip?: string;\n label?: string;\n};\n\nconst MessageAction = ({\n tooltip,\n children,\n label,\n className,\n variant = 'ghost',\n size = 'sm',\n ...props\n}: MessageActionProps): ReactNode => {\n const button = (\n <Button\n data-slot=\"message-action\"\n className={cn(\n 'relative icon-sm text-muted-foreground hover:text-base-foreground',\n className\n )}\n size={size}\n type=\"button\"\n variant={variant}\n {...props}\n >\n {children}\n <span className=\"sr-only\">{label || tooltip}</span>\n </Button>\n );\n\n if (tooltip) {\n return (\n <Tooltip>\n <TooltipTrigger render={button} />\n <TooltipContent>\n <p>{tooltip}</p>\n </TooltipContent>\n </Tooltip>\n );\n }\n\n return button;\n};\n\ntype MessageBranchContextType = {\n currentBranch: number;\n totalBranches: number;\n goToPrevious: () => void;\n goToNext: () => void;\n branches: ReactElement[];\n setBranches: (branches: ReactElement[]) => void;\n};\n\nconst MessageBranchContext = createContext<MessageBranchContextType | null>(\n null\n);\n\nconst useMessageBranch = () => {\n const context = useContext(MessageBranchContext);\n\n if (!context) {\n throw new Error(\n 'MessageBranch components must be used within MessageBranch'\n );\n }\n\n return context;\n};\n\ntype MessageBranchProps = HTMLAttributes<HTMLDivElement> & {\n defaultBranch?: number;\n onBranchChange?: (branchIndex: number) => void;\n};\n\nconst MessageBranch = ({\n defaultBranch = 0,\n onBranchChange,\n className,\n ...props\n}: MessageBranchProps): ReactNode => {\n const [currentBranch, setCurrentBranch] = useState(defaultBranch);\n const [branches, setBranches] = useState<ReactElement[]>([]);\n\n const goToPrevious = useCallback(() => {\n setCurrentBranch((prev) => {\n const newBranch = prev > 0 ? prev - 1 : branches.length - 1;\n onBranchChange?.(newBranch);\n return newBranch;\n });\n }, [branches.length, onBranchChange]);\n\n const goToNext = useCallback(() => {\n setCurrentBranch((prev) => {\n const newBranch = prev < branches.length - 1 ? prev + 1 : 0;\n onBranchChange?.(newBranch);\n return newBranch;\n });\n }, [branches.length, onBranchChange]);\n\n const contextValue = useMemo<MessageBranchContextType>(\n () => ({\n currentBranch,\n totalBranches: branches.length,\n goToPrevious,\n goToNext,\n branches,\n setBranches,\n }),\n [currentBranch, branches, goToPrevious, goToNext, setBranches]\n );\n\n return (\n <MessageBranchContext.Provider value={contextValue}>\n <div\n data-slot=\"message-branch\"\n className={cn('grid w-full gap-2 [&>div]:pb-0', className)}\n {...props}\n />\n </MessageBranchContext.Provider>\n );\n};\n\ntype MessageBranchContentProps = HTMLAttributes<HTMLDivElement>;\n\nconst MessageBranchContent = ({\n children,\n ...props\n}: MessageBranchContentProps): ReactNode[] => {\n const { currentBranch, setBranches, branches } = useMessageBranch();\n const childrenArray = useMemo(\n () => (Array.isArray(children) ? children : [children]),\n [children]\n );\n\n useEffect(() => {\n if (branches.length !== childrenArray.length) {\n setBranches(childrenArray);\n }\n }, [childrenArray, branches, setBranches]);\n\n return childrenArray.map((branch, index) => (\n <div\n data-slot=\"message-branch-content\"\n className={cn(\n 'grid gap-2 overflow-hidden [&>div]:pb-0',\n index === currentBranch ? 'block' : 'hidden'\n )}\n key={branch.key}\n {...props}\n >\n {branch}\n </div>\n ));\n};\n\ntype MessageBranchSelectorProps = HTMLAttributes<HTMLDivElement> & {\n from: UIMessage['role'];\n};\n\nconst MessageBranchSelector = ({\n ...props\n}: MessageBranchSelectorProps): ReactNode => {\n const { totalBranches } = useMessageBranch();\n\n if (totalBranches <= 1) {\n return null;\n }\n\n return (\n <ButtonGroup\n data-slot=\"message-branch-selector\"\n className=\"[&>*:not(:first-child)]:rounded-l-md [&>*:not(:last-child)]:rounded-r-md\"\n orientation=\"horizontal\"\n {...props}\n />\n );\n};\n\ntype MessageBranchPreviousProps = ComponentProps<typeof Button>;\n\nconst MessageBranchPrevious = ({\n children,\n ...props\n}: MessageBranchPreviousProps): ReactNode => {\n const { goToPrevious, totalBranches } = useMessageBranch();\n\n return (\n <Button\n data-slot=\"message-branch-previous\"\n aria-label=\"Previous branch\"\n disabled={totalBranches <= 1}\n onClick={goToPrevious}\n size=\"icon-sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <IconChevronLeft size={14} />}\n </Button>\n );\n};\n\ntype MessageBranchNextProps = ComponentProps<typeof Button>;\n\nconst MessageBranchNext = ({\n children,\n ...props\n}: MessageBranchNextProps): ReactNode => {\n const { goToNext, totalBranches } = useMessageBranch();\n\n return (\n <Button\n data-slot=\"message-branch-next\"\n aria-label=\"Next branch\"\n disabled={totalBranches <= 1}\n onClick={goToNext}\n size=\"icon-sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <IconChevronRight size={14} />}\n </Button>\n );\n};\n\ntype MessageBranchPageProps = HTMLAttributes<HTMLSpanElement>;\n\nconst MessageBranchPage = ({\n className,\n ...props\n}: MessageBranchPageProps): ReactNode => {\n const { currentBranch, totalBranches } = useMessageBranch();\n\n return (\n <ButtonGroupText\n data-slot=\"message-branch-page\"\n className={cn(\n 'border-none bg-transparent text-muted-foreground shadow-none px-2',\n className\n )}\n {...props}\n >\n {currentBranch + 1}/{totalBranches}\n </ButtonGroupText>\n );\n};\n\n/** Streamdown discards unrecognised props, so these go on a wrapper instead. */\ntype MessageResponseHostProps = Pick<\n HTMLAttributes<HTMLDivElement>,\n 'id' | 'role' | 'aria-label' | 'aria-labelledby' | 'aria-describedby'\n> & {\n 'data-testid'?: string;\n};\n\ntype MessageResponseProps = ComponentProps<typeof Streamdown> &\n MessageResponseHostProps;\n\ntype MarkdownComponentProps<T extends keyof JSX.IntrinsicElements> =\n JSX.IntrinsicElements[T] & ExtraProps;\n\nconst messageResponseComponents: Components = {\n h1: ({ children }: MarkdownComponentProps<'h1'>) => (\n <h1 className=\"mt-0 mb-2 scroll-m-20 text-xl font-medium tracking-tightest\">\n {children}\n </h1>\n ),\n h2: ({ children }: MarkdownComponentProps<'h2'>) => (\n <h2 className=\"mt-4 mb-1 scroll-m-20 text-lg font-medium tracking-tightest\">\n {children}\n </h2>\n ),\n h3: ({ children }: MarkdownComponentProps<'h3'>) => (\n <h3 className=\"mt-4 mb-1 scroll-m-20 text-base font-medium tracking-tighter\">\n {children}\n </h3>\n ),\n h4: ({ children }: MarkdownComponentProps<'h4'>) => (\n <h4 className=\"mt-2 mb-0 scroll-m-20 text-sm font-medium tracking-normal\">\n {children}\n </h4>\n ),\n h5: ({ children }: MarkdownComponentProps<'h5'>) => (\n <h5 className=\"mt-0 mb-0 scroll-m-20 text-xs font-medium tracking-tighter\">\n {children}\n </h5>\n ),\n h6: ({ children }: MarkdownComponentProps<'h6'>) => (\n <h6 className=\"mt-0 mb-0 scroll-m-20 text-2xs font-medium tracking-tighter\">\n {children}\n </h6>\n ),\n p: ({ children }: MarkdownComponentProps<'p'>) => (\n <p className=\"mt-2 mb-3 text-base font-normal leading-5 tracking-tightest\">\n {children}\n </p>\n ),\n strong: ({ children }: MarkdownComponentProps<'strong'>) => (\n <strong className=\"font-medium\">{children}</strong>\n ),\n em: ({ children }: MarkdownComponentProps<'em'>) => (\n <em className=\"italic\">{children}</em>\n ),\n b: ({ children }: MarkdownComponentProps<'b'>) => (\n <b className=\"font-medium\">{children}</b>\n ),\n i: ({ children }: MarkdownComponentProps<'i'>) => (\n <i className=\"italic\">{children}</i>\n ),\n ul: ({ children }: MarkdownComponentProps<'ul'>) => (\n <ul className=\"ml-8.25 mb-3 pt-2 pl-0 pb-0 list-disc text-base font-normal tracking-tightest\">\n {children}\n </ul>\n ),\n ol: ({ children }: MarkdownComponentProps<'ol'>) => (\n <ol className=\"ml-8.25 mb-3 pt-2 pl-0 pb-0 list-decimal text-base font-normal tracking-tightest\">\n {children}\n </ol>\n ),\n li: ({ children }: MarkdownComponentProps<'li'>) => (\n <li className=\"py-0\">{children}</li>\n ),\n blockquote: ({ children }: MarkdownComponentProps<'blockquote'>) => (\n <blockquote className=\"my-3 pr-2 pl-2 border-l border-l-default text-sm text-muted-foreground font-normal tracking-tight not-italic\">\n {children}\n </blockquote>\n ),\n hr: () => <hr className=\"my-4 border-default\" />,\n a: ({ children, href, ...props }: MarkdownComponentProps<'a'>) => (\n <a\n className=\"text-link-foreground no-underline hover:underline underline-offset-4\"\n href={href}\n {...props}\n >\n {children}\n </a>\n ),\n table: ({ children }: MarkdownComponentProps<'table'>) => (\n <div\n className=\"my-6 overflow-x-auto\"\n tabIndex={0}\n role=\"group\"\n aria-label=\"Atlas AI Chat Table\"\n >\n <table className=\"w-full\">{children}</table>\n </div>\n ),\n thead: ({ children }: MarkdownComponentProps<'thead'>) => (\n <thead>{children}</thead>\n ),\n tbody: ({ children }: MarkdownComponentProps<'tbody'>) => (\n <tbody>{children}</tbody>\n ),\n tr: ({ children }: MarkdownComponentProps<'tr'>) => (\n <tr className=\"m-0 border-t p-0 even:bg-muted-background\">{children}</tr>\n ),\n th: ({ children }: MarkdownComponentProps<'th'>) => (\n <th className=\"border px-4 py-2 text-left font-bold\">{children}</th>\n ),\n td: ({ children }: MarkdownComponentProps<'td'>) => (\n <td className=\"border px-4 py-2 text-left\">{children}</td>\n ),\n};\n\nconst MessageResponseMarkdown = ({\n className,\n components,\n plugins,\n controls,\n ...props\n}: ComponentProps<typeof Streamdown>): JSX.Element => (\n <Streamdown\n className={cn(\n 'size-full',\n // Blockquote paragraph overrides\n '[&_blockquote_p]:text-sm',\n '[&_blockquote_p]:tracking-tight',\n // Inline code\n '[&_code]:relative',\n '[&_code]:rounded',\n '[&_code]:bg-muted-background',\n '[&_code]:px-[0.3rem]',\n '[&_code]:py-[0.2rem]',\n '[&_code]:font-mono',\n '[&_code]:text-sm',\n '[&_code]:font-semibold',\n // Code blocks (Streamdown container)\n '[&_div[data-streamdown=\"code-block\"]]:my-4',\n '[&_div[data-streamdown=\"code-block\"]]:w-full',\n '[&_div[data-streamdown=\"code-block\"]]:overflow-hidden',\n '[&_div[data-streamdown=\"code-block\"]]:rounded-xl',\n '[&_div[data-streamdown=\"code-block\"]]:border',\n '[&_div[data-streamdown=\"code-block\"]]:border-default',\n // Code block header\n '[&_div[data-streamdown=\"code-block-header\"]]:flex',\n '[&_div[data-streamdown=\"code-block-header\"]]:items-center',\n '[&_div[data-streamdown=\"code-block-header\"]]:justify-between',\n '[&_div[data-streamdown=\"code-block-header\"]]:bg-muted-background/80',\n '[&_div[data-streamdown=\"code-block-header\"]]:px-4',\n '[&_div[data-streamdown=\"code-block-header\"]]:py-3',\n '[&_div[data-streamdown=\"code-block-header\"]]:text-xs',\n '[&_div[data-streamdown=\"code-block-header\"]]:text-muted-foreground',\n // Pre element inside code block\n '[&_div[data-streamdown=\"code-block\"]_pre]:m-0',\n '[&_div[data-streamdown=\"code-block\"]_pre]:overflow-x-auto',\n '[&_div[data-streamdown=\"code-block\"]_pre]:border-t',\n '[&_div[data-streamdown=\"code-block\"]_pre]:border-default',\n '[&_div[data-streamdown=\"code-block\"]_pre]:bg-card-background!',\n '[&_div[data-streamdown=\"code-block\"]_pre]:p-4',\n '[&_div[data-streamdown=\"code-block\"]_pre]:text-sm',\n '[&_div[data-streamdown=\"code-block\"]_pre]:text-medium-foreground!',\n // Code element inside pre\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:static',\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:rounded-none',\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:bg-transparent',\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:p-0',\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:font-mono',\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:text-sm',\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:font-normal',\n // Code block buttons\n '[&_button[data-streamdown=\"code-block-copy-button\"]]:cursor-pointer',\n '[&_button[data-streamdown=\"code-block-copy-button\"]]:p-1',\n '[&_button[data-streamdown=\"code-block-copy-button\"]]:text-muted-foreground',\n '[&_button[data-streamdown=\"code-block-copy-button\"]]:transition-all',\n '[&_button[data-streamdown=\"code-block-copy-button\"]]:hover:text-base-foreground',\n '[&_button[data-streamdown=\"code-block-download-button\"]]:cursor-pointer',\n '[&_button[data-streamdown=\"code-block-download-button\"]]:p-1',\n '[&_button[data-streamdown=\"code-block-download-button\"]]:text-muted-foreground',\n '[&_button[data-streamdown=\"code-block-download-button\"]]:transition-all',\n '[&_button[data-streamdown=\"code-block-download-button\"]]:hover:text-base-foreground',\n // Regular pre blocks (not in Streamdown code blocks)\n '[&_pre:not([data-streamdown])]:my-3',\n '[&_pre:not([data-streamdown])]:mx-0',\n '[&_pre:not([data-streamdown])]:overflow-x-auto',\n '[&_pre:not([data-streamdown])]:rounded-md',\n '[&_pre:not([data-streamdown])]:border',\n '[&_pre:not([data-streamdown])]:bg-card-background',\n '[&_pre:not([data-streamdown])]:p-4',\n '[&_pre:not([data-streamdown])]:text-medium-foreground',\n '[&_pre:not([data-streamdown])]:text-sm',\n '[&_pre:not([data-streamdown])_code]:static',\n '[&_pre:not([data-streamdown])_code]:rounded-none',\n '[&_pre:not([data-streamdown])_code]:bg-transparent',\n '[&_pre:not([data-streamdown])_code]:px-0',\n '[&_pre:not([data-streamdown])_code]:py-0',\n '[&_pre:not([data-streamdown])_code]:font-mono',\n '[&_pre:not([data-streamdown])_code]:text-sm',\n '[&_pre:not([data-streamdown])_code]:font-normal',\n // Mermaid diagram blocks\n '[&_div[data-streamdown=\"mermaid-block\"]]:bg-card-background',\n '[&_div[data-streamdown=\"mermaid-block\"]]:text-base-foreground',\n '[&_div[data-streamdown=\"mermaid-block\"]]:flex',\n '[&_div[data-streamdown=\"mermaid-block\"]]:flex-col',\n '[&_div[data-streamdown=\"mermaid-block\"]]:rounded-lg',\n '[&_div[data-streamdown=\"mermaid-block\"]]:hover:bg-base-background-hover',\n '[&_div[data-streamdown=\"mermaid-block\"]]:border-0',\n // Positioning context for the action strip (see below)\n '[&_div[data-streamdown=\"mermaid-block\"]]:relative',\n // Nested scroll + sticky + pointer-events breaks hit-testing on Mermaid Copy/Download\n // (same class of issue as github.com/vercel/streamdown/issues/494). Force absolute strip.\n '[&_div[data-streamdown=\"mermaid-block\"]>div:has([data-streamdown=\"mermaid-block-actions\"])]:!absolute',\n '[&_div[data-streamdown=\"mermaid-block\"]>div:has([data-streamdown=\"mermaid-block-actions\"])]:!top-2',\n '[&_div[data-streamdown=\"mermaid-block\"]>div:has([data-streamdown=\"mermaid-block-actions\"])]:!right-2',\n '[&_div[data-streamdown=\"mermaid-block\"]>div:has([data-streamdown=\"mermaid-block-actions\"])]:!z-10',\n '[&_div[data-streamdown=\"mermaid-block\"]>div:has([data-streamdown=\"mermaid-block-actions\"])]:!mt-0',\n '[&_div[data-streamdown=\"mermaid-block\"]>div:has([data-streamdown=\"mermaid-block-actions\"])]:!pointer-events-auto',\n // Ensure mermaid container is tall enough for the toolbar (pan/zoom + actions)\n '[&_div[data-streamdown=\"mermaid-block\"]_.relative.w-full]:!min-h-28',\n // KaTeX sizing (overflow rules live in styles.source.css)\n '[&_.katex-display]:my-3',\n '[&_.katex]:text-[1em]',\n // First and last child margin resets\n '[&>*:first-child]:mt-0',\n '[&>*:last-child]:mb-0',\n className\n )}\n components={{ ...messageResponseComponents, ...components }}\n controls={controls ?? MESSAGE_RESPONSE_DEFAULT_STREAMDOWN_CONTROLS}\n plugins={{ ...plugins, mermaid: mermaidPlugin }}\n {...props}\n />\n);\n\nconst MessageResponse = ({\n id,\n role,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'data-testid': dataTestId,\n ...props\n}: MessageResponseProps): JSX.Element => (\n <div\n data-slot=\"message-response\"\n id={id}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n data-testid={dataTestId}\n >\n <MessageResponseMarkdown {...props} />\n </div>\n);\n\ntype MessageAttachmentProps = HTMLAttributes<HTMLDivElement> & {\n data: FileUIPart;\n className?: string;\n onRemove?: () => void;\n};\n\nfunction MessageAttachment({\n data,\n className,\n onRemove,\n ...props\n}: MessageAttachmentProps): ReactNode {\n const filename = data.filename || '';\n const mediaType =\n data.mediaType?.startsWith('image/') && data.url ? 'image' : 'file';\n const isImage = mediaType === 'image';\n const attachmentLabel = filename || (isImage ? 'Image' : 'Attachment');\n\n return (\n <div\n data-slot=\"message-attachment\"\n className={cn(\n 'group relative size-24 overflow-hidden rounded-lg',\n className\n )}\n {...props}\n >\n {isImage ? (\n <>\n <img\n alt={filename || 'attachment'}\n className=\"size-full object-cover\"\n height={100}\n src={data.url}\n width={100}\n />\n {onRemove && (\n <Button\n aria-label=\"Remove attachment\"\n className=\"absolute top-2 right-2 size-6 rounded-full bg-card-background/80 p-0 opacity-0 backdrop-blur-sm transition-opacity hover:bg-card-background group-hover:opacity-100 [&>svg]:size-3\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n type=\"button\"\n variant=\"ghost\"\n >\n <IconX />\n <span className=\"sr-only\">Remove</span>\n </Button>\n )}\n </>\n ) : (\n <>\n <Tooltip>\n <TooltipTrigger\n render={\n <div className=\"flex size-full shrink-0 items-center justify-center rounded-lg bg-muted-background text-muted-foreground\">\n <IconPaperclip className=\"size-4\" />\n </div>\n }\n />\n <TooltipContent>\n <p>{attachmentLabel}</p>\n </TooltipContent>\n </Tooltip>\n {onRemove && (\n <Button\n aria-label=\"Remove attachment\"\n className=\"size-6 shrink-0 rounded-full p-0 opacity-0 transition-opacity hover:bg-base-background-hover group-hover:opacity-100 [&>svg]:size-3\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n type=\"button\"\n variant=\"ghost\"\n >\n <IconX />\n <span className=\"sr-only\">Remove</span>\n </Button>\n )}\n </>\n )}\n </div>\n );\n}\n\ntype MessageAttachmentsProps = ComponentProps<'div'>;\n\nfunction MessageAttachments({\n children,\n className,\n ...props\n}: MessageAttachmentsProps): ReactNode {\n if (!children) {\n return null;\n }\n\n return (\n <div\n data-slot=\"message-attachments\"\n className={cn(\n 'ml-auto flex w-fit flex-wrap items-start gap-2',\n className\n )}\n {...props}\n >\n {children}\n </div>\n );\n}\n\ntype MessageToolbarProps = ComponentProps<'div'>;\n\nconst MessageToolbar = ({\n className,\n children,\n ...props\n}: MessageToolbarProps): ReactNode => (\n <div\n data-slot=\"message-toolbar\"\n className={cn(\n 'mt-4 flex w-full items-center justify-between gap-4',\n className\n )}\n {...props}\n >\n {children}\n </div>\n);\n\nexport {\n Message,\n MessageAction,\n MessageActions,\n MessageAttachment,\n MessageAttachments,\n MessageAvatar,\n MessageAvatarIcon,\n MessageBranch,\n MessageBranchContent,\n MessageBranchNext,\n MessageBranchPage,\n MessageBranchPrevious,\n MessageBranchSelector,\n MessageContent,\n MessageResponse,\n MessageToolbar,\n};\n"],"names":["createContext","useCallback","useContext","useEffect","useMemo","useState","mermaid","mermaidPlugin","IconChevronLeft","IconChevronRight","IconPaperclip","IconX","Streamdown","cn","getInitials","Avatar","AvatarFallback","AvatarIcon","AvatarImage","Button","ButtonGroup","ButtonGroupText","Tooltip","TooltipContent","TooltipTrigger","MESSAGE_RESPONSE_DEFAULT_STREAMDOWN_CONTROLS","Message","className","isResponse","props","div","data-slot","MessageContent","children","MessageAvatar","avatarUrl","name","variant","sizes","fallbackText","alt","src","MessageAvatarIcon","MessageActions","MessageAction","tooltip","label","size","button","type","span","render","p","MessageBranchContext","useMessageBranch","context","Error","MessageBranch","defaultBranch","onBranchChange","currentBranch","setCurrentBranch","branches","setBranches","goToPrevious","prev","newBranch","length","goToNext","contextValue","totalBranches","Provider","value","MessageBranchContent","childrenArray","Array","isArray","map","branch","index","key","MessageBranchSelector","orientation","MessageBranchPrevious","aria-label","disabled","onClick","MessageBranchNext","MessageBranchPage","messageResponseComponents","h1","h2","h3","h4","h5","h6","strong","em","b","i","ul","ol","li","blockquote","hr","a","href","table","tabIndex","role","thead","tbody","tr","th","td","MessageResponseMarkdown","components","plugins","controls","MessageResponse","id","ariaLabel","ariaLabelledBy","ariaDescribedBy","dataTestId","aria-labelledby","aria-describedby","data-testid","MessageAttachment","data","onRemove","filename","mediaType","startsWith","url","isImage","attachmentLabel","img","height","width","e","stopPropagation","MessageAttachments","MessageToolbar"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/components/ui/core/message/message.tsx"],"sourcesContent":["import type {\n ComponentProps,\n HTMLAttributes,\n ReactElement,\n ReactNode,\n} from 'react';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react';\n\nimport { mermaid as mermaidPlugin } from '@streamdown/mermaid';\nimport {\n IconChevronLeft,\n IconChevronRight,\n IconPaperclip,\n IconX,\n} from '@tabler/icons-react';\nimport type { JSX } from 'react/jsx-runtime';\nimport type { Components, ExtraProps } from 'streamdown';\nimport { Streamdown } from 'streamdown';\n\nimport type { FileUIPart, UIMessage } from '../../../../lib/ai/types';\nimport { usePortalContainer } from '../../../../lib/portal-container-context';\nimport { cn, getInitials } from '../../../../lib/utils';\nimport {\n Avatar,\n AvatarFallback,\n AvatarIcon,\n AvatarImage,\n} from '../avatar/avatar';\nimport { Button } from '../button/button';\nimport { ButtonGroup, ButtonGroupText } from '../button-group/button-group';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip/tooltip';\n\nimport { MESSAGE_RESPONSE_DEFAULT_STREAMDOWN_CONTROLS } from './message-response-default-streamdown-controls';\n\ntype MessageProps = HTMLAttributes<HTMLDivElement> & {\n isResponse?: boolean;\n};\n\nconst Message = ({\n className,\n isResponse = false,\n ...props\n}: MessageProps): ReactNode => (\n <div\n data-slot=\"message\"\n className={cn(\n 'group flex w-full items-start justify-start gap-3 mb-0 py-3',\n isResponse ? 'is-assistant items-start' : 'is-user flex-row-reverse',\n className\n )}\n {...props}\n />\n);\n\ntype MessageContentProps = HTMLAttributes<HTMLDivElement>;\n\nconst MessageContent = ({\n children,\n className,\n ...props\n}: MessageContentProps): ReactNode => (\n <div\n data-slot=\"message-content\"\n className={cn(\n 'is-user:dark flex flex-col gap-4 rounded-md text-base leading-tight tracking-tightest',\n 'max-w-4/5',\n 'group-[.is-user]:overflow-hidden group-[.is-user]:bg-medium-background group-[.is-user]:p-2 group-[.is-user]:text-base-foreground',\n 'group-[.is-assistant]:text-base-foreground group-[.is-assistant]:pt-1',\n className\n )}\n {...props}\n >\n {children}\n </div>\n);\n\ntype MessageAvatarProps = ComponentProps<typeof Avatar> & {\n avatarUrl?: string;\n name?: string;\n};\n\nconst MessageAvatar = ({\n avatarUrl,\n name,\n className,\n children,\n variant,\n sizes,\n ...props\n}: MessageAvatarProps): ReactNode => {\n const fallbackText = name ? getInitials(name) : 'ME';\n\n return (\n <Avatar\n data-slot=\"message-avatar\"\n className={cn('size-7 group-[.is-user]:mt-1', className)}\n variant={variant}\n sizes={sizes}\n {...props}\n >\n {children || (\n <>\n {avatarUrl && (\n <AvatarImage\n alt={name || ''}\n className=\"mt-0 mb-0\"\n src={avatarUrl}\n />\n )}\n <AvatarFallback>{fallbackText}</AvatarFallback>\n </>\n )}\n </Avatar>\n );\n};\n\ntype MessageAvatarIconProps = ComponentProps<typeof AvatarIcon>;\n\nconst MessageAvatarIcon = (props: MessageAvatarIconProps): ReactNode => (\n <AvatarIcon data-slot=\"message-avatar-icon\" {...props} />\n);\n\ntype MessageActionsProps = ComponentProps<'div'>;\n\nconst MessageActions = ({\n className,\n children,\n ...props\n}: MessageActionsProps): ReactNode => (\n <div\n data-slot=\"message-actions\"\n className={cn('flex items-center gap-2 pt-2', className)}\n {...props}\n >\n {children}\n </div>\n);\n\ntype MessageActionProps = ComponentProps<typeof Button> & {\n tooltip?: string;\n label?: string;\n};\n\nconst MessageAction = ({\n tooltip,\n children,\n label,\n className,\n variant = 'ghost',\n size = 'sm',\n ...props\n}: MessageActionProps): ReactNode => {\n const button = (\n <Button\n data-slot=\"message-action\"\n className={cn(\n 'relative icon-sm text-muted-foreground hover:text-base-foreground',\n className\n )}\n size={size}\n type=\"button\"\n variant={variant}\n {...props}\n >\n {children}\n <span className=\"sr-only\">{label || tooltip}</span>\n </Button>\n );\n\n if (tooltip) {\n return (\n <Tooltip>\n <TooltipTrigger render={button} />\n <TooltipContent>\n <p>{tooltip}</p>\n </TooltipContent>\n </Tooltip>\n );\n }\n\n return button;\n};\n\ntype MessageBranchContextType = {\n currentBranch: number;\n totalBranches: number;\n goToPrevious: () => void;\n goToNext: () => void;\n branches: ReactElement[];\n setBranches: (branches: ReactElement[]) => void;\n};\n\nconst MessageBranchContext = createContext<MessageBranchContextType | null>(\n null\n);\n\nconst useMessageBranch = () => {\n const context = useContext(MessageBranchContext);\n\n if (!context) {\n throw new Error(\n 'MessageBranch components must be used within MessageBranch'\n );\n }\n\n return context;\n};\n\ntype MessageBranchProps = HTMLAttributes<HTMLDivElement> & {\n defaultBranch?: number;\n onBranchChange?: (branchIndex: number) => void;\n};\n\nconst MessageBranch = ({\n defaultBranch = 0,\n onBranchChange,\n className,\n ...props\n}: MessageBranchProps): ReactNode => {\n const [currentBranch, setCurrentBranch] = useState(defaultBranch);\n const [branches, setBranches] = useState<ReactElement[]>([]);\n\n const goToPrevious = useCallback(() => {\n setCurrentBranch((prev) => {\n const newBranch = prev > 0 ? prev - 1 : branches.length - 1;\n onBranchChange?.(newBranch);\n return newBranch;\n });\n }, [branches.length, onBranchChange]);\n\n const goToNext = useCallback(() => {\n setCurrentBranch((prev) => {\n const newBranch = prev < branches.length - 1 ? prev + 1 : 0;\n onBranchChange?.(newBranch);\n return newBranch;\n });\n }, [branches.length, onBranchChange]);\n\n const contextValue = useMemo<MessageBranchContextType>(\n () => ({\n currentBranch,\n totalBranches: branches.length,\n goToPrevious,\n goToNext,\n branches,\n setBranches,\n }),\n [currentBranch, branches, goToPrevious, goToNext, setBranches]\n );\n\n return (\n <MessageBranchContext.Provider value={contextValue}>\n <div\n data-slot=\"message-branch\"\n className={cn('grid w-full gap-2 [&>div]:pb-0', className)}\n {...props}\n />\n </MessageBranchContext.Provider>\n );\n};\n\ntype MessageBranchContentProps = HTMLAttributes<HTMLDivElement>;\n\nconst MessageBranchContent = ({\n children,\n ...props\n}: MessageBranchContentProps): ReactNode[] => {\n const { currentBranch, setBranches, branches } = useMessageBranch();\n const childrenArray = useMemo(\n () => (Array.isArray(children) ? children : [children]),\n [children]\n );\n\n useEffect(() => {\n if (branches.length !== childrenArray.length) {\n setBranches(childrenArray);\n }\n }, [childrenArray, branches, setBranches]);\n\n return childrenArray.map((branch, index) => (\n <div\n data-slot=\"message-branch-content\"\n className={cn(\n 'grid gap-2 overflow-hidden [&>div]:pb-0',\n index === currentBranch ? 'block' : 'hidden'\n )}\n key={branch.key}\n {...props}\n >\n {branch}\n </div>\n ));\n};\n\ntype MessageBranchSelectorProps = HTMLAttributes<HTMLDivElement> & {\n from: UIMessage['role'];\n};\n\nconst MessageBranchSelector = ({\n ...props\n}: MessageBranchSelectorProps): ReactNode => {\n const { totalBranches } = useMessageBranch();\n\n if (totalBranches <= 1) {\n return null;\n }\n\n return (\n <ButtonGroup\n data-slot=\"message-branch-selector\"\n className=\"[&>*:not(:first-child)]:rounded-l-md [&>*:not(:last-child)]:rounded-r-md\"\n orientation=\"horizontal\"\n {...props}\n />\n );\n};\n\ntype MessageBranchPreviousProps = ComponentProps<typeof Button>;\n\nconst MessageBranchPrevious = ({\n children,\n ...props\n}: MessageBranchPreviousProps): ReactNode => {\n const { goToPrevious, totalBranches } = useMessageBranch();\n\n return (\n <Button\n data-slot=\"message-branch-previous\"\n aria-label=\"Previous branch\"\n disabled={totalBranches <= 1}\n onClick={goToPrevious}\n size=\"icon-sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <IconChevronLeft size={14} />}\n </Button>\n );\n};\n\ntype MessageBranchNextProps = ComponentProps<typeof Button>;\n\nconst MessageBranchNext = ({\n children,\n ...props\n}: MessageBranchNextProps): ReactNode => {\n const { goToNext, totalBranches } = useMessageBranch();\n\n return (\n <Button\n data-slot=\"message-branch-next\"\n aria-label=\"Next branch\"\n disabled={totalBranches <= 1}\n onClick={goToNext}\n size=\"icon-sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <IconChevronRight size={14} />}\n </Button>\n );\n};\n\ntype MessageBranchPageProps = HTMLAttributes<HTMLSpanElement>;\n\nconst MessageBranchPage = ({\n className,\n ...props\n}: MessageBranchPageProps): ReactNode => {\n const { currentBranch, totalBranches } = useMessageBranch();\n\n return (\n <ButtonGroupText\n data-slot=\"message-branch-page\"\n className={cn(\n 'border-none bg-transparent text-muted-foreground shadow-none px-2',\n className\n )}\n {...props}\n >\n {currentBranch + 1}/{totalBranches}\n </ButtonGroupText>\n );\n};\n\n/** Streamdown discards unrecognised props, so these go on a wrapper instead. */\ntype MessageResponseHostProps = Pick<\n HTMLAttributes<HTMLDivElement>,\n 'id' | 'role' | 'aria-label' | 'aria-labelledby' | 'aria-describedby'\n> & {\n 'data-testid'?: string;\n};\n\ntype MessageResponseProps = ComponentProps<typeof Streamdown> &\n MessageResponseHostProps;\n\ntype MarkdownComponentProps<T extends keyof JSX.IntrinsicElements> =\n JSX.IntrinsicElements[T] & ExtraProps;\n\nconst messageResponseComponents: Components = {\n h1: ({ children }: MarkdownComponentProps<'h1'>) => (\n <h1 className=\"mt-0 mb-2 scroll-m-20 text-xl font-medium tracking-tightest\">\n {children}\n </h1>\n ),\n h2: ({ children }: MarkdownComponentProps<'h2'>) => (\n <h2 className=\"mt-4 mb-1 scroll-m-20 text-lg font-medium tracking-tightest\">\n {children}\n </h2>\n ),\n h3: ({ children }: MarkdownComponentProps<'h3'>) => (\n <h3 className=\"mt-4 mb-1 scroll-m-20 text-base font-medium tracking-tighter\">\n {children}\n </h3>\n ),\n h4: ({ children }: MarkdownComponentProps<'h4'>) => (\n <h4 className=\"mt-2 mb-0 scroll-m-20 text-sm font-medium tracking-normal\">\n {children}\n </h4>\n ),\n h5: ({ children }: MarkdownComponentProps<'h5'>) => (\n <h5 className=\"mt-0 mb-0 scroll-m-20 text-xs font-medium tracking-tighter\">\n {children}\n </h5>\n ),\n h6: ({ children }: MarkdownComponentProps<'h6'>) => (\n <h6 className=\"mt-0 mb-0 scroll-m-20 text-2xs font-medium tracking-tighter\">\n {children}\n </h6>\n ),\n p: ({ children }: MarkdownComponentProps<'p'>) => (\n <p className=\"mt-2 mb-3 text-base font-normal leading-5 tracking-tightest\">\n {children}\n </p>\n ),\n strong: ({ children }: MarkdownComponentProps<'strong'>) => (\n <strong className=\"font-medium\">{children}</strong>\n ),\n em: ({ children }: MarkdownComponentProps<'em'>) => (\n <em className=\"italic\">{children}</em>\n ),\n b: ({ children }: MarkdownComponentProps<'b'>) => (\n <b className=\"font-medium\">{children}</b>\n ),\n i: ({ children }: MarkdownComponentProps<'i'>) => (\n <i className=\"italic\">{children}</i>\n ),\n ul: ({ children }: MarkdownComponentProps<'ul'>) => (\n <ul className=\"ml-8.25 mb-3 pt-2 pl-0 pb-0 list-disc text-base font-normal tracking-tightest\">\n {children}\n </ul>\n ),\n ol: ({ children }: MarkdownComponentProps<'ol'>) => (\n <ol className=\"ml-8.25 mb-3 pt-2 pl-0 pb-0 list-decimal text-base font-normal tracking-tightest\">\n {children}\n </ol>\n ),\n li: ({ children }: MarkdownComponentProps<'li'>) => (\n <li className=\"py-0\">{children}</li>\n ),\n blockquote: ({ children }: MarkdownComponentProps<'blockquote'>) => (\n <blockquote className=\"my-3 pr-2 pl-2 border-l border-l-default text-sm text-muted-foreground font-normal tracking-tight not-italic\">\n {children}\n </blockquote>\n ),\n hr: () => <hr className=\"my-4 border-default\" />,\n a: ({ children, href, ...props }: MarkdownComponentProps<'a'>) => (\n <a\n className=\"text-link-foreground no-underline hover:underline underline-offset-4\"\n href={href}\n {...props}\n >\n {children}\n </a>\n ),\n table: ({ children }: MarkdownComponentProps<'table'>) => (\n <div\n className=\"my-6 overflow-x-auto\"\n tabIndex={0}\n role=\"group\"\n aria-label=\"Atlas AI Chat Table\"\n >\n <table className=\"w-full\">{children}</table>\n </div>\n ),\n thead: ({ children }: MarkdownComponentProps<'thead'>) => (\n <thead>{children}</thead>\n ),\n tbody: ({ children }: MarkdownComponentProps<'tbody'>) => (\n <tbody>{children}</tbody>\n ),\n tr: ({ children }: MarkdownComponentProps<'tr'>) => (\n <tr className=\"m-0 border-t p-0 even:bg-muted-background\">{children}</tr>\n ),\n th: ({ children }: MarkdownComponentProps<'th'>) => (\n <th className=\"border px-4 py-2 text-left font-bold\">{children}</th>\n ),\n td: ({ children }: MarkdownComponentProps<'td'>) => (\n <td className=\"border px-4 py-2 text-left\">{children}</td>\n ),\n};\n\nconst MessageResponseMarkdown = ({\n className,\n components,\n plugins,\n controls,\n portal,\n ...props\n}: ComponentProps<typeof Streamdown>): JSX.Element => {\n const portalContainer = usePortalContainer();\n\n return (\n <Streamdown\n className={cn(\n 'size-full',\n // Blockquote paragraph overrides\n '[&_blockquote_p]:text-sm',\n '[&_blockquote_p]:tracking-tight',\n // Inline code\n '[&_code]:relative',\n '[&_code]:rounded',\n '[&_code]:bg-muted-background',\n '[&_code]:px-[0.3rem]',\n '[&_code]:py-[0.2rem]',\n '[&_code]:font-mono',\n '[&_code]:text-sm',\n '[&_code]:font-semibold',\n // Code blocks (Streamdown container)\n '[&_div[data-streamdown=\"code-block\"]]:my-4',\n '[&_div[data-streamdown=\"code-block\"]]:w-full',\n '[&_div[data-streamdown=\"code-block\"]]:overflow-hidden',\n '[&_div[data-streamdown=\"code-block\"]]:rounded-xl',\n '[&_div[data-streamdown=\"code-block\"]]:border',\n '[&_div[data-streamdown=\"code-block\"]]:border-default',\n // Code block header\n '[&_div[data-streamdown=\"code-block-header\"]]:flex',\n '[&_div[data-streamdown=\"code-block-header\"]]:items-center',\n '[&_div[data-streamdown=\"code-block-header\"]]:justify-between',\n '[&_div[data-streamdown=\"code-block-header\"]]:bg-muted-background/80',\n '[&_div[data-streamdown=\"code-block-header\"]]:px-4',\n '[&_div[data-streamdown=\"code-block-header\"]]:py-3',\n '[&_div[data-streamdown=\"code-block-header\"]]:text-xs',\n '[&_div[data-streamdown=\"code-block-header\"]]:text-muted-foreground',\n // Pre element inside code block\n '[&_div[data-streamdown=\"code-block\"]_pre]:m-0',\n '[&_div[data-streamdown=\"code-block\"]_pre]:overflow-x-auto',\n '[&_div[data-streamdown=\"code-block\"]_pre]:border-t',\n '[&_div[data-streamdown=\"code-block\"]_pre]:border-default',\n '[&_div[data-streamdown=\"code-block\"]_pre]:bg-card-background!',\n '[&_div[data-streamdown=\"code-block\"]_pre]:p-4',\n '[&_div[data-streamdown=\"code-block\"]_pre]:text-sm',\n '[&_div[data-streamdown=\"code-block\"]_pre]:text-medium-foreground!',\n // Code element inside pre\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:static',\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:rounded-none',\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:bg-transparent',\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:p-0',\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:font-mono',\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:text-sm',\n '[&_div[data-streamdown=\"code-block\"]_pre_code]:font-normal',\n // Code block buttons\n '[&_button[data-streamdown=\"code-block-copy-button\"]]:cursor-pointer',\n '[&_button[data-streamdown=\"code-block-copy-button\"]]:p-1',\n '[&_button[data-streamdown=\"code-block-copy-button\"]]:text-muted-foreground',\n '[&_button[data-streamdown=\"code-block-copy-button\"]]:transition-all',\n '[&_button[data-streamdown=\"code-block-copy-button\"]]:hover:text-base-foreground',\n '[&_button[data-streamdown=\"code-block-download-button\"]]:cursor-pointer',\n '[&_button[data-streamdown=\"code-block-download-button\"]]:p-1',\n '[&_button[data-streamdown=\"code-block-download-button\"]]:text-muted-foreground',\n '[&_button[data-streamdown=\"code-block-download-button\"]]:transition-all',\n '[&_button[data-streamdown=\"code-block-download-button\"]]:hover:text-base-foreground',\n // Regular pre blocks (not in Streamdown code blocks)\n '[&_pre:not([data-streamdown])]:my-3',\n '[&_pre:not([data-streamdown])]:mx-0',\n '[&_pre:not([data-streamdown])]:overflow-x-auto',\n '[&_pre:not([data-streamdown])]:rounded-md',\n '[&_pre:not([data-streamdown])]:border',\n '[&_pre:not([data-streamdown])]:bg-card-background',\n '[&_pre:not([data-streamdown])]:p-4',\n '[&_pre:not([data-streamdown])]:text-medium-foreground',\n '[&_pre:not([data-streamdown])]:text-sm',\n '[&_pre:not([data-streamdown])_code]:static',\n '[&_pre:not([data-streamdown])_code]:rounded-none',\n '[&_pre:not([data-streamdown])_code]:bg-transparent',\n '[&_pre:not([data-streamdown])_code]:px-0',\n '[&_pre:not([data-streamdown])_code]:py-0',\n '[&_pre:not([data-streamdown])_code]:font-mono',\n '[&_pre:not([data-streamdown])_code]:text-sm',\n '[&_pre:not([data-streamdown])_code]:font-normal',\n // Mermaid diagram blocks\n '[&_div[data-streamdown=\"mermaid-block\"]]:bg-card-background',\n '[&_div[data-streamdown=\"mermaid-block\"]]:text-base-foreground',\n '[&_div[data-streamdown=\"mermaid-block\"]]:flex',\n '[&_div[data-streamdown=\"mermaid-block\"]]:flex-col',\n '[&_div[data-streamdown=\"mermaid-block\"]]:rounded-lg',\n '[&_div[data-streamdown=\"mermaid-block\"]]:hover:bg-base-background-hover',\n '[&_div[data-streamdown=\"mermaid-block\"]]:border-0',\n // Positioning context for the action strip (see below)\n '[&_div[data-streamdown=\"mermaid-block\"]]:relative',\n // Nested scroll + sticky + pointer-events breaks hit-testing on Mermaid Copy/Download\n // (same class of issue as github.com/vercel/streamdown/issues/494). Force absolute strip.\n '[&_div[data-streamdown=\"mermaid-block\"]>div:has([data-streamdown=\"mermaid-block-actions\"])]:!absolute',\n '[&_div[data-streamdown=\"mermaid-block\"]>div:has([data-streamdown=\"mermaid-block-actions\"])]:!top-2',\n '[&_div[data-streamdown=\"mermaid-block\"]>div:has([data-streamdown=\"mermaid-block-actions\"])]:!right-2',\n '[&_div[data-streamdown=\"mermaid-block\"]>div:has([data-streamdown=\"mermaid-block-actions\"])]:!z-10',\n '[&_div[data-streamdown=\"mermaid-block\"]>div:has([data-streamdown=\"mermaid-block-actions\"])]:!mt-0',\n '[&_div[data-streamdown=\"mermaid-block\"]>div:has([data-streamdown=\"mermaid-block-actions\"])]:!pointer-events-auto',\n // Ensure mermaid container is tall enough for the toolbar (pan/zoom + actions)\n '[&_div[data-streamdown=\"mermaid-block\"]_.relative.w-full]:!min-h-28',\n // KaTeX sizing (overflow rules live in styles.source.css)\n '[&_.katex-display]:my-3',\n '[&_.katex]:text-[1em]',\n // First and last child margin resets\n '[&>*:first-child]:mt-0',\n '[&>*:last-child]:mb-0',\n className\n )}\n components={{ ...messageResponseComponents, ...components }}\n controls={controls ?? MESSAGE_RESPONSE_DEFAULT_STREAMDOWN_CONTROLS}\n plugins={{ ...plugins, mermaid: mermaidPlugin }}\n portal={portal ?? portalContainer}\n {...props}\n />\n );\n};\n\nconst MessageResponse = ({\n id,\n role,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'data-testid': dataTestId,\n ...props\n}: MessageResponseProps): JSX.Element => (\n <div\n data-slot=\"message-response\"\n id={id}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n data-testid={dataTestId}\n >\n <MessageResponseMarkdown {...props} />\n </div>\n);\n\ntype MessageAttachmentProps = HTMLAttributes<HTMLDivElement> & {\n data: FileUIPart;\n className?: string;\n onRemove?: () => void;\n};\n\nfunction MessageAttachment({\n data,\n className,\n onRemove,\n ...props\n}: MessageAttachmentProps): ReactNode {\n const filename = data.filename || '';\n const mediaType =\n data.mediaType?.startsWith('image/') && data.url ? 'image' : 'file';\n const isImage = mediaType === 'image';\n const attachmentLabel = filename || (isImage ? 'Image' : 'Attachment');\n\n return (\n <div\n data-slot=\"message-attachment\"\n className={cn(\n 'group relative size-24 overflow-hidden rounded-lg',\n className\n )}\n {...props}\n >\n {isImage ? (\n <>\n <img\n alt={filename || 'attachment'}\n className=\"size-full object-cover\"\n height={100}\n src={data.url}\n width={100}\n />\n {onRemove && (\n <Button\n aria-label=\"Remove attachment\"\n className=\"absolute top-2 right-2 size-6 rounded-full bg-card-background/80 p-0 opacity-0 backdrop-blur-sm transition-opacity hover:bg-card-background group-hover:opacity-100 [&>svg]:size-3\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n type=\"button\"\n variant=\"ghost\"\n >\n <IconX />\n <span className=\"sr-only\">Remove</span>\n </Button>\n )}\n </>\n ) : (\n <>\n <Tooltip>\n <TooltipTrigger\n render={\n <div className=\"flex size-full shrink-0 items-center justify-center rounded-lg bg-muted-background text-muted-foreground\">\n <IconPaperclip className=\"size-4\" />\n </div>\n }\n />\n <TooltipContent>\n <p>{attachmentLabel}</p>\n </TooltipContent>\n </Tooltip>\n {onRemove && (\n <Button\n aria-label=\"Remove attachment\"\n className=\"size-6 shrink-0 rounded-full p-0 opacity-0 transition-opacity hover:bg-base-background-hover group-hover:opacity-100 [&>svg]:size-3\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n type=\"button\"\n variant=\"ghost\"\n >\n <IconX />\n <span className=\"sr-only\">Remove</span>\n </Button>\n )}\n </>\n )}\n </div>\n );\n}\n\ntype MessageAttachmentsProps = ComponentProps<'div'>;\n\nfunction MessageAttachments({\n children,\n className,\n ...props\n}: MessageAttachmentsProps): ReactNode {\n if (!children) {\n return null;\n }\n\n return (\n <div\n data-slot=\"message-attachments\"\n className={cn(\n 'ml-auto flex w-fit flex-wrap items-start gap-2',\n className\n )}\n {...props}\n >\n {children}\n </div>\n );\n}\n\ntype MessageToolbarProps = ComponentProps<'div'>;\n\nconst MessageToolbar = ({\n className,\n children,\n ...props\n}: MessageToolbarProps): ReactNode => (\n <div\n data-slot=\"message-toolbar\"\n className={cn(\n 'mt-4 flex w-full items-center justify-between gap-4',\n className\n )}\n {...props}\n >\n {children}\n </div>\n);\n\nexport {\n Message,\n MessageAction,\n MessageActions,\n MessageAttachment,\n MessageAttachments,\n MessageAvatar,\n MessageAvatarIcon,\n MessageBranch,\n MessageBranchContent,\n MessageBranchNext,\n MessageBranchPage,\n MessageBranchPrevious,\n MessageBranchSelector,\n MessageContent,\n MessageResponse,\n MessageToolbar,\n};\n"],"names":["createContext","useCallback","useContext","useEffect","useMemo","useState","mermaid","mermaidPlugin","IconChevronLeft","IconChevronRight","IconPaperclip","IconX","Streamdown","usePortalContainer","cn","getInitials","Avatar","AvatarFallback","AvatarIcon","AvatarImage","Button","ButtonGroup","ButtonGroupText","Tooltip","TooltipContent","TooltipTrigger","MESSAGE_RESPONSE_DEFAULT_STREAMDOWN_CONTROLS","Message","className","isResponse","props","div","data-slot","MessageContent","children","MessageAvatar","avatarUrl","name","variant","sizes","fallbackText","alt","src","MessageAvatarIcon","MessageActions","MessageAction","tooltip","label","size","button","type","span","render","p","MessageBranchContext","useMessageBranch","context","Error","MessageBranch","defaultBranch","onBranchChange","currentBranch","setCurrentBranch","branches","setBranches","goToPrevious","prev","newBranch","length","goToNext","contextValue","totalBranches","Provider","value","MessageBranchContent","childrenArray","Array","isArray","map","branch","index","key","MessageBranchSelector","orientation","MessageBranchPrevious","aria-label","disabled","onClick","MessageBranchNext","MessageBranchPage","messageResponseComponents","h1","h2","h3","h4","h5","h6","strong","em","b","i","ul","ol","li","blockquote","hr","a","href","table","tabIndex","role","thead","tbody","tr","th","td","MessageResponseMarkdown","components","plugins","controls","portal","portalContainer","MessageResponse","id","ariaLabel","ariaLabelledBy","ariaDescribedBy","dataTestId","aria-labelledby","aria-describedby","data-testid","MessageAttachment","data","onRemove","filename","mediaType","startsWith","url","isImage","attachmentLabel","img","height","width","e","stopPropagation","MessageAttachments","MessageToolbar"],"mappings":"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,oBACA,0BACA,qCAAqC;QACrC,8CACA,gDACA,yDACA,oDACA,gDACA,wDACA,oBAAoB;QACpB,qDACA,6DACA,gEACA,uEACA,qDACA,qDACA,wDACA,sEACA,gCAAgC;QAChC,iDACA,6DACA,sDACA,4DACA,iEACA,iDACA,qDACA,qEACA,0BAA0B;QAC1B,yDACA,+DACA,iEACA,sDACA,4DACA,0DACA,8DACA,qBAAqB;QACrB,uEACA,4DACA,8EACA,uEACA,mFACA,2EACA,gEACA,kFACA,2EACA,uFACA,qDAAqD;QACrD,uCACA,uCACA,kDACA,6CACA,yCACA,qDACA,sCACA,yDACA,0CACA,8CACA,oDACA,sDACA,4CACA,4CACA,iDACA,+CACA,mDACA,yBAAyB;QACzB,+DACA,iEACA,iDACA,qDACA,uDACA,2EACA,qDACA,uDAAuD;QACvD,qDACA,sFAAsF;QACtF,0FAA0F;QAC1F,yGACA,sGACA,wGACA,qGACA,qGACA,oHACA,+EAA+E;QAC/E,uEACA,0DAA0D;QAC1D,2BACA,yBACA,qCAAqC;QACrC,0BACA,yBACAc;QAEFyF,YAAY;YAAE,GAAG3B,yBAAyB;YAAE,GAAG2B,UAAU;QAAC;QAC1DE,UAAUA,YAAY7F;QACtB4F,SAAS;YAAE,GAAGA,OAAO;YAAEhH,SAASC;QAAc;QAC9CiH,QAAQA,UAAUC;QACjB,GAAG3F,KAAK;;AAGf;AAEA,MAAM4F,kBAAkB,CAAC,EACvBC,EAAE,EACFb,IAAI,EACJ,cAAcc,SAAS,EACvB,mBAAmBC,cAAc,EACjC,oBAAoBC,eAAe,EACnC,eAAeC,UAAU,EACzB,GAAGjG,OACkB,iBACrB,KAACC;QACCC,aAAU;QACV2F,IAAIA;QACJb,MAAMA;QACNzB,cAAYuC;QACZI,mBAAiBH;QACjBI,oBAAkBH;QAClBI,eAAaH;kBAEb,cAAA,KAACX;YAAyB,GAAGtF,KAAK;;;AAUtC,SAASqG,kBAAkB,EACzBC,IAAI,EACJxG,SAAS,EACTyG,QAAQ,EACR,GAAGvG,OACoB;IACvB,MAAMwG,WAAWF,KAAKE,QAAQ,IAAI;IAClC,MAAMC,YACJH,KAAKG,SAAS,EAAEC,WAAW,aAAaJ,KAAKK,GAAG,GAAG,UAAU;IAC/D,MAAMC,UAAUH,cAAc;IAC9B,MAAMI,kBAAkBL,YAAaI,CAAAA,UAAU,UAAU,YAAW;IAEpE,qBACE,KAAC3G;QACCC,aAAU;QACVJ,WAAWd,GACT,qDACAc;QAED,GAAGE,KAAK;kBAER4G,wBACC;;8BACE,KAACE;oBACCnG,KAAK6F,YAAY;oBACjB1G,WAAU;oBACViH,QAAQ;oBACRnG,KAAK0F,KAAKK,GAAG;oBACbK,OAAO;;gBAERT,0BACC,MAACjH;oBACCiE,cAAW;oBACXzD,WAAU;oBACV2D,SAAS,CAACwD;wBACRA,EAAEC,eAAe;wBACjBX;oBACF;oBACAnF,MAAK;oBACLZ,SAAQ;;sCAER,KAAC3B;sCACD,KAACwC;4BAAKvB,WAAU;sCAAU;;;;;2BAKhC;;8BACE,MAACL;;sCACC,KAACE;4BACC2B,sBACE,KAACrB;gCAAIH,WAAU;0CACb,cAAA,KAAClB;oCAAckB,WAAU;;;;sCAI/B,KAACJ;sCACC,cAAA,KAAC6B;0CAAGsF;;;;;gBAGPN,0BACC,MAACjH;oBACCiE,cAAW;oBACXzD,WAAU;oBACV2D,SAAS,CAACwD;wBACRA,EAAEC,eAAe;wBACjBX;oBACF;oBACAnF,MAAK;oBACLZ,SAAQ;;sCAER,KAAC3B;sCACD,KAACwC;4BAAKvB,WAAU;sCAAU;;;;;;;AAOxC;AAIA,SAASqH,mBAAmB,EAC1B/G,QAAQ,EACRN,SAAS,EACT,GAAGE,OACqB;IACxB,IAAI,CAACI,UAAU;QACb,OAAO;IACT;IAEA,qBACE,KAACH;QACCC,aAAU;QACVJ,WAAWd,GACT,kDACAc;QAED,GAAGE,KAAK;kBAERI;;AAGP;AAIA,MAAMgH,iBAAiB,CAAC,EACtBtH,SAAS,EACTM,QAAQ,EACR,GAAGJ,OACiB,iBACpB,KAACC;QACCC,aAAU;QACVJ,WAAWd,GACT,uDACAc;QAED,GAAGE,KAAK;kBAERI;;AAIL,SACEP,OAAO,EACPkB,aAAa,EACbD,cAAc,EACduF,iBAAiB,EACjBc,kBAAkB,EAClB9G,aAAa,EACbQ,iBAAiB,EACjBe,aAAa,EACbgB,oBAAoB,EACpBc,iBAAiB,EACjBC,iBAAiB,EACjBL,qBAAqB,EACrBF,qBAAqB,EACrBjD,cAAc,EACdyF,eAAe,EACfwB,cAAc,GACd"}