@ds-mo/ui 13.3.0 → 13.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.package-ready.json +1 -1
- package/dist/agent-patterns.json +14 -1
- package/dist/agent.json +126 -28
- 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-input.js +1 -1
- package/dist/components/ds-input.js.map +1 -1
- package/dist/components/ds-markdown.js +1 -1
- package/dist/components/ds-menu.js +1 -1
- package/dist/components/ds-message-actions.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-select.js.map +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 +291 -16
- package/dist/mcp-data/registry/agent-activity.json +1 -1
- package/dist/mcp-data/registry/agent-response.json +25 -4
- package/dist/mcp-data/registry/agent-source-list.json +1 -1
- package/dist/mcp-data/registry/agent-tool-call.json +1 -1
- package/dist/mcp-data/registry/attachment-list.json +1 -1
- package/dist/mcp-data/registry/avatar.json +2 -2
- package/dist/mcp-data/registry/badge.json +1 -1
- package/dist/mcp-data/registry/bar-nav.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-unfilled.json +1 -1
- package/dist/mcp-data/registry/card-data-viz.json +1 -1
- package/dist/mcp-data/registry/card-overview.json +33 -35
- package/dist/mcp-data/registry/card-setting.json +1 -1
- package/dist/mcp-data/registry/chart-bar.json +1 -1
- package/dist/mcp-data/registry/chart-donut.json +1 -1
- package/dist/mcp-data/registry/chart-legend.json +1 -1
- package/dist/mcp-data/registry/chart-line.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 +2 -2
- 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 +1 -1
- 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/icon.json +1 -1
- package/dist/mcp-data/registry/input.json +6 -6
- 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 +1 -1
- package/dist/mcp-data/registry/message-actions.json +186 -0
- package/dist/mcp-data/registry/message-bubble.json +1 -1
- package/dist/mcp-data/registry/message-composer.json +1 -1
- package/dist/mcp-data/registry/message-scroller.json +1 -1
- package/dist/mcp-data/registry/message.json +28 -7
- package/dist/mcp-data/registry/mobile-bar-nav.json +1 -1
- 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 +1 -1
- package/dist/mcp-data/registry/modal.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 +1 -1
- package/dist/mcp-data/registry/radio.json +1 -1
- package/dist/mcp-data/registry/registry.json +129 -28
- package/dist/mcp-data/registry/scroll-overlay.json +1 -1
- package/dist/mcp-data/registry/select.json +5 -5
- 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/tag.json +1 -1
- package/dist/mcp-data/registry/text.json +1 -1
- package/dist/mcp-data/registry/toast.json +1 -1
- package/dist/mcp-data/registry/tooltip-data-viz.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 +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 +11 -10
- package/dist/types/components/CardOverview/card-overview-controller.d.ts +13 -1
- package/dist/types/components/CardOverview/card-overview-types.d.ts +8 -2
- package/dist/types/components/CardOverview/index.d.ts +1 -1
- package/dist/types/components/CodeBlock/CodeBlock.d.ts +3 -1
- package/dist/types/components/Input/Input.d.ts +1 -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/Select/Select.d.ts +1 -1
- package/dist/types/components/conversation-types.d.ts +5 -0
- package/dist/types/components.d.ts +88 -18
- package/dist/types/utils/clipboard.d.ts +31 -0
- package/package.json +5 -8
- 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
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
},
|
|
121
121
|
"peerDependencies": {
|
|
122
122
|
"required": [
|
|
123
|
-
"@ds-mo/tokens ^5.1.
|
|
123
|
+
"@ds-mo/tokens ^5.1.1",
|
|
124
124
|
"@ds-mo/icons ^6.4.0"
|
|
125
125
|
],
|
|
126
126
|
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
@@ -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
|
]
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
],
|
|
56
56
|
"states": [
|
|
57
57
|
"Every size applies one complete control-density recipe across frame height, inline padding, icon zones, text-container inset, gap, and radius; supporting error content follows the shared 4px field flow.",
|
|
58
|
-
"The normal field boundary uses the shared secondary inset border. Focus promotes it to the thicker bold-brand inset stroke, while error uses the thicker bold-negative inset stroke without changing geometry.",
|
|
58
|
+
"The normal field boundary uses the shared secondary inset border. Focus promotes it to the thicker bold-brand inset stroke, while error uses the thicker bold-negative inset stroke without changing geometry. Set hasBorder to false only in chrome that supplies enough surrounding structure; the control then remains borderless at rest, while focused, and while invalid, with semantics and supporting error copy unchanged.",
|
|
59
59
|
"Placeholder text is secondary at rest and quaternary while the editable field is focused because it becomes decorative once typing begins.",
|
|
60
60
|
"Entered values use the parent surface's primary foreground; prefix icons, suffix content, and resting placeholder text use its secondary foreground.",
|
|
61
61
|
"Search fields show a standard borderless CrossCircle icon action only while they contain a value. Clearing emits the empty value and restores focus to the native field.",
|
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
"default": "true",
|
|
187
187
|
"required": false,
|
|
188
188
|
"mutable": false,
|
|
189
|
-
"description": "Show the standard inset border."
|
|
189
|
+
"description": "Show the standard inset border, including focused and invalid strokes."
|
|
190
190
|
},
|
|
191
191
|
"icon": {
|
|
192
192
|
"type": "string | undefined",
|
|
@@ -412,7 +412,7 @@
|
|
|
412
412
|
"default": "true",
|
|
413
413
|
"required": false,
|
|
414
414
|
"mutable": false,
|
|
415
|
-
"description": "Show the standard inset border."
|
|
415
|
+
"description": "Show the standard inset border, including focused and invalid strokes."
|
|
416
416
|
},
|
|
417
417
|
"icon": {
|
|
418
418
|
"type": "string | undefined",
|
|
@@ -566,7 +566,7 @@
|
|
|
566
566
|
},
|
|
567
567
|
"peerDependencies": {
|
|
568
568
|
"required": [
|
|
569
|
-
"@ds-mo/tokens ^5.1.
|
|
569
|
+
"@ds-mo/tokens ^5.1.1",
|
|
570
570
|
"@ds-mo/icons ^6.4.0"
|
|
571
571
|
],
|
|
572
572
|
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
@@ -586,12 +586,12 @@
|
|
|
586
586
|
"files": [
|
|
587
587
|
{
|
|
588
588
|
"path": "src/wc/components/Input/Input.css",
|
|
589
|
-
"content": "@import '../../utils/interaction-fill.css';\n@import '../../utils/control-inactive.css';\n@import '../../utils/control-density.css';\n@import '../../utils/control-parts.css';\n@import '../../utils/control-width.css';\n@import '../../utils/field-stack.css';\n@import '../../utils/typography.css';\n@import '../../utils/forced-colors.css';\n\n:host(.input-host) {\n display: inline-flex;\n --ds-input-fg: var(--color-foreground-primary);\n --ds-input-placeholder: var(--color-foreground-secondary);\n --ds-input-placeholder-active: var(--color-foreground-quaternary);\n --ds-input-adornment-fg: var(--color-foreground-secondary);\n --ds-input-border: var(--color-border-secondary);\n}\n\n:host(.ds-control-width--fill),\n:host(.ds-control-width--fill) .input-control {\n width: 100%;\n}\n\n.input-control {\n overflow: hidden;\n background: transparent;\n border: none;\n border-radius: var(--ds-control-radius, var(--dimension-radius-025));\n color: var(--ds-input-fg);\n}\n\n.input-control--bordered {\n --ds-interaction-border-width: var(--dimension-stroke-width-012);\n --ds-interaction-border-color: var(--ds-input-border);\n}\n\n.input-control--error {\n --ds-interaction-border-width: var(--dimension-stroke-width-018);\n --ds-interaction-border-color: var(--color-border-bold-negative);\n}\n\n.input-control:focus-within:not(.input-control--error) {\n --ds-interaction-border-width: var(--dimension-stroke-width-018);\n --ds-interaction-border-color: var(--color-border-bold-brand);\n}\n\n:host(.ds-control-inactive) .input-control::after {\n background: transparent;\n}\n\n.native-input {\n position: relative;\n z-index: 2;\n flex: 1 1 auto;\n min-width: 0;\n height: 100%;\n background: transparent;\n border: none;\n border-radius: inherit;\n outline: none;\n color: var(--ds-input-fg);\n font-family: inherit;\n -webkit-appearance: none;\n appearance: none;\n}\n\n.native-input:disabled {\n cursor: not-allowed;\n}\n\n.native-input:read-only:not(:disabled) {\n cursor: default;\n}\n\n.native-input::placeholder {\n color: var(--ds-input-placeholder);\n}\n\n.native-input:focus::placeholder {\n color: var(--ds-input-placeholder-active);\n}\n\n.native-input[type='search']::-webkit-search-cancel-button,\n.native-input[type='search']::-webkit-search-decoration {\n display: none;\n}\n\n.input-control__prefix,\n.input-control__suffix {\n position: relative;\n z-index: 2;\n color: var(--ds-input-adornment-fg);\n}\n\n.input-control__suffix--empty {\n display: none;\n}\n\n.input-control__clear {\n position: relative;\n z-index: 2;\n flex-shrink: 0;\n align-self: center;\n}\n\n.input-control.ds-control--lg:has(.input-control__clear),\n.input-control.ds-control--md:has(.input-control__clear),\n.input-control.ds-control--sm:has(.input-control__clear) {\n padding-right: var(--dimension-space-050);\n}\n\n.input-control.ds-control--xs:has(.input-control__clear) {\n padding-right: 0;\n}\n\n.error-text {\n width: 100%;\n}\n\n@media (forced-colors: active) {\n .input-control:focus-within:not(.input-control--error)::after {\n outline-color: var(--ds-forced-color-selected);\n }\n\n .input-control--error::after {\n outline-style: dashed;\n }\n}\n",
|
|
589
|
+
"content": "@import '../../utils/interaction-fill.css';\n@import '../../utils/control-inactive.css';\n@import '../../utils/control-density.css';\n@import '../../utils/control-parts.css';\n@import '../../utils/control-width.css';\n@import '../../utils/field-stack.css';\n@import '../../utils/typography.css';\n@import '../../utils/forced-colors.css';\n\n:host(.input-host) {\n display: inline-flex;\n --ds-input-fg: var(--color-foreground-primary);\n --ds-input-placeholder: var(--color-foreground-secondary);\n --ds-input-placeholder-active: var(--color-foreground-quaternary);\n --ds-input-adornment-fg: var(--color-foreground-secondary);\n --ds-input-border: var(--color-border-secondary);\n}\n\n:host(.ds-control-width--fill),\n:host(.ds-control-width--fill) .input-control {\n width: 100%;\n}\n\n.input-control {\n overflow: hidden;\n background: transparent;\n border: none;\n border-radius: var(--ds-control-radius, var(--dimension-radius-025));\n color: var(--ds-input-fg);\n}\n\n.input-control--bordered {\n --ds-interaction-border-width: var(--dimension-stroke-width-012);\n --ds-interaction-border-color: var(--ds-input-border);\n}\n\n.input-control--error {\n --ds-interaction-border-width: var(--dimension-stroke-width-018);\n --ds-interaction-border-color: var(--color-border-bold-negative);\n}\n\n.input-control--bordered:focus-within:not(.input-control--error) {\n --ds-interaction-border-width: var(--dimension-stroke-width-018);\n --ds-interaction-border-color: var(--color-border-bold-brand);\n}\n\n:host(.ds-control-inactive) .input-control::after {\n background: transparent;\n}\n\n.native-input {\n position: relative;\n z-index: 2;\n flex: 1 1 auto;\n min-width: 0;\n height: 100%;\n background: transparent;\n border: none;\n border-radius: inherit;\n outline: none;\n color: var(--ds-input-fg);\n font-family: inherit;\n -webkit-appearance: none;\n appearance: none;\n}\n\n.native-input:disabled {\n cursor: not-allowed;\n}\n\n.native-input:read-only:not(:disabled) {\n cursor: default;\n}\n\n.native-input::placeholder {\n color: var(--ds-input-placeholder);\n}\n\n.native-input:focus::placeholder {\n color: var(--ds-input-placeholder-active);\n}\n\n.native-input[type='search']::-webkit-search-cancel-button,\n.native-input[type='search']::-webkit-search-decoration {\n display: none;\n}\n\n.input-control__prefix,\n.input-control__suffix {\n position: relative;\n z-index: 2;\n color: var(--ds-input-adornment-fg);\n}\n\n.input-control__suffix--empty {\n display: none;\n}\n\n.input-control__clear {\n position: relative;\n z-index: 2;\n flex-shrink: 0;\n align-self: center;\n}\n\n.input-control.ds-control--lg:has(.input-control__clear),\n.input-control.ds-control--md:has(.input-control__clear),\n.input-control.ds-control--sm:has(.input-control__clear) {\n padding-right: var(--dimension-space-050);\n}\n\n.input-control.ds-control--xs:has(.input-control__clear) {\n padding-right: 0;\n}\n\n.error-text {\n width: 100%;\n}\n\n@media (forced-colors: active) {\n .input-control--bordered:focus-within:not(.input-control--error)::after {\n outline-color: var(--ds-forced-color-selected);\n }\n\n .input-control--error::after {\n outline-style: dashed;\n }\n}\n",
|
|
590
590
|
"type": "registry:ui"
|
|
591
591
|
},
|
|
592
592
|
{
|
|
593
593
|
"path": "src/wc/components/Input/Input.tsx",
|
|
594
|
-
"content": "import { AttachInternals, Component, Prop, State, Event, EventEmitter, Element, Method, Watch, h, Host } from '@stencil/core';\nimport {\n controlWidthClass,\n CONTROL_TEXT_VARIANT,\n DEFAULT_REQUIRED_MESSAGE,\n restoreStringFormState,\n setFormControlValue,\n setRequiredValidity,\n type ControlWidth,\n} from '../../utils';\n\nexport type InputType = 'text' | 'email' | 'tel' | 'url' | 'search' | 'password';\nexport type InputSize = 'lg' | 'md' | 'sm' | 'xs';\nexport type InputWidth = ControlWidth;\n\nconst ICON_SIZE: Record<InputSize, 'lg' | 'md' | 'sm' | 'xs'> = {\n lg: 'lg',\n md: 'md',\n sm: 'sm',\n xs: 'xs',\n};\n\nconst CLEAR_BUTTON_SIZE: Record<InputSize, 'md' | 'sm' | 'xs'> = {\n lg: 'md',\n md: 'sm',\n sm: 'xs',\n xs: 'xs',\n};\n\nlet idCounter = 0;\n\n@Component({\n tag: 'ds-input',\n styleUrl: 'Input.css',\n scoped: true,\n formAssociated: true,\n})\nexport class Input {\n @Element() el!: HTMLElement;\n @AttachInternals() internals!: ElementInternals;\n\n private generatedId = `ds-input-${++idCounter}`;\n private errorId = `${this.generatedId}-error`;\n\n @Prop({ mutable: true }) value: string = '';\n @Prop({ reflect: true }) name: string | undefined;\n @Prop({ reflect: true }) form: string | undefined;\n @Prop({ reflect: true }) disabled: boolean = false;\n /** Keeps the value focusable and submittable while preventing edits. */\n @Prop({ reflect: true }) readOnly: boolean = false;\n @Prop({ reflect: true }) required: boolean = false;\n @Prop() requiredMessage: string = DEFAULT_REQUIRED_MESSAGE;\n @Prop() clearLabel: string = 'Clear';\n @Prop() placeholder: string | undefined;\n @Prop() type: InputType = 'text';\n /** Native browser autofill hint. */\n @Prop({ attribute: 'autocomplete' }) autoComplete: string | undefined;\n /** Preferred virtual keyboard without changing the value semantics. */\n @Prop({ attribute: 'inputmode' }) inputMode: string = '';\n /** Preferred virtual-keyboard action label. */\n @Prop({ attribute: 'enterkeyhint' }) enterKeyHint: string = '';\n /** Control density. */\n @Prop() size: InputSize = 'md';\n /** Width fit — fill the parent (default) or hug the available content. */\n @Prop() width: InputWidth = 'fill';\n /** Show the standard inset border. */\n @Prop() hasBorder: boolean = true;\n /** Optional leading icon name. */\n @Prop() icon: string | undefined;\n @Prop() isInactive: boolean = false;\n @Prop() autoFocus: boolean = false;\n @Prop() error: boolean = false;\n @Prop() errorMessage: string | undefined;\n /** Associates the internal input with an external <label>. */\n @Prop() inputId: string | undefined;\n @Prop({ attribute: 'aria-label' }) ariaLabel: string | null = null;\n @Prop({ attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined;\n @Prop({ attribute: 'aria-describedby' }) ariaDescribedby: string | undefined;\n\n @Event() dsChange!: EventEmitter<string>;\n @Event() dsClear!: EventEmitter<void>;\n\n private initialValue = '';\n @State() private formDisabled = false;\n @State() private hasSuffix = false;\n @State() private focused = false;\n @State() private touched = false;\n\n componentWillLoad() {\n this.initialValue = this.value;\n this.hasSuffix = Boolean(this.el.querySelector('[slot=\"suffix\"]'));\n this.syncFormValue();\n }\n\n componentDidRender() {\n const hasSuffix = Boolean(this.el.querySelector('[slot=\"suffix\"]'));\n if (hasSuffix !== this.hasSuffix) this.hasSuffix = hasSuffix;\n }\n\n @Watch('value')\n @Watch('disabled')\n @Watch('isInactive')\n @Watch('required')\n syncFormValue() {\n const inactive = this.isInactive || this.disabled || this.formDisabled;\n setFormControlValue(this.internals, this.value, { inactive });\n const missing = this.required && !inactive && this.value.length === 0;\n setRequiredValidity(this.internals, missing, this.requiredMessage);\n }\n\n formDisabledCallback(disabled: boolean) {\n this.formDisabled = disabled;\n this.syncFormValue();\n }\n\n formResetCallback() {\n this.value = this.initialValue;\n }\n\n formStateRestoreCallback(state: string | File | FormData | null) {\n this.value = restoreStringFormState(state);\n }\n\n @Method()\n async setFocus() {\n this.el.querySelector('input')?.focus();\n }\n\n private handleInput = (e: Event) => {\n this.value = (e.target as HTMLInputElement).value;\n this.dsChange.emit(this.value);\n };\n\n private handleFocus = () => {\n this.focused = true;\n };\n\n private handleBlur = () => {\n this.focused = false;\n this.touched = true;\n };\n\n private handleClear = () => {\n this.value = '';\n this.dsChange.emit('');\n this.dsClear.emit();\n this.el.querySelector('input')?.focus();\n };\n\n render() {\n const inputId = this.inputId ?? this.generatedId;\n const inactive = this.isInactive || this.disabled || this.formDisabled;\n const filled = this.value.length > 0;\n const dirty = this.value !== this.initialValue;\n const showClear = this.type === 'search' && filled && !inactive && !this.readOnly;\n const showError = this.error && Boolean(this.errorMessage);\n const textVariant = CONTROL_TEXT_VARIANT[this.size];\n const iconSize = ICON_SIZE[this.size];\n\n const describedBy = [\n this.ariaDescribedby,\n showError ? this.errorId : undefined,\n ].filter(Boolean).join(' ') || undefined;\n\n return (\n <Host\n class={{\n 'input-host': true,\n 'ds-field-stack': true,\n 'ds-control-inactive': inactive,\n [`ds-control--${this.size}`]: true,\n ...controlWidthClass(this.width),\n }}\n data-disabled={inactive ? '' : undefined}\n data-readonly={this.readOnly ? '' : undefined}\n data-required={this.required ? '' : undefined}\n data-invalid={this.error ? '' : undefined}\n data-filled={filled ? '' : undefined}\n data-focused={this.focused ? '' : undefined}\n data-dirty={dirty ? '' : undefined}\n data-touched={this.touched ? '' : undefined}\n >\n <div\n class={{\n 'input-control': true,\n 'ds-control-frame': true,\n 'input-control--bordered': this.hasBorder
|
|
594
|
+
"content": "import { AttachInternals, Component, Prop, State, Event, EventEmitter, Element, Method, Watch, h, Host } from '@stencil/core';\nimport {\n controlWidthClass,\n CONTROL_TEXT_VARIANT,\n DEFAULT_REQUIRED_MESSAGE,\n restoreStringFormState,\n setFormControlValue,\n setRequiredValidity,\n type ControlWidth,\n} from '../../utils';\n\nexport type InputType = 'text' | 'email' | 'tel' | 'url' | 'search' | 'password';\nexport type InputSize = 'lg' | 'md' | 'sm' | 'xs';\nexport type InputWidth = ControlWidth;\n\nconst ICON_SIZE: Record<InputSize, 'lg' | 'md' | 'sm' | 'xs'> = {\n lg: 'lg',\n md: 'md',\n sm: 'sm',\n xs: 'xs',\n};\n\nconst CLEAR_BUTTON_SIZE: Record<InputSize, 'md' | 'sm' | 'xs'> = {\n lg: 'md',\n md: 'sm',\n sm: 'xs',\n xs: 'xs',\n};\n\nlet idCounter = 0;\n\n@Component({\n tag: 'ds-input',\n styleUrl: 'Input.css',\n scoped: true,\n formAssociated: true,\n})\nexport class Input {\n @Element() el!: HTMLElement;\n @AttachInternals() internals!: ElementInternals;\n\n private generatedId = `ds-input-${++idCounter}`;\n private errorId = `${this.generatedId}-error`;\n\n @Prop({ mutable: true }) value: string = '';\n @Prop({ reflect: true }) name: string | undefined;\n @Prop({ reflect: true }) form: string | undefined;\n @Prop({ reflect: true }) disabled: boolean = false;\n /** Keeps the value focusable and submittable while preventing edits. */\n @Prop({ reflect: true }) readOnly: boolean = false;\n @Prop({ reflect: true }) required: boolean = false;\n @Prop() requiredMessage: string = DEFAULT_REQUIRED_MESSAGE;\n @Prop() clearLabel: string = 'Clear';\n @Prop() placeholder: string | undefined;\n @Prop() type: InputType = 'text';\n /** Native browser autofill hint. */\n @Prop({ attribute: 'autocomplete' }) autoComplete: string | undefined;\n /** Preferred virtual keyboard without changing the value semantics. */\n @Prop({ attribute: 'inputmode' }) inputMode: string = '';\n /** Preferred virtual-keyboard action label. */\n @Prop({ attribute: 'enterkeyhint' }) enterKeyHint: string = '';\n /** Control density. */\n @Prop() size: InputSize = 'md';\n /** Width fit — fill the parent (default) or hug the available content. */\n @Prop() width: InputWidth = 'fill';\n /** Show the standard inset border, including focused and invalid strokes. */\n @Prop() hasBorder: boolean = true;\n /** Optional leading icon name. */\n @Prop() icon: string | undefined;\n @Prop() isInactive: boolean = false;\n @Prop() autoFocus: boolean = false;\n @Prop() error: boolean = false;\n @Prop() errorMessage: string | undefined;\n /** Associates the internal input with an external <label>. */\n @Prop() inputId: string | undefined;\n @Prop({ attribute: 'aria-label' }) ariaLabel: string | null = null;\n @Prop({ attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined;\n @Prop({ attribute: 'aria-describedby' }) ariaDescribedby: string | undefined;\n\n @Event() dsChange!: EventEmitter<string>;\n @Event() dsClear!: EventEmitter<void>;\n\n private initialValue = '';\n @State() private formDisabled = false;\n @State() private hasSuffix = false;\n @State() private focused = false;\n @State() private touched = false;\n\n componentWillLoad() {\n this.initialValue = this.value;\n this.hasSuffix = Boolean(this.el.querySelector('[slot=\"suffix\"]'));\n this.syncFormValue();\n }\n\n componentDidRender() {\n const hasSuffix = Boolean(this.el.querySelector('[slot=\"suffix\"]'));\n if (hasSuffix !== this.hasSuffix) this.hasSuffix = hasSuffix;\n }\n\n @Watch('value')\n @Watch('disabled')\n @Watch('isInactive')\n @Watch('required')\n syncFormValue() {\n const inactive = this.isInactive || this.disabled || this.formDisabled;\n setFormControlValue(this.internals, this.value, { inactive });\n const missing = this.required && !inactive && this.value.length === 0;\n setRequiredValidity(this.internals, missing, this.requiredMessage);\n }\n\n formDisabledCallback(disabled: boolean) {\n this.formDisabled = disabled;\n this.syncFormValue();\n }\n\n formResetCallback() {\n this.value = this.initialValue;\n }\n\n formStateRestoreCallback(state: string | File | FormData | null) {\n this.value = restoreStringFormState(state);\n }\n\n @Method()\n async setFocus() {\n this.el.querySelector('input')?.focus();\n }\n\n private handleInput = (e: Event) => {\n this.value = (e.target as HTMLInputElement).value;\n this.dsChange.emit(this.value);\n };\n\n private handleFocus = () => {\n this.focused = true;\n };\n\n private handleBlur = () => {\n this.focused = false;\n this.touched = true;\n };\n\n private handleClear = () => {\n this.value = '';\n this.dsChange.emit('');\n this.dsClear.emit();\n this.el.querySelector('input')?.focus();\n };\n\n render() {\n const inputId = this.inputId ?? this.generatedId;\n const inactive = this.isInactive || this.disabled || this.formDisabled;\n const filled = this.value.length > 0;\n const dirty = this.value !== this.initialValue;\n const showClear = this.type === 'search' && filled && !inactive && !this.readOnly;\n const showError = this.error && Boolean(this.errorMessage);\n const textVariant = CONTROL_TEXT_VARIANT[this.size];\n const iconSize = ICON_SIZE[this.size];\n\n const describedBy = [\n this.ariaDescribedby,\n showError ? this.errorId : undefined,\n ].filter(Boolean).join(' ') || undefined;\n\n return (\n <Host\n class={{\n 'input-host': true,\n 'ds-field-stack': true,\n 'ds-control-inactive': inactive,\n [`ds-control--${this.size}`]: true,\n ...controlWidthClass(this.width),\n }}\n data-disabled={inactive ? '' : undefined}\n data-readonly={this.readOnly ? '' : undefined}\n data-required={this.required ? '' : undefined}\n data-invalid={this.error ? '' : undefined}\n data-filled={filled ? '' : undefined}\n data-focused={this.focused ? '' : undefined}\n data-dirty={dirty ? '' : undefined}\n data-touched={this.touched ? '' : undefined}\n >\n <div\n class={{\n 'input-control': true,\n 'ds-control-frame': true,\n 'input-control--bordered': this.hasBorder,\n 'input-control--error': this.hasBorder && this.error,\n 'ds-interaction-fill': true,\n [`ds-control--${this.size}`]: true,\n }}\n >\n {this.icon && (\n <span class=\"input-control__prefix ds-control-icon-box ds-interaction-fill__content\" aria-hidden=\"true\">\n <ds-icon name={this.icon} size={iconSize} color=\"inherit\" />\n </span>\n )}\n <input\n type={this.type}\n id={inputId}\n value={this.value}\n placeholder={this.placeholder}\n disabled={inactive}\n readOnly={this.readOnly}\n required={this.required}\n autoFocus={this.autoFocus}\n autoComplete={this.autoComplete}\n inputMode={this.inputMode || undefined}\n enterKeyHint={this.enterKeyHint || undefined}\n class={`native-input ds-control-label-box ds-text--${textVariant.replace('text-', '')} ds-text--regular ds-interaction-fill__content`}\n aria-label={this.ariaLabel}\n aria-labelledby={this.ariaLabelledby}\n aria-describedby={describedBy}\n aria-invalid={this.error ? 'true' : undefined}\n onInput={this.handleInput}\n onFocus={this.handleFocus}\n onBlur={this.handleBlur}\n />\n <span class={{ 'input-control__suffix': true, 'ds-control-icon-box': true, 'input-control__suffix--empty': !this.hasSuffix }}>\n <slot name=\"suffix\" />\n </span>\n {showClear && (\n <ds-button-unfilled\n class=\"input-control__clear\"\n variant=\"icon\"\n size={CLEAR_BUTTON_SIZE[this.size]}\n icon=\"CrossCircle\"\n hasBorder={false}\n rounded\n ariaLabel={this.clearLabel}\n onDsClick={this.handleClear}\n />\n )}\n </div>\n {showError && (\n <ds-text\n class=\"error-text\"\n as=\"div\"\n variant=\"text-body-small\"\n color=\"negative\"\n textId={this.errorId}\n role=\"alert\"\n >\n {this.errorMessage}\n </ds-text>\n )}\n </Host>\n );\n }\n}\n",
|
|
595
595
|
"type": "registry:ui"
|
|
596
596
|
}
|
|
597
597
|
]
|
|
@@ -453,7 +453,7 @@
|
|
|
453
453
|
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: anchor, items, sections.",
|
|
454
454
|
"peerDependencies": {
|
|
455
455
|
"required": [
|
|
456
|
-
"@ds-mo/tokens ^5.1.
|
|
456
|
+
"@ds-mo/tokens ^5.1.1",
|
|
457
457
|
"@ds-mo/icons ^6.4.0"
|
|
458
458
|
],
|
|
459
459
|
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
@@ -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.1",
|
|
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",
|
|
@@ -228,7 +249,7 @@
|
|
|
228
249
|
},
|
|
229
250
|
"peerDependencies": {
|
|
230
251
|
"required": [
|
|
231
|
-
"@ds-mo/tokens ^5.1.
|
|
252
|
+
"@ds-mo/tokens ^5.1.1",
|
|
232
253
|
"@ds-mo/icons ^6.4.0"
|
|
233
254
|
],
|
|
234
255
|
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
@@ -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
|
]
|
|
@@ -299,7 +299,7 @@
|
|
|
299
299
|
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: currentArea.",
|
|
300
300
|
"peerDependencies": {
|
|
301
301
|
"required": [
|
|
302
|
-
"@ds-mo/tokens ^5.1.
|
|
302
|
+
"@ds-mo/tokens ^5.1.1",
|
|
303
303
|
"@ds-mo/icons ^6.4.0"
|
|
304
304
|
],
|
|
305
305
|
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
@@ -280,7 +280,7 @@
|
|
|
280
280
|
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: sections, subsections.",
|
|
281
281
|
"peerDependencies": {
|
|
282
282
|
"required": [
|
|
283
|
-
"@ds-mo/tokens ^5.1.
|
|
283
|
+
"@ds-mo/tokens ^5.1.1",
|
|
284
284
|
"@ds-mo/icons ^6.4.0"
|
|
285
285
|
],
|
|
286
286
|
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
@@ -153,7 +153,7 @@
|
|
|
153
153
|
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: sections.",
|
|
154
154
|
"peerDependencies": {
|
|
155
155
|
"required": [
|
|
156
|
-
"@ds-mo/tokens ^5.1.
|
|
156
|
+
"@ds-mo/tokens ^5.1.1",
|
|
157
157
|
"@ds-mo/icons ^6.4.0"
|
|
158
158
|
],
|
|
159
159
|
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|