@keboola/design 11.4.0 → 11.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +191 -1
- package/CHANGELOG.md +358 -0
- package/COMPONENT-API.md +68 -47
- package/dist/{AIKit-DDg5DBCG.js → AIKit-CNX6aiKm.js} +208 -62
- package/dist/AIKit-CNX6aiKm.js.map +1 -0
- package/dist/{Alert-DHJFrWnS.js → Alert-Ba5b2YPq.js} +2 -2
- package/dist/{Alert-DHJFrWnS.js.map → Alert-Ba5b2YPq.js.map} +1 -1
- package/dist/{Badge-Ch26CXoP.js → Badge-D0pXdekt.js} +2 -2
- package/dist/Badge-D0pXdekt.js.map +1 -0
- package/dist/{BrandEditor-Go7w8Zj2.js → BrandEditor-CSANsxUz.js} +6 -6
- package/dist/{BrandEditor-Go7w8Zj2.js.map → BrandEditor-CSANsxUz.js.map} +1 -1
- package/dist/{BrandLogo-Dmi7jo21.js → BrandLogo-CoKBk4MI.js} +4 -4
- package/dist/BrandLogo-CoKBk4MI.js.map +1 -0
- package/dist/{Breadcrumb-uEkM6adI.js → Breadcrumb-g_xn_-Nf.js} +2 -2
- package/dist/{Breadcrumb-uEkM6adI.js.map → Breadcrumb-g_xn_-Nf.js.map} +1 -1
- package/dist/{Checkbox-fC0BuO2B.js → Checkbox-CUIn2jap.js} +2 -2
- package/dist/{Checkbox-fC0BuO2B.js.map → Checkbox-CUIn2jap.js.map} +1 -1
- package/dist/{Clipboard-ChPdiUy3.js → Clipboard-BTW6C-b_.js} +2 -2
- package/dist/{Clipboard-ChPdiUy3.js.map → Clipboard-BTW6C-b_.js.map} +1 -1
- package/dist/{ClipboardButton-D9pDjgkB.js → ClipboardButton-CwZJdRaz.js} +2 -2
- package/dist/{ClipboardButton-D9pDjgkB.js.map → ClipboardButton-CwZJdRaz.js.map} +1 -1
- package/dist/{CodeEditor-Cxy3HnKH.js → CodeEditor-C9zy7PxK.js} +6 -6
- package/dist/{CodeEditor-Cxy3HnKH.js.map → CodeEditor-C9zy7PxK.js.map} +1 -1
- package/dist/{ColorInput-Bxj-1eLT.js → ColorInput-BZV-u_94.js} +3 -3
- package/dist/{ColorInput-Bxj-1eLT.js.map → ColorInput-BZV-u_94.js.map} +1 -1
- package/dist/{Combobox-Cs_1pj2q.js → Combobox-BfIfaVMA.js} +273 -104
- package/dist/Combobox-BfIfaVMA.js.map +1 -0
- package/dist/{Command-B7ML9YMv.js → Command-Bfa1kpbt.js} +2 -2
- package/dist/{Command-B7ML9YMv.js.map → Command-Bfa1kpbt.js.map} +1 -1
- package/dist/{CopyField-BO_sh-HO.js → CopyField-DpT0Ngz1.js} +2 -2
- package/dist/{CopyField-BO_sh-HO.js.map → CopyField-DpT0Ngz1.js.map} +1 -1
- package/dist/{DateInput-ZdaMQo5i.js → DateInput-DiEd5uCL.js} +3 -3
- package/dist/{DateInput-ZdaMQo5i.js.map → DateInput-DiEd5uCL.js.map} +1 -1
- package/dist/{DateRangeInput-DkvNh_sT.js → DateRangeInput-DPfVYchl.js} +3 -3
- package/dist/{DateRangeInput-DkvNh_sT.js.map → DateRangeInput-DPfVYchl.js.map} +1 -1
- package/dist/{FieldItem-CCd9-xnp.js → FieldItem-B7XMmZSz.js} +3 -3
- package/dist/{FieldItem-CCd9-xnp.js.map → FieldItem-B7XMmZSz.js.map} +1 -1
- package/dist/{Form-k6PH-em3.js → Form-CsttTHn4.js} +7 -7
- package/dist/Form-CsttTHn4.js.map +1 -0
- package/dist/{FormGroup-DbcDtrgU.js → FormGroup-DHvTFdno.js} +3 -3
- package/dist/{FormGroup-DbcDtrgU.js.map → FormGroup-DHvTFdno.js.map} +1 -1
- package/dist/{InputGroup-BnLHY0eq.js → InputGroup-DcZRlVnN.js} +22 -14
- package/dist/InputGroup-DcZRlVnN.js.map +1 -0
- package/dist/{Kbd-CvSM3D3-.js → Kbd-Cvvt91Q8.js} +14 -4
- package/dist/Kbd-Cvvt91Q8.js.map +1 -0
- package/dist/{MermaidDiagram-WkonYErO.js → MermaidDiagram-CXG5tC6J.js} +19 -18
- package/dist/MermaidDiagram-CXG5tC6J.js.map +1 -0
- package/dist/{MultiActionButtonGroup-CxWH7yWK.js → MultiActionButtonGroup-DokHbPgM.js} +2 -2
- package/dist/{MultiActionButtonGroup-CxWH7yWK.js.map → MultiActionButtonGroup-DokHbPgM.js.map} +1 -1
- package/dist/{Navbar-B2UsolVU.js → Navbar-Liy1TPI7.js} +6 -6
- package/dist/{Navbar-B2UsolVU.js.map → Navbar-Liy1TPI7.js.map} +1 -1
- package/dist/PageHeader-Q3IpCnQd.js.map +1 -1
- package/dist/{PageToolbar-DnbFt14Q.js → PageToolbar-DExqEYGl.js} +2 -2
- package/dist/{PageToolbar-DnbFt14Q.js.map → PageToolbar-DExqEYGl.js.map} +1 -1
- package/dist/{Popconfirm-CILjmzKI.js → Popconfirm-5pBzT_HQ.js} +10 -11
- package/dist/{Popconfirm-CILjmzKI.js.map → Popconfirm-5pBzT_HQ.js.map} +1 -1
- package/dist/{RadioGroup-XFzFd1ti.js → RadioGroup-DXPbSj8P.js} +2 -2
- package/dist/{RadioGroup-XFzFd1ti.js.map → RadioGroup-DXPbSj8P.js.map} +1 -1
- package/dist/{Search-4Bxtt8hS.js → Search-5uQAiNIP.js} +2 -2
- package/dist/{Search-4Bxtt8hS.js.map → Search-5uQAiNIP.js.map} +1 -1
- package/dist/{SearchInput-f_oY9T4Z.js → SearchInput-D4UgAXJK.js} +3 -3
- package/dist/{SearchInput-f_oY9T4Z.js.map → SearchInput-D4UgAXJK.js.map} +1 -1
- package/dist/{SectionNav-BpJlisbT.js → SectionNav-OkKCjSA-.js} +3 -3
- package/dist/{SectionNav-BpJlisbT.js.map → SectionNav-OkKCjSA-.js.map} +1 -1
- package/dist/{Select-DpcgKqKB.js → Select-DV3Hak_l.js} +3 -4
- package/dist/Select-DV3Hak_l.js.map +1 -0
- package/dist/{Sidebar-Cm6I4dE1.js → Sidebar-D3cY1kha.js} +44 -20
- package/dist/Sidebar-D3cY1kha.js.map +1 -0
- package/dist/{Slider-pPC_3gz9.js → Slider-CRf-bB4y.js} +2 -2
- package/dist/{Slider-pPC_3gz9.js.map → Slider-CRf-bB4y.js.map} +1 -1
- package/dist/{Switch-ChfPKcTE.js → Switch-B0WdGSjz.js} +7 -7
- package/dist/{Switch-ChfPKcTE.js.map → Switch-B0WdGSjz.js.map} +1 -1
- package/dist/{TextInput-DHM6dHmn.js → TextInput-DH5SkbsE.js} +3 -3
- package/dist/{TextInput-DHM6dHmn.js.map → TextInput-DH5SkbsE.js.map} +1 -1
- package/dist/{ThemeProvider-DrQJtzpd.js → ThemeProvider-2RMdVGxO.js} +17 -12
- package/dist/{ThemeProvider-DrQJtzpd.js.map → ThemeProvider-2RMdVGxO.js.map} +1 -1
- package/dist/{Timeline-6btyJl4D.js → Timeline-BG5Xogxh.js} +11 -11
- package/dist/{Timeline-6btyJl4D.js.map → Timeline-BG5Xogxh.js.map} +1 -1
- package/dist/{Workbench-BzE-Vvd9.js → Workbench-UR2FBC7I.js} +3 -1
- package/dist/Workbench-UR2FBC7I.js.map +1 -0
- package/dist/{ZoomableSvg-BWnDkR61.js → ZoomableSvg-pooPb1Cu.js} +3 -3
- package/dist/{ZoomableSvg-BWnDkR61.js.map → ZoomableSvg-pooPb1Cu.js.map} +1 -1
- package/dist/editors.js +4 -4
- package/dist/flint.js +134 -8
- package/dist/flint.js.map +1 -1
- package/dist/index.d.ts +537 -135
- package/dist/index.js +40 -39
- package/dist/internal/blocks/AIKit.js +2 -2
- package/dist/internal/blocks/AuthLayout.js +118 -0
- package/dist/internal/blocks/AuthLayout.js.map +1 -0
- package/dist/internal/blocks/BrandEditor.js +1 -1
- package/dist/internal/blocks/ClipboardButton.js +1 -1
- package/dist/internal/blocks/ColorInput.js +1 -1
- package/dist/internal/blocks/Command.js +1 -1
- package/dist/internal/blocks/CopyField.js +1 -1
- package/dist/internal/blocks/DateInput.js +1 -1
- package/dist/internal/blocks/DateRangeInput.js +1 -1
- package/dist/internal/blocks/ExportMenu.js +1 -1
- package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +1 -1
- package/dist/internal/blocks/Form.js +1 -1
- package/dist/internal/blocks/FormGroup.js +1 -1
- package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
- package/dist/internal/blocks/MultiCombobox.js +107 -48
- package/dist/internal/blocks/MultiCombobox.js.map +1 -1
- package/dist/internal/blocks/NumberInput.js +1 -1
- package/dist/internal/blocks/PageToolbar.js +1 -1
- package/dist/internal/blocks/PasswordInput.js +2 -2
- package/dist/internal/blocks/SearchInput.js +1 -1
- package/dist/internal/blocks/SearchInputWithNavigation.js +2 -2
- package/dist/internal/blocks/SectionNav.js +1 -1
- package/dist/internal/blocks/TextInput.js +1 -1
- package/dist/internal/blocks/Textarea.js +1 -1
- package/dist/internal/blocks/TimeInput.js +2 -2
- package/dist/internal/components/Alert.js +1 -1
- package/dist/internal/components/Avatar.js +1 -1
- package/dist/internal/components/Badge.js +1 -1
- package/dist/internal/components/BrandLogo.js +1 -1
- package/dist/internal/components/Breadcrumb.js +1 -1
- package/dist/internal/components/Checkbox.js +1 -1
- package/dist/internal/components/Clipboard.js +1 -1
- package/dist/internal/components/CollapsiblePanel.js +1 -1
- package/dist/internal/components/Combobox.js +2 -2
- package/dist/internal/components/InputGroup.js +1 -1
- package/dist/internal/components/Kbd.js +1 -1
- package/dist/internal/components/Navbar.js +1 -1
- package/dist/internal/components/Popconfirm.js +1 -1
- package/dist/internal/components/RadioGroup.js +1 -1
- package/dist/internal/components/Search.js +1 -1
- package/dist/internal/components/Select.js +1 -1
- package/dist/internal/components/Sidebar.js +1 -1
- package/dist/internal/components/Slider.js +1 -1
- package/dist/internal/components/Switch.js +1 -1
- package/dist/internal/components/ThemeProvider.js +1 -1
- package/dist/internal/components/Timeline.js +1 -1
- package/dist/internal/components/Tooltip.js +1 -1
- package/dist/internal/components/Truncated.js +1 -1
- package/dist/internal/components/Workbench.js +1 -1
- package/dist/internal/components/ZoomableSvg.js +1 -1
- package/dist/internal/utils.js +2 -2
- package/dist/markdown-editor.js +29 -23
- package/dist/markdown-editor.js.map +1 -1
- package/dist/mermaid.js +1 -1
- package/dist/rjsf.js +22 -23
- package/dist/rjsf.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/testing.js +1 -1
- package/dist/{useColorSchemeState-klihG9-i.js → themeScopeContext-D7fSyb06.js} +16 -3
- package/dist/themeScopeContext-D7fSyb06.js.map +1 -0
- package/dist/{themeTokens-D70HeNVF.js → themeTokens-qP1-55O7.js} +37 -10
- package/dist/themeTokens-qP1-55O7.js.map +1 -0
- package/dist/{utils-B5Z52hYs.js → utils-DSvrhU8E.js} +6 -2
- package/dist/{utils-B5Z52hYs.js.map → utils-DSvrhU8E.js.map} +1 -1
- package/dist/vega.d.ts +1 -1
- package/dist/vega.js +3 -3
- package/dist/vega.js.map +1 -1
- package/dist/{vegaTheme-DfoEQhOy.js → vegaTheme-CSvFEMBl.js} +6 -6
- package/dist/vegaTheme-CSvFEMBl.js.map +1 -0
- package/package.json +12 -10
- package/src/styles.css +3 -0
- package/dist/AIKit-DDg5DBCG.js.map +0 -1
- package/dist/Badge-Ch26CXoP.js.map +0 -1
- package/dist/BrandLogo-Dmi7jo21.js.map +0 -1
- package/dist/Combobox-Cs_1pj2q.js.map +0 -1
- package/dist/Form-k6PH-em3.js.map +0 -1
- package/dist/InputGroup-BnLHY0eq.js.map +0 -1
- package/dist/Kbd-CvSM3D3-.js.map +0 -1
- package/dist/MermaidDiagram-WkonYErO.js.map +0 -1
- package/dist/Select-DpcgKqKB.js.map +0 -1
- package/dist/Sidebar-Cm6I4dE1.js.map +0 -1
- package/dist/Workbench-BzE-Vvd9.js.map +0 -1
- package/dist/themeTokens-D70HeNVF.js.map +0 -1
- package/dist/useColorSchemeState-klihG9-i.js.map +0 -1
- package/dist/vegaTheme-DfoEQhOy.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AIKit-DDg5DBCG.js","names":["renderVariantIcon"],"sources":["../src/blocks/AIKit/CollapsibleStepHeader.tsx","../src/blocks/AIKit/InlineStepDetail.tsx","../src/blocks/AIKit/InlineStepLabel.tsx","../src/blocks/AIKit/AnswerSummary.tsx","../src/blocks/AIKit/Markdown.tsx","../src/blocks/AIKit/MessageBubble.tsx","../src/blocks/AIKit/PlanApproval.tsx","../src/blocks/AIKit/PlanRewritingIndicator.tsx","../src/blocks/AIKit/PromptInputAction.tsx","../src/blocks/AIKit/PromptInputCommands.tsx","../src/blocks/AIKit/PromptInputSubmit.tsx","../src/blocks/AIKit/PromptInput.tsx","../src/blocks/AIKit/Question.tsx","../src/blocks/AIKit/QuestionBlock.tsx","../src/blocks/AIKit/SuggestedPrompt.tsx","../src/blocks/AIKit/ThinkingIndicator.tsx","../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/UsageStatsRing.tsx","../src/blocks/AIKit/UsageStats.tsx"],"sourcesContent":["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\nconst renderVariantIcon = (variant: Variant) => {\n if (variant === 'processing') {\n return <Loader2 className={cn(iconClasses, 'tw:animate-spin')} />;\n }\n if (variant === 'error') {\n return <XCircle className={iconClasses} />;\n }\n if (variant === 'dismissed') {\n return <XCircle className={cn(iconClasses, 'tw:text-neutral-500')} />;\n }\n return <CircleCheck className={iconClasses} />;\n};\n\nexport const CollapsibleStepHeader = ({\n isExpanded,\n onToggle,\n label,\n variant = 'success',\n}: Props) => {\n return (\n <button\n type=\"button\"\n aria-expanded={isExpanded}\n onClick={onToggle}\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 {/* Zero-width joiner 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","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 type { ReactNode } from 'react';\n\nimport { CircleCheck, Loader2, XCircle } from '../../icons';\n\ntype Variant = 'processing' | 'success' | 'error' | 'dismissed';\n\ntype Props = {\n variant: Variant;\n children: ReactNode;\n};\n\n// Status lives in the icon alone, and quietly: success/dismissed marks are\n// muted (they are the expected outcome, not news), the spinner is a shade\n// stronger (it reports active work), and only a real error takes the status\n// red. Fixed neutral-* greys were invisible in dark mode; tokens follow it.\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 = ({ variant, children }: Props) => (\n <div className=\"tw:flex tw:min-w-0 tw:items-center tw:gap-1\">\n {/* The icon can punch a gap in a connector drawn behind a run of steps: set\n `--inline-step-surface` on an ancestor to whatever paints behind, and the\n box masks the line across its own height. `relative` is what makes the\n mask work — the connector is absolutely positioned, so it paints above\n static content no matter what colour that content is. Unset the variable\n and the box stays transparent, so a step outside such a list is\n unchanged. */}\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 </div>\n </div>\n);\n\nexport type { Variant as InlineStepLabelVariant, Props as InlineStepLabelProps };\n","import { useState } from 'react';\n\nimport { CollapsibleStepHeader } from './CollapsibleStepHeader';\nimport { InlineStepDetail } from './InlineStepDetail';\nimport { InlineStepLabel } from './InlineStepLabel';\n\ntype AnswerItem = {\n question: string;\n answer?: string;\n};\n\ntype Variant = 'success' | 'dismissed';\n\ntype Props = {\n items: readonly AnswerItem[];\n variant?: Variant;\n noAnswerLabel?: string;\n};\n\nconst SECTION_LABELS: Record<Variant, string> = {\n success: 'Answered questions',\n dismissed: 'Dismissed questions',\n};\n\nexport const AnswerSummary = ({\n items,\n variant = 'success',\n noAnswerLabel = 'No answer',\n}: Props) => {\n const [isExpanded, setIsExpanded] = useState(false);\n const toggle = () => setIsExpanded((prev) => !prev);\n const count = items.length;\n const [firstItem] = items;\n const label = count === 1 && firstItem ? firstItem.question : `${count} questions`;\n\n return (\n <section className=\"tw:mt-4 tw:flex tw:flex-col tw:gap-4\" aria-label={SECTION_LABELS[variant]}>\n <CollapsibleStepHeader\n isExpanded={isExpanded}\n onToggle={toggle}\n variant={variant}\n label={label}\n />\n\n {isExpanded && (\n <div className=\"tw:flex tw:flex-col tw:gap-4 tw:pl-5\">\n {items.map(({ question, answer }, index) => (\n <div key={`${index}-${question}`} className=\"tw:flex tw:flex-col tw:gap-1\">\n <InlineStepLabel variant={variant}>{question}</InlineStepLabel>\n <InlineStepDetail>\n {answer && answer.length > 0 ? answer : noAnswerLabel}\n </InlineStepDetail>\n </div>\n ))}\n </div>\n )}\n </section>\n );\n};\n\nexport type {\n AnswerItem as AnswerSummaryItem,\n Props as AnswerSummaryProps,\n Variant as AnswerSummaryVariant,\n};\n","import { isValidElement, lazy, Suspense } from 'react';\nimport type { ComponentPropsWithoutRef, 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';\nimport { DiagramSkeleton } from '../DiagramShared/DiagramSkeleton';\n\n// beautiful-mermaid pulls elkjs (~442 kB gzip). Loading it on demand keeps it\n// out of the entry chunk of every app that touches the root barrel.\nconst MermaidDiagram = lazy(() =>\n import('@keboola/design/mermaid').then(\n (module) => ({ default: module.MermaidDiagram }),\n (error: unknown) => {\n // Typically a stale tab after a deploy. Log it so the swap to plain source\n // is not silent.\n console.error('[AIKit] failed to load the MermaidDiagram chunk', error);\n return {\n default: ({ code }: { code: string }) => (\n <pre>\n <code>{code}</code>\n </pre>\n ),\n };\n },\n ),\n);\n\n// Code surfaces are painted here rather than left to Tailwind Typography, whose\n// palette is pinned to light-mode values. The fill is the same `--muted` /\n// `--foreground` pair `styles.css` gives `.tw\\:prose blockquote` — the file's\n// idiom for an inset surface — so both follow the colour scheme and the brand.\n//\n// The colour has to be stated on `pre` and on inline `code` separately:\n// `[data-theme='dark'] .tw\\:prose` applies `prose-invert`, whose `code` rules are\n// `:where()`-wrapped, so these utilities win on specificity. Set only the fill\n// and dark mode pairs an inverted light text with it.\nconst proseClass =\n 'tw:prose tw:prose-sm tw:max-w-none tw:break-words tw:[&_pre]:bg-muted tw:[&_pre]:text-foreground tw:[&_:not(pre)>code]:bg-muted tw:[&_:not(pre)>code]:text-foreground tw:[&_:not(pre)>code]:rounded tw:[&_:not(pre)>code]:px-1 tw:[&_:not(pre)>code]:py-0.5 tw:[&_:not(pre)>code]:before:content-none tw:[&_:not(pre)>code]:after:content-none';\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/**\n * The plugins this renderer always runs.\n *\n * - GFM is part of its contract: tables route through the design `Table`, and autolinks and\n * task lists are what an assistant answer is written in.\n * - A caller's own plugins are appended to these, never substituted for them.\n */\nconst baseRemarkPlugins: NonNullable<Options['remarkPlugins']> = [remarkGfm];\n\n// react-markdown passes a hast `node` to every component; strip it before\n// spreading the rest onto a DOM element.\nconst baseComponents: Components = {\n // Handle mermaid at the `pre` level: react-markdown renders fenced blocks as\n // `<pre><code class=\"language-…\">`, so a diagram (a block `<div>`) must replace\n // the whole `<pre>` — returning it from the `code` override would nest a block\n // element inside `<pre><code>` (invalid HTML).\n pre({ children, ...props }: ComponentPropsWithoutRef<'pre'> & ExtraProps) {\n const child = Array.isArray(children) ? children[0] : children;\n if (getLanguage(child) === 'mermaid') {\n const code = getText(child).replace(/\\n$/, '');\n if (!code.trim()) return null;\n return (\n <Suspense fallback={<DiagramSkeleton />}>\n <MermaidDiagram code={code} />\n </Suspense>\n );\n }\n const { node: _node, ...rest } = props;\n const code = getText(child).replace(/\\n$/, '');\n // Wrap so the copy button can reveal on hover/focus, anchored to the block.\n return (\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}>{children}</pre>\n </div>\n );\n },\n // Open absolute http(s) links in a new tab with a safe `rel`; leave relative\n // and anchor links to default in-page navigation.\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 // Route GFM tables through the design `Table` so they match the rest of the\n // system; `tw:not-prose` opts the table out of prose typography overrides.\n table({ className, ...props }: ComponentPropsWithoutRef<'table'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return (\n <div className=\"tw:not-prose tw:my-4\">\n <Table bordered className={cn('tw:!mb-0', className)} {...rest} />\n </div>\n );\n },\n thead(props: ComponentPropsWithoutRef<'thead'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return <Table.Header {...rest} />;\n },\n tbody(props: ComponentPropsWithoutRef<'tbody'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return <Table.Body {...rest} />;\n },\n tr(props: ComponentPropsWithoutRef<'tr'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return <Table.Row {...rest} />;\n },\n th(props: ComponentPropsWithoutRef<'th'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return <Table.Head {...rest} />;\n },\n td(props: ComponentPropsWithoutRef<'td'> & ExtraProps) {\n const { node: _node, ...rest } = props;\n return <Table.Cell {...rest} />;\n },\n};\n\ntype Props = {\n /** Markdown source (GFM: tables, task lists, strikethrough, autolinks). Tables\n * render through the design `Table`; fenced ```mermaid blocks render via\n * `MermaidDiagram`; other fenced blocks — including ```flint, deliberately,\n * as this is the reduced-capability renderer — get a hover copy button. */\n children: string;\n className?: string;\n /**\n * Remark plugins run after the built-in GFM one.\n *\n * - Appended to the built-ins, so GFM keeps working whatever a caller adds.\n * - The seam for an app's own inline syntax — an annotation the agent emits alongside a\n * link, say — which is app product knowledge and does not belong in this package.\n * - Hold it in a module constant. react-markdown re-parses on every render, so this\n * component is meant to be memoised by its caller, and a literal built during render\n * defeats that.\n */\n remarkPlugins?: NonNullable<Options['remarkPlugins']>;\n /**\n * Element renderers layered over the built-in ones.\n *\n * - Merged by key, and an override **replaces** that element's renderer rather than\n * wrapping it: a `table` override loses the design `Table`, an `a` override loses the\n * new-tab treatment for absolute links. Restate what you still want.\n * - Hold it in a module constant, for the same reason as `remarkPlugins`.\n */\n components?: Components;\n};\n\n/**\n * Read-only GFM Markdown renderer with design-token typography. Pair with\n * `MessageBubble` to render an assistant message body. Code blocks expose a\n * copy button, so mount a `TooltipProvider` once at the app root.\n */\nexport const Markdown = ({\n children,\n className,\n remarkPlugins,\n components: componentOverrides,\n}: Props) => {\n return (\n <div data-prose className={cn(proseClass, className)}>\n <ReactMarkdown\n remarkPlugins={\n remarkPlugins === undefined ? baseRemarkPlugins : [...baseRemarkPlugins, ...remarkPlugins]\n }\n components={\n componentOverrides === undefined\n ? baseComponents\n : { ...baseComponents, ...componentOverrides }\n }\n >\n {children}\n </ReactMarkdown>\n </div>\n );\n};\n","import type { ComponentProps, PropsWithChildren, ReactNode } from 'react';\nimport { cva } from 'class-variance-authority';\n\nimport type { Avatar } from '../../components/Avatar';\n\n// No per-message avatar. In a narrow panel a 30px portrait beside every turn\n// spends width on identity the reader already has — there are two participants\n// — and pushes the bubble into an L-shape beside it. Alignment carries the turn.\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 // Prose supplies its own rhythm between blocks, so a large gap here stacks\n // on top of it and reads as slack rather than structure.\n 'tw:gap-3',\n 'tw:break-words',\n 'tw:leading-relaxed',\n 'tw:text-foreground',\n // Hooks on `data-prose`, not the `tw:prose` class — Tailwind scans raw file\n // bytes, so a `\\:` escape in a TS string reaches the generator 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 // The cap is a share of the column, not a fixed width: it is what\n // leaves a gutter on the left, and that gutter is the whole reason\n // the bubble reads as one side of a conversation. A fixed 640px\n // never engages in a docked panel, and a left margin cannot stand in\n // for it — `w-fit` sizes to the space it has before the margin\n // applies, so the margin pushes the bubble past the column instead\n // of insetting it. The absolute term stops a fullscreen panel from\n // running a line of someone's own words 700px wide.\n 'tw:max-w-[min(85%,40rem)]',\n 'tw:w-fit',\n 'tw:bg-muted',\n // Tighter vertically than horizontally: a short message padded evenly\n // on all four sides reads as a block, not as something someone said.\n // The radius comes down with it — a 16px corner on a one-line bubble\n // is most of its height.\n 'tw:px-3',\n 'tw:py-2',\n 'tw:rounded-xl',\n 'tw:overflow-hidden',\n 'tw:break-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 /** @deprecated No avatar is rendered; accepted so existing call sites keep compiling. */\n user?: ComponentProps<typeof Avatar>['user'];\n} & PropsWithChildren;\n\nexport const MessageBubble = ({ variant, children, actions, createdAt }: Props) => {\n return (\n <div className={containerClasses({ variant })} data-testid={`chat-message-${variant}`}>\n <div className={stackClasses({ variant })}>\n {/* The timestamp is reachable on the user's own bubble — where the avatar\n that used to carry it sat. Deliberately not on the assistant's: a\n native tooltip fires from anywhere in the body after a hover pause,\n and an answer's body is full of tables and code it would cover. */}\n <div\n className={contentClasses({ variant })}\n title={variant === 'user' ? createdAt : undefined}\n >\n {children}\n </div>\n {actions}\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\ntype PlanApprovalStatus = 'pending' | 'approved' | 'dismissed' | 'changes-requested';\n\ntype PlanApprovalProps = {\n status: PlanApprovalStatus;\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 StatusPill = ({\n status,\n pendingLabel,\n approvedLabel,\n dismissedLabel,\n changesRequestedLabel,\n}: {\n status: PlanApprovalStatus;\n pendingLabel: string;\n approvedLabel: string;\n dismissedLabel: string;\n changesRequestedLabel: string;\n}) => {\n if (status === 'approved') {\n return (\n <Badge color=\"green\" variant=\"pill\" className=\"tw:normal-case tw:tracking-normal\">\n {approvedLabel}\n </Badge>\n );\n }\n if (status === 'dismissed') {\n return (\n <Badge color=\"gray\" variant=\"pill\" className=\"tw:normal-case tw:tracking-normal\">\n {dismissedLabel}\n </Badge>\n );\n }\n if (status === 'changes-requested') {\n return (\n <Badge color=\"blue\" variant=\"pill\" className=\"tw:normal-case tw:tracking-normal\">\n {changesRequestedLabel}\n </Badge>\n );\n }\n return (\n <Badge color=\"green\" variant=\"pill\" className=\"tw:normal-case tw:tracking-normal\">\n {pendingLabel}\n </Badge>\n );\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-neutral-100 tw:bg-white 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 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 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 toggleExpanded = () => {\n const next = !isExpanded;\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 <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-neutral-50',\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\n status={status}\n pendingLabel={pendingPillLabel}\n approvedLabel={approvedPillLabel}\n dismissedLabel={dismissedPillLabel}\n changesRequestedLabel={changesRequestedPillLabel}\n />\n {stepCount != null && stepCount > 0 && (\n <span className=\"tw:text-xs tw:leading-4 tw:text-neutral-500\">\n {stepCountLabel(stepCount)}\n </span>\n )}\n </div>\n <p className=\"tw:m-0 tw:text-base tw:font-semibold tw:leading-6 tw:text-neutral-800\">\n {title}\n </p>\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-neutral-100 tw:px-4 tw:pt-4 tw:text-sm tw:text-neutral-700',\n isExpanded && canShowPlanBody ? 'tw:pb-4' : 'tw:pb-2',\n )}\n >\n {summary}\n </div>\n )}\n\n {isExpanded && canShowPlanBody && (\n <div className=\"tw:max-h-[400px] tw:overflow-y-auto tw:border-0 tw:border-t tw:border-solid tw:border-neutral-100 tw:bg-white tw:p-4 tw:text-sm tw:text-neutral-700\">\n {planBody}\n </div>\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-neutral-100 tw:bg-white tw:px-4 tw:py-3',\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\n status={status}\n pendingLabel={pendingPillLabel}\n approvedLabel={approvedPillLabel}\n dismissedLabel={dismissedPillLabel}\n changesRequestedLabel={changesRequestedPillLabel}\n />\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 <FullScreenModalBody className=\"tw:bg-white tw:px-6 tw:py-4\">\n <div className=\"tw:mx-auto tw:w-full tw:max-w-[800px] tw:text-sm tw:text-neutral-700\">\n {planBody}\n </div>\n </FullScreenModalBody>\n {(showChangeRequestForm || showActions) && (\n <div className=\"tw:shrink-0 tw:border-0 tw:border-t tw:border-solid tw:border-neutral-100 tw:bg-white\">\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","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 type { ReactNode } from 'react';\n\nimport { Truncated } from '../../components/Truncated';\nimport { cn } from '../../utils';\nimport { Command } from '../Command';\n\nexport type PromptCommand = {\n label: string;\n value: string;\n description?: string;\n icon?: ReactNode;\n group: string;\n};\n\ntype Props = {\n items: PromptCommand[];\n open: boolean;\n onSelect: (value: string) => void;\n filterValue: string;\n children: ReactNode;\n};\n\nexport const PromptInputCommands = ({ items, open, onSelect, filterValue, children }: Props) => {\n const filtered = filterValue\n ? items.filter(\n (item) =>\n item.label.toLowerCase().includes(filterValue.toLowerCase()) ||\n item.value.toLowerCase().includes(filterValue.toLowerCase()),\n )\n : items;\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 return (\n <Command loop className=\"tw:relative\" shouldFilter={false}>\n {open && (\n <div\n className={cn(\n 'tw:absolute tw:bottom-full tw:left-0 tw:right-0 tw:z-50 tw:mb-1',\n 'tw:rounded-md tw:border tw:border-border tw:bg-popover tw:text-popover-foreground tw:shadow-lg',\n )}\n >\n {filtered.length === 0 ? (\n <div className=\"tw:px-4 tw:py-3 tw:text-center tw:text-sm tw:text-muted-foreground\">\n No commands found\n </div>\n ) : (\n <Command.List viewPortClassName=\"tw:max-h-80\">\n {Object.entries(groups).map(([groupName, groupItems]) => (\n <Command.Group key={groupName} heading={groupName}>\n {groupItems.map((item) => (\n <Command.Item\n key={item.value}\n value={item.value}\n icon={item.icon}\n onSelect={() => onSelect(item.value)}\n >\n <div className=\"tw:flex tw:min-w-0 tw:flex-1 tw:flex-col\">\n <span>{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, 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// Icon-only button: the tooltip is visual only, so the accessible name must be\n// set separately per status to match what the button actually does (see\n// PromptInput's handleSubmit: ready->onSend, streaming->onAbort, interrupted->onContinue).\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 up and to the right of the\n // glyph box — its centroid measures ~1.2px right and ~1.3px high at 16px —\n // so a box-centred Send reads as off-centre inside a circle. The nudge pulls\n // the mass back toward the middle; the symmetric pause/play icons need none.\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 // The only filled control in the composer, so the one button that\n // submits stays distinct from the several beside it that do not.\n //\n // - Fill is Kai's gradient (`aigradient-600`) — the same sweep the\n // field's focus border paints, so focus and send read as one family.\n // - `variant=\"primary\"` still supplies the white foreground, focus ring\n // and disabled semantics; the gradient covers its background colour.\n // - Disabled until there is content, so the composer shows ready-or-not\n // without needing a label.\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:from-[#61E4FF] tw:via-[#1F8FFF] tw:to-[#7C5CFF]',\n 'tw:hover:not-disabled:brightness-110',\n )}\n >\n {/* Suppress the child icon while isLoading — Button already renders\n the spinner; rendering both would double-stack glyphs. */}\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 {\n type ChangeEventHandler,\n type ComponentProps,\n type ComponentRef,\n type FormEventHandler,\n type KeyboardEvent,\n type KeyboardEventHandler,\n type MouseEventHandler,\n type ReactNode,\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 { TooltipProvider } from '../../components/Tooltip';\nimport { cn } from '../../utils';\n\nimport { PromptInputAction } from './PromptInputAction';\nimport type { PromptCommand } from './PromptInputCommands';\nimport { PromptInputCommands } from './PromptInputCommands';\nimport { PromptInputSubmit } from './PromptInputSubmit';\n\nconst CMDK_HIJACKED_KEYS = new Set(['ArrowUp', 'ArrowDown', 'Home', 'End', 'Enter']);\n\n// Whether cmdk would actually act on this keystroke, and so whether the guard\n// below still needs to hide it from the Command root.\n//\n// cmdk acts on every key in CMDK_HIJACKED_KEYS, modified or not — the arrows\n// branch on metaKey (jump to first/last) and altKey (jump to the adjacent\n// group), and Home/End preventDefault unconditionally. `Enter` is the sole\n// exception: its branch reads no modifier at all, so a modified Enter is the\n// only keystroke the Command root would ignore.\nconst isCmdkNavigation = (event: KeyboardEvent<HTMLTextAreaElement>) =>\n event.key !== 'Enter' || !(event.metaKey || event.ctrlKey || event.altKey);\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, always on: the composer is the one place the reader\n // addresses Kai, and the gradient is what marks it as Kai's rather than the\n // page's. Drawn by filling the interior over a gradient background so only\n // the 2px edge shows through — `bg-origin-border` puts the gradient under\n // the border box, and the inset shadow paints the card back over everything\n // inside it.\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 the ring alone. The edge is already the loudest thing the\n // control can be, so focus cannot say it louder — it says it wider, and the\n // 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 default: ['tw:flex-col', 'tw:pt-3', 'tw:pb-2'],\n inline: ['tw:flex-row', 'tw:py-3', 'tw:items-center'],\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 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 variant?: 'default' | 'inline';\n disableSubmit?: boolean;\n commands?: PromptCommand[];\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 disabled,\n disableSubmit,\n value = '',\n onValueChange,\n status = 'ready',\n maxRows = 6,\n minRows,\n commands,\n autoFocus,\n ...textareaProps\n}: Props) => {\n const defaultMinRows = variant === 'inline' ? 1 : 2;\n const isDisabled =\n (disabled || disableSubmit || !value.trim()) &&\n status !== 'streaming' &&\n status !== 'interrupted';\n\n const textareaId = useId();\n const textareaRef = useRef<ComponentRef<'textarea'>>(null);\n const [dismissedValue, setDismissedValue] = useState<string | null>(null);\n\n // `autoFocus` is applied imperatively, never as the DOM attribute.\n // - The attribute focuses with ancestor scrolling: the browser scrolls every\n // scrollable ancestor to reveal the element.\n // - A composer can mount inside a panel that is still sliding in (kbc-ui's Kai\n // rail); scrolling toward its off-canvas box drags the whole page sideways.\n // - `preventScroll` grants the focus without the scroll. Mount-only, matching\n // the attribute's semantics.\n const autoFocusRef = useRef(autoFocus);\n useEffect(() => {\n if (autoFocusRef.current) textareaRef.current?.focus({ preventScroll: true });\n }, []);\n\n // Esc dismisses the menu for the value at that moment; once the value moves away\n // from it, clear the dismissal so the menu can reopen if it re-matches the slash\n // shape. Done during render rather than in an effect, and keyed off\n // `dismissedValue` so state only updates while a dismissal is active — no extra\n // render per keystroke.\n if (dismissedValue !== null && value !== dismissedValue) setDismissedValue(null);\n\n const hasCommands = !!commands && commands.length > 0;\n const valueLooksLikeSlashCommand = value.startsWith('/') && !/\\s/.test(value);\n const commandsOpen = hasCommands && valueLooksLikeSlashCommand && value !== dismissedValue;\n const slashFilter = commandsOpen ? value.slice(1) : '';\n\n const handleSubmit = () => {\n if (isDisabled) return;\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 onValueChange?.(event.target.value);\n };\n\n const handleCommandSelect = (commandValue: string) => {\n onValueChange?.(commandValue + ' ');\n textareaRef.current?.focus();\n };\n\n const handleOnKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (event) => {\n if (commandsOpen) {\n if (event.key === 'Escape') {\n event.preventDefault();\n setDismissedValue(value);\n return;\n }\n // Don't preventDefault — let cmdk handle ArrowUp/Down/Enter via bubbling\n if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'Enter') {\n return;\n }\n } else if (hasCommands && CMDK_HIJACKED_KEYS.has(event.key) && isCmdkNavigation(event)) {\n // Keep these from bubbling to the always-mounted cmdk Command root, whose\n // keydown handler preventDefaults them and breaks multiline editing.\n // Keystrokes cmdk ignores (e.g. Cmd+Enter, Alt+Enter) must still reach\n // document-level app hotkeys, so they are deliberately not stopped here.\n event.stopPropagation();\n }\n\n if (event.key === 'Enter' && !event.shiftKey && !event.ctrlKey && !event.metaKey) {\n event.preventDefault();\n if (status !== 'streaming') handleSubmit();\n }\n };\n\n const handleOnMouseDown: MouseEventHandler<HTMLFormElement> = (event) => {\n // don't prevent default if the target is the textarea itself\n if (event.target === textareaRef.current) return;\n\n event.preventDefault();\n textareaRef.current?.focus();\n };\n\n const formEl = (\n <div className={wrapperVariants({ variant })}>\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 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 )}\n >\n {prefix && <div className=\"tw:flex tw:items-center\">{prefix}</div>}\n\n <label htmlFor={textareaId} className=\"tw:sr-only\">\n Prompt Input\n </label>\n <TextareaAutosize\n {...textareaProps}\n disabled={disabled}\n minRows={minRows ?? defaultMinRows}\n maxRows={maxRows}\n id={textareaId}\n ref={textareaRef}\n value={value}\n onChange={handleOnChange}\n onKeyDown={handleOnKeyDown}\n className={cn(\n 'tw:resize-none',\n 'tw:outline-hidden',\n 'tw:w-full',\n 'tw:px-2',\n 'tw:bg-transparent',\n\n // font\n disabled ? '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\n <div\n className={cn(\n 'tw:flex tw:items-center tw:gap-4',\n variant === 'inline' ? 'tw:items-end' : 'tw:items-center',\n )}\n >\n {suffix}\n <PromptInputSubmit disabled={isDisabled} status={status} />\n </div>\n </form>\n </div>\n );\n\n return (\n <TooltipProvider>\n {hasCommands ? (\n <PromptInputCommands\n items={commands ?? []}\n open={commandsOpen}\n onSelect={handleCommandSelect}\n filterValue={slashFilter}\n >\n {formEl}\n </PromptInputCommands>\n ) : (\n formEl\n )}\n </TooltipProvider>\n );\n};\n\nPromptInput.Action = PromptInputAction;\n","import { type KeyboardEvent, type ReactNode, useState } from 'react';\n\nimport { Button } from '../../components/Button';\nimport { Checkbox } from '../../components/Checkbox';\nimport { Progress } from '../../components/Progress';\nimport { Tooltip } from '../../components/Tooltip';\nimport { 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};\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 showSkip?: boolean;\n onSkip?: () => void;\n onClose?: () => void;\n onNext?: () => void;\n submitTooltip?: ReactNode;\n onPrevious?: () => void;\n currentStep?: number;\n totalSteps?: number;\n renderPreview?: (content: string) => ReactNode;\n className?: string;\n};\n\nconst handleKeyDown = (callback: () => void) => (e: KeyboardEvent) => {\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 showSkip = true,\n onSkip,\n onClose,\n onNext,\n submitTooltip,\n onPrevious,\n currentStep,\n totalSteps,\n renderPreview,\n className,\n}: Props) => {\n const [isCustomExpanded, setIsCustomExpanded] = useState(false);\n const isCustomSelected = isCustomExpanded || customAnswer.length > 0;\n const hasSteps = currentStep != null && totalSteps != null;\n const progressValue = hasSteps ? (currentStep / totalSteps) * 100 : 0;\n const isFirstStep = currentStep === 1;\n const isLastStep = hasSteps && currentStep === totalSteps;\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 onCustomAnswerChange?.('');\n onSelectionChange?.([optionId]);\n }\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 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 return (\n <div\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',\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) => (\n <div\n key={option.id}\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:hover:bg-accent\"\n onClick={() => handleOptionToggle(option.id)}\n onKeyDown={handleKeyDown(() => handleOptionToggle(option.id))}\n role=\"button\"\n tabIndex={0}\n data-testid={`question-option-${option.id}`}\n >\n {multiSelect && (\n <Checkbox\n checked={selectedOptionIds.includes(option.id)}\n onCheckedChange={() => handleOptionToggle(option.id)}\n onClick={(e) => e.stopPropagation()}\n className=\"tw:shrink-0\"\n />\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 <span className=\"tw:text-sm tw:font-medium tw:leading-none\">{option.label}</span>\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 {showCustomAnswer && (\n <div className=\"tw:flex tw:flex-col tw:gap-2\">\n <div\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:hover:bg-accent\"\n onClick={handleCustomRowClick}\n onKeyDown={handleKeyDown(handleCustomRowClick)}\n role=\"button\"\n tabIndex={0}\n >\n {/* Multi-select shows a checkbox alongside the option checkboxes.\n Single-select options auto-advance and carry no indicator, so\n \"Other\" is a plain clickable row that reveals the input below. */}\n {multiSelect && (\n <Checkbox\n checked={isCustomSelected}\n onCheckedChange={handleCustomToggle}\n onClick={(e) => e.stopPropagation()}\n className=\"tw:shrink-0\"\n />\n )}\n <span\n className={cn(\n '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 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 sizing=\"small\"\n testId=\"question-custom\"\n />\n </div>\n )}\n </div>\n </div>\n\n <div className=\"tw:flex tw:flex-col\">\n {hasSteps && <Progress size=\"sm\" value={progressValue} className=\"tw:rounded-none\" />}\n\n <div\n className={cn(\n 'tw:flex tw:items-center tw:justify-end tw:gap-4 tw:px-4 tw:py-3',\n !hasSteps && 'tw:border-0 tw:border-t tw:border-solid tw:border-border',\n )}\n >\n {hasSteps && (\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={onNext}\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 {showSkip && onSkip && (\n <Button\n variant=\"outline\"\n size=\"small\"\n onClick={onSkip}\n data-testid=\"question-skip-button\"\n >\n Skip\n </Button>\n )}\n {(multiSelect || isCustomSelected) &&\n (submitTooltip ? (\n <Tooltip tooltip={submitTooltip} placement=\"top\" triggerAsChild>\n <Button\n variant=\"primary\"\n size=\"small\"\n onClick={onNext}\n data-testid=\"question-next-button\"\n >\n {isLastStep ? 'Submit' : 'Next'}\n </Button>\n </Tooltip>\n ) : (\n <Button\n variant=\"primary\"\n size=\"small\"\n onClick={onNext}\n data-testid=\"question-next-button\"\n >\n {isLastStep ? 'Submit' : 'Next'}\n </Button>\n ))}\n </div>\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 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 className?: string;\n};\n\nexport const SuggestedPrompt = ({ label, disabled, onClick, icon, className }: Props) => {\n return (\n <button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'tailwindcss-preflight tw:flex tw:items-center tw:justify-start tw:gap-2.5 tw:whitespace-nowrap',\n 'tw:rounded-lg tw:px-3 tw:py-2',\n 'tw:text-left tw:text-sm tw:font-medium tw:text-foreground',\n 'tw:transition-colors tw:not-disabled:hover:bg-accent',\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-50',\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 <div className=\"tw:whitespace-normal tw:text-left\">{label}</div>\n </button>\n );\n};\n","import { Loader2 } from '../../icons';\n\ntype ThinkingIndicatorProps = {\n label?: string;\n};\n\nexport const ThinkingIndicator = ({ label = 'Thinking...' }: ThinkingIndicatorProps) => {\n return (\n // Same quiet chrome as the step rows it precedes (muted ink, no italic),\n // so the hand-off from \"Thinking...\" to the first step is seamless.\n <div className=\"tw:flex tw:items-center tw:gap-1.5\" data-testid=\"chat-thinking-indicator\">\n <Loader2 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","import { type ReactNode, useEffect } from 'react';\n\nimport { Badge } from '../../../components/Badge';\nimport { Button } from '../../../components/Button';\nimport { cn } from '../../../utils';\n\ntype ToolCallApprovalStatus = 'pending' | 'approved' | 'rejected' | 'expired';\n\ntype ToolCallApprovalProps = {\n /** The tool being called (e.g. `run_sql`). Rendered as a monospace tag. */\n toolName: string;\n /** Human-readable summary of what the tool will do. */\n title?: ReactNode;\n status: ToolCallApprovalStatus;\n onApprove?: () => void;\n onReject?: () => void;\n /** App-rendered detail — a diff, a `ToolCallChip`, a chart, arguments. */\n children?: ReactNode;\n /**\n * Replaces the default Approve/Reject buttons in the pending state. Use when\n * the call needs bespoke controls (e.g. an inline reason field).\n */\n actions?: ReactNode;\n isSubmitting?: boolean;\n /**\n * Opt into `Enter` = approve / `Escape` = reject while pending. Off by\n * default so the shortcuts never fire unexpectedly in a busy chat.\n */\n enableShortcuts?: boolean;\n approveLabel?: string;\n rejectLabel?: string;\n className?: string;\n};\n\nconst STATUS_BADGE: Record<\n ToolCallApprovalStatus,\n { label: string; color: 'blue' | 'green' | 'red' | 'gray' }\n> = {\n pending: { label: 'Needs approval', color: 'blue' },\n approved: { label: 'Approved', color: 'green' },\n rejected: { label: 'Rejected', color: 'red' },\n expired: { label: 'Expired', color: 'gray' },\n};\n\n/**\n * Per-tool-call approve/reject frame — the granular sibling of `PlanApproval`\n * (which approves a whole plan). Chrome + status + actions only: the app\n * renders the call detail as `children` and owns the SDK/permission wiring.\n */\nexport const ToolCallApproval = ({\n toolName,\n title,\n status,\n onApprove,\n onReject,\n children,\n actions,\n isSubmitting = false,\n enableShortcuts = false,\n approveLabel = 'Approve',\n rejectLabel = 'Reject',\n className,\n}: ToolCallApprovalProps) => {\n const isPending = status === 'pending';\n const hasCustomActions = actions != null;\n const showDefaultActions = isPending && !hasCustomActions && Boolean(onApprove || onReject);\n // Custom actions, like the defaults, only make sense while a decision is\n // still pending — never leave controls visible in a terminal state.\n const showActions = isPending && (showDefaultActions || hasCustomActions);\n const badge = STATUS_BADGE[status];\n\n useEffect(() => {\n if (!enableShortcuts || !isPending || isSubmitting) return;\n\n const isEditableTarget = (target: EventTarget | null) => {\n if (!(target instanceof HTMLElement)) return false;\n return (\n target.isContentEditable ||\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.tagName === 'SELECT'\n );\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n // Ignore key-repeat and keystrokes typed into a field.\n if (event.repeat || event.defaultPrevented || isEditableTarget(event.target)) return;\n\n if (\n event.key === 'Enter' &&\n !event.shiftKey &&\n !event.ctrlKey &&\n !event.metaKey &&\n onApprove\n ) {\n event.preventDefault();\n onApprove();\n } else if (event.key === 'Escape' && onReject) {\n event.preventDefault();\n onReject();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [enableShortcuts, isPending, isSubmitting, onApprove, onReject]);\n\n return (\n <section\n data-testid=\"tool-call-approval\"\n data-status={status}\n aria-label={typeof title === 'string' ? title : toolName}\n className={cn(\n 'tw:flex tw:w-full tw:max-w-[800px] tw:flex-col tw:gap-3 tw:overflow-hidden tw:rounded-xl tw:border tw:border-solid tw:border-border tw:bg-muted tw:p-4',\n className,\n )}\n >\n <div className=\"tw:flex tw:items-center tw:gap-2\">\n <Badge color={badge.color} variant=\"pill\" className=\"tw:normal-case tw:tracking-normal\">\n {badge.label}\n </Badge>\n <code className=\"tw:rounded tw:bg-background tw:px-1.5 tw:py-0.5 tw:font-mono tw:text-xs tw:text-foreground\">\n {toolName}\n </code>\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\n {children}\n\n {showActions && (\n <div className=\"tw:flex tw:items-center tw:justify-end tw:gap-2 tw:overflow-x-auto\">\n {actions ?? (\n <>\n {onReject && (\n <Button\n variant=\"outline\"\n size=\"small\"\n onClick={onReject}\n disabled={isSubmitting}\n className=\"tw:shrink-0 tw:whitespace-nowrap\"\n >\n {rejectLabel}\n </Button>\n )}\n {onApprove && (\n <Button\n variant=\"primary\"\n size=\"small\"\n onClick={onApprove}\n disabled={isSubmitting}\n className=\"tw:shrink-0 tw:whitespace-nowrap\"\n >\n {approveLabel}\n </Button>\n )}\n </>\n )}\n </div>\n )}\n </section>\n );\n};\n\nexport type { ToolCallApprovalStatus, 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-accent',\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, ChevronUp, 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// The header stays a neutral band for routine states — a filled saturated bar\n// made every successful tool call shout. Status is carried by the icon and the\n// label tint; the two states that ask for the user's attention (a pending\n// confirmation, a failure) additionally get a soft tint of their status colour\n// so they catch peripheral vision without shouting.\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, never two: a tinted header is already\n // bounded by where its wash stops, so it takes no rule — the hairline\n // belongs to the untinted states, which would otherwise have no edge.\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 <span\n data-testid=\"tool-status-text\"\n className={cn('tw:truncate tw:pr-0.5 tw:text-xs tw:font-medium', statusInk[status])}\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 (isCollapsed ? (\n <ChevronDown className=\"tw:size-3.5 tw:shrink-0 tw:text-muted-foreground\" />\n ) : (\n <ChevronUp className=\"tw:size-3.5 tw:shrink-0 tw:text-muted-foreground\" />\n ))}\n </div>\n )}\n </div>\n );\n};\n\nexport type { Props as ToolCallStatusHeaderProps, ToolCallStatus };\n","/** Clamp a percentage to 0–100 and normalize non-finite input to 0. */\nexport const clampPercentage = (value: number) =>\n Number.isFinite(value) ? Math.min(100, Math.max(0, value)) : 0;\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 className=\"tw:stroke-neutral-400 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 /**\n * `true` (or `'error'`) renders the red corner badge; `'warning'` renders\n * it amber for an approaching-limit state that isn't at-limit yet.\n */\n alert?: boolean | 'warning' | 'error';\n children: ReactNode;\n className?: string;\n /**\n * Accessible name for the trigger. Defaults to a value-aware label so\n * screen-reader users get the same information the ring conveys visually.\n */\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};\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}: 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>\n <HoverCard.Trigger asChild>\n <span\n aria-label={ariaLabel ?? defaultLabel}\n className={cn(\n 'tw:relative tw:inline-flex tw:size-8 tw:items-center tw:justify-center',\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 </span>\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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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Badge-Ch26CXoP.js","names":[],"sources":["../src/components/Badge/BadgeAddon.tsx","../src/components/Badge/BadgeButton.tsx","../src/components/Badge/BadgeLabel.tsx","../src/components/Badge/styles.ts","../src/components/Badge/BadgeRoot.tsx","../src/components/Badge/Badge.tsx"],"sourcesContent":["import type { ComponentProps } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '../../utils';\n\nconst addonVariants = cva(\n [\n 'tw:flex',\n 'tw:items-center',\n 'tw:shrink-0',\n 'tw:bg-inherit',\n 'tw:self-stretch',\n 'tw:px-1',\n 'tw:has-[button]:px-0',\n 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-3',\n ],\n {\n defaultVariants: {\n align: 'inline-end',\n variant: 'inline',\n },\n variants: {\n align: {\n 'inline-start': ['tw:order-first'],\n 'inline-end': ['tw:order-last'],\n },\n variant: {\n inline: [],\n floating: [\n 'tw:hidden',\n 'tw:group-hover/badge:flex',\n\n 'tw:absolute',\n 'tw:top-0',\n 'tw:bottom-0',\n 'tw:focus-within:flex',\n ],\n },\n },\n compoundVariants: [\n { variant: 'floating', align: 'inline-end', className: ['tw:right-0'] },\n { variant: 'floating', align: 'inline-start', className: ['tw:left-0'] },\n ],\n },\n);\n\ntype Props = ComponentProps<'div'> & VariantProps<typeof addonVariants>;\n\nexport const BadgeAddon = ({\n ref,\n align = 'inline-end',\n variant = 'inline',\n className,\n ...rest\n}: Props) => (\n <div\n {...rest}\n ref={ref}\n data-align={align}\n data-variant={variant}\n className={cn(addonVariants({ align, variant, className }))}\n />\n);\n","import type { ComponentProps } from 'react';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentProps<'button'>;\n\nexport const BadgeButton = ({ ref, className, type = 'button', children, ...rest }: Props) => (\n <button\n {...rest}\n ref={ref}\n type={type}\n className={cn(\n 'tailwindcss-preflight',\n\n 'tw:inline-flex',\n 'tw:items-center',\n 'tw:justify-center',\n 'tw:cursor-pointer',\n\n 'tw:bg-inherit',\n 'tw:text-inherit',\n\n 'tw:hover:brightness-95',\n 'tw:px-1',\n // Default sizing for Lucide-icon children (which ship at 24×24); keeps\n // the visual baseline aligned with the previous FA-icon API and other\n // icon-wrapper components (ItemIcon, SidebarMenuIcon).\n 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-3',\n className,\n )}\n >\n {children}\n </button>\n);\n","import type { ComponentProps } from 'react';\nimport { Slot } from '@radix-ui/react-slot';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentProps<'span'> & {\n asChild?: boolean;\n};\n\nexport const BadgeLabel = ({ ref, className, asChild = false, ...rest }: Props) => {\n const Comp = asChild ? Slot : 'span';\n return (\n <Comp\n {...rest}\n ref={ref}\n data-slot=\"badge-label\"\n className={cn(\n 'tw:max-w-56',\n 'tw:truncate',\n 'tw:px-2',\n 'tw:py-0.5',\n\n // Drop side padding only when an *inline* addon is present —\n // floating addons overlay the label without taking layout space,\n // so the label still needs full padding behind them.\n 'tw:group-has-[[data-align=inline-start][data-variant=inline]:not(:empty)]/badge:pl-0',\n 'tw:group-has-[[data-align=inline-end][data-variant=inline]:not(:empty)]/badge:pr-0',\n className,\n )}\n />\n );\n};\n","import { cva } from 'class-variance-authority';\n\n/**\n * Badge's `color` variants: a fill class, a foreground class, and a matching\n * `decoration-*` so an underlined badge underlines in its own fill colour.\n *\n * - Tinted (`-inverse`) variants each carry a `[data-theme=dark]` override, so the\n * chip inverts with the page instead of staying a light slab on a dark surface.\n * - Solid fills are fixed across schemes.\n * - Exported for `scripts/contrast-audit.ts` and the contrast story tests, which\n * measure each pairing rather than restating this map.\n */\nexport const badgeColors = {\n gray: 'tw:bg-neutral-400 tw:text-white tw:decoration-neutral-400',\n 'gray-darker': 'tw:bg-neutral-500 tw:text-white tw:decoration-neutral-500',\n 'gray-inverse':\n 'tw:bg-neutral-100 tw:text-neutral-500 tw:decoration-neutral-100 tw:[[data-theme=dark]_&]:bg-neutral-700 tw:[[data-theme=dark]_&]:text-neutral-300 tw:[[data-theme=dark]_&]:decoration-neutral-700',\n green: 'tw:bg-green-500 tw:text-white tw:decoration-green-500',\n 'green-darker': 'tw:bg-green-600 tw:text-white tw:decoration-green-600',\n 'green-inverse':\n 'tw:bg-green-100 tw:text-green-900 tw:decoration-green-100 tw:[[data-theme=dark]_&]:bg-green-900 tw:[[data-theme=dark]_&]:text-green-200 tw:[[data-theme=dark]_&]:decoration-green-900',\n blue: 'tw:bg-blue-500 tw:text-white tw:decoration-blue-500',\n 'blue-inverse':\n 'tw:bg-blue-100 tw:text-blue-800 tw:decoration-blue-100 tw:[[data-theme=dark]_&]:bg-blue-900 tw:[[data-theme=dark]_&]:text-blue-200 tw:[[data-theme=dark]_&]:decoration-blue-900',\n red: 'tw:bg-error-500 tw:text-white tw:decoration-error-500',\n orange: 'tw:bg-warning-500 tw:text-white tw:decoration-warning-500',\n 'orange-inverse':\n 'tw:bg-warning-100 tw:text-warning-800 tw:decoration-warning-100 tw:[[data-theme=dark]_&]:bg-warning-900 tw:[[data-theme=dark]_&]:text-warning-200 tw:[[data-theme=dark]_&]:decoration-warning-900',\n amber: 'tw:bg-warning-300 tw:text-warning-800 tw:decoration-warning-300',\n // One rung deeper than `orange-inverse` on both ends of the ramp, which is what\n // keeps caution and warning telling apart — the two share the `warning` hue.\n 'amber-inverse':\n 'tw:bg-warning-200 tw:text-warning-800 tw:decoration-warning-200 tw:[[data-theme=dark]_&]:bg-warning-800 tw:[[data-theme=dark]_&]:text-warning-200 tw:[[data-theme=dark]_&]:decoration-warning-800',\n teal: 'tw:bg-teal-500 tw:text-white tw:decoration-teal-500',\n 'teal-inverse':\n 'tw:bg-teal-100 tw:text-teal-800 tw:decoration-teal-100 tw:[[data-theme=dark]_&]:bg-teal-900 tw:[[data-theme=dark]_&]:text-teal-200 tw:[[data-theme=dark]_&]:decoration-teal-900',\n purple: 'tw:bg-purple-500 tw:text-white tw:decoration-purple-500',\n 'purple-inverse':\n 'tw:bg-purple-100 tw:text-purple-800 tw:decoration-purple-100 tw:[[data-theme=dark]_&]:bg-purple-900 tw:[[data-theme=dark]_&]:text-purple-200 tw:[[data-theme=dark]_&]:decoration-purple-900',\n cyan: 'tw:bg-cyan-500 tw:text-white tw:decoration-cyan-500',\n 'cyan-inverse':\n 'tw:bg-cyan-100 tw:text-cyan-800 tw:decoration-cyan-100 tw:[[data-theme=dark]_&]:bg-cyan-900 tw:[[data-theme=dark]_&]:text-cyan-200 tw:[[data-theme=dark]_&]:decoration-cyan-900',\n 'sidebar-primary': 'tw:bg-sidebar-primary tw:text-white tw:decoration-sidebar-primary',\n white: 'tw:bg-white/90 tw:text-neutral-600 tw:decoration-white/90',\n} as const;\n\n/** A `Badge` `color` value. */\nexport type BadgeColor = keyof typeof badgeColors;\n\n/**\n * Whether a variant paints text on its own tint rather than on a solid fill.\n *\n * - Tinted variants are the ones held to WCAG-AA per `AGENTS.md`; solid `-500`\n * fills are pinned across brands, so their contrast is recorded, not asserted.\n */\nexport const isTintedBadgeColor = (color: string): boolean => color.endsWith('-inverse');\n\nexport const badgeRootVariants = cva(\n [\n 'tailwindcss-preflight',\n 'tw:group/badge',\n\n // display\n 'tw:relative',\n 'tw:inline-flex',\n 'tw:justify-center',\n 'tw:items-center',\n 'tw:min-h-5',\n 'tw:h-fit',\n 'tw:shrink-0',\n 'tw:overflow-hidden',\n\n // text — chrome weight/tracking are brand-overridable tokens\n // (`--font-weight-medium` / `--letter-spacing-chrome`); casing lives on the\n // `default` variant below via `tw:uppercase`.\n 'tw:whitespace-pre-wrap',\n 'tw:break-normal',\n 'tw:text-xs',\n 'tw:font-medium',\n 'tw:tracking-chrome',\n 'tw:text-center',\n 'tw:underline',\n\n // content\n 'tw:border-none',\n 'tw:[&>svg]:self-center',\n 'tw:[button&]:cursor-pointer',\n\n // focus\n 'tw:focus-visible:outline-hidden',\n 'tw:focus-visible:ring-2',\n 'tw:focus-visible:ring-inset',\n 'tw:focus-visible:ring-ring',\n ],\n {\n defaultVariants: {\n color: 'gray',\n variant: 'default',\n },\n variants: {\n variant: {\n // Legacy chrome uppercases the default badge; the Keboola V2 brand\n // (`data-brand=\"keboola\"`) renders it in standard case instead.\n default: [\n 'tw:rounded tw:uppercase',\n 'tw:[[data-brand=keboola]_&]:normal-case tw:[[data-brand=keboola]_&]:tracking-normal',\n ],\n tag: ['tw:rounded tw:normal-case'],\n pill: ['tw:min-w-5 tw:rounded-full tw:normal-case tw:tracking-normal'],\n },\n color: badgeColors,\n },\n },\n);\n","import type { ComponentProps } from 'react';\nimport { type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '../../utils';\n\nimport { badgeRootVariants } from './styles';\n\ntype Props = ComponentProps<'div'> & VariantProps<typeof badgeRootVariants>;\n\nexport const BadgeRoot = ({ ref, variant, color, className, children, ...rest }: Props) => (\n <div\n {...rest}\n ref={ref}\n data-slot=\"badge\"\n className={cn(badgeRootVariants({ variant, color, className }))}\n >\n {children}\n </div>\n);\n","import type { ComponentProps, ReactNode } from 'react';\n\nimport { BadgeAddon } from './BadgeAddon';\nimport { BadgeButton } from './BadgeButton';\nimport { BadgeLabel } from './BadgeLabel';\nimport { BadgeRoot } from './BadgeRoot';\n\ntype AddonVariant = ComponentProps<typeof BadgeAddon>['variant'];\ntype BadgeRootProps = ComponentProps<typeof BadgeRoot>;\ntype BadgeLabelProps = ComponentProps<typeof BadgeLabel>;\n\n/**\n * Props for `Badge`. `color` is a categorical contract (`green` = success, `red` = error, `orange` = warning,\n * `amber` = caution, `purple/cyan/teal/blue/gray` for decorative tags) — colours stay fixed across brand themes.\n * Pass `prefix` / `suffix` for icon-style addons.\n */\ntype Props = Pick<BadgeRootProps, 'variant' | 'color'> &\n Omit<BadgeLabelProps, 'prefix'> & {\n prefix?: ReactNode;\n prefixVariant?: AddonVariant;\n suffix?: ReactNode;\n suffixVariant?: AddonVariant;\n labelClassName?: string;\n };\n\n/**\n * Compact status / category label rendered as an inline pill.\n *\n * **When to use:** encoding status (active, deprecated, beta), counts, or decorative tags next to a title\n * or in a table cell. The `color` prop is a semantic contract — `green` means success, `red` means error\n * etc., and colours are intentionally stable across customer brand themes.\n * **When NOT to use:** for an inline action use `Button` / `ButtonInline`; for a persistent contextual\n * banner use `Alert`; for a counter-only chip prefer `Badge` with just a numeric label.\n * **Composition:** drop into `PageHeader.Detail` `badges` slot, `Table.Cell`, or alongside titles in cards.\n * Use `Badge.Button` for an interactive (clickable) badge variant.\n */\nconst BadgeInner = ({\n ref,\n // root props\n variant,\n color,\n // custom props\n prefix,\n prefixVariant = 'inline',\n suffix,\n suffixVariant = 'inline',\n className,\n labelClassName,\n ...labelProps\n}: Props) => (\n <BadgeRoot className={className} variant={variant} color={color}>\n {prefix && (\n <BadgeAddon align=\"inline-start\" variant={prefixVariant}>\n {prefix}\n </BadgeAddon>\n )}\n <BadgeLabel {...labelProps} ref={ref} className={labelClassName} />\n {suffix && (\n <BadgeAddon align=\"inline-end\" variant={suffixVariant}>\n {suffix}\n </BadgeAddon>\n )}\n </BadgeRoot>\n);\n\nexport const Badge = Object.assign(BadgeInner, {\n Root: BadgeRoot,\n Button: BadgeButton,\n Label: BadgeLabel,\n Addon: BadgeAddon,\n});\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BrandLogo-Dmi7jo21.js","names":[],"sources":["../src/components/BrandLogo/BrandLogo.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport DOMPurify from 'dompurify';\n\nimport type { Brand } from '@keboola/brand-registry';\n\nimport { cn } from '../../utils';\nimport { type ResolvedColorScheme, useTheme } from '../ThemeProvider';\n\ntype Props = {\n /** `wordmark` (default, full logo) or `mark` (square icon); each falls back to the other. */\n variant?: 'mark' | 'wordmark';\n /** Sets the logo height; aspect ratio is preserved (e.g. `tw:h-7`). */\n className?: string;\n};\n\nconst isInlineSvg = (source: string) => source.trimStart().startsWith('<');\n\n// Resolved mode wins, then the other mode, then the other variant.\nconst resolveLogoSource = (\n logo: Brand['logo'],\n variant: 'mark' | 'wordmark',\n mode: ResolvedColorScheme,\n): string | undefined => {\n if (!logo) return undefined;\n const forMode = (light?: string, dark?: string) =>\n mode === 'dark' ? (dark ?? light) : (light ?? dark);\n const mark = forMode(logo.mark, logo.markDark);\n const wordmark = forMode(logo.wordmark, logo.wordmarkDark);\n return variant === 'mark' ? (mark ?? wordmark) : (wordmark ?? mark);\n};\n\n// Reference SVGs omit width/height, so without a default height a bare\n// `<BrandLogo />` renders at the browser's ~150px intrinsic size. `className` overrides it.\nconst wrapperClass = 'tw:inline-flex tw:h-6 tw:items-center tw:[&>svg]:h-full tw:[&>svg]:w-auto';\n\n/**\n * Renders the active brand's logo from the nearest `<ThemeProvider>`, or `null`\n * if the brand ships none. Inline SVG inherits `currentColor`; URLs use `<img>`.\n */\nexport const BrandLogo = ({ variant = 'wordmark', className }: Props) => {\n const { currentTheme, resolvedScheme } = useTheme();\n const source = resolveLogoSource(currentTheme.logo, variant, resolvedScheme);\n\n // A brand may come from customer config or a paste field, not just the repo.\n const safeSvg = useMemo(\n () =>\n source && isInlineSvg(source)\n ? DOMPurify.sanitize(source, { USE_PROFILES: { svg: true, svgFilters: true } })\n : null,\n [source],\n );\n\n if (!source) return null;\n\n if (safeSvg !== null) {\n return (\n <span\n role=\"img\"\n aria-label={currentTheme.name}\n className={cn(wrapperClass, className)}\n dangerouslySetInnerHTML={{ __html: safeSvg }}\n />\n );\n }\n\n return (\n <span className={cn(wrapperClass, className)}>\n <img src={source} alt={currentTheme.name} className=\"tw:h-full tw:w-auto\" />\n </span>\n );\n};\n"],"mappings":";;;;;;AAeA,MAAM,eAAe,WAAmB,OAAO,UAAU,CAAC,CAAC,WAAW,GAAG;AAGzE,MAAM,qBACJ,MACA,SACA,SACuB;CACvB,IAAI,CAAC,MAAM,OAAO,KAAA;CAClB,MAAM,WAAW,OAAgB,SAC/B,SAAS,SAAU,QAAQ,QAAU,SAAS;CAChD,MAAM,OAAO,QAAQ,KAAK,MAAM,KAAK,QAAQ;CAC7C,MAAM,WAAW,QAAQ,KAAK,UAAU,KAAK,YAAY;CACzD,OAAO,YAAY,SAAU,QAAQ,WAAa,YAAY;AAChE;AAIA,MAAM,eAAe;;;;;AAMrB,MAAa,aAAa,EAAE,UAAU,YAAY,gBAAuB;CACvE,MAAM,EAAE,cAAc,mBAAmB,SAAS;CAClD,MAAM,SAAS,kBAAkB,aAAa,MAAM,SAAS,cAAc;CAG3E,MAAM,UAAU,cAEZ,UAAU,YAAY,MAAM,IACxB,UAAU,SAAS,QAAQ,EAAE,cAAc;EAAE,KAAK;EAAM,YAAY;CAAK,EAAE,CAAC,IAC5E,MACN,CAAC,MAAM,CACT;CAEA,IAAI,CAAC,QAAQ,OAAO;CAEpB,IAAI,YAAY,MACd,OACE,oBAAC,QAAD;EACE,MAAK;EACL,cAAY,aAAa;EACzB,WAAW,GAAG,cAAc,SAAS;EACrC,yBAAyB,EAAE,QAAQ,QAAQ;CAC5C,CAAA;CAIL,OACE,oBAAC,QAAD;EAAM,WAAW,GAAG,cAAc,SAAS;EACzC,UAAA,oBAAC,OAAD;GAAK,KAAK;GAAQ,KAAK,aAAa;GAAM,WAAU;EAAuB,CAAA;CACvE,CAAA;AAEV"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Combobox-Cs_1pj2q.js","names":["BaseCombobox","BaseCombobox","BaseCombobox","BaseCombobox","BaseCombobox","BaseCombobox","BaseCombobox","BaseCombobox","BaseCombobox","BaseCombobox","BaseCombobox","BaseCombobox","BaseCombobox","Combobox","BaseCombobox"],"sources":["../src/components/Combobox/utils.ts","../src/components/Combobox/ComboboxChips.tsx","../src/components/Combobox/ComboboxContent.tsx","../src/components/Combobox/ComboboxEmpty.tsx","../src/components/Combobox/ComboboxInput.tsx","../src/components/Combobox/ComboboxInputGroup.tsx","../src/components/Combobox/ComboboxItemIndicator.tsx","../src/components/Combobox/ComboboxItem.tsx","../src/components/Combobox/ComboboxList.tsx","../src/components/Combobox/ComboboxRoot.tsx","../src/components/Combobox/ComboboxSeparator.tsx","../src/components/Combobox/Group/ComboboxGroup.tsx","../src/components/Combobox/Group/ComboboxGroupLabel.tsx","../src/components/Combobox/Group/ComboboxCollection.tsx","../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import type { CreatableItem, Group, InternalItems, LabeledItem, SelectAllItem } from './types';\n\nconst isPlainObject = (item: unknown): item is Record<string, unknown> =>\n item !== null && typeof item === 'object';\n\nconst isNumber = (item: unknown): item is number => typeof item === 'number';\nconst isString = (item: unknown): item is string => typeof item === 'string';\n\nexport const isLabeledItem = (item: unknown): item is LabeledItem =>\n isPlainObject(item) && Reflect.has(item, 'label') && Reflect.has(item, 'value');\n\nconst isInternalItem = (item: unknown): item is InternalItems =>\n isLabeledItem(item) && '__marker' in item;\n\nexport const isSelectAllItem = (item: unknown): item is SelectAllItem =>\n isInternalItem(item) && item.__marker === 'selectAll';\n\nexport const isCreatableItem = (item: unknown): item is CreatableItem => {\n return isInternalItem(item) && item.__marker === 'creatable';\n};\n\nexport const isGroupItem = <Item>(itemOrGroup: Item | Group<Item>): itemOrGroup is Group<Item> =>\n itemOrGroup !== null && typeof itemOrGroup === 'object' && Reflect.has(itemOrGroup, 'items');\n\nexport const isGroupItems = <Item, GroupShape extends Group<Item> = Group<Item>>(\n items: readonly (Item | GroupShape)[],\n): items is GroupShape[] => {\n if (!Array.isArray(items)) return false;\n if (items.length === 0) return false; // Base UI treats an empty items array as non-grouped, so we must too for consistency\n return isGroupItem(items[0]); // Base UI only checks the first item to determine if it's a group or not, so we do the same for consistency\n};\n\nexport const defaultItemToLabel = <Item>(item: Item) => {\n if (isNumber(item) || isString(item)) return item;\n if (!isLabeledItem(item))\n throw new Error(\n 'Combobox: Item does not have a `label` field. Pass `itemToLabel` for custom item shapes.',\n );\n\n return item.label;\n};\n\n/** Display string for an item — mirrors base-ui's own default logic. */\nexport const toLabel = (item: unknown): string => {\n if (isString(item)) return item;\n if (isLabeledItem(item)) {\n if (item.label) return item.label;\n if (item.value) return item.value;\n }\n return String(item);\n};\n\n/** Equality key for an item — prefers .value for stable identity. */\nexport const toValueKey = (item: unknown): string => {\n if (isString(item)) return item;\n if (isLabeledItem(item)) {\n if (item.value) return item.value;\n if (item.label) return item.label;\n }\n return String(item);\n};\n\nexport const defaultItemToIcon = <Item>(item: Item) =>\n isLabeledItem(item) ? item.icon : undefined;\n\nexport const defaultItemToDisabled = <Item>(item: Item) =>\n isLabeledItem(item) ? (item.disabled ?? false) : false;\n\nexport const defaultGroupToLabel = () => undefined;\n\n// Internal markers ------------------------------------------------------------\n// Both `selectAll` and `creatable` are LabeledItem-shaped sentinels that we\n// inject into the items list passed to Base UI. They carry a `__marker`\n// discriminator so consumer code (and user-supplied callbacks) can't collide\n// with them by accident.\n\nexport const selectAllItem: SelectAllItem = {\n __marker: 'selectAll',\n value: '__select_all__',\n label: 'Select All',\n};\n\nexport const createCreatableItem = (query: string): CreatableItem => ({\n __marker: 'creatable',\n value: query,\n label: query,\n});\n\nexport const defaultToCreateValue = <Value>(\n query: string,\n value: Value | undefined,\n queryToCreateValue?: (query: string) => Value,\n): Value => {\n if (queryToCreateValue) return queryToCreateValue(query);\n if (value === undefined) return query as Value;\n if (isString(value)) return query as Value;\n if (isLabeledItem(value)) return { value: query, label: query } as Value;\n throw new Error(\n 'Combobox: Cannot infer item shape for `allowCreate`. Pass `queryToCreateValue` for custom item shapes.',\n );\n};\n\nexport const defaultQueryToCreateLabel = (query: string) => `Create \"${query}\"`;\n","import type { ComponentProps, ReactNode } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { X } from '../../icons';\nimport { Badge } from '../Badge';\n\nimport { defaultItemToLabel } from './utils';\n\ntype BadgeColor = ComponentProps<typeof Badge>['color'];\ntype BadgeVariant = ComponentProps<typeof Badge>['variant'];\n\ntype Props<Value> = {\n maxVisible?: number;\n itemToChipLabel?: (item: Value) => ReactNode;\n itemToChipColor?: (item: Value) => BadgeColor;\n /**\n * Labels for chips the control shows but the user does not own — a pinned set the caller keeps.\n *\n * - Each label gets a chip of its own, ahead of the values and outside the `maxVisible` slice.\n * - No remove button, and no entry in `value` — there is nothing for a removal to report.\n */\n pinnedChipLabels?: ReactNode[];\n variant?: BadgeVariant;\n};\n\nexport const ComboboxChips = <Value,>({\n maxVisible = 3,\n itemToChipLabel = defaultItemToLabel,\n itemToChipColor,\n pinnedChipLabels,\n variant = 'pill',\n}: Props<Value>) => (\n <BaseCombobox.Value>\n {(values: Value[]) => {\n const visible = values.slice(0, maxVisible);\n const overflow = values.slice(maxVisible);\n\n return (\n <>\n {pinnedChipLabels?.map((label, index) => (\n // oxlint-disable-next-line react/no-array-index-key\n <Badge key={index} className=\"tw:max-w-40\" variant={variant}>\n {label}\n </Badge>\n ))}\n\n {visible.map((value: Value, index) => (\n <BaseCombobox.Chip\n // oxlint-disable-next-line react/no-array-index-key\n key={index}\n render={\n <Badge.Root\n color={itemToChipColor?.(value)}\n className=\"tw:max-w-40\"\n variant={variant}\n />\n }\n >\n <Badge.Label>{itemToChipLabel(value)}</Badge.Label>\n <Badge.Addon variant=\"inline\" align=\"inline-end\">\n <BaseCombobox.ChipRemove\n render={\n <Badge.Button aria-label=\"Remove value\">\n <X className=\"tw:size-3\" />\n </Badge.Button>\n }\n />\n </Badge.Addon>\n </BaseCombobox.Chip>\n ))}\n\n {overflow.length > 0 && (\n <Badge.Root variant=\"pill\">\n <Badge.Label>+{overflow.length}</Badge.Label>\n </Badge.Root>\n )}\n </>\n );\n }}\n </BaseCombobox.Value>\n);\n","import type { ComponentProps } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { cn } from '../../utils';\nimport { useArgoDesign } from '../ThemeProvider/context';\n\ntype PortalProps = ComponentProps<typeof BaseCombobox.Portal>;\ntype PositionerProps = ComponentProps<typeof BaseCombobox.Positioner>;\ntype PopupProps = Omit<ComponentProps<typeof BaseCombobox.Popup>, 'className'> & {\n className?: string;\n};\n\ntype Variant = 'default' | 'argo';\n\ntype Props = PopupProps &\n Pick<PositionerProps, 'side' | 'align' | 'sideOffset' | 'alignOffset' | 'anchor'> &\n Pick<PortalProps, 'container'>;\n\nexport const ComboboxContent = ({\n ref,\n align = 'start',\n side = 'bottom',\n sideOffset = 4,\n alignOffset,\n anchor,\n container,\n className,\n children,\n ...popupProps\n}: Props) => {\n const effectiveVariant: Variant = useArgoDesign() ? 'argo' : 'default';\n return (\n <BaseCombobox.Portal container={container}>\n <BaseCombobox.Positioner\n align={align}\n side={side}\n sideOffset={sideOffset}\n alignOffset={alignOffset}\n anchor={anchor}\n className=\"tw:isolate tw:z-[1055] tailwindcss-preflight\"\n >\n <BaseCombobox.Popup\n ref={ref}\n data-chips={!!anchor}\n data-variant={effectiveVariant}\n className={cn(\n 'tw:!pointer-events-auto',\n 'tw:group/combobox-content',\n 'tw:relative',\n 'tw:flex tw:flex-col tw:overflow-hidden',\n\n // sizing\n 'tw:max-h-[var(--available-height)]',\n 'tw:w-[var(--anchor-width)]',\n 'tw:max-w-[var(--available-width)]',\n 'tw:origin-[var(--transform-origin)]',\n 'tw:data-[chips=true]:min-w-[var(--anchor-width)]',\n\n // appearance\n 'tw:rounded-lg',\n 'tw:data-[variant=default]:rounded',\n\n 'tw:bg-popover',\n 'tw:text-popover-foreground',\n 'tw:shadow-md',\n 'tw:ring-1',\n 'tw:ring-foreground/10',\n 'tw:duration-100',\n\n // open animation\n 'data-open:animate-in',\n 'data-open:fade-in-0',\n 'data-open:zoom-in-95',\n\n // closed animation\n 'data-closed:animate-out',\n 'data-closed:fade-out-0',\n 'data-closed:zoom-out-95',\n\n // position animations\n 'tw:data-[side=bottom]:slide-in-from-top-2',\n 'tw:data-[side=top]:slide-in-from-bottom-2',\n 'tw:data-[side=left]:slide-in-from-right-2',\n 'tw:data-[side=right]:slide-in-from-left-2',\n 'tw:data-[side=inline-start]:slide-in-from-right-2',\n 'tw:data-[side=inline-end]:slide-in-from-left-2',\n className,\n )}\n {...popupProps}\n >\n {children}\n </BaseCombobox.Popup>\n </BaseCombobox.Positioner>\n </BaseCombobox.Portal>\n );\n};\n","import type { ComponentProps } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { cn } from '../../utils';\n\ntype Props = Omit<ComponentProps<typeof BaseCombobox.Empty>, 'className'> & {\n className?: string;\n};\n\nexport const ComboboxEmpty = ({ ref, className, ...props }: Props) => (\n <BaseCombobox.Empty\n ref={ref}\n className={cn(\n 'tw:hidden',\n 'tw:group-data-[empty]/combobox-content:flex',\n 'tw:justify-center',\n 'tw:items-center',\n 'tw:text-center',\n 'tw:px-2',\n 'tw:text-muted-foreground',\n 'tw:py-6',\n className,\n )}\n {...props}\n />\n);\n","import type { ComponentProps } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { InputGroup } from '../InputGroup';\n\ntype Props = Omit<ComponentProps<typeof BaseCombobox.Input>, 'render'>;\n\nexport const ComboboxInput = ({ ref, ...props }: Props) => (\n <BaseCombobox.Input {...props} ref={ref} render={<InputGroup.Input />} />\n);\n","import type { ComponentProps } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { InputGroup } from '../InputGroup';\n\ntype InputGroupProps = Pick<\n ComponentProps<typeof InputGroup>,\n 'variant' | 'focusVariant' | 'sizing' | 'state'\n>;\n\ntype Props = InputGroupProps &\n Omit<ComponentProps<typeof BaseCombobox.InputGroup>, 'render' | 'className'> & {\n className?: string;\n };\n\nexport const ComboboxInputGroup = ({\n ref,\n state,\n variant,\n sizing,\n focusVariant,\n className,\n ...props\n}: Props) => (\n <BaseCombobox.InputGroup\n {...props}\n ref={ref}\n render={\n <InputGroup\n state={state}\n variant={variant}\n focusVariant={focusVariant}\n sizing={sizing}\n className={className}\n />\n }\n />\n);\n","import type { ComponentProps } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { Check } from '../../icons';\nimport { cn } from '../../utils';\n\ntype Variant = 'check' | 'checkbox';\n\ntype Props = Omit<ComponentProps<typeof BaseCombobox.ItemIndicator>, 'className' | 'children'> & {\n className?: string;\n variant?: Variant;\n};\n\nexport const ComboboxItemIndicator = ({ ref, className, variant = 'check', ...props }: Props) => {\n if (variant === 'checkbox') {\n return (\n <BaseCombobox.ItemIndicator\n ref={ref}\n keepMounted\n className={cn(\n 'tw:group/combobox-item-indicator',\n\n 'tw:inline-flex',\n 'tw:items-center',\n 'tw:justify-center',\n 'tw:size-4',\n 'tw:shrink-0',\n\n 'tw:rounded',\n 'tw:border',\n 'tw:border-input',\n 'tw:bg-background',\n\n 'tw:data-[selected]:bg-primary',\n 'tw:data-[selected]:border-primary',\n className,\n )}\n {...props}\n >\n <Check\n className={cn(\n 'tw:hidden',\n 'tw:size-3',\n 'tw:stroke-[4px]',\n 'tw:!text-primary-foreground',\n 'tw:group-data-[selected]/combobox-item-indicator:block',\n )}\n />\n </BaseCombobox.ItemIndicator>\n );\n }\n\n return (\n <BaseCombobox.ItemIndicator\n {...props}\n ref={ref}\n className={cn(\n 'tw:pointer-events-none',\n 'tw:absolute',\n 'tw:right-2',\n\n 'tw:group-data-[variant=default]/combobox-content:right-4',\n // `render={<Check />}` makes the icon the indicator element itself (not a descendant), so a\n // `[&_svg]` rule never matches it — size it directly or Lucide renders at its 24px default.\n 'tw:size-4',\n 'tw:group-data-[highlighted]/combobox-item:text-accent-foreground',\n 'tw:group-data-[variant=default]/combobox-content:group-data-[highlighted]/combobox-item:text-secondary-foreground',\n className,\n )}\n render={<Check />}\n />\n );\n};\n","import type { ComponentProps, ReactNode } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { cn } from '../../utils';\n\nimport { ComboboxItemIndicator } from './ComboboxItemIndicator';\n\ntype Props = Omit<ComponentProps<typeof BaseCombobox.Item>, 'className'> & {\n className?: string;\n icon?: ReactNode;\n indicator?: ComponentProps<typeof ComboboxItemIndicator>['variant'];\n};\n\nexport const ComboboxItem = ({\n ref,\n className,\n children,\n icon,\n indicator: variant = 'check',\n ...props\n}: Props) => (\n <BaseCombobox.Item\n {...props}\n ref={ref}\n data-slot=\"combobox-item\"\n className={cn(\n 'tw:group/combobox-item',\n // layout\n 'tw:relative',\n 'tw:flex',\n 'tw:flex-1',\n 'tw:items-center',\n 'tw:gap-2',\n\n // spacing\n 'tw:py-2',\n 'tw:px-2',\n 'tw:group-data-[variant=default]/combobox-content:px-4',\n 'tw:rounded-lg',\n 'tw:group-data-[variant=default]/combobox-content:rounded-none',\n\n // typography\n 'tw:text-sm',\n 'tw:select-none',\n 'tw:cursor-default',\n 'tw:outline-hidden',\n\n // highlighted (keyboard / hover)\n 'tw:data-[highlighted]:bg-accent',\n // The legacy highlight is a neutral step, not the argo accent.\n //\n // - `secondary` carries its own foreground, so fill and ink move together.\n // - `muted` is unusable: in dark it equals `popover`, so the band would disappear\n // into the listbox.\n 'tw:group-data-[variant=default]/combobox-content:data-[highlighted]:bg-secondary',\n 'tw:data-[highlighted]:text-accent-foreground',\n 'tw:group-data-[variant=default]/combobox-content:data-[highlighted]:text-secondary-foreground',\n\n // disabled\n 'tw:data-disabled:pointer-events-none',\n 'tw:data-disabled:opacity-50',\n\n // child svg defaults\n 'tw:[&_svg]:pointer-events-none',\n 'tw:[&_svg]:shrink-0',\n 'tw:[&_svg]:text-muted-foreground',\n \"tw:[&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n >\n {<ComboboxItemIndicator variant={variant} />}\n {icon}\n <span className=\"tw:truncate\">{children}</span>\n </BaseCombobox.Item>\n);\n","import type { ComponentProps } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { cn } from '../../utils';\n\ntype Props = Omit<ComponentProps<typeof BaseCombobox.List>, 'className'> & {\n className?: string;\n};\n\nexport const ComboboxList = ({ ref, className, ...props }: Props) => (\n <BaseCombobox.List\n ref={ref}\n className={cn(\n 'tw:no-scrollbar',\n 'tw:scroll-py-1',\n 'tw:overflow-y-auto',\n 'tw:overscroll-contain',\n 'tw:min-h-0',\n 'tw:flex-1',\n\n 'tw:p-2',\n 'tw:data-[empty]:p-0',\n 'tw:group-data-[variant=default]/combobox-content:p-0',\n className,\n )}\n {...props}\n />\n);\n","import { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nexport const ComboboxRoot = <Value, Multiple extends boolean | undefined = false>(\n props: BaseCombobox.Root.Props<Value, Multiple>,\n) => <BaseCombobox.Root {...props} />;\n","import type { ComponentProps } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { cn } from '../../utils';\n\ntype Props = Omit<ComponentProps<typeof BaseCombobox.Separator>, 'className'> & {\n className?: string;\n};\n\nexport const ComboboxSeparator = ({ ref, className, ...props }: Props) => (\n <BaseCombobox.Separator\n ref={ref}\n className={cn('tw:mx-2 tw:my-1 tw:h-px tw:bg-border', className)}\n {...props}\n />\n);\n","import type { ComponentProps } from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { cn } from '../../../utils';\n\ntype Props = Omit<ComponentProps<typeof BaseCombobox.Group>, 'className'> & {\n className?: string;\n};\n\nexport const ComboboxGroup = ({ ref, className, children, ...props }: Props) => (\n <BaseCombobox.Group\n ref={ref}\n className={cn('tw:flex tw:flex-col tw:gap-0.5', className)}\n {...props}\n >\n {children}\n </BaseCombobox.Group>\n);\n","import { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\nimport { cn } from '../../../utils';\n\ntype Props = Omit<BaseCombobox.GroupLabel.Props, 'className'> & {\n className?: string;\n};\n\nexport const ComboboxGroupLabel = ({ ref, className, ...props }: Props) => (\n <BaseCombobox.GroupLabel\n {...props}\n ref={ref}\n className={cn(\n // Base (argo variant) — soft gray section label.\n 'tw:px-2',\n 'tw:py-1.5',\n 'tw:text-xs',\n 'tw:font-medium',\n 'tw:leading-none',\n 'tw:text-muted-foreground',\n\n 'tw:group-data-[variant=default]/combobox-content:uppercase',\n 'tw:group-data-[variant=default]/combobox-content:font-semibold',\n 'tw:group-data-[variant=default]/combobox-content:tracking-wider',\n 'tw:group-data-[variant=default]/combobox-content:text-[11px]',\n 'tw:group-data-[variant=default]/combobox-content:text-black',\n 'tw:group-data-[variant=default]/combobox-content:pt-2',\n 'tw:group-data-[variant=default]/combobox-content:px-4',\n\n className,\n )}\n />\n);\n","import { Combobox as BaseCombobox } from '@base-ui/react/combobox';\n\ntype Props = BaseCombobox.Collection.Props;\n\nexport const ComboboxCollection = ({ ...props }: Props) => (\n <BaseCombobox.Collection data-slot=\"combobox-collection\" {...props} />\n);\n","import {\n type ComponentProps,\n type CSSProperties,\n type ReactNode,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { Combobox as BaseCombobox } from '@base-ui/react/combobox';\nimport { useVirtualizer } from '@tanstack/react-virtual';\n\nimport { ChevronDown, Plus, X } from '../../icons';\nimport { InputGroup } from '../InputGroup';\n\nimport { ComboboxChips } from './ComboboxChips';\nimport { ComboboxContent } from './ComboboxContent';\nimport { ComboboxEmpty } from './ComboboxEmpty';\nimport { ComboboxInput } from './ComboboxInput';\nimport { ComboboxInputGroup } from './ComboboxInputGroup';\nimport { ComboboxItem } from './ComboboxItem';\nimport { ComboboxList } from './ComboboxList';\nimport { ComboboxRoot } from './ComboboxRoot';\nimport { ComboboxSeparator } from './ComboboxSeparator';\nimport { ComboboxCollection, ComboboxGroup, ComboboxGroupLabel } from './Group';\nimport type { Group } from './types';\nimport {\n createCreatableItem,\n defaultGroupToLabel,\n defaultItemToDisabled,\n defaultItemToIcon,\n defaultItemToLabel,\n defaultQueryToCreateLabel,\n defaultToCreateValue,\n isCreatableItem,\n isGroupItem,\n isGroupItems,\n toLabel,\n toValueKey,\n} from './utils';\n\n// Above this many (ungrouped) items, the list is windowed with `@tanstack/react-virtual` so only\n// the visible rows hit the DOM. Base UI keeps keyboard nav + filtering working against the full\n// `items` set (via `virtualized`), so search is unaffected.\nconst VIRTUALIZE_THRESHOLD = 30;\nconst ESTIMATED_ROW_HEIGHT = 40;\nconst ESTIMATED_LIST_HEIGHT = 320;\n\ntype ComboboxProps<Value> = BaseCombobox.Root.Props<Value, false>;\ntype ComboboxInputProps = ComponentProps<typeof ComboboxInput>;\ntype ComboboxInputGroupProps = ComponentProps<typeof ComboboxInputGroup>;\ntype ComboboxItemProps = ComponentProps<typeof ComboboxItem>;\n\ntype Indicator = NonNullable<ComboboxItemProps['indicator']>;\n\ntype PublicComboboxInputProps = Pick<ComboboxInputProps, 'placeholder' | 'id'> &\n Pick<ComboboxInputGroupProps, 'variant' | 'focusVariant' | 'sizing' | 'state' | 'className'>;\n\ntype PublicComboboxProps<Value> = Pick<\n ComboboxProps<Value>,\n | 'disabled'\n | 'inputRef'\n | 'value'\n | 'defaultValue'\n | 'onValueChange'\n | 'itemToStringLabel'\n | 'itemToStringValue'\n | 'filter'\n | 'onOpenChangeComplete'\n | 'isItemEqualToValue'\n>;\n\ntype CreatableProps<Value> = {\n allowCreate?: boolean;\n queryToCreateLabel?: (query: string) => ReactNode;\n queryToCreateValue?: (query: string) => Value;\n /**\n * Gate on the typed query for `allowCreate`.\n *\n * - Returning `false` hides the create row, so the empty state shows instead.\n * - Only called for a non-empty query that matches no existing item.\n * - Reach for it when a free-form value has a format (an email address, a URL, an identifier).\n */\n canCreate?: (query: string) => boolean;\n};\n\ntype Props<Value, GroupShape extends Group<Value> = Group<Value>> = PublicComboboxInputProps &\n PublicComboboxProps<Value> &\n CreatableProps<Value> & {\n items?: readonly (Value | GroupShape)[];\n\n // root specific\n allowClear?: boolean;\n empty?: ReactNode;\n indicator?: Indicator;\n prefix?: ReactNode;\n /**\n * Window the list with a virtualizer so large option sets stay fast. Opt-in — defaults to\n * `false` to keep behavior unchanged for existing call sites (every option stays in the DOM).\n * Pass `'auto'` to virtualize only ungrouped lists longer than {@link VIRTUALIZE_THRESHOLD},\n * or `true` to force it. Grouped lists are never virtualized.\n */\n virtualized?: boolean | 'auto';\n\n // item specific\n /** `query` is the current search text — pass it to `MarkedText` to highlight the match. */\n itemToLabel?: (item: Value, query: string) => ReactNode;\n itemToIcon?: (item: Value) => ReactNode;\n itemToDisabled?: (item: Value) => boolean;\n\n // group specific\n groupToLabel?: (group: GroupShape) => ReactNode;\n };\n\nexport const Combobox = <Value, GroupShape extends Group<Value> = Group<Value>>({\n // root props\n items: _itemsProp,\n value,\n defaultValue,\n onValueChange,\n itemToStringLabel: itemToStringLabelProp,\n itemToStringValue,\n disabled,\n filter,\n inputRef,\n onOpenChangeComplete,\n isItemEqualToValue: isItemEqualToValueProp,\n\n // input props\n variant,\n sizing,\n focusVariant,\n state,\n placeholder,\n allowClear,\n id,\n className,\n\n // own props\n empty = 'No items',\n indicator,\n prefix,\n virtualized = false,\n\n // creatable\n allowCreate,\n queryToCreateValue,\n queryToCreateLabel = defaultQueryToCreateLabel,\n canCreate,\n\n // own item props\n itemToDisabled = defaultItemToDisabled,\n itemToLabel = defaultItemToLabel,\n itemToIcon = defaultItemToIcon,\n groupToLabel = defaultGroupToLabel,\n}: Props<Value, GroupShape>) => {\n const closeReasonRef = useRef<'outside-click' | 'item-press' | 'creatable-item-press' | 'none'>(\n 'none',\n );\n const [inputValue, setInputValue] = useState(() => {\n const initial = value !== undefined ? value : defaultValue;\n if (initial == null) return '';\n return itemToStringLabelProp?.(initial) ?? toLabel(initial);\n });\n\n // Bumped on every selection so the sync effect below re-runs even when the owner leaves `value`\n // untouched.\n const [selections, setSelections] = useState(0);\n\n // Snap the input back to the controlled value's label.\n //\n // - Runs on a new `value` and after every selection, so a selection the owner does not adopt\n // cannot leave the input showing something the value does not say.\n // - `value` pinned to `null` is the \"adder\" shape: each pick is consumed by the owner and the\n // input clears, ready for the next one.\n // - Uncontrolled comboboxes (`value === undefined`) keep Base UI's own input handling.\n useEffect(() => {\n if (value === undefined) return;\n const label = value === null ? '' : (itemToStringLabelProp?.(value) ?? toLabel(value));\n setInputValue((prev) => (prev === label ? prev : label));\n }, [value, selections]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const selectedLabel =\n value == null ? undefined : (itemToStringLabelProp?.(value) ?? toLabel(value));\n // While the input still shows the current selection's label (nothing typed since the popup\n // opened), treat it as an empty query so the whole list stays browsable. Otherwise the combobox\n // filters down to just the selected item and you can't switch to a different, unrelated one\n // without clearing first.\n const isShowingSelection = selectedLabel !== undefined && inputValue === selectedLabel;\n const query = (isShowingSelection ? '' : inputValue).trim();\n const queryLower = query.toLowerCase();\n\n const itemsProp = _itemsProp ?? [];\n const sampleItem = itemsProp.flatMap((item) => (isGroupItem(item) ? item.items : [item]))[0];\n\n const [createdItems, setCreatedItems] = useState<Value[]>([]);\n\n const allItems = (() => {\n if (createdItems.length === 0) return itemsProp as (Value | GroupShape)[];\n if (isGroupItems(itemsProp))\n return [...itemsProp, { items: createdItems } as unknown as GroupShape];\n return [...itemsProp, ...createdItems];\n })();\n\n const items = (() => {\n if (!allowCreate || disabled) return allItems;\n if (!query) return allItems;\n const exactMatch = allItems\n .flatMap((item) => (isGroupItem(item) ? item.items : [item]))\n .some(\n (item) => (itemToStringLabelProp?.(item) ?? toLabel(item)).toLowerCase() === queryLower,\n );\n if (exactMatch) return allItems;\n if (canCreate && !canCreate(query)) return allItems;\n\n const creatable = isGroupItems(itemsProp)\n ? [{ items: [createCreatableItem(query)] }]\n : [createCreatableItem(query)];\n\n return [...allItems, ...creatable];\n })();\n\n const itemToStringLabel: ComboboxProps<Value>['itemToStringLabel'] = (value) => {\n if (isCreatableItem(value)) return value.value;\n return itemToStringLabelProp?.(value) ?? toLabel(value);\n };\n\n const wrappedFilter: ComboboxProps<Value>['filter'] = isShowingSelection\n ? () => true\n : !allowCreate || !filter\n ? filter\n : (item, ...args) => isCreatableItem(item) || filter(item, ...args);\n\n const wrappedItemToStringValue: ComboboxProps<Value>['itemToStringValue'] =\n !allowCreate || !itemToStringValue\n ? itemToStringValue\n : (item) => (isCreatableItem(item) ? item.value : itemToStringValue(item));\n\n const isItemEqualToValue: ComboboxProps<Value>['isItemEqualToValue'] = (a, b) => {\n if (isCreatableItem(a) || isCreatableItem(b)) return toValueKey(a) === toValueKey(b);\n return isItemEqualToValueProp?.(a, b) ?? Object.is(a, b);\n };\n\n const handleInputValueChange: NonNullable<ComboboxProps<Value>['onInputValueChange']> = (\n value,\n { reason },\n ) => {\n if (\n ['input-clear', 'none'].includes(reason) &&\n ['item-press', 'creatable-item-press'].includes(closeReasonRef.current)\n ) {\n closeReasonRef.current = 'none';\n return;\n }\n\n if (reason === 'none' && closeReasonRef.current == 'outside-click') {\n closeReasonRef.current = 'none';\n setInputValue(value);\n return;\n }\n\n setInputValue(value);\n };\n\n const handleOnOpenChangeComplete: NonNullable<ComboboxProps<Value>['onOpenChangeComplete']> = (\n open,\n ) => {\n onOpenChangeComplete?.(open);\n if (open) return;\n if (closeReasonRef.current !== 'none') return;\n closeReasonRef.current = 'outside-click';\n };\n\n const handleOnValueChange: ComboboxProps<Value>['onValueChange'] = (next, event) => {\n setSelections((count) => count + 1);\n\n if (isCreatableItem(next)) {\n const newValue = defaultToCreateValue(next.value, sampleItem, queryToCreateValue) as Value;\n closeReasonRef.current = 'creatable-item-press';\n setCreatedItems((prev) => [...prev, newValue]);\n onValueChange?.(newValue, event);\n return;\n }\n\n closeReasonRef.current = 'item-press';\n onValueChange?.(next, event);\n };\n\n // State-backed (not a ref) so a re-render fires when the popup mounts/remounts — Base UI unmounts\n // the list on close, and the virtualizer must re-observe the fresh element on each reopen or it\n // measures a stale/detached node and paints nothing.\n const [listElement, setListElement] = useState<HTMLDivElement | null>(null);\n // Base the decision on `allItems` (the real options) rather than `items`, which also holds the\n // transient creatable row — otherwise virtualization could toggle on/off as the user types.\n const isGrouped = isGroupItems(allItems);\n const shouldVirtualize =\n !isGrouped &&\n (virtualized === true || (virtualized === 'auto' && allItems.length > VIRTUALIZE_THRESHOLD));\n\n // In virtualized mode we pre-filter here and disable Base UI's filter with `null` (see the Root\n // `filter` prop — `undefined` would keep Base UI's default `contains`, which re-filters our items\n // with a different predicate and wrongly drives the empty state + keyboard nav). The creatable\n // row is always kept.\n const matchesQuery = (item: Value) => {\n if (isCreatableItem(item)) return true;\n if (!query) return true;\n if (filter) return !!filter(item, query, (value) => itemToStringLabel(value) ?? toLabel(value));\n return (itemToStringLabel(item) ?? toLabel(item)).toLowerCase().includes(queryLower);\n };\n\n const virtualItems = shouldVirtualize ? (items as Value[]).filter(matchesQuery) : [];\n\n const virtualizer = useVirtualizer({\n count: virtualItems.length,\n getScrollElement: () => listElement,\n estimateSize: () => ESTIMATED_ROW_HEIGHT,\n overscan: 12,\n enabled: shouldVirtualize,\n // Seed a viewport height so rows paint on the first frame. Without it the list measures 0 until\n // the ResizeObserver fires (a frame later), which renders an empty popup on open.\n initialRect: { width: 0, height: ESTIMATED_LIST_HEIGHT },\n });\n\n const renderItem = (item: Value, index?: number) => {\n if (isCreatableItem(item)) {\n return (\n <Combobox.Item index={index} value={item} icon={<Plus />}>\n {queryToCreateLabel(item.value)}\n </Combobox.Item>\n );\n }\n\n return (\n <Combobox.Item\n index={index}\n value={item}\n indicator={indicator}\n icon={itemToIcon(item)}\n disabled={itemToDisabled(item)}\n >\n {itemToLabel(item, query)}\n </Combobox.Item>\n );\n };\n\n const rowStyle = (offset: number): CSSProperties => ({\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n transform: `translateY(${offset}px)`,\n });\n\n return (\n <BaseCombobox.Root<Value, false>\n items={shouldVirtualize ? virtualItems : items}\n // Base UI highlights nothing until ArrowDown, so Enter after typing would drop the query\n // silently — no selection, and the popup closes. Highlighting the first match makes Enter\n // commit it, including the creatable row when `allowCreate` is on.\n autoHighlight\n value={value}\n defaultValue={defaultValue}\n filter={shouldVirtualize ? null : wrappedFilter}\n onValueChange={handleOnValueChange}\n itemToStringLabel={itemToStringLabel}\n isItemEqualToValue={isItemEqualToValue}\n itemToStringValue={wrappedItemToStringValue}\n onOpenChangeComplete={handleOnOpenChangeComplete}\n disabled={disabled}\n inputRef={inputRef}\n inputValue={inputValue}\n onInputValueChange={handleInputValueChange}\n virtualized={shouldVirtualize}\n onItemHighlighted={(_, details) => {\n if (shouldVirtualize && details.reason === 'keyboard') {\n virtualizer.scrollToIndex(details.index);\n }\n }}\n >\n <ComboboxInputGroup\n variant={variant}\n sizing={sizing}\n state={state}\n focusVariant={focusVariant}\n className={className}\n >\n {prefix && <InputGroup.Addon align=\"inline-start\">{prefix}</InputGroup.Addon>}\n <ComboboxInput id={id} placeholder={placeholder} disabled={disabled} />\n <InputGroup.Addon align=\"inline-end\">\n {allowClear && (\n <InputGroup.Button asChild aria-label=\"Clear\" disabled={disabled}>\n <BaseCombobox.Clear>\n <X className=\"tw:size-4\" />\n </BaseCombobox.Clear>\n </InputGroup.Button>\n )}\n <InputGroup.Button disabled={disabled} asChild aria-label=\"Open combobox\">\n <BaseCombobox.Trigger>\n <ChevronDown className=\"tw:size-4\" />\n </BaseCombobox.Trigger>\n </InputGroup.Button>\n </InputGroup.Addon>\n </ComboboxInputGroup>\n <ComboboxContent>\n <ComboboxEmpty>{empty}</ComboboxEmpty>\n {shouldVirtualize ? (\n <ComboboxList ref={setListElement}>\n <div\n style={{\n position: 'relative',\n width: '100%',\n height: `${virtualizer.getTotalSize()}px`,\n }}\n >\n {virtualizer.getVirtualItems().map((row) => {\n const item = virtualItems[row.index];\n if (item === undefined) return null;\n return (\n <div\n key={row.key}\n data-index={row.index}\n ref={virtualizer.measureElement}\n style={rowStyle(row.start)}\n >\n {renderItem(item, row.index)}\n </div>\n );\n })}\n </div>\n </ComboboxList>\n ) : (\n <ComboboxList>\n {(itemOrGroup: Value | GroupShape) => {\n if (isCreatableItem(itemOrGroup))\n return (\n <Combobox.Item value={itemOrGroup} icon={<Plus />}>\n {queryToCreateLabel(itemOrGroup.value)}\n </Combobox.Item>\n );\n\n if (isGroupItem(itemOrGroup)) {\n const maybeCreatable = itemOrGroup.items[0];\n\n if (isCreatableItem(maybeCreatable)) {\n return (\n <Combobox.Item value={maybeCreatable} icon={<Plus />}>\n {queryToCreateLabel(maybeCreatable.value)}\n </Combobox.Item>\n );\n }\n\n const groupLabel = groupToLabel(itemOrGroup);\n\n return (\n <Combobox.Group items={itemOrGroup.items}>\n {groupLabel && <Combobox.GroupLabel>{groupLabel}</Combobox.GroupLabel>}\n {/* Don't forward `renderItem` by reference — the collection passes its\n group-local index, which ComboboxItem uses verbatim and breaks keyboard\n nav. Drop it so the item falls back to its own global list index. */}\n <Combobox.GroupList>{(item: Value) => renderItem(item)}</Combobox.GroupList>\n </Combobox.Group>\n );\n }\n\n return renderItem(itemOrGroup);\n }}\n </ComboboxList>\n )}\n </ComboboxContent>\n </BaseCombobox.Root>\n );\n};\n\n// Base\nCombobox.Root = ComboboxRoot;\nCombobox.InputGroup = ComboboxInputGroup;\nCombobox.Input = ComboboxInput;\nCombobox.Content = ComboboxContent;\nCombobox.List = ComboboxList;\nCombobox.Item = ComboboxItem;\nCombobox.Empty = ComboboxEmpty;\nCombobox.Value = BaseCombobox.Value;\nCombobox.Separator = ComboboxSeparator;\n\n// Group\nCombobox.Group = ComboboxGroup;\nCombobox.GroupLabel = ComboboxGroupLabel;\nCombobox.GroupList = ComboboxCollection;\n\n// Chips\nCombobox.Chips = ComboboxChips;\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Form-k6PH-em3.js","names":[],"sources":["../src/blocks/Form/components/FormBody.tsx","../src/blocks/Form/components/SubmitButton.tsx","../src/blocks/Form/components/SubmitErrorAlert.tsx","../src/blocks/Form/connectors/CheckboxField.tsx","../src/blocks/Form/connectors/NumberField.tsx","../src/blocks/Form/connectors/OtpInputField.tsx","../src/blocks/Form/connectors/PasswordField.tsx","../src/blocks/Form/connectors/SelectField.tsx","../src/blocks/Form/connectors/SwitchField.tsx","../src/blocks/Form/connectors/TextareaField.tsx","../src/blocks/Form/connectors/TextField.tsx","../src/blocks/Form/formHook.ts","../src/blocks/Form/setServerFieldErrors.ts","../src/blocks/Form/setSubmitError.ts"],"sourcesContent":["import type { ComponentProps, ReactNode } from 'react';\n\nimport { cn } from '../../../utils';\nimport { useFormContext } from '../contexts';\n\ntype Props = {\n children: ReactNode;\n} & Omit<ComponentProps<'form'>, 'onSubmit'>;\n\nexport const FormBody = ({ children, className, ...formProps }: Props) => {\n const form = useFormContext();\n\n return (\n <form\n {...formProps}\n className={cn('tw:flex tw:flex-col tw:gap-4', className)}\n onSubmit={(e) => {\n e.preventDefault();\n e.stopPropagation();\n void form.handleSubmit();\n }}\n >\n {children}\n </form>\n );\n};\n","import type { ComponentProps, ReactNode } from 'react';\n\nimport { Button } from '../../../components/Button';\nimport { useFormContext } from '../contexts';\n\ntype Props = {\n children?: ReactNode;\n} & Omit<ComponentProps<typeof Button>, 'type' | 'isLoading' | 'disabled'>;\n\nexport const SubmitButton = ({ children = 'Submit', ...buttonProps }: Props) => {\n const form = useFormContext();\n\n return (\n <form.Subscribe\n selector={(state) => ({ isSubmitting: state.isSubmitting, canSubmit: state.canSubmit })}\n >\n {({ isSubmitting, canSubmit }) => (\n <Button\n {...buttonProps}\n type=\"submit\"\n isLoading={isSubmitting}\n disabled={!canSubmit || isSubmitting}\n >\n {children}\n </Button>\n )}\n </form.Subscribe>\n );\n};\n","import { Alert } from '../../../components/Alert';\nimport { useFormContext } from '../contexts';\n\n/**\n * Renders the form-level submit error (set via `setSubmitError` → `errorMap.onSubmit`) as an error\n * `Alert`. Place inside `form.FormBody`, typically just above the submit button. Renders nothing when\n * there is no submit error.\n */\nexport const SubmitErrorAlert = () => {\n const form = useFormContext();\n\n return (\n <form.Subscribe selector={(state) => state.errorMap.onSubmit}>\n {(submitError) =>\n typeof submitError === 'string' ? <Alert variant=\"error\" title={submitError} /> : null\n }\n </form.Subscribe>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport { Checkbox } from '../../../components/Checkbox';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\n// Checkbox owns its own label + description (via children), so only the wrapper className applies.\ntype Props = Pick<FieldItemProps, 'className'> &\n Omit<ComponentProps<typeof Checkbox>, 'id' | 'name' | 'checked' | 'onCheckedChange'>;\n\nexport const CheckboxField = ({ className, children, ...checkboxProps }: Props) => {\n // Strictly boolean: coerce Radix's `'indeterminate'` to `false` so a non-boolean never leaks into\n // form state (submit payloads / validators). `'indeterminate'` stays a purely visual state.\n const field = useFieldContext<boolean>();\n\n return (\n <FieldItem className={className}>\n {(control) => (\n <Checkbox\n {...checkboxProps}\n {...control}\n checked={field.state.value ?? false}\n onCheckedChange={(checked) => field.handleChange(checked === true)}\n onBlur={field.handleBlur}\n >\n {children}\n </Checkbox>\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport type { FormGroup } from '../../FormGroup';\nimport { NumberInput } from '../../NumberInput';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<\n ComponentProps<typeof FormGroup.NumberInput>,\n 'id' | 'name' | 'value' | 'onValueChange' | 'onBlur'\n >;\n\nexport const NumberField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n ...inputProps\n}: Props) => {\n const field = useFieldContext<number | null>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <NumberInput\n {...inputProps}\n {...control}\n value={field.state.value ?? null}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import { OtpInput, type OtpInputProps } from '../../OtpInput';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<\n OtpInputProps,\n | 'value'\n | 'onChange'\n | 'children'\n | 'id'\n | 'name'\n | 'aria-describedby'\n | 'aria-required'\n | 'aria-invalid'\n >;\n\nexport const OtpInputField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n maxLength,\n ...otpProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <OtpInput\n {...otpProps}\n {...control}\n maxLength={maxLength}\n value={field.state.value ?? ''}\n onChange={field.handleChange}\n onBlur={field.handleBlur}\n >\n <OtpInput.Group>\n {Array.from({ length: maxLength }, (_, index) => (\n <OtpInput.Slot key={index} index={index} />\n ))}\n </OtpInput.Group>\n </OtpInput>\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport { PasswordInput } from '../../PasswordInput';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<ComponentProps<typeof PasswordInput>, 'id' | 'name' | 'value' | 'onValueChange' | 'onBlur'>;\n\nexport const PasswordField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n ...inputProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <PasswordInput\n {...inputProps}\n {...control}\n value={field.state.value ?? ''}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport { Select, type SelectItem, type SelectItemGroup } from '../../../components/Select';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<\n ComponentProps<typeof Select>,\n // Owned by the field / `FieldItem` — see the connector rules in AGENTS.md.\n | 'id'\n | 'name'\n | 'value'\n | 'defaultValue'\n | 'onValueChange'\n | 'onBlur'\n | 'aria-describedby'\n | 'aria-invalid'\n | 'aria-required'\n // `className` styles the field frame, so the trigger gets its own prop below.\n | 'className'\n | 'items'\n > & {\n items: readonly (SelectItem | SelectItemGroup)[];\n triggerClassName?: string;\n };\n\nexport const SelectField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n triggerClassName,\n ...selectProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n // `required` deliberately stays on `FieldItem` (which turns it into `aria-required` via\n // `control`) and is not forwarded to the Radix root: a required hidden native select would\n // fail browser constraint validation and swallow the submit event before the form sees it.\n <Select\n {...selectProps}\n {...control}\n className={triggerClassName ?? 'tw:w-full'}\n value={field.state.value ?? ''}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport { Switch } from '../../../components/Switch';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\n// Switch owns its own label + description (via children), so only the wrapper className applies.\ntype Props = Pick<FieldItemProps, 'className'> &\n Omit<ComponentProps<typeof Switch>, 'id' | 'name' | 'checked' | 'onCheckedChange'>;\n\nexport const SwitchField = ({ className, children, ...switchProps }: Props) => {\n const field = useFieldContext<boolean>();\n\n return (\n <FieldItem className={className}>\n {(control) => (\n <Switch\n {...switchProps}\n {...control}\n checked={field.state.value ?? false}\n onCheckedChange={field.handleChange}\n onBlur={field.handleBlur}\n >\n {children}\n </Switch>\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport type { FormGroup } from '../../FormGroup';\nimport { Textarea } from '../../Textarea';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<\n ComponentProps<typeof FormGroup.Textarea>,\n 'id' | 'name' | 'value' | 'onValueChange' | 'onBlur'\n >;\n\nexport const TextareaField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n ...inputProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <Textarea\n {...inputProps}\n {...control}\n value={field.state.value ?? ''}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport type { FormGroup } from '../../FormGroup';\nimport { TextInput } from '../../TextInput';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<ComponentProps<typeof FormGroup.TextInput>, 'id' | 'name' | 'value' | 'onChange' | 'onBlur'>;\n\nexport const TextField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n ...inputProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <TextInput\n {...inputProps}\n {...control}\n value={field.state.value ?? ''}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import { createFormHook } from '@tanstack/react-form';\n\nimport { FormBody } from './components/FormBody';\nimport { SubmitButton } from './components/SubmitButton';\nimport { SubmitErrorAlert } from './components/SubmitErrorAlert';\nimport { CheckboxField } from './connectors/CheckboxField';\nimport { NumberField } from './connectors/NumberField';\nimport { OtpInputField } from './connectors/OtpInputField';\nimport { PasswordField } from './connectors/PasswordField';\nimport { SelectField } from './connectors/SelectField';\nimport { SwitchField } from './connectors/SwitchField';\nimport { TextareaField } from './connectors/TextareaField';\nimport { TextField } from './connectors/TextField';\nimport { fieldContext, formContext } from './contexts';\n\n/**\n * Typed form hook + `withForm` binding for the design system.\n *\n * **When to use:** any form layout that has validation, server-side errors, or a submit state — pages,\n * modals, drawers, multi-step wizards. Use `useAppForm({ defaultValues, validators, onSubmit })` at the\n * top of the form component, then render the typed `field.TextField` / `field.NumberField` /\n * `field.PasswordField` / `field.TextareaField` / `field.SelectField` / `field.CheckboxField` /\n * `field.SwitchField` / `field.OtpInputField` connectors inside `form.AppForm` → `form.FormBody`. Submit via `form.SubmitButton`.\n * `MultiComboboxField` (from `@keboola/design`) and `CodeEditorField` (from `@keboola/design/editors`)\n * compose the same way but are imported by name — `fieldComponents` does not shake per key, so a\n * control with heavy dependencies would be carried by every consumer. See their own docs.\n * **When NOT to use:** for a single uncontrolled `<input>` use `TextInput` directly; for a bare label + input\n * pair without validation use `FormGroup` + `FormGroup.TextInput`.\n * **Composition:** schema-library agnostic — pass any [Standard Schema](https://standardschema.dev/) validator\n * (zod, valibot, …) in the consuming app. Server errors come from `setServerFieldErrors` (also re-exported).\n *\n * @see RECIPES.md#modal-form — for the canonical form-in-modal composition\n */\nexport const { useAppForm, withForm } = createFormHook({\n fieldContext,\n formContext,\n fieldComponents: {\n TextField,\n NumberField,\n PasswordField,\n TextareaField,\n SelectField,\n CheckboxField,\n SwitchField,\n OtpInputField,\n },\n formComponents: {\n FormBody,\n SubmitButton,\n SubmitErrorAlert,\n },\n});\n","import type { AnyFormApi } from '@tanstack/react-form';\n\nexport type ServerFieldError = {\n field: string;\n message: string;\n};\n\n/**\n * Map a list of server-returned field errors onto a TanStack form instance.\n *\n * - Marks each field blurred — that is what `FieldItem` gates the error reveal on.\n * - `isTouched` alongside it, for anything reading TanStack's own meta (`canSubmit`, dirty checks).\n * - Both are needed. Called from a mutation's `onError` there is no submit attempt to fall back on, so\n * without `isBlurred` the message would sit in `errorMap` and render nowhere.\n */\nexport const setServerFieldErrors = (form: AnyFormApi, errors: readonly ServerFieldError[]) => {\n for (const { field, message } of errors) {\n form.setFieldMeta(field, (meta) => ({\n ...meta,\n isBlurred: true,\n isTouched: true,\n errors: [message],\n errorMap: { ...meta.errorMap, onServer: message },\n }));\n }\n};\n","import type { AnyFormApi } from '@tanstack/react-form';\n\n/**\n * Set a **form-level** submit error on a TanStack form instance — a failed submission that isn't tied\n * to a single field (bad credentials, 5xx, network). Stored on `errorMap.onSubmit` and rendered by\n * `SubmitErrorAlert`. For field-specific server errors use `setServerFieldErrors` instead.\n *\n * Note: any error entry makes the form \"invalid\", so pair this with `canSubmitWhenInvalid: true` on\n * the form to keep the submit button retryable (a resubmit re-runs the validators and clears it).\n */\nexport const setSubmitError = (form: AnyFormApi, message: string) => {\n form.setErrorMap({ onSubmit: { form: message, fields: {} } });\n};\n"],"mappings":"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"}
|