@ds-mo/ui 13.13.0 → 13.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.package-ready.json +1 -1
- package/dist/agent-patterns.json +71 -21
- package/dist/agent.json +291 -74
- package/dist/angular/ds-agent-questionnaire.d.ts +19 -0
- package/dist/angular/ds-agent-questionnaire.js +46 -0
- package/dist/angular/ds-agent-response.d.ts +1 -1
- package/dist/angular/ds-agent-response.js +3 -3
- package/dist/angular/ds-agent-source-list.d.ts +9 -2
- package/dist/angular/ds-agent-source-list.js +7 -3
- package/dist/angular/ds-agent-tool-call.d.ts +9 -2
- package/dist/angular/ds-agent-tool-call.js +9 -5
- package/dist/angular/ds-button-filled.d.ts +1 -1
- package/dist/angular/ds-button-filled.js +3 -3
- package/dist/angular/ds-button-unfilled.d.ts +1 -1
- package/dist/angular/ds-button-unfilled.js +3 -3
- package/dist/angular/ds-checkbox.d.ts +1 -1
- package/dist/angular/ds-checkbox.js +3 -3
- package/dist/angular/ds-message-composer.d.ts +1 -1
- package/dist/angular/ds-message-composer.js +3 -3
- package/dist/angular/ds-radio.js +2 -1
- package/dist/angular/ds-table.d.ts +4 -1
- package/dist/angular/ds-table.js +7 -4
- package/dist/angular/ds-tag.d.ts +1 -1
- package/dist/angular/ds-tag.js +3 -3
- package/dist/angular/index.d.ts +1 -1
- package/dist/angular/index.js +1 -0
- package/dist/angular/proxies.d.ts +1 -0
- package/dist/angular/proxies.js +1 -0
- package/dist/components/ds-agent-activity.js +1 -1
- package/dist/components/ds-agent-questionnaire.d.ts +24 -0
- package/dist/components/ds-agent-questionnaire.js +2 -0
- package/dist/components/ds-agent-questionnaire.js.map +1 -0
- package/dist/components/ds-agent-response.js +1 -1
- package/dist/components/ds-agent-response.js.map +1 -1
- package/dist/components/ds-agent-source-list.js +1 -1
- package/dist/components/ds-agent-tool-call.js +1 -1
- package/dist/components/ds-attachment-list.js +1 -1
- package/dist/components/ds-avatar.js +1 -1
- package/dist/components/ds-badge.js +1 -1
- package/dist/components/ds-banner.js +1 -1
- package/dist/components/ds-bar-nav.js +1 -1
- package/dist/components/ds-bar-title.js +1 -1
- package/dist/components/ds-bar-workflow.js +1 -1
- package/dist/components/ds-breadcrumb.js +1 -1
- package/dist/components/ds-button-filled.js +1 -1
- package/dist/components/ds-button-unfilled.js +1 -1
- package/dist/components/ds-card-chart.js +1 -1
- package/dist/components/ds-card-overview.js +1 -1
- package/dist/components/ds-card-overview.js.map +1 -1
- package/dist/components/ds-card-setting.js +1 -1
- package/dist/components/ds-chart-legend.js +1 -1
- package/dist/components/ds-chart-legend.js.map +1 -1
- package/dist/components/ds-chart.js +1 -1
- package/dist/components/ds-chart.js.map +1 -1
- package/dist/components/ds-checkbox.js +1 -1
- package/dist/components/ds-chip.js +1 -1
- package/dist/components/ds-chip.js.map +1 -1
- package/dist/components/ds-code-block.js +1 -1
- package/dist/components/ds-conversation-list-item.js +1 -1
- package/dist/components/ds-conversation-list-item.js.map +1 -1
- package/dist/components/ds-conversation-list-section.js +1 -1
- package/dist/components/ds-conversation-list.js +1 -1
- package/dist/components/ds-divider.js +1 -1
- package/dist/components/ds-empty-state.js +1 -1
- package/dist/components/ds-field.js +1 -1
- package/dist/components/ds-icon.js +1 -1
- package/dist/components/ds-input.js +1 -1
- package/dist/components/ds-input.js.map +1 -1
- package/dist/components/ds-markdown.js +1 -1
- package/dist/components/ds-menu.js +1 -1
- package/dist/components/ds-message-actions.js +1 -1
- package/dist/components/ds-message-bubble.js +1 -1
- package/dist/components/ds-message-bubble.js.map +1 -1
- package/dist/components/ds-message-composer.js +1 -1
- package/dist/components/ds-message-composer.js.map +1 -1
- package/dist/components/ds-message-scroller.js +1 -1
- package/dist/components/ds-message-scroller.js.map +1 -1
- package/dist/components/ds-message.js +1 -1
- package/dist/components/ds-mobile-bar-nav.js +1 -1
- package/dist/components/ds-mobile-header.js +1 -1
- package/dist/components/ds-mobile-section-switcher.js +1 -1
- package/dist/components/ds-mobile-sheet-nav.js +1 -1
- package/dist/components/ds-modal.js +1 -1
- package/dist/components/ds-panel-nav.js +1 -1
- package/dist/components/ds-panel-sub-nav.js +1 -1
- package/dist/components/ds-panel-sub-nav.js.map +1 -1
- package/dist/components/ds-panel-tool-header.js +1 -1
- package/dist/components/ds-panel-tool-search.js +1 -1
- package/dist/components/ds-panel-tools.js +1 -1
- package/dist/components/ds-radio.js +1 -1
- package/dist/components/ds-radio.js.map +1 -1
- package/dist/components/ds-scroll-overlay.js +1 -1
- package/dist/components/ds-select.js +1 -1
- package/dist/components/ds-select.js.map +1 -1
- package/dist/components/ds-shell-app.js +1 -1
- package/dist/components/ds-shell-app.js.map +1 -1
- package/dist/components/ds-shell-page.js +1 -1
- package/dist/components/ds-shell-tools.js +1 -1
- package/dist/components/ds-skeleton.js +1 -1
- package/dist/components/ds-slider.js +1 -1
- package/dist/components/ds-slider.js.map +1 -1
- package/dist/components/ds-swatch-picker.js +1 -1
- package/dist/components/ds-switch.js +1 -1
- package/dist/components/ds-tab-group.js +1 -1
- package/dist/components/ds-table.js +1 -1
- package/dist/components/ds-table.js.map +1 -1
- package/dist/components/ds-tag.js +1 -1
- package/dist/components/ds-text.js +1 -1
- package/dist/components/ds-toast.js +1 -1
- package/dist/components/ds-tooltip-chart.js +1 -1
- package/dist/components/ds-tooltip.js +1 -1
- package/dist/components/ds-typing-indicator.js +1 -1
- package/dist/components/index.d.ts +10 -0
- package/dist/components/{p-PQgDzzn9.js → p-00or0yGw.js} +2 -2
- package/dist/components/p-B2SoinWf.js +2 -0
- package/dist/components/p-B2SoinWf.js.map +1 -0
- package/dist/components/{p-DGkWMhHO.js → p-B69Re7HW.js} +2 -2
- package/dist/components/p-BH_lVRgp.js +2 -0
- package/dist/components/{p-CCYgBUUS.js.map → p-BH_lVRgp.js.map} +1 -1
- package/dist/components/p-BLaqjUWu.js +2 -0
- package/dist/components/{p-Cw1bbiCG.js.map → p-BLaqjUWu.js.map} +1 -1
- package/dist/components/{p-B6z51yBf.js → p-BNkU9dcc.js} +2 -2
- package/dist/components/{p-DBchq8Zw.js → p-BRze4tRe.js} +2 -2
- package/dist/components/p-BtUgncSJ.js +2 -0
- package/dist/components/p-BtUgncSJ.js.map +1 -0
- package/dist/components/p-C891ueIx.js +2 -0
- package/dist/components/p-C891ueIx.js.map +1 -0
- package/dist/components/p-C8U5BsJf.js +2 -0
- package/dist/components/p-C8U5BsJf.js.map +1 -0
- package/dist/components/p-CCkptWPj.js +2 -0
- package/dist/components/p-CCkptWPj.js.map +1 -0
- package/dist/components/p-CKo3OFG1.js +2 -0
- package/dist/components/p-CKo3OFG1.js.map +1 -0
- package/dist/components/p-CXduurfd.js.map +1 -1
- package/dist/components/{p-DLwM1RNL.js → p-CdKz-QT2.js} +2 -2
- package/dist/components/p-CdKz-QT2.js.map +1 -0
- package/dist/components/p-CekGwihQ.js +2 -0
- package/dist/components/{p-CSlTJWFG.js.map → p-CekGwihQ.js.map} +1 -1
- package/dist/components/p-ClHpIZg0.js +2 -0
- package/dist/components/p-ClHpIZg0.js.map +1 -0
- package/dist/components/p-CnUq7E8S.js +2 -0
- package/dist/components/p-CnUq7E8S.js.map +1 -0
- package/dist/components/{p-C9StMCWg.js → p-Cohb8T7G.js} +2 -2
- package/dist/components/p-CqDJRVT8.js +2 -0
- package/dist/components/p-CqDJRVT8.js.map +1 -0
- package/dist/components/p-CsXC1cHI.js +2 -0
- package/dist/components/{p-DGvzGGcu.js.map → p-CsXC1cHI.js.map} +1 -1
- package/dist/components/p-CuwopElg.js.map +1 -1
- package/dist/components/p-D4j0deyd.js +2 -0
- package/dist/components/{p-CzV4gIxd.js.map → p-D4j0deyd.js.map} +1 -1
- package/dist/components/p-D5aUkdTw.js +2 -0
- package/dist/components/p-D5aUkdTw.js.map +1 -0
- package/dist/components/p-DQXzTV8N.js +2 -0
- package/dist/components/p-DQXzTV8N.js.map +1 -0
- package/dist/components/p-DStd98dM.js +2 -0
- package/dist/components/p-DStd98dM.js.map +1 -0
- package/dist/components/p-DWNhyLp2.js +2 -0
- package/dist/components/{p-B1JB0Zn-.js.map → p-DWNhyLp2.js.map} +1 -1
- package/dist/components/p-DWjE0VNn.js +2 -0
- package/dist/components/p-DWjE0VNn.js.map +1 -0
- package/dist/components/{p-BFMV9TJO.js → p-DgIRyJoc.js} +2 -2
- package/dist/components/{p-BNiIyZCn.js → p-Dhx_3_tf.js} +2 -2
- package/dist/components/p-Dhx_3_tf.js.map +1 -0
- package/dist/components/{p-CE82aQZr.js → p-DyVAWGL9.js} +2 -2
- package/dist/components/p-GSnB-sa7.js +2 -0
- package/dist/components/p-GSnB-sa7.js.map +1 -0
- package/dist/components/p-GWUTrIlk.js +2 -0
- package/dist/components/p-GWUTrIlk.js.map +1 -0
- package/dist/components/p-IhToA4m4.js +2 -0
- package/dist/components/{p-cPh32CFB.js.map → p-IhToA4m4.js.map} +1 -1
- package/dist/components/p-NQOI5gN1.js +2 -0
- package/dist/components/p-NQOI5gN1.js.map +1 -0
- package/dist/components/p-QDcUAz9m.js +2 -0
- package/dist/components/{p-BNHPCCw8.js.map → p-QDcUAz9m.js.map} +1 -1
- package/dist/components/p-Qf-os3lG.js +2 -0
- package/dist/components/p-Qf-os3lG.js.map +1 -0
- package/dist/components/{p-DBJJiSP0.js → p-chA2WA5x.js} +2 -2
- package/dist/components/{p-DwKC_9u2.js → p-dEouiXJ8.js} +2 -2
- package/dist/components/{p-BAGTb6cZ.js → p-fKwbYrhi.js} +2 -2
- package/dist/docs/components.json +942 -20
- package/dist/lib/components/ButtonFilled/ButtonFilled.d.ts +4 -0
- package/dist/lib/utils/control-text.d.ts +2 -0
- package/dist/lib/utils/index.d.ts +1 -1
- package/dist/lib/utils/index.js.map +2 -2
- package/dist/mcp-data/registry/agent-activity.json +2 -2
- package/dist/mcp-data/registry/agent-questionnaire.json +273 -0
- package/dist/mcp-data/registry/agent-response.json +33 -12
- package/dist/mcp-data/registry/agent-source-list.json +34 -14
- package/dist/mcp-data/registry/agent-tool-call.json +60 -19
- package/dist/mcp-data/registry/attachment-list.json +2 -2
- package/dist/mcp-data/registry/avatar.json +2 -2
- package/dist/mcp-data/registry/badge.json +2 -2
- package/dist/mcp-data/registry/banner.json +2 -2
- package/dist/mcp-data/registry/bar-nav.json +3 -3
- package/dist/mcp-data/registry/bar-title.json +3 -3
- package/dist/mcp-data/registry/bar-workflow.json +2 -2
- package/dist/mcp-data/registry/breadcrumb.json +3 -3
- package/dist/mcp-data/registry/button-filled.json +22 -4
- package/dist/mcp-data/registry/button-unfilled.json +28 -8
- package/dist/mcp-data/registry/card-chart.json +2 -2
- package/dist/mcp-data/registry/card-overview.json +2 -2
- package/dist/mcp-data/registry/card-setting.json +2 -2
- package/dist/mcp-data/registry/chart-legend.json +3 -3
- package/dist/mcp-data/registry/chart.json +3 -3
- package/dist/mcp-data/registry/checkbox.json +27 -10
- package/dist/mcp-data/registry/chip.json +3 -3
- package/dist/mcp-data/registry/code-block.json +15 -7
- package/dist/mcp-data/registry/conversation-list-item.json +3 -3
- package/dist/mcp-data/registry/conversation-list-section.json +2 -2
- package/dist/mcp-data/registry/conversation-list.json +2 -2
- package/dist/mcp-data/registry/divider.json +2 -2
- package/dist/mcp-data/registry/empty-state.json +2 -2
- package/dist/mcp-data/registry/field.json +2 -2
- package/dist/mcp-data/registry/icon.json +3 -3
- package/dist/mcp-data/registry/input.json +2 -2
- package/dist/mcp-data/registry/loader.json +2 -2
- package/dist/mcp-data/registry/markdown.json +2 -2
- package/dist/mcp-data/registry/menu.json +3 -3
- package/dist/mcp-data/registry/message-actions.json +2 -2
- package/dist/mcp-data/registry/message-bubble.json +3 -3
- package/dist/mcp-data/registry/message-composer.json +31 -9
- package/dist/mcp-data/registry/message-scroller.json +18 -10
- package/dist/mcp-data/registry/message.json +2 -2
- package/dist/mcp-data/registry/mobile-bar-nav.json +2 -2
- package/dist/mcp-data/registry/mobile-header.json +2 -2
- package/dist/mcp-data/registry/mobile-section-switcher.json +2 -2
- package/dist/mcp-data/registry/mobile-sheet-nav.json +2 -2
- package/dist/mcp-data/registry/modal.json +2 -2
- package/dist/mcp-data/registry/panel-nav.json +3 -3
- package/dist/mcp-data/registry/panel-sub-nav.json +2 -2
- package/dist/mcp-data/registry/panel-tool-header.json +2 -2
- package/dist/mcp-data/registry/panel-tool-search.json +2 -2
- package/dist/mcp-data/registry/panel-tools.json +3 -3
- package/dist/mcp-data/registry/radio.json +25 -12
- package/dist/mcp-data/registry/registry.json +295 -75
- package/dist/mcp-data/registry/scroll-overlay.json +2 -2
- package/dist/mcp-data/registry/select.json +3 -3
- package/dist/mcp-data/registry/shell-app.json +3 -3
- package/dist/mcp-data/registry/shell-page.json +2 -2
- package/dist/mcp-data/registry/shell-tools.json +2 -2
- package/dist/mcp-data/registry/skeleton.json +2 -2
- package/dist/mcp-data/registry/slider.json +3 -3
- package/dist/mcp-data/registry/swatch-picker.json +3 -3
- package/dist/mcp-data/registry/switch.json +3 -3
- package/dist/mcp-data/registry/tab-group.json +2 -2
- package/dist/mcp-data/registry/table.json +122 -21
- package/dist/mcp-data/registry/tag.json +24 -6
- package/dist/mcp-data/registry/text.json +3 -3
- package/dist/mcp-data/registry/toast.json +2 -2
- package/dist/mcp-data/registry/tooltip-chart.json +6 -4
- package/dist/mcp-data/registry/tooltip.json +2 -2
- package/dist/mcp-data/registry/typing-indicator.json +2 -2
- package/dist/react/components.d.ts +1 -0
- package/dist/react/components.js +1 -0
- package/dist/react/ds-agent-questionnaire.d.ts +13 -0
- package/dist/react/ds-agent-questionnaire.js +15 -0
- package/dist/react/ds-agent-source-list.d.ts +7 -2
- package/dist/react/ds-agent-source-list.js +1 -1
- package/dist/react/ds-agent-tool-call.d.ts +7 -2
- package/dist/react/ds-agent-tool-call.js +1 -1
- package/dist/react/ds-table.d.ts +2 -1
- package/dist/react/ds-table.js +1 -0
- package/dist/styles/prose.css +21 -4
- package/dist/styles/table.css +244 -26
- package/dist/types/components/AgentQuestionnaire/AgentQuestionnaire.d.ts +49 -0
- package/dist/types/components/AgentQuestionnaire/agent-questionnaire-model.d.ts +13 -0
- package/dist/types/components/AgentResponse/AgentResponse.d.ts +3 -1
- package/dist/types/components/AgentSourceList/AgentSourceList.d.ts +5 -0
- package/dist/types/components/AgentToolCall/AgentToolCall.d.ts +21 -0
- package/dist/types/components/ButtonFilled/ButtonFilled.d.ts +4 -0
- package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +11 -1
- package/dist/types/components/Checkbox/Checkbox.d.ts +3 -0
- package/dist/types/components/MessageComposer/MessageComposer.d.ts +3 -0
- package/dist/types/components/MessageScroller/MessageScroller.d.ts +21 -1
- package/dist/types/components/Radio/Radio.d.ts +4 -0
- package/dist/types/components/Table/Table.d.ts +31 -23
- package/dist/types/components/Table/index.d.ts +1 -1
- package/dist/types/components/Table/table-cell-model.d.ts +44 -0
- package/dist/types/components/Table/table-layout-controller.d.ts +65 -0
- package/dist/types/components/Table/table-load-controller.d.ts +49 -0
- package/dist/types/components/Table/table-model.d.ts +25 -0
- package/dist/types/components/Table/table-render-model.d.ts +41 -0
- package/dist/types/components/Table/table-types.d.ts +23 -2
- package/dist/types/components/Tag/Tag.d.ts +3 -0
- package/dist/types/components/conversation-types.d.ts +51 -2
- package/dist/types/components.d.ts +231 -10
- package/dist/types/utils/control-text.d.ts +2 -0
- package/dist/types/utils/index.d.ts +1 -1
- package/package.json +7 -5
- package/dist/components/p-B1JB0Zn-.js +0 -2
- package/dist/components/p-B2t8alvH.js +0 -2
- package/dist/components/p-B2t8alvH.js.map +0 -1
- package/dist/components/p-BEEYhbIb.js +0 -2
- package/dist/components/p-BEEYhbIb.js.map +0 -1
- package/dist/components/p-BNHPCCw8.js +0 -2
- package/dist/components/p-BNiIyZCn.js.map +0 -1
- package/dist/components/p-BUZLhvs1.js +0 -2
- package/dist/components/p-BUZLhvs1.js.map +0 -1
- package/dist/components/p-BgaF83uh.js +0 -2
- package/dist/components/p-BgaF83uh.js.map +0 -1
- package/dist/components/p-Br0fwWUG.js +0 -2
- package/dist/components/p-Br0fwWUG.js.map +0 -1
- package/dist/components/p-BydCwx7x.js +0 -2
- package/dist/components/p-BydCwx7x.js.map +0 -1
- package/dist/components/p-C3Z01Glr.js +0 -2
- package/dist/components/p-C3Z01Glr.js.map +0 -1
- package/dist/components/p-CCYgBUUS.js +0 -2
- package/dist/components/p-CSlTJWFG.js +0 -2
- package/dist/components/p-CdFnvBem.js +0 -2
- package/dist/components/p-CdFnvBem.js.map +0 -1
- package/dist/components/p-Ch5yT3UA.js +0 -2
- package/dist/components/p-Ch5yT3UA.js.map +0 -1
- package/dist/components/p-Cw1bbiCG.js +0 -2
- package/dist/components/p-CzV4gIxd.js +0 -2
- package/dist/components/p-D-F8eyXy.js +0 -2
- package/dist/components/p-D-F8eyXy.js.map +0 -1
- package/dist/components/p-D6g070eY.js +0 -2
- package/dist/components/p-D6g070eY.js.map +0 -1
- package/dist/components/p-DGvzGGcu.js +0 -2
- package/dist/components/p-DLwM1RNL.js.map +0 -1
- package/dist/components/p-DmblUQ4D.js +0 -2
- package/dist/components/p-DmblUQ4D.js.map +0 -1
- package/dist/components/p-Doz2uwRv.js +0 -2
- package/dist/components/p-Doz2uwRv.js.map +0 -1
- package/dist/components/p-DumWT7NN.js +0 -2
- package/dist/components/p-DumWT7NN.js.map +0 -1
- package/dist/components/p-bLCbOPYa.js +0 -2
- package/dist/components/p-bLCbOPYa.js.map +0 -1
- package/dist/components/p-cPh32CFB.js +0 -2
- /package/dist/components/{p-PQgDzzn9.js.map → p-00or0yGw.js.map} +0 -0
- /package/dist/components/{p-DGkWMhHO.js.map → p-B69Re7HW.js.map} +0 -0
- /package/dist/components/{p-B6z51yBf.js.map → p-BNkU9dcc.js.map} +0 -0
- /package/dist/components/{p-DBchq8Zw.js.map → p-BRze4tRe.js.map} +0 -0
- /package/dist/components/{p-C9StMCWg.js.map → p-Cohb8T7G.js.map} +0 -0
- /package/dist/components/{p-BFMV9TJO.js.map → p-DgIRyJoc.js.map} +0 -0
- /package/dist/components/{p-CE82aQZr.js.map → p-DyVAWGL9.js.map} +0 -0
- /package/dist/components/{p-DBJJiSP0.js.map → p-chA2WA5x.js.map} +0 -0
- /package/dist/components/{p-DwKC_9u2.js.map → p-dEouiXJ8.js.map} +0 -0
- /package/dist/components/{p-BAGTb6cZ.js.map → p-fKwbYrhi.js.map} +0 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "agent-questionnaire",
|
|
4
|
+
"title": "AgentQuestionnaire",
|
|
5
|
+
"description": "Temporary multi-step work surface for provider-neutral agent clarification questions and durable read-only answer records.",
|
|
6
|
+
"type": "registry:ui",
|
|
7
|
+
"meta": {
|
|
8
|
+
"library": "@ds-mo/ui",
|
|
9
|
+
"distribution": "npm",
|
|
10
|
+
"storybook": "https://zainadeel.github.io/compomo/?path=/story/agent-questionnaire",
|
|
11
|
+
"source": "src/wc/components/AgentQuestionnaire/AgentQuestionnaire.tsx",
|
|
12
|
+
"intentStatus": "complete",
|
|
13
|
+
"intent": {
|
|
14
|
+
"audience": "specialized",
|
|
15
|
+
"status": "experimental",
|
|
16
|
+
"summary": "Temporary multi-step work surface for provider-neutral agent clarification questions and durable read-only answer records.",
|
|
17
|
+
"useWhen": [
|
|
18
|
+
"An agent turn pauses for one or more structured single-choice, multiple-choice, or free-text answers."
|
|
19
|
+
],
|
|
20
|
+
"avoidWhen": [
|
|
21
|
+
"The interaction is a conventional application form, a tool authorization policy, or an application-owned approval with consequences beyond collecting answers."
|
|
22
|
+
],
|
|
23
|
+
"commonlyComposedWith": [
|
|
24
|
+
"component:ds-message-scroller",
|
|
25
|
+
"component:ds-message-composer",
|
|
26
|
+
"component:ds-agent-response",
|
|
27
|
+
"component:ds-radio",
|
|
28
|
+
"component:ds-checkbox",
|
|
29
|
+
"component:ds-button-filled",
|
|
30
|
+
"component:ds-button-unfilled"
|
|
31
|
+
],
|
|
32
|
+
"patterns": [
|
|
33
|
+
"pattern:agent-chat"
|
|
34
|
+
],
|
|
35
|
+
"accessibility": [
|
|
36
|
+
"Radio and checkbox primitives own choice semantics, target density, keyboard interaction, and selected or disabled presentation; progress, validation relationships, static answered summaries, and every action remain available without relying on color or visual position.",
|
|
37
|
+
"The component never takes focus when it mounts; the application calls setFocus only when shifting focus is appropriate.",
|
|
38
|
+
"Choice rows use large Radio and Checkbox targets, while every navigation action uses a small Button primitive and Cancel is an icon-only Cross with localized tooltip and accessible name.",
|
|
39
|
+
"Selection primitives preserve focus, selected, invalid, and disabled distinctions in forced colors."
|
|
40
|
+
],
|
|
41
|
+
"states": [
|
|
42
|
+
"The component owns only the current step, validation, and unsaved in-progress draft; the application owns the request, submission, transport, resume operation, persistence, and transcript replacement.",
|
|
43
|
+
"Preparing communicates that questions are being assembled, submitting locks editing without clearing the draft, error retains it with application feedback, and answered is a quiet noninteractive record.",
|
|
44
|
+
"A changed request identifier resets to the first question and seeds a fresh local draft from the supplied answers.",
|
|
45
|
+
"Questionnaire selection primitives are isolated from ancestor forms; only dsAnswer emits the normalized ordered answer collection."
|
|
46
|
+
],
|
|
47
|
+
"responsiveBehavior": [
|
|
48
|
+
"Descriptive choices remain full-row targets, while actions collapse into a single-column layout at narrow widths."
|
|
49
|
+
],
|
|
50
|
+
"references": [
|
|
51
|
+
{
|
|
52
|
+
"label": "Questionnaire state stories",
|
|
53
|
+
"path": "src/wc/components/AgentQuestionnaire/AgentQuestionnaire.stories.ts"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"label": "Agent chat composition",
|
|
57
|
+
"path": "agent/patterns/agent-chat/pattern.agent.json"
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
"api": {
|
|
62
|
+
"props": {
|
|
63
|
+
"allowCancel": {
|
|
64
|
+
"type": "boolean",
|
|
65
|
+
"resolvedType": "boolean",
|
|
66
|
+
"attribute": "allow-cancel",
|
|
67
|
+
"default": "false",
|
|
68
|
+
"required": false,
|
|
69
|
+
"mutable": false
|
|
70
|
+
},
|
|
71
|
+
"answers": {
|
|
72
|
+
"type": "AgentQuestionAnswer[]",
|
|
73
|
+
"resolvedType": "AgentQuestionAnswer[]",
|
|
74
|
+
"default": "[]",
|
|
75
|
+
"required": false,
|
|
76
|
+
"mutable": false
|
|
77
|
+
},
|
|
78
|
+
"errorMessage": {
|
|
79
|
+
"type": "string",
|
|
80
|
+
"resolvedType": "string | undefined",
|
|
81
|
+
"attribute": "error-message",
|
|
82
|
+
"required": false,
|
|
83
|
+
"mutable": false
|
|
84
|
+
},
|
|
85
|
+
"labels": {
|
|
86
|
+
"type": "Partial<AgentQuestionnaireLabels>",
|
|
87
|
+
"resolvedType": "AgentQuestionnaireLabels | undefined",
|
|
88
|
+
"required": false,
|
|
89
|
+
"mutable": false
|
|
90
|
+
},
|
|
91
|
+
"questions": {
|
|
92
|
+
"type": "AgentQuestion[]",
|
|
93
|
+
"resolvedType": "AgentQuestion[]",
|
|
94
|
+
"required": true,
|
|
95
|
+
"mutable": false
|
|
96
|
+
},
|
|
97
|
+
"requestId": {
|
|
98
|
+
"type": "string",
|
|
99
|
+
"resolvedType": "string",
|
|
100
|
+
"attribute": "request-id",
|
|
101
|
+
"required": true,
|
|
102
|
+
"mutable": false
|
|
103
|
+
},
|
|
104
|
+
"status": {
|
|
105
|
+
"type": "AgentQuestionnaireStatus",
|
|
106
|
+
"resolvedType": "\"answered\" | \"error\" | \"preparing\" | \"ready\" | \"submitting\"",
|
|
107
|
+
"attribute": "status",
|
|
108
|
+
"default": "'ready'",
|
|
109
|
+
"required": false,
|
|
110
|
+
"mutable": false
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"events": [
|
|
114
|
+
{
|
|
115
|
+
"name": "dsAnswer",
|
|
116
|
+
"detail": "AgentQuestionnaireAnswerEventDetail",
|
|
117
|
+
"bubbles": true,
|
|
118
|
+
"cancelable": true,
|
|
119
|
+
"composed": true
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"name": "dsCancel",
|
|
123
|
+
"detail": "AgentQuestionnaireCancelEventDetail",
|
|
124
|
+
"bubbles": true,
|
|
125
|
+
"cancelable": true,
|
|
126
|
+
"composed": true
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
"methods": [
|
|
130
|
+
{
|
|
131
|
+
"name": "setFocus",
|
|
132
|
+
"signature": "setFocus() => Promise<void>"
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
"slots": []
|
|
136
|
+
},
|
|
137
|
+
"props": {
|
|
138
|
+
"allowCancel": {
|
|
139
|
+
"type": "boolean",
|
|
140
|
+
"resolvedType": "boolean",
|
|
141
|
+
"attribute": "allow-cancel",
|
|
142
|
+
"default": "false",
|
|
143
|
+
"required": false,
|
|
144
|
+
"mutable": false
|
|
145
|
+
},
|
|
146
|
+
"answers": {
|
|
147
|
+
"type": "AgentQuestionAnswer[]",
|
|
148
|
+
"resolvedType": "AgentQuestionAnswer[]",
|
|
149
|
+
"default": "[]",
|
|
150
|
+
"required": false,
|
|
151
|
+
"mutable": false
|
|
152
|
+
},
|
|
153
|
+
"errorMessage": {
|
|
154
|
+
"type": "string",
|
|
155
|
+
"resolvedType": "string | undefined",
|
|
156
|
+
"attribute": "error-message",
|
|
157
|
+
"required": false,
|
|
158
|
+
"mutable": false
|
|
159
|
+
},
|
|
160
|
+
"labels": {
|
|
161
|
+
"type": "Partial<AgentQuestionnaireLabels>",
|
|
162
|
+
"resolvedType": "AgentQuestionnaireLabels | undefined",
|
|
163
|
+
"required": false,
|
|
164
|
+
"mutable": false
|
|
165
|
+
},
|
|
166
|
+
"questions": {
|
|
167
|
+
"type": "AgentQuestion[]",
|
|
168
|
+
"resolvedType": "AgentQuestion[]",
|
|
169
|
+
"required": true,
|
|
170
|
+
"mutable": false
|
|
171
|
+
},
|
|
172
|
+
"requestId": {
|
|
173
|
+
"type": "string",
|
|
174
|
+
"resolvedType": "string",
|
|
175
|
+
"attribute": "request-id",
|
|
176
|
+
"required": true,
|
|
177
|
+
"mutable": false
|
|
178
|
+
},
|
|
179
|
+
"status": {
|
|
180
|
+
"type": "AgentQuestionnaireStatus",
|
|
181
|
+
"resolvedType": "\"answered\" | \"error\" | \"preparing\" | \"ready\" | \"submitting\"",
|
|
182
|
+
"attribute": "status",
|
|
183
|
+
"default": "'ready'",
|
|
184
|
+
"required": false,
|
|
185
|
+
"mutable": false
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
"events": [
|
|
189
|
+
{
|
|
190
|
+
"name": "dsAnswer",
|
|
191
|
+
"detail": "AgentQuestionnaireAnswerEventDetail",
|
|
192
|
+
"bubbles": true,
|
|
193
|
+
"cancelable": true,
|
|
194
|
+
"composed": true
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"name": "dsCancel",
|
|
198
|
+
"detail": "AgentQuestionnaireCancelEventDetail",
|
|
199
|
+
"bubbles": true,
|
|
200
|
+
"cancelable": true,
|
|
201
|
+
"composed": true
|
|
202
|
+
}
|
|
203
|
+
],
|
|
204
|
+
"methods": [
|
|
205
|
+
{
|
|
206
|
+
"name": "setFocus",
|
|
207
|
+
"signature": "setFocus() => Promise<void>"
|
|
208
|
+
}
|
|
209
|
+
],
|
|
210
|
+
"slots": [],
|
|
211
|
+
"exports": {
|
|
212
|
+
"customElement": "ds-agent-questionnaire",
|
|
213
|
+
"react": "DsAgentQuestionnaire",
|
|
214
|
+
"angular": "DsAgentQuestionnaire"
|
|
215
|
+
},
|
|
216
|
+
"consumption": {
|
|
217
|
+
"install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
|
|
218
|
+
"cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
|
|
219
|
+
"customElements": {
|
|
220
|
+
"import": "import '@ds-mo/ui/dist/components/ds-agent-questionnaire.js';",
|
|
221
|
+
"example": "<ds-agent-questionnaire></ds-agent-questionnaire>"
|
|
222
|
+
},
|
|
223
|
+
"react": {
|
|
224
|
+
"import": "import { DsAgentQuestionnaire } from '@ds-mo/ui/react';",
|
|
225
|
+
"example": "<DsAgentQuestionnaire />"
|
|
226
|
+
},
|
|
227
|
+
"angular": {
|
|
228
|
+
"import": "import { DsAgentQuestionnaire } from '@ds-mo/ui/angular/ds-agent-questionnaire';",
|
|
229
|
+
"example": "<ds-agent-questionnaire></ds-agent-questionnaire>"
|
|
230
|
+
},
|
|
231
|
+
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: answers, labels, questions.",
|
|
232
|
+
"peerDependencies": {
|
|
233
|
+
"required": [
|
|
234
|
+
"@ds-mo/tokens ^6.2.1",
|
|
235
|
+
"@ds-mo/icons ^6.6.0"
|
|
236
|
+
],
|
|
237
|
+
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
"dependencies": [
|
|
242
|
+
"@ds-mo/ui",
|
|
243
|
+
"@ds-mo/tokens",
|
|
244
|
+
"@ds-mo/icons"
|
|
245
|
+
],
|
|
246
|
+
"registryDependencies": [
|
|
247
|
+
"button-filled",
|
|
248
|
+
"button-unfilled",
|
|
249
|
+
"checkbox",
|
|
250
|
+
"icon",
|
|
251
|
+
"loader",
|
|
252
|
+
"radio",
|
|
253
|
+
"text",
|
|
254
|
+
"tooltip"
|
|
255
|
+
],
|
|
256
|
+
"files": [
|
|
257
|
+
{
|
|
258
|
+
"path": "src/wc/components/AgentQuestionnaire/AgentQuestionnaire.css",
|
|
259
|
+
"content": "@import '../../utils/forced-colors.css';\n@import '../../utils/visually-hidden.css';\n\n:host {\n display: block;\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n -webkit-user-select: none;\n user-select: none;\n}\n\n.questionnaire {\n display: grid;\n gap: var(--dimension-space-150);\n width: 100%;\n padding: var(--dimension-space-200);\n border-radius: var(--dimension-radius-125);\n background: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-md);\n box-sizing: border-box;\n}\n\n.questionnaire--answered {\n gap: var(--dimension-space-100);\n padding: var(--dimension-space-150);\n background: var(--color-background-secondary);\n box-shadow: none;\n}\n\n.questionnaire--preparing {\n align-items: center;\n grid-template-columns: auto minmax(0, 1fr);\n}\n\n.questionnaire__header,\n.questionnaire__actions,\n.questionnaire__actions-leading,\n.questionnaire__error,\n.questionnaire__submission-error {\n display: flex;\n align-items: center;\n}\n\n.questionnaire__header,\n.questionnaire__actions {\n justify-content: space-between;\n gap: var(--dimension-space-100);\n}\n\n.questionnaire__body,\n.questionnaire__prompt,\n.questionnaire__choices,\n.questionnaire__single-choice,\n.questionnaire__multiple-choice,\n.questionnaire__other-choice,\n.questionnaire__summary,\n.questionnaire__summary li {\n display: grid;\n}\n\n.questionnaire__body,\n.questionnaire__prompt,\n.questionnaire__choices,\n.questionnaire__single-choice,\n.questionnaire__multiple-choice,\n.questionnaire__other-choice {\n gap: var(--dimension-space-100);\n}\n\n.questionnaire__choices {\n min-width: 0;\n margin: 0;\n padding: 0;\n border: 0;\n}\n\nds-radio,\nds-checkbox {\n width: 100%;\n min-width: 0;\n}\n\n.questionnaire__other-input,\n.questionnaire__text-input {\n width: 100%;\n padding: var(--dimension-space-100);\n border: var(--dimension-stroke-width-012) solid var(--color-border-secondary);\n border-radius: var(--dimension-radius-050);\n outline: none;\n background: var(--color-background-primary);\n color: var(--color-foreground-primary);\n font-family: var(--typography-font-family-ui);\n font-size: var(--typography-fontsize-md);\n font-weight: var(--typography-weight-regular);\n line-height: var(--typography-lineheight-md);\n letter-spacing: var(--typography-letterspacing-negative-half);\n box-sizing: border-box;\n -webkit-user-select: text;\n user-select: text;\n}\n\n.questionnaire__other-input {\n width: calc(100% - var(--dimension-size-500));\n margin-inline-start: var(--dimension-size-500);\n}\n\n.questionnaire__text-input {\n min-height: calc(var(--typography-lineheight-md) * 4 + var(--dimension-space-200));\n resize: vertical;\n}\n\n.questionnaire__other-input:focus,\n.questionnaire__text-input:focus {\n border-color: var(--color-border-bold-brand);\n box-shadow: inset 0 0 0 var(--dimension-stroke-width-018)\n var(--color-border-bold-brand);\n}\n\n.questionnaire__other-input[aria-invalid='true'],\n.questionnaire__text-input[aria-invalid='true'] {\n border-color: var(--color-border-bold-negative);\n}\n\n.questionnaire__error,\n.questionnaire__submission-error {\n gap: var(--dimension-space-050);\n color: var(--color-foreground-bold-negative);\n}\n\n.questionnaire__submission-error {\n padding: var(--dimension-space-075);\n border-radius: var(--dimension-radius-050);\n background: var(--color-background-faint-negative);\n}\n\n.questionnaire__actions-leading {\n flex-wrap: wrap;\n gap: var(--dimension-space-075);\n}\n\n.questionnaire__action-item {\n width: fit-content;\n max-width: 100%;\n}\n\n.questionnaire textarea:disabled {\n color: var(--color-foreground-tertiary);\n cursor: default;\n opacity: 1;\n}\n\n.questionnaire__summary {\n gap: var(--dimension-space-100);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.questionnaire__summary li {\n gap: var(--dimension-space-025);\n}\n\n@media (max-width: 480px) {\n .questionnaire {\n padding: var(--dimension-space-150);\n }\n\n .questionnaire__actions {\n align-items: stretch;\n flex-direction: column;\n }\n\n .questionnaire__actions-leading {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n width: 100%;\n }\n\n .questionnaire__action-item,\n .questionnaire__action-item--primary {\n width: 100%;\n }\n}\n\n@media (forced-colors: active) {\n .questionnaire {\n border: var(--dimension-stroke-width-012) solid var(--ds-forced-color-content);\n box-shadow: none;\n }\n\n .questionnaire__other-input[aria-invalid='true'],\n .questionnaire__text-input[aria-invalid='true'] {\n outline: var(--dimension-stroke-width-025) dashed var(--ds-forced-color-content);\n }\n\n .questionnaire__submission-error {\n border: var(--dimension-stroke-width-012) solid var(--ds-forced-color-content);\n background: var(--ds-forced-color-surface);\n }\n\n .questionnaire input:disabled,\n .questionnaire textarea:disabled {\n color: var(--ds-forced-color-disabled);\n }\n}\n",
|
|
260
|
+
"type": "registry:ui"
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"path": "src/wc/components/AgentQuestionnaire/AgentQuestionnaire.tsx",
|
|
264
|
+
"content": "import {\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Host,\n Method,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\nimport type {\n AgentQuestion,\n AgentQuestionAnswer,\n AgentQuestionnaireAnswerEventDetail,\n AgentQuestionnaireCancelEventDetail,\n AgentQuestionnaireLabels,\n AgentQuestionnaireStatus,\n} from '../conversation-types';\nimport {\n createQuestionnaireDrafts,\n formatQuestionAnswer,\n normalizeQuestionAnswer,\n validateQuestionDraft,\n} from './agent-questionnaire-model';\nimport type {\n AgentQuestionDraft,\n AgentQuestionDrafts,\n} from './agent-questionnaire-model';\n\nconst DEFAULT_LABELS: AgentQuestionnaireLabels = {\n progress: 'Question {current} of {total}',\n previous: 'Previous',\n next: 'Next',\n answer: 'Answer',\n skip: 'Skip',\n cancel: 'Cancel',\n other: 'Other',\n otherPlaceholder: 'Enter another answer',\n preparing: 'Preparing questions…',\n};\n\nlet questionnaireId = 0;\n\n@Component({\n tag: 'ds-agent-questionnaire',\n styleUrl: 'AgentQuestionnaire.css',\n scoped: true,\n})\nexport class AgentQuestionnaire {\n @Element() el!: HTMLElement;\n\n @Prop() requestId!: string;\n @Prop() questions!: AgentQuestion[];\n @Prop() answers: AgentQuestionAnswer[] = [];\n @Prop() status: AgentQuestionnaireStatus = 'ready';\n @Prop() errorMessage?: string;\n @Prop() allowCancel: boolean = false;\n @Prop() labels?: Partial<AgentQuestionnaireLabels>;\n\n @Event() dsAnswer!: EventEmitter<AgentQuestionnaireAnswerEventDetail>;\n @Event() dsCancel!: EventEmitter<AgentQuestionnaireCancelEventDetail>;\n\n @State() private currentStep = 0;\n @State() private drafts: AgentQuestionDrafts = {};\n @State() private validation: Record<string, string> = {};\n\n private readonly instanceId = ++questionnaireId;\n private readonly otherValue = `__ds-agent-questionnaire-other-${this.instanceId}`;\n private answerPending = false;\n private resetScheduled = false;\n private draftRequestId?: string;\n private answersSnapshot: AgentQuestionAnswer[] = [];\n private waitingForRequestAnswers = false;\n\n componentWillLoad() {\n this.draftRequestId = this.requestId;\n this.answersSnapshot = this.answers;\n this.resetDraft();\n }\n\n @Watch('requestId')\n @Watch('questions')\n @Watch('answers')\n handleQuestionnaireInputChange() {\n this.scheduleDraftReset();\n }\n\n @Watch('status')\n handleStatusChange(status: AgentQuestionnaireStatus) {\n if (status !== 'submitting') this.answerPending = false;\n }\n\n @Method()\n async setFocus(): Promise<void> {\n this.focusCurrentControl();\n }\n\n private get copy(): AgentQuestionnaireLabels {\n return { ...DEFAULT_LABELS, ...this.labels };\n }\n\n private get disabled(): boolean {\n return this.status === 'submitting';\n }\n\n private resetDraft(answers = this.answers) {\n this.currentStep = 0;\n this.drafts = createQuestionnaireDrafts(this.questions ?? [], answers ?? []);\n this.validation = {};\n this.answerPending = false;\n }\n\n private scheduleDraftReset() {\n if (this.resetScheduled) return;\n this.resetScheduled = true;\n queueMicrotask(() => {\n this.resetScheduled = false;\n const requestChanged = this.requestId !== this.draftRequestId;\n const answersChanged = this.answers !== this.answersSnapshot;\n if (requestChanged && !answersChanged) {\n this.waitingForRequestAnswers = true;\n } else if (answersChanged) {\n this.waitingForRequestAnswers = false;\n }\n this.resetDraft(this.waitingForRequestAnswers ? [] : this.answers);\n this.draftRequestId = this.requestId;\n this.answersSnapshot = this.answers;\n });\n }\n\n private focusCurrentControl(preferInvalid = false) {\n const focus = () => {\n const invalidControl = preferInvalid\n ? this.el.querySelector<HTMLElement>(\n '[data-question-control][aria-invalid=\"true\"]:not([disabled])',\n )\n : null;\n const control = invalidControl ??\n this.el.querySelector<HTMLElement>(\n '[data-question-control]:not([disabled]):not([is-inactive])',\n );\n const action = this.el.querySelector<HTMLElement>(\n '[data-question-action]:not([is-inactive]):not([is-loading])',\n );\n const target = (control ?? action) as\n | (HTMLElement & { setFocus?: () => Promise<void> })\n | null;\n if (target?.setFocus) void target.setFocus();\n else target?.focus();\n };\n focus();\n requestAnimationFrame(focus);\n setTimeout(focus, 0);\n }\n\n private updateDraft(questionId: string, update: Partial<AgentQuestionDraft>) {\n const previous = this.drafts[questionId] ?? {\n value: '',\n otherSelected: false,\n otherText: '',\n skipped: false,\n };\n this.drafts = {\n ...this.drafts,\n [questionId]: { ...previous, ...update, skipped: false },\n };\n if (this.validation[questionId]) {\n const { [questionId]: _removed, ...rest } = this.validation;\n this.validation = rest;\n }\n }\n\n private validate(question: AgentQuestion): boolean {\n const message = validateQuestionDraft(question, this.drafts[question.id]);\n if (!message) return true;\n this.validation = { ...this.validation, [question.id]: message };\n this.focusCurrentControl(true);\n return false;\n }\n\n private move(step: number) {\n this.currentStep = Math.min(Math.max(step, 0), this.questions.length - 1);\n this.focusCurrentControl();\n }\n\n private next(question: AgentQuestion) {\n if (!this.validate(question)) return;\n this.move(this.currentStep + 1);\n }\n\n private skip(question: AgentQuestion) {\n if (question.required) return;\n this.drafts = {\n ...this.drafts,\n [question.id]: {\n ...(this.drafts[question.id] ?? {\n value: '',\n otherSelected: false,\n otherText: '',\n }),\n skipped: true,\n },\n };\n if (this.currentStep < this.questions.length - 1) this.move(this.currentStep + 1);\n else this.submit();\n }\n\n private submit() {\n if (this.disabled || this.answerPending) return;\n const invalidIndex = this.questions.findIndex(\n question => !this.validateWithoutFocus(question),\n );\n if (invalidIndex >= 0) {\n this.currentStep = invalidIndex;\n this.focusCurrentControl(true);\n return;\n }\n\n this.answerPending = true;\n this.dsAnswer.emit({\n requestId: this.requestId,\n answers: this.questions.map(question =>\n normalizeQuestionAnswer(question, this.drafts[question.id]),\n ),\n });\n }\n\n private validateWithoutFocus(question: AgentQuestion): boolean {\n const message = validateQuestionDraft(question, this.drafts[question.id]);\n if (!message) return true;\n this.validation = { ...this.validation, [question.id]: message };\n return false;\n }\n\n private progressLabel(): string {\n return this.copy.progress\n .split('{current}')\n .join(String(this.currentStep + 1))\n .split('{total}')\n .join(String(this.questions.length));\n }\n\n private selectSingle(question: AgentQuestion, value: string) {\n const otherSelected = value === this.otherValue;\n this.updateDraft(question.id, {\n value: otherSelected ? '' : value,\n otherSelected,\n });\n if (otherSelected) {\n requestAnimationFrame(() =>\n this.el.querySelector<HTMLInputElement>('[data-question-other-input]')?.focus(),\n );\n }\n }\n\n private renderSingleChoice(\n question: AgentQuestion,\n promptId: string,\n errorId: string,\n ) {\n const draft = this.drafts[question.id];\n const value = draft.otherSelected\n ? this.otherValue\n : typeof draft.value === 'string'\n ? draft.value\n : '';\n const options = [\n ...(question.choices ?? []),\n ...(question.allowOther\n ? [{ value: this.otherValue, label: this.copy.other }]\n : []),\n ];\n return (\n <div class=\"questionnaire__single-choice\">\n <ds-radio\n data-question-control\n size=\"lg\"\n options={options}\n value={value}\n disabled={this.disabled}\n form={`ds-agent-questionnaire-detached-${this.instanceId}`}\n ariaLabelledby={promptId}\n aria-describedby={this.validation[question.id] ? errorId : undefined}\n onDsChange={(event: CustomEvent<string>) =>\n this.selectSingle(question, event.detail)\n }\n />\n {draft.otherSelected ? this.renderOtherInput(question, errorId) : null}\n </div>\n );\n }\n\n private renderMultipleChoice(question: AgentQuestion, errorId: string) {\n const draft = this.drafts[question.id];\n const values = Array.isArray(draft.value) ? draft.value : [];\n const detachedForm = `ds-agent-questionnaire-detached-${this.instanceId}`;\n return (\n <div class=\"questionnaire__multiple-choice\">\n {question.choices?.map(choice => (\n <ds-checkbox\n key={choice.value}\n data-question-control\n size=\"lg\"\n label={choice.label}\n description={choice.description}\n value={choice.value}\n checked={values.includes(choice.value)}\n disabled={this.disabled}\n form={detachedForm}\n onDsChange={(event: CustomEvent<boolean>) => {\n this.updateDraft(question.id, {\n value: event.detail\n ? [...values, choice.value]\n : values.filter(value => value !== choice.value),\n });\n }}\n />\n ))}\n {question.allowOther ? (\n <div class=\"questionnaire__other-choice\">\n <ds-checkbox\n data-question-control\n size=\"lg\"\n label={this.copy.other}\n checked={draft.otherSelected}\n disabled={this.disabled}\n form={detachedForm}\n onDsChange={(event: CustomEvent<boolean>) => {\n this.updateDraft(question.id, { otherSelected: event.detail });\n if (event.detail) {\n requestAnimationFrame(() =>\n this.el\n .querySelector<HTMLInputElement>('[data-question-other-input]')\n ?.focus(),\n );\n }\n }}\n />\n {draft.otherSelected ? this.renderOtherInput(question, errorId) : null}\n </div>\n ) : null}\n </div>\n );\n }\n\n private renderOtherInput(question: AgentQuestion, errorId: string) {\n const draft = this.drafts[question.id];\n return (\n <input\n class=\"questionnaire__other-input\"\n data-question-control\n data-question-other-input\n type=\"text\"\n form={`ds-agent-questionnaire-detached-${this.instanceId}`}\n value={draft.otherText}\n placeholder={this.copy.otherPlaceholder}\n aria-label={this.copy.other}\n aria-invalid={this.validation[question.id] ? 'true' : undefined}\n aria-describedby={this.validation[question.id] ? errorId : undefined}\n disabled={this.disabled}\n onInput={(event: Event) =>\n this.updateDraft(question.id, {\n otherText: (event.target as HTMLInputElement).value,\n })\n }\n />\n );\n }\n\n private renderQuestion(question: AgentQuestion) {\n const draft = this.drafts[question.id];\n const errorId = `ds-agent-questionnaire-${this.instanceId}-${this.currentStep}-error`;\n const promptId = `ds-agent-questionnaire-${this.instanceId}-${this.currentStep}-prompt`;\n return (\n <div class=\"questionnaire__body\">\n <div class=\"questionnaire__prompt\">\n <ds-text as=\"h2\" variant=\"text-title-small\" textId={promptId}>\n {question.question}\n </ds-text>\n {question.description ? (\n <ds-text variant=\"text-body-small\" color=\"secondary\">\n {question.description}\n </ds-text>\n ) : null}\n </div>\n {question.type === 'text' ? (\n <textarea\n class=\"questionnaire__text-input\"\n data-question-control\n value={typeof draft.value === 'string' ? draft.value : ''}\n form={`ds-agent-questionnaire-detached-${this.instanceId}`}\n placeholder={question.placeholder}\n aria-label={question.question}\n aria-invalid={this.validation[question.id] ? 'true' : undefined}\n aria-describedby={this.validation[question.id] ? errorId : undefined}\n disabled={this.disabled}\n rows={4}\n onInput={(event: Event) =>\n this.updateDraft(question.id, {\n value: (event.target as HTMLTextAreaElement).value,\n })\n }\n />\n ) : (\n <fieldset\n class=\"questionnaire__choices\"\n aria-describedby={this.validation[question.id] ? errorId : undefined}\n >\n <legend class=\"ds-visually-hidden\">{question.question}</legend>\n {question.type === 'single'\n ? this.renderSingleChoice(question, promptId, errorId)\n : this.renderMultipleChoice(question, errorId)}\n </fieldset>\n )}\n {this.validation[question.id] ? (\n <div id={errorId} class=\"questionnaire__error\" role=\"alert\">\n <ds-icon name=\"ErrorTriangle\" size=\"xs\" color=\"inherit\" />\n <ds-text variant=\"text-body-small\" color=\"negative\">\n {this.validation[question.id]}\n </ds-text>\n </div>\n ) : null}\n </div>\n );\n }\n\n private renderAnswered() {\n return (\n <div class=\"questionnaire questionnaire--answered\">\n <ol class=\"questionnaire__summary\">\n {this.questions.map(question => (\n <li>\n <ds-text variant=\"text-body-small\" emphasis>{question.question}</ds-text>\n <ds-text variant=\"text-body-small\" color=\"secondary\">\n {formatQuestionAnswer(\n question,\n this.answers.find(answer => answer.questionId === question.id),\n )}\n </ds-text>\n </li>\n ))}\n </ol>\n </div>\n );\n }\n\n render() {\n if (this.status === 'preparing') {\n return (\n <Host>\n <div class=\"questionnaire questionnaire--preparing\" role=\"status\">\n <ds-loader size=\"sm\" />\n <ds-text variant=\"text-body-medium\">{this.copy.preparing}</ds-text>\n </div>\n </Host>\n );\n }\n if (!this.questions?.length) return null;\n if (this.status === 'answered') return <Host>{this.renderAnswered()}</Host>;\n\n const question = this.questions[this.currentStep];\n const last = this.currentStep === this.questions.length - 1;\n const canSkip = Boolean(question.skippable && !question.required);\n return (\n <Host>\n <section\n class={{\n questionnaire: true,\n 'questionnaire--submitting': this.disabled,\n 'questionnaire--error': this.status === 'error',\n }}\n aria-busy={this.disabled ? 'true' : undefined}\n aria-label={question.question}\n >\n <header class=\"questionnaire__header\">\n <ds-text variant=\"text-caption\" color=\"secondary\">{this.progressLabel()}</ds-text>\n {this.allowCancel ? (\n <ds-tooltip label={this.copy.cancel} side=\"top\" size=\"sm\">\n <ds-button-unfilled\n data-question-action\n variant=\"icon\"\n icon=\"Cross\"\n size=\"sm\"\n aria-label={this.copy.cancel}\n hasBorder={false}\n isInactive={this.disabled}\n onDsClick={() => this.dsCancel.emit({ requestId: this.requestId })}\n />\n </ds-tooltip>\n ) : null}\n </header>\n {this.renderQuestion(question)}\n {this.status === 'error' && this.errorMessage ? (\n <div class=\"questionnaire__submission-error\" role=\"alert\">\n <ds-icon name=\"ErrorTriangle\" size=\"xs\" color=\"inherit\" />\n <ds-text variant=\"text-body-small\" color=\"negative\">{this.errorMessage}</ds-text>\n </div>\n ) : null}\n <footer class=\"questionnaire__actions\">\n <div class=\"questionnaire__actions-leading\">\n {this.currentStep > 0 ? (\n <div class=\"questionnaire__action-item\">\n <ds-button-unfilled\n data-question-action\n label={this.copy.previous}\n size=\"sm\"\n width=\"fill\"\n isInactive={this.disabled}\n onDsClick={() => this.move(this.currentStep - 1)}\n />\n </div>\n ) : null}\n {canSkip ? (\n <div class=\"questionnaire__action-item\">\n <ds-button-unfilled\n data-question-action\n label={this.copy.skip}\n size=\"sm\"\n width=\"fill\"\n hasBorder={false}\n isInactive={this.disabled}\n onDsClick={() => this.skip(question)}\n />\n </div>\n ) : null}\n </div>\n <div class=\"questionnaire__action-item questionnaire__action-item--primary\">\n <ds-button-filled\n data-question-action\n label={last ? this.copy.answer : this.copy.next}\n size=\"sm\"\n width=\"fill\"\n isLoading={this.disabled}\n onDsClick={() => (last ? this.submit() : this.next(question))}\n />\n </div>\n </footer>\n </section>\n </Host>\n );\n }\n}\n",
|
|
265
|
+
"type": "registry:ui"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"path": "src/wc/components/AgentQuestionnaire/agent-questionnaire-model.ts",
|
|
269
|
+
"content": "import type {\n AgentQuestion,\n AgentQuestionAnswer,\n} from '../conversation-types';\n\nexport interface AgentQuestionDraft {\n value: string | string[];\n otherSelected: boolean;\n otherText: string;\n skipped: boolean;\n}\n\nexport type AgentQuestionDrafts = Record<string, AgentQuestionDraft>;\n\nfunction answerFor(\n answers: AgentQuestionAnswer[],\n questionId: string,\n): AgentQuestionAnswer | undefined {\n return answers.find(answer => answer.questionId === questionId);\n}\n\nexport function createQuestionnaireDrafts(\n questions: AgentQuestion[],\n answers: AgentQuestionAnswer[],\n): AgentQuestionDrafts {\n return Object.fromEntries(\n questions.map(question => {\n const answer = answerFor(answers, question.id);\n const choiceValues = new Set(question.choices?.map(choice => choice.value) ?? []);\n\n if (question.type === 'multiple') {\n const values = Array.isArray(answer?.value) ? answer.value : [];\n const known = values.filter(value => choiceValues.has(value));\n const other = values.find(value => !choiceValues.has(value)) ?? '';\n return [\n question.id,\n {\n value: known,\n otherSelected: Boolean(question.allowOther && other),\n otherText: question.allowOther ? other : '',\n skipped: answer?.value === null,\n },\n ];\n }\n\n const value = typeof answer?.value === 'string' ? answer.value : '';\n const isKnownChoice = question.type === 'single' && choiceValues.has(value);\n return [\n question.id,\n {\n value: question.type === 'single' && !isKnownChoice ? '' : value,\n otherSelected: Boolean(\n question.type === 'single' && question.allowOther && value && !isKnownChoice,\n ),\n otherText:\n question.type === 'single' && question.allowOther && value && !isKnownChoice\n ? value\n : '',\n skipped: answer?.value === null,\n },\n ];\n }),\n );\n}\n\nexport function normalizeQuestionAnswer(\n question: AgentQuestion,\n draft: AgentQuestionDraft,\n): AgentQuestionAnswer {\n if (draft.skipped) return { questionId: question.id, value: null };\n\n if (question.type === 'multiple') {\n const values = Array.isArray(draft.value) ? [...draft.value] : [];\n if (draft.otherSelected && draft.otherText.trim()) values.push(draft.otherText.trim());\n return {\n questionId: question.id,\n value: values.length || question.required ? values : null,\n };\n }\n\n if (draft.otherSelected) {\n const other = draft.otherText.trim();\n return { questionId: question.id, value: other || null };\n }\n\n const value = typeof draft.value === 'string' ? draft.value.trim() : '';\n return { questionId: question.id, value: value || null };\n}\n\nexport function validateQuestionDraft(\n question: AgentQuestion,\n draft: AgentQuestionDraft,\n): string | undefined {\n if (\n (question.type === 'single' || question.type === 'multiple') &&\n !question.choices?.length\n ) {\n return 'This question has no available choices.';\n }\n\n if (draft.otherSelected && !draft.otherText.trim()) {\n return 'Enter a response for Other.';\n }\n\n if (!question.required || draft.skipped) return undefined;\n const answer = normalizeQuestionAnswer(question, draft).value;\n const missing = answer === null || (Array.isArray(answer) && answer.length === 0);\n if (!missing) return undefined;\n return question.type === 'text'\n ? 'Enter an answer before continuing.'\n : 'Choose an answer before continuing.';\n}\n\nexport function formatQuestionAnswer(\n question: AgentQuestion,\n answer: AgentQuestionAnswer | undefined,\n): string {\n if (!answer || answer.value === null) return 'Skipped';\n const values = Array.isArray(answer.value) ? answer.value : [answer.value];\n const labels = new Map(question.choices?.map(choice => [choice.value, choice.label]) ?? []);\n return values.map(value => labels.get(value) ?? value).join(', ');\n}\n",
|
|
270
|
+
"type": "registry:ui"
|
|
271
|
+
}
|
|
272
|
+
]
|
|
273
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
3
|
"name": "agent-response",
|
|
4
4
|
"title": "AgentResponse",
|
|
5
|
-
"description": "Ordered renderer for normalized immutable agent response parts inside a generic incoming message.",
|
|
5
|
+
"description": "Ordered renderer for normalized immutable agent response parts or an application-composed response body inside a generic incoming message.",
|
|
6
6
|
"type": "registry:ui",
|
|
7
7
|
"meta": {
|
|
8
8
|
"library": "@ds-mo/ui",
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
"intent": {
|
|
14
14
|
"audience": "specialized",
|
|
15
15
|
"status": "experimental",
|
|
16
|
-
"summary": "Ordered renderer for normalized immutable agent response parts inside a generic incoming message.",
|
|
16
|
+
"summary": "Ordered renderer for normalized immutable agent response parts or an application-composed response body inside a generic incoming message.",
|
|
17
17
|
"useWhen": [
|
|
18
|
-
"An agent response combines Markdown, user-safe activity, display-only tools, attachments,
|
|
18
|
+
"An agent response combines Markdown, user-safe activity, display-only tools, attachments, answered questionnaires, sources, or application-specific content in authored order."
|
|
19
19
|
],
|
|
20
20
|
"avoidWhen": [
|
|
21
21
|
"The component would be expected to own a model, transport, persistence, title generation, approval policy, or private reasoning."
|
|
@@ -26,28 +26,30 @@
|
|
|
26
26
|
"component:ds-markdown",
|
|
27
27
|
"component:ds-agent-activity",
|
|
28
28
|
"component:ds-agent-tool-call",
|
|
29
|
-
"component:ds-agent-source-list"
|
|
29
|
+
"component:ds-agent-source-list",
|
|
30
|
+
"component:ds-agent-questionnaire"
|
|
30
31
|
],
|
|
31
32
|
"patterns": [
|
|
32
33
|
"pattern:agent-chat"
|
|
33
34
|
],
|
|
34
35
|
"accessibility": [
|
|
35
|
-
"Part order matches authored reading order and remains inside generic message semantics.",
|
|
36
|
+
"Part or composed-slot order matches authored reading order and remains inside generic message semantics.",
|
|
36
37
|
"Streaming state supplements rather than replaces meaningful textual status.",
|
|
37
38
|
"Forwarded metadata actions retain Message ordering, keyboard reveal, and touch visibility."
|
|
38
39
|
],
|
|
39
40
|
"states": [
|
|
40
41
|
"The owner replaces immutable part arrays as scripted or live output changes.",
|
|
42
|
+
"Parts mode remains the compatibility default for serializable content; composed mode ignores parts and gives the default slot ownership of the complete ordered response body.",
|
|
41
43
|
"AgentResponse renders directly in Message without borrowing a plain MessageBubble surface.",
|
|
42
|
-
"Markdown parts use the optional safe renderer; prose
|
|
44
|
+
"Markdown parts use the optional safe renderer; the response sets the public prose text measure while code, tables, tools, sources, attachments, and other structured parts retain the full lane.",
|
|
43
45
|
"The application may compose MessageActions for completed-response Copy and controlled feedback while retaining persistent retry or recovery controls in the separate actions slot."
|
|
44
46
|
],
|
|
45
47
|
"responsiveBehavior": [
|
|
46
|
-
"
|
|
48
|
+
"Direct prose blocks use a readable text measure within the available transcript width, while narrow lanes and structured content retain their available width and local overflow constraints."
|
|
47
49
|
],
|
|
48
50
|
"references": [
|
|
49
51
|
{
|
|
50
|
-
"label": "
|
|
52
|
+
"label": "Response modes and representative flow",
|
|
51
53
|
"path": "src/wc/components/AgentResponse/AgentResponse.stories.ts"
|
|
52
54
|
},
|
|
53
55
|
{
|
|
@@ -90,6 +92,15 @@
|
|
|
90
92
|
"required": false,
|
|
91
93
|
"mutable": false
|
|
92
94
|
},
|
|
95
|
+
"renderMode": {
|
|
96
|
+
"type": "AgentResponseRenderMode",
|
|
97
|
+
"resolvedType": "\"composed\" | \"parts\"",
|
|
98
|
+
"attribute": "render-mode",
|
|
99
|
+
"default": "'parts'",
|
|
100
|
+
"required": false,
|
|
101
|
+
"mutable": false,
|
|
102
|
+
"description": "Renders serializable ordered parts or lets the default slot own the complete ordered body."
|
|
103
|
+
},
|
|
93
104
|
"showAuthor": {
|
|
94
105
|
"type": "boolean",
|
|
95
106
|
"resolvedType": "boolean",
|
|
@@ -152,6 +163,15 @@
|
|
|
152
163
|
"required": false,
|
|
153
164
|
"mutable": false
|
|
154
165
|
},
|
|
166
|
+
"renderMode": {
|
|
167
|
+
"type": "AgentResponseRenderMode",
|
|
168
|
+
"resolvedType": "\"composed\" | \"parts\"",
|
|
169
|
+
"attribute": "render-mode",
|
|
170
|
+
"default": "'parts'",
|
|
171
|
+
"required": false,
|
|
172
|
+
"mutable": false,
|
|
173
|
+
"description": "Renders serializable ordered parts or lets the default slot own the complete ordered body."
|
|
174
|
+
},
|
|
155
175
|
"showAuthor": {
|
|
156
176
|
"type": "boolean",
|
|
157
177
|
"resolvedType": "boolean",
|
|
@@ -203,8 +223,8 @@
|
|
|
203
223
|
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: parts.",
|
|
204
224
|
"peerDependencies": {
|
|
205
225
|
"required": [
|
|
206
|
-
"@ds-mo/tokens ^6.
|
|
207
|
-
"@ds-mo/icons ^6.
|
|
226
|
+
"@ds-mo/tokens ^6.2.1",
|
|
227
|
+
"@ds-mo/icons ^6.6.0"
|
|
208
228
|
],
|
|
209
229
|
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
210
230
|
}
|
|
@@ -216,6 +236,7 @@
|
|
|
216
236
|
],
|
|
217
237
|
"registryDependencies": [
|
|
218
238
|
"agent-activity",
|
|
239
|
+
"agent-questionnaire",
|
|
219
240
|
"agent-source-list",
|
|
220
241
|
"agent-tool-call",
|
|
221
242
|
"attachment-list",
|
|
@@ -225,12 +246,12 @@
|
|
|
225
246
|
"files": [
|
|
226
247
|
{
|
|
227
248
|
"path": "src/wc/components/AgentResponse/AgentResponse.css",
|
|
228
|
-
"content": ":host {\n display: block;\n width: 100%;\n -webkit-user-select: none;\n user-select: none;\n}\n.agent-response {\n display: grid;\n gap: var(--dimension-space-150);\n min-width: 0;\n width: 100%;\n -webkit-user-select: none;\n user-select: none;\n}\n",
|
|
249
|
+
"content": ":host {\n display: block;\n width: 100%;\n --ds-prose-text-max-inline-size: var(--dimension-panel-width-lg);\n -webkit-user-select: none;\n user-select: none;\n}\n.agent-response {\n display: grid;\n gap: var(--dimension-space-150);\n min-width: 0;\n width: 100%;\n -webkit-user-select: none;\n user-select: none;\n}\n",
|
|
229
250
|
"type": "registry:ui"
|
|
230
251
|
},
|
|
231
252
|
{
|
|
232
253
|
"path": "src/wc/components/AgentResponse/AgentResponse.tsx",
|
|
233
|
-
"content": "import { Component, Prop, h, Host } from '@stencil/core';\nimport type {\n AgentResponsePart,\n MessageMetadataVisibility,\n} from '../conversation-types';\n\n@Component({ tag: 'ds-agent-response', styleUrl: 'AgentResponse.css', scoped: true })\nexport class AgentResponse {\n @Prop() messageId: string = '';\n @Prop() author: string = '';\n @Prop() showAuthor: boolean = true;\n @Prop() timestamp: string = '';\n @Prop() parts: AgentResponsePart[] = [];\n @Prop() streaming: boolean = false;\n /** Controls whether the complete message metadata footer is persistent or revealed through hover/focus. */\n @Prop() metadataVisibility: MessageMetadataVisibility = 'always';\n\n private renderPart(part: AgentResponsePart) {\n switch (part.type) {\n case 'markdown':\n return (\n <ds-markdown\n key={part.id}\n content={part.content}\n streaming={part.state === 'streaming'}\n />\n );\n case 'activity':\n return <ds-agent-activity key={part.id} items={part.items} />;\n case 'tool':\n return (\n <ds-agent-tool-call\n key={part.id}\n name={part.name}\n label={part.label}\n state={part.state}\n input={part.input}\n output={part.output}\n error={part.error}\n />\n );\n case 'attachments':\n return <ds-attachment-list key={part.id} items={part.items} />;\n case 'sources':\n return <ds-agent-source-list key={part.id} items={part.items} />;\n }\n }\n\n render() {\n return (\n <Host>\n <ds-message\n messageId={this.messageId}\n direction=\"incoming\"\n author={this.author}\n showAuthor={this.showAuthor}\n timestamp={this.timestamp}\n streaming={this.streaming}\n metadataVisibility={this.metadataVisibility}\n >\n <div class=\"agent-response\"
|
|
254
|
+
"content": "import { Component, Prop, h, Host } from '@stencil/core';\nimport type {\n AgentResponseRenderMode,\n AgentResponsePart,\n MessageMetadataVisibility,\n} from '../conversation-types';\n\n@Component({ tag: 'ds-agent-response', styleUrl: 'AgentResponse.css', scoped: true })\nexport class AgentResponse {\n @Prop() messageId: string = '';\n @Prop() author: string = '';\n @Prop() showAuthor: boolean = true;\n @Prop() timestamp: string = '';\n @Prop() parts: AgentResponsePart[] = [];\n /** Renders serializable ordered parts or lets the default slot own the complete ordered body. */\n @Prop() renderMode: AgentResponseRenderMode = 'parts';\n @Prop() streaming: boolean = false;\n /** Controls whether the complete message metadata footer is persistent or revealed through hover/focus. */\n @Prop() metadataVisibility: MessageMetadataVisibility = 'always';\n\n private renderPart(part: AgentResponsePart) {\n switch (part.type) {\n case 'markdown':\n return (\n <ds-markdown\n key={part.id}\n content={part.content}\n streaming={part.state === 'streaming'}\n />\n );\n case 'activity':\n return <ds-agent-activity key={part.id} items={part.items} />;\n case 'tool':\n return (\n <ds-agent-tool-call\n key={part.id}\n name={part.name}\n label={part.label}\n state={part.state}\n input={part.input}\n output={part.output}\n error={part.error}\n />\n );\n case 'attachments':\n return <ds-attachment-list key={part.id} items={part.items} />;\n case 'sources':\n return <ds-agent-source-list key={part.id} items={part.items} />;\n case 'questionnaire':\n return (\n <ds-agent-questionnaire\n key={part.id}\n requestId={part.requestId}\n questions={part.questions}\n answers={part.answers}\n status=\"answered\"\n />\n );\n }\n }\n\n render() {\n return (\n <Host>\n <ds-message\n messageId={this.messageId}\n direction=\"incoming\"\n author={this.author}\n showAuthor={this.showAuthor}\n timestamp={this.timestamp}\n streaming={this.streaming}\n metadataVisibility={this.metadataVisibility}\n >\n <div class=\"agent-response\">\n {this.renderMode === 'composed' ? (\n <slot />\n ) : (\n this.parts.map(part => this.renderPart(part))\n )}\n </div>\n <slot name=\"footer\" slot=\"footer\" />\n <slot name=\"metadata-actions\" slot=\"metadata-actions\" />\n <slot name=\"actions\" slot=\"actions\" />\n </ds-message>\n </Host>\n );\n }\n}\n",
|
|
234
255
|
"type": "registry:ui"
|
|
235
256
|
}
|
|
236
257
|
]
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
3
|
"name": "agent-source-list",
|
|
4
4
|
"title": "AgentSourceList",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Inline collapsible agent-source list with safe external links, derived hostnames, optional descriptions, and observable disclosure state.",
|
|
6
6
|
"type": "registry:ui",
|
|
7
7
|
"meta": {
|
|
8
8
|
"library": "@ds-mo/ui",
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
"intent": {
|
|
14
14
|
"audience": "specialized",
|
|
15
15
|
"status": "experimental",
|
|
16
|
-
"summary": "
|
|
16
|
+
"summary": "Inline collapsible agent-source list with safe external links, derived hostnames, optional descriptions, and observable disclosure state.",
|
|
17
17
|
"useWhen": [
|
|
18
|
-
"
|
|
18
|
+
"A stable agent response cites external material readers may inspect inline."
|
|
19
19
|
],
|
|
20
20
|
"avoidWhen": [
|
|
21
|
-
"The links are ordinary body links
|
|
21
|
+
"The links are ordinary body links, source discovery is still active, or the application expects a source drawer or deduplication behavior."
|
|
22
22
|
],
|
|
23
23
|
"commonlyComposedWith": [
|
|
24
24
|
"component:ds-agent-response",
|
|
@@ -28,16 +28,20 @@
|
|
|
28
28
|
"pattern:agent-chat"
|
|
29
29
|
],
|
|
30
30
|
"accessibility": [
|
|
31
|
-
"Each source uses descriptive linked text
|
|
32
|
-
"
|
|
31
|
+
"Each interactive source uses descriptive linked text, a visible hostname, supporting context, and an external-link indication.",
|
|
32
|
+
"Malformed and unsafe schemes remain non-interactive text rather than producing executable links.",
|
|
33
|
+
"The native disclosure exposes keyboard and expanded-state semantics, while open-change events let applications observe participant intent."
|
|
34
|
+
],
|
|
35
|
+
"states": [
|
|
36
|
+
"Applications collect and deduplicate sources, then append the stable list once; active discovery remains an activity or tool state."
|
|
33
37
|
],
|
|
34
38
|
"responsiveBehavior": [
|
|
35
|
-
"Source titles and descriptions wrap within the response width."
|
|
39
|
+
"Source titles, hostnames, and descriptions wrap within the response width."
|
|
36
40
|
],
|
|
37
41
|
"references": [
|
|
38
42
|
{
|
|
39
|
-
"label": "
|
|
40
|
-
"path": "src/wc/components/
|
|
43
|
+
"label": "Source safety and disclosure stories",
|
|
44
|
+
"path": "src/wc/components/AgentSourceList/AgentSourceList.stories.ts"
|
|
41
45
|
}
|
|
42
46
|
]
|
|
43
47
|
},
|
|
@@ -67,7 +71,15 @@
|
|
|
67
71
|
"mutable": false
|
|
68
72
|
}
|
|
69
73
|
},
|
|
70
|
-
"events": [
|
|
74
|
+
"events": [
|
|
75
|
+
{
|
|
76
|
+
"name": "dsOpenChange",
|
|
77
|
+
"detail": "{ open: boolean }",
|
|
78
|
+
"bubbles": true,
|
|
79
|
+
"cancelable": true,
|
|
80
|
+
"composed": true
|
|
81
|
+
}
|
|
82
|
+
],
|
|
71
83
|
"methods": [],
|
|
72
84
|
"slots": []
|
|
73
85
|
},
|
|
@@ -96,7 +108,15 @@
|
|
|
96
108
|
"mutable": false
|
|
97
109
|
}
|
|
98
110
|
},
|
|
99
|
-
"events": [
|
|
111
|
+
"events": [
|
|
112
|
+
{
|
|
113
|
+
"name": "dsOpenChange",
|
|
114
|
+
"detail": "{ open: boolean }",
|
|
115
|
+
"bubbles": true,
|
|
116
|
+
"cancelable": true,
|
|
117
|
+
"composed": true
|
|
118
|
+
}
|
|
119
|
+
],
|
|
100
120
|
"methods": [],
|
|
101
121
|
"slots": [],
|
|
102
122
|
"exports": {
|
|
@@ -122,8 +142,8 @@
|
|
|
122
142
|
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: items.",
|
|
123
143
|
"peerDependencies": {
|
|
124
144
|
"required": [
|
|
125
|
-
"@ds-mo/tokens ^6.
|
|
126
|
-
"@ds-mo/icons ^6.
|
|
145
|
+
"@ds-mo/tokens ^6.2.1",
|
|
146
|
+
"@ds-mo/icons ^6.6.0"
|
|
127
147
|
],
|
|
128
148
|
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
129
149
|
}
|
|
@@ -146,7 +166,7 @@
|
|
|
146
166
|
},
|
|
147
167
|
{
|
|
148
168
|
"path": "src/wc/components/AgentSourceList/AgentSourceList.tsx",
|
|
149
|
-
"content": "import { Component, Prop, h, Host } from '@stencil/core';\nimport { resolveSafeUrl } from '../../utils';\nimport type { AgentSource } from '../conversation-types';\n\n@Component({ tag: 'ds-agent-source-list', styleUrl: 'AgentSourceList.css', scoped: true })\nexport class AgentSourceList {\n @Prop() items: AgentSource[] = [];\n @Prop() heading: string = 'Sources';\n @Prop() open: boolean = false;\n\n render() {\n if (!this.items.length) return null;\n return (\n <Host>\n <details
|
|
169
|
+
"content": "import { Component, Event, EventEmitter, Prop, h, Host } from '@stencil/core';\nimport { resolveSafeUrl } from '../../utils';\nimport type { AgentSource } from '../conversation-types';\n\n@Component({ tag: 'ds-agent-source-list', styleUrl: 'AgentSourceList.css', scoped: true })\nexport class AgentSourceList {\n @Prop() items: AgentSource[] = [];\n @Prop() heading: string = 'Sources';\n @Prop() open: boolean = false;\n\n @Event() dsOpenChange!: EventEmitter<{ open: boolean }>;\n\n private hostname(href: string): string {\n try {\n return new URL(href).hostname;\n } catch {\n return '';\n }\n }\n\n render() {\n if (!this.items.length) return null;\n return (\n <Host>\n <details\n class=\"agent-sources\"\n open={this.open}\n onToggle={(event: Event) =>\n this.dsOpenChange.emit({\n open: (event.currentTarget as HTMLDetailsElement).open,\n })\n }\n >\n <summary>\n <ds-icon name=\"ChevronRight\" size=\"xs\" color=\"inherit\" />\n <ds-text variant=\"text-body-small\" emphasis>{this.heading} · {this.items.length}</ds-text>\n </summary>\n <ol>\n {this.items.map(source => {\n const href = resolveSafeUrl(source.url);\n const hostname = href ? this.hostname(href) : '';\n return <li>\n {href\n ? <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`${source.title} (${hostname}, opens in a new tab)`}\n ><ds-text variant=\"text-body-small\" emphasis>{source.title}</ds-text><ds-icon name=\"ExternalLink\" size=\"xs\" color=\"inherit\" /></a>\n : <ds-text variant=\"text-body-small\" emphasis>{source.title}</ds-text>}\n {hostname ? <ds-text variant=\"text-caption\" color=\"secondary\">{hostname}</ds-text> : null}\n {source.description ? <ds-text variant=\"text-body-small\" color=\"secondary\">{source.description}</ds-text> : null}\n </li>;\n })}\n </ol>\n </details>\n </Host>\n );\n }\n}\n",
|
|
150
170
|
"type": "registry:ui"
|
|
151
171
|
}
|
|
152
172
|
]
|