@signalflare-ai/ui 1.1.0 → 1.3.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/CHANGELOG.md +102 -5
- package/README.md +1 -1
- package/ai/component-registry.json +531 -79
- package/ai/component-registry.md +4067 -6
- package/ai/schemas.ts +6 -1
- package/dist/.build-complete +1 -1
- package/dist/ai/schemas.d.ts +76 -58
- package/dist/ai/schemas.d.ts.map +1 -1
- package/dist/{ai-actions-DSVeQn4e.js → ai-actions-CBfz5XEf.js} +4 -4
- package/dist/{ai-actions-DSVeQn4e.js.map → ai-actions-CBfz5XEf.js.map} +1 -1
- package/dist/{ai-agent-card-BXHwhWAU.js → ai-agent-card-CByAUe0q.js} +3 -3
- package/dist/ai-agent-card-CByAUe0q.js.map +1 -0
- package/dist/{ai-approval-aa0qvjFN.js → ai-approval-Ci8N70a7.js} +4 -3
- package/dist/{ai-approval-aa0qvjFN.js.map → ai-approval-Ci8N70a7.js.map} +1 -1
- package/dist/{ai-code-block-BgtIxtZZ.js → ai-code-block-P9TJHvaC.js} +37 -39
- package/dist/ai-code-block-P9TJHvaC.js.map +1 -0
- package/dist/ai-conversation-Qslfdi1t.js +228 -0
- package/dist/ai-conversation-Qslfdi1t.js.map +1 -0
- package/dist/{ai-info-banner-uFxHHwBA.js → ai-info-banner-B_9vtGK3.js} +8 -4
- package/dist/ai-info-banner-B_9vtGK3.js.map +1 -0
- package/dist/{ai-message-BjnFznXy.js → ai-message-Ci3gwM7G.js} +29 -10
- package/dist/ai-message-Ci3gwM7G.js.map +1 -0
- package/dist/{ai-mission-header-08__gULL.js → ai-mission-header-CaBc19-t.js} +2 -2
- package/dist/{ai-mission-header-08__gULL.js.map → ai-mission-header-CaBc19-t.js.map} +1 -1
- package/dist/{ai-part-group-DBtgTgAn.js → ai-part-group-Dx1Mr92B.js} +5 -4
- package/dist/ai-part-group-Dx1Mr92B.js.map +1 -0
- package/dist/{ai-prompt-input-CuluUzpf.js → ai-prompt-input-Bm4XoSj2.js} +44 -55
- package/dist/ai-prompt-input-Bm4XoSj2.js.map +1 -0
- package/dist/{ai-question-CHHoDJMg.js → ai-question-OyJovxGe.js} +4 -3
- package/dist/{ai-question-CHHoDJMg.js.map → ai-question-OyJovxGe.js.map} +1 -1
- package/dist/{ai-reasoning-CnL6ZSr5.js → ai-reasoning-BLfBXx3F.js} +9 -5
- package/dist/ai-reasoning-BLfBXx3F.js.map +1 -0
- package/dist/{ai-response-BEUg3xvd.js → ai-response-hbVCZJmo.js} +9 -4
- package/dist/ai-response-hbVCZJmo.js.map +1 -0
- package/dist/{ai-shimmer-By5_L05p.js → ai-shimmer-BamNMNK3.js} +2 -2
- package/dist/{ai-shimmer-By5_L05p.js.map → ai-shimmer-BamNMNK3.js.map} +1 -1
- package/dist/{ai-status-badge-BGYGWYF6.js → ai-status-badge-BZLczdkI.js} +2 -2
- package/dist/{ai-status-badge-BGYGWYF6.js.map → ai-status-badge-BZLczdkI.js.map} +1 -1
- package/dist/{ai-streaming-text-CMfoThV0.js → ai-streaming-text-DgYu64UH.js} +44 -16
- package/dist/ai-streaming-text-DgYu64UH.js.map +1 -0
- package/dist/{ai-subagent-DcPRqkAA.js → ai-subagent-p97AI1h9.js} +14 -6
- package/dist/ai-subagent-p97AI1h9.js.map +1 -0
- package/dist/{ai-suggestion-MgeCg5Ar.js → ai-suggestion-Bj6vF7CT.js} +3 -3
- package/dist/{ai-suggestion-MgeCg5Ar.js.map → ai-suggestion-Bj6vF7CT.js.map} +1 -1
- package/dist/{ai-task-list-Da9zIm00.js → ai-task-list-C_UQYpk9.js} +15 -6
- package/dist/ai-task-list-C_UQYpk9.js.map +1 -0
- package/dist/{ai-timeline-Cwu045IR.js → ai-timeline-CePL1LOU.js} +3 -3
- package/dist/ai-timeline-CePL1LOU.js.map +1 -0
- package/dist/{ai-tool-Cn1O4xjP.js → ai-tool-CfRcwmHT.js} +35 -16
- package/dist/ai-tool-CfRcwmHT.js.map +1 -0
- package/dist/{ai-usage-bar-DjS12DMp.js → ai-usage-bar-45pVRCGA.js} +2 -2
- package/dist/{ai-usage-bar-DjS12DMp.js.map → ai-usage-bar-45pVRCGA.js.map} +1 -1
- package/dist/{badge-D_eaA6wv.js → badge-Beb-6uut.js} +5 -5
- package/dist/{badge-D_eaA6wv.js.map → badge-Beb-6uut.js.map} +1 -1
- package/dist/{banner-B_6oBrsu.js → banner-CCEksxPg.js} +8 -3
- package/dist/banner-CCEksxPg.js.map +1 -0
- package/dist/{breadcrumbs-BlmeYfgq.js → breadcrumbs-HiTmgaZ4.js} +5 -5
- package/dist/{breadcrumbs-BlmeYfgq.js.map → breadcrumbs-HiTmgaZ4.js.map} +1 -1
- package/dist/{button-De0267YU.js → button-BHOgXJRU.js} +4 -4
- package/dist/{button-De0267YU.js.map → button-BHOgXJRU.js.map} +1 -1
- package/dist/catalog.js +1 -1
- package/dist/catalog.js.map +1 -1
- package/dist/{chart-BK3sVPnD.js → chart-B9FfZdKs.js} +7 -7
- package/dist/chart-B9FfZdKs.js.map +1 -0
- package/dist/{checkbox-DYhUmZNw.js → checkbox-Cy_OCyay.js} +3 -3
- package/dist/{checkbox-DYhUmZNw.js.map → checkbox-Cy_OCyay.js.map} +1 -1
- package/dist/{clipboard-text-ssybngLw.js → clipboard-text-CKSvNp9L.js} +6 -5
- package/dist/clipboard-text-CKSvNp9L.js.map +1 -0
- package/dist/{cn-YROP2_ox.js → cn-CmAOpn49.js} +2 -2
- package/dist/{cn-YROP2_ox.js.map → cn-CmAOpn49.js.map} +1 -1
- package/dist/{code-Cx-QSoOT.js → code-JsQz-0G_.js} +4 -4
- package/dist/{code-Cx-QSoOT.js.map → code-JsQz-0G_.js.map} +1 -1
- package/dist/{collapsible-DWsXeXmS.js → collapsible-1kOZ-89L.js} +2 -2
- package/dist/{collapsible-DWsXeXmS.js.map → collapsible-1kOZ-89L.js.map} +1 -1
- package/dist/{combobox-C0iW6a0r.js → combobox-CQwDmqgA.js} +4 -4
- package/dist/{combobox-C0iW6a0r.js.map → combobox-CQwDmqgA.js.map} +1 -1
- package/dist/command-line/cli.js +3 -3
- package/dist/{command-palette-DGzioeki.js → command-palette-Bkuv3e6o.js} +20 -5
- package/dist/command-palette-Bkuv3e6o.js.map +1 -0
- package/dist/components/ai-actions.js +1 -1
- package/dist/components/ai-agent-card.js +1 -1
- package/dist/components/ai-approval.js +1 -1
- package/dist/components/ai-code-block.js +1 -1
- package/dist/components/ai-conversation.js +2 -2
- package/dist/components/ai-info-banner.js +1 -1
- package/dist/components/ai-message.js +1 -1
- package/dist/components/ai-mission-header.js +1 -1
- package/dist/components/ai-part-group.js +1 -1
- package/dist/components/ai-prompt-input.js +1 -1
- package/dist/components/ai-question.js +1 -1
- package/dist/components/ai-reasoning.js +1 -1
- package/dist/components/ai-response.js +1 -1
- package/dist/components/ai-shimmer.js +1 -1
- package/dist/components/ai-status-badge.js +1 -1
- package/dist/components/ai-streaming-text.js +2 -2
- package/dist/components/ai-subagent.js +1 -1
- package/dist/components/ai-suggestion.js +1 -1
- package/dist/components/ai-task-list.js +1 -1
- package/dist/components/ai-timeline.js +1 -1
- package/dist/components/ai-tool.js +1 -1
- package/dist/components/ai-usage-bar.js +1 -1
- package/dist/components/badge.js +1 -1
- package/dist/components/banner.js +1 -1
- package/dist/components/breadcrumbs.js +1 -1
- package/dist/components/button.js +1 -1
- package/dist/components/chart.js +2 -2
- package/dist/components/checkbox.js +1 -1
- package/dist/components/clipboard-text.js +1 -1
- package/dist/components/code.js +1 -1
- package/dist/components/collapsible.js +1 -1
- package/dist/components/combobox.js +1 -1
- package/dist/components/command-palette.js +1 -1
- package/dist/components/data-grid.js +1 -1
- package/dist/components/date-picker.js +1 -1
- package/dist/components/date-range-picker.js +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/dropdown.js +1 -1
- package/dist/components/empty.js +1 -1
- package/dist/components/field.js +1 -1
- package/dist/components/filters.js +1 -1
- package/dist/components/flow.js +1 -1
- package/dist/components/grid.js +1 -1
- package/dist/components/input.js +2 -2
- package/dist/components/label.js +1 -1
- package/dist/components/layer-card.js +1 -1
- package/dist/components/link.js +3 -3
- package/dist/components/link.js.map +1 -1
- package/dist/components/loader.js +2 -2
- package/dist/components/menubar.js +1 -1
- package/dist/components/meter.js +1 -1
- package/dist/components/pagination.js +1 -1
- package/dist/components/popover.js +1 -1
- package/dist/components/radio.js +1 -1
- package/dist/components/select.js +1 -1
- package/dist/components/sensitive-input.js +1 -1
- package/dist/components/sidebar.js +1 -1
- package/dist/components/signalflare-ai-logo.js +1 -1
- package/dist/components/sparkline.js +1 -1
- package/dist/components/stat-card.js +1 -1
- package/dist/components/surface.js +1 -1
- package/dist/components/switch.js +1 -1
- package/dist/components/table.js +1 -1
- package/dist/components/tabs.js +1 -1
- package/dist/components/text-roll.js +1 -1
- package/dist/components/text.js +1 -1
- package/dist/components/theme-toggle.js +1 -1
- package/dist/components/toast.js +1 -1
- package/dist/components/tooltip.js +1 -1
- package/dist/components/use-agent-harness.js +1 -1
- package/dist/{data-grid-CG76N_hK.js → data-grid-DDSFMHud.js} +136 -53
- package/dist/data-grid-DDSFMHud.js.map +1 -0
- package/dist/{date-picker-Dqg9L4xu.js → date-picker-O34AqG3f.js} +2 -2
- package/dist/{date-picker-Dqg9L4xu.js.map → date-picker-O34AqG3f.js.map} +1 -1
- package/dist/{date-range-picker-D75LLINc.js → date-range-picker-YKYvum_r.js} +29 -39
- package/dist/{date-range-picker-D75LLINc.js.map → date-range-picker-YKYvum_r.js.map} +1 -1
- package/dist/{dialog-CyHEQXEY.js → dialog-DYqu4aDO.js} +3 -3
- package/dist/{dialog-CyHEQXEY.js.map → dialog-DYqu4aDO.js.map} +1 -1
- package/dist/{dist-1-gcEL2L.js → dist-6AtBsaJE.js} +153 -47
- package/dist/dist-6AtBsaJE.js.map +1 -0
- package/dist/{dropdown-qnEYRFXZ.js → dropdown-XzbnRLYR.js} +15 -5
- package/dist/dropdown-XzbnRLYR.js.map +1 -0
- package/dist/{echart-DURZEyai.js → echart-DGBIVAv1.js} +23 -57
- package/dist/{echart-DURZEyai.js.map → echart-DGBIVAv1.js.map} +1 -1
- package/dist/{empty-D2TypIId.js → empty-C1tAkawe.js} +12 -7
- package/dist/empty-C1tAkawe.js.map +1 -0
- package/dist/{field-Y_UK1_Cg.js → field-DBpFzzBS.js} +3 -3
- package/dist/{field-Y_UK1_Cg.js.map → field-DBpFzzBS.js.map} +1 -1
- package/dist/{filters-Bw_U6ZTx.js → filters-SmEl93za.js} +10 -10
- package/dist/filters-SmEl93za.js.map +1 -0
- package/dist/{flow-BRsYUCJa.js → flow-BLzgbq1T.js} +6 -6
- package/dist/flow-BLzgbq1T.js.map +1 -0
- package/dist/genui.js +2 -2
- package/dist/genui.js.map +1 -1
- package/dist/{grid-qUAN9hFx.js → grid-CifjQL-5.js} +2 -2
- package/dist/{grid-qUAN9hFx.js.map → grid-CifjQL-5.js.map} +1 -1
- package/dist/{highlight-to-react-ClEfL81q.js → highlight-to-react-DN9dUCS2.js} +9 -15
- package/dist/highlight-to-react-DN9dUCS2.js.map +1 -0
- package/dist/index.js +72 -72
- package/dist/index.js.map +1 -1
- package/dist/{input-DddtBN-g.js → input-COmx2M_R.js} +5 -5
- package/dist/{input-DddtBN-g.js.map → input-COmx2M_R.js.map} +1 -1
- package/dist/{input-DXYUjGgD.js → input-GkfMQZC_.js} +3 -3
- package/dist/{input-DXYUjGgD.js.map → input-GkfMQZC_.js.map} +1 -1
- package/dist/{label-QtJxtJ4u.js → label-CiGZ464N.js} +3 -3
- package/dist/{label-QtJxtJ4u.js.map → label-CiGZ464N.js.map} +1 -1
- package/dist/{layer-card-BME0eljh.js → layer-card-8l8GuLQr.js} +2 -2
- package/dist/{layer-card-BME0eljh.js.map → layer-card-8l8GuLQr.js.map} +1 -1
- package/dist/layout-CWBE0qwx.js +6207 -0
- package/dist/layout-CWBE0qwx.js.map +1 -0
- package/dist/{link-provider-BUZKXaNE.js → link-provider-BSn8YJon.js} +2 -2
- package/dist/link-provider-BSn8YJon.js.map +1 -0
- package/dist/{loader-DAcc-Uag.js → loader-BEMz8pJO.js} +1 -1
- package/dist/{loader-DAcc-Uag.js.map → loader-BEMz8pJO.js.map} +1 -1
- package/dist/measured-text-CXkdw9Yr.js +305 -0
- package/dist/measured-text-CXkdw9Yr.js.map +1 -0
- package/dist/{menubar-C8NzAjfd.js → menubar-CoOr4ocj.js} +3 -3
- package/dist/{menubar-C8NzAjfd.js.map → menubar-CoOr4ocj.js.map} +1 -1
- package/dist/{meter-CpmTenEr.js → meter-Pf_VOl59.js} +2 -2
- package/dist/{meter-CpmTenEr.js.map → meter-Pf_VOl59.js.map} +1 -1
- package/dist/{pagination-BVqdlONY.js → pagination-DSY279Ta.js} +2 -2
- package/dist/{pagination-BVqdlONY.js.map → pagination-DSY279Ta.js.map} +1 -1
- package/dist/{popover-BRQZ2b6z.js → popover-BY-e9co1.js} +2 -2
- package/dist/{popover-BRQZ2b6z.js.map → popover-BY-e9co1.js.map} +1 -1
- package/dist/{radio-BNSwOt3B.js → radio-DZwL13j0.js} +2 -2
- package/dist/{radio-BNSwOt3B.js.map → radio-DZwL13j0.js.map} +1 -1
- package/dist/{select-1w2aebGQ.js → select-BFifYqHA.js} +6 -6
- package/dist/{select-1w2aebGQ.js.map → select-BFifYqHA.js.map} +1 -1
- package/dist/{sensitive-input-82Cez3vj.js → sensitive-input-DHLZcM73.js} +4 -4
- package/dist/{sensitive-input-82Cez3vj.js.map → sensitive-input-DHLZcM73.js.map} +1 -1
- package/dist/{sidebar-CAsCmSpM.js → sidebar-odGsdvG4.js} +6 -7
- package/dist/sidebar-odGsdvG4.js.map +1 -0
- package/dist/{signalflare-ai-logo-DDhxMJD6.js → signalflare-ai-logo-CNaDT_w8.js} +2 -2
- package/dist/{signalflare-ai-logo-DDhxMJD6.js.map → signalflare-ai-logo-CNaDT_w8.js.map} +1 -1
- package/dist/{skeleton-line-Do3UmGk9.js → skeleton-line-CxxYVTO2.js} +2 -2
- package/dist/{skeleton-line-Do3UmGk9.js.map → skeleton-line-CxxYVTO2.js.map} +1 -1
- package/dist/{sparkline-DdbeM4Ai.js → sparkline-BQ-4j2W2.js} +2 -2
- package/dist/{sparkline-DdbeM4Ai.js.map → sparkline-BQ-4j2W2.js.map} +1 -1
- package/dist/src/blocks/agent-harness/agent-harness.d.ts.map +1 -1
- package/dist/src/blocks/agent-harness/agent-harness.tsx +40 -16
- package/dist/src/blocks/commander/commander.tsx +15 -15
- package/dist/src/blocks/map-block/map-block.d.ts.map +1 -1
- package/dist/src/blocks/map-block/map-block.tsx +11 -7
- package/dist/src/components/ai-approval/ai-approval.d.ts.map +1 -1
- package/dist/src/components/ai-code-block/ai-code-block.d.ts +14 -13
- package/dist/src/components/ai-code-block/ai-code-block.d.ts.map +1 -1
- package/dist/src/components/ai-conversation/ai-conversation.d.ts +69 -37
- package/dist/src/components/ai-conversation/ai-conversation.d.ts.map +1 -1
- package/dist/src/components/ai-conversation/index.d.ts +2 -1
- package/dist/src/components/ai-conversation/index.d.ts.map +1 -1
- package/dist/src/components/ai-conversation/measurement-constants.d.ts +30 -0
- package/dist/src/components/ai-conversation/measurement-constants.d.ts.map +1 -0
- package/dist/src/components/ai-info-banner/ai-info-banner.d.ts.map +1 -1
- package/dist/src/components/ai-message/ai-message.d.ts +3 -0
- package/dist/src/components/ai-message/ai-message.d.ts.map +1 -1
- package/dist/src/components/ai-part-group/ai-part-group.d.ts.map +1 -1
- package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts +13 -3
- package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -1
- package/dist/src/components/ai-prompt-input/controller.d.ts.map +1 -1
- package/dist/src/components/ai-prompt-input/index.d.ts +1 -1
- package/dist/src/components/ai-prompt-input/index.d.ts.map +1 -1
- package/dist/src/components/ai-prompt-input/types.d.ts.map +1 -1
- package/dist/src/components/ai-question/ai-question.d.ts.map +1 -1
- package/dist/src/components/ai-reasoning/ai-reasoning.d.ts.map +1 -1
- package/dist/src/components/ai-response/ai-response.d.ts +12 -1
- package/dist/src/components/ai-response/ai-response.d.ts.map +1 -1
- package/dist/src/components/ai-streaming-text/ai-streaming-text.d.ts +27 -0
- package/dist/src/components/ai-streaming-text/ai-streaming-text.d.ts.map +1 -1
- package/dist/src/components/ai-streaming-text/index.d.ts +1 -1
- package/dist/src/components/ai-streaming-text/index.d.ts.map +1 -1
- package/dist/src/components/ai-subagent/ai-subagent.d.ts.map +1 -1
- package/dist/src/components/ai-task-list/ai-task-list.d.ts.map +1 -1
- package/dist/src/components/ai-tool/ai-tool.d.ts.map +1 -1
- package/dist/src/components/banner/banner.d.ts.map +1 -1
- package/dist/src/components/chart/echart.d.ts.map +1 -1
- package/dist/src/components/clipboard-text/clipboard-text.d.ts.map +1 -1
- package/dist/src/components/data-grid/data-grid.d.ts +2 -1
- package/dist/src/components/data-grid/data-grid.d.ts.map +1 -1
- package/dist/src/components/data-grid/features.d.ts +20 -0
- package/dist/src/components/data-grid/features.d.ts.map +1 -0
- package/dist/src/components/data-grid/types.d.ts +38 -7
- package/dist/src/components/data-grid/types.d.ts.map +1 -1
- package/dist/src/components/empty/empty.d.ts.map +1 -1
- package/dist/src/components/filters/filters.d.ts.map +1 -1
- package/dist/src/components/flow/use-children.d.ts +1 -1
- package/dist/src/components/link/link.d.ts.map +1 -1
- package/dist/src/components/sidebar/sidebar.d.ts +1 -1
- package/dist/src/components/signalflare-ai-logo/signalflare-ai-logo.d.ts.map +1 -1
- package/dist/src/components/stat-card/stat-card.d.ts +5 -0
- package/dist/src/components/stat-card/stat-card.d.ts.map +1 -1
- package/dist/src/components/text/text.d.ts +36 -1
- package/dist/src/components/text/text.d.ts.map +1 -1
- package/dist/src/components/text-roll/text-roll.d.ts.map +1 -1
- package/dist/src/components/theme-toggle/theme-toggle.d.ts.map +1 -1
- package/dist/src/components/toast/toast.d.ts.map +1 -1
- package/dist/src/components/tooltip/tooltip.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/utils/highlight-to-react.d.ts.map +1 -1
- package/dist/src/utils/index.d.ts +2 -0
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/measured-text.d.ts +40 -0
- package/dist/src/utils/measured-text.d.ts.map +1 -0
- package/dist/src/utils/use-measured-text.d.ts +59 -0
- package/dist/src/utils/use-measured-text.d.ts.map +1 -0
- package/dist/{stat-card-CEZscNh8.js → stat-card-Bspk4XFr.js} +30 -12
- package/dist/stat-card-Bspk4XFr.js.map +1 -0
- package/dist/styles/sf-binding.css +1 -1
- package/dist/styles/sf-standalone.css +2 -2
- package/dist/styles/shadcn.css +1 -1
- package/dist/styles/theme-minimal.css +9 -9
- package/dist/styles/theme-sf.css +14 -20
- package/dist/styles/theme-vesper.css +91 -0
- package/dist/{surface-BduI7Ehl.js → surface-CWdSFVUx.js} +3 -3
- package/dist/{surface-BduI7Ehl.js.map → surface-CWdSFVUx.js.map} +1 -1
- package/dist/{switch-CzZBRBL7.js → switch-TA4cByCJ.js} +5 -5
- package/dist/switch-TA4cByCJ.js.map +1 -0
- package/dist/{table-Rv4JMy0B.js → table-BM8JBGBs.js} +3 -3
- package/dist/{table-Rv4JMy0B.js.map → table-BM8JBGBs.js.map} +1 -1
- package/dist/{tabs-1cHrYoel.js → tabs-bnH2vGLv.js} +2 -2
- package/dist/{tabs-1cHrYoel.js.map → tabs-bnH2vGLv.js.map} +1 -1
- package/dist/{text-KJmGkwnf.js → text-iQ0YUFNg.js} +27 -6
- package/dist/text-iQ0YUFNg.js.map +1 -0
- package/dist/{text-roll-BZ3I1umc.js → text-roll-C3U2jd2u.js} +5 -2
- package/dist/text-roll-C3U2jd2u.js.map +1 -0
- package/dist/{theme-toggle-Bhu681D7.js → theme-toggle-BTVxD-fD.js} +10 -9
- package/dist/theme-toggle-BTVxD-fD.js.map +1 -0
- package/dist/{toast-Nw28a5Cx.js → toast-CgZVaAkw.js} +3 -3
- package/dist/{toast-Nw28a5Cx.js.map → toast-CgZVaAkw.js.map} +1 -1
- package/dist/{tooltip-Cb7QW-7H.js → tooltip-uobk6Oh-.js} +9 -3
- package/dist/tooltip-uobk6Oh-.js.map +1 -0
- package/dist/{use-agent-harness-BMyF8pTq.js → use-agent-harness-Dl8w6X5O.js} +3 -3
- package/dist/{use-agent-harness-BMyF8pTq.js.map → use-agent-harness-Dl8w6X5O.js.map} +1 -1
- package/dist/utils.js +4 -3
- package/package.json +27 -24
- package/scripts/component-registry/discovery.ts +11 -10
- package/scripts/component-registry/example-cleanup.ts +8 -8
- package/scripts/component-registry/index.ts +6 -6
- package/scripts/component-registry/schema-generator.ts +1 -1
- package/scripts/component-registry/sub-components.ts +35 -23
- package/scripts/component-registry/utils.ts +11 -11
- package/scripts/component-registry/variant-parser.ts +17 -15
- package/scripts/convert-demos-to-stories.ts +5 -5
- package/scripts/css-build.ts +1 -1
- package/scripts/theme-generator/config.ts +28 -146
- package/scripts/theme-generator/generate-css.ts +1 -2
- package/scripts/theme-generator/index.ts +0 -1
- package/scripts/theme-generator/migrate.ts +3 -3
- package/dist/ai-agent-card-BXHwhWAU.js.map +0 -1
- package/dist/ai-code-block-BgtIxtZZ.js.map +0 -1
- package/dist/ai-conversation-CArP7C8K.js +0 -184
- package/dist/ai-conversation-CArP7C8K.js.map +0 -1
- package/dist/ai-info-banner-uFxHHwBA.js.map +0 -1
- package/dist/ai-message-BjnFznXy.js.map +0 -1
- package/dist/ai-part-group-DBtgTgAn.js.map +0 -1
- package/dist/ai-prompt-input-CuluUzpf.js.map +0 -1
- package/dist/ai-reasoning-CnL6ZSr5.js.map +0 -1
- package/dist/ai-response-BEUg3xvd.js.map +0 -1
- package/dist/ai-streaming-text-CMfoThV0.js.map +0 -1
- package/dist/ai-subagent-DcPRqkAA.js.map +0 -1
- package/dist/ai-task-list-Da9zIm00.js.map +0 -1
- package/dist/ai-timeline-Cwu045IR.js.map +0 -1
- package/dist/ai-tool-Cn1O4xjP.js.map +0 -1
- package/dist/banner-B_6oBrsu.js.map +0 -1
- package/dist/chart-BK3sVPnD.js.map +0 -1
- package/dist/clipboard-text-ssybngLw.js.map +0 -1
- package/dist/command-palette-DGzioeki.js.map +0 -1
- package/dist/data-grid-CG76N_hK.js.map +0 -1
- package/dist/dist-1-gcEL2L.js.map +0 -1
- package/dist/dropdown-qnEYRFXZ.js.map +0 -1
- package/dist/empty-D2TypIId.js.map +0 -1
- package/dist/filters-Bw_U6ZTx.js.map +0 -1
- package/dist/flow-BRsYUCJa.js.map +0 -1
- package/dist/highlight-to-react-ClEfL81q.js.map +0 -1
- package/dist/link-provider-BUZKXaNE.js.map +0 -1
- package/dist/sidebar-CAsCmSpM.js.map +0 -1
- package/dist/stat-card-CEZscNh8.js.map +0 -1
- package/dist/styles/theme-blue-tint.css +0 -98
- package/dist/switch-CzZBRBL7.js.map +0 -1
- package/dist/text-KJmGkwnf.js.map +0 -1
- package/dist/text-roll-BZ3I1umc.js.map +0 -1
- package/dist/theme-toggle-Bhu681D7.js.map +0 -1
- package/dist/tooltip-Cb7QW-7H.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-prompt-input-Bm4XoSj2.js","names":[],"sources":["../../../node_modules/.bun/@tanstack+store@0.11.0/node_modules/@tanstack/store/dist/alien.js","../../../node_modules/.bun/@tanstack+store@0.11.0/node_modules/@tanstack/store/dist/atom.js","../../../node_modules/.bun/@tanstack+store@0.11.0/node_modules/@tanstack/store/dist/store.js","../../../node_modules/.bun/@tanstack+react-store@0.11.0+7492c01c6988791b/node_modules/@tanstack/react-store/dist/useSelector.js","../../../node_modules/.bun/@tanstack+react-store@0.11.0+7492c01c6988791b/node_modules/@tanstack/react-store/dist/useStore.js","../src/components/ai-prompt-input/controller.ts","../src/components/ai-prompt-input/ai-prompt-input.tsx"],"sourcesContent":["//#region src/alien.ts\nlet ReactiveFlags = /* @__PURE__ */ function(ReactiveFlags) {\n\tReactiveFlags[ReactiveFlags[\"None\"] = 0] = \"None\";\n\tReactiveFlags[ReactiveFlags[\"Mutable\"] = 1] = \"Mutable\";\n\tReactiveFlags[ReactiveFlags[\"Watching\"] = 2] = \"Watching\";\n\tReactiveFlags[ReactiveFlags[\"RecursedCheck\"] = 4] = \"RecursedCheck\";\n\tReactiveFlags[ReactiveFlags[\"Recursed\"] = 8] = \"Recursed\";\n\tReactiveFlags[ReactiveFlags[\"Dirty\"] = 16] = \"Dirty\";\n\tReactiveFlags[ReactiveFlags[\"Pending\"] = 32] = \"Pending\";\n\treturn ReactiveFlags;\n}({});\n/* @__NO_SIDE_EFFECTS__ */\nfunction createReactiveSystem({ update, notify, unwatched }) {\n\treturn {\n\t\tlink,\n\t\tunlink,\n\t\tpropagate,\n\t\tcheckDirty,\n\t\tshallowPropagate\n\t};\n\tfunction link(dep, sub, version) {\n\t\tconst prevDep = sub.depsTail;\n\t\tif (prevDep !== void 0 && prevDep.dep === dep) return;\n\t\tconst nextDep = prevDep !== void 0 ? prevDep.nextDep : sub.deps;\n\t\tif (nextDep !== void 0 && nextDep.dep === dep) {\n\t\t\tnextDep.version = version;\n\t\t\tsub.depsTail = nextDep;\n\t\t\treturn;\n\t\t}\n\t\tconst prevSub = dep.subsTail;\n\t\tif (prevSub !== void 0 && prevSub.version === version && prevSub.sub === sub) return;\n\t\tconst newLink = sub.depsTail = dep.subsTail = {\n\t\t\tversion,\n\t\t\tdep,\n\t\t\tsub,\n\t\t\tprevDep,\n\t\t\tnextDep,\n\t\t\tprevSub,\n\t\t\tnextSub: void 0\n\t\t};\n\t\tif (nextDep !== void 0) nextDep.prevDep = newLink;\n\t\tif (prevDep !== void 0) prevDep.nextDep = newLink;\n\t\telse sub.deps = newLink;\n\t\tif (prevSub !== void 0) prevSub.nextSub = newLink;\n\t\telse dep.subs = newLink;\n\t}\n\tfunction unlink(link, sub = link.sub) {\n\t\tconst dep = link.dep;\n\t\tconst prevDep = link.prevDep;\n\t\tconst nextDep = link.nextDep;\n\t\tconst nextSub = link.nextSub;\n\t\tconst prevSub = link.prevSub;\n\t\tif (nextDep !== void 0) nextDep.prevDep = prevDep;\n\t\telse sub.depsTail = prevDep;\n\t\tif (prevDep !== void 0) prevDep.nextDep = nextDep;\n\t\telse sub.deps = nextDep;\n\t\tif (nextSub !== void 0) nextSub.prevSub = prevSub;\n\t\telse dep.subsTail = prevSub;\n\t\tif (prevSub !== void 0) prevSub.nextSub = nextSub;\n\t\telse if ((dep.subs = nextSub) === void 0) unwatched(dep);\n\t\treturn nextDep;\n\t}\n\tfunction propagate(link) {\n\t\tlet next = link.nextSub;\n\t\tlet stack;\n\t\ttop: do {\n\t\t\tconst sub = link.sub;\n\t\t\tlet flags = sub.flags;\n\t\t\tif (!(flags & (ReactiveFlags.RecursedCheck | ReactiveFlags.Recursed | ReactiveFlags.Dirty | ReactiveFlags.Pending))) sub.flags = flags | ReactiveFlags.Pending;\n\t\t\telse if (!(flags & (ReactiveFlags.RecursedCheck | ReactiveFlags.Recursed))) flags = ReactiveFlags.None;\n\t\t\telse if (!(flags & ReactiveFlags.RecursedCheck)) sub.flags = flags & ~ReactiveFlags.Recursed | ReactiveFlags.Pending;\n\t\t\telse if (!(flags & (ReactiveFlags.Dirty | ReactiveFlags.Pending)) && isValidLink(link, sub)) {\n\t\t\t\tsub.flags = flags | (ReactiveFlags.Recursed | ReactiveFlags.Pending);\n\t\t\t\tflags &= ReactiveFlags.Mutable;\n\t\t\t} else flags = ReactiveFlags.None;\n\t\t\tif (flags & ReactiveFlags.Watching) notify(sub);\n\t\t\tif (flags & ReactiveFlags.Mutable) {\n\t\t\t\tconst subSubs = sub.subs;\n\t\t\t\tif (subSubs !== void 0) {\n\t\t\t\t\tconst nextSub = (link = subSubs).nextSub;\n\t\t\t\t\tif (nextSub !== void 0) {\n\t\t\t\t\t\tstack = {\n\t\t\t\t\t\t\tvalue: next,\n\t\t\t\t\t\t\tprev: stack\n\t\t\t\t\t\t};\n\t\t\t\t\t\tnext = nextSub;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ((link = next) !== void 0) {\n\t\t\t\tnext = link.nextSub;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\twhile (stack !== void 0) {\n\t\t\t\tlink = stack.value;\n\t\t\t\tstack = stack.prev;\n\t\t\t\tif (link !== void 0) {\n\t\t\t\t\tnext = link.nextSub;\n\t\t\t\t\tcontinue top;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t} while (true);\n\t}\n\tfunction checkDirty(link, sub) {\n\t\tlet stack;\n\t\tlet checkDepth = 0;\n\t\tlet dirty = false;\n\t\ttop: do {\n\t\t\tconst dep = link.dep;\n\t\t\tconst flags = dep.flags;\n\t\t\tif (sub.flags & ReactiveFlags.Dirty) dirty = true;\n\t\t\telse if ((flags & (ReactiveFlags.Mutable | ReactiveFlags.Dirty)) === (ReactiveFlags.Mutable | ReactiveFlags.Dirty)) {\n\t\t\t\tif (update(dep)) {\n\t\t\t\t\tconst subs = dep.subs;\n\t\t\t\t\tif (subs.nextSub !== void 0) shallowPropagate(subs);\n\t\t\t\t\tdirty = true;\n\t\t\t\t}\n\t\t\t} else if ((flags & (ReactiveFlags.Mutable | ReactiveFlags.Pending)) === (ReactiveFlags.Mutable | ReactiveFlags.Pending)) {\n\t\t\t\tif (link.nextSub !== void 0 || link.prevSub !== void 0) stack = {\n\t\t\t\t\tvalue: link,\n\t\t\t\t\tprev: stack\n\t\t\t\t};\n\t\t\t\tlink = dep.deps;\n\t\t\t\tsub = dep;\n\t\t\t\t++checkDepth;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!dirty) {\n\t\t\t\tconst nextDep = link.nextDep;\n\t\t\t\tif (nextDep !== void 0) {\n\t\t\t\t\tlink = nextDep;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\twhile (checkDepth--) {\n\t\t\t\tconst firstSub = sub.subs;\n\t\t\t\tconst hasMultipleSubs = firstSub.nextSub !== void 0;\n\t\t\t\tif (hasMultipleSubs) {\n\t\t\t\t\tlink = stack.value;\n\t\t\t\t\tstack = stack.prev;\n\t\t\t\t} else link = firstSub;\n\t\t\t\tif (dirty) {\n\t\t\t\t\tif (update(sub)) {\n\t\t\t\t\t\tif (hasMultipleSubs) shallowPropagate(firstSub);\n\t\t\t\t\t\tsub = link.sub;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tdirty = false;\n\t\t\t\t} else sub.flags &= ~ReactiveFlags.Pending;\n\t\t\t\tsub = link.sub;\n\t\t\t\tconst nextDep = link.nextDep;\n\t\t\t\tif (nextDep !== void 0) {\n\t\t\t\t\tlink = nextDep;\n\t\t\t\t\tcontinue top;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn dirty;\n\t\t} while (true);\n\t}\n\tfunction shallowPropagate(link) {\n\t\tdo {\n\t\t\tconst sub = link.sub;\n\t\t\tconst flags = sub.flags;\n\t\t\tif ((flags & (ReactiveFlags.Pending | ReactiveFlags.Dirty)) === ReactiveFlags.Pending) {\n\t\t\t\tsub.flags = flags | ReactiveFlags.Dirty;\n\t\t\t\tif ((flags & (ReactiveFlags.Watching | ReactiveFlags.RecursedCheck)) === ReactiveFlags.Watching) notify(sub);\n\t\t\t}\n\t\t} while ((link = link.nextSub) !== void 0);\n\t}\n\tfunction isValidLink(checkLink, sub) {\n\t\tlet link = sub.depsTail;\n\t\twhile (link !== void 0) {\n\t\t\tif (link === checkLink) return true;\n\t\t\tlink = link.prevDep;\n\t\t}\n\t\treturn false;\n\t}\n}\n\n//#endregion\nexport { ReactiveFlags, createReactiveSystem };\n//# sourceMappingURL=alien.js.map","import { ReactiveFlags, createReactiveSystem } from \"./alien.js\";\n\n//#region src/atom.ts\nfunction toObserver(nextHandler, errorHandler, completionHandler) {\n\tconst isObserver = typeof nextHandler === \"object\";\n\tconst self = isObserver ? nextHandler : void 0;\n\treturn {\n\t\tnext: (isObserver ? nextHandler.next : nextHandler)?.bind(self),\n\t\terror: (isObserver ? nextHandler.error : errorHandler)?.bind(self),\n\t\tcomplete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)\n\t};\n}\nconst queuedEffects = [];\nlet cycle = 0;\nconst { link, unlink, propagate, checkDirty, shallowPropagate } = /* @__PURE__ */ createReactiveSystem({\n\tupdate(atom) {\n\t\treturn atom._update();\n\t},\n\tnotify(effect) {\n\t\tqueuedEffects[queuedEffectsLength++] = effect;\n\t\teffect.flags &= ~ReactiveFlags.Watching;\n\t},\n\tunwatched(atom) {\n\t\tif (atom.depsTail !== void 0) {\n\t\t\tatom.depsTail = void 0;\n\t\t\tatom.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;\n\t\t\tpurgeDeps(atom);\n\t\t}\n\t}\n});\nlet notifyIndex = 0;\nlet queuedEffectsLength = 0;\nlet activeSub;\nlet batchDepth = 0;\nfunction batch(fn) {\n\ttry {\n\t\t++batchDepth;\n\t\tfn();\n\t} finally {\n\t\tif (!--batchDepth) flush();\n\t}\n}\nfunction purgeDeps(sub) {\n\tconst depsTail = sub.depsTail;\n\tlet dep = depsTail !== void 0 ? depsTail.nextDep : sub.deps;\n\twhile (dep !== void 0) dep = unlink(dep, sub);\n}\nfunction flush() {\n\tif (batchDepth > 0) return;\n\twhile (notifyIndex < queuedEffectsLength) {\n\t\tconst effect = queuedEffects[notifyIndex];\n\t\tqueuedEffects[notifyIndex++] = void 0;\n\t\teffect.notify();\n\t}\n\tnotifyIndex = 0;\n\tqueuedEffectsLength = 0;\n}\nfunction createAsyncAtom(getValue, options) {\n\tconst ref = {};\n\tconst atom = createAtom(() => {\n\t\tgetValue().then((data) => {\n\t\t\tconst internalAtom = ref.current;\n\t\t\tif (internalAtom._update({\n\t\t\t\tstatus: \"done\",\n\t\t\t\tdata\n\t\t\t})) {\n\t\t\t\tconst subs = internalAtom.subs;\n\t\t\t\tif (subs !== void 0) {\n\t\t\t\t\tpropagate(subs);\n\t\t\t\t\tshallowPropagate(subs);\n\t\t\t\t\tflush();\n\t\t\t\t}\n\t\t\t}\n\t\t}, (error) => {\n\t\t\tconst internalAtom = ref.current;\n\t\t\tif (internalAtom._update({\n\t\t\t\tstatus: \"error\",\n\t\t\t\terror\n\t\t\t})) {\n\t\t\t\tconst subs = internalAtom.subs;\n\t\t\t\tif (subs !== void 0) {\n\t\t\t\t\tpropagate(subs);\n\t\t\t\t\tshallowPropagate(subs);\n\t\t\t\t\tflush();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn { status: \"pending\" };\n\t}, options);\n\tref.current = atom;\n\treturn atom;\n}\nfunction createAtom(valueOrFn, options) {\n\tconst isComputed = typeof valueOrFn === \"function\";\n\tconst getter = valueOrFn;\n\tconst atom = {\n\t\t_snapshot: isComputed ? void 0 : valueOrFn,\n\t\tsubs: void 0,\n\t\tsubsTail: void 0,\n\t\tdeps: void 0,\n\t\tdepsTail: void 0,\n\t\tflags: isComputed ? ReactiveFlags.None : ReactiveFlags.Mutable,\n\t\tget() {\n\t\t\tif (activeSub !== void 0) link(atom, activeSub, cycle);\n\t\t\treturn atom._snapshot;\n\t\t},\n\t\tsubscribe(observerOrFn) {\n\t\t\tconst obs = toObserver(observerOrFn);\n\t\t\tconst observed = { current: false };\n\t\t\tconst e = effect(() => {\n\t\t\t\tatom.get();\n\t\t\t\tif (!observed.current) observed.current = true;\n\t\t\t\telse obs.next?.(atom._snapshot);\n\t\t\t});\n\t\t\treturn { unsubscribe: () => {\n\t\t\t\te.stop();\n\t\t\t} };\n\t\t},\n\t\t_update(getValue) {\n\t\t\tconst prevSub = activeSub;\n\t\t\tconst compare = options?.compare ?? Object.is;\n\t\t\tif (isComputed) {\n\t\t\t\tactiveSub = atom;\n\t\t\t\t++cycle;\n\t\t\t\tatom.depsTail = void 0;\n\t\t\t} else if (getValue === void 0) return false;\n\t\t\tif (isComputed) atom.flags = ReactiveFlags.Mutable | ReactiveFlags.RecursedCheck;\n\t\t\ttry {\n\t\t\t\tconst oldValue = atom._snapshot;\n\t\t\t\tconst newValue = typeof getValue === \"function\" ? getValue(oldValue) : getValue === void 0 && isComputed ? getter(oldValue) : getValue;\n\t\t\t\tif (oldValue === void 0 || !compare(oldValue, newValue)) {\n\t\t\t\t\tatom._snapshot = newValue;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} finally {\n\t\t\t\tactiveSub = prevSub;\n\t\t\t\tif (isComputed) atom.flags &= ~ReactiveFlags.RecursedCheck;\n\t\t\t\tpurgeDeps(atom);\n\t\t\t}\n\t\t}\n\t};\n\tif (isComputed) {\n\t\tatom.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;\n\t\tatom.get = function() {\n\t\t\tconst flags = atom.flags;\n\t\t\tif (flags & ReactiveFlags.Dirty || flags & ReactiveFlags.Pending && checkDirty(atom.deps, atom)) {\n\t\t\t\tif (atom._update()) {\n\t\t\t\t\tconst subs = atom.subs;\n\t\t\t\t\tif (subs !== void 0) shallowPropagate(subs);\n\t\t\t\t}\n\t\t\t} else if (flags & ReactiveFlags.Pending) atom.flags = flags & ~ReactiveFlags.Pending;\n\t\t\tif (activeSub !== void 0) link(atom, activeSub, cycle);\n\t\t\treturn atom._snapshot;\n\t\t};\n\t} else atom.set = function(valueOrFn) {\n\t\tif (atom._update(valueOrFn)) {\n\t\t\tconst subs = atom.subs;\n\t\t\tif (subs !== void 0) {\n\t\t\t\tpropagate(subs);\n\t\t\t\tshallowPropagate(subs);\n\t\t\t\tflush();\n\t\t\t}\n\t\t}\n\t};\n\treturn atom;\n}\nfunction effect(fn) {\n\tconst run = () => {\n\t\tconst prevSub = activeSub;\n\t\tactiveSub = effectObj;\n\t\t++cycle;\n\t\teffectObj.depsTail = void 0;\n\t\teffectObj.flags = ReactiveFlags.Watching | ReactiveFlags.RecursedCheck;\n\t\ttry {\n\t\t\treturn fn();\n\t\t} finally {\n\t\t\tactiveSub = prevSub;\n\t\t\teffectObj.flags &= ~ReactiveFlags.RecursedCheck;\n\t\t\tpurgeDeps(effectObj);\n\t\t}\n\t};\n\tconst effectObj = {\n\t\tdeps: void 0,\n\t\tdepsTail: void 0,\n\t\tsubs: void 0,\n\t\tsubsTail: void 0,\n\t\tflags: ReactiveFlags.Watching | ReactiveFlags.RecursedCheck,\n\t\tnotify() {\n\t\t\tconst flags = this.flags;\n\t\t\tif (flags & ReactiveFlags.Dirty || flags & ReactiveFlags.Pending && checkDirty(this.deps, this)) run();\n\t\t\telse this.flags = ReactiveFlags.Watching;\n\t\t},\n\t\tstop() {\n\t\t\tthis.flags = ReactiveFlags.None;\n\t\t\tthis.depsTail = void 0;\n\t\t\tpurgeDeps(this);\n\t\t}\n\t};\n\trun();\n\treturn effectObj;\n}\n\n//#endregion\nexport { batch, createAsyncAtom, createAtom, flush, toObserver };\n//# sourceMappingURL=atom.js.map","import { createAtom, toObserver } from \"./atom.js\";\n\n//#region src/store.ts\nvar Store = class {\n\tconstructor(valueOrFn, actionsFactory) {\n\t\tthis.atom = createAtom(valueOrFn);\n\t\tthis.get = this.get.bind(this);\n\t\tthis.setState = this.setState.bind(this);\n\t\tthis.subscribe = this.subscribe.bind(this);\n\t\tif (actionsFactory) this.actions = actionsFactory(this);\n\t}\n\tsetState(updater) {\n\t\tthis.atom.set(updater);\n\t}\n\tget state() {\n\t\treturn this.atom.get();\n\t}\n\tget() {\n\t\treturn this.state;\n\t}\n\tsubscribe(observerOrFn) {\n\t\treturn this.atom.subscribe(toObserver(observerOrFn));\n\t}\n};\nvar ReadonlyStore = class {\n\tconstructor(valueOrFn) {\n\t\tthis.atom = createAtom(valueOrFn);\n\t}\n\tget state() {\n\t\treturn this.atom.get();\n\t}\n\tget() {\n\t\treturn this.state;\n\t}\n\tsubscribe(observerOrFn) {\n\t\treturn this.atom.subscribe(toObserver(observerOrFn));\n\t}\n};\nfunction createStore(valueOrFn, actions) {\n\tif (typeof valueOrFn === \"function\") return new ReadonlyStore(valueOrFn);\n\tif (actions) return new Store(valueOrFn, actions);\n\treturn new Store(valueOrFn);\n}\n\n//#endregion\nexport { ReadonlyStore, Store, createStore };\n//# sourceMappingURL=store.js.map","import { useCallback } from \"react\";\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/shim/with-selector\";\n\n//#region src/useSelector.ts\nfunction defaultCompare(a, b) {\n\treturn a === b;\n}\n/**\n* Selects a slice of state from an atom or store and subscribes the component\n* to that selection.\n*\n* This is the primary React read hook for TanStack Store. It works with any\n* source that exposes `get()` and `subscribe()`, including atoms, readonly\n* atoms, stores, and readonly stores.\n*\n* Omit the selector to subscribe to the whole value.\n*\n* @example\n* ```tsx\n* const count = useSelector(counterStore, (state) => state.count)\n* ```\n*\n* @example\n* ```tsx\n* const value = useSelector(countAtom)\n* ```\n*/\nfunction useSelector(source, selector = (s) => s, options) {\n\tconst compare = options?.compare ?? defaultCompare;\n\tconst subscribe = useCallback((handleStoreChange) => {\n\t\tconst { unsubscribe } = source.subscribe(handleStoreChange);\n\t\treturn unsubscribe;\n\t}, [source]);\n\tconst getSnapshot = useCallback(() => source.get(), [source]);\n\treturn useSyncExternalStoreWithSelector(subscribe, getSnapshot, getSnapshot, selector, compare);\n}\n\n//#endregion\nexport { useSelector };\n//# sourceMappingURL=useSelector.js.map","import { useSelector } from \"./useSelector.js\";\n\n//#region src/useStore.ts\n/**\n* Deprecated alias for {@link useSelector}.\n*\n* @example\n* ```tsx\n* const count = useStore(counterStore, (state) => state.count)\n* ```\n*\n* @deprecated Use `useSelector` instead.\n*/\nconst useStore = (source, selector = (s) => s, compare) => useSelector(source, selector, { compare });\n\n//#endregion\nexport { useStore };\n//# sourceMappingURL=useStore.js.map","/**\n * PromptInputController — the single source of truth for a prompt input tree.\n *\n * Built on @tanstack/store for per-slice subscriptions (sub-components\n * re-render only when the fields they read change). The controller exposes\n * two stores:\n *\n * - `request` : outbound state (text, files, mode, model, …extensions). The\n * user edits these; `submit()` ships them to `onSubmit`.\n * - `display` : inbound state (sendStatus, tasks, pendingQuestion, pendingPlan,\n * usage). The harness writes these in; sub-components read them.\n *\n * Consumers never touch the stores directly. They use:\n *\n * const mode = useRequestField('mode'); // read\n * const setMode = useSetRequestField('mode'); // write\n * const status = useDisplayField('sendStatus'); // read\n *\n * Or, for advanced use, subscribe to the whole store with\n * `useStore(controller.request)`.\n */\n\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store } from \"@tanstack/store\";\nimport { createContext, useContext, useMemo } from \"react\";\n\nimport type {\n AttachmentFile,\n PromptInputDisplayContext,\n PromptInputRequestContext,\n PromptInputSubmitPayload,\n PromptInputTag,\n} from \"./types\";\n\n// ─── Controller shape ─────────────────────────────────────────────────────────\n\nexport type PromptInputRequestController<\n TExt extends Record<string, unknown> = Record<string, unknown>,\n> = {\n /** Outbound stores (user-edited). */\n request: Store<PromptInputRequestContext<TExt>>;\n /** Inbound stores (harness-pushed). */\n display: Store<PromptInputDisplayContext>;\n\n /** Imperative helpers. */\n setRequestField: <K extends keyof PromptInputRequestContext<TExt>>(\n key: K,\n value: PromptInputRequestContext<TExt>[K]\n ) => void;\n setDisplayField: <K extends keyof PromptInputDisplayContext>(\n key: K,\n value: PromptInputDisplayContext[K]\n ) => void;\n\n /** Attachment helpers (common enough to warrant first-class methods). */\n addAttachments: (files: AttachmentFile[]) => void;\n removeAttachment: (id: string) => void;\n clearAttachments: () => void;\n\n /** Tag helpers for references attached to the prompt. */\n addTags: (tags: PromptInputTag[]) => void;\n insertTag: (\n tag: PromptInputTag,\n range?: { start: number; end: number }\n ) => void;\n removeTag: (id: string) => void;\n clearTags: () => void;\n\n /** Reset request state (clears text, files, and tags; keeps mode/model). */\n resetRequest: () => void;\n\n /** Snapshot the current request context (for onSubmit). */\n snapshot: () => PromptInputSubmitPayload<TExt>;\n};\n\n// ─── Factory ──────────────────────────────────────────────────────────────────\n\nconst DEFAULT_REQUEST: PromptInputRequestContext = {\n text: \"\",\n files: [],\n tags: [],\n};\n\nconst DEFAULT_DISPLAY: PromptInputDisplayContext = {\n sendStatus: \"idle\",\n};\n\nexport type CreatePromptInputRequestControllerOptions<\n TExt extends Record<string, unknown> = Record<string, unknown>,\n> = {\n initialRequest?: Partial<PromptInputRequestContext<TExt>>;\n initialDisplay?: Partial<PromptInputDisplayContext>;\n};\n\nexport function createPromptInputRequestController<\n TExt extends Record<string, unknown> = Record<string, unknown>,\n>(\n options: CreatePromptInputRequestControllerOptions<TExt> = {}\n): PromptInputRequestController<TExt> {\n const request = new Store<PromptInputRequestContext<TExt>>({\n ...(DEFAULT_REQUEST as PromptInputRequestContext<TExt>),\n ...(options.initialRequest as Partial<PromptInputRequestContext<TExt>>),\n });\n\n const display = new Store<PromptInputDisplayContext>({\n ...DEFAULT_DISPLAY,\n ...options.initialDisplay,\n });\n\n return {\n request,\n display,\n setRequestField(key, value) {\n request.setState((prev) => ({ ...prev, [key]: value }));\n },\n setDisplayField(key, value) {\n display.setState((prev) => ({ ...prev, [key]: value }));\n },\n addAttachments(files) {\n request.setState((prev) => ({\n ...prev,\n files: [...prev.files, ...files],\n }));\n },\n removeAttachment(id) {\n request.setState((prev) => {\n const removed = prev.files.find((f) => f.id === id);\n if (removed?.url.startsWith(\"blob:\")) URL.revokeObjectURL(removed.url);\n return { ...prev, files: prev.files.filter((f) => f.id !== id) };\n });\n },\n clearAttachments() {\n request.setState((prev) => {\n for (const f of prev.files) {\n if (f.url.startsWith(\"blob:\")) URL.revokeObjectURL(f.url);\n }\n return { ...prev, files: [] };\n });\n },\n addTags(tags) {\n request.setState((prev) => {\n const existing = prev.tags ?? [];\n const incoming = tags.filter(\n (tag) => !existing.some((item) => item.id === tag.id)\n );\n return { ...prev, tags: [...existing, ...incoming] };\n });\n },\n insertTag(tag, range) {\n request.setState((prev) => {\n const mention =\n tag.mention ?? `@${tag.label.replace(/\\s+/gu, \"-\").toLowerCase()}`;\n const text = prev.text ?? \"\";\n const start = range?.start ?? text.length;\n const end = range?.end ?? text.length;\n const prefix = text.slice(0, start);\n const suffix = text.slice(end);\n const needsPrefixSpace = prefix.length > 0 && !/\\s$/u.test(prefix);\n const needsSuffixSpace = suffix.length > 0 && !/^\\s/u.test(suffix);\n const nextText = `${prefix}${needsPrefixSpace ? \" \" : \"\"}${mention}${needsSuffixSpace ? \" \" : \"\"}${suffix}`;\n const nextTag = { ...tag, mention };\n const existing = prev.tags ?? [];\n const nextTags = existing.some((item) => item.id === tag.id)\n ? existing.map((item) => (item.id === tag.id ? nextTag : item))\n : [...existing, nextTag];\n return { ...prev, text: nextText, tags: nextTags };\n });\n },\n removeTag(id) {\n request.setState((prev) => ({\n ...prev,\n tags: (prev.tags ?? []).filter((tag) => tag.id !== id),\n }));\n },\n clearTags() {\n request.setState((prev) => ({ ...prev, tags: [] }));\n },\n resetRequest() {\n request.setState((prev) => {\n for (const f of prev.files) {\n if (f.url.startsWith(\"blob:\")) URL.revokeObjectURL(f.url);\n }\n return { ...prev, text: \"\", files: [], tags: [] };\n });\n },\n snapshot() {\n return request.state;\n },\n };\n}\n\n// ─── React context + hooks ────────────────────────────────────────────────────\n\n// Typed as `any` in the context because each provider parameterizes `TExt`\n// differently; callers narrow via the hook generic or typed consumer.\nconst PromptInputRequestControllerContext =\n // biome-ignore lint/suspicious/noExplicitAny: controller TExt is provider-parameterized\n createContext<PromptInputRequestController<any> | null>(null);\n\nexport const PromptInputRequestControllerProvider =\n PromptInputRequestControllerContext.Provider;\n\nexport function usePromptInputRequestController<\n TExt extends Record<string, unknown> = Record<string, unknown>,\n>(): PromptInputRequestController<TExt> {\n const ctx = useContext(PromptInputRequestControllerContext);\n if (!ctx) {\n throw new Error(\n \"usePromptInputRequestController must be used inside <PromptInput> or <PromptInputRequestProvider>\"\n );\n }\n return ctx as PromptInputRequestController<TExt>;\n}\n\n/** Optional variant — returns null if no controller is in context. */\nexport function useOptionalPromptInputRequestController<\n TExt extends Record<string, unknown> = Record<string, unknown>,\n>(): PromptInputRequestController<TExt> | null {\n return useContext(\n PromptInputRequestControllerContext\n ) as PromptInputRequestController<TExt> | null;\n}\n\n// ─── Field hooks ──────────────────────────────────────────────────────────────\n\n/**\n * Subscribe to one field of the request context. Component re-renders only\n * when that field changes.\n */\nexport function useRequestField<\n K extends keyof PromptInputRequestContext<TExt>,\n TExt extends Record<string, unknown> = Record<string, unknown>,\n>(key: K): PromptInputRequestContext<TExt>[K] {\n const ctrl = usePromptInputRequestController<TExt>();\n return useStore(ctrl.request, (state) => state[key]);\n}\n\n/** Returns a stable setter for one field of the request context. */\nexport function useSetRequestField<\n K extends keyof PromptInputRequestContext<TExt>,\n TExt extends Record<string, unknown> = Record<string, unknown>,\n>(key: K): (value: PromptInputRequestContext<TExt>[K]) => void {\n const ctrl = usePromptInputRequestController<TExt>();\n return useMemo(\n () => (value: PromptInputRequestContext<TExt>[K]) => {\n ctrl.setRequestField(key, value);\n },\n [ctrl, key]\n );\n}\n\n/**\n * Subscribe to one field of the display context. Component re-renders only\n * when that field changes.\n */\nexport function useDisplayField<K extends keyof PromptInputDisplayContext>(\n key: K\n): PromptInputDisplayContext[K] {\n const ctrl = usePromptInputRequestController();\n return useStore(ctrl.display, (state) => state[key]);\n}\n","\"use client\";\n\nimport { Menu as DropdownMenuPrimitive } from \"@base-ui/react/menu\";\nimport { Select as SelectPrimitive } from \"@base-ui/react/select\";\nimport { layoutWithLines, prepareWithSegments } from \"@chenglou/pretext\";\nimport {\n ArrowUpIcon,\n ArrowsClockwiseIcon,\n CaretDownIcon,\n CheckIcon,\n FileIcon,\n FileTextIcon,\n ImageIcon,\n MicrophoneIcon,\n PaperclipIcon,\n PlusIcon,\n SpinnerGapIcon,\n SquareIcon,\n XIcon,\n} from \"@phosphor-icons/react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store } from \"@tanstack/store\";\nimport type {\n ChangeEvent,\n ChangeEventHandler,\n ClipboardEventHandler,\n ComponentProps,\n CSSProperties,\n FormEvent,\n FormEventHandler,\n HTMLAttributes,\n KeyboardEventHandler,\n PropsWithChildren,\n ReactNode,\n RefObject,\n} from \"react\";\nimport {\n Fragment,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../button\";\nimport { Tooltip } from \"../tooltip\";\nimport { useOptionalPromptInputRequestController } from \"./controller\";\nimport type {\n ModeOption,\n PromptInputReferenceSearch,\n PromptInputTag as PromptInputTagData,\n} from \"./types\";\n\n// Stable fallback store for selectors used outside a controller — keeps\n// `useStore` hook order consistent whether or not the controller is mounted.\nconst FALLBACK_REQUEST_STORE = new Store<Record<string, unknown>>({});\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_PROMPT_INPUT_VARIANTS = {\n status: {\n idle: { classes: \"\", description: \"Ready to accept input\" },\n submitted: {\n classes: \"\",\n description: \"Waiting for response (shows spinner)\",\n },\n streaming: { classes: \"\", description: \"Streaming response (shows stop)\" },\n error: { classes: \"\", description: \"Error state (shows X)\" },\n },\n} as const;\n\nexport const SF_AI_PROMPT_INPUT_DEFAULT_VARIANTS = {\n status: \"idle\",\n} as const;\n\nexport type SFAiPromptInputStatus =\n keyof typeof SF_AI_PROMPT_INPUT_VARIANTS.status;\n\nexport type PromptInputBackLayerStatus = \"idle\" | \"running\" | \"error\";\n\n// ─── Attachment types ─────────────────────────────────────────────────────────\n\nexport type AttachmentFile = {\n id: string;\n url: string;\n mediaType: string;\n filename: string;\n};\n\nexport type AttachmentsContext = {\n files: AttachmentFile[];\n add: (files: File[] | FileList) => void;\n remove: (id: string) => void;\n clear: () => void;\n openFileDialog: () => void;\n fileInputRef: RefObject<HTMLInputElement | null>;\n};\n\n// ─── Provider Context & Types ─────────────────────────────────────────────────\n\nexport type TextInputContext = {\n value: string;\n setInput: (v: string) => void;\n clear: () => void;\n};\n\nexport type PromptInputController = {\n textInput: TextInputContext;\n attachments: AttachmentsContext;\n /** INTERNAL: Allows PromptInput to register its file input + \"open\" callback */\n __registerFileInput: (\n ref: RefObject<HTMLInputElement | null>,\n open: () => void\n ) => void;\n};\n\nconst PromptInputContext = createContext<PromptInputController | null>(null);\nconst ProviderAttachmentsContext = createContext<AttachmentsContext | null>(\n null\n);\n\nexport const usePromptInputController = () => {\n const ctx = useContext(PromptInputContext);\n if (!ctx) {\n throw new Error(\n \"Wrap your component inside <PromptInputProvider> to use usePromptInputController().\"\n );\n }\n return ctx;\n};\n\nconst useOptionalPromptInputController = () => useContext(PromptInputContext);\n\nexport const useProviderAttachments = () => {\n const ctx = useContext(ProviderAttachmentsContext);\n if (!ctx) {\n throw new Error(\n \"Wrap your component inside <PromptInputProvider> to use useProviderAttachments().\"\n );\n }\n return ctx;\n};\n\nconst useOptionalProviderAttachments = () =>\n useContext(ProviderAttachmentsContext);\n\n// ─── PromptInputProvider ──────────────────────────────────────────────────────\n\nexport type PromptInputProviderProps = PropsWithChildren<{\n initialInput?: string;\n}>;\n\n/**\n * Optional global provider that lifts PromptInput state outside of PromptInput.\n * If you don't use it, PromptInput stays fully self-managed.\n *\n * @example\n * ```tsx\n * <PromptInputProvider>\n * <PromptInput onSubmit={handleSubmit}>...</PromptInput>\n * </PromptInputProvider>\n * ```\n */\nexport function PromptInputProvider({\n initialInput = \"\",\n children,\n}: PromptInputProviderProps) {\n const [textInput, setTextInput] = useState(initialInput);\n const clearInput = useCallback(() => setTextInput(\"\"), []);\n\n const [attachmentItems, setAttachmentItems] = useState<AttachmentFile[]>([]);\n const fileInputRef = useRef<HTMLInputElement | null>(null);\n const openRef = useRef<() => void>(() => {});\n\n const add = useCallback((files: File[] | FileList) => {\n const incoming = Array.from(files);\n if (incoming.length === 0) return;\n setAttachmentItems((prev) =>\n prev.concat(\n incoming.map((file) => ({\n id: `${Date.now()}-${Math.random()}`,\n url: URL.createObjectURL(file),\n mediaType: file.type,\n filename: file.name,\n }))\n )\n );\n }, []);\n\n const remove = useCallback((id: string) => {\n setAttachmentItems((prev) => {\n const found = prev.find((f) => f.id === id);\n if (found?.url) URL.revokeObjectURL(found.url);\n return prev.filter((f) => f.id !== id);\n });\n }, []);\n\n const clear = useCallback(() => {\n setAttachmentItems((prev) => {\n for (const f of prev) if (f.url) URL.revokeObjectURL(f.url);\n return [];\n });\n }, []);\n\n const openFileDialog = useCallback(() => {\n openRef.current?.();\n }, []);\n\n const attachments = useMemo<AttachmentsContext>(\n () => ({\n files: attachmentItems,\n add,\n remove,\n clear,\n openFileDialog,\n fileInputRef,\n }),\n [attachmentItems, add, remove, clear, openFileDialog]\n );\n\n const __registerFileInput = useCallback(\n (ref: RefObject<HTMLInputElement | null>, open: () => void) => {\n fileInputRef.current = ref.current;\n openRef.current = open;\n },\n []\n );\n\n const controller = useMemo<PromptInputController>(\n () => ({\n textInput: {\n value: textInput,\n setInput: setTextInput,\n clear: clearInput,\n },\n attachments,\n __registerFileInput,\n }),\n [textInput, clearInput, attachments, __registerFileInput]\n );\n\n return (\n <PromptInputContext.Provider value={controller}>\n <ProviderAttachmentsContext.Provider value={attachments}>\n {children}\n </ProviderAttachmentsContext.Provider>\n </PromptInputContext.Provider>\n );\n}\n\n// ─── Local Attachments Context ────────────────────────────────────────────────\n\nconst LocalAttachmentsContext = createContext<AttachmentsContext | null>(null);\n\nexport const usePromptInputAttachments = () => {\n const provider = useOptionalProviderAttachments();\n const local = useContext(LocalAttachmentsContext);\n const context = provider ?? local;\n if (!context) {\n throw new Error(\n \"usePromptInputAttachments must be used within a PromptInput or PromptInputProvider\"\n );\n }\n return context;\n};\n\n// ─── Helpers (module-level) ───────────────────────────────────────────────────\n\n/** Convert a blob URL to a base64 data URL for serialization. */\nasync function convertBlobToDataUrl(url: string): Promise<string> {\n const response = await fetch(url);\n const blob = await response.blob();\n // FileReader is callback-only — no Promise-based API exists for this\n // oxlint-disable-next-line avoid-new\n return await new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.addEventListener(\"loadend\", () => resolve(reader.result as string));\n reader.addEventListener(\"error\", () =>\n reject(new Error(\"FileReader error\"))\n );\n reader.readAsDataURL(blob);\n });\n}\n\nfunction makeAttachmentId() {\n return `${Date.now()}-${Math.random()}`;\n}\n\n// ─── PromptInputMessage ───────────────────────────────────────────────────────\n\nexport type PromptInputMessage = {\n text?: string;\n files?: AttachmentFile[];\n tags?: PromptInputTagData[];\n};\n\n// ─── PromptInput ─────────────────────────────────────────────────────────────\n\nexport type PromptInputProps = Omit<\n HTMLAttributes<HTMLFormElement>,\n \"onSubmit\" | \"onError\"\n> & {\n /** Accepted file types — e.g. `\"image/*\"`. Default: any. */\n accept?: string;\n /** Allow selecting multiple files. */\n multiple?: boolean;\n /** When true, accept drops anywhere on document. Default false. */\n globalDrop?: boolean;\n /** Maximum number of attached files. */\n maxFiles?: number;\n /** Maximum file size in bytes. */\n maxFileSize?: number;\n onError?: (err: {\n code: \"max_files\" | \"max_file_size\" | \"accept\";\n message: string;\n }) => void;\n onSubmit: (\n message: PromptInputMessage,\n event: FormEvent<HTMLFormElement>\n ) => void | Promise<void>;\n /**\n * Content rendered in the collapsible back layer (e.g. HITL approvals, task\n * lists). When provided the prompt input is wrapped in a LayerCard shell with\n * a header row containing a chevron toggle.\n * Use `PromptInputBackLayer` to compose structured content for this slot.\n */\n backLayer?: ReactNode;\n /**\n * Header content shown in the back layer header row. Strings render as plain\n * text; pass JSX to compose with icons/spinners/badges. Defaults to\n * `\"Context\"`.\n */\n backLayerTitle?: ReactNode;\n /**\n * Optional status indicator rendered next to the title. `\"running\"` shows a\n * small spinner; `\"error\"` shows an inline error icon. Use this instead of\n * composing JSX into `backLayerTitle` for the common case of an agent doing\n * work.\n */\n backLayerStatus?: PromptInputBackLayerStatus;\n /**\n * Controls whether the back layer is visible. Pair with `onBackLayerOpenChange`\n * for a controlled pattern.\n */\n backLayerOpen?: boolean;\n /** Called when the chevron toggle changes the back layer open state. */\n onBackLayerOpenChange?: (open: boolean) => void;\n /**\n * Automatically opens the back layer when this condition is true.\n * Useful for showing pending approvals/questions without manual toggle.\n */\n autoOpenBackLayerWhen?: boolean;\n};\n\n/**\n * Prompt input form. Can be self-managed or controlled via `PromptInputProvider`.\n *\n * @example\n * ```tsx\n * <PromptInput onSubmit={({ text, files }) => send(text, files)}>\n * <PromptInputAttachments>{(f) => <PromptInputAttachment data={f} />}</PromptInputAttachments>\n * <PromptInputTextarea placeholder=\"Ask anything…\" />\n * <PromptInputToolbar>\n * <PromptInputTools>\n * <PromptInputAttachButton />\n * </PromptInputTools>\n * <PromptInputSubmit />\n * </PromptInputToolbar>\n * </PromptInput>\n * ```\n */\nexport function PromptInput({\n className,\n accept,\n multiple,\n globalDrop,\n maxFiles,\n maxFileSize,\n onError,\n onSubmit,\n children,\n backLayer,\n backLayerTitle = \"Context\",\n backLayerStatus = \"idle\",\n backLayerOpen,\n onBackLayerOpenChange,\n autoOpenBackLayerWhen,\n ...props\n}: PromptInputProps) {\n const hasBackLayer = backLayer !== undefined;\n const controller = useOptionalPromptInputController();\n const requestCtrl = useOptionalPromptInputRequestController();\n const usingProvider = !!controller;\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const anchorRef = useRef<HTMLSpanElement>(null);\n const formRef = useRef<HTMLFormElement | null>(null);\n\n useEffect(() => {\n const root = anchorRef.current?.closest(\"form\");\n if (root instanceof HTMLFormElement) {\n formRef.current = root;\n }\n }, []);\n\n // Auto-open back layer when condition is true\n useEffect(() => {\n if (autoOpenBackLayerWhen) {\n onBackLayerOpenChange?.(true);\n }\n }, [autoOpenBackLayerWhen, onBackLayerOpenChange]);\n\n // Local attachment state (only when no provider)\n const [items, setItems] = useState<AttachmentFile[]>([]);\n const files = usingProvider ? controller.attachments.files : items;\n const tags = useStore(\n requestCtrl?.request ?? FALLBACK_REQUEST_STORE,\n (state) => (state as { tags?: PromptInputTagData[] }).tags ?? []\n );\n\n const openFileDialogLocal = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n const matchesAccept = useCallback(\n (f: File) => {\n if (!accept || accept.trim() === \"\") return true;\n if (accept.includes(\"image/*\")) return f.type.startsWith(\"image/\");\n return true;\n },\n [accept]\n );\n\n const addLocal = useCallback(\n (fileList: File[] | FileList) => {\n const incoming = Array.from(fileList);\n const accepted = incoming.filter((f) => matchesAccept(f));\n if (incoming.length && accepted.length === 0) {\n onError?.({\n code: \"accept\",\n message: \"No files match the accepted types.\",\n });\n return;\n }\n const withinSize = (f: File) =>\n maxFileSize ? f.size <= maxFileSize : true;\n const sized = accepted.filter(withinSize);\n if (accepted.length > 0 && sized.length === 0) {\n onError?.({\n code: \"max_file_size\",\n message: \"All files exceed the maximum size.\",\n });\n return;\n }\n setItems((prev) => {\n const capacity =\n typeof maxFiles === \"number\"\n ? Math.max(0, maxFiles - prev.length)\n : undefined;\n const capped =\n typeof capacity === \"number\" ? sized.slice(0, capacity) : sized;\n if (typeof capacity === \"number\" && sized.length > capacity) {\n onError?.({\n code: \"max_files\",\n message: \"Too many files. Some were not added.\",\n });\n }\n const next: AttachmentFile[] = capped.map((file) => ({\n id: makeAttachmentId(),\n url: URL.createObjectURL(file),\n mediaType: file.type,\n filename: file.name,\n }));\n return prev.concat(next);\n });\n },\n [matchesAccept, maxFiles, maxFileSize, onError]\n );\n\n const add = usingProvider\n ? (f: File[] | FileList) => controller.attachments.add(f)\n : addLocal;\n\n const remove = usingProvider\n ? (id: string) => controller.attachments.remove(id)\n : (id: string) =>\n setItems((prev) => {\n const found = prev.find((f) => f.id === id);\n if (found?.url) URL.revokeObjectURL(found.url);\n return prev.filter((f) => f.id !== id);\n });\n\n const clear = usingProvider\n ? () => controller.attachments.clear()\n : () =>\n setItems((prev) => {\n for (const f of prev) if (f.url) URL.revokeObjectURL(f.url);\n return [];\n });\n\n const openFileDialog = usingProvider\n ? () => controller.attachments.openFileDialog()\n : openFileDialogLocal;\n\n useEffect(() => {\n if (!usingProvider) return;\n controller.__registerFileInput(inputRef, () => inputRef.current?.click());\n }, [usingProvider, controller]);\n\n // File drag-drop on the form\n useEffect(() => {\n const form = formRef.current;\n if (!form) return;\n const onDragOver = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n };\n const onDrop = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {\n add(e.dataTransfer.files);\n }\n };\n form.addEventListener(\"dragover\", onDragOver);\n form.addEventListener(\"drop\", onDrop);\n return () => {\n form.removeEventListener(\"dragover\", onDragOver);\n form.removeEventListener(\"drop\", onDrop);\n };\n }, [add]);\n\n useEffect(() => {\n if (!globalDrop) return;\n const onDragOver = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n };\n const onDrop = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0)\n add(e.dataTransfer.files);\n };\n document.addEventListener(\"dragover\", onDragOver);\n document.addEventListener(\"drop\", onDrop);\n return () => {\n document.removeEventListener(\"dragover\", onDragOver);\n document.removeEventListener(\"drop\", onDrop);\n };\n }, [add, globalDrop]);\n\n // Cleanup blob URLs on unmount (local mode only)\n useEffect(() => {\n return () => {\n if (!usingProvider) {\n for (const f of files) if (f.url) URL.revokeObjectURL(f.url);\n }\n };\n }, [usingProvider, files]);\n\n const handleFileInputChange: ChangeEventHandler<HTMLInputElement> = (\n event\n ) => {\n if (event.currentTarget.files) add(event.currentTarget.files);\n };\n\n const ctx = useMemo<AttachmentsContext>(\n () => ({\n files,\n add,\n remove,\n clear,\n openFileDialog,\n fileInputRef: inputRef,\n }),\n [files, add, remove, clear, openFileDialog]\n );\n\n const handleSubmit: FormEventHandler<HTMLFormElement> = (event) => {\n event.preventDefault();\n const form = event.currentTarget;\n const text = requestCtrl\n ? requestCtrl.request.state.text\n : usingProvider\n ? controller.textInput.value\n : (() => {\n const formData = new FormData(form);\n return (formData.get(\"message\") as string) || \"\";\n })();\n\n if (!usingProvider) form.reset();\n\n const doSubmit = async () => {\n const convertedFiles = await Promise.all(\n files.map(async (item) => {\n if (item.url.startsWith(\"blob:\")) {\n return { ...item, url: await convertBlobToDataUrl(item.url) };\n }\n return item;\n })\n );\n\n try {\n await onSubmit({ text, files: convertedFiles, tags }, event);\n if (requestCtrl) {\n requestCtrl.resetRequest();\n } else {\n clear();\n if (usingProvider) controller.textInput.clear();\n }\n } catch {\n // Don't clear on error — user may want to retry\n }\n };\n\n doSubmit().catch(() => {});\n };\n\n const isBackLayerOpen = backLayerOpen ?? false;\n\n const inputShell = hasBackLayer ? (\n // LayerCard-style shell: elevated outer card with header + collapsible back\n // layer + primary layer housing the actual input.\n <div className=\"flex w-full flex-col rounded-xl bg-sf-elevated ring ring-sf-line/50\">\n {/* Header row — always visible, contains title + chevron toggle */}\n <button\n aria-expanded={isBackLayerOpen}\n aria-label={isBackLayerOpen ? \"Collapse context\" : \"Expand context\"}\n className=\"flex w-full items-center justify-between gap-2 px-3 py-2 text-left\"\n onClick={() => onBackLayerOpenChange?.(!isBackLayerOpen)}\n type=\"button\"\n >\n <span className=\"flex items-center gap-1.5 text-sm font-medium text-sf-subtle uppercase tracking-wide select-none\">\n {backLayerStatus === \"running\" ? (\n <SpinnerGapIcon\n className=\"size-3.5 animate-spin\"\n aria-hidden=\"true\"\n />\n ) : null}\n {backLayerStatus === \"error\" ? (\n <XIcon className=\"size-3.5 text-sf-danger\" aria-hidden=\"true\" />\n ) : null}\n {backLayerTitle}\n </span>\n <CaretDownIcon\n className={cn(\n \"size-3.5 text-sf-subtle transition-transform duration-200\",\n isBackLayerOpen && \"rotate-180\"\n )}\n />\n </button>\n {/* Collapsible back layer content */}\n <PromptInputBackLayerPanel open={isBackLayerOpen}>\n {backLayer}\n </PromptInputBackLayerPanel>\n {/* Primary layer — the input itself, visually raised off the back layer */}\n <div className=\"flex flex-col overflow-visible rounded-xl bg-sf-base ring ring-sf-line/50 focus-within:ring-sf-ring\">\n {children}\n </div>\n </div>\n ) : (\n <div className=\"flex w-full flex-col items-stretch overflow-visible rounded-xl border-0 bg-sf-base shadow-xs ring ring-sf-line focus-within:ring-sf-ring\">\n {children}\n </div>\n );\n\n const inner = (\n <>\n <span aria-hidden=\"true\" className=\"hidden\" ref={anchorRef} />\n <input\n accept={accept}\n aria-label=\"Upload files\"\n className=\"hidden\"\n multiple={multiple}\n onChange={handleFileInputChange}\n ref={inputRef}\n type=\"file\"\n />\n <form\n className={cn(\"w-full\", className)}\n onSubmit={handleSubmit}\n {...props}\n >\n {inputShell}\n </form>\n </>\n );\n\n return usingProvider ? (\n inner\n ) : (\n <LocalAttachmentsContext.Provider value={ctx}>\n {inner}\n </LocalAttachmentsContext.Provider>\n );\n}\n\n// ─── PromptInputBody ──────────────────────────────────────────────────────────\n\nexport type PromptInputBodyProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputBody = ({\n className,\n ...props\n}: PromptInputBodyProps) => (\n <div className={cn(\"contents\", className)} {...props} />\n);\n\n// ─── PromptInputBackLayerPanel (internal) ─────────────────────────────────────\n// Grid-rows animation: collapses to 0fr when closed, expands to 1fr when open.\n\ntype PromptInputBackLayerPanelProps = PropsWithChildren<{\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}>;\n\nfunction PromptInputBackLayerPanel({\n open,\n children,\n}: PromptInputBackLayerPanelProps) {\n const isOpen = open ?? false;\n\n return (\n <div\n aria-hidden={!isOpen}\n className=\"grid\"\n style={{\n gridTemplateRows: isOpen ? \"1fr\" : \"0fr\",\n opacity: isOpen ? 1 : 0,\n transition: \"grid-template-rows 200ms ease-out, opacity 200ms ease-out\",\n }}\n >\n {/* min-h-0 lets the grid row collapse to 0 */}\n <div className=\"min-h-0 overflow-hidden\">{children}</div>\n </div>\n );\n}\n\n// ─── PromptInputBackLayer (public) ────────────────────────────────────────────\n\nexport type PromptInputBackLayerProps = PropsWithChildren<{\n className?: string;\n}>;\n\n/**\n * Container for back-layer content (HITL approvals, task lists, agent status,\n * etc.). Pass instances of this as the `backLayer` prop on `PromptInput`.\n *\n * @example\n * ```tsx\n * <PromptInput\n * onSubmit={handleSubmit}\n * backLayer={<PromptInputBackLayer>...</PromptInputBackLayer>}\n * backLayerOpen={open}\n * onBackLayerOpenChange={setOpen}\n * >\n * <PromptInputTextarea />\n * <PromptInputToolbar>\n * <PromptInputTools />\n * <PromptInputSubmit />\n * </PromptInputToolbar>\n * </PromptInput>\n * ```\n */\nexport function PromptInputBackLayer({\n children,\n className,\n}: PromptInputBackLayerProps) {\n return (\n <div\n className={cn(\n \"flex flex-col gap-2 px-3 py-2.5 text-sm text-sf-default\",\n className\n )}\n >\n {children}\n </div>\n );\n}\n\n// ─── Textarea helpers (module-level) ──────────────────────────────────────────\n\nconst handleTextareaKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (\n e\n) => {\n if (e.key === \"Enter\") {\n if (e.nativeEvent.isComposing) return;\n if (e.shiftKey) return;\n e.preventDefault();\n e.currentTarget.form?.requestSubmit();\n }\n};\n\n// ─── PromptInputTextarea ──────────────────────────────────────────────────────\n\nexport type PromptInputTextareaProps = ComponentProps<\"textarea\"> & {\n placeholder?: string;\n};\n\n/**\n * Auto-resizing textarea for the prompt. Submits on Enter (Shift+Enter for newline).\n * Pastes files into attachments.\n */\nexport const PromptInputTextarea = ({\n onChange,\n className,\n placeholder = \"What would you like to know?\",\n ...props\n}: PromptInputTextareaProps) => {\n const controller = useOptionalPromptInputController();\n const requestCtrl = useOptionalPromptInputRequestController();\n const requestText = useStore(\n requestCtrl?.request ?? FALLBACK_REQUEST_STORE,\n (state) => (typeof state.text === \"string\" ? state.text : \"\")\n );\n const attachments = usePromptInputAttachments();\n\n const handlePaste: ClipboardEventHandler<HTMLTextAreaElement> = (event) => {\n const items = event.clipboardData?.items;\n if (!items) return;\n const pastedFiles: File[] = [];\n for (const item of items) {\n if (item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) pastedFiles.push(file);\n }\n }\n if (pastedFiles.length > 0) {\n event.preventDefault();\n attachments.add(pastedFiles);\n }\n };\n\n const controlledProps = requestCtrl\n ? {\n value: requestText,\n onChange: (e: ChangeEvent<HTMLTextAreaElement>) => {\n requestCtrl.setRequestField(\"text\", e.currentTarget.value);\n onChange?.(e);\n },\n }\n : controller\n ? {\n value: controller.textInput.value,\n onChange: (e: ChangeEvent<HTMLTextAreaElement>) => {\n controller.textInput.setInput(e.currentTarget.value);\n onChange?.(e);\n },\n }\n : { onChange };\n\n return (\n <textarea\n className={cn(\n \"field-sizing-content max-h-48 min-h-16 w-full resize-none border-0 bg-transparent px-3 pt-3 pb-1 text-sm text-sf-default outline-none placeholder:text-sf-inactive\",\n className\n )}\n name=\"message\"\n onKeyDown={handleTextareaKeyDown}\n onPaste={handlePaste}\n placeholder={placeholder}\n rows={1}\n {...props}\n {...controlledProps}\n />\n );\n};\n\n// ─── PromptInputEditor ────────────────────────────────────────────────────────\n\ntype PromptInputMentionState = {\n start: number;\n end: number;\n query: string;\n};\n\nconst getTagMention = (tag: PromptInputTagData) =>\n tag.mention ?? `@${tag.label.replace(/\\s+/gu, \"-\").toLowerCase()}`;\n\nconst findMentionAtCursor = (\n text: string,\n cursor: number\n): PromptInputMentionState | null => {\n const beforeCursor = text.slice(0, cursor);\n const match = /(^|\\s)@([\\w-]*)$/u.exec(beforeCursor);\n if (!match) return null;\n const token = match[0];\n const start = cursor - token.trimStart().length;\n return { start, end: cursor, query: match[2] ?? \"\" };\n};\n\nconst renderInlineReferenceText = (\n text: string,\n tags: PromptInputTagData[]\n) => {\n if (text.length === 0) return null;\n\n const mentions = tags\n .map((tag) => ({ tag, mention: getTagMention(tag) }))\n .filter((item) => item.mention.length > 0)\n .sort((a, b) => b.mention.length - a.mention.length);\n\n const parts: ReactNode[] = [];\n let index = 0;\n\n while (index < text.length) {\n let match: (typeof mentions)[number] | undefined;\n for (const mention of mentions) {\n if (text.startsWith(mention.mention, index)) {\n match = mention;\n break;\n }\n }\n\n if (match) {\n parts.push(\n <span\n className=\"rounded-md bg-sf-tint font-medium text-sf-strong ring-1 ring-sf-line\"\n key={`${match.tag.id}-${index}`}\n >\n {match.mention}\n </span>\n );\n index += match.mention.length;\n continue;\n }\n\n parts.push(text[index]);\n index += 1;\n }\n\n return parts;\n};\n\ntype PromptInputReferencePickerProps = {\n activeIndex: number;\n onSelect: (tag: PromptInputTagData) => void;\n options: PromptInputTagData[];\n style?: CSSProperties;\n};\n\ntype PromptInputPickerPosition = {\n left: number;\n top: number;\n};\n\nconst getTextareaCursorPosition = (\n textarea: HTMLTextAreaElement,\n wrapper: HTMLDivElement | null\n): PromptInputPickerPosition => {\n if (!wrapper) return { left: 12, top: 0 };\n\n const computed = window.getComputedStyle(textarea);\n const wrapperRect = wrapper.getBoundingClientRect();\n\n const paddingLeft = parseFloat(computed.paddingLeft) || 0;\n const paddingTop = parseFloat(computed.paddingTop) || 0;\n const contentWidth = Math.max(\n 1,\n textarea.clientWidth -\n paddingLeft -\n (parseFloat(computed.paddingRight) || 0)\n );\n const lineHeightPx = parseFloat(computed.lineHeight) || 20;\n\n const font =\n computed.font ||\n `${computed.fontStyle} ${computed.fontWeight} ${computed.fontSize} ${computed.fontFamily}`;\n\n const text = textarea.value.slice(0, textarea.selectionStart);\n\n const prepared = prepareWithSegments(text, font, { whiteSpace: \"pre-wrap\" });\n const result = layoutWithLines(prepared, contentWidth, lineHeightPx);\n\n const lineCount = result.lines.length || 1;\n const lastLine = result.lines[result.lines.length - 1];\n const lastLineWidth = lastLine ? lastLine.width : 0;\n\n const top =\n (lineCount - 1) * lineHeightPx + paddingTop + textarea.offsetTop - 6;\n const left = Math.min(\n Math.max(lastLineWidth + paddingLeft + textarea.offsetLeft, 12),\n Math.max(wrapperRect.width - 300, 12)\n );\n\n return { left, top };\n};\n\nconst PromptInputReferencePicker = ({\n activeIndex,\n onSelect,\n options,\n style,\n}: PromptInputReferencePickerProps) => (\n <div\n className=\"absolute z-50 w-72 -translate-y-full overflow-hidden rounded-lg bg-sf-elevated p-1 shadow-lg ring ring-sf-line\"\n style={style}\n >\n <div className=\"px-2 py-1.5 text-xs font-medium text-sf-subtle\">\n References\n </div>\n <div className=\"max-h-56 overflow-y-auto\">\n {options.map((tag, index) => (\n <button\n aria-selected={index === activeIndex}\n className={cn(\n \"flex w-full items-start gap-2 rounded-md px-2 py-2 text-left text-sm text-sf-default hover:bg-sf-tint aria-selected:bg-sf-tint\",\n index === activeIndex && \"bg-sf-tint\"\n )}\n key={tag.id}\n onMouseDown={(event) => {\n event.preventDefault();\n onSelect(tag);\n }}\n // oxlint-disable-next-line prefer-tag-over-role -- custom combobox option, not inside a native <select>\n role=\"option\"\n type=\"button\"\n >\n {tag.icon && <span className=\"mt-0.5 shrink-0\">{tag.icon}</span>}\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium\">{tag.label}</span>\n {tag.description && (\n <span className=\"block truncate text-xs text-sf-subtle\">\n {tag.description}\n </span>\n )}\n </span>\n <span className=\"shrink-0 text-xs text-sf-subtle\">\n {getTagMention(tag)}\n </span>\n </button>\n ))}\n </div>\n </div>\n);\n\nexport type PromptInputEditorProps = Omit<\n ComponentProps<\"textarea\">,\n \"children\"\n> & {\n onReferenceSearch?: PromptInputReferenceSearch;\n references?: PromptInputTagData[];\n};\n\nexport const PromptInputEditor = ({\n className,\n placeholder = \"What would you like to know?\",\n onReferenceSearch,\n references,\n onChange,\n onKeyDown,\n style,\n ...props\n}: PromptInputEditorProps) => {\n const controller = useOptionalPromptInputController();\n const requestCtrl = useOptionalPromptInputRequestController();\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n const wrapperRef = useRef<HTMLDivElement | null>(null);\n const [mention, setMention] = useState<PromptInputMentionState | null>(null);\n const [options, setOptions] = useState<PromptInputTagData[]>([]);\n const [activeIndex, setActiveIndex] = useState(0);\n const [pickerPosition, setPickerPosition] =\n useState<PromptInputPickerPosition>({\n left: 12,\n top: 0,\n });\n\n const requestText = useStore(\n requestCtrl?.request ?? FALLBACK_REQUEST_STORE,\n (state) => (typeof state.text === \"string\" ? state.text : \"\")\n );\n const tags = useStore(\n requestCtrl?.request ?? FALLBACK_REQUEST_STORE,\n (state) =>\n Array.isArray(state.tags) ? (state.tags as PromptInputTagData[]) : []\n );\n const attachments = usePromptInputAttachments();\n const value = requestCtrl ? requestText : (controller?.textInput.value ?? \"\");\n\n const updateMention = useCallback((textarea: HTMLTextAreaElement) => {\n const nextMention = findMentionAtCursor(\n textarea.value,\n textarea.selectionStart\n );\n if (nextMention) {\n setPickerPosition(\n getTextareaCursorPosition(textarea, wrapperRef.current)\n );\n }\n setMention((current) => {\n if (!(current || nextMention)) return current;\n if (\n current &&\n nextMention &&\n current.start === nextMention.start &&\n current.end === nextMention.end &&\n current.query === nextMention.query\n ) {\n return current;\n }\n return nextMention;\n });\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n if (!mention) {\n setOptions([]);\n return;\n }\n\n const load = async () => {\n const result = onReferenceSearch\n ? await onReferenceSearch({ trigger: \"@\", query: mention.query })\n : (references ?? []).filter((tag) =>\n tag.label.toLowerCase().includes(mention.query.toLowerCase())\n );\n if (!cancelled) {\n setOptions(result);\n setActiveIndex((index) => (index < result.length ? index : 0));\n }\n };\n\n load().catch(() => {\n if (!cancelled) setOptions([]);\n });\n\n return () => {\n cancelled = true;\n };\n }, [mention, onReferenceSearch, references]);\n\n const insertReference = useCallback(\n (tag: PromptInputTagData) => {\n if (!(requestCtrl && mention)) return;\n const mentionText = getTagMention(tag);\n requestCtrl.insertTag({ ...tag, mention: mentionText }, mention);\n setMention(null);\n setOptions([]);\n requestAnimationFrame(() => {\n const textarea = textareaRef.current;\n if (!textarea) return;\n const cursor = mention.start + mentionText.length + 1;\n textarea.focus();\n textarea.setSelectionRange(cursor, cursor);\n });\n },\n [mention, requestCtrl]\n );\n\n const handlePaste: ClipboardEventHandler<HTMLTextAreaElement> = (event) => {\n const items = event.clipboardData?.items;\n if (!items) return;\n const pastedFiles: File[] = [];\n for (const item of items) {\n if (item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) pastedFiles.push(file);\n }\n }\n if (pastedFiles.length > 0) {\n event.preventDefault();\n attachments.add(pastedFiles);\n }\n };\n\n const handleKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (event) => {\n if (mention && options.length > 0) {\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n setActiveIndex((index) => (index + 1) % options.length);\n return;\n }\n if (event.key === \"ArrowUp\") {\n event.preventDefault();\n setActiveIndex(\n (index) => (index - 1 + options.length) % options.length\n );\n return;\n }\n if (event.key === \"Enter\" || event.key === \"Tab\") {\n event.preventDefault();\n insertReference(options[activeIndex]);\n return;\n }\n if (event.key === \"Escape\") {\n event.preventDefault();\n setMention(null);\n setOptions([]);\n return;\n }\n }\n\n handleTextareaKeyDown(event);\n onKeyDown?.(event);\n };\n\n const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {\n if (requestCtrl) {\n requestCtrl.setRequestField(\"text\", event.currentTarget.value);\n } else if (controller) {\n controller.textInput.setInput(event.currentTarget.value);\n }\n updateMention(event.currentTarget);\n onChange?.(event);\n };\n\n const showPicker = mention && options.length > 0;\n\n return (\n <div className=\"relative\" ref={wrapperRef}>\n <div\n aria-hidden=\"true\"\n className={cn(\n \"pointer-events-none field-sizing-content max-h-48 min-h-16 w-full overflow-hidden whitespace-pre-wrap break-words px-3 pt-3 pb-1 text-sm text-sf-default\",\n value.length === 0 && \"text-transparent\"\n )}\n >\n {renderInlineReferenceText(value, tags)}\n </div>\n <textarea\n className={cn(\n \"absolute inset-0 field-sizing-content max-h-48 min-h-16 w-full resize-none border-0 bg-transparent px-3 pt-3 pb-1 text-sm text-transparent outline-none placeholder:text-sf-inactive\",\n className\n )}\n name=\"message\"\n onChange={handleChange}\n onClick={(event) => updateMention(event.currentTarget)}\n onKeyDown={handleKeyDown}\n onKeyUp={(event) => {\n if (\n [\"ArrowDown\", \"ArrowUp\", \"Enter\", \"Tab\", \"Escape\"].includes(\n event.key\n )\n ) {\n return;\n }\n updateMention(event.currentTarget);\n }}\n onPaste={handlePaste}\n placeholder={placeholder}\n ref={textareaRef}\n rows={1}\n style={{ caretColor: \"var(--text-color-sf-default)\", ...style }}\n value={value}\n {...props}\n />\n {showPicker && (\n <PromptInputReferencePicker\n activeIndex={activeIndex}\n onSelect={insertReference}\n options={options}\n style={{ left: pickerPosition.left, top: pickerPosition.top }}\n />\n )}\n </div>\n );\n};\n\n// ─── PromptInputToolbar ───────────────────────────────────────────────────────\n\nexport type PromptInputToolbarProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputToolbar = ({\n className,\n ...props\n}: PromptInputToolbarProps) => (\n <div\n className={cn(\n \"grid grid-cols-[minmax(0,1fr)_auto] items-end gap-2 px-2.5 pt-1 pb-2\",\n className\n )}\n {...props}\n />\n);\n\n// ─── PromptInputTools ─────────────────────────────────────────────────────────\n\nexport type PromptInputToolsProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputTools = ({\n className,\n ...props\n}: PromptInputToolsProps) => (\n <div\n className={cn(\"flex min-w-0 flex-wrap items-center gap-1\", className)}\n {...props}\n />\n);\n\n// ─── PromptInputButton ────────────────────────────────────────────────────────\n\nexport type PromptInputButtonProps = ComponentProps<typeof Button> & {\n \"aria-label\": string;\n};\n\nexport const PromptInputButton = ({\n variant = \"ghost\",\n size = \"sm\",\n className,\n ...props\n}: PromptInputButtonProps) => (\n <Button\n className={cn(\"text-sf-subtle hover:text-sf-default\", className)}\n size={size}\n type=\"button\"\n variant={variant}\n {...props}\n />\n);\n\n// ─── PromptInputSubmit ────────────────────────────────────────────────────────\n\nexport type PromptInputSubmitProps = ComponentProps<typeof Button> & {\n status?: SFAiPromptInputStatus;\n};\n\n/**\n * Submit button. Icon changes based on `status`:\n * - `idle` → send arrow\n * - `submitted` → spinner\n * - `streaming` → stop square\n * - `error` → X\n */\nexport const PromptInputSubmit = ({\n className,\n variant = \"primary\",\n size = \"sm\",\n status = \"idle\",\n children,\n ...props\n}: PromptInputSubmitProps) => {\n let Icon: ReactNode;\n if (status === \"submitted\") {\n Icon = <SpinnerGapIcon className=\"size-4 animate-spin\" />;\n } else if (status === \"streaming\") {\n Icon = <SquareIcon className=\"size-4\" />;\n } else if (status === \"error\") {\n Icon = <XIcon className=\"size-4\" />;\n } else {\n Icon = <ArrowUpIcon className=\"size-4\" />;\n }\n\n return (\n <Button\n aria-label=\"Submit\"\n className={cn(\"size-8 shrink-0 justify-center rounded-lg p-0\", className)}\n size={size}\n type=\"submit\"\n variant={variant}\n {...props}\n >\n {children ?? Icon}\n </Button>\n );\n};\n\n// ─── PromptInputActionMenu ────────────────────────────────────────────────────\n\nconst DropdownMenu = DropdownMenuPrimitive;\n\nexport type PromptInputActionMenuProps = ComponentProps<\n typeof DropdownMenu.Root\n>;\n\nexport const PromptInputActionMenu = (props: PromptInputActionMenuProps) => (\n <DropdownMenu.Root {...props} />\n);\n\nexport type PromptInputActionMenuTriggerProps = Omit<\n PromptInputButtonProps,\n \"aria-label\"\n> & {\n \"aria-label\"?: string;\n};\n\nexport const PromptInputActionMenuTrigger = ({\n className,\n children,\n \"aria-label\": ariaLabel = \"More actions\",\n ...props\n}: PromptInputActionMenuTriggerProps) => (\n <DropdownMenu.Trigger\n render={\n <Button\n aria-label={ariaLabel}\n className={cn(\"text-sf-subtle hover:text-sf-default\", className)}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <PlusIcon className=\"size-4\" />}\n </Button>\n }\n />\n);\n\nexport type PromptInputActionMenuContentProps = ComponentProps<\n typeof DropdownMenu.Positioner\n> & { className?: string; children?: ReactNode };\n\nexport const PromptInputActionMenuContent = ({\n className,\n children,\n ...props\n}: PromptInputActionMenuContentProps) => (\n <DropdownMenu.Positioner className=\"z-50\" side=\"top\" align=\"start\" {...props}>\n <DropdownMenu.Popup\n className={cn(\n \"min-w-[160px] rounded-lg bg-sf-elevated p-1 shadow-md\",\n \"data-[starting-style]:opacity-0 data-[ending-style]:opacity-0 transition-opacity duration-100\",\n className\n )}\n >\n {children}\n </DropdownMenu.Popup>\n </DropdownMenu.Positioner>\n);\n\nexport type PromptInputActionMenuItemProps = ComponentProps<\n typeof DropdownMenu.Item\n>;\n\nexport const PromptInputActionMenuItem = ({\n className,\n ...props\n}: PromptInputActionMenuItemProps) => (\n <DropdownMenu.Item\n className={cn(\n \"flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm text-sf-default outline-none\",\n \"data-highlighted:bg-sf-tint\",\n className\n )}\n {...props}\n />\n);\n\n// ─── PromptInputActionAddAttachments ─────────────────────────────────────────\n\nexport type PromptInputActionAddAttachmentsProps =\n PromptInputActionMenuItemProps & {\n label?: string;\n };\n\nexport const PromptInputActionAddAttachments = ({\n label = \"Add photos or files\",\n ...props\n}: PromptInputActionAddAttachmentsProps) => {\n const attachments = usePromptInputAttachments();\n const handleSelect = useCallback(() => {\n attachments.openFileDialog();\n }, [attachments]);\n return (\n <PromptInputActionMenuItem {...props} onSelect={handleSelect}>\n <ImageIcon className=\"size-4\" />\n {label}\n </PromptInputActionMenuItem>\n );\n};\n\n// ─── PromptInputModeSelector ───────────────────────────────────────────────────\n\n/**\n * Pill-style mode selector.\n *\n * Two wiring modes:\n * 1. **Controller-driven (preferred)** — omit `value`/`onChange`; the selector\n * reads/writes `requestContext.mode` via `usePromptInputController()`.\n * 2. **Explicit props** — pass `value` + `onChange` for controlled usage\n * outside a controller (e.g. standalone demos or legacy harnesses).\n *\n * Generic over `TValue` so consumers with a known id union get narrow types.\n *\n * @example Controller-driven\n * ```tsx\n * <PromptInput onSubmit={(ctx) => send(ctx)}>\n * <PromptInputTextarea />\n * <PromptInputToolbar>\n * <PromptInputModeSelector<'build' | 'plan' | 'research'>\n * options={[\n * { value: 'build', label: 'Build' },\n * { value: 'plan', label: 'Plan' },\n * { value: 'research', label: 'Research' },\n * ]}\n * />\n * <PromptInputSubmit />\n * </PromptInputToolbar>\n * </PromptInput>\n * ```\n *\n * @example Explicit\n * ```tsx\n * <PromptInputModeSelector options={opts} value={mode} onChange={setMode} />\n * ```\n */\nexport type PromptInputModeSelectorProps<TValue extends string = string> = {\n /** Available options. Pass an empty array to hide the selector. */\n options: ModeOption<TValue>[];\n /** Controlled value. Omit to bind to `requestContext.mode` via controller. */\n value?: TValue;\n /** Controlled handler. Omit to write `requestContext.mode` via controller. */\n onChange?: (value: TValue) => void;\n /** Optional aria-label override. */\n \"aria-label\"?: string;\n className?: string;\n};\n\nexport const PromptInputModeSelector = <TValue extends string = string>({\n options,\n value: valueProp,\n onChange: onChangeProp,\n \"aria-label\": ariaLabel = \"Select mode\",\n className,\n}: PromptInputModeSelectorProps<TValue>) => {\n const controller = useOptionalPromptInputRequestController();\n\n // Always call the store hook; default to empty store to keep hook order stable.\n const ctxMode = useStore(\n controller?.request ?? FALLBACK_REQUEST_STORE,\n (s) => (s as { mode?: string }).mode\n ) as TValue | undefined;\n\n if (options.length === 0) return null;\n\n const isControlled = valueProp !== undefined || onChangeProp !== undefined;\n const value = isControlled ? valueProp : ctxMode;\n\n const handleSelect = (next: TValue) => {\n if (onChangeProp) {\n onChangeProp(next);\n return;\n }\n if (!isControlled && controller) {\n controller.setRequestField(\"mode\", next);\n }\n };\n\n return (\n <div\n className={cn(\n \"flex items-center gap-0.5 rounded-md bg-sf-tint p-0.5\",\n className\n )}\n // oxlint-disable-next-line prefer-tag-over-role -- toolbar grouping with a dynamic aria-label\n role=\"group\"\n aria-label={ariaLabel}\n >\n {options.map((opt) => {\n const isSelected = opt.value === value;\n return (\n <button\n key={opt.value}\n aria-pressed={isSelected}\n disabled={opt.disabled}\n className={cn(\n \"flex cursor-pointer items-center gap-1 rounded-[4px] px-2 py-0.5 text-[11px] font-medium transition-colors\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n isSelected\n ? \"bg-sf-elevated text-sf-default shadow-sm\"\n : \"text-sf-subtle hover:text-sf-default\"\n )}\n onClick={() => handleSelect(opt.value)}\n title={opt.description}\n type=\"button\"\n >\n {opt.icon}\n {opt.label}\n </button>\n );\n })}\n </div>\n );\n};\n\n// ─── PromptInputCompactSelect (shared primitive) ─────────────────────────────\n\nexport type CompactSelectOption = {\n /** Stable value identifier. */\n value: string;\n /** Display label. Falls back to `value` when omitted. */\n label?: string;\n /** Disable selection. */\n disabled?: boolean;\n};\n\nexport type PromptInputCompactSelectProps = {\n /** Available options. Pass an empty array to render nothing. */\n options: CompactSelectOption[];\n /** Controlled value. */\n value?: string;\n /** Fires when the user picks a new option. */\n onChange?: (value: string) => void;\n /** Trigger text when `value` is empty or doesn't match any option. */\n placeholder?: string;\n /** aria-label for the trigger. */\n \"aria-label\"?: string;\n /** Max width of the trigger label (with truncation). Default `160px`. */\n maxWidth?: number | string;\n className?: string;\n};\n\n/**\n * Compact Select primitive sized for the PromptInput toolbar.\n *\n * - 24px-tall trigger with `text-[11px]` label and truncating value\n * - Matching compact popup with the same text scale\n *\n * Build toolbar-specific selectors (mode, model, voice, tone, ...) by\n * wrapping this and wiring `value`/`onChange` to your state source.\n */\nexport const PromptInputCompactSelect = ({\n options,\n value,\n onChange,\n placeholder = \"Select\",\n \"aria-label\": ariaLabel = \"Select\",\n maxWidth = 160,\n className,\n}: PromptInputCompactSelectProps) => {\n if (options.length === 0) return null;\n\n const selected = options.find((o) => o.value === value);\n const triggerMaxWidth =\n typeof maxWidth === \"number\" ? `${maxWidth}px` : maxWidth;\n\n return (\n <SelectPrimitive.Root\n value={value ?? \"\"}\n onValueChange={(v) => {\n if (typeof v === \"string\") onChange?.(v);\n }}\n >\n <SelectPrimitive.Trigger\n aria-label={ariaLabel}\n style={{ maxWidth: triggerMaxWidth }}\n className={cn(\n \"flex h-6 min-w-0 shrink cursor-pointer items-center gap-1 rounded-[4px] px-2 text-[11px] leading-none font-medium text-sf-subtle transition-colors\",\n \"hover:text-sf-default focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-sf-ring\",\n className\n )}\n >\n <SelectPrimitive.Value className=\"min-w-0 truncate\">\n {selected ? (selected.label ?? selected.value) : placeholder}\n </SelectPrimitive.Value>\n <SelectPrimitive.Icon className=\"flex shrink-0 items-center\">\n <CaretDownIcon className=\"size-3\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n <SelectPrimitive.Portal>\n <SelectPrimitive.Positioner sideOffset={6}>\n <SelectPrimitive.Popup\n className={cn(\n \"overflow-hidden rounded-lg bg-sf-control p-1 text-[11px] text-sf-default shadow-lg ring ring-sf-line\",\n \"min-w-[calc(var(--anchor-width)+3px)]\"\n )}\n >\n {options.map((opt) => (\n <SelectPrimitive.Item\n key={opt.value}\n value={opt.value}\n disabled={opt.disabled}\n className={cn(\n \"flex cursor-pointer items-center justify-between gap-2 rounded px-2 py-1 text-[11px] leading-tight outline-none\",\n \"data-[highlighted]:bg-sf-tint data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\"\n )}\n >\n <SelectPrimitive.ItemText>\n {opt.label ?? opt.value}\n </SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-3\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n ))}\n </SelectPrimitive.Popup>\n </SelectPrimitive.Positioner>\n </SelectPrimitive.Portal>\n </SelectPrimitive.Root>\n );\n};\n\n// ─── PromptInputModelSelect ──────────────────────────────────────────────────\n\nexport type ModelOption = {\n /** Stable model identifier (e.g. `\"anthropic/claude-sonnet-4\"`). */\n value: string;\n /** Display label. Falls back to the last path segment of `value`. */\n label?: string;\n /** Optional group/provider label. */\n group?: string;\n /** Disable selection. */\n disabled?: boolean;\n};\n\nexport type PromptInputModelSelectProps = {\n /** Available model options. Pass an empty array to hide the selector. */\n options: ModelOption[];\n /** Controlled value. Omit to bind to `requestContext.model` via controller. */\n value?: string;\n /** Controlled handler. Omit to write `requestContext.model` via controller. */\n onChange?: (value: string) => void;\n /** Optional aria-label override. */\n \"aria-label\"?: string;\n className?: string;\n};\n\nfunction getModelLabel(option: ModelOption): string {\n if (option.label) return option.label;\n return option.value.split(\"/\").pop() ?? option.value;\n}\n\n/**\n * Compact model selector for the PromptInput toolbar.\n *\n * - Controlled: pass `value` + `onChange`.\n * - Controller-bound: omit both and wrap in `PromptInputRequestControllerProvider`\n * — the selector reads/writes `requestContext.model` automatically.\n */\nexport const PromptInputModelSelect = ({\n options,\n value: valueProp,\n onChange: onChangeProp,\n \"aria-label\": ariaLabel = \"Select model\",\n className,\n}: PromptInputModelSelectProps) => {\n const controller = useOptionalPromptInputRequestController();\n\n const ctxModel = useStore(\n controller?.request ?? FALLBACK_REQUEST_STORE,\n (s) => (s as { model?: string }).model\n );\n\n const isControlled = valueProp !== undefined || onChangeProp !== undefined;\n const value = isControlled ? valueProp : ctxModel;\n\n const handleChange = (next: string) => {\n if (onChangeProp) {\n onChangeProp(next);\n return;\n }\n if (!isControlled && controller) {\n controller.setRequestField(\"model\", next);\n }\n };\n\n const normalized = options.map((o) => ({\n value: o.value,\n label: getModelLabel(o),\n disabled: o.disabled,\n }));\n\n return (\n <PromptInputCompactSelect\n options={normalized}\n value={value}\n onChange={handleChange}\n placeholder=\"Select model\"\n aria-label={ariaLabel}\n className={className}\n />\n );\n};\n\n// ─── PromptInputModeSelect ───────────────────────────────────────────────────\n\nexport type PromptInputModeSelectProps = {\n /** Available modes. */\n options: ModeOption[];\n /** Controlled value. Omit to bind to `requestContext.mode` via controller. */\n value?: string;\n /** Controlled handler. Omit to write `requestContext.mode` via controller. */\n onChange?: (value: string) => void;\n /** Optional aria-label override. */\n \"aria-label\"?: string;\n className?: string;\n};\n\n/**\n * Compact mode selector for the PromptInput toolbar — matches\n * `PromptInputModelSelect` visually. For a segmented button-group look\n * (multi-mode headers, empty states), use `PromptInputModeSelector` instead.\n *\n * - Controlled: pass `value` + `onChange`.\n * - Controller-bound: omit both and wrap in `PromptInputRequestControllerProvider`\n * — the selector reads/writes `requestContext.mode` automatically.\n */\nexport const PromptInputModeSelect = ({\n options,\n value: valueProp,\n onChange: onChangeProp,\n \"aria-label\": ariaLabel = \"Select mode\",\n className,\n}: PromptInputModeSelectProps) => {\n const controller = useOptionalPromptInputRequestController();\n\n const ctxMode = useStore(\n controller?.request ?? FALLBACK_REQUEST_STORE,\n (s) => (s as { mode?: string }).mode\n );\n\n const isControlled = valueProp !== undefined || onChangeProp !== undefined;\n const value = isControlled ? valueProp : ctxMode;\n\n const handleChange = (next: string) => {\n if (onChangeProp) {\n onChangeProp(next);\n return;\n }\n if (!isControlled && controller) {\n controller.setRequestField(\"mode\", next);\n }\n };\n\n const normalized = options.map((o) => ({\n value: o.value,\n label: o.label ?? o.value,\n disabled: o.disabled,\n }));\n\n return (\n <PromptInputCompactSelect\n options={normalized}\n value={value}\n onChange={handleChange}\n placeholder=\"Select mode\"\n aria-label={ariaLabel}\n className={className}\n />\n );\n};\n\n// ─── PromptInputCompactCycle (shared primitive) ──────────────────────────────\n\nexport type PromptInputCompactCycleProps = {\n /** Available options. Cycles through them in order, wrapping at end. */\n options: CompactSelectOption[];\n /** Current value. If unset (or no match), the first option is highlighted. */\n value?: string;\n /** Fires when the user clicks (advances to next non-disabled option). */\n onChange?: (value: string) => void;\n /** aria-label for the button. */\n \"aria-label\"?: string;\n /** Show the small cycle icon next to the label. @default true */\n showIcon?: boolean;\n /** Max width of the label (truncates). @default 160px */\n maxWidth?: number | string;\n className?: string;\n};\n\n/**\n * Single compact button that cycles through `options` on click.\n *\n * - Click / Enter / Space → next option (wraps at end)\n * - Shift+Click / Shift+Enter → previous option\n * - Skips `disabled` options\n *\n * Useful for binary or 2–3 option toggles where a dropdown feels heavy.\n */\nexport const PromptInputCompactCycle = ({\n options,\n value,\n onChange,\n \"aria-label\": ariaLabel = \"Cycle option\",\n showIcon = true,\n maxWidth = 160,\n className,\n}: PromptInputCompactCycleProps) => {\n const enabledOptions = options.filter((o) => !o.disabled);\n if (enabledOptions.length === 0) return null;\n\n const currentIndex = options.findIndex((o) => o.value === value);\n const current =\n currentIndex === -1 ? enabledOptions[0] : options[currentIndex];\n\n const advance = (direction: 1 | -1) => {\n // Find the next/prev non-disabled option, wrapping around.\n const start = currentIndex === -1 ? -direction : currentIndex;\n const len = options.length;\n for (let step = 1; step <= len; step++) {\n const i = (start + direction * step + len * len) % len;\n const candidate = options[i];\n if (candidate && !candidate.disabled) {\n onChange?.(candidate.value);\n return;\n }\n }\n };\n\n const triggerMaxWidth =\n typeof maxWidth === \"number\" ? `${maxWidth}px` : maxWidth;\n\n return (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n title={`${current?.label ?? current?.value ?? \"\"} — click to cycle`}\n style={{ maxWidth: triggerMaxWidth }}\n onClick={(e) => advance(e.shiftKey ? -1 : 1)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n advance(e.shiftKey ? -1 : 1);\n }\n }}\n className={cn(\n \"flex h-6 min-w-0 shrink cursor-pointer items-center gap-1 rounded-[4px] px-2 text-[11px] leading-none font-medium text-sf-subtle transition-colors\",\n \"hover:text-sf-default focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-sf-ring\",\n className\n )}\n >\n <span className=\"min-w-0 truncate\">\n {current?.label ?? current?.value ?? \"\"}\n </span>\n {showIcon && (\n <ArrowsClockwiseIcon className=\"size-3 shrink-0 opacity-70\" />\n )}\n </button>\n );\n};\n\n// ─── PromptInputModeCycle ────────────────────────────────────────────────────\n\nexport type PromptInputModeCycleProps = {\n /** Available modes to cycle through. */\n options: ModeOption[];\n /** Controlled value. Omit to bind to `requestContext.mode` via controller. */\n value?: string;\n /** Controlled handler. Omit to write `requestContext.mode` via controller. */\n onChange?: (value: string) => void;\n /** Optional aria-label override. */\n \"aria-label\"?: string;\n /** Show the small cycle icon next to the label. @default true */\n showIcon?: boolean;\n className?: string;\n};\n\n/**\n * Click-to-cycle mode picker. Single compact button that advances through\n * `options` on each click. Best for 2–3 modes.\n *\n * - Controlled: pass `value` + `onChange`.\n * - Controller-bound: omit both and wrap in `PromptInputRequestControllerProvider`\n * — reads/writes `requestContext.mode` automatically.\n */\nexport const PromptInputModeCycle = ({\n options,\n value: valueProp,\n onChange: onChangeProp,\n \"aria-label\": ariaLabel = \"Cycle mode\",\n showIcon = true,\n className,\n}: PromptInputModeCycleProps) => {\n const controller = useOptionalPromptInputRequestController();\n\n const ctxMode = useStore(\n controller?.request ?? FALLBACK_REQUEST_STORE,\n (s) => (s as { mode?: string }).mode\n );\n\n const isControlled = valueProp !== undefined || onChangeProp !== undefined;\n const value = isControlled ? valueProp : ctxMode;\n\n const handleChange = (next: string) => {\n if (onChangeProp) {\n onChangeProp(next);\n return;\n }\n if (!isControlled && controller) {\n controller.setRequestField(\"mode\", next);\n }\n };\n\n const normalized = options.map((o) => ({\n value: o.value,\n label: o.label ?? o.value,\n disabled: o.disabled,\n }));\n\n return (\n <PromptInputCompactCycle\n options={normalized}\n value={value}\n onChange={handleChange}\n aria-label={ariaLabel}\n showIcon={showIcon}\n className={className}\n />\n );\n};\n\n// ─── PromptInputModelCycle ───────────────────────────────────────────────────\n\nexport type PromptInputModelCycleProps = {\n /** Available models to cycle through. */\n options: ModelOption[];\n /** Controlled value. Omit to bind to `requestContext.model` via controller. */\n value?: string;\n /** Controlled handler. Omit to write `requestContext.model` via controller. */\n onChange?: (value: string) => void;\n /** Optional aria-label override. */\n \"aria-label\"?: string;\n /** Show the small cycle icon next to the label. @default true */\n showIcon?: boolean;\n className?: string;\n};\n\n/**\n * Click-to-cycle model picker. Single compact button that advances through\n * `options` on each click. Best for 2–3 models.\n *\n * - Controlled: pass `value` + `onChange`.\n * - Controller-bound: omit both and wrap in `PromptInputRequestControllerProvider`\n * — reads/writes `requestContext.model` automatically.\n */\nexport const PromptInputModelCycle = ({\n options,\n value: valueProp,\n onChange: onChangeProp,\n \"aria-label\": ariaLabel = \"Cycle model\",\n showIcon = true,\n className,\n}: PromptInputModelCycleProps) => {\n const controller = useOptionalPromptInputRequestController();\n\n const ctxModel = useStore(\n controller?.request ?? FALLBACK_REQUEST_STORE,\n (s) => (s as { model?: string }).model\n );\n\n const isControlled = valueProp !== undefined || onChangeProp !== undefined;\n const value = isControlled ? valueProp : ctxModel;\n\n const handleChange = (next: string) => {\n if (onChangeProp) {\n onChangeProp(next);\n return;\n }\n if (!isControlled && controller) {\n controller.setRequestField(\"model\", next);\n }\n };\n\n const normalized = options.map((o) => ({\n value: o.value,\n label: getModelLabel(o),\n disabled: o.disabled,\n }));\n\n return (\n <PromptInputCompactCycle\n options={normalized}\n value={value}\n onChange={handleChange}\n aria-label={ariaLabel}\n showIcon={showIcon}\n className={className}\n />\n );\n};\n\n// ─── Attachment display helpers ───────────────────────────────────────────────\n\nconst IMAGE_EXTS = new Set([\"jpg\", \"jpeg\", \"png\", \"gif\", \"webp\", \"svg\"]);\n\nfunction getFileIcon(filename: string): ReactNode {\n const ext = filename.split(\".\").pop()?.toLowerCase() ?? \"\";\n if (IMAGE_EXTS.has(ext)) return <ImageIcon className=\"size-3.5\" />;\n if ([\"pdf\", \"doc\", \"docx\", \"txt\", \"md\"].includes(ext))\n return <FileTextIcon className=\"size-3.5\" />;\n return <FileIcon className=\"size-3.5\" />;\n}\n\n// ─── PromptInputAttachment ────────────────────────────────────────────────────\n\nexport type PromptInputAttachmentProps = HTMLAttributes<HTMLDivElement> & {\n data: AttachmentFile;\n};\n\n/**\n * Single attachment chip for images or files. Includes a remove button.\n */\nexport function PromptInputAttachment({\n data,\n className,\n ...props\n}: PromptInputAttachmentProps) {\n const attachments = usePromptInputAttachments();\n const isImage = data.mediaType?.startsWith(\"image/\") && data.url;\n\n const handleRemove = useCallback(() => {\n attachments.remove(data.id);\n }, [attachments, data.id]);\n\n if (isImage) {\n return (\n <div\n className={cn(\n \"group relative size-14 overflow-hidden rounded-md\",\n className\n )}\n {...props}\n >\n <img\n alt={data.filename || \"attachment\"}\n className=\"size-full object-cover\"\n src={data.url}\n />\n <Button\n aria-label=\"Remove attachment\"\n className=\"absolute top-1 right-1 size-5 rounded-full bg-sf-overlay/80 p-0 opacity-0 backdrop-blur-sm transition-opacity group-hover:opacity-100\"\n onClick={handleRemove}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n >\n <XIcon className=\"size-3\" />\n </Button>\n </div>\n );\n }\n\n const ext = data.filename.split(\".\").pop()?.toUpperCase() ?? \"FILE\";\n const name = data.filename.replace(/\\.[^/.]+$/u, \"\");\n\n return (\n <div\n className={cn(\n \"group relative inline-flex h-8 items-center gap-2 rounded-md bg-sf-tint/50 px-2 text-sm\",\n className\n )}\n {...props}\n >\n <div className=\"flex size-5 shrink-0 items-center justify-center text-sf-subtle\">\n {getFileIcon(data.filename)}\n </div>\n <Tooltip content={data.filename}>\n <span className=\"max-w-[160px] truncate font-medium text-sf-default\">\n {name || \"File\"}\n </span>\n </Tooltip>\n <span className=\"rounded bg-sf-tint px-1 py-0.5 font-semibold text-sf-subtle text-[10px] uppercase\">\n {ext}\n </span>\n <Button\n aria-label=\"Remove attachment\"\n className=\"ml-0.5 size-4 shrink-0 rounded-full p-0 opacity-0 transition-opacity group-hover:opacity-100\"\n onClick={handleRemove}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n >\n <XIcon className=\"size-3\" />\n </Button>\n </div>\n );\n}\n\n// ─── PromptInputAttachments ───────────────────────────────────────────────────\n\nexport type PromptInputAttachmentsProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n \"children\"\n> & {\n children: (attachment: AttachmentFile) => ReactNode;\n};\n\n/**\n * Renders all attachments using a render prop. Hidden when no files.\n * Animates height as files are added/removed.\n */\nexport function PromptInputAttachments({\n className,\n children,\n ...props\n}: PromptInputAttachmentsProps) {\n const attachments = usePromptInputAttachments();\n const [height, setHeight] = useState(0);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (!el) return;\n const ro = new ResizeObserver(() => {\n setHeight(el.getBoundingClientRect().height);\n });\n ro.observe(el);\n setHeight(el.getBoundingClientRect().height);\n return () => ro.disconnect();\n }, []);\n\n // Re-measure when file count changes\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional re-measure on count change\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (el) setHeight(el.getBoundingClientRect().height);\n }, [attachments.files.length]);\n\n if (attachments.files.length === 0) return null;\n\n return (\n <div\n aria-live=\"polite\"\n className={cn(\n \"overflow-hidden px-2.5 transition-[height] duration-200 ease-out\",\n className\n )}\n style={{ height: attachments.files.length ? height : 0 }}\n {...props}\n >\n <div className=\"flex flex-wrap gap-2 pt-2 pb-1\" ref={contentRef}>\n {attachments.files.map((file) => (\n <Fragment key={file.id}>{children(file)}</Fragment>\n ))}\n </div>\n </div>\n );\n}\n\n// ─── PromptInputTags ──────────────────────────────────────────────────────────\n\nexport type PromptInputTagProps = HTMLAttributes<HTMLDivElement> & {\n data: PromptInputTagData;\n};\n\n/**\n * Single reference chip for prompt tags. Includes a remove button when mounted\n * inside a PromptInputRequestControllerProvider.\n */\nexport function PromptInputTag({\n data,\n className,\n ...props\n}: PromptInputTagProps) {\n const requestCtrl = useOptionalPromptInputRequestController();\n\n const handleRemove = useCallback(() => {\n requestCtrl?.removeTag(data.id);\n }, [requestCtrl, data.id]);\n\n const chip = (\n <div\n className={cn(\n \"group inline-flex h-8 items-center gap-2 rounded-md border border-sf-info/30 bg-sf-info-tint px-2 text-sm text-sf-default\",\n className\n )}\n {...props}\n >\n {data.icon && (\n <div className=\"flex size-4 shrink-0 items-center justify-center\">\n {data.icon}\n </div>\n )}\n <span className=\"max-w-[180px] truncate font-medium\">{data.label}</span>\n {requestCtrl && (\n <Button\n aria-label=\"Remove tag\"\n className=\"ml-0.5 size-4 shrink-0 rounded-full p-0 opacity-0 transition-opacity group-hover:opacity-100\"\n onClick={handleRemove}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n >\n <XIcon className=\"size-3\" />\n </Button>\n )}\n </div>\n );\n\n if (!data.description) return chip;\n return <Tooltip content={data.description}>{chip}</Tooltip>;\n}\n\nexport type PromptInputTagsProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n \"children\"\n> & {\n children: (tag: PromptInputTagData) => ReactNode;\n};\n\n/**\n * Renders all prompt tags using a render prop. Hidden when no tags.\n * Animates height as tags are added/removed.\n */\nexport function PromptInputTags({\n className,\n children,\n ...props\n}: PromptInputTagsProps) {\n const requestCtrl = useOptionalPromptInputRequestController();\n const tags = useStore(\n requestCtrl?.request ?? FALLBACK_REQUEST_STORE,\n (state) => (state as { tags?: PromptInputTagData[] }).tags ?? []\n );\n const [height, setHeight] = useState(0);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (!el) return;\n const ro = new ResizeObserver(() => {\n setHeight(el.getBoundingClientRect().height);\n });\n ro.observe(el);\n setHeight(el.getBoundingClientRect().height);\n return () => ro.disconnect();\n }, []);\n\n // Re-measure when tag count changes\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional re-measure on count change\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (el) setHeight(el.getBoundingClientRect().height);\n }, [tags.length]);\n\n if (tags.length === 0) return null;\n\n return (\n <div\n aria-live=\"polite\"\n className={cn(\n \"overflow-hidden px-2.5 transition-[height] duration-200 ease-out\",\n className\n )}\n style={{ height: tags.length ? height : 0 }}\n {...props}\n >\n <div className=\"flex flex-wrap gap-2 pt-2 pb-1\" ref={contentRef}>\n {tags.map((tag) => (\n <Fragment key={tag.id}>{children(tag)}</Fragment>\n ))}\n </div>\n </div>\n );\n}\n\nexport type PromptInputAddTagButtonProps = ComponentProps<typeof Button> & {\n onOpenPicker?: () => void;\n};\n\n/**\n * Toolbar trigger for opening a consumer-owned tag picker.\n */\nexport function PromptInputAddTagButton({\n children,\n onClick,\n onOpenPicker,\n ...props\n}: PromptInputAddTagButtonProps) {\n return (\n <Button\n aria-label=\"Add tag\"\n onClick={(event) => {\n onOpenPicker?.();\n onClick?.(event);\n }}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <PlusIcon className=\"size-4\" />}\n </Button>\n );\n}\n\n// ─── Speech recognition types ─────────────────────────────────────────────────\n\ntype SpeechRecognitionInstance = EventTarget & {\n continuous: boolean;\n interimResults: boolean;\n lang: string;\n start(): void;\n stop(): void;\n};\n\ntype SpeechRecognitionResultEvent = Event & {\n results: {\n readonly length: number;\n item(index: number): {\n isFinal: boolean;\n [i: number]: { transcript: string };\n };\n [index: number]: { isFinal: boolean; [i: number]: { transcript: string } };\n };\n};\n\ntype SpeechRecognitionConstructor = new () => SpeechRecognitionInstance;\n\ndeclare global {\n interface Window {\n SpeechRecognition?: SpeechRecognitionConstructor;\n webkitSpeechRecognition?: SpeechRecognitionConstructor;\n }\n}\n\n// ─── PromptInputSpeechButton ──────────────────────────────────────────────────\n\nexport type PromptInputSpeechButtonProps = Omit<\n PromptInputButtonProps,\n \"aria-label\"\n> & {\n \"aria-label\"?: string;\n textareaRef?: RefObject<HTMLTextAreaElement | null>;\n onTranscriptionChange?: (text: string) => void;\n};\n\n/**\n * Voice input button. Uses the Web Speech API (Chrome/Edge). Hidden on unsupported browsers.\n * Pulses while listening.\n */\nexport const PromptInputSpeechButton = ({\n className,\n textareaRef,\n onTranscriptionChange,\n \"aria-label\": ariaLabel = \"Voice input\",\n ...props\n}: PromptInputSpeechButtonProps) => {\n const [isListening, setIsListening] = useState(false);\n const [recognition, setRecognition] =\n useState<SpeechRecognitionInstance | null>(null);\n const recognitionRef = useRef<SpeechRecognitionInstance | null>(null);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const SR = window.SpeechRecognition ?? window.webkitSpeechRecognition;\n if (!SR) return;\n\n const sr = new SR() as SpeechRecognitionInstance & {\n continuous: boolean;\n interimResults: boolean;\n lang: string;\n };\n sr.continuous = true;\n sr.interimResults = true;\n sr.lang = \"en-US\";\n\n const handleStart = () => setIsListening(true);\n const handleEnd = () => setIsListening(false);\n const handleResult = (event: Event) => {\n const e = event as SpeechRecognitionResultEvent;\n let final = \"\";\n for (const result of Array.from(\n { length: e.results.length },\n (_, i) => e.results[i]\n )) {\n if (result?.isFinal && result[0]?.transcript) {\n final += result[0].transcript;\n }\n }\n if (final && textareaRef?.current) {\n const ta = textareaRef.current;\n const next = ta.value + (ta.value ? \" \" : \"\") + final;\n ta.value = next;\n ta.dispatchEvent(new Event(\"input\", { bubbles: true }));\n onTranscriptionChange?.(next);\n }\n };\n const handleError = (_event: Event) => setIsListening(false);\n\n sr.addEventListener(\"start\", handleStart);\n sr.addEventListener(\"end\", handleEnd);\n sr.addEventListener(\"result\", handleResult);\n sr.addEventListener(\"error\", handleError);\n\n recognitionRef.current = sr;\n setRecognition(sr);\n\n return () => {\n sr.removeEventListener(\"start\", handleStart);\n sr.removeEventListener(\"end\", handleEnd);\n sr.removeEventListener(\"result\", handleResult);\n sr.removeEventListener(\"error\", handleError);\n recognitionRef.current?.stop();\n };\n }, [textareaRef, onTranscriptionChange]);\n\n const handleToggleListening = useCallback(() => {\n if (!recognition) return;\n const sr = recognition as SpeechRecognitionInstance & {\n start(): void;\n stop(): void;\n };\n if (isListening) sr.stop();\n else sr.start();\n }, [recognition, isListening]);\n\n const button = (\n <Button\n aria-label={ariaLabel}\n className={cn(\n \"text-sf-subtle hover:text-sf-default transition-all\",\n isListening && \"animate-pulse text-sf-brand\",\n className\n )}\n disabled={!recognition}\n onClick={handleToggleListening}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n <MicrophoneIcon className=\"size-4\" />\n </Button>\n );\n\n if (!recognition) return null;\n\n return (\n <Tooltip content={isListening ? \"Stop listening\" : \"Voice input\"}>\n {button}\n </Tooltip>\n );\n};\n\n// ─── PromptInputAttachButton ──────────────────────────────────────────────────\n\nexport type PromptInputAttachButtonProps = Omit<\n PromptInputButtonProps,\n \"aria-label\"\n> & {\n \"aria-label\"?: string;\n};\n\n/**\n * Convenience button that opens the file dialog directly (no dropdown needed).\n */\nexport const PromptInputAttachButton = ({\n \"aria-label\": ariaLabel = \"Attach file\",\n className,\n ...props\n}: PromptInputAttachButtonProps) => {\n const attachments = usePromptInputAttachments();\n const handleClick = useCallback(() => {\n attachments.openFileDialog();\n }, [attachments]);\n return (\n <Tooltip content={ariaLabel}>\n <Button\n aria-label={ariaLabel}\n className={cn(\"text-sf-subtle hover:text-sf-default\", className)}\n onClick={handleClick}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n <PaperclipIcon className=\"size-4\" />\n </Button>\n </Tooltip>\n );\n};\n\nPromptInput.BackLayer = PromptInputBackLayer;\nPromptInput.Textarea = PromptInputTextarea;\nPromptInput.Editor = PromptInputEditor;\nPromptInput.Toolbar = PromptInputToolbar;\nPromptInput.Tools = PromptInputTools;\nPromptInput.Submit = PromptInputSubmit;\nPromptInput.ModeSelector = PromptInputModeSelector;\nPromptInput.AddTagButton = PromptInputAddTagButton;\nPromptInput.Tags = PromptInputTags;\nPromptInput.Tag = PromptInputTag;\nPromptInput.AttachButton = PromptInputAttachButton;\nPromptInput.Attachments = PromptInputAttachments;\nPromptInput.Attachment = PromptInputAttachment;\n"],"x_google_ignoreList":[0,1,2,3,4],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { t as cn } from "./cn-
|
|
3
|
-
import { t as Button } from "./button-
|
|
2
|
+
import { t as cn } from "./cn-CmAOpn49.js";
|
|
3
|
+
import { t as Button } from "./button-BHOgXJRU.js";
|
|
4
4
|
import { useCallback, useState } from "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { ChatCircleDotsIcon, CheckIcon } from "@phosphor-icons/react";
|
|
@@ -116,6 +116,7 @@ function AiQuestion({ questionId, question, header, status = "pending", options,
|
|
|
116
116
|
})
|
|
117
117
|
}),
|
|
118
118
|
isPending && allowCustom && /* @__PURE__ */ jsx("textarea", {
|
|
119
|
+
"aria-label": "Custom answer",
|
|
119
120
|
className: "min-h-[48px] resize-none rounded-md border border-sf-line/50 bg-sf-base px-2.5 py-1.5 text-sm text-sf-default outline-none placeholder:text-sf-inactive focus:border-sf-ring",
|
|
120
121
|
onChange: (e) => setCustomText(e.target.value),
|
|
121
122
|
placeholder: "Type your answer…",
|
|
@@ -146,4 +147,4 @@ AiQuestion.displayName = "AiQuestion";
|
|
|
146
147
|
//#endregion
|
|
147
148
|
export { SF_AI_QUESTION_DEFAULT_VARIANTS as n, SF_AI_QUESTION_VARIANTS as r, AiQuestion as t };
|
|
148
149
|
|
|
149
|
-
//# sourceMappingURL=ai-question-
|
|
150
|
+
//# sourceMappingURL=ai-question-OyJovxGe.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-question-CHHoDJMg.js","names":[],"sources":["../src/components/ai-question/ai-question.tsx"],"sourcesContent":["\"use client\";\n\nimport { ChatCircleDotsIcon, CheckIcon } from \"@phosphor-icons/react\";\nimport type { ElementType, HTMLAttributes, ReactNode } from \"react\";\nimport { useCallback, useState } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../button\";\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_QUESTION_VARIANTS = {\n status: {\n pending: { classes: \"\", description: \"Waiting for answer\" },\n answered: { classes: \"\", description: \"User has answered\" },\n },\n} as const;\n\nexport const SF_AI_QUESTION_DEFAULT_VARIANTS = {\n status: \"pending\",\n} as const;\n\nexport type SFAiQuestionStatus = keyof typeof SF_AI_QUESTION_VARIANTS.status;\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type AiQuestionOption = {\n label: string;\n description?: string;\n};\n\nexport type AiQuestionProps = Omit<HTMLAttributes<HTMLDivElement>, \"title\"> & {\n /** Unique identifier for this question (maps to harness `questionId`). */\n questionId: string;\n /** The question text. */\n question: string;\n /** Optional header/context label. */\n header?: string;\n /** Current status. */\n status?: SFAiQuestionStatus;\n /** Available choice options. */\n options?: AiQuestionOption[];\n /** Allow selecting multiple options. Default: `false`. */\n multiple?: boolean;\n /**\n * Allow freeform text input (custom answer). Default: `true`.\n * When options are provided, this adds a text field below them.\n */\n allowCustom?: boolean;\n /** Custom icon for the question header. */\n icon?: ElementType;\n /** Called when the user submits their answer. */\n onAnswer?: (questionId: string, answer: string) => void;\n /** The answer that was submitted (shown when `status=\"answered\"`). */\n answeredWith?: string;\n /** Content rendered below the question, above options. */\n children?: ReactNode;\n};\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\n/**\n * Agent question card. Renders when the agent uses the `ask_user` built-in\n * tool and needs a response before continuing.\n *\n * Maps to harness event: `ask_question`.\n *\n * @example\n * ```tsx\n * <AiQuestion\n * questionId=\"q-123\"\n * question=\"How should I handle the failing tests?\"\n * header=\"Decision needed\"\n * options={[\n * { label: \"Fix them\", description: \"Update the test expectations\" },\n * { label: \"Skip them\", description: \"Mark as skipped for now\" },\n * ]}\n * onAnswer={(id, answer) => harness.respondToQuestion({ questionId: id, answer })}\n * />\n * ```\n */\nexport function AiQuestion({\n questionId,\n question,\n header,\n status = \"pending\",\n options,\n multiple = false,\n allowCustom = true,\n icon,\n onAnswer,\n answeredWith,\n children,\n className,\n ...props\n}: AiQuestionProps) {\n const [selected, setSelected] = useState<Set<string>>(new Set());\n const [customText, setCustomText] = useState(\"\");\n const isPending = status === \"pending\";\n\n const IconComponent = icon ?? ChatCircleDotsIcon;\n\n const toggleOption = useCallback(\n (label: string) => {\n setSelected((prev) => {\n const next = new Set(prev);\n if (multiple) {\n if (next.has(label)) next.delete(label);\n else next.add(label);\n } else if (next.has(label)) {\n next.clear();\n } else {\n next.clear();\n next.add(label);\n }\n return next;\n });\n },\n [multiple]\n );\n\n const handleSubmit = useCallback(() => {\n // Custom text takes priority; otherwise join selected option labels\n const answer = customText.trim() || [...selected].join(\", \");\n if (answer) {\n onAnswer?.(questionId, answer);\n }\n }, [customText, selected, questionId, onAnswer]);\n\n const hasAnswer = customText.trim() || selected.size > 0;\n\n return (\n <div\n className={cn(\n \"flex flex-col gap-2.5 rounded-lg bg-sf-tint/50 p-3\",\n !isPending && \"opacity-75\",\n className\n )}\n {...props}\n >\n {/* Header */}\n <div className=\"flex items-start gap-2.5\">\n <div className=\"mt-0.5 flex size-6 shrink-0 items-center justify-center rounded-md bg-sf-brand/10 text-sf-brand\">\n <IconComponent className=\"size-4\" weight=\"bold\" />\n </div>\n <div className=\"flex min-w-0 flex-col gap-0.5\">\n {header && (\n <span className=\"text-sm font-medium text-sf-subtle uppercase tracking-wide\">\n {header}\n </span>\n )}\n <span className=\"text-sm font-medium text-sf-default\">\n {question}\n </span>\n </div>\n </div>\n\n {children}\n\n {/* Options */}\n {isPending && options && options.length > 0 && (\n <div className=\"flex flex-col gap-1 pl-0.5\">\n {options.map((opt) => {\n const isSelected = selected.has(opt.label);\n return (\n <button\n className={cn(\n \"flex items-center gap-2.5 rounded-md border px-2.5 py-2 text-left text-sm transition-colors\",\n isSelected\n ? \"border-sf-line/50 bg-sf-tint text-sf-default\"\n : \"border-transparent bg-transparent text-sf-default hover:bg-sf-tint/50\"\n )}\n key={opt.label}\n onClick={() => toggleOption(opt.label)}\n type=\"button\"\n >\n <div\n className={cn(\n \"flex size-4 shrink-0 items-center justify-center rounded border transition-colors\",\n isSelected\n ? \"border-sf-brand bg-sf-brand text-sf-inverse\"\n : \"border-sf-line\"\n )}\n >\n {isSelected && <CheckIcon className=\"size-3\" weight=\"bold\" />}\n </div>\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"font-medium\">{opt.label}</span>\n {opt.description && (\n <span className=\"text-sm text-sf-subtle\">\n {opt.description}\n </span>\n )}\n </div>\n </button>\n );\n })}\n </div>\n )}\n\n {/* Custom text input */}\n {isPending && allowCustom && (\n <textarea\n className=\"min-h-[48px] resize-none rounded-md border border-sf-line/50 bg-sf-base px-2.5 py-1.5 text-sm text-sf-default outline-none placeholder:text-sf-inactive focus:border-sf-ring\"\n onChange={(e) => setCustomText(e.target.value)}\n placeholder=\"Type your answer…\"\n value={customText}\n />\n )}\n\n {/* Submit */}\n {isPending && (\n <div className=\"flex justify-end\">\n <Button\n disabled={!hasAnswer}\n onClick={handleSubmit}\n size=\"sm\"\n type=\"button\"\n variant=\"primary\"\n >\n Submit answer\n </Button>\n </div>\n )}\n\n {/* Answered state */}\n {!isPending && answeredWith && (\n <div className=\"flex items-center gap-2 pl-8 text-sm text-sf-subtle\">\n <CheckIcon className=\"size-3.5 text-sf-success\" weight=\"bold\" />\n <span>Answered: {answeredWith}</span>\n </div>\n )}\n </div>\n );\n}\n\nAiQuestion.displayName = \"AiQuestion\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-question-OyJovxGe.js","names":[],"sources":["../src/components/ai-question/ai-question.tsx"],"sourcesContent":["\"use client\";\n\nimport { ChatCircleDotsIcon, CheckIcon } from \"@phosphor-icons/react\";\nimport type { ElementType, HTMLAttributes, ReactNode } from \"react\";\nimport { useCallback, useState } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../button\";\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_QUESTION_VARIANTS = {\n status: {\n pending: { classes: \"\", description: \"Waiting for answer\" },\n answered: { classes: \"\", description: \"User has answered\" },\n },\n} as const;\n\nexport const SF_AI_QUESTION_DEFAULT_VARIANTS = {\n status: \"pending\",\n} as const;\n\nexport type SFAiQuestionStatus = keyof typeof SF_AI_QUESTION_VARIANTS.status;\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type AiQuestionOption = {\n label: string;\n description?: string;\n};\n\nexport type AiQuestionProps = Omit<HTMLAttributes<HTMLDivElement>, \"title\"> & {\n /** Unique identifier for this question (maps to harness `questionId`). */\n questionId: string;\n /** The question text. */\n question: string;\n /** Optional header/context label. */\n header?: string;\n /** Current status. */\n status?: SFAiQuestionStatus;\n /** Available choice options. */\n options?: AiQuestionOption[];\n /** Allow selecting multiple options. Default: `false`. */\n multiple?: boolean;\n /**\n * Allow freeform text input (custom answer). Default: `true`.\n * When options are provided, this adds a text field below them.\n */\n allowCustom?: boolean;\n /** Custom icon for the question header. */\n icon?: ElementType;\n /** Called when the user submits their answer. */\n onAnswer?: (questionId: string, answer: string) => void;\n /** The answer that was submitted (shown when `status=\"answered\"`). */\n answeredWith?: string;\n /** Content rendered below the question, above options. */\n children?: ReactNode;\n};\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\n/**\n * Agent question card. Renders when the agent uses the `ask_user` built-in\n * tool and needs a response before continuing.\n *\n * Maps to harness event: `ask_question`.\n *\n * @example\n * ```tsx\n * <AiQuestion\n * questionId=\"q-123\"\n * question=\"How should I handle the failing tests?\"\n * header=\"Decision needed\"\n * options={[\n * { label: \"Fix them\", description: \"Update the test expectations\" },\n * { label: \"Skip them\", description: \"Mark as skipped for now\" },\n * ]}\n * onAnswer={(id, answer) => harness.respondToQuestion({ questionId: id, answer })}\n * />\n * ```\n */\nexport function AiQuestion({\n questionId,\n question,\n header,\n status = \"pending\",\n options,\n multiple = false,\n allowCustom = true,\n icon,\n onAnswer,\n answeredWith,\n children,\n className,\n ...props\n}: AiQuestionProps) {\n const [selected, setSelected] = useState<Set<string>>(new Set());\n const [customText, setCustomText] = useState(\"\");\n const isPending = status === \"pending\";\n\n const IconComponent = icon ?? ChatCircleDotsIcon;\n\n const toggleOption = useCallback(\n (label: string) => {\n setSelected((prev) => {\n const next = new Set(prev);\n if (multiple) {\n if (next.has(label)) next.delete(label);\n else next.add(label);\n } else if (next.has(label)) {\n next.clear();\n } else {\n next.clear();\n next.add(label);\n }\n return next;\n });\n },\n [multiple]\n );\n\n const handleSubmit = useCallback(() => {\n // Custom text takes priority; otherwise join selected option labels\n const answer = customText.trim() || [...selected].join(\", \");\n if (answer) {\n onAnswer?.(questionId, answer);\n }\n }, [customText, selected, questionId, onAnswer]);\n\n const hasAnswer = customText.trim() || selected.size > 0;\n\n return (\n <div\n className={cn(\n \"flex flex-col gap-2.5 rounded-lg bg-sf-tint/50 p-3\",\n !isPending && \"opacity-75\",\n className\n )}\n {...props}\n >\n {/* Header */}\n <div className=\"flex items-start gap-2.5\">\n <div className=\"mt-0.5 flex size-6 shrink-0 items-center justify-center rounded-md bg-sf-brand/10 text-sf-brand\">\n <IconComponent className=\"size-4\" weight=\"bold\" />\n </div>\n <div className=\"flex min-w-0 flex-col gap-0.5\">\n {header && (\n <span className=\"text-sm font-medium text-sf-subtle uppercase tracking-wide\">\n {header}\n </span>\n )}\n <span className=\"text-sm font-medium text-sf-default\">\n {question}\n </span>\n </div>\n </div>\n\n {children}\n\n {/* Options */}\n {isPending && options && options.length > 0 && (\n <div className=\"flex flex-col gap-1 pl-0.5\">\n {options.map((opt) => {\n const isSelected = selected.has(opt.label);\n return (\n <button\n className={cn(\n \"flex items-center gap-2.5 rounded-md border px-2.5 py-2 text-left text-sm transition-colors\",\n isSelected\n ? \"border-sf-line/50 bg-sf-tint text-sf-default\"\n : \"border-transparent bg-transparent text-sf-default hover:bg-sf-tint/50\"\n )}\n key={opt.label}\n onClick={() => toggleOption(opt.label)}\n type=\"button\"\n >\n <div\n className={cn(\n \"flex size-4 shrink-0 items-center justify-center rounded border transition-colors\",\n isSelected\n ? \"border-sf-brand bg-sf-brand text-sf-inverse\"\n : \"border-sf-line\"\n )}\n >\n {isSelected && <CheckIcon className=\"size-3\" weight=\"bold\" />}\n </div>\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"font-medium\">{opt.label}</span>\n {opt.description && (\n <span className=\"text-sm text-sf-subtle\">\n {opt.description}\n </span>\n )}\n </div>\n </button>\n );\n })}\n </div>\n )}\n\n {/* Custom text input */}\n {isPending && allowCustom && (\n <textarea\n aria-label=\"Custom answer\"\n className=\"min-h-[48px] resize-none rounded-md border border-sf-line/50 bg-sf-base px-2.5 py-1.5 text-sm text-sf-default outline-none placeholder:text-sf-inactive focus:border-sf-ring\"\n onChange={(e) => setCustomText(e.target.value)}\n placeholder=\"Type your answer…\"\n value={customText}\n />\n )}\n\n {/* Submit */}\n {isPending && (\n <div className=\"flex justify-end\">\n <Button\n disabled={!hasAnswer}\n onClick={handleSubmit}\n size=\"sm\"\n type=\"button\"\n variant=\"primary\"\n >\n Submit answer\n </Button>\n </div>\n )}\n\n {/* Answered state */}\n {!isPending && answeredWith && (\n <div className=\"flex items-center gap-2 pl-8 text-sm text-sf-subtle\">\n <CheckIcon className=\"size-3.5 text-sf-success\" weight=\"bold\" />\n <span>Answered: {answeredWith}</span>\n </div>\n )}\n </div>\n );\n}\n\nAiQuestion.displayName = \"AiQuestion\";\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { t as cn } from "./cn-
|
|
3
|
-
import { t as AiStatusBadge } from "./ai-status-badge-
|
|
2
|
+
import { t as cn } from "./cn-CmAOpn49.js";
|
|
3
|
+
import { t as AiStatusBadge } from "./ai-status-badge-BZLczdkI.js";
|
|
4
4
|
import { Suspense, lazy, memo, useCallback, useEffect, useRef, useState } from "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { BrainIcon, CaretDownIcon, CaretRightIcon, CheckIcon, SparkleIcon, SpinnerGapIcon } from "@phosphor-icons/react";
|
|
@@ -43,7 +43,7 @@ function truncateReasoning(text, maxLength = 100) {
|
|
|
43
43
|
}
|
|
44
44
|
/** Extract the first **bold** text from markdown-style reasoning. */
|
|
45
45
|
function extractFirstBoldText(text) {
|
|
46
|
-
return /\*\*([^*]+)
|
|
46
|
+
return /\*\*([^*]+)\*\*/u.exec(text)?.[1]?.trim() ?? null;
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
49
|
* Collapsible reasoning block. Supports three display variants:
|
|
@@ -78,7 +78,7 @@ var AiReasoning = memo(({ part, variant = "default", isStreaming = false, durati
|
|
|
78
78
|
}, [setIsOpen]);
|
|
79
79
|
const displayDuration = durationProp ?? internalDuration;
|
|
80
80
|
const reasoningText = part.text || "";
|
|
81
|
-
const extractedBoldTitle =
|
|
81
|
+
const extractedBoldTitle = isStreaming ? null : extractFirstBoldText(reasoningText);
|
|
82
82
|
const dynamicLabel = extractedBoldTitle ? truncateReasoning(extractedBoldTitle, 40) : null;
|
|
83
83
|
const displayLabel = isStreaming ? streamingLabelProp ?? labelProp ?? "Thinking..." : labelProp ?? dynamicLabel ?? "Reasoning";
|
|
84
84
|
const ActiveIcon = iconProp ?? (isStreaming ? SparkleIcon : BrainIcon);
|
|
@@ -167,6 +167,7 @@ var AiReasoning = memo(({ part, variant = "default", isStreaming = false, durati
|
|
|
167
167
|
children: [/* @__PURE__ */ jsxs(Collapsible.Trigger, {
|
|
168
168
|
render: /* @__PURE__ */ jsx("button", {
|
|
169
169
|
type: "button",
|
|
170
|
+
"aria-label": displayLabel,
|
|
170
171
|
className: "flex w-fit items-center gap-1.5 rounded px-1 py-0.5 text-left transition-colors hover:bg-sf-tint"
|
|
171
172
|
}),
|
|
172
173
|
children: [
|
|
@@ -203,6 +204,7 @@ var AiReasoning = memo(({ part, variant = "default", isStreaming = false, durati
|
|
|
203
204
|
children: [/* @__PURE__ */ jsx(Collapsible.Trigger, {
|
|
204
205
|
render: /* @__PURE__ */ jsx("button", {
|
|
205
206
|
type: "button",
|
|
207
|
+
"aria-label": displayLabel,
|
|
206
208
|
className: "cursor-pointer"
|
|
207
209
|
}),
|
|
208
210
|
children: /* @__PURE__ */ jsx(AiStatusBadge, {
|
|
@@ -248,6 +250,7 @@ var AiReasoning = memo(({ part, variant = "default", isStreaming = false, durati
|
|
|
248
250
|
children: [/* @__PURE__ */ jsxs(Collapsible.Trigger, {
|
|
249
251
|
render: /* @__PURE__ */ jsx("button", {
|
|
250
252
|
type: "button",
|
|
253
|
+
"aria-label": displayLabel,
|
|
251
254
|
className: "flex w-fit items-center gap-1.5 rounded px-1 py-0.5 text-left transition-colors hover:bg-sf-tint"
|
|
252
255
|
}),
|
|
253
256
|
children: [
|
|
@@ -309,6 +312,7 @@ function AiReasoningGroup({ parts, isStreaming = false, totalDuration, defaultEx
|
|
|
309
312
|
children: [/* @__PURE__ */ jsxs(Collapsible.Trigger, {
|
|
310
313
|
render: /* @__PURE__ */ jsx("button", {
|
|
311
314
|
type: "button",
|
|
315
|
+
"aria-label": isStreaming ? "Thinking..." : `${parts.length} reasoning steps`,
|
|
312
316
|
className: "flex w-fit items-center gap-1.5 rounded px-1 py-0.5 text-left transition-colors hover:bg-sf-tint"
|
|
313
317
|
}),
|
|
314
318
|
children: [
|
|
@@ -346,4 +350,4 @@ function AiReasoningGroup({ parts, isStreaming = false, totalDuration, defaultEx
|
|
|
346
350
|
//#endregion
|
|
347
351
|
export { extractFirstBoldText as a, SF_AI_REASONING_VARIANTS as i, AiReasoningGroup as n, formatDuration as o, SF_AI_REASONING_DEFAULT_VARIANTS as r, truncateReasoning as s, AiReasoning as t };
|
|
348
352
|
|
|
349
|
-
//# sourceMappingURL=ai-reasoning-
|
|
353
|
+
//# sourceMappingURL=ai-reasoning-BLfBXx3F.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-reasoning-BLfBXx3F.js","names":[],"sources":["../src/components/ai-reasoning/ai-reasoning.tsx"],"sourcesContent":["\"use client\";\n\nimport { Collapsible as BaseCollapsible } from \"@base-ui/react/collapsible\";\nimport {\n BrainIcon,\n CaretDownIcon,\n CaretRightIcon,\n SparkleIcon,\n SpinnerGapIcon,\n CheckIcon,\n} from \"@phosphor-icons/react\";\nimport type { ComponentProps, ElementType } from \"react\";\nimport {\n memo,\n Suspense,\n lazy,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { AiStatusBadge } from \"../ai-status-badge\";\n\n// Lazy-load Streamdown for markdown rendering in reasoning content.\n// Mirrors the pattern from ai-response.tsx for SSR safety.\ntype StreamdownModule = {\n default: (props: { children: string; className?: string }) => React.ReactNode;\n};\n\nconst Streamdown = lazy((): Promise<StreamdownModule> => {\n if (typeof window === \"undefined\") {\n return Promise.resolve({\n default: ({ children }: { children: string }) => <span>{children}</span>,\n });\n }\n return import(\"streamdown\").then((sd) => ({\n default: (props: { children: string; className?: string }) => (\n <sd.Streamdown {...props} />\n ),\n }));\n});\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_REASONING_VARIANTS = {\n variant: {\n default: {\n classes: \"\",\n description:\n \"Expandable card with collapsible reasoning text and duration\",\n },\n inline: {\n classes: \"\",\n description: \"Compact single-line display with left accent border\",\n },\n minimal: {\n classes: \"\",\n description: \"Pill-shaped status badge\",\n },\n ephemeral: {\n classes: \"\",\n description:\n \"Single-status row that auto-dismisses after streaming ends. Persists when the user expands it.\",\n },\n },\n} as const;\n\nexport const SF_AI_REASONING_DEFAULT_VARIANTS = {\n variant: \"default\",\n} as const;\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Display variant for reasoning rendering. */\nexport type AiReasoningVariant = keyof typeof SF_AI_REASONING_VARIANTS.variant;\n\n/**\n * Structured reasoning part — mirrors the shape of Vercel AI SDK's\n * `ReasoningUIPart` without requiring the `ai` package as a dependency.\n */\nexport interface AiReasoningPart {\n /** The reasoning text content. */\n text: string;\n}\n\nexport type AiReasoningProps = Omit<ComponentProps<\"div\">, \"part\"> & {\n /** Structured reasoning part data. */\n part: AiReasoningPart;\n /** Display variant. @default \"default\" */\n variant?: AiReasoningVariant;\n /** Whether reasoning is currently streaming. */\n isStreaming?: boolean;\n /** Duration in seconds (passed in or self-tracked when streaming). */\n duration?: number;\n /** Default expanded state. @default false */\n defaultExpanded?: boolean;\n /** Controlled open state. */\n open?: boolean;\n /** Called when open state changes. */\n onOpenChange?: (open: boolean) => void;\n /** Delay in ms before auto-closing after streaming ends. Set to 0 to disable. @default 1000 */\n autoCloseDelay?: number;\n /**\n * Custom icon override. Defaults to `SparkleIcon` (streaming) or `BrainIcon` (done).\n * Use to distinguish observation/reflection blocks from standard reasoning.\n */\n icon?: ElementType;\n /**\n * Custom label override. Defaults to `\"Thinking...\"` (streaming) or `\"Reasoning\"` (done).\n * Use to label observational memory blocks: `\"Observing...\"`, `\"Reflecting...\"`, etc.\n */\n label?: string;\n /**\n * Custom streaming label. When provided, used instead of `label` while `isStreaming` is true.\n * Falls back to `label`, then to the default `\"Thinking...\"`.\n */\n streamingLabel?: string;\n /**\n * For `variant=\"ephemeral\"`: ms to keep the completed row visible before\n * fading out. Set to `0` to disable auto-dismiss. @default 800\n */\n dismissDelay?: number;\n /**\n * For `variant=\"ephemeral\"`: when `true`, the row never auto-dismisses.\n * User-expanded rows are pinned automatically.\n */\n persist?: boolean;\n /** Called once the ephemeral row has finished its dismiss animation. */\n onDismiss?: () => void;\n};\n\nexport type AiReasoningGroupProps = Omit<ComponentProps<\"div\">, \"part\"> & {\n /** Array of reasoning parts. */\n parts: AiReasoningPart[];\n /** Whether the last part is currently streaming. */\n isStreaming?: boolean;\n /** Total duration in seconds. */\n totalDuration?: number;\n /** Default expanded state. @default false */\n defaultExpanded?: boolean;\n};\n\n// ─── Utilities ───────────────────────────────────────────────────────────────\n\n/** Format seconds into a human-friendly duration string. */\nexport function formatDuration(seconds: number): string {\n if (seconds < 60) return `${seconds}s`;\n const mins = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`;\n}\n\n/** Truncate reasoning text with an ellipsis. */\nexport function truncateReasoning(text: string, maxLength = 100): string {\n if (text.length <= maxLength) return text;\n return `${text.slice(0, maxLength).trim()}...`;\n}\n\n/** Extract the first **bold** text from markdown-style reasoning. */\nexport function extractFirstBoldText(text: string): string | null {\n const match = /\\*\\*([^*]+)\\*\\*/u.exec(text);\n return match?.[1]?.trim() ?? null;\n}\n\n// ─── AiReasoning ─────────────────────────────────────────────────────────────\n\n/**\n * Collapsible reasoning block. Supports three display variants:\n * - `\"default\"` — expandable card with auto-open on stream start\n * - `\"inline\"` — compact single-line with left accent border\n * - `\"minimal\"` — pill-shaped status badge\n *\n * @example\n * ```tsx\n * <AiReasoning\n * part={{ text: \"First I considered the user's intent...\" }}\n * isStreaming={false}\n * duration={3}\n * />\n * ```\n */\nexport const AiReasoning = memo(\n ({\n part,\n variant = \"default\",\n isStreaming = false,\n duration: durationProp,\n defaultExpanded = false,\n open: openProp,\n onOpenChange,\n autoCloseDelay = 1000,\n icon: iconProp,\n label: labelProp,\n streamingLabel: streamingLabelProp,\n dismissDelay = 800,\n persist = false,\n onDismiss,\n className,\n ...props\n }: AiReasoningProps) => {\n const [internalOpen, setInternalOpen] = useState(defaultExpanded);\n const [hasAutoClosed, setHasAutoClosed] = useState(false);\n const [userOpened, setUserOpened] = useState(false);\n const [internalDuration, setInternalDuration] = useState(0);\n const startTimeRef = useRef<number | null>(null);\n\n const isControlled = openProp !== undefined;\n const isOpen = isControlled ? openProp : internalOpen;\n\n const rawSetIsOpen = isControlled ? onOpenChange : setInternalOpen;\n const setIsOpen = useCallback(\n (value: boolean) => {\n rawSetIsOpen?.(value);\n },\n [rawSetIsOpen]\n );\n\n const handleUserToggle = useCallback(\n (value: boolean) => {\n if (value) setUserOpened(true);\n setIsOpen(value);\n },\n [setIsOpen]\n );\n\n const displayDuration = durationProp ?? internalDuration;\n const reasoningText = part.text || \"\";\n\n // Resolve custom icon/label (with defaults)\n // When not streaming, try to extract a dynamic title from first **bold** text\n const extractedBoldTitle = isStreaming\n ? null\n : extractFirstBoldText(reasoningText);\n const dynamicLabel = extractedBoldTitle\n ? truncateReasoning(extractedBoldTitle, 40)\n : null;\n const displayLabel = isStreaming\n ? (streamingLabelProp ?? labelProp ?? \"Thinking...\")\n : (labelProp ?? dynamicLabel ?? \"Reasoning\");\n const ActiveIcon = iconProp ?? (isStreaming ? SparkleIcon : BrainIcon);\n const StreamIcon = iconProp ?? SparkleIcon;\n const DoneIcon = iconProp ?? BrainIcon;\n\n // Track duration while streaming\n useEffect(() => {\n if (isStreaming) {\n if (startTimeRef.current === null) {\n startTimeRef.current = Date.now();\n }\n const interval = setInterval(() => {\n if (startTimeRef.current) {\n setInternalDuration(\n Math.round((Date.now() - startTimeRef.current) / 1000)\n );\n }\n }, 1000);\n return () => clearInterval(interval);\n }\n if (startTimeRef.current !== null) {\n setInternalDuration(\n Math.round((Date.now() - startTimeRef.current) / 1000)\n );\n startTimeRef.current = null;\n }\n }, [isStreaming]);\n\n // Auto-open on stream start, auto-close when done (unless user opened)\n useEffect(() => {\n if (isStreaming && !isOpen) {\n setUserOpened(false);\n setIsOpen(true);\n return;\n }\n if (\n !isStreaming &&\n isOpen &&\n !defaultExpanded &&\n !hasAutoClosed &&\n !userOpened &&\n autoCloseDelay > 0\n ) {\n const timer = setTimeout(() => {\n setIsOpen(false);\n setHasAutoClosed(true);\n }, autoCloseDelay);\n return () => clearTimeout(timer);\n }\n }, [\n isStreaming,\n isOpen,\n defaultExpanded,\n hasAutoClosed,\n userOpened,\n autoCloseDelay,\n setIsOpen,\n ]);\n\n // ── Ephemeral ────────────────────────────────────────────────────────────\n // Single-status row that auto-dismisses after streaming ends. Pins on\n // user expand or when `persist` is set.\n\n const [ephemeralPhase, setEphemeralPhase] = useState<\n \"live\" | \"fading\" | \"gone\"\n >(\"live\");\n const ephemeralUserExpandedRef = useRef(false);\n\n useEffect(() => {\n if (variant !== \"ephemeral\") return;\n if (ephemeralPhase !== \"live\") return;\n if (isStreaming) return;\n if (persist || ephemeralUserExpandedRef.current) return;\n if (dismissDelay <= 0) return;\n\n const settleTimer = setTimeout(() => {\n setEphemeralPhase(\"fading\");\n }, dismissDelay);\n return () => clearTimeout(settleTimer);\n }, [variant, ephemeralPhase, isStreaming, persist, dismissDelay]);\n\n useEffect(() => {\n if (variant !== \"ephemeral\") return;\n if (ephemeralPhase !== \"fading\") return;\n const fadeTimer = setTimeout(() => {\n setEphemeralPhase(\"gone\");\n onDismiss?.();\n }, 200);\n return () => clearTimeout(fadeTimer);\n }, [variant, ephemeralPhase, onDismiss]);\n\n if (variant === \"ephemeral\") {\n if (ephemeralPhase === \"gone\") return null;\n\n const handleEphemeralToggle = (next: boolean) => {\n if (next) ephemeralUserExpandedRef.current = true;\n setIsOpen(next);\n };\n\n return (\n <BaseCollapsible.Root\n open={isOpen}\n onOpenChange={handleEphemeralToggle}\n >\n <div\n className={cn(\n \"my-0.5 flex w-full max-w-sm flex-col overflow-hidden\",\n \"transition-[opacity,max-height,margin] duration-200 ease-out\",\n ephemeralPhase === \"live\"\n ? \"max-h-40 opacity-100\"\n : \"pointer-events-none my-0 max-h-0 opacity-0\",\n ephemeralPhase === \"live\" && \"animate-in fade-in-0 duration-150\",\n className\n )}\n data-phase={ephemeralPhase}\n {...props}\n >\n <BaseCollapsible.Trigger\n render={\n <button\n type=\"button\"\n aria-label={displayLabel}\n className=\"flex w-fit items-center gap-1.5 rounded px-1 py-0.5 text-left transition-colors hover:bg-sf-tint\"\n />\n }\n >\n {isStreaming ? (\n <SpinnerGapIcon className=\"size-3.5 shrink-0 animate-spin text-sf-subtle\" />\n ) : (\n <CheckIcon className=\"size-3.5 shrink-0 text-sf-success\" />\n )}\n <span className=\"min-w-0 truncate text-sm text-sf-subtle\">\n {displayLabel}\n </span>\n {displayDuration > 0 && !isStreaming ? (\n <span className=\"text-xs tabular-nums text-sf-subtle/60\">\n {formatDuration(displayDuration)}\n </span>\n ) : null}\n <CaretDownIcon\n className={cn(\n \"size-3 shrink-0 text-sf-subtle/60 transition-transform duration-200\",\n !isOpen && \"-rotate-90\"\n )}\n />\n </BaseCollapsible.Trigger>\n\n <BaseCollapsible.Panel className=\"overflow-hidden\">\n <div className=\"mt-1 rounded-lg bg-sf-tint/50 px-3 py-2\">\n <Suspense>\n <Streamdown className=\"text-sf-subtle text-sm [&>*:first-child]:mt-0 [&>*:last-child]:mb-0\">\n {reasoningText || \"*No reasoning content*\"}\n </Streamdown>\n </Suspense>\n </div>\n </BaseCollapsible.Panel>\n </div>\n </BaseCollapsible.Root>\n );\n }\n\n // ── Minimal ──────────────────────────────────────────────────────────────\n\n if (variant === \"minimal\") {\n return (\n <BaseCollapsible.Root open={isOpen} onOpenChange={handleUserToggle}>\n <div className={cn(\"my-1.5\", className)} {...props}>\n <BaseCollapsible.Trigger\n render={\n <button\n type=\"button\"\n aria-label={displayLabel}\n className=\"cursor-pointer\"\n />\n }\n >\n <AiStatusBadge\n className=\"py-1\"\n icon={DoneIcon}\n label={displayLabel}\n status={isStreaming ? \"running\" : \"success\"}\n />\n </BaseCollapsible.Trigger>\n <BaseCollapsible.Panel className=\"overflow-hidden\">\n <div className=\"mx-2 mt-1 rounded-lg bg-sf-tint/50 px-3 py-2\">\n <Suspense>\n <Streamdown className=\"text-sf-subtle text-sm [&>*:first-child]:mt-0 [&>*:last-child]:mb-0\">\n {reasoningText}\n </Streamdown>\n </Suspense>\n </div>\n </BaseCollapsible.Panel>\n </div>\n </BaseCollapsible.Root>\n );\n }\n\n // ── Inline ───────────────────────────────────────────────────────────────\n\n if (variant === \"inline\") {\n return (\n <div\n className={cn(\n \"my-1.5 flex items-center gap-2 border-l-2 border-sf-line py-1 pl-2\",\n \"animate-in fade-in-0 slide-in-from-bottom-1 duration-200\",\n className\n )}\n {...props}\n >\n <ActiveIcon className=\"size-3.5 shrink-0 text-sf-subtle\" />\n <span className=\"text-sm text-sf-subtle\">{displayLabel}</span>\n {isStreaming ? (\n <SpinnerGapIcon className=\"size-3.5 animate-spin text-sf-subtle\" />\n ) : null}\n {!isStreaming && reasoningText ? (\n <span className=\"max-w-[300px] truncate text-xs text-sf-subtle/60\">\n — {truncateReasoning(reasoningText)}\n </span>\n ) : null}\n </div>\n );\n }\n\n // ── Default (compact expandable row) ─────────────────────────────────────\n\n return (\n <BaseCollapsible.Root open={isOpen} onOpenChange={handleUserToggle}>\n <div\n className={cn(\n \"my-0.5 flex w-full flex-col\",\n \"animate-in fade-in-0 duration-150\",\n className\n )}\n {...props}\n >\n {/* Trigger — content-width, left-justified */}\n <BaseCollapsible.Trigger\n render={\n <button\n type=\"button\"\n aria-label={displayLabel}\n className=\"flex w-fit items-center gap-1.5 rounded px-1 py-0.5 text-left transition-colors hover:bg-sf-tint\"\n />\n }\n >\n {isStreaming ? (\n <StreamIcon className=\"size-3.5 shrink-0 animate-pulse text-sf-subtle\" />\n ) : (\n <DoneIcon className=\"size-3.5 shrink-0 text-sf-subtle\" />\n )}\n <span className=\"text-sm text-sf-subtle\">{displayLabel}</span>\n {isStreaming ? (\n <SpinnerGapIcon className=\"size-3 shrink-0 animate-spin text-sf-subtle\" />\n ) : null}\n {displayDuration > 0 && !isStreaming ? (\n <span className=\"text-xs tabular-nums text-sf-subtle/60\">\n {formatDuration(displayDuration)}\n </span>\n ) : null}\n {isOpen ? (\n <CaretDownIcon className=\"size-3 shrink-0 text-sf-subtle/60\" />\n ) : (\n <CaretRightIcon className=\"size-3 shrink-0 text-sf-subtle/60\" />\n )}\n </BaseCollapsible.Trigger>\n\n {/* Detail panel */}\n <BaseCollapsible.Panel className=\"overflow-hidden\">\n <div className=\"mt-1 rounded-lg bg-sf-tint/50 px-3 py-2\">\n <Suspense>\n <Streamdown className=\"text-sf-subtle text-sm [&>*:first-child]:mt-0 [&>*:last-child]:mb-0\">\n {reasoningText || \"*No reasoning content*\"}\n </Streamdown>\n </Suspense>\n </div>\n </BaseCollapsible.Panel>\n </div>\n </BaseCollapsible.Root>\n );\n }\n);\n\nAiReasoning.displayName = \"AiReasoning\";\n\n// ─── AiReasoningGroup ────────────────────────────────────────────────────────\n\n/**\n * Renders multiple reasoning steps. Shows a single `<AiReasoning>` directly\n * when only one part is provided. When multiple parts exist, renders a\n * collapsible group with step labels.\n *\n * @example\n * ```tsx\n * <AiReasoningGroup parts={reasoningParts} isStreaming={false} totalDuration={5} />\n * ```\n */\nexport function AiReasoningGroup({\n parts,\n isStreaming = false,\n totalDuration,\n defaultExpanded = false,\n className,\n ...props\n}: AiReasoningGroupProps) {\n const [isExpanded, setIsExpanded] = useState(defaultExpanded);\n\n // Single part — render directly\n if (parts.length === 1 && parts[0]) {\n const singlePart = parts[0];\n // Strip `part` from div props spread to avoid collision with HTML `part` attribute\n const { part: _part, ...restProps } = props as typeof props & {\n part?: unknown;\n };\n return (\n <AiReasoning\n part={singlePart}\n isStreaming={isStreaming}\n duration={totalDuration}\n className={className}\n {...restProps}\n />\n );\n }\n\n return (\n <BaseCollapsible.Root open={isExpanded} onOpenChange={setIsExpanded}>\n <div\n className={cn(\n \"my-0.5 flex w-full flex-col\",\n \"animate-in fade-in-0 duration-150\",\n className\n )}\n {...props}\n >\n <BaseCollapsible.Trigger\n render={\n <button\n type=\"button\"\n aria-label={\n isStreaming ? \"Thinking...\" : `${parts.length} reasoning steps`\n }\n className=\"flex w-fit items-center gap-1.5 rounded px-1 py-0.5 text-left transition-colors hover:bg-sf-tint\"\n />\n }\n >\n {isStreaming ? (\n <SparkleIcon className=\"size-3.5 shrink-0 animate-pulse text-sf-subtle\" />\n ) : (\n <BrainIcon className=\"size-3.5 shrink-0 text-sf-subtle\" />\n )}\n <span className=\"text-sm text-sf-subtle\">\n {isStreaming ? \"Thinking...\" : `${parts.length} reasoning steps`}\n </span>\n {isStreaming ? (\n <SpinnerGapIcon className=\"size-3 shrink-0 animate-spin text-sf-subtle\" />\n ) : null}\n {totalDuration && totalDuration > 0 && !isStreaming ? (\n <span className=\"text-xs tabular-nums text-sf-subtle/60\">\n {formatDuration(totalDuration)}\n </span>\n ) : null}\n {isExpanded ? (\n <CaretDownIcon className=\"size-3 shrink-0 text-sf-subtle/60\" />\n ) : (\n <CaretRightIcon className=\"size-3 shrink-0 text-sf-subtle/60\" />\n )}\n </BaseCollapsible.Trigger>\n\n <BaseCollapsible.Panel className=\"overflow-hidden\">\n <div className=\"mt-1 space-y-2 rounded-lg bg-sf-tint/50 px-3 py-2\">\n {parts.map((partItem, index) => (\n <div key={index} className=\"text-sm text-sf-subtle\">\n {parts.length > 1 ? (\n <p className=\"mb-0.5 text-[10px] uppercase tracking-wider text-sf-subtle/50\">\n Step {index + 1}\n </p>\n ) : null}\n <Suspense>\n <Streamdown className=\"[&>*:first-child]:mt-0 [&>*:last-child]:mb-0\">\n {partItem.text || \"*No content*\"}\n </Streamdown>\n </Suspense>\n </div>\n ))}\n </div>\n </BaseCollapsible.Panel>\n </div>\n </BaseCollapsible.Root>\n );\n}\n"],"mappings":"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"}
|