@ds-mo/ui 14.36.0 → 15.0.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 +1 -1
- package/dist/agent.json +5083 -4924
- package/dist/angular/ds-conversation-list.d.ts +1 -1
- package/dist/angular/ds-conversation-list.js +3 -4
- package/dist/angular/ds-data-customize.d.ts +18 -0
- package/dist/angular/ds-data-customize.js +46 -0
- package/dist/angular/ds-data-filter.d.ts +50 -0
- package/dist/angular/{ds-table-filter.js → ds-data-filter.js} +10 -10
- package/dist/angular/ds-data-group.d.ts +29 -0
- package/dist/angular/{ds-table-group.js → ds-data-group.js} +10 -10
- package/dist/angular/ds-data-preferences.d.ts +39 -0
- package/dist/angular/{ds-table-preferences.js → ds-data-preferences.js} +15 -15
- package/dist/angular/ds-data-saved-views.d.ts +49 -0
- package/dist/angular/{ds-table-saved-views.js → ds-data-saved-views.js} +10 -10
- package/dist/angular/ds-data-search.d.ts +20 -0
- package/dist/angular/{ds-table-search.js → ds-data-search.js} +12 -12
- package/dist/angular/ds-data-sort.d.ts +16 -0
- package/dist/angular/{ds-table-sort.js → ds-data-sort.js} +12 -12
- package/dist/angular/ds-data-toolbar.d.ts +12 -0
- package/dist/angular/{ds-table-toolbar.js → ds-data-toolbar.js} +10 -10
- package/dist/angular/ds-table.d.ts +7 -7
- package/dist/angular/ds-table.js +6 -6
- package/dist/angular/index.d.ts +1 -1
- package/dist/angular/index.js +8 -7
- package/dist/angular/proxies.d.ts +8 -7
- package/dist/angular/proxies.js +8 -7
- package/dist/components/ds-agent-activity.js +1 -1
- package/dist/components/ds-agent-questionnaire.js +1 -1
- package/dist/components/ds-agent-response.js +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-action.js +1 -1
- package/dist/components/ds-bar-nav.js +1 -1
- package/dist/components/ds-bar-page-title.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-inverted.js +1 -1
- package/dist/components/ds-button-unfilled.js +1 -1
- package/dist/components/ds-calendar.js +1 -1
- package/dist/components/ds-card-action-center.js +1 -1
- package/dist/components/ds-card-chart.js +1 -1
- package/dist/components/ds-card-navigation.js +1 -1
- package/dist/components/ds-card-overview.js +1 -1
- package/dist/components/ds-card-setting.js +1 -1
- package/dist/components/ds-card-settings-scope.js +1 -1
- package/dist/components/ds-chart-legend.js +1 -1
- package/dist/components/ds-chart.js +1 -1
- package/dist/components/ds-checkbox.js +1 -1
- package/dist/components/ds-chip.js +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-section.js +1 -1
- package/dist/components/ds-conversation-list.js +1 -1
- package/dist/components/ds-conversation-list.js.map +1 -1
- package/dist/components/ds-data-customize.d.ts +11 -0
- package/dist/components/ds-data-customize.js +2 -0
- package/dist/components/ds-data-customize.js.map +1 -0
- package/dist/components/{ds-table-group.d.ts → ds-data-filter.d.ts} +4 -4
- package/dist/components/ds-data-filter.js +2 -0
- package/dist/components/ds-data-filter.js.map +1 -0
- package/dist/components/{ds-table-sort.d.ts → ds-data-group.d.ts} +4 -4
- package/dist/components/ds-data-group.js +2 -0
- package/dist/components/{ds-table-saved-views.d.ts → ds-data-preferences.d.ts} +4 -4
- package/dist/components/ds-data-preferences.js +2 -0
- package/dist/components/ds-data-preferences.js.map +1 -0
- package/dist/components/ds-data-saved-views.d.ts +11 -0
- package/dist/components/ds-data-saved-views.js +2 -0
- package/dist/components/ds-data-saved-views.js.map +1 -0
- package/dist/components/{ds-table-search.d.ts → ds-data-search.d.ts} +4 -4
- package/dist/components/ds-data-search.js +2 -0
- package/dist/components/ds-data-search.js.map +1 -0
- package/dist/components/ds-data-sort.d.ts +11 -0
- package/dist/components/ds-data-sort.js +2 -0
- package/dist/components/ds-data-sort.js.map +1 -0
- package/dist/components/{ds-table-filter.d.ts → ds-data-toolbar.d.ts} +4 -4
- package/dist/components/ds-data-toolbar.js +2 -0
- package/dist/components/ds-data-toolbar.js.map +1 -0
- 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-filter-menu.js +1 -1
- package/dist/components/ds-icon.js +1 -1
- package/dist/components/ds-input-date.js +1 -1
- package/dist/components/ds-input-time.js +1 -1
- package/dist/components/ds-input-time.js.map +1 -1
- package/dist/components/ds-input.js +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-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.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-pagination.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-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-paper-texture.js +1 -1
- package/dist/components/ds-radio.js +1 -1
- package/dist/components/ds-score.js +1 -1
- package/dist/components/ds-scroll-overlay.js +1 -1
- package/dist/components/ds-select.js +1 -1
- package/dist/components/ds-shell-app.js +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-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-textarea.js +1 -1
- package/dist/components/ds-time-picker.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 +5 -5
- package/dist/components/{p-D8rpKod8.js → p-0FYD2bev.js} +2 -2
- package/dist/components/p-0qY_HDId.js +2 -0
- package/dist/components/{p-C0CE2v5D.js.map → p-0qY_HDId.js.map} +1 -1
- package/dist/components/{p-DK9Ex3aY.js → p-5URekSny.js} +2 -2
- package/dist/components/{p-Ds51RgCi.js → p-7V1AhetH.js} +2 -2
- package/dist/components/{p-C2JnoaWI.js → p-8yBdCXCn.js} +2 -2
- package/dist/components/{p-CQIh2yRP.js → p-BKZdqJQB.js} +2 -2
- package/dist/components/p-BKZdqJQB.js.map +1 -0
- package/dist/components/p-BYrBU_U9.js +2 -0
- package/dist/components/p-BYrBU_U9.js.map +1 -0
- package/dist/components/{p-su6y4hLK.js → p-BciTtTwx.js} +2 -2
- package/dist/components/{p-DgG9W9N4.js → p-BeNa6tw5.js} +2 -2
- package/dist/components/{p-DgG9W9N4.js.map → p-BeNa6tw5.js.map} +1 -1
- package/dist/components/p-BgQMEHRa.js +2 -0
- package/dist/components/{p-D7yBIPB6.js.map → p-BgQMEHRa.js.map} +1 -1
- package/dist/components/{p-CQ5RwY2C.js → p-BhJXmuRA.js} +2 -2
- package/dist/components/{p-neWTRxmf.js → p-Bm7rqs3C.js} +2 -2
- package/dist/components/{p-BV5T1hzN.js → p-Bn8I7iw6.js} +2 -2
- package/dist/components/{p-PmcUwTQ_.js → p-Bpd6YCo4.js} +2 -2
- package/dist/components/p-C-3YqeTb.js +2 -0
- package/dist/components/{p-TjXGRPik.js.map → p-C-3YqeTb.js.map} +1 -1
- package/dist/components/{p-C4m8y9ki.js → p-CD4DZPy_.js} +2 -2
- package/dist/components/{p-B27_chI7.js → p-CElUM-xU.js} +2 -2
- package/dist/components/{p-CuwopElg.js → p-CGidq1iC.js} +2 -2
- package/dist/components/{p-CWog26I_.js → p-CNxvnQ6A.js} +2 -2
- package/dist/components/{p-2GVGhrh0.js → p-CUcUHwI3.js} +2 -2
- package/dist/components/{p-CbSUyv5B.js → p-CYzFfFcH.js} +2 -2
- package/dist/components/p-CdgOLWX9.js +2 -0
- package/dist/components/p-CdgOLWX9.js.map +1 -0
- package/dist/components/{p-Jaqdfw4E.js → p-CiH4GG6r.js} +2 -2
- package/dist/components/{p-Cl9phSf0.js → p-CiJ1WR11.js} +2 -2
- package/dist/components/{p-Cus1Sigh.js → p-CmexIVnE.js} +2 -2
- package/dist/components/{p-DLXXGgmf.js → p-CzIpquvw.js} +2 -2
- package/dist/components/{p-tNQ0YulU.js → p-D0y7Sja6.js} +2 -2
- package/dist/components/{p-x1wf38q3.js → p-D1vQGJzc.js} +2 -2
- package/dist/components/{p-x1wf38q3.js.map → p-D1vQGJzc.js.map} +1 -1
- package/dist/components/{p-Dryt3COt.js → p-D6Wl3dRO.js} +2 -2
- package/dist/components/{p-ji09W9el.js → p-D922f6Tb.js} +2 -2
- package/dist/components/{p-CaNCGKEJ.js → p-DHICPS4n.js} +2 -2
- package/dist/components/{p-Cga6Ex0E.js → p-DOAybCp0.js} +2 -2
- package/dist/components/{p-CWPT3aOB.js → p-DVINzOoK.js} +2 -2
- package/dist/components/{p-CWPT3aOB.js.map → p-DVINzOoK.js.map} +1 -1
- package/dist/components/{p-7O-2D29W.js → p-DVOjjuXc.js} +2 -2
- package/dist/components/{p-DkikNSSO.js → p-Di5FH7eh.js} +2 -2
- package/dist/components/{p-DkikNSSO.js.map → p-Di5FH7eh.js.map} +1 -1
- package/dist/components/p-DjkUFlDW.js +2 -0
- package/dist/components/p-DjkUFlDW.js.map +1 -0
- package/dist/components/{p-DVd1TIxi.js → p-Dn9QHL4O.js} +2 -2
- package/dist/components/{p-C-dHtQMi.js → p-Do2FJd1y.js} +2 -2
- package/dist/components/{p-BWfzaSc3.js → p-DpoTwJAR.js} +2 -2
- package/dist/components/{p-ClJhuG5Y.js → p-Dpr2y6_S.js} +2 -2
- package/dist/components/{p-ClJhuG5Y.js.map → p-Dpr2y6_S.js.map} +1 -1
- package/dist/components/p-Dw9sE6Iw.js +2 -0
- package/dist/components/p-Dw9sE6Iw.js.map +1 -0
- package/dist/components/{p-BgLI9JoT.js → p-DwbcNDJF.js} +2 -2
- package/dist/components/p-Dzndkdx5.js +2 -0
- package/dist/components/{p-BOhpMUwO.js.map → p-Dzndkdx5.js.map} +1 -1
- package/dist/components/{p-DvzI2A_M.js → p-E5W27Fu_.js} +2 -2
- package/dist/components/{p-DkfM55x8.js → p-FIBCluwV.js} +2 -2
- package/dist/components/{p-CMQUuGvl.js → p-IEq_06J0.js} +2 -2
- package/dist/components/{p-CMQUuGvl.js.map → p-IEq_06J0.js.map} +1 -1
- package/dist/components/{p-8oRkhvjy.js → p-MG4lcN0D.js} +2 -2
- package/dist/components/{p-DtkLtKY0.js → p-Nc76seSq.js} +2 -2
- package/dist/components/p-Nc76seSq.js.map +1 -0
- package/dist/components/{p-DBwa1OXP.js → p-ZhP2tVmM.js} +2 -2
- package/dist/components/p-aD5cw_m2.js +2 -0
- package/dist/components/p-aD5cw_m2.js.map +1 -0
- package/dist/components/{p-J5x-QtlD.js → p-etifxiDc.js} +2 -2
- package/dist/components/p-kDZ0sEII.js +2 -0
- package/dist/components/p-kDZ0sEII.js.map +1 -0
- package/dist/components/{p-rYePOPbJ.js → p-ljbw3UMZ.js} +2 -2
- package/dist/components/{p-DZ58Sg5a.js → p-vfCu7XSc.js} +2 -2
- package/dist/components/{p-Ce4zy8q1.js → p-xdmJCPCg.js} +2 -2
- package/dist/components/{p-CDJ2Ntcq.js → p-xtGGIZmU.js} +2 -2
- package/dist/docs/components.json +13115 -12615
- package/dist/lib/components/Icon/flag-icon-catalog.d.ts +2 -0
- package/dist/lib/components/Icon/icon-cache.d.ts +36 -4
- package/dist/lib/components/Icon/map-icon-catalog.d.ts +2 -0
- package/dist/lib/shell/index.js +2 -2
- package/dist/lib/shell/index.js.map +1 -1
- package/dist/lib/utils/index.js +68 -5
- package/dist/lib/utils/index.js.map +3 -3
- package/dist/mcp-data/registry/agent-activity.json +2 -2
- package/dist/mcp-data/registry/agent-questionnaire.json +2 -2
- package/dist/mcp-data/registry/agent-response.json +1 -1
- package/dist/mcp-data/registry/agent-source-list.json +1 -1
- package/dist/mcp-data/registry/agent-tool-call.json +2 -2
- package/dist/mcp-data/registry/attachment-list.json +1 -1
- package/dist/mcp-data/registry/avatar.json +1 -1
- package/dist/mcp-data/registry/badge.json +1 -1
- package/dist/mcp-data/registry/banner.json +1 -1
- package/dist/mcp-data/registry/bar-action.json +1 -1
- package/dist/mcp-data/registry/bar-nav.json +1 -1
- package/dist/mcp-data/registry/bar-page-title.json +1 -1
- package/dist/mcp-data/registry/bar-title.json +1 -1
- package/dist/mcp-data/registry/bar-workflow.json +1 -1
- package/dist/mcp-data/registry/breadcrumb.json +1 -1
- package/dist/mcp-data/registry/button-filled.json +1 -1
- package/dist/mcp-data/registry/button-inverted.json +1 -1
- package/dist/mcp-data/registry/button-unfilled.json +1 -1
- package/dist/mcp-data/registry/calendar.json +1 -1
- package/dist/mcp-data/registry/card-action-center.json +1 -1
- package/dist/mcp-data/registry/card-chart.json +1 -1
- package/dist/mcp-data/registry/card-navigation.json +1 -1
- package/dist/mcp-data/registry/card-overview.json +1 -1
- package/dist/mcp-data/registry/card-setting.json +1 -1
- package/dist/mcp-data/registry/card-settings-scope.json +1 -1
- package/dist/mcp-data/registry/chart-legend.json +1 -1
- package/dist/mcp-data/registry/chart.json +1 -1
- package/dist/mcp-data/registry/checkbox.json +1 -1
- package/dist/mcp-data/registry/chip.json +1 -1
- package/dist/mcp-data/registry/code-block.json +1 -1
- package/dist/mcp-data/registry/conversation-list-item.json +1 -1
- package/dist/mcp-data/registry/conversation-list-section.json +1 -1
- package/dist/mcp-data/registry/conversation-list.json +10 -32
- package/dist/mcp-data/registry/data-customize.json +374 -0
- package/dist/mcp-data/registry/{table-filter.json → data-filter.json} +33 -33
- package/dist/mcp-data/registry/data-group.json +358 -0
- package/dist/mcp-data/registry/data-preferences.json +566 -0
- package/dist/mcp-data/registry/data-saved-views.json +433 -0
- package/dist/mcp-data/registry/data-search.json +367 -0
- package/dist/mcp-data/registry/data-sort.json +254 -0
- package/dist/mcp-data/registry/data-toolbar.json +181 -0
- package/dist/mcp-data/registry/divider.json +1 -1
- package/dist/mcp-data/registry/empty-state.json +1 -1
- package/dist/mcp-data/registry/field.json +1 -1
- package/dist/mcp-data/registry/filter-menu.json +3 -3
- package/dist/mcp-data/registry/icon.json +13 -7
- package/dist/mcp-data/registry/input-date.json +1 -1
- package/dist/mcp-data/registry/input-time.json +1 -1
- package/dist/mcp-data/registry/input.json +2 -2
- package/dist/mcp-data/registry/loader.json +1 -1
- package/dist/mcp-data/registry/markdown.json +1 -1
- package/dist/mcp-data/registry/menu.json +3 -3
- package/dist/mcp-data/registry/message-actions.json +1 -1
- package/dist/mcp-data/registry/message-bubble.json +1 -1
- package/dist/mcp-data/registry/message-composer.json +2 -2
- package/dist/mcp-data/registry/message-scroller.json +1 -1
- package/dist/mcp-data/registry/message.json +1 -1
- package/dist/mcp-data/registry/mobile-bar-nav.json +2 -2
- package/dist/mcp-data/registry/mobile-header.json +1 -1
- package/dist/mcp-data/registry/mobile-section-switcher.json +1 -1
- package/dist/mcp-data/registry/mobile-sheet-nav.json +2 -2
- package/dist/mcp-data/registry/modal.json +1 -1
- package/dist/mcp-data/registry/pagination.json +1 -1
- package/dist/mcp-data/registry/panel-nav.json +1 -1
- package/dist/mcp-data/registry/panel-sub-nav.json +1 -1
- package/dist/mcp-data/registry/panel-tool-header.json +1 -1
- package/dist/mcp-data/registry/panel-tool-search.json +1 -1
- package/dist/mcp-data/registry/panel-tools.json +3 -3
- package/dist/mcp-data/registry/paper-texture.json +1 -1
- package/dist/mcp-data/registry/radio.json +1 -1
- package/dist/mcp-data/registry/registry.json +5026 -4864
- package/dist/mcp-data/registry/score.json +1 -1
- package/dist/mcp-data/registry/scroll-overlay.json +1 -1
- package/dist/mcp-data/registry/select.json +1 -1
- package/dist/mcp-data/registry/shell-app.json +1 -1
- package/dist/mcp-data/registry/shell-page.json +1 -1
- package/dist/mcp-data/registry/shell-tools.json +1 -1
- package/dist/mcp-data/registry/skeleton.json +1 -1
- package/dist/mcp-data/registry/slider.json +1 -1
- package/dist/mcp-data/registry/swatch-picker.json +1 -1
- package/dist/mcp-data/registry/switch.json +1 -1
- package/dist/mcp-data/registry/tab-group.json +1 -1
- package/dist/mcp-data/registry/table.json +71 -71
- package/dist/mcp-data/registry/tag.json +1 -1
- package/dist/mcp-data/registry/text.json +1 -1
- package/dist/mcp-data/registry/textarea.json +1 -1
- package/dist/mcp-data/registry/time-picker.json +1 -1
- package/dist/mcp-data/registry/toast.json +1 -1
- package/dist/mcp-data/registry/tooltip-chart.json +1 -1
- package/dist/mcp-data/registry/tooltip.json +1 -1
- package/dist/mcp-data/registry/typing-indicator.json +1 -1
- package/dist/react/components.d.ts +8 -7
- package/dist/react/components.js +8 -7
- package/dist/react/ds-data-customize.d.ts +13 -0
- package/dist/react/ds-data-customize.js +15 -0
- package/dist/react/ds-data-filter.d.ts +18 -0
- package/dist/react/{ds-table-filter.js → ds-data-filter.js} +5 -5
- package/dist/react/ds-data-group.d.ts +14 -0
- package/dist/react/{ds-table-group.js → ds-data-group.js} +5 -5
- package/dist/react/ds-data-preferences.d.ts +21 -0
- package/dist/react/{ds-table-preferences.js → ds-data-preferences.js} +6 -6
- package/dist/react/ds-data-saved-views.d.ts +17 -0
- package/dist/react/{ds-table-saved-views.js → ds-data-saved-views.js} +5 -5
- package/dist/react/ds-data-search.d.ts +14 -0
- package/dist/react/{ds-table-search.js → ds-data-search.js} +5 -5
- package/dist/react/ds-data-sort.d.ts +12 -0
- package/dist/react/ds-data-sort.js +12 -0
- package/dist/react/{ds-table-toolbar.d.ts → ds-data-toolbar.d.ts} +3 -3
- package/dist/react/ds-data-toolbar.js +12 -0
- package/dist/react/ds-table.d.ts +3 -3
- package/dist/react/ds-table.js +1 -1
- package/dist/styles/table.css +11 -11
- package/dist/types/components/ConversationList/ConversationList.d.ts +0 -7
- package/dist/types/components/DataCustomize/DataCustomize.d.ts +67 -0
- package/dist/types/components/{TableFilter/TableFilter.d.ts → DataFilter/DataFilter.d.ts} +2 -2
- package/dist/types/components/{TableGroup/TableGroup.d.ts → DataGroup/DataGroup.d.ts} +8 -8
- package/dist/types/components/{TablePreferences/TablePreferences.d.ts → DataPreferences/DataPreferences.d.ts} +29 -13
- package/dist/types/components/{TableSavedViews/TableSavedViews.d.ts → DataSavedViews/DataSavedViews.d.ts} +10 -10
- package/dist/types/components/DataSavedViews/data-saved-views-types.d.ts +24 -0
- package/dist/types/components/DataSavedViews/index.d.ts +2 -0
- package/dist/types/components/{TableSearch/TableSearch.d.ts → DataSearch/DataSearch.d.ts} +6 -6
- package/dist/types/components/{TableSearch/table-search-model.d.ts → DataSearch/data-search-model.d.ts} +6 -6
- package/dist/types/components/{TableSearch/table-search-types.d.ts → DataSearch/data-search-types.d.ts} +3 -3
- package/dist/types/components/{TableSort/TableSort.d.ts → DataSort/DataSort.d.ts} +7 -6
- package/dist/types/components/DataSort/data-sort-menu.d.ts +15 -0
- package/dist/types/components/{TableToolbar/TableToolbar.d.ts → DataToolbar/DataToolbar.d.ts} +3 -3
- package/dist/types/components/Icon/icon-cache.d.ts +36 -4
- package/dist/types/components/Icon/map-icon-catalog.d.ts +3 -0
- package/dist/types/components/PanelTools/PanelTools.d.ts +1 -1
- package/dist/types/components/Table/Table.d.ts +9 -9
- package/dist/types/components/Table/index.d.ts +1 -1
- package/dist/types/components/Table/table-action-menu.d.ts +1 -1
- package/dist/types/components/Table/table-body-renderer.d.ts +2 -2
- package/dist/types/components/Table/table-column-customizer.d.ts +9 -9
- package/dist/types/components/Table/table-group-load-controller.d.ts +2 -2
- package/dist/types/components/Table/table-model.d.ts +7 -7
- package/dist/types/components/Table/table-render-model.d.ts +3 -3
- package/dist/types/components/Table/table-types.d.ts +17 -36
- package/dist/types/components/Table/table-virtual-model.d.ts +2 -2
- package/dist/types/components.d.ts +3837 -3640
- package/dist/types/utils/data-field.d.ts +38 -0
- package/dist/types/utils/list-customizer.d.ts +38 -0
- package/dist/types/utils/table-caption-compact.d.ts +1 -1
- package/dist/vue/components.d.ts +8 -7
- package/dist/vue/components.js +8 -7
- package/dist/vue/ds-conversation-list.js +1 -3
- package/dist/vue/ds-data-customize.d.ts +3 -0
- package/dist/vue/ds-data-customize.js +23 -0
- package/dist/vue/{ds-table-group.d.ts → ds-data-filter.d.ts} +1 -1
- package/dist/vue/{ds-table-filter.js → ds-data-filter.js} +2 -2
- package/dist/vue/{ds-table-sort.d.ts → ds-data-group.d.ts} +1 -1
- package/dist/vue/{ds-table-group.js → ds-data-group.js} +2 -2
- package/dist/vue/{ds-table-saved-views.d.ts → ds-data-preferences.d.ts} +1 -1
- package/dist/vue/{ds-table-preferences.js → ds-data-preferences.js} +10 -7
- package/dist/vue/ds-data-saved-views.d.ts +3 -0
- package/dist/vue/{ds-table-saved-views.js → ds-data-saved-views.js} +2 -2
- package/dist/vue/{ds-table-filter.d.ts → ds-data-search.d.ts} +1 -1
- package/dist/vue/{ds-table-search.js → ds-data-search.js} +3 -3
- package/dist/vue/{ds-table-search.d.ts → ds-data-sort.d.ts} +1 -1
- package/dist/vue/{ds-table-sort.js → ds-data-sort.js} +3 -3
- package/dist/vue/ds-data-toolbar.d.ts +3 -0
- package/dist/vue/ds-data-toolbar.js +9 -0
- package/dist/vue/ds-table.js +4 -4
- package/package.json +3 -3
- package/dist/angular/ds-table-filter.d.ts +0 -50
- package/dist/angular/ds-table-group.d.ts +0 -29
- package/dist/angular/ds-table-preferences.d.ts +0 -39
- package/dist/angular/ds-table-saved-views.d.ts +0 -49
- package/dist/angular/ds-table-search.d.ts +0 -20
- package/dist/angular/ds-table-sort.d.ts +0 -16
- package/dist/angular/ds-table-toolbar.d.ts +0 -12
- package/dist/components/ds-table-filter.js +0 -2
- package/dist/components/ds-table-filter.js.map +0 -1
- package/dist/components/ds-table-group.js +0 -2
- package/dist/components/ds-table-preferences.d.ts +0 -11
- package/dist/components/ds-table-preferences.js +0 -2
- package/dist/components/ds-table-preferences.js.map +0 -1
- package/dist/components/ds-table-saved-views.js +0 -2
- package/dist/components/ds-table-saved-views.js.map +0 -1
- package/dist/components/ds-table-search.js +0 -2
- package/dist/components/ds-table-search.js.map +0 -1
- package/dist/components/ds-table-sort.js +0 -2
- package/dist/components/ds-table-sort.js.map +0 -1
- package/dist/components/ds-table-toolbar.d.ts +0 -11
- package/dist/components/ds-table-toolbar.js +0 -2
- package/dist/components/ds-table-toolbar.js.map +0 -1
- package/dist/components/p-BOhpMUwO.js +0 -2
- package/dist/components/p-C0CE2v5D.js +0 -2
- package/dist/components/p-CKarsuR2.js +0 -2
- package/dist/components/p-CKarsuR2.js.map +0 -1
- package/dist/components/p-CQIh2yRP.js.map +0 -1
- package/dist/components/p-Cea7rROU.js +0 -2
- package/dist/components/p-Cea7rROU.js.map +0 -1
- package/dist/components/p-D7yBIPB6.js +0 -2
- package/dist/components/p-DtkLtKY0.js.map +0 -1
- package/dist/components/p-KBrC9IG4.js +0 -2
- package/dist/components/p-KBrC9IG4.js.map +0 -1
- package/dist/components/p-MQ36mEgn.js +0 -2
- package/dist/components/p-MQ36mEgn.js.map +0 -1
- package/dist/components/p-TjXGRPik.js +0 -2
- package/dist/components/p-bM3LH3kc.js +0 -2
- package/dist/components/p-bM3LH3kc.js.map +0 -1
- package/dist/mcp-data/registry/table-group.json +0 -358
- package/dist/mcp-data/registry/table-preferences.json +0 -511
- package/dist/mcp-data/registry/table-saved-views.json +0 -433
- package/dist/mcp-data/registry/table-search.json +0 -366
- package/dist/mcp-data/registry/table-sort.json +0 -253
- package/dist/mcp-data/registry/table-toolbar.json +0 -180
- package/dist/react/ds-table-filter.d.ts +0 -18
- package/dist/react/ds-table-group.d.ts +0 -14
- package/dist/react/ds-table-preferences.d.ts +0 -21
- package/dist/react/ds-table-saved-views.d.ts +0 -17
- package/dist/react/ds-table-search.d.ts +0 -14
- package/dist/react/ds-table-sort.d.ts +0 -12
- package/dist/react/ds-table-sort.js +0 -12
- package/dist/react/ds-table-toolbar.js +0 -12
- package/dist/types/components/TableSavedViews/index.d.ts +0 -2
- package/dist/types/components/TableSavedViews/table-saved-views-types.d.ts +0 -24
- package/dist/types/components/TableSort/table-sort-menu.d.ts +0 -15
- package/dist/vue/ds-table-preferences.d.ts +0 -3
- package/dist/vue/ds-table-toolbar.d.ts +0 -3
- package/dist/vue/ds-table-toolbar.js +0 -9
- /package/dist/components/{ds-table-group.js.map → ds-data-group.js.map} +0 -0
- /package/dist/components/{p-D8rpKod8.js.map → p-0FYD2bev.js.map} +0 -0
- /package/dist/components/{p-DK9Ex3aY.js.map → p-5URekSny.js.map} +0 -0
- /package/dist/components/{p-Ds51RgCi.js.map → p-7V1AhetH.js.map} +0 -0
- /package/dist/components/{p-C2JnoaWI.js.map → p-8yBdCXCn.js.map} +0 -0
- /package/dist/components/{p-su6y4hLK.js.map → p-BciTtTwx.js.map} +0 -0
- /package/dist/components/{p-CQ5RwY2C.js.map → p-BhJXmuRA.js.map} +0 -0
- /package/dist/components/{p-neWTRxmf.js.map → p-Bm7rqs3C.js.map} +0 -0
- /package/dist/components/{p-BV5T1hzN.js.map → p-Bn8I7iw6.js.map} +0 -0
- /package/dist/components/{p-PmcUwTQ_.js.map → p-Bpd6YCo4.js.map} +0 -0
- /package/dist/components/{p-C4m8y9ki.js.map → p-CD4DZPy_.js.map} +0 -0
- /package/dist/components/{p-B27_chI7.js.map → p-CElUM-xU.js.map} +0 -0
- /package/dist/components/{p-CuwopElg.js.map → p-CGidq1iC.js.map} +0 -0
- /package/dist/components/{p-CWog26I_.js.map → p-CNxvnQ6A.js.map} +0 -0
- /package/dist/components/{p-2GVGhrh0.js.map → p-CUcUHwI3.js.map} +0 -0
- /package/dist/components/{p-CbSUyv5B.js.map → p-CYzFfFcH.js.map} +0 -0
- /package/dist/components/{p-Jaqdfw4E.js.map → p-CiH4GG6r.js.map} +0 -0
- /package/dist/components/{p-Cl9phSf0.js.map → p-CiJ1WR11.js.map} +0 -0
- /package/dist/components/{p-Cus1Sigh.js.map → p-CmexIVnE.js.map} +0 -0
- /package/dist/components/{p-DLXXGgmf.js.map → p-CzIpquvw.js.map} +0 -0
- /package/dist/components/{p-tNQ0YulU.js.map → p-D0y7Sja6.js.map} +0 -0
- /package/dist/components/{p-Dryt3COt.js.map → p-D6Wl3dRO.js.map} +0 -0
- /package/dist/components/{p-ji09W9el.js.map → p-D922f6Tb.js.map} +0 -0
- /package/dist/components/{p-CaNCGKEJ.js.map → p-DHICPS4n.js.map} +0 -0
- /package/dist/components/{p-Cga6Ex0E.js.map → p-DOAybCp0.js.map} +0 -0
- /package/dist/components/{p-7O-2D29W.js.map → p-DVOjjuXc.js.map} +0 -0
- /package/dist/components/{p-DVd1TIxi.js.map → p-Dn9QHL4O.js.map} +0 -0
- /package/dist/components/{p-C-dHtQMi.js.map → p-Do2FJd1y.js.map} +0 -0
- /package/dist/components/{p-BWfzaSc3.js.map → p-DpoTwJAR.js.map} +0 -0
- /package/dist/components/{p-BgLI9JoT.js.map → p-DwbcNDJF.js.map} +0 -0
- /package/dist/components/{p-DvzI2A_M.js.map → p-E5W27Fu_.js.map} +0 -0
- /package/dist/components/{p-DkfM55x8.js.map → p-FIBCluwV.js.map} +0 -0
- /package/dist/components/{p-8oRkhvjy.js.map → p-MG4lcN0D.js.map} +0 -0
- /package/dist/components/{p-DBwa1OXP.js.map → p-ZhP2tVmM.js.map} +0 -0
- /package/dist/components/{p-J5x-QtlD.js.map → p-etifxiDc.js.map} +0 -0
- /package/dist/components/{p-rYePOPbJ.js.map → p-ljbw3UMZ.js.map} +0 -0
- /package/dist/components/{p-DZ58Sg5a.js.map → p-vfCu7XSc.js.map} +0 -0
- /package/dist/components/{p-Ce4zy8q1.js.map → p-xdmJCPCg.js.map} +0 -0
- /package/dist/components/{p-CDJ2Ntcq.js.map → p-xtGGIZmU.js.map} +0 -0
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
"peerDependencies": {
|
|
133
133
|
"required": [
|
|
134
134
|
"@ds-mo/tokens ^6.5.1",
|
|
135
|
-
"@ds-mo/icons ^
|
|
135
|
+
"@ds-mo/icons ^8.1.0"
|
|
136
136
|
],
|
|
137
137
|
"frameworks": "Custom Elements; React 18/19 wrappers; Vue 3 wrappers; Angular 19-22 standalone adapters."
|
|
138
138
|
}
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
},
|
|
157
157
|
{
|
|
158
158
|
"path": "src/wc/components/AgentActivity/AgentActivity.tsx",
|
|
159
|
-
"content": "import { Component, Prop, State, Watch, h, Host } from '@stencil/core';\nimport type { AgentActivityItem } from '../conversation-types';\n\n@Component({\n tag: 'ds-agent-activity',\n styleUrl: 'AgentActivity.css',\n scoped: true,\n})\nexport class AgentActivity {\n @Prop() items: AgentActivityItem[] = [];\n @Prop() heading: string = 'Activity';\n @Prop() open: boolean = false;\n\n @State() private expanded: boolean = false;\n\n componentWillLoad() {\n this.expanded = this.open;\n }\n\n @Watch('open')\n handleOpenChange(open: boolean) {\n this.expanded = open;\n }\n\n private get currentItem(): AgentActivityItem | undefined {\n return (\n this.items.find(item => item.state === 'active') ??\n this.items.find(item => item.state === 'error') ??\n [...this.items].reverse().find(item => item.state === 'complete') ??\n this.items.find(item => item.state === 'pending')\n );\n }\n\n private handleToggle = (event: Event) => {\n this.expanded = (event.currentTarget as HTMLDetailsElement).open;\n };\n\n private stateLabel(item: AgentActivityItem): string {\n if (item.state === 'active') return 'In progress';\n if (item.state === 'complete') return 'Complete';\n if (item.state === 'error') return 'Error';\n return 'Pending';\n }\n\n render() {\n return (\n <Host>\n <details class=\"agent-activity\" open={this.open} onToggle={this.handleToggle}>\n <summary>\n <ds-icon name=\"ChevronRight\" size=\"xs\" color=\"inherit\" />\n <ds-text\n class=\"agent-activity__summary-label\"\n variant=\"text-body-small\"\n shimmer={!this.expanded && this.currentItem?.state === 'active'}\n >\n {this.expanded ? this.heading : (this.currentItem?.label ?? this.heading)}\n </ds-text>\n </summary>\n <ol>\n {this.items.map(item => (\n <li class={`agent-activity__item agent-activity__item--${item.state}`}>\n <span class=\"agent-activity__marker\" aria-hidden=\"true\">\n {item.state === 'active' ? (\n <ds-loader size=\"xs\" color=\"inherit\" />\n ) : item.state === 'pending' ? (\n <span class=\"agent-activity__pending-dot\" />\n ) : (\n <ds-icon\n name={item.state === 'error' ? '
|
|
159
|
+
"content": "import { Component, Prop, State, Watch, h, Host } from '@stencil/core';\nimport type { AgentActivityItem } from '../conversation-types';\n\n@Component({\n tag: 'ds-agent-activity',\n styleUrl: 'AgentActivity.css',\n scoped: true,\n})\nexport class AgentActivity {\n @Prop() items: AgentActivityItem[] = [];\n @Prop() heading: string = 'Activity';\n @Prop() open: boolean = false;\n\n @State() private expanded: boolean = false;\n\n componentWillLoad() {\n this.expanded = this.open;\n }\n\n @Watch('open')\n handleOpenChange(open: boolean) {\n this.expanded = open;\n }\n\n private get currentItem(): AgentActivityItem | undefined {\n return (\n this.items.find(item => item.state === 'active') ??\n this.items.find(item => item.state === 'error') ??\n [...this.items].reverse().find(item => item.state === 'complete') ??\n this.items.find(item => item.state === 'pending')\n );\n }\n\n private handleToggle = (event: Event) => {\n this.expanded = (event.currentTarget as HTMLDetailsElement).open;\n };\n\n private stateLabel(item: AgentActivityItem): string {\n if (item.state === 'active') return 'In progress';\n if (item.state === 'complete') return 'Complete';\n if (item.state === 'error') return 'Error';\n return 'Pending';\n }\n\n render() {\n return (\n <Host>\n <details class=\"agent-activity\" open={this.open} onToggle={this.handleToggle}>\n <summary>\n <ds-icon name=\"ChevronRight\" size=\"xs\" color=\"inherit\" />\n <ds-text\n class=\"agent-activity__summary-label\"\n variant=\"text-body-small\"\n shimmer={!this.expanded && this.currentItem?.state === 'active'}\n >\n {this.expanded ? this.heading : (this.currentItem?.label ?? this.heading)}\n </ds-text>\n </summary>\n <ol>\n {this.items.map(item => (\n <li class={`agent-activity__item agent-activity__item--${item.state}`}>\n <span class=\"agent-activity__marker\" aria-hidden=\"true\">\n {item.state === 'active' ? (\n <ds-loader size=\"xs\" color=\"inherit\" />\n ) : item.state === 'pending' ? (\n <span class=\"agent-activity__pending-dot\" />\n ) : (\n <ds-icon\n name={item.state === 'error' ? 'ExclamationTriangle' : 'Check'}\n size=\"xs\"\n color=\"inherit\"\n />\n )}\n </span>\n <span>\n <ds-text variant=\"text-body-small\" shimmer={item.state === 'active'}>\n {item.label}\n </ds-text>\n {item.detail ? (\n <ds-text variant=\"text-caption\" color=\"secondary\">\n {item.detail}\n </ds-text>\n ) : null}\n <span class=\"agent-activity__state ds-visually-hidden\">\n {this.stateLabel(item)}\n </span>\n </span>\n </li>\n ))}\n </ol>\n </details>\n </Host>\n );\n }\n}\n",
|
|
160
160
|
"type": "registry:ui"
|
|
161
161
|
}
|
|
162
162
|
]
|
|
@@ -237,7 +237,7 @@
|
|
|
237
237
|
"peerDependencies": {
|
|
238
238
|
"required": [
|
|
239
239
|
"@ds-mo/tokens ^6.5.1",
|
|
240
|
-
"@ds-mo/icons ^
|
|
240
|
+
"@ds-mo/icons ^8.1.0"
|
|
241
241
|
],
|
|
242
242
|
"frameworks": "Custom Elements; React 18/19 wrappers; Vue 3 wrappers; Angular 19-22 standalone adapters."
|
|
243
243
|
}
|
|
@@ -266,7 +266,7 @@
|
|
|
266
266
|
},
|
|
267
267
|
{
|
|
268
268
|
"path": "src/wc/components/AgentQuestionnaire/AgentQuestionnaire.tsx",
|
|
269
|
-
"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 { AgentQuestionDraft, AgentQuestionDrafts } 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 =\n 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(question => !this.validateWithoutFocus(question));\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(question: AgentQuestion, promptId: string, errorId: string) {\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 ? [{ value: this.otherValue, label: this.copy.other }] : []),\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>) => this.selectSingle(question, event.detail)}\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.querySelector<HTMLInputElement>('[data-question-other-input]')?.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>\n {question.question}\n </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\">\n {this.progressLabel()}\n </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\">\n {this.errorMessage}\n </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",
|
|
269
|
+
"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 { AgentQuestionDraft, AgentQuestionDrafts } 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 =\n 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(question => !this.validateWithoutFocus(question));\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(question: AgentQuestion, promptId: string, errorId: string) {\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 ? [{ value: this.otherValue, label: this.copy.other }] : []),\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>) => this.selectSingle(question, event.detail)}\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.querySelector<HTMLInputElement>('[data-question-other-input]')?.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=\"ExclamationTriangle\" 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>\n {question.question}\n </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\">\n {this.progressLabel()}\n </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=\"ExclamationTriangle\" size=\"xs\" color=\"inherit\" />\n <ds-text variant=\"text-body-small\" color=\"negative\">\n {this.errorMessage}\n </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",
|
|
270
270
|
"type": "registry:ui"
|
|
271
271
|
},
|
|
272
272
|
{
|
|
@@ -228,7 +228,7 @@
|
|
|
228
228
|
"peerDependencies": {
|
|
229
229
|
"required": [
|
|
230
230
|
"@ds-mo/tokens ^6.5.1",
|
|
231
|
-
"@ds-mo/icons ^
|
|
231
|
+
"@ds-mo/icons ^8.1.0"
|
|
232
232
|
],
|
|
233
233
|
"frameworks": "Custom Elements; React 18/19 wrappers; Vue 3 wrappers; Angular 19-22 standalone adapters."
|
|
234
234
|
}
|
|
@@ -252,7 +252,7 @@
|
|
|
252
252
|
},
|
|
253
253
|
{
|
|
254
254
|
"path": "src/wc/components/AgentToolCall/AgentToolCall.tsx",
|
|
255
|
-
"content": "import { Component, Element, Event, EventEmitter, h, Host, Prop, State } from '@stencil/core';\nimport type { AgentToolState } from '../conversation-types';\n\nconst STATUS_LABELS: Record<AgentToolState, string> = {\n preparing: 'Preparing',\n queued: 'Queued',\n running: 'Running',\n 'waiting-for-user': 'Waiting for your response',\n success: 'Completed',\n error: 'Failed',\n denied: 'Permission denied',\n canceled: 'Canceled',\n};\n\n@Component({ tag: 'ds-agent-tool-call', styleUrl: 'AgentToolCall.css', scoped: true })\nexport class AgentToolCall {\n @Element() el!: HTMLElement;\n\n @Prop() name: string = '';\n @Prop() label: string = '';\n @Prop() state: AgentToolState = 'queued';\n @Prop() statusLabel?: string;\n @Prop() input?: unknown;\n @Prop() output?: unknown;\n @Prop() error?: string;\n @Prop() open: boolean = false;\n\n @Event() dsOpenChange!: EventEmitter<{ open: boolean }>;\n\n @State() private hasSummary = false;\n @State() private hasResult = false;\n @State() private hasPlainTextResult = false;\n @State() private hasDetails = false;\n\n private slotObserver?: MutationObserver;\n\n componentWillLoad() {\n this.syncSlots();\n }\n\n componentDidLoad() {\n this.syncSlots();\n this.slotObserver = new MutationObserver(() => this.syncSlots());\n this.slotObserver.observe(this.el, {\n childList: true,\n subtree: false,\n attributes: true,\n attributeFilter: ['slot'],\n });\n }\n\n disconnectedCallback() {\n this.slotObserver?.disconnect();\n }\n\n private syncSlots() {\n this.hasSummary = Boolean(this.el.querySelector('[slot=\"summary\"]'));\n const result = this.el.querySelector<HTMLElement>('[slot=\"result\"]');\n this.hasResult = Boolean(result);\n this.hasPlainTextResult = Boolean(\n result && result.childElementCount === 0 && result.textContent?.trim()\n );\n this.hasDetails = Boolean(this.el.querySelector('[slot=\"details\"]'));\n }\n\n private serialize(value: unknown) {\n if (value === undefined) return '';\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n }\n\n private get active(): boolean {\n return ['preparing', 'queued', 'running'].includes(this.state);\n }\n\n private get expandable(): boolean {\n return (\n this.hasDetails ||\n this.input !== undefined ||\n this.output !== undefined ||\n Boolean(this.error)\n );\n }\n\n private renderStatusIcon() {\n if (this.active) return <ds-loader size=\"xs\" color=\"inherit\" />;\n if (this.state === 'success') {\n return <ds-icon name=\"Check\" size=\"xs\" color=\"inherit\" />;\n }\n if (this.state === 'waiting-for-user') {\n return <ds-icon name=\"Clock\" size=\"xs\" color=\"inherit\" />;\n }\n return <ds-icon name=\"
|
|
255
|
+
"content": "import { Component, Element, Event, EventEmitter, h, Host, Prop, State } from '@stencil/core';\nimport type { AgentToolState } from '../conversation-types';\n\nconst STATUS_LABELS: Record<AgentToolState, string> = {\n preparing: 'Preparing',\n queued: 'Queued',\n running: 'Running',\n 'waiting-for-user': 'Waiting for your response',\n success: 'Completed',\n error: 'Failed',\n denied: 'Permission denied',\n canceled: 'Canceled',\n};\n\n@Component({ tag: 'ds-agent-tool-call', styleUrl: 'AgentToolCall.css', scoped: true })\nexport class AgentToolCall {\n @Element() el!: HTMLElement;\n\n @Prop() name: string = '';\n @Prop() label: string = '';\n @Prop() state: AgentToolState = 'queued';\n @Prop() statusLabel?: string;\n @Prop() input?: unknown;\n @Prop() output?: unknown;\n @Prop() error?: string;\n @Prop() open: boolean = false;\n\n @Event() dsOpenChange!: EventEmitter<{ open: boolean }>;\n\n @State() private hasSummary = false;\n @State() private hasResult = false;\n @State() private hasPlainTextResult = false;\n @State() private hasDetails = false;\n\n private slotObserver?: MutationObserver;\n\n componentWillLoad() {\n this.syncSlots();\n }\n\n componentDidLoad() {\n this.syncSlots();\n this.slotObserver = new MutationObserver(() => this.syncSlots());\n this.slotObserver.observe(this.el, {\n childList: true,\n subtree: false,\n attributes: true,\n attributeFilter: ['slot'],\n });\n }\n\n disconnectedCallback() {\n this.slotObserver?.disconnect();\n }\n\n private syncSlots() {\n this.hasSummary = Boolean(this.el.querySelector('[slot=\"summary\"]'));\n const result = this.el.querySelector<HTMLElement>('[slot=\"result\"]');\n this.hasResult = Boolean(result);\n this.hasPlainTextResult = Boolean(\n result && result.childElementCount === 0 && result.textContent?.trim()\n );\n this.hasDetails = Boolean(this.el.querySelector('[slot=\"details\"]'));\n }\n\n private serialize(value: unknown) {\n if (value === undefined) return '';\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n }\n\n private get active(): boolean {\n return ['preparing', 'queued', 'running'].includes(this.state);\n }\n\n private get expandable(): boolean {\n return (\n this.hasDetails ||\n this.input !== undefined ||\n this.output !== undefined ||\n Boolean(this.error)\n );\n }\n\n private renderStatusIcon() {\n if (this.active) return <ds-loader size=\"xs\" color=\"inherit\" />;\n if (this.state === 'success') {\n return <ds-icon name=\"Check\" size=\"xs\" color=\"inherit\" />;\n }\n if (this.state === 'waiting-for-user') {\n return <ds-icon name=\"Clock\" size=\"xs\" color=\"inherit\" />;\n }\n return <ds-icon name=\"ExclamationTriangle\" size=\"xs\" color=\"inherit\" />;\n }\n\n private renderSummary(expandable: boolean) {\n return (\n <span class=\"agent-tool__summary-content\">\n <span class=\"agent-tool__status-icon\" aria-hidden=\"true\">\n {this.renderStatusIcon()}\n </span>\n <span class=\"agent-tool__title\">\n {this.hasSummary ? (\n <slot name=\"summary\" />\n ) : (\n <ds-text as=\"span\" variant=\"text-body-small\" emphasis>\n {this.label || this.name}\n </ds-text>\n )}\n <ds-text\n class=\"agent-tool__state-label\"\n as=\"span\"\n variant=\"text-caption\"\n color={['error', 'denied'].includes(this.state) ? 'negative' : 'secondary'}\n >\n {this.statusLabel ?? STATUS_LABELS[this.state]}\n </ds-text>\n </span>\n {expandable ? (\n <ds-icon class=\"agent-tool__chevron\" name=\"ChevronRight\" size=\"xs\" color=\"inherit\" />\n ) : null}\n </span>\n );\n }\n\n private renderGenericDetails() {\n return (\n <div class=\"agent-tool__diagnostics\">\n {this.input !== undefined ? (\n <section>\n <ds-text variant=\"text-caption\" emphasis>\n Input\n </ds-text>\n <pre>{this.serialize(this.input)}</pre>\n </section>\n ) : null}\n {this.output !== undefined ? (\n <section>\n <ds-text variant=\"text-caption\" emphasis>\n Output\n </ds-text>\n <pre>{this.serialize(this.output)}</pre>\n </section>\n ) : null}\n {this.error ? (\n <section>\n <ds-text variant=\"text-caption\" emphasis>\n Error\n </ds-text>\n <pre>{this.error}</pre>\n </section>\n ) : null}\n </div>\n );\n }\n\n private handleToggle = (event: Event) => {\n this.dsOpenChange.emit({ open: (event.currentTarget as HTMLDetailsElement).open });\n };\n\n render() {\n const expandable = this.expandable;\n return (\n <Host>\n <div class={`agent-tool agent-tool--${this.state}`}>\n {expandable ? (\n <details open={this.open} onToggle={this.handleToggle}>\n <summary>{this.renderSummary(true)}</summary>\n <div class=\"agent-tool__details\">\n {this.hasDetails ? <slot name=\"details\" /> : this.renderGenericDetails()}\n </div>\n </details>\n ) : (\n <div class=\"agent-tool__row\">{this.renderSummary(false)}</div>\n )}\n {this.hasResult ? (\n <div\n class={{\n 'agent-tool__result': true,\n 'agent-tool__result--plain-text': this.hasPlainTextResult,\n }}\n >\n <slot name=\"result\" />\n </div>\n ) : null}\n </div>\n </Host>\n );\n }\n}\n",
|
|
256
256
|
"type": "registry:ui"
|
|
257
257
|
}
|
|
258
258
|
]
|
|
@@ -23,8 +23,7 @@
|
|
|
23
23
|
"commonlyComposedWith": [
|
|
24
24
|
"component:ds-conversation-list-section",
|
|
25
25
|
"component:ds-conversation-list-item",
|
|
26
|
-
"component:ds-empty-state"
|
|
27
|
-
"component:ds-scroll-overlay"
|
|
26
|
+
"component:ds-empty-state"
|
|
28
27
|
],
|
|
29
28
|
"patterns": [
|
|
30
29
|
"pattern:conversation"
|
|
@@ -34,14 +33,13 @@
|
|
|
34
33
|
"Keep the empty message descriptive and every persistent action explicitly named."
|
|
35
34
|
],
|
|
36
35
|
"states": [
|
|
37
|
-
"The
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"ConversationList paints its measured fade on a separate surface-aware layer so contextual row actions retain a real backdrop for blur; hovered, focused, and menu-open rows rise above that decorative fade.",
|
|
36
|
+
"The action stays at the lower end corner, inset 16px from both edges.",
|
|
37
|
+
"Slot an icon-only rounded button; the corner action is the single supported placement, so a full-width labelled action no longer has a layout to sit in.",
|
|
38
|
+
"Rows scroll beneath the action. The list reserves no end clearance and paints no fade, so it keeps its full height whether or not an action is slotted.",
|
|
41
39
|
"The persistent action wrapper splits its md outer shadow from a top inset-highlight overlay so opaque filled actions keep the complete TokoMo elevation; slotted buttons disable optional resting borders and the press-scale modifier moves the button and elevated surface as one unit."
|
|
42
40
|
],
|
|
43
41
|
"responsiveBehavior": [
|
|
44
|
-
"The list fills its owner, scrolls independently, and
|
|
42
|
+
"The list fills its owner, scrolls independently, and floats its corner action above scrolling rows."
|
|
45
43
|
],
|
|
46
44
|
"references": [
|
|
47
45
|
{
|
|
@@ -51,32 +49,12 @@
|
|
|
51
49
|
]
|
|
52
50
|
},
|
|
53
51
|
"api": {
|
|
54
|
-
"props": {
|
|
55
|
-
"actionLayout": {
|
|
56
|
-
"type": "ConversationListActionLayout",
|
|
57
|
-
"resolvedType": "\"floating\" | \"footer\"",
|
|
58
|
-
"attribute": "action-layout",
|
|
59
|
-
"default": "'floating'",
|
|
60
|
-
"required": false,
|
|
61
|
-
"mutable": false,
|
|
62
|
-
"description": "Corner icon action or full-width persistent footer action."
|
|
63
|
-
}
|
|
64
|
-
},
|
|
52
|
+
"props": {},
|
|
65
53
|
"events": [],
|
|
66
54
|
"methods": [],
|
|
67
55
|
"slots": []
|
|
68
56
|
},
|
|
69
|
-
"props": {
|
|
70
|
-
"actionLayout": {
|
|
71
|
-
"type": "ConversationListActionLayout",
|
|
72
|
-
"resolvedType": "\"floating\" | \"footer\"",
|
|
73
|
-
"attribute": "action-layout",
|
|
74
|
-
"default": "'floating'",
|
|
75
|
-
"required": false,
|
|
76
|
-
"mutable": false,
|
|
77
|
-
"description": "Corner icon action or full-width persistent footer action."
|
|
78
|
-
}
|
|
79
|
-
},
|
|
57
|
+
"props": {},
|
|
80
58
|
"events": [],
|
|
81
59
|
"methods": [],
|
|
82
60
|
"slots": [],
|
|
@@ -108,7 +86,7 @@
|
|
|
108
86
|
"peerDependencies": {
|
|
109
87
|
"required": [
|
|
110
88
|
"@ds-mo/tokens ^6.5.1",
|
|
111
|
-
"@ds-mo/icons ^
|
|
89
|
+
"@ds-mo/icons ^8.1.0"
|
|
112
90
|
],
|
|
113
91
|
"frameworks": "Custom Elements; React 18/19 wrappers; Vue 3 wrappers; Angular 19-22 standalone adapters."
|
|
114
92
|
}
|
|
@@ -122,12 +100,12 @@
|
|
|
122
100
|
"files": [
|
|
123
101
|
{
|
|
124
102
|
"path": "src/wc/components/ConversationList/ConversationList.css",
|
|
125
|
-
"content": "@import '../../styles/control-elevation.css';\n\n:host {\n display: block;\n position: relative;\n width: 100%;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n -webkit-user-select: none;\n user-select: none;\n}\n\n.conversation-list {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n}\n\n.conversation-list__viewport {\n position: relative;\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n box-sizing: border-box;\n}\n\n.conversation-list__content {\n position: relative;\n min-height: 100%;\n padding: var(--dimension-space-100);\n
|
|
103
|
+
"content": "@import '../../styles/control-elevation.css';\n\n:host {\n display: block;\n position: relative;\n width: 100%;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n -webkit-user-select: none;\n user-select: none;\n}\n\n.conversation-list {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n}\n\n.conversation-list__viewport {\n position: relative;\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n box-sizing: border-box;\n}\n\n.conversation-list__content {\n position: relative;\n min-height: 100%;\n padding: var(--dimension-space-100);\n box-sizing: border-box;\n}\n\n.conversation-list__empty {\n position: absolute;\n inset: 0;\n box-sizing: border-box;\n}\n\n/* The named slot itself keeps this wrapper from matching :empty. Only create\n its full-size hit area when assigned empty-state content is actually here. */\n.conversation-list__empty:not(:has([slot='empty'])) {\n display: none;\n}\n\n/* Corner action. Rows scroll beneath it — there is no reserved clearance and no\n fade, so the list keeps its full height whether or not an action is slotted. */\n.conversation-list__actions {\n position: absolute;\n right: 0;\n bottom: 0;\n z-index: var(--dimension-z-index-floating);\n padding: 0 var(--dimension-space-200) var(--dimension-space-200) 0;\n}\n\n.conversation-list__actions-surface {\n display: flex;\n border-radius: var(--dimension-radius-half);\n}\n\n.conversation-list__actions-surface:empty {\n display: none;\n}\n",
|
|
126
104
|
"type": "registry:ui"
|
|
127
105
|
},
|
|
128
106
|
{
|
|
129
107
|
"path": "src/wc/components/ConversationList/ConversationList.tsx",
|
|
130
|
-
"content": "import { Component, Element, h, Host
|
|
108
|
+
"content": "import { Component, Element, h, Host } from '@stencil/core';\n\n@Component({\n tag: 'ds-conversation-list',\n styleUrl: 'ConversationList.css',\n scoped: true,\n})\nexport class ConversationList {\n @Element() el!: HTMLElement;\n\n private empty?: HTMLElement;\n private emptySlotObserver?: MutationObserver;\n\n componentDidLoad(): void {\n this.syncEmptyStateLayout();\n this.emptySlotObserver = new MutationObserver(this.syncEmptyStateLayout);\n this.emptySlotObserver.observe(this.el, { childList: true, subtree: true });\n }\n\n disconnectedCallback(): void {\n this.emptySlotObserver?.disconnect();\n }\n\n private syncEmptyStateLayout = (): void => {\n const emptyState = this.el.querySelector<HTMLElement>('[slot=\"empty\"]');\n if (emptyState && !this.empty?.contains(emptyState)) {\n // Stencil's scoped-slot runtime does not relocate nodes appended after\n // hydration. Keep that dynamic fallback aligned with the CSS-owned\n // wrapper used by declarative slot content.\n emptyState.style.setProperty('position', 'absolute');\n emptyState.style.setProperty('inset-block-start', '0');\n emptyState.style.setProperty('inset-inline', '0');\n emptyState.style.setProperty('inset-block-end', '0');\n emptyState.style.setProperty('height', 'auto');\n emptyState.style.setProperty('box-sizing', 'border-box');\n }\n };\n\n render() {\n return (\n <Host>\n <div class=\"conversation-list\">\n <div class=\"conversation-list__viewport\">\n <div class=\"conversation-list__content\">\n <slot />\n <div\n class=\"conversation-list__empty\"\n ref={element => {\n this.empty = element;\n }}\n >\n <slot name=\"empty\" />\n </div>\n </div>\n </div>\n <div class=\"conversation-list__actions\">\n <div class=\"conversation-list__actions-surface ds-control-elevation ds-control-elevation--md ds-control-elevation--press-scale\">\n <slot name=\"actions\" />\n </div>\n </div>\n </div>\n </Host>\n );\n }\n}\n",
|
|
131
109
|
"type": "registry:ui"
|
|
132
110
|
}
|
|
133
111
|
]
|