@ds-mo/ui 13.3.0 → 13.4.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 +14 -1
- package/dist/agent.json +108 -8
- package/dist/angular/boolean-value-accessor.js +3 -3
- package/dist/angular/ds-agent-activity.js +3 -3
- package/dist/angular/ds-agent-response.d.ts +1 -1
- package/dist/angular/ds-agent-response.js +5 -5
- package/dist/angular/ds-agent-source-list.js +3 -3
- package/dist/angular/ds-agent-tool-call.js +3 -3
- package/dist/angular/ds-attachment-list.js +3 -3
- package/dist/angular/ds-avatar.js +3 -3
- package/dist/angular/ds-badge.js +3 -3
- package/dist/angular/ds-bar-nav.js +3 -3
- package/dist/angular/ds-bar-title.js +3 -3
- package/dist/angular/ds-bar-workflow.js +3 -3
- package/dist/angular/ds-breadcrumb.js +3 -3
- package/dist/angular/ds-button-filled.js +3 -3
- package/dist/angular/ds-button-unfilled.js +3 -3
- package/dist/angular/ds-card-data-viz.js +3 -3
- package/dist/angular/ds-card-overview.js +3 -3
- package/dist/angular/ds-card-setting.js +3 -3
- package/dist/angular/ds-chart-bar.js +3 -3
- package/dist/angular/ds-chart-donut.js +3 -3
- package/dist/angular/ds-chart-legend.js +3 -3
- package/dist/angular/ds-chart-line.js +3 -3
- package/dist/angular/ds-checkbox.js +3 -3
- package/dist/angular/ds-chip.js +3 -3
- package/dist/angular/ds-code-block.js +3 -3
- package/dist/angular/ds-conversation-list-item.js +3 -3
- package/dist/angular/ds-conversation-list-section.js +3 -3
- package/dist/angular/ds-conversation-list.js +3 -3
- package/dist/angular/ds-divider.js +3 -3
- package/dist/angular/ds-empty-state.js +3 -3
- package/dist/angular/ds-field.js +3 -3
- package/dist/angular/ds-icon.js +3 -3
- package/dist/angular/ds-input.js +3 -3
- package/dist/angular/ds-loader.js +3 -3
- package/dist/angular/ds-markdown.js +3 -3
- package/dist/angular/ds-menu.js +3 -3
- package/dist/angular/ds-message-actions.d.ts +19 -0
- package/dist/angular/ds-message-actions.js +45 -0
- package/dist/angular/ds-message-bubble.js +3 -3
- package/dist/angular/ds-message-composer.js +3 -3
- package/dist/angular/ds-message-scroller.js +3 -3
- package/dist/angular/ds-message.d.ts +1 -1
- package/dist/angular/ds-message.js +5 -5
- package/dist/angular/ds-mobile-bar-nav.js +3 -3
- package/dist/angular/ds-mobile-header.js +3 -3
- package/dist/angular/ds-mobile-section-switcher.js +3 -3
- package/dist/angular/ds-mobile-sheet-nav.js +3 -3
- package/dist/angular/ds-modal.js +3 -3
- package/dist/angular/ds-panel-nav.js +3 -3
- package/dist/angular/ds-panel-sub-nav.js +3 -3
- package/dist/angular/ds-panel-tool-header.js +3 -3
- package/dist/angular/ds-panel-tool-search.js +3 -3
- package/dist/angular/ds-panel-tools.js +3 -3
- package/dist/angular/ds-radio.js +3 -3
- package/dist/angular/ds-scroll-overlay.js +3 -3
- package/dist/angular/ds-select.js +3 -3
- package/dist/angular/ds-shell-app.js +3 -3
- package/dist/angular/ds-shell-page.js +3 -3
- package/dist/angular/ds-shell-tools.js +3 -3
- package/dist/angular/ds-skeleton.js +3 -3
- package/dist/angular/ds-slider.js +3 -3
- package/dist/angular/ds-swatch-picker.js +3 -3
- package/dist/angular/ds-switch.js +3 -3
- package/dist/angular/ds-tab-group.js +3 -3
- package/dist/angular/ds-tag.js +3 -3
- package/dist/angular/ds-text.js +3 -3
- package/dist/angular/ds-toast.js +3 -3
- package/dist/angular/ds-tooltip-data-viz.js +3 -3
- package/dist/angular/ds-tooltip.js +3 -3
- package/dist/angular/ds-typing-indicator.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/angular/radio-value-accessor.js +3 -3
- package/dist/angular/select-value-accessor.js +3 -3
- package/dist/angular/text-value-accessor.js +3 -3
- package/dist/angular/value-accessor.js +3 -3
- package/dist/components/ds-agent-response.js +1 -1
- package/dist/components/ds-agent-response.js.map +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-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-card-overview.js +1 -1
- package/dist/components/ds-card-overview.js.map +1 -1
- package/dist/components/ds-chart-donut.js +1 -1
- package/dist/components/ds-chart-line.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-empty-state.js +1 -1
- package/dist/components/ds-field.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.d.ts +11 -0
- package/dist/components/ds-message-actions.js +2 -0
- package/dist/components/ds-message-actions.js.map +1 -0
- package/dist/components/ds-message-composer.js +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-panel-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-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-swatch-picker.js +1 -1
- package/dist/components/ds-toast.js +1 -1
- package/dist/components/ds-tooltip-data-viz.js +1 -1
- package/dist/components/ds-typing-indicator.js +1 -1
- package/dist/components/index.d.ts +3 -0
- package/dist/components/{p-DEaszb15.js → p-1moOgMI-.js} +2 -2
- package/dist/components/p-4scN0Mgn.js +2 -0
- package/dist/components/{p-dVlKpt8U.js → p-B3PdrMP0.js} +2 -2
- package/dist/components/{p-Beejrd-R.js → p-BN9FZESH.js} +2 -2
- package/dist/components/{p-CAAWaTYD.js → p-BQTJ7ePr.js} +2 -2
- package/dist/components/{p-POvz6PiQ.js → p-BgjtMMye.js} +2 -2
- package/dist/components/p-BnhGV__o.js +2 -0
- package/dist/components/p-BnhGV__o.js.map +1 -0
- package/dist/components/p-BxEOlO5k.js +2 -0
- package/dist/components/p-BxEOlO5k.js.map +1 -0
- package/dist/components/{p-CUWFHTM6.js → p-CIgag7g2.js} +2 -2
- package/dist/components/{p-E7Ds1fQa.js → p-CQ4vAZ9j.js} +2 -2
- package/dist/components/{p-L-JEw-kX.js → p-CUSz0JFa.js} +2 -2
- package/dist/components/{p-xNfMEOpU.js → p-CWItD0gL.js} +2 -2
- package/dist/components/p-CWKrq35a.js +2 -0
- package/dist/components/p-CWKrq35a.js.map +1 -0
- package/dist/components/{p-CyjC57Dk.js → p-CmUGA_q4.js} +2 -2
- package/dist/components/p-CqOswTy8.js +2 -0
- package/dist/components/{p-Bi-21Kvd.js.map → p-CqOswTy8.js.map} +1 -1
- package/dist/components/{p-DKaXlmoQ.js → p-D4bVE7e4.js} +2 -2
- package/dist/components/{p-DAbOfJgz.js → p-D5PN6zdD.js} +2 -2
- package/dist/components/{p-BvvoC1lV.js → p-DXGKfXTh.js} +2 -2
- package/dist/components/{p-krhJI5_Y.js → p-DtV263qO.js} +2 -2
- package/dist/components/{p-vY5ia2gz.js → p-RT1mts9U.js} +2 -2
- package/dist/components/{p-z6c6TMlA.js → p-a6cnCKWk.js} +2 -2
- package/dist/docs/components.json +282 -1
- package/dist/mcp-data/registry/agent-response.json +24 -3
- package/dist/mcp-data/registry/avatar.json +1 -1
- package/dist/mcp-data/registry/card-overview.json +2 -2
- package/dist/mcp-data/registry/code-block.json +1 -1
- package/dist/mcp-data/registry/message-actions.json +186 -0
- package/dist/mcp-data/registry/message.json +27 -6
- package/dist/mcp-data/registry/registry.json +110 -7
- package/dist/react/components.d.ts +1 -0
- package/dist/react/components.js +1 -0
- package/dist/react/ds-agent-activity.d.ts +1 -1
- package/dist/react/ds-agent-activity.js +1 -1
- package/dist/react/ds-agent-response.d.ts +1 -1
- package/dist/react/ds-agent-response.js +1 -1
- package/dist/react/ds-agent-source-list.d.ts +1 -1
- package/dist/react/ds-agent-source-list.js +1 -1
- package/dist/react/ds-agent-tool-call.d.ts +1 -1
- package/dist/react/ds-agent-tool-call.js +1 -1
- package/dist/react/ds-attachment-list.d.ts +1 -1
- package/dist/react/ds-attachment-list.js +1 -1
- package/dist/react/ds-avatar.d.ts +1 -1
- package/dist/react/ds-avatar.js +1 -1
- package/dist/react/ds-badge.d.ts +1 -1
- package/dist/react/ds-badge.js +1 -1
- package/dist/react/ds-bar-nav.d.ts +1 -1
- package/dist/react/ds-bar-nav.js +1 -1
- package/dist/react/ds-bar-title.d.ts +1 -1
- package/dist/react/ds-bar-title.js +1 -1
- package/dist/react/ds-bar-workflow.d.ts +1 -1
- package/dist/react/ds-bar-workflow.js +1 -1
- package/dist/react/ds-breadcrumb.d.ts +1 -1
- package/dist/react/ds-breadcrumb.js +1 -1
- package/dist/react/ds-button-filled.d.ts +1 -1
- package/dist/react/ds-button-filled.js +1 -1
- package/dist/react/ds-button-unfilled.d.ts +1 -1
- package/dist/react/ds-button-unfilled.js +1 -1
- package/dist/react/ds-card-data-viz.d.ts +1 -1
- package/dist/react/ds-card-data-viz.js +1 -1
- package/dist/react/ds-card-overview.d.ts +1 -1
- package/dist/react/ds-card-overview.js +1 -1
- package/dist/react/ds-card-setting.d.ts +1 -1
- package/dist/react/ds-card-setting.js +1 -1
- package/dist/react/ds-chart-bar.d.ts +1 -1
- package/dist/react/ds-chart-bar.js +1 -1
- package/dist/react/ds-chart-donut.d.ts +1 -1
- package/dist/react/ds-chart-donut.js +1 -1
- package/dist/react/ds-chart-legend.d.ts +1 -1
- package/dist/react/ds-chart-legend.js +1 -1
- package/dist/react/ds-chart-line.d.ts +1 -1
- package/dist/react/ds-chart-line.js +1 -1
- package/dist/react/ds-checkbox.d.ts +1 -1
- package/dist/react/ds-checkbox.js +1 -1
- package/dist/react/ds-chip.d.ts +1 -1
- package/dist/react/ds-chip.js +1 -1
- package/dist/react/ds-code-block.d.ts +1 -1
- package/dist/react/ds-code-block.js +1 -1
- package/dist/react/ds-conversation-list-item.d.ts +1 -1
- package/dist/react/ds-conversation-list-item.js +1 -1
- package/dist/react/ds-conversation-list-section.d.ts +1 -1
- package/dist/react/ds-conversation-list-section.js +1 -1
- package/dist/react/ds-conversation-list.d.ts +1 -1
- package/dist/react/ds-conversation-list.js +1 -1
- package/dist/react/ds-divider.d.ts +1 -1
- package/dist/react/ds-divider.js +1 -1
- package/dist/react/ds-empty-state.d.ts +1 -1
- package/dist/react/ds-empty-state.js +1 -1
- package/dist/react/ds-field.d.ts +1 -1
- package/dist/react/ds-field.js +1 -1
- package/dist/react/ds-icon.d.ts +1 -1
- package/dist/react/ds-icon.js +1 -1
- package/dist/react/ds-input.d.ts +1 -1
- package/dist/react/ds-input.js +1 -1
- package/dist/react/ds-loader.d.ts +1 -1
- package/dist/react/ds-loader.js +1 -1
- package/dist/react/ds-markdown.d.ts +1 -1
- package/dist/react/ds-markdown.js +1 -1
- package/dist/react/ds-menu.d.ts +1 -1
- package/dist/react/ds-menu.js +1 -1
- package/dist/react/ds-message-actions.d.ts +13 -0
- package/dist/react/ds-message-actions.js +15 -0
- package/dist/react/ds-message-bubble.d.ts +1 -1
- package/dist/react/ds-message-bubble.js +1 -1
- package/dist/react/ds-message-composer.d.ts +1 -1
- package/dist/react/ds-message-composer.js +1 -1
- package/dist/react/ds-message-scroller.d.ts +1 -1
- package/dist/react/ds-message-scroller.js +1 -1
- package/dist/react/ds-message.d.ts +1 -1
- package/dist/react/ds-message.js +1 -1
- package/dist/react/ds-mobile-bar-nav.d.ts +1 -1
- package/dist/react/ds-mobile-bar-nav.js +1 -1
- package/dist/react/ds-mobile-header.d.ts +1 -1
- package/dist/react/ds-mobile-header.js +1 -1
- package/dist/react/ds-mobile-section-switcher.d.ts +1 -1
- package/dist/react/ds-mobile-section-switcher.js +1 -1
- package/dist/react/ds-mobile-sheet-nav.d.ts +1 -1
- package/dist/react/ds-mobile-sheet-nav.js +1 -1
- package/dist/react/ds-modal.d.ts +1 -1
- package/dist/react/ds-modal.js +1 -1
- package/dist/react/ds-panel-nav.d.ts +1 -1
- package/dist/react/ds-panel-nav.js +1 -1
- package/dist/react/ds-panel-sub-nav.d.ts +1 -1
- package/dist/react/ds-panel-sub-nav.js +1 -1
- package/dist/react/ds-panel-tool-header.d.ts +1 -1
- package/dist/react/ds-panel-tool-header.js +1 -1
- package/dist/react/ds-panel-tool-search.d.ts +1 -1
- package/dist/react/ds-panel-tool-search.js +1 -1
- package/dist/react/ds-panel-tools.d.ts +1 -1
- package/dist/react/ds-panel-tools.js +1 -1
- package/dist/react/ds-radio.d.ts +1 -1
- package/dist/react/ds-radio.js +1 -1
- package/dist/react/ds-scroll-overlay.d.ts +1 -1
- package/dist/react/ds-scroll-overlay.js +1 -1
- package/dist/react/ds-select.d.ts +1 -1
- package/dist/react/ds-select.js +1 -1
- package/dist/react/ds-shell-app.d.ts +1 -1
- package/dist/react/ds-shell-app.js +1 -1
- package/dist/react/ds-shell-page.d.ts +1 -1
- package/dist/react/ds-shell-page.js +1 -1
- package/dist/react/ds-shell-tools.d.ts +1 -1
- package/dist/react/ds-shell-tools.js +1 -1
- package/dist/react/ds-skeleton.d.ts +1 -1
- package/dist/react/ds-skeleton.js +1 -1
- package/dist/react/ds-slider.d.ts +1 -1
- package/dist/react/ds-slider.js +1 -1
- package/dist/react/ds-swatch-picker.d.ts +1 -1
- package/dist/react/ds-swatch-picker.js +1 -1
- package/dist/react/ds-switch.d.ts +1 -1
- package/dist/react/ds-switch.js +1 -1
- package/dist/react/ds-tab-group.d.ts +1 -1
- package/dist/react/ds-tab-group.js +1 -1
- package/dist/react/ds-tag.d.ts +1 -1
- package/dist/react/ds-tag.js +1 -1
- package/dist/react/ds-text.d.ts +1 -1
- package/dist/react/ds-text.js +1 -1
- package/dist/react/ds-toast.d.ts +1 -1
- package/dist/react/ds-toast.js +1 -1
- package/dist/react/ds-tooltip-data-viz.d.ts +1 -1
- package/dist/react/ds-tooltip-data-viz.js +1 -1
- package/dist/react/ds-tooltip.d.ts +1 -1
- package/dist/react/ds-tooltip.js +1 -1
- package/dist/react/ds-typing-indicator.d.ts +1 -1
- package/dist/react/ds-typing-indicator.js +1 -1
- package/dist/react/react-runtime.d.ts +17 -0
- package/dist/react/react-runtime.js +13 -0
- package/dist/types/components/AgentResponse/AgentResponse.d.ts +3 -1
- package/dist/types/components/CardOverview/CardOverview.d.ts +1 -1
- package/dist/types/components/CodeBlock/CodeBlock.d.ts +3 -1
- package/dist/types/components/Message/Message.d.ts +4 -1
- package/dist/types/components/MessageActions/MessageActions.d.ts +18 -0
- package/dist/types/components/conversation-types.d.ts +5 -0
- package/dist/types/components.d.ts +72 -2
- package/dist/types/utils/clipboard.d.ts +31 -0
- package/package.json +3 -6
- package/dist/components/p-B_A4g4Xe.js +0 -2
- package/dist/components/p-B_A4g4Xe.js.map +0 -1
- package/dist/components/p-Bi-21Kvd.js +0 -2
- package/dist/components/p-DV-tK5TR.js +0 -2
- package/dist/components/p-awaBUdlz.js +0 -2
- package/dist/components/p-awaBUdlz.js.map +0 -1
- /package/dist/components/{p-DEaszb15.js.map → p-1moOgMI-.js.map} +0 -0
- /package/dist/components/{p-DV-tK5TR.js.map → p-4scN0Mgn.js.map} +0 -0
- /package/dist/components/{p-dVlKpt8U.js.map → p-B3PdrMP0.js.map} +0 -0
- /package/dist/components/{p-Beejrd-R.js.map → p-BN9FZESH.js.map} +0 -0
- /package/dist/components/{p-CAAWaTYD.js.map → p-BQTJ7ePr.js.map} +0 -0
- /package/dist/components/{p-POvz6PiQ.js.map → p-BgjtMMye.js.map} +0 -0
- /package/dist/components/{p-CUWFHTM6.js.map → p-CIgag7g2.js.map} +0 -0
- /package/dist/components/{p-E7Ds1fQa.js.map → p-CQ4vAZ9j.js.map} +0 -0
- /package/dist/components/{p-L-JEw-kX.js.map → p-CUSz0JFa.js.map} +0 -0
- /package/dist/components/{p-xNfMEOpU.js.map → p-CWItD0gL.js.map} +0 -0
- /package/dist/components/{p-CyjC57Dk.js.map → p-CmUGA_q4.js.map} +0 -0
- /package/dist/components/{p-DKaXlmoQ.js.map → p-D4bVE7e4.js.map} +0 -0
- /package/dist/components/{p-DAbOfJgz.js.map → p-D5PN6zdD.js.map} +0 -0
- /package/dist/components/{p-BvvoC1lV.js.map → p-DXGKfXTh.js.map} +0 -0
- /package/dist/components/{p-krhJI5_Y.js.map → p-DtV263qO.js.map} +0 -0
- /package/dist/components/{p-vY5ia2gz.js.map → p-RT1mts9U.js.map} +0 -0
- /package/dist/components/{p-z6c6TMlA.js.map → p-a6cnCKWk.js.map} +0 -0
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
},
|
|
145
145
|
{
|
|
146
146
|
"path": "src/wc/components/CodeBlock/CodeBlock.tsx",
|
|
147
|
-
"content": "import { Component, h, Host, Prop, State } from '@stencil/core';\n\n@Component({\n tag: 'ds-code-block',\n styleUrl: 'CodeBlock.css',\n scoped: true,\n})\nexport class CodeBlock {\n @Prop() code: string = '';\n @Prop() language: string = '';\n @Prop() filename: string = '';\n\n @State() private copied: boolean = false;\n private
|
|
147
|
+
"content": "import { Component, h, Host, Prop, State, Watch } from '@stencil/core';\nimport { ClipboardFeedbackController } from '../../utils/clipboard';\n\n@Component({\n tag: 'ds-code-block',\n styleUrl: 'CodeBlock.css',\n scoped: true,\n})\nexport class CodeBlock {\n @Prop() code: string = '';\n @Prop() language: string = '';\n @Prop() filename: string = '';\n\n @State() private copied: boolean = false;\n private readonly copyFeedback = new ClipboardFeedbackController(copied => {\n this.copied = copied;\n });\n\n connectedCallback() {\n this.copyFeedback.connect();\n }\n\n @Watch('code')\n handleCodeChange() {\n this.copyFeedback.reset();\n }\n\n disconnectedCallback() {\n this.copyFeedback.disconnect();\n }\n\n private copy = async () => {\n await this.copyFeedback.copy(this.code);\n };\n\n render() {\n const label = this.filename || this.language || 'Code';\n return (\n <Host>\n <figure class=\"code-block\">\n <figcaption class=\"code-block__header\">\n <ds-text as=\"span\" variant=\"text-caption\" emphasis color=\"on-strong\">\n {label}\n </ds-text>\n <ds-tooltip label={this.copied ? 'Copied' : 'Copy code'} side=\"bottom\" size=\"sm\">\n <ds-button-unfilled\n variant=\"icon\"\n icon={this.copied ? 'Check' : 'Copy'}\n size=\"xs\"\n aria-label={this.copied ? 'Copied' : 'Copy code'}\n hasBorder={false}\n onDsClick={this.copy}\n />\n </ds-tooltip>\n </figcaption>\n <pre>\n <code>{this.code}</code>\n </pre>\n </figure>\n </Host>\n );\n }\n}\n",
|
|
148
148
|
"type": "registry:ui"
|
|
149
149
|
}
|
|
150
150
|
]
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "message-actions",
|
|
4
|
+
"title": "MessageActions",
|
|
5
|
+
"description": "Reusable message-level Copy and controlled response-feedback actions with consistent compact presentation and browser clipboard feedback.",
|
|
6
|
+
"type": "registry:ui",
|
|
7
|
+
"meta": {
|
|
8
|
+
"library": "@ds-mo/ui",
|
|
9
|
+
"distribution": "npm",
|
|
10
|
+
"storybook": "https://zainadeel.github.io/compomo/?path=/story/message-actions",
|
|
11
|
+
"source": "src/wc/components/MessageActions/MessageActions.tsx",
|
|
12
|
+
"intentStatus": "complete",
|
|
13
|
+
"intent": {
|
|
14
|
+
"audience": "specialized",
|
|
15
|
+
"status": "experimental",
|
|
16
|
+
"summary": "Reusable message-level Copy and controlled response-feedback actions with consistent compact presentation and browser clipboard feedback.",
|
|
17
|
+
"useWhen": [
|
|
18
|
+
"A message metadata row needs Copy alone or Copy with mutually exclusive positive and negative response feedback."
|
|
19
|
+
],
|
|
20
|
+
"avoidWhen": [
|
|
21
|
+
"The action executes, retries, regenerates, approves, edits, or otherwise changes message content."
|
|
22
|
+
],
|
|
23
|
+
"commonlyComposedWith": [
|
|
24
|
+
"component:ds-message",
|
|
25
|
+
"component:ds-agent-response",
|
|
26
|
+
"component:ds-button-unfilled"
|
|
27
|
+
],
|
|
28
|
+
"patterns": [
|
|
29
|
+
"pattern:conversation",
|
|
30
|
+
"pattern:agent-chat"
|
|
31
|
+
],
|
|
32
|
+
"accessibility": [
|
|
33
|
+
"Every icon action has a matching tooltip and accessible name.",
|
|
34
|
+
"Feedback uses genuine pressed toggle semantics and Copy announces its temporary Copied state through the control name."
|
|
35
|
+
],
|
|
36
|
+
"states": [
|
|
37
|
+
"The component owns clipboard execution and temporary copied feedback while the application supplies the exact copyable text.",
|
|
38
|
+
"Feedback is controlled: the component emits the requested positive, negative, or cleared value while the application owns persistence and consequences.",
|
|
39
|
+
"Copy, positive feedback, and negative feedback retain one stable order."
|
|
40
|
+
],
|
|
41
|
+
"responsiveBehavior": [
|
|
42
|
+
"The compact action group follows the visibility and metadata placement policy of its owning Message."
|
|
43
|
+
],
|
|
44
|
+
"references": [
|
|
45
|
+
{
|
|
46
|
+
"label": "Message metadata composition",
|
|
47
|
+
"path": "src/wc/components/Message/Message.stories.ts"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"api": {
|
|
52
|
+
"props": {
|
|
53
|
+
"copyText": {
|
|
54
|
+
"type": "string | undefined",
|
|
55
|
+
"resolvedType": "string | undefined",
|
|
56
|
+
"attribute": "copy-text",
|
|
57
|
+
"required": false,
|
|
58
|
+
"mutable": false
|
|
59
|
+
},
|
|
60
|
+
"feedback": {
|
|
61
|
+
"type": "MessageFeedback | undefined",
|
|
62
|
+
"resolvedType": "\"negative\" | \"positive\" | undefined",
|
|
63
|
+
"attribute": "feedback",
|
|
64
|
+
"required": false,
|
|
65
|
+
"mutable": false
|
|
66
|
+
},
|
|
67
|
+
"feedbackEnabled": {
|
|
68
|
+
"type": "boolean",
|
|
69
|
+
"resolvedType": "boolean",
|
|
70
|
+
"attribute": "feedback-enabled",
|
|
71
|
+
"default": "false",
|
|
72
|
+
"required": false,
|
|
73
|
+
"mutable": false
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"events": [
|
|
77
|
+
{
|
|
78
|
+
"name": "dsCopyResult",
|
|
79
|
+
"detail": "MessageCopyResultEventDetail",
|
|
80
|
+
"bubbles": true,
|
|
81
|
+
"cancelable": true,
|
|
82
|
+
"composed": true
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "dsFeedbackChange",
|
|
86
|
+
"detail": "MessageFeedback | undefined",
|
|
87
|
+
"bubbles": true,
|
|
88
|
+
"cancelable": true,
|
|
89
|
+
"composed": true
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
"methods": [],
|
|
93
|
+
"slots": []
|
|
94
|
+
},
|
|
95
|
+
"props": {
|
|
96
|
+
"copyText": {
|
|
97
|
+
"type": "string | undefined",
|
|
98
|
+
"resolvedType": "string | undefined",
|
|
99
|
+
"attribute": "copy-text",
|
|
100
|
+
"required": false,
|
|
101
|
+
"mutable": false
|
|
102
|
+
},
|
|
103
|
+
"feedback": {
|
|
104
|
+
"type": "MessageFeedback | undefined",
|
|
105
|
+
"resolvedType": "\"negative\" | \"positive\" | undefined",
|
|
106
|
+
"attribute": "feedback",
|
|
107
|
+
"required": false,
|
|
108
|
+
"mutable": false
|
|
109
|
+
},
|
|
110
|
+
"feedbackEnabled": {
|
|
111
|
+
"type": "boolean",
|
|
112
|
+
"resolvedType": "boolean",
|
|
113
|
+
"attribute": "feedback-enabled",
|
|
114
|
+
"default": "false",
|
|
115
|
+
"required": false,
|
|
116
|
+
"mutable": false
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"events": [
|
|
120
|
+
{
|
|
121
|
+
"name": "dsCopyResult",
|
|
122
|
+
"detail": "MessageCopyResultEventDetail",
|
|
123
|
+
"bubbles": true,
|
|
124
|
+
"cancelable": true,
|
|
125
|
+
"composed": true
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"name": "dsFeedbackChange",
|
|
129
|
+
"detail": "MessageFeedback | undefined",
|
|
130
|
+
"bubbles": true,
|
|
131
|
+
"cancelable": true,
|
|
132
|
+
"composed": true
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
"methods": [],
|
|
136
|
+
"slots": [],
|
|
137
|
+
"exports": {
|
|
138
|
+
"customElement": "ds-message-actions",
|
|
139
|
+
"react": "DsMessageActions",
|
|
140
|
+
"angular": "DsMessageActions"
|
|
141
|
+
},
|
|
142
|
+
"consumption": {
|
|
143
|
+
"install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
|
|
144
|
+
"cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
|
|
145
|
+
"customElements": {
|
|
146
|
+
"import": "import '@ds-mo/ui/dist/components/ds-message-actions.js';",
|
|
147
|
+
"example": "<ds-message-actions></ds-message-actions>"
|
|
148
|
+
},
|
|
149
|
+
"react": {
|
|
150
|
+
"import": "import { DsMessageActions } from '@ds-mo/ui/react';",
|
|
151
|
+
"example": "<DsMessageActions />"
|
|
152
|
+
},
|
|
153
|
+
"angular": {
|
|
154
|
+
"import": "import { DsMessageActions } from '@ds-mo/ui/angular/ds-message-actions';",
|
|
155
|
+
"example": "<ds-message-actions></ds-message-actions>"
|
|
156
|
+
},
|
|
157
|
+
"peerDependencies": {
|
|
158
|
+
"required": [
|
|
159
|
+
"@ds-mo/tokens ^5.1.0",
|
|
160
|
+
"@ds-mo/icons ^6.4.0"
|
|
161
|
+
],
|
|
162
|
+
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
"dependencies": [
|
|
167
|
+
"@ds-mo/ui",
|
|
168
|
+
"@ds-mo/tokens"
|
|
169
|
+
],
|
|
170
|
+
"registryDependencies": [
|
|
171
|
+
"button-unfilled",
|
|
172
|
+
"tooltip"
|
|
173
|
+
],
|
|
174
|
+
"files": [
|
|
175
|
+
{
|
|
176
|
+
"path": "src/wc/components/MessageActions/MessageActions.css",
|
|
177
|
+
"content": ":host {\n display: inline-flex;\n box-sizing: border-box;\n}\n\n.message-actions {\n display: inline-flex;\n align-items: center;\n gap: var(--dimension-space-050);\n}\n",
|
|
178
|
+
"type": "registry:ui"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"path": "src/wc/components/MessageActions/MessageActions.tsx",
|
|
182
|
+
"content": "import { Component, Event, EventEmitter, h, Host, Prop, State, Watch } from '@stencil/core';\nimport { ClipboardFeedbackController } from '../../utils/clipboard';\nimport type { MessageCopyResultEventDetail, MessageFeedback } from '../conversation-types';\n\n@Component({\n tag: 'ds-message-actions',\n styleUrl: 'MessageActions.css',\n scoped: true,\n})\nexport class MessageActions {\n @Prop() copyText: string | undefined;\n @Prop() feedbackEnabled: boolean = false;\n @Prop() feedback: MessageFeedback | undefined;\n\n @State() private copied: boolean = false;\n\n @Event() dsCopyResult!: EventEmitter<MessageCopyResultEventDetail>;\n @Event() dsFeedbackChange!: EventEmitter<MessageFeedback | undefined>;\n\n private readonly copyFeedback = new ClipboardFeedbackController(copied => {\n this.copied = copied;\n });\n\n connectedCallback() {\n this.copyFeedback.connect();\n }\n\n @Watch('copyText')\n handleCopyTextChange() {\n this.copyFeedback.reset();\n }\n\n disconnectedCallback() {\n this.copyFeedback.disconnect();\n }\n\n private copy = async () => {\n const success = await this.copyFeedback.copy(this.copyText ?? '');\n if (success === undefined) return;\n\n this.dsCopyResult.emit({ status: success ? 'success' : 'error' });\n };\n\n private changeFeedback(feedback: MessageFeedback, selected: boolean) {\n this.dsFeedbackChange.emit(selected ? feedback : undefined);\n }\n\n render() {\n const copyLabel = this.copied ? 'Copied' : 'Copy message';\n\n return (\n <Host>\n <div class=\"message-actions\" role=\"group\" aria-label=\"Message actions\">\n {this.copyText ? (\n <ds-tooltip label={copyLabel} side=\"top\" size=\"sm\">\n <ds-button-unfilled\n variant=\"icon\"\n icon={this.copied ? 'Check' : 'Copy'}\n size=\"xs\"\n aria-label={copyLabel}\n hasBorder={false}\n onDsClick={this.copy}\n />\n </ds-tooltip>\n ) : null}\n {this.feedbackEnabled ? (\n <ds-tooltip label=\"Good response\" side=\"top\" size=\"sm\">\n <ds-button-unfilled\n variant=\"icon\"\n icon={this.feedback === 'positive' ? 'ThumbsUpFilled' : 'ThumbsUp'}\n size=\"xs\"\n aria-label=\"Good response\"\n hasBorder={false}\n pressed={this.feedback === 'positive'}\n onDsChange={(event: CustomEvent<boolean>) =>\n this.changeFeedback('positive', event.detail)\n }\n />\n </ds-tooltip>\n ) : null}\n {this.feedbackEnabled ? (\n <ds-tooltip label=\"Bad response\" side=\"top\" size=\"sm\">\n <ds-button-unfilled\n variant=\"icon\"\n icon={this.feedback === 'negative' ? 'ThumbsDownFilled' : 'ThumbsDown'}\n size=\"xs\"\n aria-label=\"Bad response\"\n hasBorder={false}\n pressed={this.feedback === 'negative'}\n onDsChange={(event: CustomEvent<boolean>) =>\n this.changeFeedback('negative', event.detail)\n }\n />\n </ds-tooltip>\n ) : null}\n </div>\n </Host>\n );\n }\n}\n",
|
|
183
|
+
"type": "registry:ui"
|
|
184
|
+
}
|
|
185
|
+
]
|
|
186
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
3
|
"name": "message",
|
|
4
4
|
"title": "Message",
|
|
5
|
-
"description": "Channel-neutral message row owning direction, grouping, author, time, delivery metadata, and
|
|
5
|
+
"description": "Channel-neutral message row owning direction, grouping, author, time, delivery metadata, and persistent or metadata action regions.",
|
|
6
6
|
"type": "registry:ui",
|
|
7
7
|
"meta": {
|
|
8
8
|
"library": "@ds-mo/ui",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"intent": {
|
|
14
14
|
"audience": "general",
|
|
15
15
|
"status": "experimental",
|
|
16
|
-
"summary": "Channel-neutral message row owning direction, grouping, author, time, delivery metadata, and
|
|
16
|
+
"summary": "Channel-neutral message row owning direction, grouping, author, time, delivery metadata, and persistent or metadata action regions.",
|
|
17
17
|
"useWhen": [
|
|
18
18
|
"A transcript contains messages that need consistent incoming, outgoing, or system layout."
|
|
19
19
|
],
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"commonlyComposedWith": [
|
|
24
24
|
"component:ds-message-bubble",
|
|
25
|
+
"component:ds-message-actions",
|
|
25
26
|
"component:ds-message-scroller"
|
|
26
27
|
],
|
|
27
28
|
"patterns": [
|
|
@@ -29,14 +30,16 @@
|
|
|
29
30
|
],
|
|
30
31
|
"accessibility": [
|
|
31
32
|
"Author and time metadata remain textual when they are necessary to interpret the transcript.",
|
|
32
|
-
"Delivery failure uses negative Failed to send text in the footer while the message bubble keeps its normal outgoing treatment; when time is also visible, a tertiary middle dot separates the failure label and timestamp."
|
|
33
|
+
"Delivery failure uses negative Failed to send text in the footer while the message bubble keeps its normal outgoing treatment; when time is also visible, a tertiary middle dot separates the failure label and timestamp.",
|
|
34
|
+
"Hover-only metadata rows remain keyboard reachable, reveal on focus, and stay visible for touch and coarse-pointer input."
|
|
33
35
|
],
|
|
34
36
|
"states": [
|
|
35
37
|
"Pass an ISO timestamp. Message keeps the full value in dateTime and formats the visible value as a localized time; applications must not render a raw ISO string as visible transcript metadata.",
|
|
36
38
|
"A visible incoming author uses body-small emphasis with primary foreground; timestamp and delivery metadata remain caption text.",
|
|
37
39
|
"Visible author, bubble content, and timestamp or delivery footer use consistent 4px vertical gaps.",
|
|
38
40
|
"Grouping joins adjacent bubble corners, shows the incoming author only at the start, and shows delivery/time metadata only at the end. Outgoing author remains in the accessible message label without repeating a visible You label.",
|
|
39
|
-
"Set showAuthor false only when the product makes participant and assistant roles visually self-evident; continue passing author so the accessible message label remains specific."
|
|
41
|
+
"Set showAuthor false only when the product makes participant and assistant roles visually self-evident; continue passing author so the accessible message label remains specific.",
|
|
42
|
+
"Metadata actions precede incoming timestamps and follow outgoing timestamps. In hover mode the complete reserved footer—delivery, timestamp, and actions—fades as one unit without changing geometry; the persistent actions slot retains separate message-level controls."
|
|
40
43
|
],
|
|
41
44
|
"responsiveBehavior": [
|
|
42
45
|
"Outgoing and incoming rows adapt to available width while preserving their directional alignment."
|
|
@@ -89,6 +92,15 @@
|
|
|
89
92
|
"required": false,
|
|
90
93
|
"mutable": false
|
|
91
94
|
},
|
|
95
|
+
"metadataVisibility": {
|
|
96
|
+
"type": "MessageMetadataVisibility",
|
|
97
|
+
"resolvedType": "\"always\" | \"hover\"",
|
|
98
|
+
"attribute": "metadata-visibility",
|
|
99
|
+
"default": "'always'",
|
|
100
|
+
"required": false,
|
|
101
|
+
"mutable": false,
|
|
102
|
+
"description": "Controls whether the complete metadata footer is persistent or revealed through hover/focus."
|
|
103
|
+
},
|
|
92
104
|
"scrollAnchor": {
|
|
93
105
|
"type": "boolean",
|
|
94
106
|
"resolvedType": "boolean",
|
|
@@ -168,6 +180,15 @@
|
|
|
168
180
|
"required": false,
|
|
169
181
|
"mutable": false
|
|
170
182
|
},
|
|
183
|
+
"metadataVisibility": {
|
|
184
|
+
"type": "MessageMetadataVisibility",
|
|
185
|
+
"resolvedType": "\"always\" | \"hover\"",
|
|
186
|
+
"attribute": "metadata-visibility",
|
|
187
|
+
"default": "'always'",
|
|
188
|
+
"required": false,
|
|
189
|
+
"mutable": false,
|
|
190
|
+
"description": "Controls whether the complete metadata footer is persistent or revealed through hover/focus."
|
|
191
|
+
},
|
|
171
192
|
"scrollAnchor": {
|
|
172
193
|
"type": "boolean",
|
|
173
194
|
"resolvedType": "boolean",
|
|
@@ -245,12 +266,12 @@
|
|
|
245
266
|
"files": [
|
|
246
267
|
{
|
|
247
268
|
"path": "src/wc/components/Message/Message.css",
|
|
248
|
-
"content": ":host {\n display: block;\n box-sizing: border-box;\n content-visibility: auto;\n contain-intrinsic-size: auto var(--dimension-size-800);\n -webkit-user-select: none;\n user-select: none;\n}\n\n:host(.message-host--group-middle),\n:host(.message-host--group-last) {\n margin-block-start: calc(var(--dimension-space-050) - var(--dimension-space-300));\n}\n\n.message {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: end;\n gap: 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.message--outgoing {\n grid-template-columns: minmax(0, 1fr) auto;\n}\n\n.message__header:empty,\n.message__footer:empty,\n.message__actions:empty {\n display: none;\n}\n\n.message__actions:not(:empty) {\n margin-inline-start: var(--dimension-space-075);\n}\n\n.message__body {\n display: flex;\n flex-direction: column;\n min-width: 0;\n gap: var(--dimension-space-050);\n}\n\n.message--incoming .message__body {\n width: 100%;\n}\n\n.message--outgoing .message__body {\n align-items: flex-end;\n}\n\n.message--outgoing .message__header {\n display: none;\n}\n\n.message--system .message__body {\n align-items: center;\n}\n\n.message__header,\n.message__footer,\n.message__actions {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n}\n\n.message__content {\n width: 100%;\n min-width: 0;\n -webkit-user-select: text;\n user-select: text;\n}\n\n.message--outgoing .message__content {\n display: flex;\n justify-content: flex-end;\n}\n\n.message__footer time {\n display: inline-flex;\n}\n\n.message--group-middle .message__header,\n.message--group-last .message__header {\n display: none;\n}\n\n.message--group-first .message__footer,\n.message--group-middle .message__footer {\n display: none;\n}\n",
|
|
269
|
+
"content": ":host {\n display: block;\n box-sizing: border-box;\n content-visibility: auto;\n contain-intrinsic-size: auto var(--dimension-size-800);\n -webkit-user-select: none;\n user-select: none;\n}\n\n:host(.message-host--group-middle),\n:host(.message-host--group-last) {\n margin-block-start: calc(var(--dimension-space-050) - var(--dimension-space-300));\n}\n\n.message {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: end;\n gap: 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.message--outgoing {\n grid-template-columns: minmax(0, 1fr) auto;\n}\n\n.message__header:empty,\n.message__footer:empty,\n.message__metadata-actions:empty,\n.message__actions:empty {\n display: none;\n}\n\n.message__actions:not(:empty) {\n margin-inline-start: var(--dimension-space-075);\n}\n\n.message__body {\n display: flex;\n flex-direction: column;\n min-width: 0;\n gap: var(--dimension-space-050);\n}\n\n.message--incoming .message__body {\n width: 100%;\n}\n\n.message--outgoing .message__body {\n align-items: flex-end;\n}\n\n.message--outgoing .message__header {\n display: none;\n}\n\n.message--system .message__body {\n align-items: center;\n}\n\n.message__header,\n.message__footer,\n.message__metadata-actions,\n.message__actions {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .message--metadata-hover .message__footer {\n opacity: 0;\n pointer-events: none;\n transition: opacity var(--effect-motion-short-2);\n }\n\n .message--metadata-hover:hover .message__footer,\n .message--metadata-hover:focus-within .message__footer {\n opacity: 1;\n pointer-events: auto;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .message--metadata-hover .message__footer {\n transition: none;\n }\n}\n\n.message__content {\n width: 100%;\n min-width: 0;\n -webkit-user-select: text;\n user-select: text;\n}\n\n.message--outgoing .message__content {\n display: flex;\n justify-content: flex-end;\n}\n\n.message__footer time {\n display: inline-flex;\n}\n\n.message--group-middle .message__header,\n.message--group-last .message__header {\n display: none;\n}\n\n.message--group-first .message__footer,\n.message--group-middle .message__footer {\n display: none;\n}\n",
|
|
249
270
|
"type": "registry:ui"
|
|
250
271
|
},
|
|
251
272
|
{
|
|
252
273
|
"path": "src/wc/components/Message/Message.tsx",
|
|
253
|
-
"content": "import { Component, h, Host, Prop } from '@stencil/core';\nimport type {\n MessageDeliveryState,\n MessageDirection,\n MessageGroupPosition,\n} from '../conversation-types';\n\nconst DELIVERY_LABELS: Record<MessageDeliveryState, string> = {\n sending: 'Sending',\n sent: 'Sent',\n delivered: 'Delivered',\n read: 'Read',\n failed: 'Failed to send',\n};\n\n@Component({\n tag: 'ds-message',\n styleUrl: 'Message.css',\n scoped: true,\n})\nexport class Message {\n @Prop({ reflect: true }) messageId: string = '';\n @Prop({ reflect: true }) direction: MessageDirection = 'incoming';\n @Prop() groupPosition: MessageGroupPosition = 'single';\n @Prop() author: string = '';\n /** Keep author semantics while allowing products with self-evident roles to hide the visible label. */\n @Prop() showAuthor: boolean = true;\n /** ISO timestamp. */\n @Prop() timestamp: string = '';\n @Prop() deliveryState: MessageDeliveryState | undefined;\n @Prop() streaming: boolean = false;\n @Prop({ reflect: true }) scrollAnchor: boolean = false;\n\n private formattedTimestamp(): string {\n if (!this.timestamp) return '';\n const parsed = Date.parse(this.timestamp);\n if (Number.isNaN(parsed)) return this.timestamp;\n return new Intl.DateTimeFormat(undefined, {\n hour: 'numeric',\n minute: '2-digit',\n }).format(new Date(parsed));\n }\n\n render() {\n const delivery = this.deliveryState ? DELIVERY_LABELS[this.deliveryState] : '';\n const formattedTimestamp = this.formattedTimestamp();\n return (\n <Host\n class={`message-host--group-${this.groupPosition}`}\n data-message-id={this.messageId || undefined}\n data-scroll-anchor={this.scrollAnchor ? 'true' : undefined}\n aria-busy={this.streaming ? 'true' : undefined}\n >\n <article\n class={{\n message: true,\n [`message--${this.direction}`]: true,\n [`message--group-${this.groupPosition}`]: true,\n }}\n aria-label={this.author ? `Message from ${this.author}` : 'Message'}\n >\n <div class=\"message__body\">\n <div class=\"message__header\">\n <slot name=\"header\" />\n {this.author && this.showAuthor ? (\n <ds-text as=\"span\" variant=\"text-body-small\" emphasis color=\"primary\">\n {this.author}\n </ds-text>\n ) : null}\n </div>\n <div class=\"message__content\">\n <slot />\n </div>\n <div class=\"message__footer\">\n <slot name=\"footer\" />\n {delivery ? (\n <ds-text\n as=\"span\"\n variant=\"text-caption\"\n color={this.deliveryState === 'failed' ? 'negative' : 'secondary'}\n >\n {delivery}\n </ds-text>\n ) : null}\n {this.deliveryState === 'failed' && formattedTimestamp ? (\n <ds-text as=\"span\" variant=\"text-caption\" color=\"tertiary\" aria-hidden=\"true\">\n ·\n </ds-text>\n ) : null}\n {formattedTimestamp ? (\n <time dateTime={this.timestamp}>\n <ds-text as=\"span\" variant=\"text-caption\" color=\"secondary\">\n {formattedTimestamp}\n </ds-text>\n </time>\n ) : null}\n </div>\n </div>\n <div class=\"message__actions\">\n <slot name=\"actions\" />\n </div>\n </article>\n </Host>\n );\n }\n}\n",
|
|
274
|
+
"content": "import { Component, h, Host, Prop } from '@stencil/core';\nimport type {\n MessageDeliveryState,\n MessageDirection,\n MessageGroupPosition,\n MessageMetadataVisibility,\n} from '../conversation-types';\n\nconst DELIVERY_LABELS: Record<MessageDeliveryState, string> = {\n sending: 'Sending',\n sent: 'Sent',\n delivered: 'Delivered',\n read: 'Read',\n failed: 'Failed to send',\n};\n\n@Component({\n tag: 'ds-message',\n styleUrl: 'Message.css',\n scoped: true,\n})\nexport class Message {\n @Prop({ reflect: true }) messageId: string = '';\n @Prop({ reflect: true }) direction: MessageDirection = 'incoming';\n @Prop() groupPosition: MessageGroupPosition = 'single';\n @Prop() author: string = '';\n /** Keep author semantics while allowing products with self-evident roles to hide the visible label. */\n @Prop() showAuthor: boolean = true;\n /** ISO timestamp. */\n @Prop() timestamp: string = '';\n @Prop() deliveryState: MessageDeliveryState | undefined;\n @Prop() streaming: boolean = false;\n /** Controls whether the complete metadata footer is persistent or revealed through hover/focus. */\n @Prop() metadataVisibility: MessageMetadataVisibility = 'always';\n @Prop({ reflect: true }) scrollAnchor: boolean = false;\n\n private formattedTimestamp(): string {\n if (!this.timestamp) return '';\n const parsed = Date.parse(this.timestamp);\n if (Number.isNaN(parsed)) return this.timestamp;\n return new Intl.DateTimeFormat(undefined, {\n hour: 'numeric',\n minute: '2-digit',\n }).format(new Date(parsed));\n }\n\n private renderMetadataActions() {\n return (\n <div class=\"message__metadata-actions\">\n <slot name=\"metadata-actions\" />\n </div>\n );\n }\n\n render() {\n const delivery = this.deliveryState ? DELIVERY_LABELS[this.deliveryState] : '';\n const formattedTimestamp = this.formattedTimestamp();\n return (\n <Host\n class={`message-host--group-${this.groupPosition}`}\n data-message-id={this.messageId || undefined}\n data-scroll-anchor={this.scrollAnchor ? 'true' : undefined}\n aria-busy={this.streaming ? 'true' : undefined}\n >\n <article\n class={{\n message: true,\n [`message--${this.direction}`]: true,\n [`message--group-${this.groupPosition}`]: true,\n [`message--metadata-${this.metadataVisibility}`]: true,\n }}\n aria-label={this.author ? `Message from ${this.author}` : 'Message'}\n >\n <div class=\"message__body\">\n <div class=\"message__header\">\n <slot name=\"header\" />\n {this.author && this.showAuthor ? (\n <ds-text as=\"span\" variant=\"text-body-small\" emphasis color=\"primary\">\n {this.author}\n </ds-text>\n ) : null}\n </div>\n <div class=\"message__content\">\n <slot />\n </div>\n <div class=\"message__footer\">\n {this.direction === 'incoming' ? this.renderMetadataActions() : null}\n <slot name=\"footer\" />\n {delivery ? (\n <ds-text\n as=\"span\"\n variant=\"text-caption\"\n color={this.deliveryState === 'failed' ? 'negative' : 'secondary'}\n >\n {delivery}\n </ds-text>\n ) : null}\n {this.deliveryState === 'failed' && formattedTimestamp ? (\n <ds-text as=\"span\" variant=\"text-caption\" color=\"tertiary\" aria-hidden=\"true\">\n ·\n </ds-text>\n ) : null}\n {formattedTimestamp ? (\n <time dateTime={this.timestamp}>\n <ds-text as=\"span\" variant=\"text-caption\" color=\"secondary\">\n {formattedTimestamp}\n </ds-text>\n </time>\n ) : null}\n {this.direction !== 'incoming' ? this.renderMetadataActions() : null}\n </div>\n </div>\n <div class=\"message__actions\">\n <slot name=\"actions\" />\n </div>\n </article>\n </Host>\n );\n }\n}\n",
|
|
254
275
|
"type": "registry:ui"
|
|
255
276
|
}
|
|
256
277
|
]
|
|
@@ -122,6 +122,7 @@
|
|
|
122
122
|
],
|
|
123
123
|
"commonlyComposedWith": [
|
|
124
124
|
"component:ds-message",
|
|
125
|
+
"component:ds-message-actions",
|
|
125
126
|
"component:ds-markdown",
|
|
126
127
|
"component:ds-agent-activity",
|
|
127
128
|
"component:ds-agent-tool-call",
|
|
@@ -132,12 +133,14 @@
|
|
|
132
133
|
],
|
|
133
134
|
"accessibility": [
|
|
134
135
|
"Part order matches authored reading order and remains inside generic message semantics.",
|
|
135
|
-
"Streaming state supplements rather than replaces meaningful textual status."
|
|
136
|
+
"Streaming state supplements rather than replaces meaningful textual status.",
|
|
137
|
+
"Forwarded metadata actions retain Message ordering, keyboard reveal, and touch visibility."
|
|
136
138
|
],
|
|
137
139
|
"states": [
|
|
138
140
|
"The owner replaces immutable part arrays as scripted or live output changes.",
|
|
139
141
|
"AgentResponse renders directly in Message without borrowing a plain MessageBubble surface.",
|
|
140
|
-
"Markdown parts use the optional safe renderer; prose CSS owns only semantic-tree styling and never response ordering or streaming state."
|
|
142
|
+
"Markdown parts use the optional safe renderer; prose CSS owns only semantic-tree styling and never response ordering or streaming state.",
|
|
143
|
+
"The application may compose MessageActions for completed-response Copy and controlled feedback while retaining persistent retry or recovery controls in the separate actions slot."
|
|
141
144
|
],
|
|
142
145
|
"responsiveBehavior": [
|
|
143
146
|
"Rich content uses the available transcript width while respecting readable measure and local overflow constraints."
|
|
@@ -162,6 +165,10 @@
|
|
|
162
165
|
"type": "string",
|
|
163
166
|
"required": false
|
|
164
167
|
},
|
|
168
|
+
"metadataVisibility": {
|
|
169
|
+
"type": "MessageMetadataVisibility",
|
|
170
|
+
"required": false
|
|
171
|
+
},
|
|
165
172
|
"parts": {
|
|
166
173
|
"type": "AgentResponsePart[]",
|
|
167
174
|
"required": false
|
|
@@ -451,7 +458,7 @@
|
|
|
451
458
|
"intentStatus": "complete",
|
|
452
459
|
"intent": {
|
|
453
460
|
"audience": "general",
|
|
454
|
-
"status": "
|
|
461
|
+
"status": "stable",
|
|
455
462
|
"summary": "Compact icon avatar for visually identifying a person, group, channel, or conversation type.",
|
|
456
463
|
"useWhen": [
|
|
457
464
|
"A list or message composition needs a consistent circular identity marker represented by an icon at md, sm, or xs control density."
|
|
@@ -4376,7 +4383,7 @@
|
|
|
4376
4383
|
{
|
|
4377
4384
|
"name": "message",
|
|
4378
4385
|
"title": "Message",
|
|
4379
|
-
"description": "Channel-neutral message row owning direction, grouping, author, time, delivery metadata, and
|
|
4386
|
+
"description": "Channel-neutral message row owning direction, grouping, author, time, delivery metadata, and persistent or metadata action regions.",
|
|
4380
4387
|
"type": "registry:ui",
|
|
4381
4388
|
"meta": {
|
|
4382
4389
|
"library": "@ds-mo/ui",
|
|
@@ -4387,7 +4394,7 @@
|
|
|
4387
4394
|
"intent": {
|
|
4388
4395
|
"audience": "general",
|
|
4389
4396
|
"status": "experimental",
|
|
4390
|
-
"summary": "Channel-neutral message row owning direction, grouping, author, time, delivery metadata, and
|
|
4397
|
+
"summary": "Channel-neutral message row owning direction, grouping, author, time, delivery metadata, and persistent or metadata action regions.",
|
|
4391
4398
|
"useWhen": [
|
|
4392
4399
|
"A transcript contains messages that need consistent incoming, outgoing, or system layout."
|
|
4393
4400
|
],
|
|
@@ -4396,6 +4403,7 @@
|
|
|
4396
4403
|
],
|
|
4397
4404
|
"commonlyComposedWith": [
|
|
4398
4405
|
"component:ds-message-bubble",
|
|
4406
|
+
"component:ds-message-actions",
|
|
4399
4407
|
"component:ds-message-scroller"
|
|
4400
4408
|
],
|
|
4401
4409
|
"patterns": [
|
|
@@ -4403,14 +4411,16 @@
|
|
|
4403
4411
|
],
|
|
4404
4412
|
"accessibility": [
|
|
4405
4413
|
"Author and time metadata remain textual when they are necessary to interpret the transcript.",
|
|
4406
|
-
"Delivery failure uses negative Failed to send text in the footer while the message bubble keeps its normal outgoing treatment; when time is also visible, a tertiary middle dot separates the failure label and timestamp."
|
|
4414
|
+
"Delivery failure uses negative Failed to send text in the footer while the message bubble keeps its normal outgoing treatment; when time is also visible, a tertiary middle dot separates the failure label and timestamp.",
|
|
4415
|
+
"Hover-only metadata rows remain keyboard reachable, reveal on focus, and stay visible for touch and coarse-pointer input."
|
|
4407
4416
|
],
|
|
4408
4417
|
"states": [
|
|
4409
4418
|
"Pass an ISO timestamp. Message keeps the full value in dateTime and formats the visible value as a localized time; applications must not render a raw ISO string as visible transcript metadata.",
|
|
4410
4419
|
"A visible incoming author uses body-small emphasis with primary foreground; timestamp and delivery metadata remain caption text.",
|
|
4411
4420
|
"Visible author, bubble content, and timestamp or delivery footer use consistent 4px vertical gaps.",
|
|
4412
4421
|
"Grouping joins adjacent bubble corners, shows the incoming author only at the start, and shows delivery/time metadata only at the end. Outgoing author remains in the accessible message label without repeating a visible You label.",
|
|
4413
|
-
"Set showAuthor false only when the product makes participant and assistant roles visually self-evident; continue passing author so the accessible message label remains specific."
|
|
4422
|
+
"Set showAuthor false only when the product makes participant and assistant roles visually self-evident; continue passing author so the accessible message label remains specific.",
|
|
4423
|
+
"Metadata actions precede incoming timestamps and follow outgoing timestamps. In hover mode the complete reserved footer—delivery, timestamp, and actions—fades as one unit without changing geometry; the persistent actions slot retains separate message-level controls."
|
|
4414
4424
|
],
|
|
4415
4425
|
"responsiveBehavior": [
|
|
4416
4426
|
"Outgoing and incoming rows adapt to available width while preserving their directional alignment."
|
|
@@ -4443,6 +4453,10 @@
|
|
|
4443
4453
|
"type": "string",
|
|
4444
4454
|
"required": false
|
|
4445
4455
|
},
|
|
4456
|
+
"metadataVisibility": {
|
|
4457
|
+
"type": "MessageMetadataVisibility",
|
|
4458
|
+
"required": false
|
|
4459
|
+
},
|
|
4446
4460
|
"scrollAnchor": {
|
|
4447
4461
|
"type": "boolean",
|
|
4448
4462
|
"required": false
|
|
@@ -4476,6 +4490,95 @@
|
|
|
4476
4490
|
"text"
|
|
4477
4491
|
]
|
|
4478
4492
|
},
|
|
4493
|
+
{
|
|
4494
|
+
"name": "message-actions",
|
|
4495
|
+
"title": "MessageActions",
|
|
4496
|
+
"description": "Reusable message-level Copy and controlled response-feedback actions with consistent compact presentation and browser clipboard feedback.",
|
|
4497
|
+
"type": "registry:ui",
|
|
4498
|
+
"meta": {
|
|
4499
|
+
"library": "@ds-mo/ui",
|
|
4500
|
+
"distribution": "npm",
|
|
4501
|
+
"storybook": "https://zainadeel.github.io/compomo/?path=/story/message-actions",
|
|
4502
|
+
"source": "src/wc/components/MessageActions/MessageActions.tsx",
|
|
4503
|
+
"intentStatus": "complete",
|
|
4504
|
+
"intent": {
|
|
4505
|
+
"audience": "specialized",
|
|
4506
|
+
"status": "experimental",
|
|
4507
|
+
"summary": "Reusable message-level Copy and controlled response-feedback actions with consistent compact presentation and browser clipboard feedback.",
|
|
4508
|
+
"useWhen": [
|
|
4509
|
+
"A message metadata row needs Copy alone or Copy with mutually exclusive positive and negative response feedback."
|
|
4510
|
+
],
|
|
4511
|
+
"avoidWhen": [
|
|
4512
|
+
"The action executes, retries, regenerates, approves, edits, or otherwise changes message content."
|
|
4513
|
+
],
|
|
4514
|
+
"commonlyComposedWith": [
|
|
4515
|
+
"component:ds-message",
|
|
4516
|
+
"component:ds-agent-response",
|
|
4517
|
+
"component:ds-button-unfilled"
|
|
4518
|
+
],
|
|
4519
|
+
"patterns": [
|
|
4520
|
+
"pattern:conversation",
|
|
4521
|
+
"pattern:agent-chat"
|
|
4522
|
+
],
|
|
4523
|
+
"accessibility": [
|
|
4524
|
+
"Every icon action has a matching tooltip and accessible name.",
|
|
4525
|
+
"Feedback uses genuine pressed toggle semantics and Copy announces its temporary Copied state through the control name."
|
|
4526
|
+
],
|
|
4527
|
+
"states": [
|
|
4528
|
+
"The component owns clipboard execution and temporary copied feedback while the application supplies the exact copyable text.",
|
|
4529
|
+
"Feedback is controlled: the component emits the requested positive, negative, or cleared value while the application owns persistence and consequences.",
|
|
4530
|
+
"Copy, positive feedback, and negative feedback retain one stable order."
|
|
4531
|
+
],
|
|
4532
|
+
"responsiveBehavior": [
|
|
4533
|
+
"The compact action group follows the visibility and metadata placement policy of its owning Message."
|
|
4534
|
+
],
|
|
4535
|
+
"references": [
|
|
4536
|
+
{
|
|
4537
|
+
"label": "Message metadata composition",
|
|
4538
|
+
"path": "src/wc/components/Message/Message.stories.ts"
|
|
4539
|
+
}
|
|
4540
|
+
]
|
|
4541
|
+
},
|
|
4542
|
+
"props": {
|
|
4543
|
+
"copyText": {
|
|
4544
|
+
"type": "string | undefined",
|
|
4545
|
+
"required": false
|
|
4546
|
+
},
|
|
4547
|
+
"feedback": {
|
|
4548
|
+
"type": "MessageFeedback | undefined",
|
|
4549
|
+
"required": false
|
|
4550
|
+
},
|
|
4551
|
+
"feedbackEnabled": {
|
|
4552
|
+
"type": "boolean",
|
|
4553
|
+
"required": false
|
|
4554
|
+
}
|
|
4555
|
+
},
|
|
4556
|
+
"events": [
|
|
4557
|
+
{
|
|
4558
|
+
"name": "dsCopyResult",
|
|
4559
|
+
"detail": "MessageCopyResultEventDetail"
|
|
4560
|
+
},
|
|
4561
|
+
{
|
|
4562
|
+
"name": "dsFeedbackChange",
|
|
4563
|
+
"detail": "MessageFeedback | undefined"
|
|
4564
|
+
}
|
|
4565
|
+
],
|
|
4566
|
+
"slots": [],
|
|
4567
|
+
"exports": {
|
|
4568
|
+
"customElement": "ds-message-actions",
|
|
4569
|
+
"react": "DsMessageActions",
|
|
4570
|
+
"angular": "DsMessageActions"
|
|
4571
|
+
}
|
|
4572
|
+
},
|
|
4573
|
+
"dependencies": [
|
|
4574
|
+
"@ds-mo/ui",
|
|
4575
|
+
"@ds-mo/tokens"
|
|
4576
|
+
],
|
|
4577
|
+
"registryDependencies": [
|
|
4578
|
+
"button-unfilled",
|
|
4579
|
+
"tooltip"
|
|
4580
|
+
]
|
|
4581
|
+
},
|
|
4479
4582
|
{
|
|
4480
4583
|
"name": "message-bubble",
|
|
4481
4584
|
"title": "MessageBubble",
|
|
@@ -36,6 +36,7 @@ export { DsInput } from "./ds-input.js";
|
|
|
36
36
|
export { DsLoader } from "./ds-loader.js";
|
|
37
37
|
export { DsMarkdown } from "./ds-markdown.js";
|
|
38
38
|
export { DsMenu } from "./ds-menu.js";
|
|
39
|
+
export { DsMessageActions } from "./ds-message-actions.js";
|
|
39
40
|
export { DsMessageBubble } from "./ds-message-bubble.js";
|
|
40
41
|
export { DsMessageComposer } from "./ds-message-composer.js";
|
|
41
42
|
export { DsMessageScroller } from "./ds-message-scroller.js";
|
package/dist/react/components.js
CHANGED
|
@@ -37,6 +37,7 @@ export { DsInput } from "./ds-input.js";
|
|
|
37
37
|
export { DsLoader } from "./ds-loader.js";
|
|
38
38
|
export { DsMarkdown } from "./ds-markdown.js";
|
|
39
39
|
export { DsMenu } from "./ds-menu.js";
|
|
40
|
+
export { DsMessageActions } from "./ds-message-actions.js";
|
|
40
41
|
export { DsMessageBubble } from "./ds-message-bubble.js";
|
|
41
42
|
export { DsMessageComposer } from "./ds-message-composer.js";
|
|
42
43
|
export { DsMessageScroller } from "./ds-message-scroller.js";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* This file was automatically generated by the Stencil React Output Target.
|
|
3
3
|
* Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
|
|
4
4
|
*/
|
|
5
|
-
import type { StencilReactComponent } from '
|
|
5
|
+
import type { StencilReactComponent } from './react-runtime.js';
|
|
6
6
|
import type { Components } from "@ds-mo/ui/dist/components";
|
|
7
7
|
import { DsAgentActivity as DsAgentActivityElement } from "@ds-mo/ui/dist/components/ds-agent-activity.js";
|
|
8
8
|
export type DsAgentActivityEvents = NonNullable<unknown>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { createComponent } from '
|
|
2
|
+
import { createComponent } from './react-runtime.js';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { DsAgentActivity as DsAgentActivityElement, defineCustomElement as defineDsAgentActivity } from "@ds-mo/ui/dist/components/ds-agent-activity.js";
|
|
5
5
|
export const DsAgentActivity = /*@__PURE__*/ createComponent({
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* This file was automatically generated by the Stencil React Output Target.
|
|
3
3
|
* Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
|
|
4
4
|
*/
|
|
5
|
-
import type { StencilReactComponent } from '
|
|
5
|
+
import type { StencilReactComponent } from './react-runtime.js';
|
|
6
6
|
import type { Components } from "@ds-mo/ui/dist/components";
|
|
7
7
|
import { DsAgentResponse as DsAgentResponseElement } from "@ds-mo/ui/dist/components/ds-agent-response.js";
|
|
8
8
|
export type DsAgentResponseEvents = NonNullable<unknown>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { createComponent } from '
|
|
2
|
+
import { createComponent } from './react-runtime.js';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { DsAgentResponse as DsAgentResponseElement, defineCustomElement as defineDsAgentResponse } from "@ds-mo/ui/dist/components/ds-agent-response.js";
|
|
5
5
|
export const DsAgentResponse = /*@__PURE__*/ createComponent({
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* This file was automatically generated by the Stencil React Output Target.
|
|
3
3
|
* Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
|
|
4
4
|
*/
|
|
5
|
-
import type { StencilReactComponent } from '
|
|
5
|
+
import type { StencilReactComponent } from './react-runtime.js';
|
|
6
6
|
import type { Components } from "@ds-mo/ui/dist/components";
|
|
7
7
|
import { DsAgentSourceList as DsAgentSourceListElement } from "@ds-mo/ui/dist/components/ds-agent-source-list.js";
|
|
8
8
|
export type DsAgentSourceListEvents = NonNullable<unknown>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { createComponent } from '
|
|
2
|
+
import { createComponent } from './react-runtime.js';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { DsAgentSourceList as DsAgentSourceListElement, defineCustomElement as defineDsAgentSourceList } from "@ds-mo/ui/dist/components/ds-agent-source-list.js";
|
|
5
5
|
export const DsAgentSourceList = /*@__PURE__*/ createComponent({
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* This file was automatically generated by the Stencil React Output Target.
|
|
3
3
|
* Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
|
|
4
4
|
*/
|
|
5
|
-
import type { StencilReactComponent } from '
|
|
5
|
+
import type { StencilReactComponent } from './react-runtime.js';
|
|
6
6
|
import type { Components } from "@ds-mo/ui/dist/components";
|
|
7
7
|
import { DsAgentToolCall as DsAgentToolCallElement } from "@ds-mo/ui/dist/components/ds-agent-tool-call.js";
|
|
8
8
|
export type DsAgentToolCallEvents = NonNullable<unknown>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { createComponent } from '
|
|
2
|
+
import { createComponent } from './react-runtime.js';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { DsAgentToolCall as DsAgentToolCallElement, defineCustomElement as defineDsAgentToolCall } from "@ds-mo/ui/dist/components/ds-agent-tool-call.js";
|
|
5
5
|
export const DsAgentToolCall = /*@__PURE__*/ createComponent({
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* This file was automatically generated by the Stencil React Output Target.
|
|
3
3
|
* Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
|
|
4
4
|
*/
|
|
5
|
-
import type { StencilReactComponent } from '
|
|
5
|
+
import type { StencilReactComponent } from './react-runtime.js';
|
|
6
6
|
import type { Components } from "@ds-mo/ui/dist/components";
|
|
7
7
|
import { DsAttachmentList as DsAttachmentListElement } from "@ds-mo/ui/dist/components/ds-attachment-list.js";
|
|
8
8
|
export type DsAttachmentListEvents = NonNullable<unknown>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { createComponent } from '
|
|
2
|
+
import { createComponent } from './react-runtime.js';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { DsAttachmentList as DsAttachmentListElement, defineCustomElement as defineDsAttachmentList } from "@ds-mo/ui/dist/components/ds-attachment-list.js";
|
|
5
5
|
export const DsAttachmentList = /*@__PURE__*/ createComponent({
|