@keboola/design 15.0.0 → 15.1.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.
Files changed (108) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/{AIKit-CaAW4GLx.js → AIKit-BR6jfsdI.js} +60 -21
  3. package/dist/AIKit-BR6jfsdI.js.map +1 -0
  4. package/dist/{AlertModal-D4AtpvLS.js → AlertModal-DMsn62JJ.js} +3 -3
  5. package/dist/AlertModal-DMsn62JJ.js.map +1 -0
  6. package/dist/{Badge-5GHIsgRS.js → Badge-CqlOE5A2.js} +10 -10
  7. package/dist/Badge-CqlOE5A2.js.map +1 -0
  8. package/dist/{BrandEditor-CTGtQUFZ.js → BrandEditor-D61pzWRq.js} +3 -3
  9. package/dist/{BrandEditor-CTGtQUFZ.js.map → BrandEditor-D61pzWRq.js.map} +1 -1
  10. package/dist/{Breadcrumb-B2YSNON4.js → Breadcrumb-DbqvDnYl.js} +2 -2
  11. package/dist/{Breadcrumb-B2YSNON4.js.map → Breadcrumb-DbqvDnYl.js.map} +1 -1
  12. package/dist/{ColorModeSwitch-B6UEzG0H.js → ColorModeSwitch-BlrH8jAi.js} +2 -2
  13. package/dist/{ColorModeSwitch-B6UEzG0H.js.map → ColorModeSwitch-BlrH8jAi.js.map} +1 -1
  14. package/dist/{Combobox-CaKqgstG.js → Combobox-BLqX-Tdh.js} +3 -3
  15. package/dist/Combobox-BLqX-Tdh.js.map +1 -0
  16. package/dist/{DateInput-BgbMDJkm.js → DateInput-duinbI9_.js} +2 -2
  17. package/dist/{DateInput-BgbMDJkm.js.map → DateInput-duinbI9_.js.map} +1 -1
  18. package/dist/{DatePicker-BXpDRo-R.js → DatePicker-Cg_aG_N4.js} +2 -2
  19. package/dist/{DatePicker-BXpDRo-R.js.map → DatePicker-Cg_aG_N4.js.map} +1 -1
  20. package/dist/{DateRangeInput-BW0-_jV0.js → DateRangeInput-BYVHf9zo.js} +2 -2
  21. package/dist/{DateRangeInput-BW0-_jV0.js.map → DateRangeInput-BYVHf9zo.js.map} +1 -1
  22. package/dist/{DateRangePicker-C4-DoWac.js → DateRangePicker-m47cSV1r.js} +3 -3
  23. package/dist/{DateRangePicker-C4-DoWac.js.map → DateRangePicker-m47cSV1r.js.map} +1 -1
  24. package/dist/{DropdownMenu-CcVbZ_5u.js → DropdownMenu-Bum99mVf.js} +2 -2
  25. package/dist/DropdownMenu-Bum99mVf.js.map +1 -0
  26. package/dist/{Form-CAofWyMI.js → Form-Dqbt_tIs.js} +2 -2
  27. package/dist/{Form-CAofWyMI.js.map → Form-Dqbt_tIs.js.map} +1 -1
  28. package/dist/HoverCard-Cf9iYyaW.js +26 -0
  29. package/dist/HoverCard-Cf9iYyaW.js.map +1 -0
  30. package/dist/{MermaidDiagram-Te-5gOCU.js → MermaidDiagram-2-EuNu1i.js} +2 -2
  31. package/dist/{MermaidDiagram-Te-5gOCU.js.map → MermaidDiagram-2-EuNu1i.js.map} +1 -1
  32. package/dist/{Modal-CbUz-5YH.js → Modal-DwuvuiUx.js} +3 -3
  33. package/dist/Modal-DwuvuiUx.js.map +1 -0
  34. package/dist/{ModalTitle-cy0Ht9VY.js → ModalTitle-RGWwIMU6.js} +2 -2
  35. package/dist/ModalTitle-RGWwIMU6.js.map +1 -0
  36. package/dist/{PageToolbar-DJ5tdYla.js → PageToolbar-LKP6PiP_.js} +3 -3
  37. package/dist/{PageToolbar-DJ5tdYla.js.map → PageToolbar-LKP6PiP_.js.map} +1 -1
  38. package/dist/{Popconfirm-DwLCYNaF.js → Popconfirm-p72DiagN.js} +2 -2
  39. package/dist/{Popconfirm-DwLCYNaF.js.map → Popconfirm-p72DiagN.js.map} +1 -1
  40. package/dist/{Popover-DtUDwUVO.js → Popover-DnBw5Uay.js} +2 -2
  41. package/dist/Popover-DnBw5Uay.js.map +1 -0
  42. package/dist/{SectionNav-tLK3iF6c.js → SectionNav-6hcIpZLO.js} +3 -3
  43. package/dist/{SectionNav-tLK3iF6c.js.map → SectionNav-6hcIpZLO.js.map} +1 -1
  44. package/dist/{Select-B22hB_-w.js → Select-C6zKeip5.js} +2 -2
  45. package/dist/Select-C6zKeip5.js.map +1 -0
  46. package/dist/{Sheet-0TWKTqid.js → Sheet-DKG20J7W.js} +3 -3
  47. package/dist/Sheet-DKG20J7W.js.map +1 -0
  48. package/dist/{Sidebar-C5hdANBU.js → Sidebar-BlYqasnX.js} +4 -4
  49. package/dist/{Sidebar-C5hdANBU.js.map → Sidebar-BlYqasnX.js.map} +1 -1
  50. package/dist/{TimePicker-CoRpiEM3.js → TimePicker-lk3NGqeK.js} +2 -2
  51. package/dist/{TimePicker-CoRpiEM3.js.map → TimePicker-lk3NGqeK.js.map} +1 -1
  52. package/dist/Workbench-CxgNCs3I.js.map +1 -1
  53. package/dist/{ZoomableSvg-DnFXo2L4.js → ZoomableSvg-CxXKanUR.js} +2 -2
  54. package/dist/{ZoomableSvg-DnFXo2L4.js.map → ZoomableSvg-CxXKanUR.js.map} +1 -1
  55. package/dist/flint.js +1 -1
  56. package/dist/index.d.ts +42 -8
  57. package/dist/index.js +26 -25
  58. package/dist/internal/blocks/AIKit.js +1 -1
  59. package/dist/internal/blocks/BrandEditor.js +1 -1
  60. package/dist/internal/blocks/ChipEditor.js +1 -1
  61. package/dist/internal/blocks/ColorModeSwitch.js +1 -1
  62. package/dist/internal/blocks/DateInput.js +1 -1
  63. package/dist/internal/blocks/DateRangeInput.js +1 -1
  64. package/dist/internal/blocks/ExportMenu.js +1 -1
  65. package/dist/internal/blocks/Form/connectors/ComboboxField.js +1 -1
  66. package/dist/internal/blocks/Form.js +1 -1
  67. package/dist/internal/blocks/MultiCombobox.js +1 -1
  68. package/dist/internal/blocks/PageToolbar.js +1 -1
  69. package/dist/internal/blocks/SectionNav.js +1 -1
  70. package/dist/internal/blocks/SplitButton.js +1 -1
  71. package/dist/internal/blocks/TimeInput.js +1 -1
  72. package/dist/internal/components/AlertModal.js +1 -1
  73. package/dist/internal/components/Badge.js +1 -1
  74. package/dist/internal/components/Breadcrumb.js +1 -1
  75. package/dist/internal/components/Combobox.js +1 -1
  76. package/dist/internal/components/DatePicker.js +1 -1
  77. package/dist/internal/components/DateRangePicker.js +1 -1
  78. package/dist/internal/components/DropdownMenu.js +1 -1
  79. package/dist/internal/components/HoverCard.js +1 -1
  80. package/dist/internal/components/Modal.js +1 -1
  81. package/dist/internal/components/Popconfirm.js +1 -1
  82. package/dist/internal/components/Popover.js +1 -1
  83. package/dist/internal/components/Select.js +1 -1
  84. package/dist/internal/components/Sheet.js +1 -1
  85. package/dist/internal/components/Sidebar.js +1 -1
  86. package/dist/internal/components/TimePicker.js +1 -1
  87. package/dist/internal/components/ZoomableSvg.js +1 -1
  88. package/dist/internal/hooks/useTimeout.js +19 -0
  89. package/dist/internal/hooks/useTimeout.js.map +1 -0
  90. package/dist/markdown-editor.js +3 -3
  91. package/dist/mermaid.js +1 -1
  92. package/dist/rjsf.js +2 -2
  93. package/dist/styles.css +1 -1
  94. package/dist/utils-DwC9u0tM.js.map +1 -1
  95. package/package.json +1 -1
  96. package/src/theme.css +4 -0
  97. package/dist/AIKit-CaAW4GLx.js.map +0 -1
  98. package/dist/AlertModal-D4AtpvLS.js.map +0 -1
  99. package/dist/Badge-5GHIsgRS.js.map +0 -1
  100. package/dist/Combobox-CaKqgstG.js.map +0 -1
  101. package/dist/DropdownMenu-CcVbZ_5u.js.map +0 -1
  102. package/dist/HoverCard-Cv5rmvJq.js +0 -26
  103. package/dist/HoverCard-Cv5rmvJq.js.map +0 -1
  104. package/dist/Modal-CbUz-5YH.js.map +0 -1
  105. package/dist/ModalTitle-cy0Ht9VY.js.map +0 -1
  106. package/dist/Popover-DtUDwUVO.js.map +0 -1
  107. package/dist/Select-B22hB_-w.js.map +0 -1
  108. package/dist/Sheet-0TWKTqid.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AIKit-BR6jfsdI.js","names":["renderVariantIcon","LinkIcon","TableIcon","Table","Table","Table","Table","Table","isEditableTarget"],"sources":["../src/blocks/AIKit/AnswerCommentInput.tsx","../src/blocks/AIKit/AnswerActions.tsx","../src/blocks/AIKit/SourceChip.tsx","../src/blocks/AIKit/AnswerSources.tsx","../src/blocks/AIKit/CollapsibleBody.tsx","../src/blocks/AIKit/CollapsibleStepHeader.tsx","../src/blocks/AIKit/hasMotion.ts","../src/blocks/AIKit/InlineStepDetail.tsx","../src/blocks/AIKit/InlineStepLabel.tsx","../src/blocks/AIKit/AnswerSummary.tsx","../src/blocks/AIKit/AttachmentChip.tsx","../src/blocks/AIKit/ChatInlineIcon.tsx","../src/blocks/AIKit/useCountdown.ts","../src/blocks/AIKit/ChatNotice.tsx","../src/blocks/AIKit/ContextChip.tsx","../src/blocks/AIKit/FileDownloadChip.tsx","../src/blocks/AIKit/FileGalleryTile.tsx","../src/blocks/AIKit/FileGallery.tsx","../src/blocks/AIKit/InlineStepGroup.tsx","../src/blocks/AIKit/JumpToLatest.tsx","../src/blocks/AIKit/DiagramBlock.tsx","../src/blocks/AIKit/diagramChunk.ts","../src/blocks/AIKit/downloadSvgFile.ts","../src/blocks/AIKit/DiagramDownloadButton.tsx","../src/blocks/AIKit/highlightChunk.ts","../src/blocks/AIKit/HighlightedCode.tsx","../src/blocks/AIKit/highlightLanguages.ts","../src/blocks/AIKit/markdownOptions.ts","../src/blocks/AIKit/tableSort.ts","../src/blocks/AIKit/tableSortContext.ts","../src/blocks/AIKit/TableSortProvider.tsx","../src/blocks/AIKit/MarkdownGrid.tsx","../src/blocks/AIKit/MarkdownTableBody.tsx","../src/blocks/AIKit/MarkdownTableHead.tsx","../src/blocks/AIKit/MarkdownTableRow.tsx","../src/blocks/AIKit/svgFence.ts","../src/blocks/AIKit/scopeSvgReferences.ts","../src/blocks/AIKit/filterSvgStyle.ts","../src/blocks/AIKit/sanitizeSvgFence.ts","../src/blocks/AIKit/SvgFencesContext.ts","../src/blocks/AIKit/SvgFenceChart.tsx","../src/blocks/AIKit/diagramLanguages.ts","../src/blocks/AIKit/Markdown.tsx","../src/blocks/AIKit/MarkdownTable.tsx","../src/blocks/AIKit/CollapsedMessageBody.tsx","../src/blocks/AIKit/MessageDeliveryStatus.tsx","../src/blocks/AIKit/MessageTimestamp.tsx","../src/blocks/AIKit/MessageBubble.tsx","../src/blocks/AIKit/ModeChip.tsx","../src/blocks/AIKit/PlanApproval.tsx","../src/blocks/AIKit/PlanRewritingIndicator.tsx","../src/blocks/AIKit/constants.ts","../src/blocks/AIKit/AnimatedHeight.tsx","../src/blocks/AIKit/PromptInputAction.tsx","../src/blocks/AIKit/PromptInputCommands.tsx","../src/blocks/AIKit/PromptInputMenuTrigger.tsx","../src/blocks/AIKit/PromptInputSubmit.tsx","../src/blocks/AIKit/usePromptHistory.ts","../src/blocks/AIKit/PromptInput.tsx","../src/blocks/AIKit/Question.tsx","../src/blocks/AIKit/QuestionBlock.tsx","../src/blocks/AIKit/streamingMarkdown.ts","../src/blocks/AIKit/SuggestedPrompt.tsx","../src/blocks/AIKit/ThinkingIndicator.tsx","../src/blocks/AIKit/ToolCall/ToolCallApprovalActions.tsx","../src/blocks/AIKit/ToolCall/ToolCallApprovalNotice.tsx","../src/blocks/AIKit/ToolCall/ToolCallApprovalRecord.tsx","../src/blocks/AIKit/ToolCall/toolCallApprovalStatus.ts","../src/blocks/AIKit/ToolCall/useApprovalShortcut.ts","../src/blocks/AIKit/ToolCall/ToolCallApproval.tsx","../src/blocks/AIKit/ToolCall/ToolCallChip.tsx","../src/blocks/AIKit/ToolCallStatusHeader.tsx","../src/blocks/AIKit/usageStatsHelpers.ts","../src/blocks/AIKit/UsageBar.tsx","../src/blocks/AIKit/UsageStatsRing.tsx","../src/blocks/AIKit/UsageStats.tsx"],"sourcesContent":["import { useRef, useState } from 'react';\nimport type { KeyboardEvent } from 'react';\n\nimport { TextInput } from '../TextInput';\n\nconst MAX_COMMENT_LENGTH = 2000;\n\ntype Props = {\n placeholder: string;\n onSubmit: (text: string) => void;\n};\n\n/**\n * One-line follow-up to a thumbs-down.\n *\n * - Submits on Enter or blur, trimmed, and only when the text differs from the last one sent.\n * - Never submits an empty comment.\n */\nexport const AnswerCommentInput = ({ placeholder, onSubmit }: Props) => {\n const [text, setText] = useState('');\n const lastSubmittedRef = useRef('');\n\n const submit = () => {\n const comment = text.trim();\n if (!comment || comment === lastSubmittedRef.current) return;\n lastSubmittedRef.current = comment;\n onSubmit(comment);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key !== 'Enter') return;\n event.preventDefault();\n submit();\n };\n\n return (\n <TextInput\n value={text}\n onValueChange={setText}\n onKeyDown={handleKeyDown}\n onBlur={submit}\n maxLength={MAX_COMMENT_LENGTH}\n placeholder={placeholder}\n aria-label={placeholder}\n className=\"tw:w-64 tw:max-w-full tw:[&_input]:text-ellipsis\"\n />\n );\n};\n","import type { ReactNode } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { ButtonGroup } from '../../components/ButtonGroup';\nimport { Tooltip } from '../../components/Tooltip';\nimport { RotateCcw, ThumbsDown, ThumbsUp } from '../../icons';\nimport { cn } from '../../utils';\nimport { ClipboardButton } from '../ClipboardButton';\n\nimport { AnswerCommentInput } from './AnswerCommentInput';\n\n/** Which way a reader rated an answer. */\nexport type AnswerVote = 'up' | 'down';\n\nconst VOTE_BUTTONS = [\n { vote: 'up', icon: <ThumbsUp className=\"tw:size-4\" /> },\n { vote: 'down', icon: <ThumbsDown className=\"tw:size-4\" /> },\n] as const;\n\nconst DEFAULT_LABELS = { up: 'Good answer', down: 'Bad answer' } as const;\n\n/** Roomier for a panel; compact for a dense transcript. */\nconst SIZES = {\n small: { button: 'icon-xs', gap: 'extra-small' },\n medium: { button: 'icon-sm', gap: 'little-small' },\n} as const;\n\n/** A control a host adds beside copy and thumbs, drawn in their style. */\nexport type AnswerExtraAction = {\n id: string;\n label: string;\n icon: ReactNode;\n onSelect: () => void;\n disabled?: boolean;\n};\n\ntype Props = {\n /** The answer as text, for the clipboard; empty or absent draws no copy button. */\n copyText?: string;\n /** The vote already recorded against this answer, or `null` for none. */\n vote: AnswerVote | null;\n onVote: (vote: AnswerVote) => void;\n /** Extra controls, e.g. a report button; drawn ahead of copy. */\n actions?: ReactNode;\n /** Extra controls drawn like copy and thumbs, right after Copy in either layout; each is named and tooltipped by `label`. */\n extraActions?: AnswerExtraAction[];\n /** What the thumbs call the thing rated: \"response\" or \"answer\". */\n labels?: { up: string; down: string };\n /** Announced politely once a vote lands, if set. */\n confirmation?: { up: string; down: string };\n size?: keyof typeof SIZES;\n /** `inline` (default): one group. `split`: votes left, actions right, at the bubble's edges. */\n layout?: 'inline' | 'split';\n /** Fires on copy; the button does the copying itself. */\n onCopy?: () => void;\n /** Opt-in. After a thumbs-down, a one-line input sends the reader's comment here; the caller upserts it. */\n onDownComment?: (text: string) => void;\n commentPlaceholder?: string;\n /** Opt-in. Draws a button that asks the question again. */\n onRegenerate?: () => void;\n regenerateLabel?: string;\n};\n\n/**\n * Copy and thumbs up/down for a finished answer.\n *\n * - Always rendered, never hover-only, so it is reachable without a pointer.\n * - A vote can be changed but not withdrawn; pressing the pressed one re-sends it.\n * - The caller owns the recorded vote and the write.\n */\nexport const AnswerActions = ({\n copyText,\n vote,\n onVote,\n onCopy,\n actions,\n extraActions = [],\n labels = DEFAULT_LABELS,\n confirmation,\n size = 'small',\n layout = 'inline',\n onDownComment,\n commentPlaceholder = 'What was wrong? (optional)',\n onRegenerate,\n regenerateLabel = 'Ask again',\n}: Props) => {\n const { button, gap } = SIZES[size];\n\n const votes = VOTE_BUTTONS.map(({ vote: candidate, icon }) => {\n const isRecorded = vote === candidate;\n const label = labels[candidate];\n\n return (\n <Tooltip key={candidate} tooltip={label} placement=\"top\" triggerAsChild>\n <Button\n size={button}\n variant=\"invisible\"\n className={cn(\n isRecorded &&\n candidate === 'up' &&\n 'tw:bg-success/10 tw:text-success tw:hover:not-disabled:bg-success/20 tw:hover:not-disabled:text-success',\n isRecorded &&\n candidate === 'down' &&\n 'tw:bg-destructive/10 tw:text-destructive tw:hover:not-disabled:bg-destructive/20 tw:hover:not-disabled:text-destructive',\n )}\n aria-label={label}\n aria-pressed={isRecorded}\n onClick={() => onVote(candidate)}\n >\n {icon}\n </Button>\n </Tooltip>\n );\n });\n\n const copy = copyText ? (\n <ClipboardButton\n text={copyText}\n tooltip=\"Copy answer\"\n size={button}\n variant=\"invisible\"\n onClick={onCopy}\n />\n ) : null;\n\n const regenerate = onRegenerate ? (\n <Tooltip tooltip={regenerateLabel} placement=\"top\" triggerAsChild>\n <Button size={button} variant=\"invisible\" aria-label={regenerateLabel} onClick={onRegenerate}>\n <RotateCcw className=\"tw:size-4\" />\n </Button>\n </Tooltip>\n ) : null;\n\n const extras = extraActions.map(({ id, label, icon, onSelect, disabled }) => (\n <Tooltip key={id} tooltip={label} placement=\"top\" triggerAsChild>\n <Button\n size={button}\n variant=\"invisible\"\n aria-label={label}\n disabled={disabled}\n onClick={onSelect}\n >\n {icon}\n </Button>\n </Tooltip>\n ));\n\n const comment =\n onDownComment && vote === 'down' ? (\n <AnswerCommentInput placeholder={commentPlaceholder} onSubmit={onDownComment} />\n ) : null;\n\n // Mounted empty: a live region that arrives with its text is generally not announced.\n const said = confirmation ? (\n <span\n aria-live=\"polite\"\n className=\"tw:ml-1 tw:text-xs tw:font-medium tw:text-foreground tw:empty:hidden tw:animate-in tw:fade-in tw:slide-in-from-left-1 tw:duration-300\"\n >\n {vote ? confirmation[vote] : ''}\n </span>\n ) : null;\n\n if (layout === 'split') {\n return (\n <div className=\"tw:flex tw:w-full tw:flex-wrap tw:items-center tw:justify-between tw:gap-2\">\n <ButtonGroup space={gap} aria-label=\"Answer actions\">\n {votes}\n {said}\n </ButtonGroup>\n {comment}\n <ButtonGroup space={gap}>\n {actions}\n {regenerate}\n {copy}\n {extras}\n </ButtonGroup>\n </div>\n );\n }\n\n const group = (\n <ButtonGroup space={gap} aria-label=\"Answer actions\">\n {copy}\n {extras}\n {votes}\n {regenerate}\n {actions}\n {said}\n </ButtonGroup>\n );\n\n if (!comment) return group;\n\n return (\n <div className=\"tw:flex tw:flex-wrap tw:items-center tw:gap-2\">\n {group}\n {comment}\n </div>\n );\n};\n","import type { ReactNode } from 'react';\n\nimport { cn } from '../../utils';\n\nexport type SourceState = 'verified' | 'unverified' | 'neutral';\n\nexport type SourceChipProps = {\n label: string;\n /** `verified`: a tool call supports it. `unverified`: named but never touched. `neutral`: nothing to check against. */\n state?: SourceState;\n /** What kind of thing it is (e.g. \"table\"); part of the accessible name, not the face. */\n kind?: string;\n icon?: ReactNode;\n /** Renders a link; also takes `onClick` for an in-page open that keeps the link as a fallback. */\n href?: string;\n /** Opens the link in a new tab. */\n external?: boolean;\n onClick?: () => void;\n title?: string;\n className?: string;\n};\n\nconst STATE_CLASSES = {\n verified: 'tw:border-solid tw:border-success/30 tw:bg-success/10 tw:text-foreground',\n unverified: 'tw:border-dashed tw:border-warning/60 tw:bg-warning/10 tw:text-foreground',\n neutral: 'tw:border-solid tw:border-border tw:bg-muted tw:text-foreground',\n} as const satisfies Record<SourceState, string>;\n\nconst STATE_WORD: Partial<Record<SourceState, string>> = {\n verified: 'verified',\n unverified: 'unverified',\n};\n\nconst accessibleName = ({ kind, label, state = 'neutral' }: SourceChipProps) =>\n [[kind, label].filter(Boolean).join(' '), STATE_WORD[state]].filter(Boolean).join(', ');\n\n/**\n * One cited source in an answer's provenance row.\n *\n * - The verdict rides the border and the accessible name, not the visible text.\n * - A link when it has `href`, a button when it only has `onClick`, a plain label otherwise.\n * - A plain left click goes to `onClick`; modified clicks keep the link's own behaviour.\n */\nexport const SourceChip = (props: SourceChipProps) => {\n const { label, state = 'neutral', icon, href, external, onClick, title, className } = props;\n const classes = cn(\n 'tailwindcss-preflight tw:inline-flex tw:h-6 tw:max-w-64 tw:min-w-0 tw:items-center tw:gap-1 tw:rounded-md tw:border tw:px-2 tw:text-xs tw:no-underline',\n STATE_CLASSES[state],\n (href || onClick) &&\n 'tw:cursor-pointer tw:hover:bg-hover tw:focus-visible:outline-none tw:focus-visible:ring-2 tw:focus-visible:ring-ring',\n className,\n );\n const content = (\n <>\n {icon && (\n <span aria-hidden className=\"tw:inline-flex tw:shrink-0 tw:[&_svg]:size-3.5\">\n {icon}\n </span>\n )}\n <span className=\"tw:min-w-0 tw:truncate\">{label}</span>\n </>\n );\n const common = { 'aria-label': accessibleName(props), title, 'data-state': state };\n\n if (href) {\n return (\n <a\n {...common}\n href={href}\n target={external ? '_blank' : undefined}\n rel={external ? 'noopener noreferrer' : undefined}\n className={classes}\n onClick={(event) => {\n const isModified = event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;\n if (!onClick || isModified || event.button !== 0) return;\n event.preventDefault();\n onClick();\n }}\n >\n {content}\n </a>\n );\n }\n if (onClick) {\n return (\n <button\n {...common}\n type=\"button\"\n className={cn(classes, 'tw:bg-clip-padding')}\n onClick={onClick}\n >\n {content}\n </button>\n );\n }\n return (\n <span {...common} className={classes}>\n {content}\n </span>\n );\n};\n","import { useState } from 'react';\nimport type { ReactNode } from 'react';\n\nimport { TriangleAlert } from '../../icons';\nimport { cn } from '../../utils';\n\nimport type { SourceChipProps } from './SourceChip';\nimport { SourceChip } from './SourceChip';\n\nexport const ANSWER_SOURCES_VISIBLE = 6;\n\nexport type AnswerSource = SourceChipProps & { id: string };\n\ntype Props = {\n sources: AnswerSource[];\n /** Row heading. */\n label?: string;\n /** Shown instead of chips when `sources` is empty. */\n emptyLabel?: string;\n /** Chips shown before \"+N more\". */\n visibleCount?: number;\n /** Extra line under the row, e.g. the assumptions the answer made. */\n footnote?: ReactNode;\n className?: string;\n};\n\n/**\n * The provenance row under an answer: where its figures came from.\n *\n * - Says \"N unverified\" once, instead of on every chip, so checked sources can look calm.\n * - Collapses past `visibleCount` behind a \"+N more\" toggle.\n * - Empty `sources` states that none were declared, which is itself information.\n */\nexport const AnswerSources = ({\n sources,\n label = 'Sources',\n emptyLabel = 'none declared',\n visibleCount = ANSWER_SOURCES_VISIBLE,\n footnote,\n className,\n}: Props) => {\n const [isExpanded, setIsExpanded] = useState(false);\n const isCollapsible = sources.length > visibleCount;\n const shown = isCollapsible && !isExpanded ? sources.slice(0, visibleCount) : sources;\n const unverifiedCount = sources.filter((source) => source.state === 'unverified').length;\n\n return (\n <div className={cn('tailwindcss-preflight tw:flex tw:flex-col tw:gap-1 tw:text-xs', className)}>\n <div className=\"tw:flex tw:flex-wrap tw:items-center tw:gap-1.5\">\n <span className=\"tw:font-medium tw:text-muted-foreground\">{label}</span>\n {sources.length === 0 && <span className=\"tw:text-muted-foreground\">{emptyLabel}</span>}\n {shown.map(({ id, ...chip }) => (\n <SourceChip key={id} {...chip} />\n ))}\n {isCollapsible && (\n <button\n type=\"button\"\n aria-expanded={isExpanded}\n onClick={() => setIsExpanded((current) => !current)}\n className=\"tw:cursor-pointer tw:border-0 tw:bg-transparent tw:p-0 tw:text-xs tw:text-muted-foreground tw:underline tw:hover:text-foreground\"\n >\n {isExpanded ? 'Show fewer' : `+${sources.length - visibleCount} more`}\n </button>\n )}\n {unverifiedCount > 0 && (\n <span\n className=\"tw:inline-flex tw:items-center tw:gap-1 tw:text-warning\"\n title=\"No tool call in this turn touched these: the answer named them, nothing ran on them.\"\n >\n <TriangleAlert aria-hidden className=\"tw:size-3.5\" />\n {unverifiedCount} unverified\n </span>\n )}\n </div>\n {footnote}\n </div>\n );\n};\n","import type { ReactNode, TransitionEvent } from 'react';\n\nimport { cn } from '../../utils';\n\ntype Props = {\n isExpanded: boolean;\n isClosing: boolean;\n onClosed: () => void;\n children: ReactNode;\n};\n\nexport const CollapsibleBody = ({ isExpanded, isClosing, onClosed, children }: Props) => {\n const handleTransitionEnd = (event: TransitionEvent<HTMLDivElement>) => {\n if (event.target !== event.currentTarget) return;\n if (event.propertyName !== 'grid-template-rows') return;\n if (!isExpanded) onClosed();\n };\n\n return (\n <div\n className={cn(\n 'tw:grid tw:transition-[grid-template-rows] tw:duration-300 tw:ease-out tw:motion-reduce:transition-none',\n isExpanded ? 'tw:grid-rows-[1fr]' : 'tw:grid-rows-[0fr]',\n )}\n onTransitionEnd={handleTransitionEnd}\n >\n <div className=\"tw:min-h-0 tw:overflow-hidden\">{(isExpanded || isClosing) && children}</div>\n </div>\n );\n};\n","import type { ReactNode } from 'react';\n\nimport { ChevronDown, CircleCheck, Loader2, XCircle } from '../../icons';\nimport { cn } from '../../utils';\n\ntype Variant = 'success' | 'error' | 'processing' | 'dismissed';\n\ntype Props = {\n isExpanded: boolean;\n onToggle: () => void;\n label: ReactNode;\n variant?: Variant;\n};\n\n// Chrome speaks grey: step headers are meta-information, so they read in\n// muted ink and darken on hover — blue is reserved for genuinely interactive\n// elements (links, buttons), and status colour lives only in the icon. Error\n// keeps its tinted label: a failed step is content, not chrome.\nconst variantClasses: Record<Variant, string> = {\n success:\n 'tw:text-muted-foreground tw:focus-visible:outline-ring tw:not-disabled:hover:text-foreground',\n error:\n 'tw:text-destructive tw:focus-visible:outline-destructive tw:not-disabled:hover:text-destructive',\n processing:\n 'tw:text-muted-foreground tw:focus-visible:outline-ring tw:not-disabled:hover:text-foreground',\n dismissed:\n 'tw:text-muted-foreground tw:focus-visible:outline-ring tw:not-disabled:hover:text-foreground',\n};\n\n// Icons one step quieter than the label so the row reads text-first.\nconst iconClasses = 'tw:size-3.5 tw:shrink-0 tw:basis-3.5 tw:opacity-70';\n\n// What the icon says, for a reader who is not looking at it. Joins the button's accessible name,\n// so a closed group announces how the run came out and not only what it was called.\nconst variantStatus: Record<Variant, string> = {\n success: 'finished',\n error: 'failed',\n processing: 'running',\n dismissed: 'not run',\n};\n\nconst renderVariantIcon = (variant: Variant) => {\n if (variant === 'processing') {\n return <Loader2 className={cn(iconClasses, 'tw:animate-spin')} />;\n }\n // `error` and `dismissed` share the mark and take their ink from the\n // button's variant class — `destructive` for a real failure,\n // `muted-foreground` for a step the user waved off.\n if (variant === 'error' || variant === 'dismissed') {\n return <XCircle className={iconClasses} />;\n }\n return <CircleCheck className={iconClasses} />;\n};\n\nexport const CollapsibleStepHeader = ({\n isExpanded,\n onToggle,\n label,\n variant = 'success',\n}: Props) => {\n // `data-variant` is how the run came out, for a selector: an E2E test asserting on an outcome\n // would otherwise have to read the icon's shape or the label's ink.\n return (\n <button\n type=\"button\"\n aria-expanded={isExpanded}\n onClick={onToggle}\n data-variant={variant}\n className={cn(\n 'tw:flex tw:w-fit tw:items-center tw:gap-1.5 tw:text-left tw:text-xs tw:font-medium tw:transition-colors tw:focus-visible:outline tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:disabled:opacity-40',\n variantClasses[variant],\n )}\n >\n {renderVariantIcon(variant)}\n <span className=\"tw:min-w-0\">\n {label}\n <span className=\"tw:sr-only\">{` (${variantStatus[variant]})`}</span>\n {/* A word joiner (U+2060) keeps the chevron on the label's last line —\n an inline chevron with nothing binding it to the preceding word\n orphans onto a line of its own at some container widths. */}\n <span className=\"tw:whitespace-nowrap\">\n {'⁠'}\n <ChevronDown\n className={cn(\n 'tw:ml-1.5 tw:inline-block tw:size-3.5 tw:align-middle tw:transition-transform',\n isExpanded && 'tw:rotate-180',\n )}\n />\n </span>\n </span>\n </button>\n );\n};\n","export const hasMotion = () =>\n typeof window.matchMedia === 'function' &&\n !window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n","import type { ReactNode } from 'react';\n\ntype Props = {\n children: ReactNode;\n};\n\nexport const InlineStepDetail = ({ children }: Props) => (\n // `ml-2.5` is half of the `size-5` icon box `InlineStepLabel` puts beside a\n // step, so the rule falls on that icon's centre line rather than 2px inside\n // it. Anything drawing a run of steps can then line its own connector up with\n // the same number.\n <div className=\"tw:ml-2.5 tw:whitespace-pre-wrap tw:border-l tw:border-border tw:pl-3 tw:text-xs tw:text-muted-foreground\">\n {children}\n </div>\n);\n\nexport type { Props as InlineStepDetailProps };\n","import { useState } from 'react';\nimport type { ReactNode } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { CircleCheck, Loader2, XCircle } from '../../icons';\n\n/**\n * How a step reads in one mark.\n *\n * - A step that failed and then succeeded on retry is `success`.\n * - A step that was stopped before it finished is `dismissed`.\n */\ntype Variant = 'processing' | 'success' | 'error' | 'dismissed';\n\ntype Props = {\n variant: Variant;\n children: ReactNode;\n /** Quiet trailing text after the label, e.g. how long the step took. */\n meta?: ReactNode;\n /** Opt-in. What the step did or returned, behind a Details toggle on the row. */\n detail?: ReactNode;\n defaultExpanded?: boolean;\n};\n\n// Only a real error takes status red; success/dismissed stay muted.\nconst renderVariantIcon = (variant: Variant) => {\n if (variant === 'processing') {\n return <Loader2 className=\"tw:size-3.5 tw:animate-spin tw:text-muted-foreground\" />;\n }\n if (variant === 'error') {\n return <XCircle className=\"tw:size-3.5 tw:text-destructive\" />;\n }\n if (variant === 'dismissed') {\n return <XCircle className=\"tw:size-3.5 tw:text-muted-foreground/50\" />;\n }\n return <CircleCheck className=\"tw:size-3.5 tw:text-muted-foreground/50\" />;\n};\n\nexport const InlineStepLabel = ({\n variant,\n children,\n meta,\n detail,\n defaultExpanded = false,\n}: Props) => {\n const [isExpanded, setIsExpanded] = useState(defaultExpanded);\n\n const row = (\n <div className=\"tw:flex tw:min-w-0 tw:items-center tw:gap-1\">\n {/* Masks a connector behind it with `--inline-step-surface` (transparent when unset).\n `relative` is required: the absolute connector otherwise paints above static content. */}\n <div className=\"tw:relative tw:flex tw:size-5 tw:shrink-0 tw:items-center tw:justify-center tw:[background:var(--inline-step-surface,transparent)]\">\n {renderVariantIcon(variant)}\n </div>\n <div className=\"tw:flex tw:min-w-0 tw:flex-wrap tw:items-center tw:gap-x-1.5 tw:gap-y-1 tw:text-xs tw:font-medium tw:text-muted-foreground\">\n {children}\n {meta && <span className=\"tw:font-normal tw:text-muted-foreground\">{meta}</span>}\n {detail && (\n <Button\n variant=\"inline\"\n size=\"small\"\n className=\"tw:px-0\"\n aria-expanded={isExpanded}\n onClick={() => setIsExpanded((value) => !value)}\n >\n {isExpanded ? 'Hide details' : 'Details'}\n </Button>\n )}\n </div>\n </div>\n );\n\n if (!detail) return row;\n\n return (\n <div className=\"tw:flex tw:min-w-0 tw:flex-col tw:gap-1\">\n {row}\n {isExpanded && <div className=\"tw:min-w-0 tw:pl-6 tw:text-xs\">{detail}</div>}\n </div>\n );\n};\n\nexport type { Variant as InlineStepLabelVariant, Props as InlineStepLabelProps };\n","import { type ReactNode, useState } from 'react';\n\nimport { CollapsibleBody } from './CollapsibleBody';\nimport { CollapsibleStepHeader } from './CollapsibleStepHeader';\nimport { hasMotion } from './hasMotion';\nimport { InlineStepDetail } from './InlineStepDetail';\nimport { InlineStepLabel } from './InlineStepLabel';\n\ntype AnswerItem = {\n question: string;\n answer?: string;\n};\n\ntype Variant = 'success' | 'dismissed' | 'expired';\n\ntype Props = {\n items: readonly AnswerItem[];\n variant?: Variant;\n /** Follows the header label, e.g. `Cancelled`; defaults to `Expired` for the `expired` variant. */\n statusLabel?: string;\n /** Why the questions are in their state, shown first once expanded. */\n statusMessage?: ReactNode;\n noAnswerLabel?: string;\n onExpandToggle?: (next: boolean) => void;\n};\n\nconst SECTION_LABELS: Record<Variant, string> = {\n success: 'Answered questions',\n dismissed: 'Dismissed questions',\n expired: 'Expired questions',\n};\n\nconst STEP_VARIANT: Record<Variant, 'success' | 'dismissed'> = {\n success: 'success',\n dismissed: 'dismissed',\n expired: 'dismissed',\n};\n\nconst DEFAULT_STATUS_LABEL: Partial<Record<Variant, string>> = { expired: 'Expired' };\n\nexport const AnswerSummary = ({\n items,\n variant = 'success',\n statusLabel = DEFAULT_STATUS_LABEL[variant],\n statusMessage,\n noAnswerLabel = 'No answer',\n onExpandToggle,\n}: Props) => {\n const [isExpanded, setIsExpanded] = useState(false);\n const [isClosing, setIsClosing] = useState(false);\n const toggle = () => {\n const next = !isExpanded;\n if (!next) setIsClosing(hasMotion());\n setIsExpanded(next);\n onExpandToggle?.(next);\n };\n const count = items.length;\n const [firstItem] = items;\n const questionLabel = count === 1 && firstItem ? firstItem.question : `${count} questions`;\n const label = statusLabel ? (\n <>\n {questionLabel} <span className=\"tw:font-normal\">{statusLabel}</span>\n </>\n ) : (\n questionLabel\n );\n const stepVariant = STEP_VARIANT[variant];\n\n return (\n <section className=\"tw:mt-4 tw:flex tw:flex-col\" aria-label={SECTION_LABELS[variant]}>\n <CollapsibleStepHeader\n isExpanded={isExpanded}\n onToggle={toggle}\n variant={stepVariant}\n label={label}\n />\n\n <CollapsibleBody\n isExpanded={isExpanded}\n isClosing={isClosing}\n onClosed={() => setIsClosing(false)}\n >\n <div className=\"tw:flex tw:flex-col tw:gap-4 tw:pt-4 tw:pl-5\">\n {statusMessage != null && (\n <p className=\"tw:m-0 tw:text-xs tw:text-muted-foreground\">{statusMessage}</p>\n )}\n {items.map(({ question, answer }, index) => (\n <div key={`${index}-${question}`} className=\"tw:flex tw:flex-col tw:gap-1\">\n <InlineStepLabel variant={stepVariant}>{question}</InlineStepLabel>\n <InlineStepDetail>\n {answer && answer.length > 0 ? answer : noAnswerLabel}\n </InlineStepDetail>\n </div>\n ))}\n </div>\n </CollapsibleBody>\n </section>\n );\n};\n\nexport type {\n AnswerItem as AnswerSummaryItem,\n Props as AnswerSummaryProps,\n Variant as AnswerSummaryVariant,\n};\n","import type { ReactNode } from 'react';\n\nimport { Tooltip } from '../../components/Tooltip';\nimport { CircleAlert, FileText, LoaderCircle, X } from '../../icons';\nimport { cn } from '../../utils';\n\nexport type AttachmentStatus = 'uploading' | 'ready' | 'error';\n\ntype Props = {\n name: string;\n /** Replaces the file glyph while the upload is not failing. */\n thumbnailUrl?: string;\n /** Replaces the glyph or thumbnail while the upload is not failing, e.g. a table icon. */\n lead?: ReactNode;\n /** Replaces the plain name text, e.g. a link; `name` still names the remove control. */\n label?: ReactNode;\n status: AttachmentStatus;\n /** Shown as a tooltip on an `error` chip. */\n error?: string;\n onRemove: () => void;\n /** Extra content after the name, e.g. a size. */\n trailing?: ReactNode;\n className?: string;\n};\n\ntype LeadProps = Pick<Props, 'status' | 'thumbnailUrl' | 'lead'>;\n\nconst Lead = ({ status, thumbnailUrl, lead }: LeadProps) => {\n if (status === 'uploading') {\n return <LoaderCircle aria-hidden className=\"tw:size-4 tw:shrink-0 tw:animate-spin\" />;\n }\n if (status === 'error') {\n return <CircleAlert aria-hidden className=\"tw:size-4 tw:shrink-0 tw:text-destructive\" />;\n }\n if (lead) return lead;\n if (thumbnailUrl) {\n return (\n <img\n src={thumbnailUrl}\n alt=\"\"\n className=\"tw:size-4 tw:shrink-0 tw:rounded-sm tw:object-cover\"\n />\n );\n }\n return <FileText aria-hidden className=\"tw:size-4 tw:shrink-0\" />;\n};\n\n/**\n * A file attached to a message being composed.\n *\n * - Capped width with a truncating name, so a long filename cannot push the text away.\n * - `error` explains itself in a tooltip; the remove control stays available in every status.\n */\nexport const AttachmentChip = ({\n name,\n thumbnailUrl,\n lead,\n label,\n status,\n error,\n onRemove,\n trailing,\n className,\n}: Props) => {\n const chip = (\n <span\n data-status={status}\n className={cn(\n 'tailwindcss-preflight tw:inline-flex tw:h-6 tw:min-w-0 tw:max-w-48 tw:items-center tw:gap-1 tw:rounded-md tw:bg-muted tw:px-2 tw:text-xs tw:text-muted-foreground',\n status === 'error' && 'tw:text-destructive',\n className,\n )}\n >\n <Lead status={status} thumbnailUrl={thumbnailUrl} lead={lead} />\n {label ?? <span className=\"tw:min-w-0 tw:truncate\">{name}</span>}\n {trailing}\n <button\n type=\"button\"\n aria-label={`Remove ${name}`}\n onClick={onRemove}\n className=\"tw:-mr-1 tw:shrink-0 tw:cursor-pointer tw:rounded-sm tw:border-0 tw:bg-transparent tw:p-0 tw:text-muted-foreground tw:hover:text-foreground tw:focus-visible:outline-none tw:focus-visible:ring-2 tw:focus-visible:ring-ring\"\n >\n <X className=\"tw:size-3.5\" />\n </button>\n </span>\n );\n\n if (status !== 'error' || !error) return chip;\n return (\n <Tooltip tooltip={error} placement=\"top\" triggerAsChild>\n {chip}\n </Tooltip>\n );\n};\n","import type { ChatInlineIconName } from '@keboola/agent-vocabulary';\n\nimport type { LucideIcon } from '../../icons';\nimport {\n AlertCircle,\n ArrowDown,\n ArrowLeft,\n ArrowRight,\n ArrowUp,\n Ban,\n BarChart3,\n Bell,\n Bookmark,\n BookOpen,\n Box,\n Bug,\n Calendar,\n ChartBar,\n ChartPie,\n Check,\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n ChevronUp,\n Circle,\n CircleAlert,\n CircleCheck,\n CircleHelp,\n CirclePause,\n CirclePlay,\n CirclePlus,\n CircleStop,\n CircleX,\n Clock,\n Cloud,\n Cog,\n Copy,\n Database,\n Download,\n Ellipsis,\n ExternalLink,\n Eye,\n File,\n FilePen,\n FileText,\n Filter,\n Flag,\n Folder,\n Gauge,\n GitBranch,\n GitMerge,\n GitPullRequest,\n Globe,\n Hand,\n HardDrive,\n History,\n Hourglass,\n Info,\n Key,\n Layers,\n Lightbulb,\n LineChart,\n Link as LinkIcon,\n List,\n ListChecks,\n Loader2,\n Lock,\n Mail,\n Minus,\n Package,\n Pause,\n Pencil,\n Pin,\n Play,\n Plus,\n RefreshCw,\n Rocket,\n RotateCcw,\n RotateCw,\n Save,\n Search,\n Send,\n Server,\n Settings,\n Shield,\n Sparkles,\n Star,\n Table as TableIcon,\n ThumbsDown,\n ThumbsUp,\n Trash2,\n TrendingDown,\n TrendingUp,\n TriangleAlert,\n Upload,\n User,\n Users,\n WandSparkles,\n Warehouse,\n Workflow,\n Wrench,\n X,\n Zap,\n} from '../../icons';\nimport { cn } from '../../utils';\n\n/**\n * The Lucide component each `icon:<name>` token draws.\n *\n * - Names are FontAwesome-solid ones, published as `CHAT_INLINE_ICON_NAMES`.\n * - The `satisfies` is the drift guard: a name the prompt teaches and this map lacks fails to compile.\n */\nconst FONT_AWESOME_ICONS = {\n 'alert-circle': AlertCircle,\n 'arrow-down': ArrowDown,\n 'arrow-left': ArrowLeft,\n 'arrow-right': ArrowRight,\n 'arrow-rotate-back': RotateCcw,\n 'arrow-rotate-left': RotateCcw,\n 'arrow-rotate-right': RotateCw,\n 'arrow-up': ArrowUp,\n 'arrow-up-right-from-square': ExternalLink,\n 'arrows-rotate': RefreshCw,\n analytics: BarChart3,\n ban: Ban,\n bell: Bell,\n bug: Bug,\n calendar: Calendar,\n changes: FilePen,\n 'chart-line': LineChart,\n check: Check,\n 'check-circle': CircleCheck,\n 'chevron-down': ChevronDown,\n 'chevron-left': ChevronLeft,\n 'chevron-right': ChevronRight,\n 'chevron-up': ChevronUp,\n circle: Circle,\n 'circle-check': CircleCheck,\n 'circle-exclamation': CircleAlert,\n 'circle-info': Info,\n 'circle-pause': CirclePause,\n 'circle-play': CirclePlay,\n 'circle-plus': CirclePlus,\n 'circle-question': CircleHelp,\n 'circle-stop': CircleStop,\n 'circle-xmark': CircleX,\n clock: Clock,\n 'clock-rotate-left': History,\n 'code-branch': GitBranch,\n 'code-merge': GitMerge,\n 'code-pull-request': GitPullRequest,\n cog: Cog,\n configuration: Settings,\n copy: Copy,\n database: Database,\n 'diagram-project': Workflow,\n download: Download,\n ellipsis: Ellipsis,\n envelope: Mail,\n 'exclamation-circle': CircleAlert,\n 'exclamation-triangle': TriangleAlert,\n eye: Eye,\n file: File,\n 'file-lines': FileText,\n flag: Flag,\n folder: Folder,\n gauge: Gauge,\n gear: Settings,\n globe: Globe,\n hand: Hand,\n 'hourglass-half': Hourglass,\n 'info-circle': Info,\n key: Key,\n 'layer-group': Layers,\n link: LinkIcon,\n 'list-check': ListChecks,\n 'list-ul': List,\n lock: Lock,\n 'magnifying-glass': Search,\n minus: Minus,\n 'paper-plane-top': Send,\n pen: Pencil,\n play: Play,\n plus: Plus,\n refresh: RefreshCw,\n rocket: Rocket,\n save: Save,\n 'save-changes': Save,\n search: Search,\n spinner: Loader2,\n sparkles: Sparkles,\n star: Star,\n stop: CircleStop,\n table: TableIcon,\n 'thumbs-down': ThumbsDown,\n 'thumbs-up': ThumbsUp,\n transformation: WandSparkles,\n trash: Trash2,\n 'triangle-exclamation': TriangleAlert,\n upload: Upload,\n user: User,\n 'user-group': Users,\n warning: TriangleAlert,\n warehouse: Warehouse,\n xmark: X,\n zap: Zap,\n} satisfies Record<ChatInlineIconName, LucideIcon>;\n\n/**\n * Lucide names for the same glyphs, for prompts that teach Lucide ids rather than FontAwesome ones.\n *\n * - Additive: a FontAwesome name keeps its glyph.\n */\nconst LUCIDE_ALIASES: Record<string, LucideIcon> = {\n 'book-open': BookOpen,\n bookmark: Bookmark,\n box: Box,\n 'chart-bar': ChartBar,\n 'chart-pie': ChartPie,\n 'circle-alert': CircleAlert,\n 'circle-help': CircleHelp,\n 'circle-x': CircleX,\n cloud: Cloud,\n 'external-link': ExternalLink,\n 'file-text': FileText,\n filter: Filter,\n 'git-branch': GitBranch,\n 'hard-drive': HardDrive,\n history: History,\n hourglass: Hourglass,\n info: Info,\n layers: Layers,\n lightbulb: Lightbulb,\n list: List,\n 'list-checks': ListChecks,\n mail: Mail,\n package: Package,\n pause: Pause,\n pencil: Pencil,\n pin: Pin,\n 'refresh-cw': RefreshCw,\n server: Server,\n settings: Settings,\n shield: Shield,\n 'trash-2': Trash2,\n 'trending-down': TrendingDown,\n 'trending-up': TrendingUp,\n 'triangle-alert': TriangleAlert,\n users: Users,\n workflow: Workflow,\n wrench: Wrench,\n x: X,\n};\n\n/** Every drawable name; read through `Object.hasOwn`, or `icon:constructor` hits `Object.prototype`. */\nconst ICON_REGISTRY: Record<string, LucideIcon | undefined> = {\n ...LUCIDE_ALIASES,\n ...FONT_AWESOME_ICONS,\n};\n\n/**\n * Extra classes a single name needs.\n *\n * - `spinner` spins (per `MAINTAINING.md`): a still `Loader2` reads as a broken ring.\n * - Read through `Object.hasOwn`, like the registry.\n */\nconst ICON_CLASSES: Record<string, string | undefined> = {\n spinner: 'tw:animate-spin',\n};\n\n/**\n * A whole `icon:<name>` token and nothing else.\n *\n * - Must match the name shape `remarkIconSyntax` (`@keboola/kai-chat`) accepts.\n * - Anchored, so inline code like `` `icon: database` `` or `` `icon:` `` stays code.\n */\nconst TOKEN = /^icon:([a-z][a-z0-9-]*)$/;\n\n/** Built once: an answer is re-parsed per streamed chunk, so `isArriving` runs per code node. */\nconst ICON_NAMES = Object.keys(ICON_REGISTRY);\n\n/** Whether a name is a strict prefix of a registry name: `tabl` → `true`, `table-name` → `false`. */\nconst isArriving = (name: string): boolean =>\n ICON_NAMES.some((key) => key.length > name.length && key.startsWith(name));\n\n/**\n * The icon name in a code node's text, if the text is a token — drawn, or still arriving.\n *\n * - An unknown name → `undefined`, so the call site's `<code>` fall-through keeps the text.\n * - A prefix of a known name is a token still streaming; `<ChatInlineIcon />` draws it blank.\n * - A name that is both (`save`, of `save-changes`) is drawn now.\n */\nexport const getChatInlineIconName = (text: string): string | undefined => {\n const name = TOKEN.exec(text)?.[1];\n if (name === undefined) return undefined;\n return Object.hasOwn(ICON_REGISTRY, name) || isArriving(name) ? name : undefined;\n};\n\ntype Props = {\n /** The name from the token, without the `icon:` prefix. */\n name: string;\n};\n\n/**\n * One inline `icon:<name>` token, drawn at the size of the text it leads.\n *\n * - An unknown name (a token still arriving) renders nothing.\n * - `mr` widens the single source space, which reads as cramped beside a glyph.\n * - The heavier stroke holds its own beside a bold heading.\n * - `aria-hidden`: the token's text is removed, so the glyph has no label to announce.\n */\nexport const ChatInlineIcon = ({ name }: Props) => {\n const Icon = Object.hasOwn(ICON_REGISTRY, name) ? ICON_REGISTRY[name] : undefined;\n\n if (Icon === undefined) return null;\n\n return (\n <Icon\n aria-hidden\n className={cn(\n 'tw:mr-[0.15em] tw:inline-block tw:size-[1em] tw:shrink-0 tw:align-[-0.125em] tw:text-muted-foreground',\n Object.hasOwn(ICON_CLASSES, name) ? ICON_CLASSES[name] : undefined,\n )}\n strokeWidth={2.25}\n />\n );\n};\n","import { useEffect, useState } from 'react';\n\nconst TICK_MS = 1000;\n\n/** Whole seconds left of a countdown that starts at `seconds`; `undefined` when there is none. */\nexport const useCountdown = (seconds: number | undefined) => {\n const [ticks, setTicks] = useState({ start: seconds, elapsed: 0 });\n\n useEffect(() => {\n if (seconds === undefined || seconds <= 0) return undefined;\n\n const interval = setInterval(() => {\n setTicks((current) => ({\n start: seconds,\n elapsed: (current.start === seconds ? current.elapsed : 0) + 1,\n }));\n }, TICK_MS);\n return () => clearInterval(interval);\n }, [seconds]);\n\n if (seconds === undefined) return undefined;\n const elapsed = ticks.start === seconds ? ticks.elapsed : 0;\n return Math.max(seconds - elapsed, 0);\n};\n","import type { ReactNode } from 'react';\n\nimport { Alert } from '../../components/Alert';\nimport { Collapsible } from '../../components/Collapsible';\nimport { ChevronDown } from '../../icons';\n\nimport { useCountdown } from './useCountdown';\n\nexport type ChatNoticeTone = 'error' | 'warn' | 'info';\n\ntype Props = {\n tone: ChatNoticeTone;\n children: ReactNode;\n /** A control for the reader to act on, e.g. a retry button. */\n action?: ReactNode;\n /** Raw error text, behind a collapsed \"Technical details\". */\n details?: string;\n /** Seconds until the action is worth trying again; counts down beside the message. */\n retryAfter?: number;\n className?: string;\n};\n\nconst ALERT_VARIANT = { error: 'error', warn: 'warning', info: 'info' } as const;\n\nconst countdownLabel = (remaining: number) =>\n remaining > 0 ? `Try again in ${remaining}s.` : 'You can try again now.';\n\n/**\n * A notice row in a chat transcript.\n *\n * - Thin wrapper over `Alert`; `warn` maps to the warning variant.\n * - `details` stays collapsed so a stack trace never crowds the message.\n * - `retryAfter` appends a live countdown; `action` is always rendered, so the host decides whether to gate it.\n */\nexport const ChatNotice = ({ tone, children, action, details, retryAfter, className }: Props) => {\n const remaining = useCountdown(retryAfter);\n\n return (\n <Alert variant={ALERT_VARIANT[tone]} role=\"status\" className={className}>\n <div className=\"tw:flex tw:flex-wrap tw:items-start tw:gap-x-3 tw:gap-y-2\">\n <div className=\"tw:min-w-0 tw:flex-1 tw:basis-40\">\n <span>{children}</span>\n {remaining !== undefined && (\n <span className=\"tw:ml-1 tw:text-muted-foreground\" data-testid=\"chat-notice-countdown\">\n {countdownLabel(remaining)}\n </span>\n )}\n {details && (\n <Collapsible className=\"tw:mt-1\">\n <Collapsible.Trigger className=\"tailwindcss-preflight tw:group tw:flex tw:cursor-pointer tw:items-center tw:gap-1 tw:border-0 tw:bg-transparent tw:p-0 tw:text-xs tw:text-muted-foreground tw:hover:text-foreground\">\n Technical details\n <ChevronDown className=\"tw:size-3 tw:transition-transform tw:group-data-[state=open]:rotate-180\" />\n </Collapsible.Trigger>\n <Collapsible.Content>\n <code className=\"tw:mt-1 tw:block tw:whitespace-pre-wrap tw:break-words tw:text-xs\">\n {details}\n </code>\n </Collapsible.Content>\n </Collapsible>\n )}\n </div>\n {action && <div className=\"tw:ml-auto tw:flex tw:shrink-0 tw:gap-2\">{action}</div>}\n </div>\n </Alert>\n );\n};\n","import { useState } from 'react';\n\nimport { Quote, X } from '../../icons';\nimport { cn } from '../../utils';\n\nexport const CONTEXT_CHIP_EXPANDABLE_LENGTH = 120;\n\ntype ContextImage = { src: string; alt: string };\n\ntype Props = {\n /** Where the quote came from, e.g. a message or a page title. */\n label: string;\n /** Absent or empty draws the label alone. */\n excerpt?: string;\n images?: ContextImage[];\n /** A position drawn as a numbered disc in place of the quote glyph, so a message can cite it. */\n number?: number;\n /** Absent draws the chip read-only, e.g. on a sent message. */\n onRemove?: () => void;\n className?: string;\n};\n\n/**\n * A quote or reference attached to a message being composed.\n *\n * - The excerpt is clamped to two lines; \"Show all\" appears once it is long enough to be cut.\n * - Images sit under the excerpt as small thumbnails.\n */\nexport const ContextChip = ({\n label,\n excerpt = '',\n images = [],\n number,\n onRemove,\n className,\n}: Props) => {\n const [isExpanded, setIsExpanded] = useState(false);\n const isExpandable = excerpt.length > CONTEXT_CHIP_EXPANDABLE_LENGTH;\n\n return (\n <div\n className={cn(\n 'tailwindcss-preflight tw:flex tw:w-full tw:min-w-0 tw:flex-col tw:gap-1 tw:rounded-md tw:border-0 tw:border-l-2 tw:border-solid tw:border-border tw:bg-muted tw:px-3 tw:py-2 tw:text-xs',\n className,\n )}\n >\n <div className=\"tw:flex tw:items-center tw:gap-1 tw:text-muted-foreground\">\n {number === undefined ? (\n <Quote aria-hidden className=\"tw:size-3.5 tw:shrink-0\" />\n ) : (\n <span\n aria-hidden\n className=\"tw:inline-flex tw:size-4 tw:shrink-0 tw:items-center tw:justify-center tw:rounded-full tw:bg-primary tw:text-[10px] tw:font-semibold tw:text-primary-foreground\"\n >\n {number}\n </span>\n )}\n <span className=\"tw:min-w-0 tw:flex-1 tw:truncate tw:font-medium\">{label}</span>\n {onRemove && (\n <button\n type=\"button\"\n aria-label={number === undefined ? `Remove ${label}` : `Remove ${number}, ${label}`}\n onClick={onRemove}\n className=\"tw:shrink-0 tw:cursor-pointer tw:rounded-sm tw:border-0 tw:bg-transparent tw:p-0 tw:text-muted-foreground tw:hover:text-foreground tw:focus-visible:outline-none tw:focus-visible:ring-2 tw:focus-visible:ring-ring\"\n >\n <X className=\"tw:size-3.5\" />\n </button>\n )}\n </div>\n {excerpt && (\n <p\n className={cn(\n 'tw:m-0 tw:whitespace-pre-wrap tw:break-words tw:text-foreground',\n !isExpanded && 'tw:line-clamp-2',\n )}\n >\n {excerpt}\n </p>\n )}\n {isExpandable && (\n <button\n type=\"button\"\n aria-expanded={isExpanded}\n onClick={() => setIsExpanded((current) => !current)}\n className=\"tw:w-fit tw:cursor-pointer tw:border-0 tw:bg-transparent tw:p-0 tw:text-xs tw:text-muted-foreground tw:underline tw:hover:text-foreground\"\n >\n {isExpanded ? 'Show less' : 'Show all'}\n </button>\n )}\n {images.length > 0 && (\n <div className=\"tw:flex tw:flex-wrap tw:gap-1\">\n {images.map((image) => (\n <img\n key={image.src}\n src={image.src}\n alt={image.alt}\n className=\"tw:size-10 tw:rounded-sm tw:border tw:border-border tw:object-cover\"\n />\n ))}\n </div>\n )}\n </div>\n );\n};\n","import type { ReactNode } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { ButtonGroup } from '../../components/ButtonGroup';\nimport { Download, FileText } from '../../icons';\nimport { cn } from '../../utils';\n\ntype Props = {\n /** The file's own name, as the reader will see it saved. */\n fileName: string;\n /** Where it sits in the workspace, shown on hover — what tells two `report.pdf`s apart. */\n filePath?: string;\n /** Its size, when known. Absent draws nothing rather than claiming a file is empty. */\n size?: string;\n /** Whether a download is in flight — the host owns the fetch and the save. */\n isPending?: boolean;\n onDownload: () => void;\n /** Opt-in. Makes the name a preview button and the download a button of its own beside it. */\n onPreview?: () => void;\n /** Opt-in. Extra controls drawn as part of the chip, e.g. Save to library. */\n actions?: ReactNode;\n className?: string;\n};\n\n/**\n * A file the agent wrote, offered inside its own answer.\n *\n * - By default the whole chip is the control: a small icon beside a truncating filename is hard to hit.\n * - With `onPreview` or `actions` the chip splits: the name previews (or downloads, without\n * `onPreview`), the download sits beside it, and `actions` follow.\n * - Presentation only — the host fetches and saves, through its own auth.\n */\nexport const FileDownloadChip = ({\n fileName,\n filePath,\n size,\n isPending = false,\n onDownload,\n onPreview,\n actions,\n className,\n}: Props) => {\n const isSplit = onPreview !== undefined || actions !== undefined;\n const target = filePath ?? fileName;\n\n const handleDownload = () => {\n if (!isPending) onDownload();\n };\n\n const nameAndSize = (\n <>\n <FileText className=\"tw:size-4 tw:shrink-0 tw:text-muted-foreground\" />\n <span className=\"tw:truncate\">{fileName}</span>\n {size !== undefined && (\n <span className=\"tw:shrink-0 tw:text-xs tw:text-muted-foreground\">{size}</span>\n )}\n </>\n );\n\n if (!isSplit) {\n return (\n <Button\n variant=\"secondary\"\n size=\"small\"\n isLoading={isPending}\n // `aria-disabled`, not `disabled`: a disabled chip drops focus mid-download.\n aria-disabled={isPending}\n // By path: `title` isn't in the accessible name, so two `report.pdf`s would sound alike.\n aria-label={`Download ${target}`}\n title={filePath}\n onClick={handleDownload}\n className={cn('tw:max-w-full tw:justify-start tw:gap-2 tw:font-normal', className)}\n >\n {nameAndSize}\n {!isPending && <Download className=\"tw:size-4 tw:shrink-0\" />}\n </Button>\n );\n }\n\n return (\n <ButtonGroup space=\"compact\" className={cn('tw:max-w-full', className)}>\n {onPreview ? (\n <Button\n variant=\"secondary\"\n size=\"small\"\n aria-label={`Preview ${target}`}\n title={filePath}\n onClick={onPreview}\n className=\"tw:min-w-0 tw:!shrink tw:justify-start tw:gap-2 tw:overflow-hidden tw:font-normal\"\n >\n {nameAndSize}\n </Button>\n ) : null}\n <Button\n variant=\"secondary\"\n size={onPreview ? 'icon-sm' : 'small'}\n isLoading={isPending}\n aria-disabled={isPending}\n aria-label={`Download ${target}`}\n title={onPreview ? undefined : filePath}\n onClick={handleDownload}\n className={cn(\n onPreview\n ? 'tw:shrink-0'\n : 'tw:min-w-0 tw:!shrink tw:justify-start tw:gap-2 tw:overflow-hidden tw:font-normal',\n )}\n >\n {onPreview ? !isPending && <Download className=\"tw:size-4\" /> : nameAndSize}\n {!onPreview && !isPending && <Download className=\"tw:size-4 tw:shrink-0\" />}\n </Button>\n {actions}\n </ButtonGroup>\n );\n};\n","import { useEffect, useState } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { useStableCallback } from '../../hooks/useStableCallback';\nimport { cn } from '../../utils';\n\nexport type FileGalleryImage = {\n id: string;\n name: string;\n /** The thumbnail's URL; absent while the host is still loading it. */\n src?: string;\n /** The host could not produce a thumbnail. */\n isFailed?: boolean;\n};\n\ntype Props = {\n image: FileGalleryImage;\n onOpen: (image: FileGalleryImage) => void;\n onRetry?: (image: FileGalleryImage) => void;\n /** Fires once the tile is near the viewport — the host starts its load here. */\n onVisible?: (image: FileGalleryImage) => void;\n};\n\nconst VISIBLE_MARGIN = '200px';\n\n/**\n * One image in a `FileGallery`.\n *\n * - Reports itself visible once, 200px before it scrolls in; without an `IntersectionObserver`\n * (jsdom) it reports on mount.\n * - A thumbnail that fails to decode counts as failed, and a press retries instead of opening.\n */\nexport const FileGalleryTile = ({ image, onOpen, onRetry, onVisible }: Props) => {\n const [tile, setTile] = useState<HTMLElement | null>(null);\n const [isBroken, setIsBroken] = useState(false);\n const isFailed = image.isFailed === true || isBroken;\n const isLoading = !isFailed && image.src === undefined;\n const hasVisibleHandler = onVisible !== undefined;\n const reportVisible = useStableCallback(() => onVisible?.(image));\n\n useEffect(() => {\n if (!tile || !hasVisibleHandler) return;\n if (typeof IntersectionObserver === 'undefined') {\n reportVisible();\n return;\n }\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (!entries.some((entry) => entry.isIntersecting)) return;\n observer.disconnect();\n reportVisible();\n },\n { rootMargin: VISIBLE_MARGIN },\n );\n observer.observe(tile);\n\n return () => observer.disconnect();\n }, [tile, hasVisibleHandler, reportVisible]);\n\n const handleClick = () => {\n if (!isFailed) return onOpen(image);\n setIsBroken(false);\n onRetry?.(image);\n };\n\n return (\n <Button\n ref={setTile}\n variant=\"invisible\"\n aria-label={isFailed ? `Retry preview of ${image.name}` : image.name}\n onClick={handleClick}\n className={cn(\n 'tw:relative tw:aspect-square tw:!h-auto tw:!max-h-none tw:!min-h-0 tw:!w-full tw:overflow-hidden tw:rounded-md tw:border tw:border-border tw:bg-muted tw:p-0',\n isFailed && 'tw:text-xs tw:text-muted-foreground',\n )}\n >\n {isLoading && (\n <span\n aria-hidden\n className=\"tw:absolute tw:inset-0 tw:animate-pulse tw:bg-muted-foreground/10\"\n />\n )}\n {isFailed && (\n <span className=\"tw:px-2 tw:text-center tw:whitespace-normal\">\n Preview unavailable — retry\n </span>\n )}\n {!isFailed && image.src !== undefined && (\n <img\n src={image.src}\n alt={image.name}\n loading=\"lazy\"\n decoding=\"async\"\n onError={() => setIsBroken(true)}\n className=\"tw:size-full tw:object-cover\"\n />\n )}\n </Button>\n );\n};\n","import { useState } from 'react';\n\nimport { Button } from '../../components/Button';\n\nimport type { FileGalleryImage } from './FileGalleryTile';\nimport { FileGalleryTile } from './FileGalleryTile';\n\nconst DEFAULT_MAX_TILES = 12;\n\ntype Props = {\n images: readonly FileGalleryImage[];\n onOpen: (image: FileGalleryImage) => void;\n onRetry?: (image: FileGalleryImage) => void;\n /** Fires once per tile as it nears the viewport; the host loads its thumbnail here. */\n onImageVisible?: (image: FileGalleryImage) => void;\n /** Tiles drawn before the rest sit behind \"+N more\". */\n maxTiles?: number;\n className?: string;\n};\n\n/**\n * Image files the agent wrote, as a grid of thumbnails.\n *\n * - Presentation only: the host owns thumbnail URLs, their loading and their auth.\n * - Tiles ask for their thumbnail as they near the viewport, so a long gallery loads on scroll.\n * - Draws `maxTiles`, then a \"+N more\" button that reveals the rest.\n */\nexport const FileGallery = ({\n images,\n onOpen,\n onRetry,\n onImageVisible,\n maxTiles = DEFAULT_MAX_TILES,\n className,\n}: Props) => {\n const [isShowingAll, setIsShowingAll] = useState(false);\n const shown = isShowingAll ? images : images.slice(0, maxTiles);\n const hiddenCount = images.length - shown.length;\n\n if (images.length === 0) return null;\n\n return (\n <div\n role=\"group\"\n aria-label=\"Images\"\n className={className ?? 'tw:grid tw:grid-cols-[repeat(auto-fill,minmax(6rem,1fr))] tw:gap-2'}\n >\n {shown.map((image) => (\n <FileGalleryTile\n key={image.id}\n image={image}\n onOpen={onOpen}\n onRetry={onRetry}\n onVisible={onImageVisible}\n />\n ))}\n {hiddenCount > 0 && (\n <Button variant=\"secondary\" onClick={() => setIsShowingAll(true)}>\n +{hiddenCount} more\n </Button>\n )}\n </div>\n );\n};\n\nexport type { FileGalleryImage };\n","import type { CSSProperties, ReactNode } from 'react';\n\nimport { cn } from '../../utils';\n\nimport { CollapsibleStepHeader } from './CollapsibleStepHeader';\nimport type { InlineStepLabelVariant } from './InlineStepLabel';\n\n/** The surface colour, as the custom property the step icons mask against. */\nconst surfaceStyle = (\n surface: string,\n): CSSProperties & Record<'--inline-step-surface', string> => ({\n '--inline-step-surface': surface,\n});\n\ntype Props = {\n label: ReactNode;\n /** How the whole run reads in one mark; a retried-then-recovered run is `success`, a stopped one `dismissed`. */\n variant?: InlineStepLabelVariant;\n isExpanded: boolean;\n onToggle: () => void;\n /** The CSS colour behind the group; step icons mask the connector with it. Must match the\n * actual surface (e.g. a panel), not the page background. */\n surface?: string;\n 'aria-label'?: string;\n /** E2E anchor; selectors in `packages/e2e-testing` break silently if it moves. */\n 'data-testid'?: string;\n className?: string;\n /** Opt-in. Drawn under the last row, inside the group, e.g. a connect link or a retry. */\n footer?: ReactNode;\n /** The rows: `InlineStepLabel`, `InlineStepDetail`, and whatever a host draws between them. */\n children: ReactNode;\n};\n\n/**\n * A collapsible run of agent steps behind one summary line; rows arrive as children.\n *\n * - Connector sits at the icon centre line (`pl-5` + half a `size-5` box), drawn once so it\n * survives icon-less rows.\n * - Animates `grid-template-rows`; children stay mounted while closed.\n * - `role=\"group\"`, not a `region` landmark: dozens per transcript would drown real landmarks.\n */\nexport const InlineStepGroup = ({\n label,\n variant = 'success',\n isExpanded,\n onToggle,\n surface = 'rgb(var(--background))',\n 'aria-label': ariaLabel,\n 'data-testid': testId,\n className,\n footer,\n children,\n}: Props) => (\n <section\n role=\"group\"\n className={cn('tw:flex tw:flex-col', className)}\n aria-label={ariaLabel}\n data-testid={testId}\n >\n <CollapsibleStepHeader\n isExpanded={isExpanded}\n onToggle={onToggle}\n label={label}\n variant={variant}\n />\n\n <div\n className={cn(\n 'tw:grid tw:transition-[grid-template-rows] tw:duration-200 tw:ease-out tw:motion-reduce:transition-none',\n isExpanded ? 'tw:grid-rows-[1fr]' : 'tw:grid-rows-[0fr]',\n )}\n >\n {/* `0fr` hides only visually; `inert` + `aria-hidden` drop it from a11y tree and tab order. */}\n <div\n className=\"tw:min-h-0 tw:overflow-hidden\"\n inert={!isExpanded}\n aria-hidden={isExpanded ? undefined : true}\n >\n <div\n style={surfaceStyle(surface)}\n className=\"tw:relative tw:flex tw:flex-col tw:gap-4 tw:pt-4 tw:pl-5\"\n >\n <span\n aria-hidden=\"true\"\n className=\"tw:pointer-events-none tw:absolute tw:top-4 tw:bottom-0 tw:left-[30px] tw:w-px tw:bg-border\"\n />\n {children}\n {footer && (\n <div className=\"tw:relative tw:pl-6 tw:[background:var(--inline-step-surface,transparent)]\">\n {footer}\n </div>\n )}\n </div>\n </div>\n </div>\n </section>\n);\n\nexport type { Props as InlineStepGroupProps };\n","import { Button } from '../../components/Button';\nimport { Tooltip } from '../../components/Tooltip';\nimport { ArrowDown } from '../../icons';\nimport { cn } from '../../utils';\n\ntype Props = {\n visible: boolean;\n /** The agent is still writing below the fold: the button pulses. */\n working?: boolean;\n onClick: () => void;\n /** Text beside the arrow; absent draws an icon-only button named \"Scroll to bottom\". */\n label?: string;\n /** Shown beside the button on hover, to its left, where the button sits against the right edge. */\n tooltip?: string;\n className?: string;\n};\n\n/**\n * Scrolls a transcript back to its newest message.\n *\n * - Renders nothing while `visible` is false.\n * - Positioning is the host's: pass `className` to pin it over the list.\n */\nexport const JumpToLatest = ({\n visible,\n working = false,\n onClick,\n label,\n tooltip,\n className,\n}: Props) => {\n if (!visible) return null;\n\n const button = (\n <Button\n variant=\"outline\"\n size={label ? 'small' : 'icon-sm'}\n aria-label={label ?? 'Scroll to bottom'}\n data-working={working}\n onClick={onClick}\n className={cn(\n 'tw:rounded-full tw:shadow-md',\n working && 'tw:animate-pulse tw:motion-reduce:animate-none',\n className,\n )}\n >\n <ArrowDown className=\"tw:size-4\" />\n {label}\n </Button>\n );\n\n if (!tooltip) return button;\n return (\n <Tooltip tooltip={tooltip} placement=\"left\" triggerAsChild>\n {button}\n </Tooltip>\n );\n};\n","import { useEffect, useState } from 'react';\nimport type { ReactNode } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { DiagramSkeleton } from '../DiagramShared/DiagramSkeleton';\nimport { DiagramSource } from '../DiagramShared/DiagramSource';\n\nimport type { DiagramComponent, DiagramLoader } from './diagramChunk';\n\ntype Props = {\n load: DiagramLoader;\n code: string;\n /** Extra toolbar controls for the drawn diagram; receives its sanitized SVG. */\n renderActions?: (safeSvg: string) => ReactNode;\n};\n\n/**\n * One diagram block: a skeleton while its chunk loads, the fence source plus a retry if it fails.\n *\n * - Each attempt is a fresh fetch; the loader drops its rejected promise and logs the failure.\n * - Retry is manual: a chunk gone after a deploy never returns, so a timer would loop forever.\n * - A new `load` resets the block, or a dialect switch keeps the previous renderer.\n * - Functions in state go through the setter form, or React calls them.\n */\nexport const DiagramBlock = ({ load, code, renderActions }: Props) => {\n const [Diagram, setDiagram] = useState<DiagramComponent | null>(null);\n const [failed, setFailed] = useState(false);\n const [attempt, setAttempt] = useState(0);\n\n // Reset during render, not in an effect, so a dialect change never paints the old renderer.\n const [prevLoad, setPrevLoad] = useState(() => load);\n if (load !== prevLoad) {\n setPrevLoad(() => load);\n setDiagram(null);\n setFailed(false);\n }\n\n useEffect(() => {\n let cancelled = false;\n load().then(\n (component) => {\n if (!cancelled) setDiagram(() => component);\n },\n () => {\n if (!cancelled) setFailed(true);\n },\n );\n return () => {\n cancelled = true;\n };\n // `attempt` is the retry trigger — bumping it re-runs the import.\n }, [load, attempt]);\n\n if (Diagram) return <Diagram code={code} renderActions={renderActions} />;\n\n if (failed) {\n return (\n <div>\n <DiagramSource code={code} />\n <Button\n variant=\"inline\"\n size=\"small\"\n className=\"tw:mb-3\"\n onClick={() => {\n setFailed(false);\n setAttempt((count) => count + 1);\n }}\n >\n Try again\n </Button>\n </div>\n );\n }\n\n return <DiagramSkeleton />;\n};\n","import type { ComponentType, ReactNode } from 'react';\n\nexport type DiagramComponent = ComponentType<{\n code: string;\n renderActions?: (safeSvg: string) => ReactNode;\n}>;\nexport type DiagramLoader = () => Promise<DiagramComponent>;\n\n/**\n * An on-demand diagram chunk, shared between mounts and retryable.\n *\n * - Not `lazy()`: it memoizes a failed import, stranding every diagram until a reload.\n * - A resolved import is kept; a failed one is cleared so the next mount retries.\n * - Same contract as `getFlintRuntime()` in `FlintChart`.\n * - Failures are logged here, where the chunk's name is known.\n */\nexport const diagramChunk = (name: string, load: DiagramLoader): DiagramLoader => {\n let pending: Promise<DiagramComponent> | null = null;\n return () => {\n pending ??= load().catch((error: unknown) => {\n console.error(`[AIKit] failed to load the ${name} chunk`, error);\n pending = null;\n throw error;\n });\n return pending;\n };\n};\n","import { toSvgFileContent } from '../../components/ZoomableSvg/exportSvg';\n\n/** How long the object URL outlives the click; the download has started by then. */\nconst REVOKE_DELAY_MS = 1_000;\n\n/** Saves sanitized SVG markup as a standalone `.svg` file. */\nexport const downloadSvgFile = (svg: string, filename = 'diagram.svg'): void => {\n const blob = new Blob([toSvgFileContent(svg)], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = filename;\n document.body.append(anchor);\n anchor.click();\n anchor.remove();\n setTimeout(() => URL.revokeObjectURL(url), REVOKE_DELAY_MS);\n};\n","import { Button } from '../../components/Button';\nimport { Tooltip } from '../../components/Tooltip';\nimport { Download } from '../../icons';\n\nimport { downloadSvgFile } from './downloadSvgFile';\n\n/** A diagram toolbar action that saves the drawn diagram as an SVG file. */\nexport const DiagramDownloadButton = ({ safeSvg }: { safeSvg: string }) => (\n <Tooltip tooltip=\"Download SVG\" placement=\"top\" triggerAsChild>\n <Button\n size=\"icon-sm\"\n variant=\"outline\"\n aria-label=\"Download SVG\"\n onClick={() => downloadSvgFile(safeSvg)}\n >\n <Download className=\"tw:size-4\" />\n </Button>\n </Tooltip>\n);\n","import type { HighlightGrammar } from './highlightLanguages';\n\nexport type HighlightToken = { text: string; className: string };\n\nexport type Highlighter = (code: string, grammar: HighlightGrammar) => HighlightToken[];\n\nlet pending: Promise<Highlighter | null> | null = null;\n\n/**\n * The syntax highlighter, loaded on first use and shared between blocks.\n *\n * - The parsers are heavy, so they stay out of the main chunk.\n * - A failed import is logged and resolves `null`; the next block retries.\n */\nexport const loadHighlighter = (): Promise<Highlighter | null> => {\n pending ??= import('./highlightCode').then(\n (module) => module.highlightCode,\n (error: unknown) => {\n console.error('[AIKit] failed to load the syntax highlighter chunk', error);\n pending = null;\n return null;\n },\n );\n return pending;\n};\n","import { useEffect, useMemo, useState } from 'react';\nimport type { ReactNode } from 'react';\n\nimport type { Highlighter } from './highlightChunk';\nimport { loadHighlighter } from './highlightChunk';\nimport type { HighlightGrammar } from './highlightLanguages';\n\ntype Props = {\n code: string;\n grammar: HighlightGrammar;\n className?: string;\n /** The plain `<code>`, shown until the highlighter chunk arrives or if it fails. */\n children: ReactNode;\n};\n\n/**\n * A fenced block's `<code>`, coloured once the highlighter chunk loads.\n *\n * - Functions in state go through the setter form, or React calls them.\n */\nexport const HighlightedCode = ({ code, grammar, className, children }: Props) => {\n const [highlight, setHighlight] = useState<Highlighter | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n void loadHighlighter().then((loaded) => {\n if (!cancelled && loaded) setHighlight(() => loaded);\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n const tokens = useMemo(() => highlight?.(code, grammar), [highlight, code, grammar]);\n\n if (!tokens) return children;\n\n return (\n <code className={className}>\n {tokens.map((token, index) =>\n token.className ? (\n // oxlint-disable-next-line react/no-array-index-key -- runs of one string, never reordered\n <span key={index} className={token.className}>\n {token.text}\n </span>\n ) : (\n token.text\n ),\n )}\n </code>\n );\n};\n","export type HighlightGrammar =\n | 'sql'\n | 'python'\n | 'javascript'\n | 'jsx'\n | 'typescript'\n | 'tsx'\n | 'json'\n | 'shell'\n | 'yaml';\n\n/**\n * Fence language → the grammar that highlights it.\n *\n * - Read via `Object.hasOwn`: ```constructor would otherwise hit `Object.prototype`.\n */\nconst HIGHLIGHT_GRAMMARS: Record<string, HighlightGrammar | undefined> = {\n sql: 'sql',\n snowflake: 'sql',\n sfsql: 'sql',\n python: 'python',\n py: 'python',\n js: 'javascript',\n javascript: 'javascript',\n jsx: 'jsx',\n ts: 'typescript',\n typescript: 'typescript',\n tsx: 'tsx',\n json: 'json',\n sh: 'shell',\n bash: 'shell',\n shell: 'shell',\n zsh: 'shell',\n yaml: 'yaml',\n yml: 'yaml',\n};\n\n/** The grammar for a fence language, or `undefined` when the block stays plain. */\nexport const getHighlightGrammar = (language: string | undefined): HighlightGrammar | undefined => {\n const key = language?.toLowerCase();\n return key !== undefined && Object.hasOwn(HIGHLIGHT_GRAMMARS, key)\n ? HIGHLIGHT_GRAMMARS[key]\n : undefined;\n};\n","import { createContext } from 'react';\nimport type { ReactNode } from 'react';\n\nexport type RenderDiagramActions = (safeSvg: string) => ReactNode;\n\n/**\n * The opt-in features of one `Markdown.Block`, read by its static renderers.\n *\n * - Every field off by default, so an unconfigured block renders as it always has.\n */\nexport type MarkdownOptions = {\n highlight: boolean;\n sortable: boolean;\n renderDiagramActions: RenderDiagramActions | undefined;\n};\n\nexport const MarkdownOptionsContext = createContext<MarkdownOptions>({\n highlight: false,\n sortable: false,\n renderDiagramActions: undefined,\n});\n","import type { ExtraProps } from 'react-markdown';\n\nexport type SortDirection = 'ascending' | 'descending';\n\nexport type TableSort = { column: number; direction: SortDirection } | null;\n\nexport type HastElement = NonNullable<ExtraProps['node']>;\ntype HastNode = HastElement['children'][number];\n\n/** Characters a number cell carries for the reader: grouping, currency, percent, sign, spaces. */\nconst NUMBER_NOISE = /[\\s,_%$€£¥+]/g;\n\n/** A trailing magnitude: `142k`, `1.2M`, `3B`. */\nconst MAGNITUDE = /^(.*?)([kmb])$/i;\n\nconst MAGNITUDES: Record<string, number | undefined> = { k: 1e3, m: 1e6, b: 1e9 };\n\n/** A cell's number, or `null` when it is not one: `1,234`, `−5.1%`, `€142` and `1.2M` all read. */\nexport const parseSortNumber = (text: string): number | null => {\n const cleaned = text.replace(NUMBER_NOISE, '').replace(/^\\u2212/, '-');\n const [, digits = cleaned, suffix = ''] = MAGNITUDE.exec(cleaned) ?? [];\n if (digits === '' || /[^\\d.eE-]/.test(digits)) return null;\n const value = Number(digits) * (MAGNITUDES[suffix.toLowerCase()] ?? 1);\n return Number.isFinite(value) ? value : null;\n};\n\n/** Cells a model writes for \"no value\"; they sort with the empty ones. */\nconst PLACEHOLDER = /^(?:n\\/?a|-+|[\\u2013\\u2014\\u2026?]|none|null)$/i;\n\nconst isBlank = (key: string): boolean => key === '' || PLACEHOLDER.test(key);\n\nconst collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });\n\n/**\n * Row indices in the order one column sorts them.\n *\n * - Numeric when every non-empty cell parses as a number; otherwise locale-aware text.\n * - Empty and placeholder cells (`n/a`, `—`) go last in both directions; ties keep source order.\n */\nexport const sortRowOrder = (cells: readonly string[], direction: SortDirection): number[] => {\n const keys = cells.map((cell) => cell.trim());\n const numbers = keys.map(parseSortNumber);\n const filled = keys.flatMap((key, index) => (isBlank(key) ? [] : [index]));\n const empty = keys.flatMap((key, index) => (isBlank(key) ? [index] : []));\n const numeric = filled.every((index) => numbers[index] !== null);\n\n const compare = (a: number, b: number) =>\n numeric\n ? (numbers[a] ?? 0) - (numbers[b] ?? 0)\n : collator.compare(keys[a] ?? '', keys[b] ?? '');\n\n const sorted = filled.toSorted(compare);\n return [...(direction === 'ascending' ? sorted : sorted.toReversed()), ...empty];\n};\n\n/** The sort after a header press: a new column sorts ascending, the same one flips. */\nexport const nextSort = (current: TableSort, column: number): TableSort =>\n current?.column === column && current.direction === 'ascending'\n ? { column, direction: 'descending' }\n : { column, direction: 'ascending' };\n\nconst getHastText = (node: HastNode): string => {\n if (node.type === 'text') return node.value;\n if (node.type === 'element') return node.children.map(getHastText).join('');\n return '';\n};\n\n/** A row's cells, read off its hast node; `[]` without one. */\nexport const getRowCells = (row: HastElement | undefined): HastElement[] =>\n row?.children.filter(\n (child): child is HastElement => child.type === 'element' && /^t[dh]$/.test(child.tagName),\n ) ?? [];\n\n/** The text of a row's cell at `column`; `''` when the row is short. */\nexport const getRowCellText = (row: HastElement | undefined, column: number): string => {\n const cell = getRowCells(row)[column];\n return cell ? getHastText(cell) : '';\n};\n","import { createContext } from 'react';\n\nimport type { HastElement, TableSort } from './tableSort';\n\n/** The sort of the table being rendered; `null` outside a sortable table. */\nexport const TableSortContext = createContext<{\n sort: TableSort;\n toggle: (column: number) => void;\n} | null>(null);\n\n/** The hast cells of the row being rendered; a cell finds its column by identity. */\nexport const RowCellsContext = createContext<readonly HastElement[]>([]);\n","import { useMemo, useState } from 'react';\nimport type { ReactNode } from 'react';\n\nimport type { TableSort } from './tableSort';\nimport { nextSort } from './tableSort';\nimport { TableSortContext } from './tableSortContext';\n\n/** Holds one table's sort; the `Markdown` header, row and body renderers read it. */\nexport const TableSortProvider = ({ children }: { children: ReactNode }) => {\n const [sort, setSort] = useState<TableSort>(null);\n const value = useMemo(\n () => ({ sort, toggle: (column: number) => setSort((current) => nextSort(current, column)) }),\n [sort],\n );\n return <TableSortContext value={value}>{children}</TableSortContext>;\n};\n","import { use } from 'react';\nimport type { ComponentPropsWithoutRef } from 'react';\nimport type { ExtraProps } from 'react-markdown';\n\nimport { Table } from '../../components/Table';\nimport { cn } from '../../utils';\n\nimport { MarkdownOptionsContext } from './markdownOptions';\nimport { TableSortProvider } from './TableSortProvider';\n\n/** The `table` renderer; a sortable block gives each table its own sort. */\nexport const MarkdownGrid = (props: ComponentPropsWithoutRef<'table'> & ExtraProps) => {\n const { className, node: _node, ...rest } = props;\n const { sortable } = use(MarkdownOptionsContext);\n const grid = (\n <div className=\"tw:not-prose tw:my-4\">\n <Table bordered className={cn('tw:!mb-0', className)} {...rest} />\n </div>\n );\n return sortable ? <TableSortProvider>{grid}</TableSortProvider> : grid;\n};\n","import { isValidElement, use } from 'react';\nimport type { ComponentPropsWithoutRef } from 'react';\nimport type { ExtraProps } from 'react-markdown';\n\nimport { Table } from '../../components/Table';\n\nimport { getRowCellText, sortRowOrder } from './tableSort';\nimport { TableSortContext } from './tableSortContext';\n\n/**\n * The body of an answer's table, in the order its sorted column puts the rows.\n *\n * - react-markdown hands rows over as a keyed array, each with its hast `node`.\n * - Rows keep their keys, so a sort moves them rather than remounting them.\n */\nexport const MarkdownTableBody = (props: ComponentPropsWithoutRef<'tbody'> & ExtraProps) => {\n const { children, node: _node, ...rest } = props;\n const sort = use(TableSortContext)?.sort ?? null;\n if (sort === null || !Array.isArray(children))\n return <Table.Body {...rest}>{children}</Table.Body>;\n\n const rows = children.filter(isValidElement<ExtraProps>);\n const order = sortRowOrder(\n rows.map((row) => getRowCellText(row.props.node, sort.column)),\n sort.direction,\n );\n return <Table.Body {...rest}>{order.map((index) => rows[index])}</Table.Body>;\n};\n","import { use } from 'react';\nimport type { ComponentPropsWithoutRef } from 'react';\nimport type { ExtraProps } from 'react-markdown';\n\nimport type { TableSortDirection } from '../../components/Table';\nimport { Table, tableAriaSort } from '../../components/Table';\n\nimport { RowCellsContext, TableSortContext } from './tableSortContext';\n\n/**\n * A header cell in an answer's table; a sort control inside a sortable table.\n *\n * - The button sorts on click, Enter and Space; `aria-sort` sits on the cell.\n */\nexport const MarkdownTableHead = (props: ComponentPropsWithoutRef<'th'> & ExtraProps) => {\n const { children, node, ...rest } = props;\n const sorting = use(TableSortContext);\n const column = node ? use(RowCellsContext).indexOf(node) : -1;\n\n if (sorting === null || column === -1) return <Table.Head {...rest}>{children}</Table.Head>;\n\n const { sort, toggle } = sorting;\n const sorted: TableSortDirection =\n sort?.column !== column ? false : sort.direction === 'ascending' ? 'asc' : 'desc';\n\n return (\n <Table.Head aria-sort={tableAriaSort(sorted)} {...rest}>\n <Table.SortHeader sorted={sorted} onClick={() => toggle(column)}>\n {children}\n </Table.SortHeader>\n </Table.Head>\n );\n};\n","import { use } from 'react';\nimport type { ComponentPropsWithoutRef } from 'react';\nimport type { ExtraProps } from 'react-markdown';\n\nimport { Table } from '../../components/Table';\n\nimport { getRowCells } from './tableSort';\nimport { RowCellsContext, TableSortContext } from './tableSortContext';\n\n/** A row in an answer's table; inside a sortable table its cells can find their column. */\nexport const MarkdownTableRow = (props: ComponentPropsWithoutRef<'tr'> & ExtraProps) => {\n const { node, ...rest } = props;\n const sorting = use(TableSortContext);\n const row = <Table.Row {...rest} />;\n return sorting === null ? (\n row\n ) : (\n <RowCellsContext value={getRowCells(node)}>{row}</RowCellsContext>\n );\n};\n","/** Fence languages whose body may be a single SVG document. */\nconst SVG_FENCE_LANGUAGES: readonly string[] = ['svg', 'xml', 'html'];\n\n/** A root start tag: `<svg` then whitespace, `/` or `>` — not `<svg-chart`. */\nconst SVG_ROOT = /^<svg[\\s/>]/i;\n\n/** An end tag for `svg` as the HTML parser sees one. */\nconst SVG_END_TAG = /<\\/svg[\\s/>]/iy;\n\n/** The only spelling that closes a chart: `</svg>`, optional whitespace before `>`. */\nconst SVG_CLOSE = /<\\/svg\\s*>/iy;\n\nconst COMMENT_END = /--!?>/g;\n\n/**\n * Where the HTML parser ends the comment, CDATA or other `<!…>` / `<?…>` markup opening at `lt`.\n *\n * - The index just past it, `-1` while it is still open, `null` when none opens there.\n */\nconst skipMarkup = (text: string, lt: number): number | null => {\n if (text.startsWith('<!--', lt)) {\n const body = lt + 4;\n if (text.startsWith('>', body)) return body + 1;\n if (text.startsWith('->', body)) return body + 2;\n COMMENT_END.lastIndex = body;\n const end = COMMENT_END.exec(text);\n return end ? end.index + end[0].length : -1;\n }\n if (text.startsWith('<![CDATA[', lt)) {\n const end = text.indexOf(']]>', lt + 9);\n return end < 0 ? -1 : end + 3;\n }\n if (text.startsWith('<!', lt) || text.startsWith('<?', lt)) {\n const end = text.indexOf('>', lt + 2);\n return end < 0 ? -1 : end + 1;\n }\n return null;\n};\n\n/**\n * Index just past the first `</svg>` at or after `from` outside skipped markup, or `-1`.\n *\n * - Any other spelling of that first end tag (`</svg/>`, junk attributes) also gives `-1`.\n * - One pass over the `<`s, never a backtracking regex: it runs on every streamed chunk.\n */\nconst svgEndTagEnd = (text: string, from: number): number => {\n let at = from;\n for (;;) {\n const lt = text.indexOf('<', at);\n if (lt < 0) return -1;\n const skipped = skipMarkup(text, lt);\n if (skipped === -1) return -1;\n if (skipped !== null) {\n at = skipped;\n continue;\n }\n SVG_END_TAG.lastIndex = lt;\n if (SVG_END_TAG.test(text)) {\n SVG_CLOSE.lastIndex = lt;\n return SVG_CLOSE.test(text) ? SVG_CLOSE.lastIndex : -1;\n }\n at = lt + 1;\n }\n};\n\n/**\n * The SVG document a fenced block holds, or `null` when it holds anything else.\n *\n * - Only `svg`, `xml` and `html` fences; an XML prolog, doctype or comments may lead.\n * - Exactly one document: a second one, prose around it or one still streaming stays code.\n * - The scan mirrors the HTML parser; whatever it accepts is still sanitized.\n */\nexport const svgFenceDocument = (language: string | undefined, body: string): string | null => {\n if (language === undefined || !SVG_FENCE_LANGUAGES.includes(language.toLowerCase())) return null;\n const text = body.trim();\n let at = 0;\n for (;;) {\n while (at < text.length && /\\s/.test(text.charAt(at))) at++;\n const skipped = skipMarkup(text, at);\n if (skipped === null) break;\n if (skipped === -1) return null;\n at = skipped;\n }\n if (!SVG_ROOT.test(text.slice(at, at + 5))) return null;\n return svgEndTagEnd(text, at) === text.length ? text.slice(at) : null;\n};\n","/** More cloned nodes than any honest chart needs; matplotlib's glyphs stay well under it. */\nconst MAX_CLONED_NODES = 20_000;\n\nconst LINK_ATTRIBUTES = ['href', 'xlink:href'];\n\n/**\n * The only id shape a reference may name.\n *\n * - No `%`, `\\\\` or quotes: the browser decodes those where this check would not.\n */\nconst STRICT_ID = /^[A-Za-z_][\\w.-]*$/;\n\n/** A `url(#id)` paint, clip, mask, filter or marker reference, in its one accepted spelling. */\nexport const URL_REFERENCE = /url\\(\\s*(['\"]?)#([A-Za-z_][\\w.-]*)\\1\\s*\\)/gi;\n\n/** Anything the browser could read as a `url(` or a CSS escape. */\nconst ANY_URL = /url\\s*\\(|\\\\/gi;\n\n/**\n * The ids an attribute value points at; `null` when it cannot be read safely.\n *\n * - Fails closed: a `url(` or escape the strict spelling does not account for is unreadable.\n */\nconst referencesIn = (name: string, value: string): string[] | null => {\n if (LINK_ATTRIBUTES.includes(name)) {\n const id = value.trim().replace(/^#/, '');\n return value.trim().startsWith('#') && STRICT_ID.test(id) ? [id] : null;\n }\n const strict = [...value.matchAll(URL_REFERENCE)].map((match) => match[2] ?? '');\n const anything = value.match(ANY_URL)?.length ?? 0;\n return anything === strict.length ? strict : null;\n};\n\n/** The ids an element's own attributes point at, by attribute name; `null` marks an unreadable one. */\nconst ownReferences = (element: Element): Map<string, string[] | null> => {\n const references = new Map<string, string[] | null>();\n for (const { name, value } of element.attributes) {\n const ids = referencesIn(name, value);\n if (ids === null || ids.length > 0) references.set(name, ids);\n }\n return references;\n};\n\n/** Drops a reference that failed the check: a `<use>` goes whole, anything else loses the attribute. */\nconst dropReference = (element: Element, attribute: string) => {\n if (element.localName === 'use' && LINK_ATTRIBUTES.includes(attribute)) element.remove();\n else element.removeAttribute(attribute);\n};\n\nlet fenceCount = 0;\n\nconst nextPrefix = () => {\n fenceCount += 1;\n return `svgf${fenceCount.toString(36)}${Math.random().toString(36).slice(2, 8)}-`;\n};\n\n/**\n * Confines a sanitized fence's internal references to the fence itself, at linear cost.\n *\n * 1. An id outside `STRICT_ID` is removed; a repeated one keeps its first element, as the browser does.\n * 2. A reference survives only if readable and aimed at an in-fence, reference-free subtree.\n * 3. Each `<use>` costs its target's node count; past `MAX_CLONED_NODES` the rest go.\n * 4. Every id and reference gets a per-fence prefix, so nothing resolves into the host page.\n */\nexport const scopeSvgReferences = (root: ParentNode): void => {\n const elements = [...root.querySelectorAll('*')];\n const byId = new Map<string, Element>();\n for (const element of elements) {\n if (!element.hasAttribute('id')) continue;\n if (!STRICT_ID.test(element.id) || byId.has(element.id)) element.removeAttribute('id');\n else byId.set(element.id, element);\n }\n\n const references = new Map(elements.map((element) => [element, ownReferences(element)]));\n const referencing = new Set<Element>();\n for (const [element, refs] of references) {\n if (refs.size === 0) continue;\n for (let node: Element | null = element; node; node = node.parentElement) referencing.add(node);\n }\n\n for (const [element, refs] of references) {\n for (const [attribute, ids] of refs) {\n const unsafe =\n ids === null ||\n ids.some((id) => {\n const target = byId.get(id);\n return !target || referencing.has(target);\n });\n if (unsafe) dropReference(element, attribute);\n }\n }\n\n const targetSize = new Map<Element, number>();\n let cloned = 0;\n for (const use of root.querySelectorAll('use')) {\n const href = use.getAttribute('href') ?? use.getAttribute('xlink:href') ?? '';\n const target = byId.get(href.trim().slice(1));\n if (!target) continue;\n let size = targetSize.get(target);\n if (size === undefined) {\n size = target.getElementsByTagName('*').length + 1;\n targetSize.set(target, size);\n }\n cloned += size;\n if (cloned > MAX_CLONED_NODES) use.remove();\n }\n\n const prefix = nextPrefix();\n for (const element of root.querySelectorAll('*')) {\n if (element.id) element.id = `${prefix}${element.id}`;\n for (const { name, value } of [...element.attributes]) {\n const scoped = LINK_ATTRIBUTES.includes(name)\n ? value.trim().replace(/^#/, `#${prefix}`)\n : value.replace(URL_REFERENCE, (_match, quote: string, id: string) => {\n return `url(${quote}#${prefix}${id}${quote})`;\n });\n if (scoped !== value) element.setAttribute(name, scoped);\n }\n }\n};\n","import { URL_REFERENCE } from './scopeSvgReferences';\n\n/** The CSS properties a fenced chart may set inline: nothing that loads a URL or leaves the box. */\nconst SAFE_PROPERTIES = new Set([\n 'alignment-baseline',\n 'baseline-shift',\n 'clip-path',\n 'clip-rule',\n 'color',\n 'display',\n 'dominant-baseline',\n 'fill',\n 'fill-opacity',\n 'fill-rule',\n 'filter',\n 'flood-color',\n 'flood-opacity',\n 'font',\n 'font-family',\n 'font-size',\n 'font-style',\n 'font-weight',\n 'letter-spacing',\n 'lighting-color',\n 'marker',\n 'marker-end',\n 'marker-mid',\n 'marker-start',\n 'mask',\n 'opacity',\n 'paint-order',\n 'shape-rendering',\n 'stop-color',\n 'stop-opacity',\n 'stroke',\n 'stroke-dasharray',\n 'stroke-dashoffset',\n 'stroke-linecap',\n 'stroke-linejoin',\n 'stroke-miterlimit',\n 'stroke-opacity',\n 'stroke-width',\n 'text-anchor',\n 'text-decoration',\n 'text-rendering',\n 'vector-effect',\n 'visibility',\n 'word-spacing',\n]);\n\n/**\n * The only functions a value may call: colours, and a same-document reference.\n *\n * - Colour arguments take words, numbers and `/`, never a nested `(`.\n */\nconst SAFE_FUNCTION = new RegExp(\n String.raw`(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch)\\([\\w\\s.,%+/-]*\\)|${URL_REFERENCE.source}`,\n 'gi',\n);\n\n/** What is left of a value once its safe functions are gone: words, numbers, colours, quotes. */\nconst SAFE_REMAINDER = /^[\\w\\s#.,%'\"+/-]*$/;\n\nconst isSafeDeclaration = (property: string, value: string): boolean =>\n SAFE_PROPERTIES.has(property) && SAFE_REMAINDER.test(value.replace(SAFE_FUNCTION, ''));\n\n/**\n * A `style` attribute reduced to the declarations a static chart needs.\n *\n * - Allowlist, not denylist: `image-set()`, escapes and positioning never pass.\n * - A declaration goes whole; `''` when none survive.\n */\nexport const filterSvgStyle = (style: string): string =>\n style\n .split(';')\n .flatMap((declaration) => {\n const colon = declaration.indexOf(':');\n if (colon < 0) return [];\n const property = declaration.slice(0, colon).trim().toLowerCase();\n const value = declaration.slice(colon + 1).trim();\n return isSafeDeclaration(property, value) ? [`${property}: ${value}`] : [];\n })\n .join('; ');\n","import DOMPurify from 'dompurify';\n\nimport { filterSvgStyle } from './filterSvgStyle';\nimport { scopeSvgReferences } from './scopeSvgReferences';\n\n/**\n * Elements a fenced chart never keeps.\n *\n * - SMIL (`animate*`, `set`) sets attributes at runtime, past every attribute check.\n * - `foreignObject` carries HTML; a `style` element would restyle the whole page.\n */\nconst FORBIDDEN_TAGS = [\n 'script',\n 'foreignObject',\n 'animate',\n 'animateMotion',\n 'animateTransform',\n 'set',\n 'style',\n];\n\nconst URL_ATTRIBUTES = new Set(['href', 'xlink:href']);\n\nlet purifier: ReturnType<typeof DOMPurify> | null = null;\n\n/** A DOMPurify instance of its own, so these hooks never reach `ZoomableSvg` or other callers. */\nconst getPurifier = () => {\n if (purifier) return purifier;\n const instance = DOMPurify(window);\n instance.addHook('uponSanitizeAttribute', (_node, data) => {\n const name = data.attrName.toLowerCase();\n if (URL_ATTRIBUTES.has(name) && !data.attrValue.trim().startsWith('#')) data.keepAttr = false;\n if (name === 'style') {\n data.attrValue = filterSvgStyle(data.attrValue);\n if (!data.attrValue) data.keepAttr = false;\n }\n });\n purifier = instance;\n return instance;\n};\n\n/**\n * A model-written SVG document reduced to static, self-contained drawing.\n *\n * - SVG profile only: scripts, event handlers and HTML go.\n * - `href`s survive only as same-document `#` references, so nothing loads from elsewhere.\n * - `use` is allowed back in for that reason (matplotlib draws every glyph with it).\n * - References are then confined to the fence; see `scopeSvgReferences`.\n */\nexport const sanitizeSvgFence = (svg: string): string => {\n const template = document.createElement('template');\n template.innerHTML = getPurifier().sanitize(svg, {\n USE_PROFILES: { svg: true, svgFilters: true },\n ADD_TAGS: ['use'],\n FORBID_TAGS: FORBIDDEN_TAGS,\n });\n scopeSvgReferences(template.content);\n return template.innerHTML;\n};\n","import { createContext } from 'react';\n\n/** Whether the `Markdown.Block` being rendered draws ```svg fences; off by default. */\nexport const SvgFencesContext = createContext(false);\n","import { use, useMemo } from 'react';\nimport type { ReactNode } from 'react';\n\nimport { ZoomableSvg } from '../../components/ZoomableSvg';\nimport { makeResponsive } from '../DiagramShared/svgTransforms';\n\nimport { sanitizeSvgFence } from './sanitizeSvgFence';\nimport { SvgFencesContext } from './SvgFencesContext';\n\ntype Props = {\n /** The fence's single SVG document, unsanitized. */\n svg: string;\n /** The fence as it was written, for the copy action. */\n source: string;\n /** The code block, shown when the block does not draw svg fences. */\n children: ReactNode;\n};\n\n/** A fenced SVG chart, sanitized and drawn responsive, in a block that opted in. */\nexport const SvgFenceChart = ({ svg, source, children }: Props) => {\n const allowed = use(SvgFencesContext);\n const html = useMemo(\n () => (allowed ? makeResponsive(sanitizeSvgFence(svg)) : ''),\n [allowed, svg],\n );\n if (!allowed || !html) return children;\n return <ZoomableSvg html={html} copyText={source} className=\"tw:my-3\" allowUse />;\n};\n","const DIAGRAM_LANGUAGE_LIST = ['mermaid', 'flint', 'flint-chart'] as const;\n\nexport type DiagramLanguage = (typeof DIAGRAM_LANGUAGE_LIST)[number];\n\n/**\n * The fence languages `Markdown` draws instead of printing.\n *\n * - Streaming callers hold an open fence back as plain code, or every keystroke fetches the chunk.\n * - Frozen: it is shared across every app in the bundle.\n */\nexport const DIAGRAM_LANGUAGES: readonly string[] = Object.freeze([...DIAGRAM_LANGUAGE_LIST]);\n","import { createContext, isValidElement, use, useMemo } from 'react';\nimport type { ComponentPropsWithoutRef, PropsWithChildren, ReactNode } from 'react';\nimport type { Components, ExtraProps, Options } from 'react-markdown';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\n\nimport { Table } from '../../components/Table';\nimport { cn } from '../../utils';\nimport { ClipboardButton } from '../ClipboardButton';\n\nimport { ChatInlineIcon, getChatInlineIconName } from './ChatInlineIcon';\nimport { DiagramBlock } from './DiagramBlock';\nimport type { DiagramLoader } from './diagramChunk';\nimport { diagramChunk } from './diagramChunk';\nimport { DiagramDownloadButton } from './DiagramDownloadButton';\nimport type { DiagramLanguage } from './diagramLanguages';\nimport { HighlightedCode } from './HighlightedCode';\nimport { getHighlightGrammar } from './highlightLanguages';\nimport { MarkdownGrid } from './MarkdownGrid';\nimport type { MarkdownOptions, RenderDiagramActions } from './markdownOptions';\nimport { MarkdownOptionsContext } from './markdownOptions';\nimport { MarkdownTableBody } from './MarkdownTableBody';\nimport { MarkdownTableHead } from './MarkdownTableHead';\nimport { MarkdownTableRow } from './MarkdownTableRow';\nimport { svgFenceDocument } from './svgFence';\nimport { SvgFenceChart } from './SvgFenceChart';\nimport { SvgFencesContext } from './SvgFencesContext';\n\nexport { DIAGRAM_LANGUAGES } from './diagramLanguages';\n\n// Both chunks are heavy (Pele, vega) and rarely needed, so they load on demand.\nconst loadMermaid = diagramChunk('MermaidDiagram', () =>\n import('@keboola/design/mermaid').then((module) => module.MermaidDiagram),\n);\n\nconst loadFlint = diagramChunk('FlintChart', () =>\n import('@keboola/design/flint').then((module) => module.FlintChart),\n);\n\n// The one definition of how a Keboola answer reads.\n//\n// - Rhythm lives in `tw:prose-answer` (`src/styles.css`), palette in `typography.ts`\n// (`@keboola/tailwind-config`); don't layer utilities here.\n// - `tw:prose-code-chip` on both: otherwise chrome keeps `#c7254e` (3.36:1 on dark).\nconst PROSE_CLASS = {\n answer: 'tw:prose tw:prose-answer tw:prose-code-chip tw:break-words',\n chrome: 'tw:prose tw:prose-sm tw:prose-code-chip tw:break-words',\n} as const;\n\n/**\n * Which reading rhythm the surface wears.\n *\n * - `answer`: an assistant reply, 78ch measure.\n * - `chrome`: uncapped, dense; for content a model did not write.\n */\ntype Rhythm = keyof typeof PROSE_CLASS;\n\nconst getText = (node: ReactNode): string => {\n if (typeof node === 'string') return node;\n if (typeof node === 'number') return String(node);\n if (Array.isArray(node)) return node.map(getText).join('');\n if (\n isValidElement(node) &&\n typeof node.props === 'object' &&\n node.props !== null &&\n 'children' in node.props\n ) {\n return getText((node.props as { children: ReactNode }).children);\n }\n return '';\n};\n\nconst getLanguage = (element: ReactNode): string | undefined => {\n if (!isValidElement(element)) return undefined;\n const { props } = element;\n if (typeof props !== 'object' || props === null || !('className' in props)) return undefined;\n if (typeof props.className !== 'string') return undefined;\n return props.className.match(/language-(\\S+)/)?.[1];\n};\n\n/** Always run; a caller's plugins are appended, never substituted. */\nconst baseRemarkPlugins: NonNullable<Options['remarkPlugins']> = [remarkGfm];\n\n/**\n * Fence language → the on-demand chunk that draws it.\n *\n * - Dialects come from kai-agent's prompt; keep in sync with kbc-ui `markdownComponents.tsx`.\n * - `flint-chart`: alias models emit unprompted.\n * - Read via `Object.hasOwn`: ```constructor would otherwise hit `Object.prototype` and throw.\n */\nconst DIAGRAM_CHUNKS: Record<string, DiagramLoader | undefined> = {\n mermaid: loadMermaid,\n flint: loadFlint,\n 'flint-chart': loadFlint,\n} satisfies Record<DiagramLanguage, DiagramLoader>;\n\n/**\n * Whether the `code` being rendered sits inside a fenced block.\n *\n * - Set by `pre`: a fence without info string has no `language-…` class, like inline code.\n */\nconst CodeBlockContext = createContext(false);\n\n/**\n * The `code` renderer: an inline `icon:<name>` token becomes the icon it names.\n *\n * - Fenced blocks never swap.\n * - Unknown names stay code; a name still streaming renders nothing.\n */\nconst MarkdownCode = ({\n children,\n className,\n ...props\n}: ComponentPropsWithoutRef<'code'> & ExtraProps) => {\n const { node: _node, ...rest } = props;\n const isBlock = use(CodeBlockContext);\n const name = isBlock ? undefined : getChatInlineIconName(getText(children));\n if (name !== undefined) return <ChatInlineIcon name={name} />;\n return (\n <code className={className} {...rest}>\n {children}\n </code>\n );\n};\n\n/**\n * The `pre` renderer: a diagram fence draws, any other fence prints with a copy button.\n *\n * - Diagrams replace the whole `<pre>`; a `<div>` inside `<pre><code>` is invalid HTML.\n * - A `highlight` block colours a fence whose language has a grammar, once the chunk loads.\n */\nconst MarkdownPre = (props: ComponentPropsWithoutRef<'pre'> & ExtraProps) => {\n const { children, node: _node, ...rest } = props;\n const { highlight, renderDiagramActions } = use(MarkdownOptionsContext);\n const child = Array.isArray(children) ? children[0] : children;\n const code = getText(child).replace(/\\n$/, '');\n const language = getLanguage(child);\n const load =\n language !== undefined && Object.hasOwn(DIAGRAM_CHUNKS, language)\n ? DIAGRAM_CHUNKS[language]\n : undefined;\n if (load) {\n if (!code.trim()) return null;\n return <DiagramBlock load={load} code={code} renderActions={renderDiagramActions} />;\n }\n const grammar = highlight ? getHighlightGrammar(language) : undefined;\n const block = (\n <div className=\"tw:group tw:relative\">\n <span className=\"tw:absolute tw:right-2 tw:top-2 tw:opacity-0 tw:transition-opacity tw:group-focus-within:opacity-100 tw:group-hover:opacity-100\">\n <ClipboardButton text={code} tooltip=\"Copy\" size=\"icon-xs\" variant=\"outline\" />\n </span>\n <pre {...rest}>\n <CodeBlockContext value={true}>\n {grammar === undefined ? (\n children\n ) : (\n <HighlightedCode code={code} grammar={grammar} className={`language-${language}`}>\n {children}\n </HighlightedCode>\n )}\n </CodeBlockContext>\n </pre>\n </div>\n );\n const svg = svgFenceDocument(language, code);\n if (svg === null) return block;\n return (\n <SvgFenceChart svg={svg} source={`\\`\\`\\`${language}\\n${code}\\n\\`\\`\\``}>\n {block}\n </SvgFenceChart>\n );\n};\n\n// Strip react-markdown's hast `node` before spreading onto a DOM element.\nconst baseComponents: Components = {\n pre: MarkdownPre,\n code: MarkdownCode,\n a({ children, href, ...props }: ComponentPropsWithoutRef<'a'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n const isExternal = !!href && /^https?:\\/\\//.test(href);\n return (\n <a\n href={href}\n {...(isExternal ? { target: '_blank', rel: 'noopener noreferrer' } : null)}\n {...rest}\n >\n {children}\n </a>\n );\n },\n table: MarkdownGrid,\n thead(props: ComponentPropsWithoutRef<'thead'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return <Table.Header {...rest} />;\n },\n tbody: MarkdownTableBody,\n tr: MarkdownTableRow,\n th: MarkdownTableHead,\n td(props: ComponentPropsWithoutRef<'td'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return <Table.Cell {...rest} />;\n },\n};\n\ntype BlockProps = {\n /** GFM source; ```mermaid/```flint fences render as diagrams. */\n children: string;\n /** Appended after GFM. Keep in a module constant, or the caller's memo breaks. */\n remarkPlugins?: NonNullable<Options['remarkPlugins']>;\n /** Merged by key; an override **replaces** the built-in renderer, not wraps it.\n * Keep in a module constant. */\n components?: Components;\n /** Colour fenced code with a grammar (SQL, Python, JS/TS, JSON, shell, YAML); loads on demand. */\n highlight?: boolean;\n /** Sort table rows by a header press; numeric columns sort as numbers. */\n sortable?: boolean;\n /** Extra diagram toolbar controls; receives the sanitized SVG. Keep in a module constant. */\n diagramActions?: RenderDiagramActions;\n /** Add a built-in \"Download SVG\" action to every diagram. */\n diagramDownload?: boolean;\n /**\n * Draw a ```svg fence (or an ```xml/```html one holding a single SVG document) as a chart.\n * Sanitized: no scripts, handlers, `foreignObject`, SMIL or external references.\n */\n allowSvgFences?: boolean;\n};\n\ntype Props = BlockProps & { className?: string; rhythm?: Rhythm };\n\n/**\n * The prose surface an answer is drawn on.\n *\n * - Wrap all `Block`s of one answer in one `Root`, so `:first-child`/`:last-child` span the reply.\n * - `data-prose` is `MessageBubble`'s colour hook; Tailwind can't target `tw:prose` directly.\n * - Spacing overrides need `!`: `tw:prose-answer` rules are `(0,2,1)`, above `[&_p]:mb-1`.\n */\nconst MarkdownRoot = ({\n children,\n className,\n rhythm = 'answer',\n}: PropsWithChildren<{ className?: string; rhythm?: Rhythm }>) => (\n <div data-prose className={cn(PROSE_CLASS[rhythm], className)}>\n {children}\n </div>\n);\n\n/** The diagram toolbar a block asks for: the caller's actions, then the built-in download. */\nconst composeDiagramActions = (\n diagramActions: RenderDiagramActions | undefined,\n diagramDownload: boolean,\n): RenderDiagramActions | undefined => {\n if (!diagramDownload) return diagramActions;\n return (safeSvg) => (\n <>\n {diagramActions?.(safeSvg)}\n <DiagramDownloadButton safeSvg={safeSvg} />\n </>\n );\n};\n\n/** One parsed piece of an answer, with no surface of its own; memoise at the call site. */\nconst MarkdownBlock = ({\n children,\n remarkPlugins,\n components: componentOverrides,\n highlight = false,\n sortable = false,\n diagramActions,\n diagramDownload = false,\n allowSvgFences = false,\n}: BlockProps) => {\n const options = useMemo<MarkdownOptions>(\n () => ({\n highlight,\n sortable,\n renderDiagramActions: composeDiagramActions(diagramActions, diagramDownload),\n }),\n [highlight, sortable, diagramActions, diagramDownload],\n );\n return (\n <MarkdownOptionsContext value={options}>\n <SvgFencesContext value={allowSvgFences}>\n <ReactMarkdown\n remarkPlugins={\n remarkPlugins === undefined\n ? baseRemarkPlugins\n : [...baseRemarkPlugins, ...remarkPlugins]\n }\n components={\n componentOverrides === undefined\n ? baseComponents\n : { ...baseComponents, ...componentOverrides }\n }\n >\n {children}\n </ReactMarkdown>\n </SvgFencesContext>\n </MarkdownOptionsContext>\n );\n};\n\n/**\n * Read-only GFM Markdown renderer with design-token typography.\n *\n * - Needs a `TooltipProvider` at the app root (code copy button).\n * - Pass `rhythm=\"chrome\"` for content a model did not write.\n */\nexport const Markdown = ({ className, rhythm, ...blockProps }: Props) => (\n <MarkdownRoot className={className} rhythm={rhythm}>\n <MarkdownBlock {...blockProps} />\n </MarkdownRoot>\n);\n\nMarkdown.Root = MarkdownRoot;\nMarkdown.Block = MarkdownBlock;\n","import { type ReactNode, useCallback, useEffect, useRef, useState } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { Tooltip } from '../../components/Tooltip';\nimport { Maximize2 } from '../../icons';\nimport { cn } from '../../utils';\n\nimport { TableSortProvider } from './TableSortProvider';\n\n/** How much wider than its column a table has to be before the column is the wrong surface. */\nconst EXPAND_RATIO = 1.5;\n\n/**\n * The fade's end colour — must match the host's surface, or it draws a strip over the data.\n *\n * - Full class strings: Tailwind reads literals.\n */\nconst FADE_SURFACE = {\n card: 'tw:from-card',\n background: 'tw:from-background',\n} as const;\n\ntype Surface = keyof typeof FADE_SURFACE;\n\ntype Props = {\n /** A `Table bordered` at intrinsic width (`tw:min-w-max`) — otherwise it wraps and never overflows. */\n children: ReactNode;\n /** What the host paints behind the table; paint `Table`'s header band this colour too. */\n surface?: Surface;\n /** Host controls left of the expand action; hover reveal is the host's (`tw:group` on `className`). */\n actions?: ReactNode;\n /** Opens the table somewhere wider; omit where there is nowhere to go (the fade still draws). */\n onExpand?: () => void;\n /** Sort rows by a header press, when the table is drawn by `Markdown`'s row and cell renderers. */\n sortable?: boolean;\n className?: string;\n};\n\n/**\n * A table in an answer that shows when it is cut off on the right.\n *\n * - Controls sit in a fixed-height rail above the grid, so they never cover rows or shift them.\n * - The fade shows only while content remains to the right.\n * - A painted gradient, not `tw:scroll-fade-x`: that needs scroll-driven animations, which the\n * `baseline-widely-available` build floor lacks, and must sit on `Table`'s own container.\n * - Past `EXPAND_RATIO` the expand action shows without hover.\n */\nexport const MarkdownTable = ({\n children,\n actions,\n onExpand,\n surface = 'card',\n sortable = false,\n className,\n}: Props) => {\n const frameRef = useRef<HTMLDivElement>(null);\n const [overflow, setOverflow] = useState({ scrollable: false, atEnd: true, ratio: 1 });\n\n // Scrolls `Table`'s own container (the frame's first child); the frame stays visible for the fade.\n const measure = useCallback(() => {\n const box = frameRef.current?.firstElementChild;\n if (!box) return;\n\n const { scrollLeft, scrollWidth, clientWidth } = box;\n const hidden = scrollWidth - clientWidth;\n\n setOverflow({\n scrollable: hidden > 1,\n atEnd: scrollLeft >= hidden - 1,\n ratio: clientWidth > 0 ? scrollWidth / clientWidth : 1,\n });\n }, []);\n\n useEffect(() => {\n const box = frameRef.current?.firstElementChild;\n if (!box) return;\n\n measure();\n box.addEventListener('scroll', measure, { passive: true });\n\n // Both widths move independently:\n // - the box's, when the panel resizes without the viewport;\n // - the grid's, as streamed cells widen it inside a box that never moves.\n const observer = new ResizeObserver(measure);\n observer.observe(box);\n if (box.firstElementChild) observer.observe(box.firstElementChild);\n\n return () => {\n box.removeEventListener('scroll', measure);\n observer.disconnect();\n };\n }, [measure]);\n\n const showExpand = !!onExpand && overflow.scrollable && overflow.ratio >= EXPAND_RATIO;\n\n return (\n <div className={className}>\n {(actions || onExpand) && (\n // Hover controls go left: a hidden reveal span keeps its width and would leave a gap.\n <div className=\"tw:flex tw:h-8 tw:items-center tw:justify-end tw:gap-1\">\n {actions}\n {showExpand && (\n // Not a native `title`: it renders under the pointer, over the header row.\n <Tooltip\n tooltip=\"This table is wider than the space it has\"\n placement=\"top\"\n triggerAsChild\n >\n <Button size=\"small\" variant=\"invisible\" onClick={onExpand}>\n <Maximize2 className=\"tw:size-3.5\" />\n Open wider\n </Button>\n </Tooltip>\n )}\n </div>\n )}\n\n <div ref={frameRef} className=\"tw:relative\">\n {sortable ? <TableSortProvider>{children}</TableSortProvider> : children}\n\n {overflow.scrollable && !overflow.atEnd && (\n <span\n aria-hidden\n data-testid=\"markdown-table-fade\"\n className={cn(\n 'tw:pointer-events-none tw:absolute tw:inset-y-px tw:right-px tw:w-12 tw:rounded-r-[10px] tw:bg-gradient-to-l tw:to-transparent',\n FADE_SURFACE[surface],\n )}\n />\n )}\n </div>\n </div>\n );\n};\n","import { useLayoutEffect, useRef, useState } from 'react';\nimport type { ReactNode } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { cn } from '../../utils';\n\ntype Props = {\n maxHeight: number;\n /** The `from-*` utility matching the surface the fade runs into. */\n fadeClassName: string;\n children: ReactNode;\n};\n\n/**\n * Clips tall content at `maxHeight` behind a fade, with a Show more / Show less toggle.\n *\n * - The toggle and fade appear only while the content is taller than `maxHeight`.\n * - Height is measured with a `ResizeObserver`; without one (jsdom) nothing is clipped.\n */\nexport const CollapsedMessageBody = ({ maxHeight, fadeClassName, children }: Props) => {\n const contentRef = useRef<HTMLDivElement>(null);\n const [isOverflowing, setIsOverflowing] = useState(false);\n const [isExpanded, setIsExpanded] = useState(false);\n\n useLayoutEffect(() => {\n const node = contentRef.current;\n if (!node || typeof ResizeObserver === 'undefined') return;\n\n const observer = new ResizeObserver(() => setIsOverflowing(node.offsetHeight > maxHeight));\n observer.observe(node);\n\n return () => observer.disconnect();\n }, [maxHeight]);\n\n const isClipped = isOverflowing && !isExpanded;\n\n return (\n <div className=\"tw:flex tw:flex-col tw:items-start tw:gap-1\">\n <div\n className=\"tw:relative tw:w-full tw:overflow-hidden\"\n style={isClipped ? { maxHeight } : undefined}\n >\n <div ref={contentRef}>{children}</div>\n {isClipped && (\n <div\n aria-hidden\n className={cn(\n 'tw:pointer-events-none tw:absolute tw:inset-x-0 tw:bottom-0 tw:h-12 tw:bg-gradient-to-t tw:to-transparent',\n fadeClassName,\n )}\n />\n )}\n </div>\n {isOverflowing && (\n <Button\n variant=\"inline\"\n size=\"small\"\n className=\"tw:px-0\"\n aria-expanded={isExpanded}\n onClick={() => setIsExpanded((v) => !v)}\n >\n {isExpanded ? 'Show less' : 'Show more'}\n </Button>\n )}\n </div>\n );\n};\n","import { Button } from '../../components/Button';\n\nexport type MessageStatus = 'sending' | 'failed';\n\ntype Props = {\n status: MessageStatus;\n onRetry?: () => void;\n};\n\n/**\n * Where a sent message stands, until it is delivered.\n *\n * - `sending` is announced politely; `failed` is an alert with a Retry button when `onRetry` is set.\n */\nexport const MessageDeliveryStatus = ({ status, onRetry }: Props) => {\n if (status === 'sending') {\n return (\n <span role=\"status\" className=\"tw:text-xs tw:text-muted-foreground\">\n Sending…\n </span>\n );\n }\n\n return (\n <span\n role=\"alert\"\n className=\"tw:inline-flex tw:items-center tw:gap-2 tw:text-xs tw:text-destructive\"\n >\n Failed to send\n {onRetry && (\n <Button variant=\"inline\" size=\"small\" className=\"tw:px-0\" onClick={onRetry}>\n Retry\n </Button>\n )}\n </span>\n );\n};\n","type Props = {\n createdAt: string;\n};\n\nconst TIME_FORMAT = { hour: '2-digit', minute: '2-digit' } as const;\n\n/**\n * The time a message was sent.\n *\n * - Shows the clock time, with the full locale date and time as the tooltip.\n * - Draws nothing for a value that is not a date.\n */\nexport const MessageTimestamp = ({ createdAt }: Props) => {\n const date = new Date(createdAt);\n if (Number.isNaN(date.getTime())) return null;\n\n return (\n <time\n dateTime={date.toISOString()}\n title={date.toLocaleString()}\n className=\"tw:text-xs tw:text-muted-foreground\"\n >\n {date.toLocaleTimeString([], TIME_FORMAT)}\n </time>\n );\n};\n","import type { ComponentProps, PropsWithChildren, ReactNode } from 'react';\nimport { cva } from 'class-variance-authority';\n\nimport type { Avatar } from '../../components/Avatar';\nimport { cn } from '../../utils';\n\nimport { CollapsedMessageBody } from './CollapsedMessageBody';\nimport { MessageDeliveryStatus, type MessageStatus } from './MessageDeliveryStatus';\nimport { MessageTimestamp } from './MessageTimestamp';\n\nconst containerClasses = cva(['tw:flex', 'tw:max-w-full', 'tw:gap-3'], {\n variants: {\n variant: {\n user: ['tw:justify-end'],\n assistant: ['tw:justify-start', 'tw:w-full'],\n },\n },\n defaultVariants: {\n variant: 'assistant',\n },\n});\n\nconst stackClasses = cva(['tw:flex', 'tw:min-w-0', 'tw:flex-1', 'tw:flex-col', 'tw:gap-2'], {\n variants: {\n variant: {\n user: ['tw:items-end'],\n assistant: [],\n },\n },\n defaultVariants: {\n variant: 'assistant',\n },\n});\n\nconst contentClasses = cva(\n [\n 'tw:flex',\n 'tw:flex-col',\n // Small gap: prose already spaces its blocks.\n 'tw:gap-3',\n 'tw:break-words',\n 'tw:leading-relaxed',\n 'tw:text-foreground',\n // `data-prose`, not `tw:prose`: Tailwind scans raw bytes, so a `\\:` escape reaches it doubled.\n 'tw:[&_[data-prose]]:text-foreground',\n ],\n {\n variants: {\n variant: {\n assistant: ['tw:flex-1', 'tw:w-full', 'tw:min-w-0', 'tw:[&>*]:min-w-0'],\n user: [\n // A share of the column, so a docked panel keeps the left gutter; a margin would push\n // a `w-fit` bubble past the column. The absolute cap bounds a fullscreen panel.\n 'tw:max-w-[min(85%,40rem)]',\n 'tw:w-fit',\n 'tw:bg-muted',\n // Tighter vertically, with a smaller radius, so a one-line message reads as speech.\n 'tw:px-3',\n 'tw:py-2',\n 'tw:rounded-xl',\n 'tw:overflow-hidden',\n 'tw:wrap-anywhere',\n ],\n },\n },\n\n defaultVariants: {\n variant: 'assistant',\n },\n },\n);\n\ntype Props = {\n variant: 'user' | 'assistant';\n actions?: ReactNode;\n createdAt?: string;\n /** `visible` draws the time in the actions row; the default keeps it as the user bubble's tooltip. */\n timestamp?: 'tooltip' | 'visible';\n /** What a user message replies to, drawn as a muted blockquote above the text. */\n quote?: ReactNode;\n /** User variant: a message still on its way, or one that did not arrive. */\n status?: MessageStatus;\n onRetry?: () => void;\n /** Who wrote it, where several people share a chat. */\n author?: ReactNode;\n /** Clip the message at this height behind Show more / Show less. */\n collapseAfterPx?: number;\n /** Opt-in per-message avatar, beside the bubble; none by default so a narrow panel keeps its width. */\n avatar?: ReactNode;\n /** @deprecated No avatar is rendered; accepted so existing call sites keep compiling. */\n user?: ComponentProps<typeof Avatar>['user'];\n} & PropsWithChildren;\n\nexport const MessageBubble = ({\n variant,\n children,\n actions,\n createdAt,\n timestamp = 'tooltip',\n quote,\n status,\n onRetry,\n author,\n collapseAfterPx,\n avatar,\n}: Props) => {\n const isTimestampVisible = timestamp === 'visible' && createdAt !== undefined;\n const isSending = variant === 'user' && status === 'sending';\n const deliveryStatus =\n variant === 'user' && status ? (\n <MessageDeliveryStatus status={status} onRetry={onRetry} />\n ) : null;\n\n const body =\n collapseAfterPx === undefined ? (\n children\n ) : (\n <CollapsedMessageBody\n maxHeight={collapseAfterPx}\n fadeClassName={variant === 'user' ? 'tw:from-muted' : 'tw:from-background'}\n >\n {children}\n </CollapsedMessageBody>\n );\n\n const hasActionsRow = isTimestampVisible || deliveryStatus !== null;\n\n return (\n <div className={containerClasses({ variant })} data-testid={`chat-message-${variant}`}>\n {variant === 'assistant' && avatar}\n <div className={stackClasses({ variant })}>\n {author && (\n <div className=\"tw:text-xs tw:font-medium tw:text-muted-foreground\">{author}</div>\n )}\n {/* Timestamp on the user's bubble only: on an answer the native tooltip would cover\n tables and code. */}\n <div\n className={cn(contentClasses({ variant }), isSending && 'tw:opacity-70')}\n title={variant === 'user' && timestamp === 'tooltip' ? createdAt : undefined}\n >\n {quote && (\n <blockquote className=\"tw:m-0 tw:border-l-2 tw:border-border tw:pl-2 tw:text-sm tw:text-muted-foreground\">\n {quote}\n </blockquote>\n )}\n {body}\n </div>\n {hasActionsRow ? (\n <div className=\"tw:flex tw:items-center tw:gap-2\">\n {isTimestampVisible && <MessageTimestamp createdAt={createdAt} />}\n {deliveryStatus}\n {actions}\n </div>\n ) : (\n actions\n )}\n </div>\n {variant === 'user' && avatar}\n </div>\n );\n};\n","import type { ComponentProps, ReactNode } from 'react';\n\nimport { Badge } from '../../components/Badge';\nimport { Tooltip } from '../../components/Tooltip';\nimport { X } from '../../icons';\nimport { cn } from '../../utils';\n\ntype Props = {\n children: ReactNode;\n /** Mounted either way; `false` collapses and fades it out so neighbours slide instead of jump. */\n visible?: boolean;\n tooltip?: ReactNode;\n /** Accessible name of the chip, which turns the mode off. */\n removeLabel: string;\n color?: ComponentProps<typeof Badge>['color'];\n onRemove: () => void;\n className?: string;\n};\n\n/**\n * A removable pill naming a mode the composer is in.\n *\n * - The whole chip turns the mode off, not just the ×.\n * - Collapsed via a `0fr` / `1fr` grid column and taken out of the tab order while hidden.\n */\nexport const ModeChip = ({\n children,\n visible = true,\n tooltip,\n removeLabel,\n color = 'amber',\n onRemove,\n className,\n}: Props) => {\n const button = (\n <button\n type=\"button\"\n onClick={onRemove}\n tabIndex={visible ? undefined : -1}\n aria-label={removeLabel}\n className=\"tailwindcss-preflight tw:cursor-pointer tw:border-0 tw:bg-transparent tw:p-0\"\n >\n <Badge variant=\"pill\" color={color} suffix={<X className=\"tw:size-3\" />}>\n {children}\n </Badge>\n </button>\n );\n\n return (\n <div\n aria-hidden={!visible}\n className={cn(\n 'tw:grid tw:transition-all tw:duration-200 tw:ease-out tw:motion-reduce:transition-none',\n visible\n ? 'tw:mr-1 tw:grid-cols-[1fr] tw:opacity-100'\n : 'tw:mr-0 tw:grid-cols-[0fr] tw:opacity-0',\n className,\n )}\n >\n <div className=\"tw:overflow-hidden\">\n {tooltip ? (\n <Tooltip placement=\"top\" tooltip={tooltip} triggerAsChild>\n {button}\n </Tooltip>\n ) : (\n button\n )}\n </div>\n </div>\n );\n};\n","import { type FormEvent, type KeyboardEvent, type ReactNode, useState } from 'react';\n\nimport { Badge } from '../../components/Badge';\nimport { Button } from '../../components/Button';\nimport {\n FullScreenModal,\n FullScreenModalBody,\n FullScreenModalHeader,\n} from '../../components/FullScreenModal';\nimport { Tooltip } from '../../components/Tooltip';\nimport { ChevronDown, Maximize2, Minimize2, Send, X } from '../../icons';\nimport { cn } from '../../utils';\nimport { Textarea } from '../Textarea';\n\nimport { CollapsibleBody } from './CollapsibleBody';\nimport { hasMotion } from './hasMotion';\n\ntype PlanApprovalStatus = 'pending' | 'approved' | 'dismissed' | 'changes-requested' | 'expired';\n\ntype PlanApprovalProps = {\n status: PlanApprovalStatus;\n /** Replaces the status pill's text, e.g. `Cancelled` for an `expired` card closed by a restart. */\n statusLabel?: string;\n /** Why the card is in its status, shown under the title. */\n statusMessage?: ReactNode;\n title: string;\n summary?: ReactNode;\n stepCount?: number;\n planBody?: ReactNode;\n\n defaultExpanded?: boolean;\n isExpanded?: boolean;\n onExpandToggle?: (next: boolean) => void;\n\n onApprove?: () => void;\n onRequestChanges?: (reason: string) => void;\n onClose?: () => void;\n isSubmitting?: boolean;\n approveTooltip?: ReactNode;\n\n pendingPillLabel?: string;\n approvedPillLabel?: string;\n dismissedPillLabel?: string;\n changesRequestedPillLabel?: string;\n approveLabel?: string;\n requestChangesLabel?: string;\n cancelLabel?: string;\n showMoreLabel?: string;\n showLessLabel?: string;\n closeLabel?: string;\n fullScreenLabel?: string;\n exitFullScreenLabel?: string;\n changeRequestPlaceholder?: string;\n changeRequestSubmitLabel?: string;\n stepCountLabel?: (count: number) => string;\n\n className?: string;\n};\n\nconst defaultStepCountLabel = (count: number) => `${count} step${count === 1 ? '' : 's'}`;\n\nconst STATUS_PILL_COLOR: Record<PlanApprovalStatus, 'green' | 'gray' | 'blue' | 'orange'> = {\n pending: 'green',\n approved: 'green',\n dismissed: 'gray',\n 'changes-requested': 'blue',\n expired: 'orange',\n};\n\nconst StatusPill = ({ status, label }: { status: PlanApprovalStatus; label: string }) => (\n <Badge color={STATUS_PILL_COLOR[status]} variant=\"pill\">\n {label}\n </Badge>\n);\n\nconst ExpandToggle = ({\n isExpanded,\n onToggle,\n showMoreLabel,\n showLessLabel,\n}: {\n isExpanded: boolean;\n onToggle: () => void;\n showMoreLabel: string;\n showLessLabel: string;\n}) => (\n <button\n type=\"button\"\n onClick={onToggle}\n aria-expanded={isExpanded}\n className=\"tw:inline-flex tw:cursor-pointer tw:items-center tw:gap-1 tw:bg-transparent tw:p-0 tw:text-sm tw:font-medium tw:text-secondary-500 tw:hover:text-secondary-600 tw:focus-visible:outline tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:focus-visible:outline-ring tailwindcss-preflight\"\n >\n <span>{isExpanded ? showLessLabel : showMoreLabel}</span>\n <ChevronDown\n className={cn('tw:size-5 tw:transition-transform', isExpanded && 'tw:rotate-180')}\n />\n </button>\n);\n\nconst ChangeRequestForm = ({\n value,\n onValueChange,\n onSubmit,\n onKeyDown,\n placeholder,\n submitLabel,\n formLabel,\n canSubmit,\n isSubmitting,\n}: {\n value: string;\n onValueChange: (value: string) => void;\n onSubmit: (event?: FormEvent) => void;\n onKeyDown: (event: KeyboardEvent<HTMLTextAreaElement>) => void;\n placeholder: string;\n submitLabel: string;\n formLabel: string;\n canSubmit: boolean;\n isSubmitting: boolean;\n}) => (\n <form\n onSubmit={onSubmit}\n className=\"tw:border-0 tw:border-t tw:border-solid tw:border-border tw:bg-card tw:text-card-foreground tw:px-4 tw:py-3\"\n aria-label={formLabel}\n >\n <div className=\"tw:relative\">\n <Textarea\n value={value}\n onValueChange={onValueChange}\n placeholder={placeholder}\n maxRows={4}\n autoFocus\n onKeyDown={onKeyDown}\n containerClassName=\"tw:pr-12\"\n disabled={isSubmitting}\n aria-label={placeholder}\n data-testid=\"plan-change-request-input\"\n />\n <Button\n type=\"submit\"\n variant=\"invisible\"\n size=\"icon-sm\"\n aria-label={submitLabel}\n disabled={!canSubmit}\n className=\"tw:absolute tw:right-2 tw:top-1/2 tw:-translate-y-1/2 tw:[&_svg]:text-secondary-500 tw:not-disabled:hover:[&_svg]:text-secondary-600\"\n data-testid=\"plan-change-request-submit\"\n >\n <Send className=\"tw:size-4\" />\n </Button>\n </div>\n </form>\n);\n\nconst PlanActions = ({\n isRequestingChanges,\n isSubmitting,\n onApprove,\n onRequestChanges,\n onOpenRequestChanges,\n onCancelChangeRequest,\n approveLabel,\n requestChangesLabel,\n cancelLabel,\n approveTooltip,\n}: {\n isRequestingChanges: boolean;\n isSubmitting: boolean;\n onApprove?: () => void;\n onRequestChanges?: (reason: string) => void;\n onOpenRequestChanges: () => void;\n onCancelChangeRequest: () => void;\n approveLabel: string;\n requestChangesLabel: string;\n cancelLabel: string;\n approveTooltip?: ReactNode;\n}) => (\n <div className=\"tw:flex tw:shrink-0 tw:items-center tw:gap-2\">\n {isRequestingChanges ? (\n <Button\n variant=\"outline\"\n size=\"small\"\n onClick={onCancelChangeRequest}\n disabled={isSubmitting}\n data-testid=\"plan-cancel-button\"\n className=\"tw:shrink-0 tw:whitespace-nowrap\"\n >\n {cancelLabel}\n </Button>\n ) : (\n onRequestChanges && (\n <Button\n variant=\"outline\"\n size=\"small\"\n onClick={onOpenRequestChanges}\n disabled={isSubmitting}\n data-testid=\"plan-request-changes-button\"\n className=\"tw:shrink-0 tw:whitespace-nowrap\"\n >\n {requestChangesLabel}\n </Button>\n )\n )}\n {onApprove &&\n (approveTooltip ? (\n <Tooltip tooltip={approveTooltip} placement=\"top\" triggerAsChild>\n <Button\n variant=\"primary\"\n size=\"small\"\n onClick={onApprove}\n disabled={isSubmitting || isRequestingChanges}\n data-testid=\"plan-approve-button\"\n className=\"tw:shrink-0 tw:whitespace-nowrap\"\n >\n {approveLabel}\n </Button>\n </Tooltip>\n ) : (\n <Button\n variant=\"primary\"\n size=\"small\"\n onClick={onApprove}\n disabled={isSubmitting || isRequestingChanges}\n data-testid=\"plan-approve-button\"\n className=\"tw:shrink-0 tw:whitespace-nowrap\"\n >\n {approveLabel}\n </Button>\n ))}\n </div>\n);\n\nexport const PlanApproval = ({\n status,\n statusLabel,\n statusMessage,\n title,\n summary,\n stepCount,\n planBody,\n\n defaultExpanded = false,\n isExpanded: isExpandedProp,\n onExpandToggle,\n\n onApprove,\n onRequestChanges,\n onClose,\n isSubmitting = false,\n approveTooltip,\n\n pendingPillLabel = 'Ready for approval',\n approvedPillLabel = 'Approved',\n dismissedPillLabel = 'Dismissed',\n changesRequestedPillLabel = 'Changes Requested',\n approveLabel = 'Approve',\n requestChangesLabel = 'Request Changes',\n cancelLabel = 'Cancel',\n showMoreLabel = 'Show more',\n showLessLabel = 'Show less',\n closeLabel = 'Dismiss plan',\n fullScreenLabel = 'View full screen',\n exitFullScreenLabel = 'Exit full screen',\n changeRequestPlaceholder = 'What would you like to change in the plan?',\n changeRequestSubmitLabel = 'Send change request',\n stepCountLabel = defaultStepCountLabel,\n\n className,\n}: PlanApprovalProps) => {\n const [uncontrolledExpanded, setUncontrolledExpanded] = useState(defaultExpanded);\n const isExpanded = isExpandedProp ?? uncontrolledExpanded;\n const [isRequestingChanges, setIsRequestingChanges] = useState(false);\n const [changeRequest, setChangeRequest] = useState('');\n const [isFullScreen, setIsFullScreen] = useState(false);\n\n const pillLabel =\n statusLabel ??\n {\n pending: pendingPillLabel,\n approved: approvedPillLabel,\n dismissed: dismissedPillLabel,\n 'changes-requested': changesRequestedPillLabel,\n expired: 'Expired',\n }[status];\n const isPending = status === 'pending';\n const showActions = isPending && (onApprove || onRequestChanges);\n const showClose = isPending && Boolean(onClose);\n const canShowPlanBody = planBody != null;\n const trimmedChangeRequest = changeRequest.trim();\n const canSubmitChangeRequest = trimmedChangeRequest.length > 0 && !isSubmitting;\n\n const [isClosing, setIsClosing] = useState(false);\n\n const toggleExpanded = () => {\n const next = !isExpanded;\n if (!next) setIsClosing(hasMotion());\n if (isExpandedProp === undefined) {\n setUncontrolledExpanded(next);\n }\n onExpandToggle?.(next);\n };\n\n const handleOpenRequestChanges = () => {\n setIsRequestingChanges(true);\n if (!isExpanded) {\n toggleExpanded();\n }\n };\n\n const handleCancelChangeRequest = () => {\n setIsRequestingChanges(false);\n setChangeRequest('');\n };\n\n const handleSubmitChangeRequest = (event?: FormEvent) => {\n event?.preventDefault();\n if (!canSubmitChangeRequest) return;\n onRequestChanges?.(trimmedChangeRequest);\n };\n\n const handleTextareaKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n handleSubmitChangeRequest();\n }\n };\n\n const showChangeRequestForm = isRequestingChanges && isPending;\n\n const changeRequestForm = (\n <ChangeRequestForm\n value={changeRequest}\n onValueChange={setChangeRequest}\n onSubmit={handleSubmitChangeRequest}\n onKeyDown={handleTextareaKeyDown}\n placeholder={changeRequestPlaceholder}\n submitLabel={changeRequestSubmitLabel}\n formLabel={requestChangesLabel}\n canSubmit={canSubmitChangeRequest}\n isSubmitting={isSubmitting}\n />\n );\n\n const planActions = (\n <PlanActions\n isRequestingChanges={isRequestingChanges}\n isSubmitting={isSubmitting}\n onApprove={onApprove}\n onRequestChanges={onRequestChanges}\n onOpenRequestChanges={handleOpenRequestChanges}\n onCancelChangeRequest={handleCancelChangeRequest}\n approveLabel={approveLabel}\n requestChangesLabel={requestChangesLabel}\n cancelLabel={cancelLabel}\n approveTooltip={approveTooltip}\n />\n );\n\n return (\n <>\n {/* Two surface tiers: shell on `background`; plan body, form and action bar on `card`.\n\n - Each tier pins its foreground too, or it inherits the host's ink and can read\n same-on-same in one scheme. */}\n <section\n aria-label={title}\n className={cn(\n 'tw:flex tw:w-full tw:max-w-[800px] tw:flex-col tw:overflow-hidden tw:rounded-xl tw:border tw:border-solid tw:border-border tw:bg-background tw:text-foreground',\n className,\n )}\n data-testid=\"plan-approval-root\"\n data-plan-status={status}\n >\n <div className=\"tw:flex tw:items-start tw:gap-2 tw:pl-4 tw:pr-2 tw:pt-4\">\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-col tw:gap-2 tw:pb-4\">\n <div className=\"tw:flex tw:items-center tw:gap-3\">\n <StatusPill status={status} label={pillLabel} />\n {/* 12px `muted-foreground` sits at the AA floor (4.55:1 in light).\n\n - The ratio is pinned in `tokenBlocks.test.ts`; fix headroom in the token. */}\n {stepCount != null && stepCount > 0 && (\n <span className=\"tw:text-xs tw:leading-4 tw:text-muted-foreground\">\n {stepCountLabel(stepCount)}\n </span>\n )}\n </div>\n <p className=\"tw:m-0 tw:text-base tw:font-semibold tw:leading-6\">{title}</p>\n {statusMessage != null && (\n <p\n className=\"tw:m-0 tw:text-sm tw:text-muted-foreground\"\n data-testid=\"plan-status-message\"\n >\n {statusMessage}\n </p>\n )}\n </div>\n <div className=\"tw:flex tw:items-center tw:gap-2\">\n {canShowPlanBody && !isFullScreen && (\n <Tooltip tooltip={fullScreenLabel} placement=\"top\" triggerAsChild>\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={fullScreenLabel}\n onClick={() => setIsFullScreen(true)}\n data-testid=\"plan-fullscreen-button\"\n >\n <Maximize2 className=\"tw:size-4\" />\n </Button>\n </Tooltip>\n )}\n {showClose && !isFullScreen && (\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={closeLabel}\n onClick={onClose}\n disabled={isSubmitting}\n data-testid=\"plan-close-button\"\n >\n <X className=\"tw:size-4\" />\n </Button>\n )}\n </div>\n </div>\n\n {summary != null && (\n <div\n className={cn(\n 'tw:whitespace-pre-wrap tw:border-0 tw:border-t tw:border-solid tw:border-border tw:px-4 tw:pt-4 tw:text-sm',\n isExpanded && canShowPlanBody ? 'tw:pb-4' : 'tw:pb-2',\n )}\n >\n {summary}\n </div>\n )}\n\n {canShowPlanBody && (\n <CollapsibleBody\n isExpanded={isExpanded}\n isClosing={isClosing}\n onClosed={() => setIsClosing(false)}\n >\n <div className=\"tw:max-h-[400px] tw:overflow-y-auto tw:border-0 tw:border-t tw:border-solid tw:border-border tw:bg-card tw:p-4 tw:text-sm tw:text-card-foreground\">\n {planBody}\n </div>\n </CollapsibleBody>\n )}\n\n {!isFullScreen && (\n <>\n {showChangeRequestForm && changeRequestForm}\n\n <div\n className={cn(\n 'tw:flex tw:items-center tw:gap-2 tw:overflow-x-auto tw:border-0 tw:border-t tw:border-solid tw:border-border tw:bg-card tw:px-4 tw:py-3 tw:text-card-foreground',\n canShowPlanBody ? 'tw:justify-between' : 'tw:justify-end',\n )}\n >\n {canShowPlanBody && (\n <div className=\"tw:shrink-0\">\n <ExpandToggle\n isExpanded={isExpanded}\n onToggle={toggleExpanded}\n showMoreLabel={showMoreLabel}\n showLessLabel={showLessLabel}\n />\n </div>\n )}\n\n {showActions && planActions}\n </div>\n </>\n )}\n </section>\n\n {canShowPlanBody && isFullScreen && (\n <FullScreenModal onEscapeKeyDown={() => setIsFullScreen(false)}>\n <FullScreenModalHeader\n title={\n <div className=\"tw:flex tw:min-w-0 tw:items-center tw:gap-3\">\n <StatusPill status={status} label={pillLabel} />\n <span className=\"tw:truncate\">{title}</span>\n </div>\n }\n onClose={() => setIsFullScreen(false)}\n showPreviousTitle={false}\n >\n <div className=\"tw:flex tw:items-center tw:gap-2\">\n {showClose && (\n <Tooltip tooltip={closeLabel} placement=\"bottom\" triggerAsChild>\n <Button\n variant=\"outline\"\n size=\"icon\"\n aria-label={closeLabel}\n onClick={onClose}\n disabled={isSubmitting}\n data-testid=\"plan-close-button\"\n >\n <X className=\"tw:size-4\" />\n </Button>\n </Tooltip>\n )}\n <Tooltip tooltip={exitFullScreenLabel} placement=\"bottom\" triggerAsChild>\n <Button\n variant=\"outline\"\n size=\"icon\"\n aria-label={exitFullScreenLabel}\n onClick={() => setIsFullScreen(false)}\n data-testid=\"plan-exit-fullscreen-button\"\n >\n <Minimize2 className=\"tw:size-4\" />\n </Button>\n </Tooltip>\n </div>\n </FullScreenModalHeader>\n {/* Portalled to `document.body`, so body and footer pin their own surface and ink. */}\n <FullScreenModalBody className=\"tw:bg-card tw:px-6 tw:py-4 tw:text-card-foreground\">\n <div className=\"tw:mx-auto tw:w-full tw:max-w-[800px] tw:text-sm\">{planBody}</div>\n </FullScreenModalBody>\n {(showChangeRequestForm || showActions) && (\n <div className=\"tw:shrink-0 tw:border-0 tw:border-t tw:border-solid tw:border-border tw:bg-card tw:text-card-foreground\">\n <div className=\"tw:mx-auto tw:w-full tw:max-w-[800px]\">\n {showChangeRequestForm && changeRequestForm}\n {showActions && (\n <div className=\"tw:flex tw:justify-end tw:px-4 tw:py-3\">{planActions}</div>\n )}\n </div>\n </div>\n )}\n </FullScreenModal>\n )}\n </>\n );\n};\n\nexport type { PlanApprovalStatus, PlanApprovalProps };\n","import { Loader2 } from '../../icons';\n\ntype PlanRewritingIndicatorProps = {\n label?: string;\n};\n\nexport const PlanRewritingIndicator = ({\n label = 'Rewriting the plan...',\n}: PlanRewritingIndicatorProps) => (\n <div\n className=\"tw:flex tw:items-center tw:gap-2\"\n role=\"status\"\n data-testid=\"plan-rewriting-indicator\"\n >\n <Loader2 className=\"tw:size-4 tw:animate-spin tw:text-secondary-500\" />\n <span className=\"tw:text-sm tw:italic tw:text-secondary-500\">{label}</span>\n </div>\n);\n\nexport type { PlanRewritingIndicatorProps };\n","/**\n * Names the container query `PromptInput`'s `inline` row reads to fold into the stacked layout.\n *\n * It has to sit on an **ancestor**: a container query matches descendants only, so the field that\n * would read it cannot name it, and its own wrapper is the width the fold changes. A host that\n * never names it keeps the one-line row at every width.\n */\nexport const PROMPT_INPUT_CONTAINER = 'tw:@container/composer';\n","import { type ReactNode, type TransitionEvent, useLayoutEffect, useRef, useState } from 'react';\n\nimport { cn } from '../../utils';\n\nimport { hasMotion } from './hasMotion';\n\ntype Props = {\n children: ReactNode;\n className?: string;\n};\n\n/**\n * A box whose height eases to whatever its content measures.\n *\n * - Content is measured with a `ResizeObserver`; without one (jsdom) the box is plain `auto`.\n * - The first measurement lands without a transition, so mounting with content does not grow in.\n * - Overflow is clipped only while the height moves, so focus rings are not cut off at rest.\n * - `prefers-reduced-motion` drops the transition.\n */\nexport const AnimatedHeight = ({ children, className }: Props) => {\n const contentRef = useRef<HTMLDivElement>(null);\n const heightRef = useRef<number>(undefined);\n const [height, setHeight] = useState<number>();\n const [isAnimating, setIsAnimating] = useState(false);\n\n useLayoutEffect(() => {\n const node = contentRef.current;\n if (!node || typeof ResizeObserver === 'undefined') return;\n\n const observer = new ResizeObserver(() => {\n const next = node.offsetHeight;\n const prev = heightRef.current;\n if (prev !== undefined && prev !== next && hasMotion()) setIsAnimating(true);\n heightRef.current = next;\n setHeight(next);\n });\n observer.observe(node);\n return () => observer.disconnect();\n }, []);\n\n const handleTransitionEnd = (event: TransitionEvent<HTMLDivElement>) => {\n if (event.target !== event.currentTarget || event.propertyName !== 'height') return;\n setIsAnimating(false);\n };\n\n return (\n <div\n style={{ height }}\n onTransitionEnd={handleTransitionEnd}\n className={cn(\n 'tw:transition-[height] tw:duration-200 tw:ease-out tw:motion-reduce:transition-none',\n isAnimating && 'tw:overflow-hidden',\n className,\n )}\n >\n <div ref={contentRef}>{children}</div>\n </div>\n );\n};\n","import type { ComponentProps, MouseEventHandler } from 'react';\nimport { Slot } from '@radix-ui/react-slot';\n\ntype Props = ComponentProps<'button'>;\n\nexport const PromptInputAction = ({ ref, onMouseDown, ...rest }: Props) => {\n const handleOnMouseDown: MouseEventHandler<HTMLButtonElement> = (event) => {\n // Prevents focus stealing by PromptInput.\n event.stopPropagation();\n onMouseDown?.(event);\n };\n\n return <Slot {...rest} ref={ref} onMouseDown={handleOnMouseDown}></Slot>;\n};\n","import {\n type ComponentRef,\n type CSSProperties,\n type KeyboardEventHandler,\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport { Truncated } from '../../components/Truncated';\nimport { cn } from '../../utils';\nimport { Command } from '../Command';\n\n/** What the menu needs above or below the composer before it will open on that side. */\nconst MENU_HEIGHT = 440;\n/** As tall as the list ever gets, however much room there is. */\nconst MENU_MAX_HEIGHT = 416;\n/** Space kept from the measured edge; `POPUP_CHROME` is the popup's own border and padding. */\nconst MENU_GUTTER = 16;\nconst POPUP_CHROME = 10;\n\n/**\n * The rows a typed filter leaves.\n *\n * - An empty filter keeps everything.\n * - A row matches on its label or its value.\n * - Matching nothing falls back to the action rows.\n */\nexport const matchesFilter = (items: PromptCommand[], filterValue: string): PromptCommand[] => {\n if (!filterValue) return items;\n const query = filterValue.toLowerCase();\n const matched = items.filter(\n (item) => item.label.toLowerCase().includes(query) || item.value.toLowerCase().includes(query),\n );\n return matched.length > 0 ? matched : items.filter((item) => item.onSelect !== undefined);\n};\n\n/**\n * The band the menu has to stay inside: the window, narrowed by every ancestor that clips.\n *\n * - The chat sidebar's panel clips well below the window's top edge.\n */\nconst CLIPS = new Set(['hidden', 'auto', 'scroll', 'clip', 'overlay']);\n\nconst clipBand = (node: Element) => {\n let top = 0;\n let bottom = window.innerHeight;\n let parent = node.parentElement;\n while (parent) {\n const { overflowY, overflowX } = window.getComputedStyle(parent);\n if (CLIPS.has(overflowY) || CLIPS.has(overflowX)) {\n const box = parent.getBoundingClientRect();\n top = Math.max(top, box.top);\n bottom = Math.min(bottom, box.bottom);\n }\n parent = parent.parentElement;\n }\n return { top, bottom };\n};\n\nexport type PromptCommand = {\n label: string;\n value: string;\n description?: string;\n group: string;\n /** A leading adornment, for a list whose rows are things rather than commands. */\n icon?: ReactNode;\n /** The row's own rendering, in place of the label; the filter still matches `label`. */\n content?: ReactNode;\n /** An action row: picking it runs this instead of inserting `value` into the message. */\n onSelect?: () => void;\n};\n\ntype Props = {\n items: PromptCommand[];\n open: boolean;\n onSelect: (item: PromptCommand) => void;\n filterValue: string;\n /** Tab picks the highlighted row, like Enter. */\n tabPicks?: boolean;\n /** A node, not a string: an empty list is where a host points at what would fill it. */\n emptyText?: ReactNode;\n /** Takes the list's place in the popup — a small form the host opened from an action row. */\n panel?: ReactNode;\n /** A control on a group's heading line, for whatever that group's rows come from. */\n groupAction?: (group: string) => ReactNode;\n /** A group's heading, rendered by the host when the group key is an id rather than a name. */\n groupHeading?: (group: string) => ReactNode;\n children: ReactNode;\n};\n\nexport const PromptInputCommands = ({\n items,\n open,\n onSelect,\n filterValue,\n tabPicks = false,\n emptyText = 'No commands found',\n panel,\n groupAction,\n groupHeading,\n children,\n}: Props) => {\n const filtered = matchesFilter(items, filterValue);\n\n // Held here: cmdk only auto-picks on its own input changing, and the textarea drives the filter.\n // - The last row moved to while it matches, else the first match, so Enter always has a pick.\n const [highlighted, setHighlighted] = useState<string>();\n // Every opening starts at the top of the list.\n const [wasOpen, setWasOpen] = useState(open);\n if (open !== wasOpen) {\n setWasOpen(open);\n if (open) setHighlighted(undefined);\n }\n\n /**\n * Which side the menu opens on.\n *\n * - Above by default; below when there is not room above and more room below.\n * - Re-measured while open: the composer and the transcript above it move.\n */\n const rootRef = useRef<ComponentRef<'div'>>(null);\n const [below, setBelow] = useState(false);\n // Capped by the measured room, not a constant: the sidebar panel has far less than a full page.\n const [maxHeight, setMaxHeight] = useState(MENU_MAX_HEIGHT);\n\n const measure = useCallback(() => {\n const node = rootRef.current;\n const box = node?.getBoundingClientRect();\n if (!node || !box) return;\n const band = clipBand(node);\n const above = box.top - band.top;\n const under = band.bottom - box.bottom;\n const openBelow = above < MENU_HEIGHT && under > above;\n setBelow(openBelow);\n setMaxHeight(\n Math.max(\n 0,\n Math.min(MENU_MAX_HEIGHT, (openBelow ? under : above) - MENU_GUTTER - POPUP_CHROME),\n ),\n );\n }, []);\n\n // First measurement in the ref callback, so the side is settled before paint.\n const attachRoot = useCallback(\n (node: ComponentRef<'div'> | null) => {\n rootRef.current = node;\n if (node) measure();\n },\n [measure],\n );\n\n useEffect(() => {\n if (!open) return;\n\n const node = rootRef.current;\n const observer = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(measure) : null;\n if (node) observer?.observe(node);\n window.addEventListener('resize', measure);\n window.addEventListener('scroll', measure, true);\n return () => {\n observer?.disconnect();\n window.removeEventListener('resize', measure);\n window.removeEventListener('scroll', measure, true);\n };\n }, [open, measure]);\n\n const highlightedValue = filtered.some((item) => item.value === highlighted)\n ? highlighted\n : filtered[0]?.value;\n\n const groups = filtered.reduce<Record<string, PromptCommand[]>>((acc, item) => {\n const group = acc[item.group] ?? [];\n group.push(item);\n acc[item.group] = group;\n return acc;\n }, {});\n\n // Tab takes the highlighted row the way Enter does; the textarea's keys bubble to this root.\n // - Only the textarea's own, unhandled, non-composing Tab: other controls keep their focus move.\n const handleKeyDown: KeyboardEventHandler<HTMLDivElement> = (event) => {\n if (!tabPicks || event.key !== 'Tab' || event.shiftKey || !open || panel) return;\n if (!(event.target instanceof HTMLTextAreaElement)) return;\n if (event.defaultPrevented || event.nativeEvent.isComposing) return;\n const picked = filtered.find((item) => item.value === highlightedValue);\n if (!picked) return;\n event.preventDefault();\n onSelect(picked);\n };\n\n // A custom property: `Command.List` takes a class for its scroll viewport, not a style.\n const menuStyle: CSSProperties & Record<string, string> = {\n '--prompt-menu-max-h': `${maxHeight}px`,\n };\n\n return (\n <Command\n ref={attachRoot}\n loop\n className=\"tw:relative\"\n shouldFilter={false}\n value={highlightedValue ?? ''}\n onValueChange={setHighlighted}\n onKeyDown={handleKeyDown}\n >\n {open && (\n <div\n className={cn(\n 'tw:absolute tw:left-0 tw:z-50 tw:w-full tw:max-w-lg',\n below ? 'tw:top-full tw:mt-1' : 'tw:bottom-full tw:mb-1',\n 'tw:rounded-[14px] tw:border tw:border-border tw:bg-popover tw:text-popover-foreground tw:shadow-lg',\n 'tw:p-1',\n )}\n style={menuStyle}\n >\n {panel ? (\n <div className=\"tw:p-3\">{panel}</div>\n ) : filtered.length === 0 ? (\n <div className=\"tw:py-3 tw:pl-4 tw:text-center tw:text-sm tw:text-muted-foreground\">\n {emptyText}\n </div>\n ) : (\n <Command.List\n className=\"tw:px-1 tw:pb-1\"\n // Radix lays viewport content out as a table sized to the longest row; block fits the popup.\n viewPortClassName=\"tw:max-h-[var(--prompt-menu-max-h)] tw:[&>div]:!block\"\n >\n {Object.entries(groups).map(([groupName, groupItems], index) => (\n <Command.Group\n key={groupName}\n // An empty group name gets no heading.\n heading={\n groupName ? (\n <span className=\"tw:flex tw:items-center tw:justify-between tw:gap-2\">\n <span className=\"tw:min-w-0 tw:truncate\">\n {groupHeading?.(groupName) ?? groupName}\n </span>\n {groupAction?.(groupName)}\n </span>\n ) : undefined\n }\n className={cn(\n 'tw:[&_[cmdk-group-heading]]:normal-case',\n 'tw:[&_[cmdk-group-heading]]:tracking-normal',\n 'tw:[&_[cmdk-group-heading]]:border-b-0',\n // `!`: `Command.Group` sets a padding on this selector that would not merge.\n 'tw:[&_[cmdk-group-heading]]:!py-0',\n 'tw:[&_[cmdk-group-heading]]:mt-2',\n 'tw:[&_[cmdk-group-heading]]:mb-1',\n 'tw:[&_[cmdk-group-heading]]:pl-2',\n 'tw:[&_[cmdk-group-heading]]:text-xs',\n index > 0 && 'tw:mt-3',\n )}\n >\n {groupItems.map((item) => (\n <Command.Item\n key={item.value}\n value={item.value}\n className=\"tw:w-full tw:min-w-0 tw:rounded-md\"\n onSelect={() => onSelect(item)}\n >\n {item.icon}\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-col\">\n {item.content ?? <span className=\"tw:truncate\">{item.label}</span>}\n {item.description && (\n <Truncated\n text={item.description}\n twoLines\n className=\"tw:text-xs tw:text-muted-foreground\"\n />\n )}\n </div>\n </Command.Item>\n ))}\n </Command.Group>\n ))}\n </Command.List>\n )}\n </div>\n )}\n\n {children}\n </Command>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { Plus } from '../../icons';\nimport { cn } from '../../utils';\n\nimport { PromptInputAction } from './PromptInputAction';\n\ntype Props = Omit<ComponentProps<typeof Button>, 'children' | 'size' | 'variant'> & {\n /** Whether the menu this opens is showing; the glyph turns into an × while it is. */\n open?: boolean;\n /** Sized up to match a large composer's send button. */\n large?: boolean;\n};\n\n/**\n * The composer's \"add to message\" button.\n *\n * - One glyph for both states: a plus rotated 45° reads as a close cross, so nothing swaps.\n * - `aria-expanded` mirrors `open`; the accessible name changes with it.\n * - Wrapped in `PromptInputAction` so a click does not hand focus to the textarea.\n */\nexport const PromptInputMenuTrigger = ({\n open = false,\n large = false,\n className,\n ref,\n ...props\n}: Props) => (\n <PromptInputAction>\n <Button\n ref={ref}\n type=\"button\"\n size={large ? 'icon' : 'icon-sm'}\n variant=\"invisible\"\n aria-expanded={open}\n aria-label={open ? 'Close menu' : 'Add to message'}\n data-testid=\"prompt-input-menu-trigger\"\n // Gray like the rest of the row: `invisible` hovers blue, and an open menu's own trigger\n // reads as pressed, not as a link.\n className={cn(\n 'tw:rounded-full',\n 'tw:hover:not-disabled:bg-muted tw:hover:not-disabled:text-foreground tw:hover:not-disabled:border-transparent',\n 'tw:aria-expanded:bg-muted',\n className,\n )}\n {...props}\n >\n {/* One extra quarter turn on the way to the ×: the glyph is symmetric every 90°, so the\n spin costs nothing and lands on the same cross. */}\n <Plus\n className={cn(\n large ? 'tw:size-5' : 'tw:size-4',\n 'tw:transition-transform tw:duration-300 tw:ease-out tw:motion-reduce:transition-none',\n open && 'tw:rotate-135',\n )}\n />\n </Button>\n </PromptInputAction>\n);\n","import type { ComponentProps, ReactNode } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { Tooltip } from '../../components/Tooltip';\nimport { CirclePause, Play, Send } from '../../icons';\nimport { cn } from '../../utils';\n\nimport { PromptInputAction } from './PromptInputAction';\n\ntype SubmitStatus = 'submitted' | 'ready' | 'streaming' | 'interrupted';\n\ntype Props = Pick<ComponentProps<typeof Button>, 'disabled' | 'ref'> & {\n status?: SubmitStatus;\n};\n\n// The accessible name per status; must match PromptInput's `handleSubmit` actions.\nconst ARIA_LABEL_BY_STATUS: Record<SubmitStatus, string> = {\n ready: 'Send message',\n streaming: 'Stop',\n interrupted: 'Continue',\n submitted: 'Sending…',\n};\n\nexport const PromptInputSubmit = ({ ref, disabled, status = 'ready' }: Props) => {\n const icon: ReactNode = (() => {\n if (status === 'streaming') return <CirclePause className=\"tw:size-4\" />;\n if (status === 'interrupted') return <Play className=\"tw:size-4\" />;\n // Optical centring: the paper plane's ink sits ~1px up and right of its box.\n return <Send className=\"tw:size-4 tw:translate-x-[-1px] tw:translate-y-[1px]\" />;\n })();\n\n const getTooltipText = () => {\n if (status === 'streaming') return 'Stop';\n if (status === 'interrupted') return 'Continue';\n return undefined;\n };\n\n return (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <PromptInputAction>\n <Button\n ref={ref}\n type=\"submit\"\n disabled={disabled}\n aria-label={ARIA_LABEL_BY_STATUS[status]}\n size=\"icon-sm\"\n // `primary` supplies foreground, focus ring and disabled state; the gradient covers its fill.\n variant=\"primary\"\n isLoading={status === 'submitted'}\n className={cn(\n 'tw:ml-auto tw:flex tw:items-center tw:rounded-full',\n 'tw:bg-gradient-to-br tw:bg-origin-border tw:from-[#61E4FF] tw:via-[#1F8FFF] tw:to-[#7C5CFF]',\n 'tw:hover:not-disabled:brightness-110',\n )}\n >\n {/* Button renders its own spinner while loading. */}\n {status !== 'submitted' && icon}\n </Button>\n </PromptInputAction>\n </Tooltip.Trigger>\n\n {getTooltipText() && (\n <Tooltip.Content placement=\"top\" variant=\"action\">\n {getTooltipText()}\n </Tooltip.Content>\n )}\n </Tooltip.Root>\n );\n};\n","import { type KeyboardEvent, useMemo, useRef } from 'react';\n\ntype Browsing = { position: number; draft: string };\n\n/** The prompts ↑ steps through: blanks dropped, a prompt sent twice in a row kept once. */\nconst toRecallStack = (history: string[]) =>\n history.reduce<string[]>((stack, prompt) => {\n if (prompt.trim() && stack.at(-1) !== prompt) stack.push(prompt);\n return stack;\n }, []);\n\nconst isPlainArrow = (event: KeyboardEvent<HTMLTextAreaElement>) =>\n (event.key === 'ArrowUp' || event.key === 'ArrowDown') &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.shiftKey &&\n !event.nativeEvent.isComposing;\n\n/** Whether the caret sits on the text's first line (↑) or last line (↓), where a textarea has nowhere to move it. */\nconst isOnEdgeLine = ({ key, currentTarget }: KeyboardEvent<HTMLTextAreaElement>) => {\n const { value, selectionStart, selectionEnd } = currentTarget;\n return key === 'ArrowUp'\n ? !value.slice(0, selectionStart).includes('\\n')\n : !value.slice(selectionEnd).includes('\\n');\n};\n\n/**\n * Shell-style recall of the prompts already sent, on ↑ and ↓.\n *\n * - ↑ starts from the caret at the very start of the text.\n * - While browsing, ↑ and ↓ step only from the first and last line; inside a multi-line prompt they move the caret.\n * - ↓ past the newest prompt gives back the draft typed before browsing began.\n * - Browsing ends on any edit, or once the value is no longer the recalled prompt.\n */\nexport const usePromptHistory = ({\n history,\n value,\n onRecall,\n}: {\n history: string[] | undefined;\n value: string;\n onRecall: (text: string) => void;\n}) => {\n const stack = useMemo(() => toRecallStack(history ?? []), [history]);\n const browsingRef = useRef<Browsing | null>(null);\n\n const stop = () => {\n browsingRef.current = null;\n };\n\n const recall = (\n event: KeyboardEvent<HTMLTextAreaElement>,\n next: Browsing | null,\n text: string,\n ) => {\n browsingRef.current = next;\n event.preventDefault();\n onRecall(text);\n return true;\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (stack.length === 0 || !isPlainArrow(event)) return false;\n const current = browsingRef.current;\n const browsing = current && stack[current.position] === value ? current : null;\n\n if (event.key === 'ArrowUp') {\n const { selectionStart, selectionEnd } = event.currentTarget;\n const canStart = selectionStart === 0 && selectionEnd === 0;\n if (browsing ? !isOnEdgeLine(event) : !canStart) return false;\n const position = (browsing?.position ?? stack.length) - 1;\n const older = stack[position];\n if (older === undefined) return false;\n return recall(event, { position, draft: browsing?.draft ?? value }, older);\n }\n\n if (!browsing || !isOnEdgeLine(event)) return false;\n const position = browsing.position + 1;\n const newer = stack[position];\n if (newer === undefined) return recall(event, null, browsing.draft);\n return recall(event, { ...browsing, position }, newer);\n };\n\n return { handleKeyDown, stop };\n};\n","import {\n type ChangeEventHandler,\n type ClipboardEventHandler,\n type ComponentProps,\n type ComponentRef,\n type FormEventHandler,\n type KeyboardEvent,\n type KeyboardEventHandler,\n type MouseEventHandler,\n type ReactNode,\n type RefObject,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\nimport TextareaAutosize from 'react-textarea-autosize';\nimport type { VariantProps } from 'class-variance-authority';\nimport { cva } from 'class-variance-authority';\n\nimport { Button } from '../../components/Button';\nimport { Tooltip, TooltipProvider } from '../../components/Tooltip';\nimport { CirclePause } from '../../icons';\nimport { cn } from '../../utils';\n\nimport { AnimatedHeight } from './AnimatedHeight';\nimport { PromptInputAction } from './PromptInputAction';\nimport type { PromptCommand } from './PromptInputCommands';\nimport { matchesFilter, PromptInputCommands } from './PromptInputCommands';\nimport { PromptInputMenuTrigger } from './PromptInputMenuTrigger';\nimport { PromptInputSubmit } from './PromptInputSubmit';\nimport { usePromptHistory } from './usePromptHistory';\n\n// The `inline` fold, below 480px of the `PROMPT_INPUT_CONTAINER` container.\n//\n// - Classes written out, never interpolated: Tailwind scans source text.\n// - Variants only set properties the base classes leave unset: the app's utilities load later and win.\n// - A host that names no container keeps the one-line row.\nconst CMDK_HIJACKED_KEYS = new Set(['ArrowUp', 'ArrowDown', 'Home', 'End', 'Enter']);\n\n/**\n * Whether the composer's always-mounted cmdk root would act on this keystroke, cancelling its default.\n *\n * - cmdk acts on every `CMDK_HIJACKED_KEYS` key regardless of modifiers, except a modified Enter.\n * - The textarea and the form stop these from bubbling, or a focused button never clicks on Enter.\n */\nconst isCmdkNavigation = (event: Pick<KeyboardEvent, 'key' | 'metaKey' | 'ctrlKey' | 'altKey'>) =>\n CMDK_HIJACKED_KEYS.has(event.key) &&\n (event.key !== 'Enter' || !(event.metaKey || event.ctrlKey || event.altKey));\n\n/**\n * The `@token` the caret sits at the end of, if any.\n *\n * - `@` has to open a word: it must start the value or follow whitespace.\n * - The token holds no whitespace or second `@` and runs past the caret, so a mid-word pick takes the word.\n * - `start` indexes the `@` itself, so replacing `[start, end)` removes the token.\n */\nexport const findMentionToken = (value: string, caret: number) => {\n const before = value.slice(0, caret);\n const match = /(?:^|\\s)@([^\\s@]*)$/.exec(before);\n if (!match) return null;\n const typed = match[1] ?? '';\n const tail = /^[^\\s@]*/.exec(value.slice(caret))?.[0] ?? '';\n return { start: caret - typed.length - 1, end: caret + tail.length, query: typed + tail };\n};\n\n/**\n * The `/token` a message leads with, while the caret is still on it.\n *\n * - Only the first token: the Agent SDK expands a skill only at the start of a message.\n * - Text may follow it.\n * - The caret past the token closes the menu.\n */\nexport const findSlashToken = (value: string, caret: number) => {\n const match = /^\\/(\\S*)/.exec(value);\n if (!match) return null;\n const end = match[0].length;\n if (caret > end) return null;\n return { end, query: match[1] ?? '' };\n};\n\nconst promptInputVariants = cva(\n [\n 'tailwindcss-preflight',\n 'tw:relative',\n\n 'tw:flex',\n 'tw:gap-2',\n 'tw:justify-center',\n\n // Kai's gradient edge: a gradient under the border box (`bg-origin-border`), with the inset\n // shadow painting the card back over the interior so only the 2px edge shows.\n 'tw:border',\n 'tw:border-2',\n 'tw:border-transparent',\n 'tw:rounded-[14px]',\n 'tw:bg-gradient-to-bl',\n 'tw:from-[#61E4FF]',\n 'tw:via-[#1F8FFF]',\n 'tw:to-[#7C5CFF]',\n 'tw:bg-origin-border',\n 'tw:shadow-[inset_0_100vw_rgb(var(--card))]',\n\n // Focus adds only a ring; the border width never changes, so nothing shifts.\n 'tw:has-[textarea:focus]:ring-4',\n 'tw:has-[textarea:focus]:ring-ring/30',\n\n 'tw:cursor-text',\n 'tw:px-2',\n ],\n {\n defaultVariants: {\n variant: 'default',\n },\n variants: {\n variant: {\n // Both are columns: attachments sit in rows above the line.\n default: ['tw:flex-col', 'tw:pt-3', 'tw:pb-2'],\n inline: ['tw:flex-col', 'tw:py-3'],\n },\n },\n },\n);\n\nconst wrapperVariants = cva(null, {\n defaultVariants: {\n variant: 'default',\n },\n variants: {\n variant: {\n default: 'tw:rounded-[14px]',\n inline: '',\n },\n },\n});\n\ntype Props = {\n /** The textarea, for a host that has to put the caret back. Not `ref`: that name is the textarea's own. */\n textareaRef?: RefObject<ComponentRef<'textarea'> | null>;\n onSend?: (value: string) => void;\n onAbort?: () => void;\n onContinue?: () => void;\n value?: string;\n onValueChange?: (value: string) => void;\n defaultValue?: string;\n prefix?: ReactNode;\n suffix?: ReactNode;\n /** Images and chips already attached, in rows of their own above the text. */\n attachments?: ReactNode;\n className?: string;\n /** On the element around the frame, for an outer pattern that themes the shell itself. */\n shellClassName?: string;\n /** Fires as focus enters or leaves the composer; the outer element also carries `data-focused`. */\n onFocusChange?: (focused: boolean) => void;\n variant?: 'default' | 'inline';\n disableSubmit?: boolean;\n /** Holds the composer read-only while the host reconnects: focus stays, Enter and send do nothing. */\n busy?: boolean;\n /** Escape with no menu open takes the caret out of the textarea. */\n blurOnEscape?: boolean;\n /** Runs after the composer's own key handling, and only for a key it left alone. */\n onKeyDown?: KeyboardEventHandler<HTMLTextAreaElement>;\n /** Files on the clipboard; a paste carrying text as well still inserts the text. */\n onPasteFiles?: (files: File[]) => void;\n /** Lets send fire with an empty text — for a host whose attachments are the message. */\n canSubmitEmpty?: boolean;\n /** A non-empty box sends while `streaming`/`submitted` instead of aborting; what that means is\n * the host's call. An empty box is unaffected, so Stop stays reachable. */\n allowSendWhileBusy?: boolean;\n /** Whether stopping is connected to anything; default `true`. `submitted` also covers an\n * approval POST, where aborting can cancel the question being answered. */\n canAbort?: boolean;\n /** `/` menu: pick one and it becomes the start of the message. */\n commands?: PromptCommand[];\n /** What the `/` list says when it has nothing to list or nothing matches — the host owns that wording. */\n commandsEmptyText?: ReactNode;\n /** The `/` commands are still on their way: an empty list says so instead of \"none\". */\n commandsLoading?: boolean;\n /** `typed` opens the `/` menu only for a `/` typed into an empty composer, never for pasted or set text. */\n slashTrigger?: 'value' | 'typed';\n /** A form in the popup's place, opened by a `commands` action row; menus stay closed, Escape calls `onClose`. */\n panel?: { content: ReactNode; onClose: () => void };\n /** A control on a `/` group's heading line — where that group's rows are managed. */\n commandsGroupAction?: (group: string) => ReactNode;\n /** `@` menu: things to attach or reference, reachable from anywhere in the text. */\n mentions?: PromptCommand[];\n /** Fires after the `@` token is replaced; the host attaches or opens whatever the item stands for. */\n onMentionSelect?: (item: PromptCommand) => void;\n /** Text a picked mention leaves at the caret, in the same update that removes its `@token`; ignored with `mentionsMultiple`. */\n mentionInsert?: (item: PromptCommand) => string;\n /** What the `@` list says when it has nothing to list — the host owns that wording. */\n mentionsEmptyText?: ReactNode;\n /** An `@` group's heading — the group key names a bucket, the host says how a bucket looks. */\n mentionsGroupHeading?: (group: string) => ReactNode;\n /** More than one `@` pick per menu: each pick leaves a bare `@`, so the list stays open. */\n mentionsMultiple?: boolean;\n /** Prompts already sent, oldest first: ↑ at the start of the text recalls them, ↓ steps back. */\n history?: string[];\n} & VariantProps<typeof promptInputVariants> &\n Pick<\n ComponentProps<typeof TextareaAutosize>,\n 'placeholder' | 'minRows' | 'maxRows' | 'disabled' | 'defaultValue' | 'autoFocus'\n > &\n ComponentProps<typeof PromptInputSubmit>;\n\nexport const PromptInput = ({\n onSend,\n onAbort,\n onContinue,\n prefix,\n variant,\n suffix,\n attachments,\n className,\n shellClassName,\n onFocusChange,\n disabled,\n disableSubmit,\n busy = false,\n blurOnEscape = false,\n onKeyDown,\n onPasteFiles,\n canSubmitEmpty = false,\n allowSendWhileBusy = false,\n canAbort = true,\n value = '',\n onValueChange,\n status = 'ready',\n maxRows = 6,\n minRows,\n commands,\n commandsEmptyText = 'No commands found',\n commandsLoading = false,\n slashTrigger = 'value',\n commandsGroupAction,\n panel,\n mentions,\n onMentionSelect,\n mentionInsert,\n mentionsEmptyText = 'Nothing to attach',\n mentionsGroupHeading,\n mentionsMultiple = false,\n history,\n autoFocus,\n textareaRef: publishedRef,\n ...textareaProps\n}: Props) => {\n const defaultMinRows = variant === 'inline' ? 1 : 2;\n\n // A send the busy statuses would otherwise refuse.\n //\n // - Only with text in the box: an empty box keeps `streaming`'s abort, so Stop stays reachable.\n // - `disableSubmit` still wins — a host that says \"not now\" (an open modal, a limit) means it in\n // every status.\n const canSendWhileBusy =\n allowSendWhileBusy &&\n (status === 'streaming' || status === 'submitted') &&\n !busy &&\n !disabled &&\n !disableSubmit &&\n value.trim() !== '';\n\n // When Stop needs a control of its own, the submit button not being one.\n //\n // - A busy send is available, so the submit button says Send.\n // - `submitted` draws a spinner there, which is what a long job looks like.\n const showSeparateStop =\n allowSendWhileBusy && canAbort && (canSendWhileBusy || status === 'submitted');\n\n const isDisabled =\n busy ||\n (!canSendWhileBusy &&\n (disabled || disableSubmit || (!canSubmitEmpty && !value.trim())) &&\n status !== 'streaming' &&\n status !== 'interrupted');\n\n const [isFocused, setIsFocused] = useState(false);\n const changeFocus = (next: boolean) => {\n if (next === isFocused) return;\n setIsFocused(next);\n onFocusChange?.(next);\n };\n\n const textareaId = useId();\n const textareaRef = useRef<ComponentRef<'textarea'>>(null);\n\n // From the ref callback, not an effect: a host restructure recreates the element while this stays mounted.\n const setTextareaNode = useCallback(\n (node: ComponentRef<'textarea'> | null) => {\n textareaRef.current = node;\n if (publishedRef) publishedRef.current = node;\n },\n [publishedRef],\n );\n const [dismissedValue, setDismissedValue] = useState<string | null>(null);\n // The caret, for the `@` menu, with the value it belongs to.\n // - A value the host set moves the caret to its end, not a stale offset.\n const [caret, setCaret] = useState(0);\n const [caretValue, setCaretValue] = useState(value);\n const moveCaret = (next: number, forValue: string) => {\n setCaret(next);\n setCaretValue(forValue);\n };\n if (value !== caretValue) moveCaret(value.length, value);\n\n // `autoFocus` is applied imperatively with `preventScroll`, mount-only.\n // - The DOM attribute scrolls ancestors; in a panel still sliding in, that drags the page sideways.\n const autoFocusRef = useRef(autoFocus);\n useEffect(() => {\n if (autoFocusRef.current) textareaRef.current?.focus({ preventScroll: true });\n }, []);\n\n // The value a typing session last produced; a `/` typed into an empty composer starts one.\n // - Text the host sets, a paste or a composition ends it, because the value no longer matches.\n const [typedSlashValue, setTypedSlashValue] = useState<string | null>(null);\n\n // Esc dismisses the menu for the current value; a changed value clears the dismissal.\n if (dismissedValue !== null && value !== dismissedValue) setDismissedValue(null);\n\n const hasCommands = commands !== undefined;\n const panelOpen = panel !== undefined;\n // Wired, not filled: an `@` in a project with nothing to attach still opens, and says so.\n const hasMentions = mentions !== undefined;\n const hasMenus = hasCommands || hasMentions;\n const slashToken =\n hasCommands &&\n !panelOpen &&\n value !== dismissedValue &&\n (slashTrigger === 'value' || typedSlashValue === value)\n ? findSlashToken(value, Math.min(caret, value.length))\n : null;\n const commandsOpen = slashToken !== null;\n const mentionToken =\n hasMentions && !commandsOpen && !panelOpen && value !== dismissedValue\n ? findMentionToken(value, Math.min(caret, value.length))\n : null;\n const mentionsOpen = mentionToken !== null;\n const menuOpen = commandsOpen || mentionsOpen || panelOpen;\n const menuItems = commandsOpen ? (commands ?? []) : (mentions ?? []);\n const menuFilter = commandsOpen ? slashToken.query : (mentionToken?.query ?? '');\n\n // A recalled prompt opens no menu: ↑ and ↓ keep stepping through history.\n const promptHistory = usePromptHistory({\n history,\n value,\n onRecall: (text) => {\n onValueChange?.(text);\n moveCaret(text.length, text);\n setDismissedValue(text);\n requestAnimationFrame(() => {\n textareaRef.current?.setSelectionRange(text.length, text.length);\n });\n },\n });\n\n const handleSubmit = () => {\n if (isDisabled) return;\n if (canSendWhileBusy) {\n onSend?.(value);\n return;\n }\n if (status === 'streaming') onAbort?.();\n if (status === 'interrupted') onContinue?.();\n if (status === 'ready') onSend?.(value);\n };\n\n const handleOnSubmit: FormEventHandler<HTMLFormElement> = (event) => {\n event.preventDefault();\n handleSubmit();\n };\n\n const handleOnChange: ChangeEventHandler<HTMLTextAreaElement> = (event) => {\n promptHistory.stop();\n const inputType = event.nativeEvent instanceof InputEvent ? event.nativeEvent.inputType : '';\n const isTyping = inputType === 'insertText' || inputType.startsWith('delete');\n const startsSession = inputType === 'insertText' && value === '' && event.target.value === '/';\n const continuesSession = isTyping && typedSlashValue === value;\n setTypedSlashValue(startsSession || continuesSession ? event.target.value : null);\n moveCaret(event.target.selectionStart ?? event.target.value.length, event.target.value);\n onValueChange?.(event.target.value);\n };\n\n // Clicks and arrow keys move the caret without changing the value; `select` fires for both.\n const handleOnSelect: FormEventHandler<HTMLTextAreaElement> = (event) => {\n moveCaret(event.currentTarget.selectionStart ?? 0, event.currentTarget.value);\n };\n\n const handleMenuSelect = (item: PromptCommand) => {\n if (item.onSelect) {\n // An action is not a message: the token that reached it goes.\n const start = mentionToken?.start ?? 0;\n const end = mentionToken?.end ?? slashToken?.end;\n if (end !== undefined) {\n const next = value.slice(0, start) + value.slice(end);\n onValueChange?.(next);\n moveCaret(start, next);\n }\n item.onSelect();\n textareaRef.current?.focus();\n return;\n }\n if (mentionToken) {\n // The token goes; without `mentionInsert` the item attaches through `onMentionSelect`, never as text.\n const keep = mentionsMultiple ? '@' : (mentionInsert?.(item) ?? '');\n const next = value.slice(0, mentionToken.start) + keep + value.slice(mentionToken.end);\n const nextCaret = mentionToken.start + keep.length;\n onValueChange?.(next);\n moveCaret(nextCaret, next);\n // The value lands on the next render; the caret has to be placed after it.\n requestAnimationFrame(() => {\n textareaRef.current?.setSelectionRange(nextCaret, nextCaret);\n });\n onMentionSelect?.(item);\n } else {\n const rest = slashToken ? value.slice(slashToken.end).replace(/^\\s+/, '') : '';\n const head = `${item.value} `;\n onValueChange?.(head + rest);\n moveCaret(head.length, head + rest);\n requestAnimationFrame(() => {\n textareaRef.current?.setSelectionRange(head.length, head.length);\n });\n }\n textareaRef.current?.focus();\n };\n\n // A message that is only its token, or a bare `@` left by a multiple pick, goes on dismiss.\n const dismissMenu = () => {\n if (value.trim() === '/' || value.trim() === '@') {\n onValueChange?.('');\n return;\n }\n if (mentionToken && mentionToken.query === '') {\n const next = (value.slice(0, mentionToken.start) + value.slice(mentionToken.end)).replace(\n /\\s+$/,\n '',\n );\n onValueChange?.(next);\n moveCaret(next.length, next);\n return;\n }\n setDismissedValue(value);\n };\n\n const handleOnPaste: ClipboardEventHandler<HTMLTextAreaElement> = (event) => {\n if (!onPasteFiles) return;\n const files = Array.from(event.clipboardData.files);\n if (files.length === 0) return;\n onPasteFiles(files);\n if (!event.clipboardData.getData('text/plain')) event.preventDefault();\n };\n\n const handleOnComposerKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (event) => {\n if (menuOpen) {\n if (event.key === 'Escape') {\n event.preventDefault();\n if (panel) panel.onClose();\n else dismissMenu();\n return;\n }\n // A panel has its own controls; the textarea's keys are its own again.\n if (panelOpen) return;\n // Let cmdk handle these via bubbling; Enter with nothing to pick falls through to send.\n if (event.key === 'ArrowUp' || event.key === 'ArrowDown') return;\n if (event.key === 'Enter' && matchesFilter(menuItems, menuFilter).length > 0) return;\n } else if (hasMenus && isCmdkNavigation(event)) {\n // The always-mounted cmdk root would preventDefault these and break multiline editing.\n // - Keys cmdk ignores (Cmd+Enter) still reach document-level hotkeys.\n event.stopPropagation();\n }\n\n if (promptHistory.handleKeyDown(event)) return;\n\n if (event.key === 'Enter' && !event.shiftKey && !event.ctrlKey && !event.metaKey) {\n event.preventDefault();\n // Enter never aborts — it either sends or, while busy, does nothing at all.\n if (status !== 'streaming' || canSendWhileBusy) handleSubmit();\n }\n };\n\n const handleOnKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (event) => {\n handleOnComposerKeyDown(event);\n if (event.defaultPrevented) return;\n if (blurOnEscape && event.key === 'Escape') event.currentTarget.blur();\n onKeyDown?.(event);\n };\n\n // Keys from a control other than the textarea stop here, before the cmdk root cancels them.\n // - Otherwise a focused button in a slot never clicks on Enter.\n // - Portalled layers of those controls bubble here too, through React.\n const handleOnFormKeyDown: KeyboardEventHandler<HTMLFormElement> = (event) => {\n if (hasMenus && event.target !== textareaRef.current && isCmdkNavigation(event)) {\n event.stopPropagation();\n }\n };\n\n const handleOnMouseDown: MouseEventHandler<HTMLFormElement> = (event) => {\n const { currentTarget, target } = event;\n if (target === textareaRef.current) return;\n // A portalled layer's mousedown reaches here through React; it keeps its own focus.\n if (!(target instanceof Node && currentTarget.contains(target))) return;\n\n event.preventDefault();\n textareaRef.current?.focus();\n };\n\n const formEl = (\n <div\n className={cn(wrapperVariants({ variant }), shellClassName)}\n data-focused={isFocused ? '' : undefined}\n >\n {/*This is alright, just refocused into a textarea. */}\n {/* oxlint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */}\n <form\n data-testid=\"prompt-input\"\n data-status={status}\n onKeyDown={handleOnFormKeyDown}\n onFocus={() => changeFocus(true)}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget)) changeFocus(false);\n }}\n onMouseDown={handleOnMouseDown}\n onSubmit={handleOnSubmit}\n className={cn(\n promptInputVariants({ variant }),\n disabled &&\n 'tw:bg-none tw:border-border tw:shadow-[inset_0_100vw_rgb(var(--muted))] tw:cursor-default',\n className,\n )}\n >\n {/* Always mounted so it can animate; `-mb-2` cancels the form gap so an empty box adds no space. */}\n <AnimatedHeight className=\"tw:-mb-2\">\n {attachments && <div className=\"tw:flex tw:flex-col tw:gap-2 tw:pb-4\">{attachments}</div>}\n </AnimatedHeight>\n\n <label htmlFor={textareaId} className=\"tw:sr-only\">\n Prompt Input\n </label>\n <div\n className={cn(\n 'tw:flex tw:min-w-0 tw:gap-2',\n variant === 'inline'\n ? 'tw:flex-row tw:items-center tw:@max-[480px]/composer:flex-wrap'\n : 'tw:flex-col',\n )}\n >\n {prefix && <div className=\"tw:flex tw:shrink-0 tw:items-center\">{prefix}</div>}\n <div\n className={cn(\n 'tw:flex tw:min-w-0 tw:items-center',\n // `grow`, not `flex-1`, so the folded basis has no base class to beat.\n variant === 'inline'\n ? 'tw:grow tw:@max-[480px]/composer:order-first tw:@max-[480px]/composer:basis-full'\n : 'tw:flex-1',\n )}\n >\n <TextareaAutosize\n {...textareaProps}\n disabled={disabled}\n minRows={minRows ?? defaultMinRows}\n maxRows={maxRows}\n id={textareaId}\n ref={setTextareaNode}\n value={value}\n onChange={handleOnChange}\n onSelect={handleOnSelect}\n onKeyDown={handleOnKeyDown}\n onPaste={handleOnPaste}\n readOnly={busy}\n aria-busy={busy || undefined}\n className={cn(\n 'tw:resize-none',\n 'tw:outline-hidden',\n 'tw:min-w-32 tw:flex-1',\n // Indent aligns the text with the menu button's glyph.\n // - No `px-0` inline: the app re-emits base classes later, which would beat the fold.\n variant === 'inline' ? 'tw:@max-[480px]/composer:pl-2' : 'tw:pl-2 tw:pr-0',\n 'tw:bg-transparent',\n\n disabled || busy ? 'tw:text-muted-foreground' : 'tw:text-foreground',\n 'tw:text-sm',\n 'tw:font-sans',\n\n 'tw:transition-[width]',\n 'tw:delay-75',\n 'tw:ease-linear',\n 'tw:overflow-auto',\n )}\n />\n </div>\n\n <div\n className={cn(\n 'tw:flex tw:items-center tw:gap-1',\n // Optical spacing: the filled send button reads closer than the outline ones.\n 'tw:[&>*:last-child]:ml-1',\n 'tw:shrink-0',\n // Inline, send needs extra room from the field's rounded corner.\n variant === 'inline' &&\n 'tw:pr-2.5 tw:@max-[480px]/composer:grow tw:@max-[480px]/composer:pr-0',\n )}\n >\n {suffix}\n {/* Stop is the turn's only brake, so it gets a control of its own the moment the\n submit button stops being one — otherwise cancelling would mean emptying the box\n first, and the one button's meaning would flip on every keystroke. Both busy\n statuses, not just `streaming`: a host that maps a running job to `submitted`\n (kbc-ui does) would otherwise leave a long wait with no way out — with or without\n a draft in the box. */}\n {showSeparateStop && (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <PromptInputAction>\n <Button\n type=\"button\"\n onClick={() => onAbort?.()}\n aria-label=\"Stop\"\n size=\"icon-sm\"\n variant=\"outline\"\n className=\"tw:flex tw:items-center tw:rounded-full\"\n >\n <CirclePause className=\"tw:size-4\" />\n </Button>\n </PromptInputAction>\n </Tooltip.Trigger>\n <Tooltip.Content placement=\"top\" variant=\"action\">\n Stop\n </Tooltip.Content>\n </Tooltip.Root>\n )}\n {/* The button says what pressing it does, so a busy send shows Send, not Stop. */}\n <PromptInputSubmit disabled={isDisabled} status={canSendWhileBusy ? 'ready' : status} />\n </div>\n </div>\n </form>\n </div>\n );\n\n return (\n <TooltipProvider>\n {hasMenus ? (\n <PromptInputCommands\n items={menuItems}\n open={menuOpen}\n onSelect={handleMenuSelect}\n filterValue={menuFilter}\n tabPicks={commandsOpen}\n emptyText={\n mentionsOpen\n ? mentionsEmptyText\n : commandsLoading\n ? 'Loading commands…'\n : commandsEmptyText\n }\n panel={panel?.content}\n groupAction={commandsOpen ? commandsGroupAction : undefined}\n groupHeading={mentionsOpen ? mentionsGroupHeading : undefined}\n >\n {formEl}\n </PromptInputCommands>\n ) : (\n formEl\n )}\n </TooltipProvider>\n );\n};\n\nPromptInput.Action = PromptInputAction;\nPromptInput.MenuTrigger = PromptInputMenuTrigger;\n","import { type KeyboardEvent, type ReactNode, useEffect, useRef, useState } from 'react';\n\nimport { Badge } from '../../components/Badge';\nimport { Button } from '../../components/Button';\nimport { Kbd, keys } from '../../components/Kbd';\nimport { Progress } from '../../components/Progress';\nimport { Tooltip } from '../../components/Tooltip';\nimport {\n digitFromKeyCode,\n MAX_DIGIT_HOTKEY,\n useAltDigitHotkey,\n} from '../../hooks/useAltDigitHotkey';\nimport { ArrowDown, ArrowUp, Check, ChevronLeft, ChevronRight, X } from '../../icons';\nimport { cn } from '../../utils';\nimport { TextInput } from '../TextInput';\n\ntype QuestionOption = {\n id: string;\n label: string;\n description?: string;\n preview?: string;\n /** A short tag after the label, e.g. `Recommended`. */\n badge?: string;\n};\n\ntype Props = {\n question: string;\n header?: string;\n options: readonly QuestionOption[];\n multiSelect?: boolean;\n selectedOptionIds?: readonly string[];\n onSelectionChange?: (selectedIds: readonly string[]) => void;\n customAnswer?: string;\n onCustomAnswerChange?: (value: string) => void;\n onCustomAnswerConfirm?: () => void;\n showCustomAnswer?: boolean;\n customAnswerPlaceholder?: string;\n customAnswerMaxLength?: number;\n showSkip?: boolean;\n onSkip?: () => void;\n /** Replaces the Skip button's `Space` hint; `null` drops the tooltip. */\n skipTooltip?: ReactNode;\n onClose?: () => void;\n onNext?: () => void;\n submitTooltip?: ReactNode;\n /** Keeps the answer from being sent, by click or by ⌘/Ctrl+Enter. */\n isSubmitDisabled?: boolean;\n /** The answer is on its way: Submit spins and every action is disabled. */\n isSubmitting?: boolean;\n /** Why the last send failed, shown above the footer. */\n error?: ReactNode;\n onPrevious?: () => void;\n currentStep?: number;\n totalSteps?: number;\n renderPreview?: (content: string) => ReactNode;\n /** Focuses the card on mount, unless the focused field already holds text. */\n autoFocus?: boolean;\n /** ⌥1–⌥9 picks an option from anywhere on the page, text fields included. */\n enableShortcuts?: boolean;\n className?: string;\n};\n\nconst isEditableTarget = (target: EventTarget | null) =>\n target instanceof HTMLElement &&\n (target.isContentEditable || ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName));\n\nconst isFieldWithText = (element: Element | null) => {\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n return element.value !== '';\n }\n return element instanceof HTMLElement && element.isContentEditable && !!element.textContent;\n};\n\nconst hasCommandModifier = (e: KeyboardEvent) => e.altKey || e.ctrlKey || e.metaKey;\n\nconst SEND_KEY_CLASS = 'tw:!bg-white/20 tw:!text-primary-foreground';\n\nconst DEFAULT_SKIP_TOOLTIP = (\n <Kbd variant=\"primary\" casing=\"as-written\">\n Space\n </Kbd>\n);\n\nconst keyRange = (count: number) => (count > 1 ? `1–${count}` : '1');\n\n/** An option's key, or a blank slot past the ninth; a picked option's turns into a check. */\nconst OptionKey = ({ digit, checked }: { digit: number | null; checked: boolean }) =>\n digit === null && !checked ? (\n <span aria-hidden className=\"tw:w-5 tw:shrink-0\" />\n ) : (\n <Kbd\n aria-hidden\n className={cn('tw:-my-0.5', checked && 'tw:!bg-primary tw:!text-primary-foreground')}\n data-testid=\"question-option-digit\"\n >\n {checked ? (\n <Check className=\"tw:size-3 tw:animate-in tw:fade-in tw:zoom-in-50 tw:duration-150\" />\n ) : (\n digit\n )}\n </Kbd>\n );\n\nconst handleKeyDown = (callback: () => void) => (e: KeyboardEvent) => {\n if (hasCommandModifier(e) || e.repeat) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n callback();\n }\n};\n\nexport const Question = ({\n question,\n header,\n options,\n multiSelect = true,\n selectedOptionIds = [],\n onSelectionChange,\n customAnswer = '',\n onCustomAnswerChange,\n onCustomAnswerConfirm,\n showCustomAnswer = true,\n customAnswerPlaceholder = 'Type your answer…',\n customAnswerMaxLength,\n showSkip = true,\n onSkip,\n skipTooltip = DEFAULT_SKIP_TOOLTIP,\n onClose,\n onNext,\n submitTooltip,\n isSubmitDisabled = false,\n isSubmitting = false,\n error,\n onPrevious,\n currentStep,\n totalSteps,\n renderPreview,\n autoFocus = false,\n enableShortcuts = false,\n className,\n}: Props) => {\n const [isCustomExpanded, setIsCustomExpanded] = useState(false);\n const [activeRow, setActiveRow] = useState(0);\n const [pendingId, setPendingId] = useState<string | null>(null);\n const rootRef = useRef<HTMLDivElement>(null);\n const rowsRef = useRef<(HTMLDivElement | null)[]>([]);\n const customInputRef = useRef<HTMLInputElement>(null);\n const isCustomSelected = isCustomExpanded || customAnswer.length > 0;\n const hasSteps = currentStep != null && totalSteps != null;\n // A one-question card has nothing to step through: \"1 of 1\" over a full bar, with both\n // chevrons dead, describes a journey that does not exist. `hasSteps` still stands — it is what\n // makes this the last step, and so what makes the action read Submit rather than Next.\n const showStepControls = hasSteps && totalSteps > 1;\n const showSkipButton = showSkip && onSkip != null;\n // Single-select: the option a key picked, else the one already chosen.\n const chosenId = multiSelect ? null : (pendingId ?? selectedOptionIds[0] ?? null);\n const showSubmitButton = multiSelect || isCustomSelected || chosenId !== null;\n // Every slot in the footer is conditional, so the row itself has to be: a bordered strip with\n // nothing in it reads as a control that failed to render.\n const showFooter = showStepControls || showSkipButton || showSubmitButton;\n const canSend = !isSubmitDisabled && !isSubmitting;\n const progressValue = hasSteps ? (currentStep / totalSteps) * 100 : 0;\n const isFirstStep = currentStep === 1;\n const isLastStep = hasSteps && currentStep === totalSteps;\n const numberedCount = Math.min(options.length, MAX_DIGIT_HOTKEY);\n const otherDigit =\n showCustomAnswer && options.length < MAX_DIGIT_HOTKEY ? options.length + 1 : null;\n const rowCount = options.length + (showCustomAnswer ? 1 : 0);\n const tabbableRow = activeRow < rowCount ? activeRow : 0;\n\n const handleOptionToggle = (optionId: string) => {\n if (multiSelect) {\n const isSelected = selectedOptionIds.includes(optionId);\n const nextIds = isSelected\n ? selectedOptionIds.filter((id) => id !== optionId)\n : [...selectedOptionIds, optionId];\n onSelectionChange?.(nextIds);\n } else {\n // Single-select: picking a real option deselects \"Other\" and drops any\n // typed custom answer so it can't leak into the submitted answer.\n setIsCustomExpanded(false);\n setPendingId(null);\n onCustomAnswerChange?.('');\n onSelectionChange?.([optionId]);\n }\n };\n\n // A key press picks without sending: multi-select toggles, single-select waits for ⌘/Ctrl+Enter.\n const handleOptionKey = (optionId: string) => {\n if (multiSelect) {\n handleOptionToggle(optionId);\n } else {\n setIsCustomExpanded(false);\n onCustomAnswerChange?.('');\n setPendingId(optionId);\n }\n };\n\n useAltDigitHotkey({\n count: numberedCount,\n onDigit: (index) => handleOptionKey(options[index]!.id),\n enabled: enableShortcuts,\n ref: rootRef,\n });\n\n useEffect(() => {\n if (!autoFocus || isFieldWithText(document.activeElement)) return;\n rootRef.current?.focus({ preventScroll: true });\n }, [autoFocus]);\n\n const focusRow = (index: number) => {\n setActiveRow(index);\n rowsRef.current[index]?.focus();\n };\n\n /**\n * The card's own keys, never fired from a text field inside it; a held key acts once.\n *\n * 1. ↑ / ↓ move focus; a digit picks or toggles; Enter on a row selects or toggles it.\n * 2. ⌘/Ctrl+Enter sends: the selected option (single-select) or the next step; Space skips.\n * 3. Any other character starts a custom answer: focus moves to \"Other\", which receives it.\n * 4. A key the card takes stops here, so page shortcuts (`a`, `/`) never see it.\n */\n const handleCardKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey) && !e.altKey && !e.repeat) {\n if (!showSubmitButton || !canSend) return;\n send();\n // Stops here, so the page's own ⌘/Ctrl+Enter does not send a second time.\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n if (e.key === 'ArrowUp' && e.target === customInputRef.current && !hasCommandModifier(e)) {\n e.preventDefault();\n focusRow(options.length);\n return;\n }\n\n if (e.defaultPrevented || hasCommandModifier(e) || isEditableTarget(e.target)) return;\n\n if ((e.key === 'ArrowDown' || e.key === 'ArrowUp') && rowCount > 0) {\n e.preventDefault();\n const delta = e.key === 'ArrowDown' ? 1 : -1;\n const target = e.target;\n const current = rowsRef.current.findIndex(\n (row) => target instanceof Node && !!row?.contains(target),\n );\n const from = current === -1 ? (delta > 0 ? -1 : rowCount) : current;\n focusRow((from + delta + rowCount) % rowCount);\n return;\n }\n\n if (e.repeat) return;\n\n const digit = digitFromKeyCode(e.code);\n if (digit !== null && digit === otherDigit) {\n e.preventDefault();\n e.stopPropagation();\n customInputRef.current?.focus();\n return;\n }\n\n if (digit !== null && digit <= numberedCount) {\n e.preventDefault();\n e.stopPropagation();\n handleOptionKey(options[digit - 1]!.id);\n return;\n }\n\n if (e.key === ' ' && e.target === e.currentTarget) {\n e.preventDefault();\n e.stopPropagation();\n if (showSkipButton && !isSubmitting) onSkip?.();\n return;\n }\n\n if (showCustomAnswer && digit === null && e.key.length === 1 && e.key !== ' ') {\n e.stopPropagation();\n customInputRef.current?.focus();\n return;\n }\n };\n\n // The single-select option chosen with Enter is sent here; otherwise the step goes on.\n const send = () => {\n if (!multiSelect && !isCustomSelected && chosenId) handleOptionToggle(chosenId);\n else onNext?.();\n };\n\n // The › chevron: a key-picked option not yet sent goes out instead of being dropped.\n const handleNextStep = () => {\n if (!multiSelect && pendingId) handleOptionToggle(pendingId);\n else onNext?.();\n };\n\n const handleCustomToggle = (checked: boolean) => {\n setIsCustomExpanded(checked);\n if (checked) {\n // Single-select: \"Other\" and a real option are mutually exclusive.\n if (!multiSelect) {\n onSelectionChange?.([]);\n }\n } else {\n onCustomAnswerChange?.('');\n }\n };\n\n // Typing into (or focusing) the custom input selects \"Other\" directly — no\n // need to click the row/checkbox first.\n const handleCustomFocus = () => {\n setIsCustomExpanded(true);\n setPendingId(null);\n if (!multiSelect) {\n onSelectionChange?.([]);\n }\n };\n\n const handleCustomRowClick = () => {\n // Multi-select: the row toggles the checkbox. Single-select: clicking only\n // selects (never deselects, so a second click can't wipe typed text) —\n // switch away by picking a real option instead.\n if (multiSelect) {\n handleCustomToggle(!isCustomSelected);\n } else {\n handleCustomFocus();\n }\n };\n\n // From the keyboard, opening \"Other\" also moves focus into its text box.\n const handleCustomRowKey = () => {\n const opens = !multiSelect || !isCustomSelected;\n handleCustomRowClick();\n if (opens) customInputRef.current?.focus();\n };\n\n const submitButton = (\n <Button\n variant=\"primary\"\n size=\"small\"\n onClick={send}\n disabled={!canSend}\n isLoading={isSubmitting}\n data-testid=\"question-next-button\"\n >\n {isLastStep ? 'Submit' : 'Next'}\n <Kbd aria-hidden casing=\"as-written\" className={SEND_KEY_CLASS}>\n {`${keys.mod.symbol} Enter`}\n </Kbd>\n </Button>\n );\n\n const skipButton = (\n <Button\n variant=\"outline\"\n size=\"small\"\n onClick={onSkip}\n disabled={isSubmitting}\n aria-keyshortcuts=\"Space\"\n data-testid=\"question-skip-button\"\n >\n Skip\n </Button>\n );\n\n return (\n <div\n ref={rootRef}\n role=\"group\"\n aria-label={question}\n tabIndex={-1}\n onKeyDown={handleCardKeyDown}\n className={cn(\n 'tw:flex tw:max-w-[800px] tw:flex-col tw:gap-4 tw:overflow-hidden tw:rounded-xl tw:border tw:border-solid tw:border-border tw:bg-card tw:text-card-foreground tw:shadow-lg tw:outline-none',\n className,\n )}\n data-testid=\"question-root\"\n data-question-step={currentStep}\n data-question-total-steps={totalSteps}\n data-question-multi-select={multiSelect}\n >\n <div className=\"tw:flex tw:items-start tw:gap-2 tw:pl-4 tw:pr-2 tw:pt-4\">\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-col tw:gap-1\">\n <p className=\"tw:m-0 tw:text-base tw:font-semibold tw:leading-6\">{question}</p>\n {header && (\n <p className=\"tw:m-0 tw:text-xs tw:leading-4 tw:text-muted-foreground\">{header}</p>\n )}\n </div>\n {onClose && (\n <Button\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label=\"Close\"\n onClick={onClose}\n data-testid=\"question-close-button\"\n >\n <X className=\"tw:size-4\" />\n </Button>\n )}\n </div>\n\n <div className=\"tw:px-4\">\n <div className=\"tw:flex tw:flex-col tw:gap-4 tw:border-0 tw:border-l tw:border-solid tw:border-primary tw:px-4 tw:py-2\">\n {options.map((option, index) => {\n const digit = index < numberedCount ? index + 1 : null;\n const isSelected = selectedOptionIds.includes(option.id);\n return (\n <div\n key={option.id}\n ref={(row) => {\n rowsRef.current[index] = row;\n }}\n className=\"tw:-mx-2 tw:-my-1.5 tw:flex tw:cursor-pointer tw:items-start tw:gap-2 tw:rounded-md tw:px-2 tw:py-1.5 tw:outline-none tw:hover:bg-hover tw:focus-visible:ring-2 tw:focus-visible:ring-ring\"\n onClick={() => handleOptionToggle(option.id)}\n onKeyDown={(e) => {\n if (hasCommandModifier(e) || e.repeat) return;\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n handleOptionKey(option.id);\n }\n }}\n onFocus={() => setActiveRow(index)}\n role=\"button\"\n aria-pressed={multiSelect ? isSelected : chosenId === option.id}\n tabIndex={index === tabbableRow ? 0 : -1}\n aria-keyshortcuts={\n digit === null\n ? undefined\n : [String(digit), enableShortcuts && `Alt+${digit}`].filter(Boolean).join(' ')\n }\n data-question-option\n data-testid={`question-option-${option.id}`}\n >\n <OptionKey\n digit={digit}\n checked={multiSelect ? isSelected : chosenId === option.id}\n />\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:items-start tw:gap-3\">\n <div className=\"tw:flex tw:flex-col tw:gap-1.5\">\n {option.badge ? (\n <span className=\"tw:flex tw:flex-wrap tw:items-center tw:gap-x-2 tw:gap-y-1 tw:text-sm tw:font-medium tw:leading-none\">\n {option.label}\n <Badge\n variant=\"pill\"\n color=\"green-inverse\"\n data-testid=\"question-option-badge\"\n >\n {option.badge}\n </Badge>\n </span>\n ) : (\n <span className=\"tw:text-sm tw:font-medium tw:leading-none\">\n {option.label}\n </span>\n )}\n {option.description && (\n <span className=\"tw:text-sm tw:font-normal tw:leading-5 tw:text-muted-foreground\">\n {option.description}\n </span>\n )}\n </div>\n {option.preview && (\n <div\n data-testid=\"question-option-preview\"\n className={cn(\n 'tw:ml-auto tw:flex tw:max-h-40 tw:min-w-0 tw:max-w-[50%] tw:flex-col tw:overflow-hidden tw:rounded-md',\n !renderPreview &&\n 'tw:overflow-auto tw:border tw:border-solid tw:border-border tw:bg-muted tw:p-2 tw:text-foreground',\n )}\n >\n {renderPreview ? (\n renderPreview(option.preview)\n ) : (\n // `text-foreground` restates the ink the box above already\n // sets, and is not redundant: consuming apps ship a global\n // `pre { color; background-color; border }` rule that beats\n // inheritance but loses to a utility — the same reason\n // `border-0` and `bg-transparent` are spelled out here.\n <pre className=\"tw:m-0 tw:overflow-visible tw:border-0 tw:bg-transparent tw:p-0 tw:font-mono tw:text-xs tw:leading-5 tw:text-foreground\">\n {option.preview}\n </pre>\n )}\n </div>\n )}\n </div>\n </div>\n );\n })}\n\n {showCustomAnswer && (\n <div className=\"tw:flex tw:flex-col tw:gap-2\">\n <div\n ref={(row) => {\n rowsRef.current[options.length] = row;\n }}\n className=\"tw:-mx-2 tw:-my-1.5 tw:flex tw:cursor-pointer tw:items-start tw:gap-2 tw:rounded-md tw:px-2 tw:py-1.5 tw:outline-none tw:hover:bg-hover tw:focus-visible:ring-2 tw:focus-visible:ring-ring\"\n onClick={handleCustomRowClick}\n onKeyDown={handleKeyDown(handleCustomRowKey)}\n onFocus={() => setActiveRow(options.length)}\n role=\"button\"\n aria-pressed={isCustomSelected}\n aria-keyshortcuts={otherDigit === null ? undefined : String(otherDigit)}\n tabIndex={options.length === tabbableRow ? 0 : -1}\n >\n <OptionKey digit={otherDigit} checked={isCustomSelected} />\n <span\n className={cn(\n 'tw:flex-1 tw:text-sm tw:font-medium tw:leading-none',\n !multiSelect && isCustomSelected && 'tw:text-primary',\n )}\n >\n Other\n </span>\n </div>\n {/* Always rendered and editable: typing or focusing selects \"Other\"\n directly, and keeping it mounted avoids layout shift. */}\n <TextInput\n ref={customInputRef}\n value={customAnswer}\n onValueChange={(value) => onCustomAnswerChange?.(value)}\n onFocus={handleCustomFocus}\n onKeyDown={\n onCustomAnswerConfirm\n ? (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter' && !e.shiftKey && !(e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n onCustomAnswerConfirm();\n }\n }\n : undefined\n }\n placeholder={customAnswerPlaceholder}\n maxLength={customAnswerMaxLength}\n testId=\"question-custom\"\n />\n </div>\n )}\n </div>\n </div>\n\n {numberedCount > 0 && (\n <div\n aria-hidden\n className=\"tw:-mt-1 tw:flex tw:flex-wrap tw:items-center tw:gap-x-3 tw:gap-y-1 tw:px-4 tw:text-xs tw:text-muted-foreground\"\n data-testid=\"question-keyboard-hint\"\n >\n <span className=\"tw:inline-flex tw:items-center tw:gap-1\">\n <Kbd casing=\"as-written\">{keyRange(numberedCount + (otherDigit === null ? 0 : 1))}</Kbd>\n {multiSelect ? 'toggle' : 'choose'}\n </span>\n {rowCount > 1 && (\n <span className=\"tw:inline-flex tw:items-center tw:gap-1\">\n <Kbd>\n <ArrowUp className=\"tw:size-3\" />\n <ArrowDown className=\"tw:size-3\" />\n </Kbd>\n move\n </span>\n )}\n <span className=\"tw:inline-flex tw:items-center tw:gap-1\">\n <Kbd casing=\"as-written\">Enter</Kbd>\n {multiSelect ? 'toggle' : 'select'}\n </span>\n </div>\n )}\n\n {error != null && (\n <div\n role=\"alert\"\n data-testid=\"question-error\"\n className=\"tw:mx-4 tw:-mt-1 tw:rounded-md tw:bg-destructive/10 tw:px-3 tw:py-2 tw:text-sm tw:text-destructive\"\n >\n {error}\n </div>\n )}\n\n <div className=\"tw:flex tw:flex-col\">\n {showStepControls && (\n <Progress size=\"sm\" value={progressValue} className=\"tw:rounded-none\" />\n )}\n\n {showFooter && (\n <div\n className={cn(\n 'tw:flex tw:items-center tw:justify-end tw:gap-4 tw:px-4 tw:py-3',\n !showStepControls && 'tw:border-0 tw:border-t tw:border-solid tw:border-border',\n )}\n >\n {showStepControls && (\n <div className=\"tw:flex tw:items-center tw:gap-2\">\n <button\n type=\"button\"\n disabled={isFirstStep}\n className=\"tw:flex tw:cursor-pointer tw:items-center tw:justify-center tw:bg-transparent tw:p-0 tw:disabled:cursor-default tailwindcss-preflight\"\n onClick={onPrevious}\n aria-label=\"Previous step\"\n >\n <ChevronLeft\n className={cn(\n 'tw:size-5',\n isFirstStep ? 'tw:text-primary/25' : 'tw:text-primary',\n )}\n />\n </button>\n <span className=\"tw:text-xs tw:leading-4 tw:text-muted-foreground\">\n {currentStep} of {totalSteps}\n </span>\n <button\n type=\"button\"\n disabled={currentStep === totalSteps}\n className=\"tw:flex tw:cursor-pointer tw:items-center tw:justify-center tw:bg-transparent tw:p-0 tw:disabled:cursor-default tailwindcss-preflight\"\n onClick={handleNextStep}\n aria-label=\"Next step\"\n >\n <ChevronRight\n className={cn(\n 'tw:size-5',\n currentStep === totalSteps ? 'tw:text-primary/25' : 'tw:text-primary',\n )}\n />\n </button>\n </div>\n )}\n {showSkipButton &&\n (skipTooltip == null ? (\n skipButton\n ) : (\n <Tooltip tooltip={skipTooltip} placement=\"top\" triggerAsChild>\n {skipButton}\n </Tooltip>\n ))}\n {showSubmitButton &&\n (submitTooltip ? (\n <Tooltip tooltip={submitTooltip} placement=\"top\" triggerAsChild>\n {submitButton}\n </Tooltip>\n ) : (\n submitButton\n ))}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport type { QuestionOption, Props as QuestionProps };\n","import { type ReactNode, useState } from 'react';\n\nimport type { QuestionOption } from './Question';\nimport { Question } from './Question';\n\ntype QuestionStep = {\n question: string;\n header?: string;\n options: readonly QuestionOption[];\n multiSelect?: boolean;\n showCustomAnswer?: boolean;\n customAnswerPlaceholder?: string;\n};\n\ntype QuestionAnswers = {\n selections: Record<number, readonly string[]>;\n customAnswers: Record<number, string>;\n};\n\ntype Props = {\n steps: readonly [QuestionStep, ...QuestionStep[]];\n showSkip?: boolean;\n onSubmit?: (answers: QuestionAnswers) => void;\n onClose?: () => void;\n renderPreview?: (content: string) => ReactNode;\n className?: string;\n};\n\nexport const QuestionBlock = ({\n steps,\n showSkip = true,\n onSubmit,\n onClose,\n renderPreview,\n className,\n}: Props) => {\n const [currentStep, setCurrentStep] = useState(1);\n const [selections, setSelections] = useState<Record<number, readonly string[]>>({});\n const [customAnswers, setCustomAnswers] = useState<Record<number, string>>({});\n const stepData = steps[currentStep - 1]!;\n const isLastStep = currentStep === steps.length;\n\n const advance = (updatedSelections?: Record<number, readonly string[]>) => {\n const finalSelections = updatedSelections ?? selections;\n if (isLastStep) {\n onSubmit?.({ selections: finalSelections, customAnswers });\n } else {\n setCurrentStep((s) => Math.min(s + 1, steps.length));\n }\n };\n\n const handleSelectionChange = (ids: readonly string[]) => {\n const updated = { ...selections, [currentStep]: ids };\n setSelections(updated);\n if (!stepData.multiSelect) {\n advance(updated);\n }\n };\n\n return (\n <Question\n key={currentStep}\n {...stepData}\n selectedOptionIds={selections[currentStep] ?? []}\n onSelectionChange={handleSelectionChange}\n customAnswer={customAnswers[currentStep] ?? ''}\n onCustomAnswerChange={(value) =>\n setCustomAnswers((prev) => ({ ...prev, [currentStep]: value }))\n }\n currentStep={currentStep}\n totalSteps={steps.length}\n showSkip={showSkip && !isLastStep}\n onNext={() => advance()}\n onPrevious={() => setCurrentStep((s) => Math.max(s - 1, 1))}\n onSkip={() => setCurrentStep((s) => Math.min(s + 1, steps.length))}\n onClose={onClose}\n renderPreview={renderPreview}\n className={className}\n />\n );\n};\n\nexport type { QuestionStep, QuestionAnswers, Props as QuestionBlockProps };\n","import { DIAGRAM_LANGUAGES } from './diagramLanguages';\n\n/** A fence delimiter line: up to three spaces, then three or more backticks or tildes. */\nconst FENCE_LINE = /^ {0,3}(`{3,}|~{3,})/;\n\n/** A list-item marker: a bullet or a `1.`/`1)` ordinal, then a space or the line end. */\nconst LIST_MARKER = /^ {0,3}(?:[-*+]|\\d{1,9}[.)])(?:\\s|$)/;\n\n/** A line at column four continues whatever block sits above a blank line. */\nconst INDENTED = /^(?: {4}| {0,3}\\t)/;\n\n/** A line that continues an open list: one to three spaces, or another marker. */\nconst CONTINUES_LIST = /^(?: {1,3}|(?:[-*+]|\\d{1,9}[.)])(?:\\s|$))/;\n\n/** A line that can only be a GFM table row: it opens with a pipe. */\nconst TABLE_ROW = /^ {0,3}\\|/;\n\n/** A delimiter row still streaming: pipes, dashes, colons and spaces only. */\nconst TABLE_DELIMITER_PARTIAL = /^ {0,3}\\|?[ :|-]*$/;\n\n/** Past this length a lone pipe line with no second pipe is prose, not a header. */\nconst TABLE_HEAD_FIRST_CELL_MAX = 80;\n\n/** Whether `line` closes a fence opened with `marker`: same character, at least as long, nothing after. */\nconst closesFence = (line: string, marker: string): boolean => {\n const match = FENCE_LINE.exec(line);\n return (\n !!match?.[1] &&\n match[1][0] === marker[0] &&\n match[1].length >= marker.length &&\n !line.slice(match[0].length).trim()\n );\n};\n\n/**\n * Every offset where all blocks before it are closed.\n *\n * - A cut is the end of a blank line outside a fence whose next line opens a fresh block.\n * - The last line is never classified: it is still streaming.\n * - An indented line, or a list continuation while a list is open, defers the cut.\n */\nconst sealableBoundaries = (text: string): number[] => {\n const cuts: number[] = [];\n let pos = 0;\n let fence: string | null = null;\n let pendingBlank = -1;\n let listOpen = false;\n\n const cutAtBlank = () => {\n if (pendingBlank > 0) cuts.push(pendingBlank);\n listOpen = false;\n };\n\n while (pos < text.length) {\n const nl = text.indexOf('\\n', pos);\n if (nl === -1) break;\n const line = text.slice(pos, nl);\n pos = nl + 1;\n\n if (fence !== null) {\n if (closesFence(line, fence)) fence = null;\n continue;\n }\n\n const continuesList = listOpen && CONTINUES_LIST.test(line);\n const opener = FENCE_LINE.exec(line)?.[1];\n if (opener !== undefined) {\n fence = opener;\n if (pendingBlank !== -1 && !continuesList) cutAtBlank();\n pendingBlank = -1;\n } else if (!line.trim()) {\n pendingBlank = pos;\n } else {\n const continues = INDENTED.test(line) || continuesList;\n if (pendingBlank !== -1 && !continues) cutAtBlank();\n pendingBlank = -1;\n if (LIST_MARKER.test(line)) listOpen = true;\n }\n }\n return cuts;\n};\n\n/**\n * A streaming answer split into blocks that can no longer change and the tail that still can.\n *\n * - Render each `sealed` block in its own memoised `Markdown.Block`, keyed by index; only `tail` re-parses.\n * - A sealed block's text never changes as more text arrives.\n * - Reference links and footnotes defined in a later block resolve only once the full answer renders.\n */\nexport const splitSealedBlocks = (text: string): { sealed: string[]; tail: string } => {\n const sealed: string[] = [];\n let from = 0;\n for (const cut of sealableBoundaries(text)) {\n sealed.push(text.slice(from, cut));\n from = cut;\n }\n return { sealed, tail: text.slice(from) };\n};\n\ntype OpenFence = { start: number; language: string | null };\n\n/**\n * The fence still open at the end of `text`, if any.\n *\n * - `language` is `null` while the info string is still streaming (no newline yet).\n */\nconst findOpenFence = (text: string): OpenFence | null => {\n let open: (OpenFence & { marker: string }) | null = null;\n let pos = 0;\n for (;;) {\n const nl = text.indexOf('\\n', pos);\n const line = text.slice(pos, nl === -1 ? text.length : nl);\n\n if (open !== null) {\n if (nl !== -1 && closesFence(line, open.marker)) open = null;\n } else {\n const match = FENCE_LINE.exec(line);\n if (match?.[1]) {\n const info = line.slice(match[0].length).trim().split(/\\s+/)[0] ?? '';\n open = {\n start: pos,\n marker: match[1],\n language: nl === -1 ? null : info.toLowerCase(),\n };\n }\n }\n\n if (nl === -1) break;\n pos = nl + 1;\n }\n return open && { start: open.start, language: open.language };\n};\n\n/**\n * Drops a table header still waiting for its delimiter row.\n *\n * - Until the delimiter row ends, GFM renders the header as a paragraph of raw pipes.\n * - Two shapes are withheld at the end: a lone pipe line, or that line plus a partial delimiter.\n * - A data row is never withheld: it has table rows above it.\n */\nconst withholdTableHead = (text: string): string => {\n const lastNl = text.lastIndexOf('\\n');\n const last = text.slice(lastNl + 1);\n const prevNl = lastNl === -1 ? -1 : text.lastIndexOf('\\n', lastNl - 1);\n const prev = lastNl === -1 ? null : text.slice(prevNl + 1, lastNl);\n const prevIsRow = prev !== null && TABLE_ROW.test(prev);\n\n if (TABLE_ROW.test(last) && !prevIsRow) {\n const firstPipe = last.indexOf('|');\n const isProse =\n last.indexOf('|', firstPipe + 1) === -1 && last.length > TABLE_HEAD_FIRST_CELL_MAX;\n return isProse ? text : text.slice(0, lastNl + 1);\n }\n\n if (prevIsRow && TABLE_DELIMITER_PARTIAL.test(last)) {\n const prev2Nl = prevNl === -1 ? -1 : text.lastIndexOf('\\n', prevNl - 1);\n const prev2 = prevNl === -1 ? null : text.slice(prev2Nl + 1, prevNl);\n if (prev2 === null || !TABLE_ROW.test(prev2)) return text.slice(0, prevNl + 1);\n }\n return text;\n};\n\ntype WithholdOptions = {\n /** Fence languages held back while open; `true` means every language `Markdown` draws. */\n diagram?: boolean | readonly string[];\n /** Hold back a table header until its delimiter row is complete. */\n tableHead?: boolean;\n};\n\n/**\n * The part of a streaming answer that is safe to paint now.\n *\n * - An open fence whose language is still being typed is always held back.\n * - An open fence in a `diagram` language is held back, or every chunk redraws the chart.\n * - Any other open fence streams as a growing code block.\n */\nexport const withholdOpenTail = (\n text: string,\n { diagram = false, tableHead = false }: WithholdOptions = {},\n): string => {\n const fence = findOpenFence(text);\n const diagramLanguages: readonly string[] =\n diagram === true ? DIAGRAM_LANGUAGES : diagram === false ? [] : diagram;\n\n const visible =\n fence === null\n ? text\n : fence.language === null || diagramLanguages.includes(fence.language)\n ? text.slice(0, fence.start)\n : null;\n\n if (visible === null) return text;\n return tableHead ? withholdTableHead(visible) : visible;\n};\n","import type { ReactNode } from 'react';\n\nimport { Sparkles } from '../../icons';\nimport { cn } from '../../utils';\n\ntype Props = {\n label: string;\n disabled?: boolean;\n onClick: () => void;\n icon?: ReactNode;\n /** A secondary line under the label. */\n description?: ReactNode;\n /** Content pinned to the end of the row, e.g. a badge. */\n trailing?: ReactNode;\n 'aria-label'?: string;\n /** `bubble`: shaped like a chat message and outlined — a reply waiting to be sent. */\n variant?: 'row' | 'bubble';\n className?: string;\n};\n\nexport const SuggestedPrompt = ({\n label,\n disabled,\n onClick,\n icon,\n description,\n trailing,\n 'aria-label': ariaLabel,\n variant = 'row',\n className,\n}: Props) => {\n const isBubble = variant === 'bubble';\n return (\n <button\n type=\"button\"\n disabled={disabled}\n aria-label={ariaLabel}\n data-variant={variant}\n className={cn(\n 'tailwindcss-preflight tw:flex tw:items-center tw:justify-start tw:gap-2.5 tw:whitespace-nowrap',\n 'tw:text-left tw:text-sm tw:text-foreground tw:transition-colors',\n 'tw:focus-visible:outline-none tw:focus-visible:ring-2 tw:focus-visible:ring-ring tw:focus-visible:ring-offset-1',\n 'tw:disabled:cursor-not-allowed tw:disabled:opacity-disabled',\n isBubble\n ? [\n // The user bubble's shape, outlined on the card fill; hover and focus fill it in.\n 'tw:w-fit tw:max-w-[min(85%,40rem)] tw:rounded-xl tw:px-3 tw:py-2',\n 'tw:border tw:border-solid tw:border-border tw:bg-card',\n 'tw:not-disabled:hover:bg-hover tw:focus-visible:bg-hover',\n ]\n : 'tw:rounded-lg tw:px-3 tw:py-2 tw:font-medium tw:not-disabled:hover:bg-hover',\n className,\n )}\n onClick={onClick}\n >\n {icon ?? (\n // Lucide icons are stroke-based — paint the visible line with the AI\n // gradient (no fill, so the glyph keeps its outline silhouette instead\n // of becoming a solid block). The `*` selector catches every shape\n // element (path, circle, polyline, …) so multi-part icons don't lose\n // sub-shapes the way `path`-only selectors do.\n <Sparkles className=\"tw:size-4 tw:shrink-0 tw:basis-4 tw:[&_*]:stroke-aigradient-600\" />\n )}\n {description === undefined ? (\n <div className=\"tw:whitespace-normal tw:text-left\">{label}</div>\n ) : (\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-col tw:gap-0.5 tw:whitespace-normal tw:text-left\">\n <span>{label}</span>\n <span className=\"tw:text-xs tw:font-normal tw:text-muted-foreground\">{description}</span>\n </div>\n )}\n {trailing !== undefined && <span className=\"tw:ml-auto tw:shrink-0\">{trailing}</span>}\n </button>\n );\n};\n","import { Loader2 } from '../../icons';\n\ntype ThinkingIndicatorProps = {\n label?: string;\n};\n\n/**\n * The agent's turn is in flight and has nothing to show yet.\n *\n * - Quiet chrome, matching the step rows it precedes (muted ink, no italic), so the hand-off\n * from \"Thinking...\" to the first step is seamless.\n * - `role=\"status\"` because a spinner is silence to a screen reader, and for much of a turn\n * this is all a transcript shows. The label is the announcement, so it is never decorative.\n * - The icon is hidden from the tree: it says the same thing as the label beside it.\n */\nexport const ThinkingIndicator = ({ label = 'Thinking...' }: ThinkingIndicatorProps) => {\n return (\n <div\n className=\"tw:flex tw:items-center tw:gap-1.5\"\n role=\"status\"\n data-testid=\"chat-thinking-indicator\"\n >\n <Loader2 aria-hidden className=\"tw:size-3.5 tw:animate-spin tw:text-muted-foreground\" />\n <span className=\"tw:text-xs tw:font-medium tw:text-muted-foreground\">{label}</span>\n </div>\n );\n};\n\nexport type { ThinkingIndicatorProps };\n","import { Button } from '../../../components/Button';\nimport { Kbd, keys } from '../../../components/Kbd';\nimport { Tooltip } from '../../../components/Tooltip';\n\nimport type { ToolCallApprovalAction } from './toolCallApprovalStatus';\nimport type { ToolCallApprovalShortcutKey } from './useApprovalShortcut';\n\ntype ToolCallApprovalExtraAction = { label: string; onClick: () => void };\n\ntype Props = {\n onApprove?: () => void;\n onReject?: () => void;\n extraAction?: ToolCallApprovalExtraAction;\n approveLabel: string;\n rejectLabel: string;\n approveVariant: 'primary' | 'danger';\n pendingAction?: ToolCallApprovalAction | null;\n isDisabled: boolean;\n shortcutKey: ToolCallApprovalShortcutKey;\n};\n\nconst ShortcutHint = ({ shortcutKey }: { shortcutKey: 'enter' | 'mod-enter' }) => (\n <Kbd.Group separator=\"+\">\n {shortcutKey === 'mod-enter' && <Kbd variant=\"primary\">{keys.mod.symbol}</Kbd>}\n <Kbd variant=\"primary\">{keys.enter.symbol}</Kbd>\n </Kbd.Group>\n);\n\nconst BUTTON_CLASS = 'tw:shrink-0 tw:whitespace-nowrap';\n\nexport const ToolCallApprovalActions = ({\n onApprove,\n onReject,\n extraAction,\n approveLabel,\n rejectLabel,\n approveVariant,\n pendingAction,\n isDisabled,\n shortcutKey,\n}: Props) => {\n const isLocked = isDisabled || pendingAction != null;\n const approveButton = onApprove && (\n <Button\n data-testid=\"tool-approve-button\"\n variant={approveVariant}\n size=\"small\"\n className={BUTTON_CLASS}\n onClick={onApprove}\n disabled={isLocked}\n isLoading={pendingAction === 'approve'}\n >\n {approveLabel}\n </Button>\n );\n\n return (\n <div className=\"tw:flex tw:items-center tw:justify-end tw:gap-2 tw:overflow-x-auto\">\n {onReject && (\n <Button\n data-testid=\"tool-decline-button\"\n variant=\"outline\"\n size=\"small\"\n className={BUTTON_CLASS}\n onClick={onReject}\n disabled={isLocked}\n isLoading={pendingAction === 'reject'}\n >\n {rejectLabel}\n </Button>\n )}\n {extraAction && (\n <Button\n data-testid=\"tool-extra-action-button\"\n variant=\"outline\"\n size=\"small\"\n className={BUTTON_CLASS}\n onClick={extraAction.onClick}\n disabled={isLocked}\n isLoading={pendingAction === 'extra'}\n >\n {extraAction.label}\n </Button>\n )}\n {approveButton && shortcutKey !== 'none' ? (\n <Tooltip\n tooltip={<ShortcutHint shortcutKey={shortcutKey} />}\n placement=\"top\"\n triggerAsChild\n >\n {approveButton}\n </Tooltip>\n ) : (\n approveButton\n )}\n </div>\n );\n};\n\nexport type { ToolCallApprovalExtraAction };\n","import type { ReactNode } from 'react';\n\nimport type { LucideIcon } from '../../../icons';\nimport { CircleAlert, Info, TriangleAlert } from '../../../icons';\nimport { cn } from '../../../utils';\n\ntype NoticeTone = 'warning' | 'destructive' | 'info';\n\ntype ToolCallApprovalNoticeItem = {\n tone: NoticeTone;\n content: ReactNode;\n icon?: LucideIcon;\n};\n\nconst TONE: Record<NoticeTone, { icon: LucideIcon; className: string }> = {\n warning: { icon: TriangleAlert, className: 'tw:bg-warning/10 tw:text-warning' },\n destructive: { icon: CircleAlert, className: 'tw:bg-destructive/10 tw:text-destructive' },\n info: { icon: Info, className: 'tw:bg-info/10 tw:text-info' },\n};\n\nexport const ToolCallApprovalNotice = ({ tone, content, icon }: ToolCallApprovalNoticeItem) => {\n const Icon = icon ?? TONE[tone].icon;\n return (\n <p\n data-testid=\"tool-call-approval-notice\"\n data-tone={tone}\n className={cn(\n 'tw:m-0 tw:flex tw:items-start tw:gap-2 tw:rounded-md tw:px-2.5 tw:py-1.5 tw:text-sm',\n TONE[tone].className,\n )}\n >\n <Icon className=\"tw:mt-0.5 tw:size-4 tw:shrink-0\" aria-hidden />\n <span className=\"tw:min-w-0 tw:text-foreground\">{content}</span>\n </p>\n );\n};\n\nexport type { NoticeTone as ToolCallApprovalNoticeTone, ToolCallApprovalNoticeItem };\n","import type { ReactNode } from 'react';\n\nimport { CircleCheck, CircleX } from '../../../icons';\nimport { cn } from '../../../utils';\n\nimport type { ToolCallApprovalStatus } from './toolCallApprovalStatus';\n\ntype Props = {\n status: ToolCallApprovalStatus;\n label: string;\n subject?: ReactNode;\n resolvedBy?: ReactNode;\n resolvedAt?: Date;\n className?: string;\n};\n\nexport const ToolCallApprovalRecord = ({\n status,\n label,\n subject,\n resolvedBy,\n resolvedAt,\n className,\n}: Props) => {\n const isApproved = status === 'approved';\n const Icon = isApproved ? CircleCheck : CircleX;\n return (\n <p\n data-testid=\"tool-call-approval\"\n data-status={status}\n data-density=\"record\"\n className={cn(\n 'tw:m-0 tw:flex tw:min-w-0 tw:items-center tw:gap-1.5 tw:text-xs tw:text-muted-foreground',\n className,\n )}\n >\n <Icon\n aria-hidden\n className={cn('tw:size-3.5 tw:shrink-0', isApproved ? 'tw:text-success' : 'tw:opacity-70')}\n />\n <span className=\"tw:flex tw:min-w-0 tw:flex-wrap tw:items-baseline tw:gap-x-1.5\">\n <span className=\"tw:font-medium tw:text-foreground\">{label}</span>\n {subject != null && <span className=\"tw:min-w-0 tw:truncate\">{subject}</span>}\n {resolvedBy != null && <span>{resolvedBy}</span>}\n {resolvedAt && (\n <time dateTime={resolvedAt.toISOString()}>{resolvedAt.toLocaleString()}</time>\n )}\n </span>\n </p>\n );\n};\n","import type { BadgeColor } from '../../../components/Badge/styles';\n\ntype ToolCallApprovalStatus =\n | 'pending'\n | 'approved'\n | 'rejected'\n | 'expired'\n | 'timed-out'\n | 'cancelled'\n | 'unattended';\n\ntype ToolCallApprovalAction = 'approve' | 'reject' | 'extra';\n\nexport const STATUS_BADGE: Record<ToolCallApprovalStatus, { label: string; color: BadgeColor }> = {\n pending: { label: 'Needs approval', color: 'blue' },\n approved: { label: 'Approved', color: 'green' },\n rejected: { label: 'Rejected', color: 'red' },\n expired: { label: 'Expired', color: 'orange' },\n 'timed-out': { label: 'Timed out', color: 'orange' },\n cancelled: { label: 'Cancelled', color: 'gray' },\n unattended: { label: 'Unattended', color: 'gray' },\n};\n\nexport type { ToolCallApprovalAction, ToolCallApprovalStatus };\n","import { useEffect } from 'react';\n\nimport { isMac } from '../../../utils';\n\ntype ShortcutKey = 'enter' | 'mod-enter' | 'none';\n\nconst isEditableTarget = (target: EventTarget | null) =>\n target instanceof HTMLElement &&\n (target.isContentEditable ||\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.tagName === 'SELECT');\n\nconst isModPressed = (event: KeyboardEvent) => (isMac ? event.metaKey : event.ctrlKey);\n\nconst matchesShortcut = (event: KeyboardEvent, shortcutKey: ShortcutKey) => {\n if (event.key !== 'Enter' || event.shiftKey || event.altKey) return false;\n if (shortcutKey === 'mod-enter') return isModPressed(event);\n return !event.metaKey && !event.ctrlKey && !isEditableTarget(event.target);\n};\n\n/**\n * Approves on `shortcutKey` from anywhere on the page while `isEnabled`.\n *\n * - `enter` skips keystrokes typed into a field; `mod-enter` fires from one too.\n * - Ignores key-repeat, IME composition and an event another handler already took.\n */\nexport const useApprovalShortcut = ({\n shortcutKey,\n isEnabled,\n onApprove,\n}: {\n shortcutKey: ShortcutKey;\n isEnabled: boolean;\n onApprove?: () => void;\n}) => {\n useEffect(() => {\n if (shortcutKey === 'none' || !isEnabled || !onApprove) return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.repeat || event.isComposing || event.defaultPrevented) return;\n if (!matchesShortcut(event, shortcutKey)) return;\n event.preventDefault();\n onApprove();\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [shortcutKey, isEnabled, onApprove]);\n};\n\nexport type { ShortcutKey as ToolCallApprovalShortcutKey };\n","import type { ReactNode } from 'react';\n\nimport { Badge } from '../../../components/Badge';\nimport { cn } from '../../../utils';\n\nimport {\n ToolCallApprovalActions,\n type ToolCallApprovalExtraAction,\n} from './ToolCallApprovalActions';\nimport { ToolCallApprovalNotice, type ToolCallApprovalNoticeItem } from './ToolCallApprovalNotice';\nimport { ToolCallApprovalRecord } from './ToolCallApprovalRecord';\nimport {\n STATUS_BADGE,\n type ToolCallApprovalAction,\n type ToolCallApprovalStatus,\n} from './toolCallApprovalStatus';\nimport { type ToolCallApprovalShortcutKey, useApprovalShortcut } from './useApprovalShortcut';\n\ntype ToolCallApprovalProps = {\n status: ToolCallApprovalStatus;\n /** Replaces the status badge's text, e.g. `Cancelled by Kai`. */\n statusLabel?: string;\n /** Why the call is in its terminal status, shown under the title. */\n statusMessage?: ReactNode;\n /** `record` collapses a resolved call to one line; a pending call always renders as a card. */\n density?: 'card' | 'record';\n resolvedBy?: ReactNode;\n resolvedAt?: Date;\n\n /** The tool being called (e.g. `run_sql`), rendered as a monospace tag. */\n toolName?: string;\n /** Leads the header, e.g. \"Kai needs your OK\" or an app's own status row. */\n eyebrow?: ReactNode;\n title?: ReactNode;\n\n /** App-rendered detail — a diff, a `ToolCallChip`, arguments. */\n children?: ReactNode;\n /** Rows above the detail naming what the call will do — a link going public, a destructive write. */\n notices?: readonly ToolCallApprovalNoticeItem[];\n /** A preview beside the detail; stacks under it in a narrow container. */\n aside?: ReactNode;\n error?: ReactNode;\n\n onApprove?: () => void;\n onReject?: () => void;\n /** A third action beside the pair, e.g. \"Always allow\". */\n extraAction?: ToolCallApprovalExtraAction;\n approveLabel?: string;\n rejectLabel?: string;\n approveVariant?: 'primary' | 'danger';\n /** The action in flight: its button spins and every action is disabled. */\n pendingAction?: ToolCallApprovalAction | null;\n isDisabled?: boolean;\n /** Approves from anywhere on the page and shows the key on the approve button. */\n shortcutKey?: ToolCallApprovalShortcutKey;\n /** Shows the key without listening for it, for an app that owns the shortcut itself. */\n isShortcutHintOnly?: boolean;\n\n className?: string;\n};\n\n/**\n * Per-tool-call approve/reject frame — the granular sibling of `PlanApproval`.\n *\n * - Chrome, status and actions only: the app renders the call detail and owns the permission wiring.\n * - Actions render only while `pending`.\n */\nexport const ToolCallApproval = ({\n status,\n statusLabel,\n statusMessage,\n density = 'card',\n resolvedBy,\n resolvedAt,\n toolName,\n eyebrow,\n title,\n children,\n notices = [],\n aside,\n error,\n onApprove,\n onReject,\n extraAction,\n approveLabel = 'Approve',\n rejectLabel = 'Reject',\n approveVariant = 'primary',\n pendingAction = null,\n isDisabled = false,\n shortcutKey = 'none',\n isShortcutHintOnly = false,\n className,\n}: ToolCallApprovalProps) => {\n const isPending = status === 'pending';\n const badge = STATUS_BADGE[status];\n const label = statusLabel ?? badge.label;\n const showActions = isPending && Boolean(onApprove || onReject || extraAction);\n\n useApprovalShortcut({\n shortcutKey: isShortcutHintOnly ? 'none' : shortcutKey,\n isEnabled: isPending && !isDisabled && pendingAction == null,\n onApprove,\n });\n\n if (density === 'record' && !isPending) {\n return (\n <ToolCallApprovalRecord\n status={status}\n label={label}\n subject={title ?? toolName}\n resolvedBy={resolvedBy}\n resolvedAt={resolvedAt}\n className={className}\n />\n );\n }\n\n const showBadge = !isPending || eyebrow == null;\n const hasHeadline = showBadge || toolName != null;\n\n return (\n <section\n data-testid=\"tool-call-approval\"\n data-status={status}\n data-density=\"card\"\n aria-label={typeof title === 'string' ? title : (toolName ?? label)}\n className={cn(\n 'tw:flex tw:w-full tw:max-w-[800px] tw:flex-col tw:overflow-hidden tw:rounded-lg tw:border tw:border-solid tw:border-border tw:bg-card tw:text-card-foreground',\n className,\n )}\n >\n {eyebrow}\n <div className=\"tw:flex tw:flex-col tw:gap-3 tw:p-3\">\n {(hasHeadline || title != null || (!isPending && statusMessage != null)) && (\n <div className=\"tw:flex tw:flex-col tw:gap-1.5\">\n {hasHeadline && (\n <div className=\"tw:flex tw:flex-wrap tw:items-center tw:gap-2\">\n {showBadge && (\n <Badge color={badge.color} variant=\"pill\">\n {label}\n </Badge>\n )}\n {toolName != null && (\n <code className=\"tw:rounded tw:bg-muted tw:px-1.5 tw:py-0.5 tw:font-mono tw:text-xs tw:text-foreground\">\n {toolName}\n </code>\n )}\n </div>\n )}\n {title != null && (\n <p className=\"tw:m-0 tw:text-sm tw:font-medium tw:text-foreground\">{title}</p>\n )}\n {!isPending && statusMessage != null && (\n <p\n data-testid=\"tool-call-approval-status-message\"\n className=\"tw:m-0 tw:text-sm tw:text-muted-foreground\"\n >\n {statusMessage}\n </p>\n )}\n {(resolvedBy != null || resolvedAt) && !isPending && (\n <p className=\"tw:m-0 tw:flex tw:flex-wrap tw:gap-x-1.5 tw:text-xs tw:text-muted-foreground\">\n {resolvedBy != null && <span>{resolvedBy}</span>}\n {resolvedAt && (\n <time dateTime={resolvedAt.toISOString()}>{resolvedAt.toLocaleString()}</time>\n )}\n </p>\n )}\n </div>\n )}\n\n {notices.map((notice, index) => (\n <ToolCallApprovalNotice key={index} {...notice} />\n ))}\n\n {(children != null || aside != null) && (\n <div className=\"tw:@container\">\n <div className=\"tw:flex tw:flex-col tw:gap-3 tw:@xl:flex-row\">\n {children != null && <div className=\"tw:min-w-0 tw:flex-1\">{children}</div>}\n {aside != null && (\n <div\n data-testid=\"tool-call-approval-aside\"\n className=\"tw:min-w-0 tw:@xl:w-1/2 tw:@xl:shrink-0\"\n >\n {aside}\n </div>\n )}\n </div>\n </div>\n )}\n\n {error != null && (\n <div\n role=\"alert\"\n className=\"tw:rounded-md tw:bg-destructive/10 tw:p-2 tw:text-sm tw:text-destructive tw:whitespace-pre-wrap tw:break-words\"\n >\n {error}\n </div>\n )}\n\n {showActions && (\n <ToolCallApprovalActions\n onApprove={onApprove}\n onReject={onReject}\n extraAction={extraAction}\n approveLabel={approveLabel}\n rejectLabel={rejectLabel}\n approveVariant={approveVariant}\n pendingAction={pendingAction}\n isDisabled={isDisabled}\n shortcutKey={shortcutKey}\n />\n )}\n </div>\n </section>\n );\n};\n\nexport type { ToolCallApprovalProps };\n","import type { MouseEventHandler, ReactNode } from 'react';\nimport { cva } from 'class-variance-authority';\n\nimport { CircleCheck, CircleX, Loader2 } from '../../../icons';\nimport { cn } from '../../../utils';\n\ntype ToolCallState = 'processing' | 'done' | 'error';\n\ntype ToolCallChipProps = {\n label: ReactNode;\n state: ToolCallState;\n /** Leading icon; defaults to a state glyph (spinner / check / x). */\n icon?: ReactNode;\n /** Trailing node (e.g. a chevron or count). */\n trailing?: ReactNode;\n /** When set, the chip renders as a button and fires this on click. */\n onClick?: MouseEventHandler<HTMLButtonElement>;\n className?: string;\n};\n\nconst chipClasses = cva(\n [\n 'tw:inline-flex tw:items-center tw:gap-1.5 tw:rounded-md tw:border tw:border-solid',\n 'tw:border-border tw:bg-muted tw:px-2 tw:py-1 tw:text-xs tw:text-foreground',\n ],\n {\n variants: {\n interactive: {\n true: 'tw:cursor-pointer tw:focus-visible:outline-hidden tw:focus-visible:ring-2 tw:focus-visible:ring-ring tw:not-disabled:hover:bg-hover',\n false: '',\n },\n },\n defaultVariants: { interactive: false },\n },\n);\n\nconst StateIcon = ({ state }: { state: ToolCallState }) => {\n if (state === 'processing') {\n return <Loader2 className=\"tw:size-3.5 tw:shrink-0 tw:animate-spin tw:text-muted-foreground\" />;\n }\n if (state === 'error') {\n return <CircleX className=\"tw:size-3.5 tw:shrink-0 tw:text-error-500\" />;\n }\n return <CircleCheck className=\"tw:size-3.5 tw:shrink-0 tw:text-primary\" />;\n};\n\n/**\n * Presentational chip summarising a single tool call (icon + label + optional\n * trailing action). It has **no** URL/router knowledge — wrap it in a `Link`\n * or pass `onClick` for navigation; the app owns deep-linking.\n */\nexport const ToolCallChip = ({\n label,\n state,\n icon,\n trailing,\n onClick,\n className,\n}: ToolCallChipProps) => {\n const content = (\n <>\n {icon ?? <StateIcon state={state} />}\n <span className=\"tw:min-w-0 tw:truncate\">{label}</span>\n {trailing != null && (\n <span className=\"tw:ml-auto tw:inline-flex tw:shrink-0 tw:items-center\">{trailing}</span>\n )}\n </>\n );\n\n if (onClick) {\n return (\n <button\n type=\"button\"\n data-testid=\"tool-call-chip\"\n data-state={state}\n onClick={onClick}\n className={cn('tailwindcss-preflight', chipClasses({ interactive: true }), className)}\n >\n {content}\n </button>\n );\n }\n\n return (\n <span\n data-testid=\"tool-call-chip\"\n data-state={state}\n className={cn(chipClasses({ interactive: false }), className)}\n >\n {content}\n </span>\n );\n};\n\nexport type { ToolCallChipProps, ToolCallState };\n","import type { ReactNode } from 'react';\nimport { cva } from 'class-variance-authority';\n\nimport type { LucideIcon } from '../../icons';\nimport { ChevronDown, TriangleAlert } from '../../icons';\nimport { cn } from '../../utils';\n\ntype ToolCallStatus = 'processing' | 'warning' | 'success' | 'error';\n\ntype Props = {\n icon: LucideIcon;\n iconSpin?: boolean;\n status: ToolCallStatus;\n text: ReactNode;\n needsConfirmation?: boolean;\n isCollapsible?: boolean;\n isCollapsed?: boolean;\n onToggleCollapse?: () => void;\n};\n\n// Neutral band for routine states; status is carried by icon and label tint.\n// Only warning and error, which need attention, get a soft background tint.\nconst headerVariants = cva(\n 'tw:flex tw:items-center tw:justify-between tw:gap-2 tw:px-2.5 tw:py-1.5',\n {\n variants: {\n // One boundary cue per state: tinted states end at their wash, untinted\n // ones get the hairline.\n status: {\n processing: 'tw:border-b tw:border-border/60',\n warning: 'tw:bg-warning/10',\n success: 'tw:border-b tw:border-border/60',\n error: 'tw:bg-destructive/10',\n },\n },\n defaultVariants: {\n status: 'success',\n },\n },\n);\n\nconst statusInk: Record<ToolCallStatus, string> = {\n processing: 'tw:text-muted-foreground',\n warning: 'tw:text-warning',\n success: 'tw:text-muted-foreground',\n error: 'tw:text-destructive',\n};\n\nconst statusIconInk: Record<ToolCallStatus, string> = {\n processing: 'tw:text-muted-foreground',\n warning: 'tw:text-warning',\n success: 'tw:text-success/70',\n error: 'tw:text-destructive',\n};\n\nexport const ToolCallStatusHeader = ({\n icon: IconComponent,\n iconSpin,\n status,\n text,\n needsConfirmation,\n isCollapsible,\n isCollapsed,\n onToggleCollapse,\n}: Props) => {\n return (\n <div\n role={isCollapsible ? 'button' : undefined}\n tabIndex={isCollapsible ? 0 : undefined}\n aria-expanded={isCollapsible ? !isCollapsed : undefined}\n data-status={status}\n className={cn(headerVariants({ status }), isCollapsible && 'tw:cursor-pointer')}\n onClick={isCollapsible ? onToggleCollapse : undefined}\n onKeyDown={\n isCollapsible\n ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onToggleCollapse?.();\n }\n }\n : undefined\n }\n >\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:items-center tw:gap-1.5\">\n <IconComponent\n className={cn(\n 'tw:size-3.5 tw:shrink-0',\n statusIconInk[status],\n iconSpin && 'tw:animate-spin',\n )}\n />\n {/* Awaiting confirmation, the label names the action being approved: full ink, so it\n reads at least as strongly as the content below it. */}\n <span\n data-testid=\"tool-status-text\"\n className={cn(\n 'tw:truncate tw:pr-0.5 tw:text-xs tw:font-medium',\n needsConfirmation ? 'tw:text-foreground' : statusInk[status],\n )}\n >\n {text}\n </span>\n </div>\n {(needsConfirmation || isCollapsible) && (\n <div className=\"tw:flex tw:shrink-0 tw:items-center tw:gap-2\">\n {needsConfirmation && (\n <div className=\"tw:flex tw:items-center tw:gap-1\">\n <span\n data-testid=\"tool-confirmation-required\"\n className=\"tw:text-xs tw:font-medium tw:text-warning\"\n >\n Confirmation required\n </span>\n <TriangleAlert className=\"tw:size-3.5 tw:text-warning\" />\n </div>\n )}\n {isCollapsible && (\n <ChevronDown\n className={cn(\n 'tw:size-3.5 tw:shrink-0 tw:text-muted-foreground',\n 'tw:transition-transform tw:duration-300 tw:ease-out tw:motion-reduce:transition-none',\n !isCollapsed && 'tw:rotate-180',\n )}\n />\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport type { Props as ToolCallStatusHeaderProps, ToolCallStatus };\n","/**\n * Clamp a percentage to 0–100 and normalize non-finite input to 0.\n *\n * - `Progress`'s indicator is unclamped, so a value over 100 slides the bar off-screen.\n * - `NaN` normalizes to 0 — `Math.min`/`Math.max` propagate it, and it renders as no bar at all.\n */\nexport const clampPercentage = (value: number) =>\n Number.isFinite(value) ? Math.min(100, Math.max(0, value)) : 0;\n\n/**\n * A percentage as text — `72%`, `0.2%`, `99%`.\n *\n * - Whole numbers from 1% up; a decimal only below 1%, where rounding would read as `0%`.\n * - A non-zero share never prints as `0.0%` — it floors at `0.1%`.\n * - Never `100%` for a value under 100: the text would disagree with the at-limit state computed\n * from the raw value, exactly at the boundary everything else turns on.\n */\nexport const formatPercentage = (value: number) => {\n const oneDecimal = Math.round(value * 10) / 10;\n if (value > 0 && oneDecimal < 1) {\n return `${Math.max(0.1, oneDecimal).toFixed(1)}%`;\n }\n const rounded = Math.round(value);\n return `${value < 100 ? Math.min(rounded, 99) : rounded}%`;\n};\n","import type { ComponentProps, ReactNode } from 'react';\n\nimport { Progress } from '../../components/Progress';\nimport { cn } from '../../utils';\n\nimport { clampPercentage, formatPercentage } from './usageStatsHelpers';\n\ntype Props = Omit<ComponentProps<'span'>, 'children'> & {\n /** Share of the budget SPENT, 0–100; the bar fills with it, the figure shows what is LEFT. */\n value: number;\n label: ReactNode;\n /** Untoned by default: when to escalate is the host's product rule, not the bar's. */\n variant?: ComponentProps<typeof Progress>['variant'];\n};\n\n/**\n * One budget, as a labelled row over a bar.\n *\n * - `value` is clamped by `clampPercentage` — `Progress`'s indicator is unclamped.\n */\nexport const UsageBar = ({ value, label, variant, className, ...props }: Props) => (\n <span\n {...props}\n className={cn('tw:flex tw:flex-col tw:gap-1.5 tw:text-xs tw:text-muted-foreground', className)}\n >\n <span className=\"tw:flex tw:items-baseline tw:justify-between tw:gap-2\">\n <span>{label}</span>\n <span>{`${formatPercentage(Math.max(0, 100 - value))} left`}</span>\n </span>\n <Progress size=\"sm\" variant={variant} value={clampPercentage(value)} />\n </span>\n);\n","import { cn } from '../../utils';\n\nimport { clampPercentage } from './usageStatsHelpers';\n\ntype Props = {\n value: number;\n size?: number;\n strokeWidth?: number;\n className?: string;\n};\n\nexport const UsageStatsRing = ({ value, size = 16, strokeWidth = 2.5, className }: Props) => {\n const radius = Math.max(0, (size - strokeWidth) / 2 - 1);\n const circumference = 2 * Math.PI * radius;\n const offset = circumference * (1 - clampPercentage(value) / 100);\n\n return (\n <svg\n width={size}\n height={size}\n viewBox={`0 0 ${size} ${size}`}\n className={cn('tw:-rotate-90', className)}\n role=\"presentation\"\n >\n <circle\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n strokeWidth={strokeWidth}\n // The unfilled remainder of the gauge: a muted mark, not a surface.\n className=\"tw:stroke-muted-foreground tw:opacity-50\"\n />\n <circle\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={offset}\n className=\"tw:stroke-primary tw:transition-all\"\n />\n </svg>\n );\n};\n","import type { ComponentProps, ReactNode } from 'react';\n\nimport { HoverCard } from '../../components/HoverCard';\nimport { AlertCircle } from '../../icons';\nimport { cn } from '../../utils';\n\nimport { clampPercentage } from './usageStatsHelpers';\nimport { UsageStatsRing } from './UsageStatsRing';\n\ntype Props = {\n value: number;\n /** `true`/`'error'` renders a red corner badge, `'warning'` an amber one. */\n alert?: boolean | 'warning' | 'error';\n children: ReactNode;\n className?: string;\n /** Accessible name for the trigger; defaults to a label carrying the value. */\n ariaLabel?: string;\n align?: ComponentProps<typeof HoverCard.Content>['align'];\n side?: ComponentProps<typeof HoverCard.Content>['side'];\n sideOffset?: ComponentProps<typeof HoverCard.Content>['sideOffset'];\n /** Hold the card open past a pointer leave, e.g. while a popover inside it is up. */\n open?: ComponentProps<typeof HoverCard>['open'];\n onOpenChange?: ComponentProps<typeof HoverCard>['onOpenChange'];\n};\n\nexport const UsageStats = ({\n value,\n alert = false,\n children,\n className,\n ariaLabel,\n align = 'end',\n side = 'top',\n sideOffset = 8,\n open,\n onOpenChange,\n}: Props) => {\n const hasAlert = Boolean(alert);\n const isWarning = alert === 'warning';\n const defaultLabel = `Usage: ${Math.round(clampPercentage(value))}%${hasAlert ? ' (usage alert)' : ''}`;\n return (\n <HoverCard open={open} onOpenChange={onOpenChange}>\n <HoverCard.Trigger asChild>\n <button\n type=\"button\"\n aria-label={ariaLabel ?? defaultLabel}\n // `shrink-0`: otherwise a `shrink-0` sibling (like `Button`) squashes the fixed ring.\n className={cn(\n 'tw:relative tw:inline-flex tw:size-8 tw:shrink-0 tw:items-center tw:justify-center',\n 'tw:cursor-pointer tw:rounded-full tw:border-0 tw:bg-transparent tw:p-0',\n 'tw:transition-colors tw:hover:bg-muted',\n 'tw:focus-visible:outline-hidden tw:focus-visible:ring-2 tw:focus-visible:ring-ring/50',\n className,\n )}\n >\n <UsageStatsRing value={value} />\n {hasAlert && (\n <AlertCircle\n data-testid=\"usage-stats-alert\"\n className={cn(\n 'tw:absolute tw:-right-0.5 tw:-top-0.5 tw:size-3',\n isWarning ? 'tw:text-warning-500' : 'tw:text-error-500',\n )}\n />\n )}\n </button>\n </HoverCard.Trigger>\n\n <HoverCard.Content align={align} side={side} sideOffset={sideOffset}>\n {children}\n </HoverCard.Content>\n </HoverCard>\n );\n};\n"],"mappings":"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"}