@ds-mo/ui 9.1.0 → 9.2.1
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/README.md +0 -79
- package/dist/.build-stamp +1 -1
- package/dist/agent-patterns.json +165 -1
- package/dist/agent.json +2131 -639
- package/dist/angular/ds-agent-activity.d.ts +12 -0
- package/dist/angular/ds-agent-activity.js +38 -0
- package/dist/angular/ds-agent-response.d.ts +12 -0
- package/dist/angular/ds-agent-response.js +38 -0
- package/dist/angular/ds-agent-source-list.d.ts +12 -0
- package/dist/angular/ds-agent-source-list.js +38 -0
- package/dist/angular/ds-agent-tool-call.d.ts +12 -0
- package/dist/angular/ds-agent-tool-call.js +38 -0
- package/dist/angular/ds-attachment-list.d.ts +12 -0
- package/dist/angular/ds-attachment-list.js +38 -0
- package/dist/angular/ds-avatar.d.ts +12 -0
- package/dist/angular/ds-avatar.js +38 -0
- package/dist/angular/ds-code-block.d.ts +12 -0
- package/dist/angular/ds-code-block.js +38 -0
- package/dist/angular/ds-conversation-list-item.d.ts +19 -0
- package/dist/angular/ds-conversation-list-item.js +42 -0
- package/dist/angular/ds-conversation-list-section.d.ts +12 -0
- package/dist/angular/ds-conversation-list-section.js +38 -0
- package/dist/angular/ds-conversation-list.d.ts +12 -0
- package/dist/angular/ds-conversation-list.js +37 -0
- package/dist/angular/ds-markdown.d.ts +12 -0
- package/dist/angular/ds-markdown.js +38 -0
- package/dist/angular/ds-menu.d.ts +6 -1
- package/dist/angular/ds-menu.js +7 -4
- package/dist/angular/ds-message-bubble.d.ts +12 -0
- package/dist/angular/ds-message-bubble.js +38 -0
- package/dist/angular/ds-message-composer.d.ts +23 -0
- package/dist/angular/ds-message-composer.js +49 -0
- package/dist/angular/ds-message-scroller.d.ts +15 -0
- package/dist/angular/ds-message-scroller.js +43 -0
- package/dist/angular/ds-message.d.ts +12 -0
- package/dist/angular/ds-message.js +38 -0
- package/dist/angular/ds-panel-nav.d.ts +1 -1
- package/dist/angular/ds-panel-nav.js +3 -3
- package/dist/angular/ds-panel-tool-header.d.ts +25 -0
- package/dist/angular/ds-panel-tool-header.js +49 -0
- package/dist/angular/ds-panel-tool-search.d.ts +19 -0
- package/dist/angular/ds-panel-tool-search.js +49 -0
- package/dist/angular/ds-panel-tools.d.ts +30 -1
- package/dist/angular/ds-panel-tools.js +14 -5
- package/dist/angular/index.d.ts +1 -1
- package/dist/angular/index.js +17 -0
- package/dist/angular/proxies.d.ts +17 -0
- package/dist/angular/proxies.js +17 -0
- package/dist/components/ds-agent-activity.d.ts +11 -0
- package/dist/components/ds-agent-activity.js +2 -0
- package/dist/components/ds-agent-activity.js.map +1 -0
- package/dist/components/ds-agent-response.d.ts +11 -0
- package/dist/components/ds-agent-response.js +2 -0
- package/dist/components/ds-agent-response.js.map +1 -0
- package/dist/components/ds-agent-source-list.d.ts +11 -0
- package/dist/components/ds-agent-source-list.js +2 -0
- package/dist/components/ds-agent-source-list.js.map +1 -0
- package/dist/components/ds-agent-tool-call.d.ts +11 -0
- package/dist/components/ds-agent-tool-call.js +2 -0
- package/dist/components/ds-agent-tool-call.js.map +1 -0
- package/dist/components/ds-app-shell.js +1 -1
- package/dist/components/ds-app-shell.js.map +1 -1
- package/dist/components/ds-attachment-list.d.ts +11 -0
- package/dist/components/ds-attachment-list.js +2 -0
- package/dist/components/ds-attachment-list.js.map +1 -0
- package/dist/components/ds-avatar.d.ts +11 -0
- package/dist/components/ds-avatar.js +2 -0
- package/dist/components/ds-avatar.js.map +1 -0
- package/dist/components/ds-badge.js +1 -1
- package/dist/components/ds-banner.js +1 -1
- package/dist/components/ds-bar-nav.js +1 -1
- package/dist/components/ds-bar-nav.js.map +1 -1
- package/dist/components/ds-button-filled.js +1 -1
- package/dist/components/ds-button-unfilled.js +1 -1
- package/dist/components/ds-card-data-viz-donut.js +1 -1
- package/dist/components/ds-card-setting.js +1 -1
- package/dist/components/ds-card-shell-data-viz.js +1 -1
- package/dist/components/ds-card.js +1 -1
- package/dist/components/ds-chart-bar.js +1 -1
- package/dist/components/ds-chart-bar.js.map +1 -1
- package/dist/components/ds-chart-donut.js +1 -1
- package/dist/components/ds-chart-legend.js +1 -1
- package/dist/components/ds-chart-line.js +1 -1
- package/dist/components/ds-checkbox.js +1 -1
- package/dist/components/ds-chip.js +1 -1
- package/dist/components/ds-code-block.d.ts +11 -0
- package/dist/components/ds-code-block.js +2 -0
- package/dist/components/ds-code-block.js.map +1 -0
- package/dist/components/ds-conversation-list-item.d.ts +11 -0
- package/dist/components/ds-conversation-list-item.js +2 -0
- package/dist/components/ds-conversation-list-item.js.map +1 -0
- package/dist/components/ds-conversation-list-section.d.ts +11 -0
- package/dist/components/ds-conversation-list-section.js +2 -0
- package/dist/components/ds-conversation-list-section.js.map +1 -0
- package/dist/components/ds-conversation-list.d.ts +11 -0
- package/dist/components/ds-conversation-list.js +2 -0
- package/dist/components/ds-conversation-list.js.map +1 -0
- package/dist/components/ds-divider.js +1 -1
- package/dist/components/ds-divider.js.map +1 -1
- package/dist/components/ds-empty-state.js +1 -1
- package/dist/components/ds-field.js +1 -1
- package/dist/components/ds-icon.js +1 -1
- package/dist/components/ds-input.js +1 -1
- package/dist/components/ds-markdown.d.ts +11 -0
- package/dist/components/ds-markdown.js +2 -0
- package/dist/components/ds-markdown.js.map +1 -0
- package/dist/components/ds-menu.js +1 -1
- package/dist/components/ds-message-bubble.d.ts +11 -0
- package/dist/components/ds-message-bubble.js +2 -0
- package/dist/components/ds-message-bubble.js.map +1 -0
- package/dist/components/ds-message-composer.d.ts +11 -0
- package/dist/components/ds-message-composer.js +2 -0
- package/dist/components/ds-message-composer.js.map +1 -0
- package/dist/components/ds-message-scroller.d.ts +11 -0
- package/dist/components/ds-message-scroller.js +2 -0
- package/dist/components/ds-message-scroller.js.map +1 -0
- package/dist/components/ds-message.d.ts +11 -0
- package/dist/components/ds-message.js +2 -0
- package/dist/components/ds-message.js.map +1 -0
- package/dist/components/ds-modal.js +1 -1
- package/dist/components/ds-panel-nav.js +1 -1
- package/dist/components/ds-panel-nav.js.map +1 -1
- package/dist/components/ds-panel-sub-nav.js +1 -1
- package/dist/components/ds-panel-tool-header.d.ts +11 -0
- package/dist/components/ds-panel-tool-header.js +2 -0
- package/dist/components/ds-panel-tool-header.js.map +1 -0
- package/dist/components/ds-panel-tool-search.d.ts +11 -0
- package/dist/components/ds-panel-tool-search.js +2 -0
- package/dist/components/ds-panel-tool-search.js.map +1 -0
- package/dist/components/ds-panel-tools.js +1 -1
- package/dist/components/ds-panel-tools.js.map +1 -1
- package/dist/components/ds-radio.js +1 -1
- package/dist/components/ds-select-multi.js +1 -1
- package/dist/components/ds-select-multi.js.map +1 -1
- package/dist/components/ds-select.js +1 -1
- package/dist/components/ds-select.js.map +1 -1
- package/dist/components/ds-shell-gradient-picker.js +1 -1
- package/dist/components/ds-shell-gradient-picker.js.map +1 -1
- package/dist/components/ds-shell-gradient-swatch.js +1 -1
- package/dist/components/ds-skeleton.js +1 -1
- package/dist/components/ds-slider.js +1 -1
- package/dist/components/ds-slider.js.map +1 -1
- package/dist/components/ds-swatch-picker.js +1 -1
- package/dist/components/ds-switch.js +1 -1
- package/dist/components/ds-tab-group.js +1 -1
- package/dist/components/ds-tab-group.js.map +1 -1
- package/dist/components/ds-tag.js +1 -1
- package/dist/components/ds-tag.js.map +1 -1
- package/dist/components/ds-text.js +1 -1
- package/dist/components/ds-tooltip-data-viz.js +1 -1
- package/dist/components/ds-tooltip.js +1 -1
- package/dist/components/index.d.ts +14 -0
- package/dist/components/{p-HBIxvS5C.js → p-B1pWGQn1.js} +2 -2
- package/dist/components/p-BBu_Svz7.js +2 -0
- package/dist/components/p-BBu_Svz7.js.map +1 -0
- package/dist/components/p-BHpWYKtP.js +2 -0
- package/dist/components/p-BHpWYKtP.js.map +1 -0
- package/dist/components/{p-KRGBGTu5.js → p-BO6C8abO.js} +2 -2
- package/dist/components/p-BRfOCc_h.js +2 -0
- package/dist/components/p-BRfOCc_h.js.map +1 -0
- package/dist/components/{p-CbS_WWs2.js → p-BSOZXagj.js} +2 -2
- package/dist/components/p-BSOZXagj.js.map +1 -0
- package/dist/components/p-BhC1YyId.js +2 -0
- package/dist/components/p-BhC1YyId.js.map +1 -0
- package/dist/components/p-BjtXYFhw.js +2 -0
- package/dist/components/p-BjtXYFhw.js.map +1 -0
- package/dist/components/p-CBYuvZKM.js +2 -0
- package/dist/components/p-CBYuvZKM.js.map +1 -0
- package/dist/components/{p-CZ9wemOA.js → p-CJlgONwR.js} +2 -2
- package/dist/components/p-CKaJx0IX.js +2 -0
- package/dist/components/p-CKaJx0IX.js.map +1 -0
- package/dist/components/p-CWNdl52Y.js +2 -0
- package/dist/components/p-CWNdl52Y.js.map +1 -0
- package/dist/components/{p-DT2MK8Kt.js → p-CblAABEo.js} +2 -2
- package/dist/components/p-CeFBA7Dx.js +2 -0
- package/dist/components/p-CeFBA7Dx.js.map +1 -0
- package/dist/components/p-CiKGqsA2.js +2 -0
- package/dist/components/{p-BLzivrE3.js.map → p-CiKGqsA2.js.map} +1 -1
- package/dist/components/p-Ci_nVk5P.js +2 -0
- package/dist/components/p-Ci_nVk5P.js.map +1 -0
- package/dist/components/p-Cijzn3YQ.js +2 -0
- package/dist/components/p-Cijzn3YQ.js.map +1 -0
- package/dist/components/{p-BbV68F23.js → p-CiwdnKKp.js} +2 -2
- package/dist/components/p-DFxqk71w.js +2 -0
- package/dist/components/p-DFxqk71w.js.map +1 -0
- package/dist/components/p-DVsje4AY.js +2 -0
- package/dist/components/p-DVsje4AY.js.map +1 -0
- package/dist/components/p-DaQ0ZE_V.js +2 -0
- package/dist/components/p-DaQ0ZE_V.js.map +1 -0
- package/dist/components/p-DiooIO2B.js +2 -0
- package/dist/components/p-DiooIO2B.js.map +1 -0
- package/dist/components/p-Dj5MejHv.js +2 -0
- package/dist/components/p-Dj5MejHv.js.map +1 -0
- package/dist/components/{p-B-zhgAvL.js → p-DnMCRAwx.js} +2 -2
- package/dist/components/{p-DyZj3k9S.js → p-Dst-OliP.js} +2 -2
- package/dist/components/p-Dst-OliP.js.map +1 -0
- package/dist/components/p-T0Mzhv3-.js +2 -0
- package/dist/components/p-T0Mzhv3-.js.map +1 -0
- package/dist/components/p-a9nGf1s6.js +2 -0
- package/dist/components/p-a9nGf1s6.js.map +1 -0
- package/dist/components/p-gidVv1FX.js +2 -0
- package/dist/components/p-gidVv1FX.js.map +1 -0
- package/dist/components/p-kezp2_Xu.js +2 -0
- package/dist/components/p-kezp2_Xu.js.map +1 -0
- package/dist/components/p-rEe-3KR_.js +2 -0
- package/dist/components/p-rEe-3KR_.js.map +1 -0
- package/dist/components/{p-C7RObioO.js → p-xB0GPG3-.js} +2 -2
- package/dist/docs/components.json +8294 -4079
- package/dist/lib/components/Menu/menu-placement.d.ts +13 -0
- package/dist/lib/shell/index.d.ts +1 -1
- package/dist/lib/shell/index.js +8 -0
- package/dist/lib/shell/index.js.map +2 -2
- package/dist/mcp-data/registry/agent-activity.json +158 -0
- package/dist/mcp-data/registry/agent-response.json +211 -0
- package/dist/mcp-data/registry/agent-source-list.json +153 -0
- package/dist/mcp-data/registry/agent-tool-call.json +213 -0
- package/dist/mcp-data/registry/app-shell.json +2 -2
- package/dist/mcp-data/registry/attachment-list.json +137 -0
- package/dist/mcp-data/registry/avatar.json +154 -0
- package/dist/mcp-data/registry/bar-nav.json +2 -2
- package/dist/mcp-data/registry/button-unfilled.json +2 -2
- package/dist/mcp-data/registry/code-block.json +150 -0
- package/dist/mcp-data/registry/conversation-list-item.json +283 -0
- package/dist/mcp-data/registry/conversation-list-section.json +139 -0
- package/dist/mcp-data/registry/conversation-list.json +101 -0
- package/dist/mcp-data/registry/markdown.json +141 -0
- package/dist/mcp-data/registry/menu.json +43 -7
- package/dist/mcp-data/registry/message-bubble.json +119 -0
- package/dist/mcp-data/registry/message-composer.json +265 -0
- package/dist/mcp-data/registry/message-scroller.json +217 -0
- package/dist/mcp-data/registry/message.json +255 -0
- package/dist/mcp-data/registry/panel-nav.json +20 -2
- package/dist/mcp-data/registry/panel-tool-header.json +342 -0
- package/dist/mcp-data/registry/panel-tool-search.json +387 -0
- package/dist/mcp-data/registry/panel-tools.json +150 -10
- package/dist/mcp-data/registry/registry.json +2159 -616
- package/dist/mcp-data/registry/select.json +1 -1
- package/dist/mcp-data/registry/slider.json +4 -4
- package/dist/mcp-data/registry/switch.json +1 -1
- package/dist/mcp-data/registry/tab-group.json +2 -2
- package/dist/mcp-data/registry/tag.json +2 -2
- package/dist/mcp-data/registry/text.json +1 -1
- package/dist/react/components.d.ts +17 -0
- package/dist/react/components.js +17 -0
- package/dist/react/ds-agent-activity.d.ts +9 -0
- package/dist/react/ds-agent-activity.js +12 -0
- package/dist/react/ds-agent-response.d.ts +9 -0
- package/dist/react/ds-agent-response.js +12 -0
- package/dist/react/ds-agent-source-list.d.ts +9 -0
- package/dist/react/ds-agent-source-list.js +12 -0
- package/dist/react/ds-agent-tool-call.d.ts +9 -0
- package/dist/react/ds-agent-tool-call.js +12 -0
- package/dist/react/ds-attachment-list.d.ts +9 -0
- package/dist/react/ds-attachment-list.js +12 -0
- package/dist/react/ds-avatar.d.ts +9 -0
- package/dist/react/ds-avatar.js +12 -0
- package/dist/react/ds-code-block.d.ts +9 -0
- package/dist/react/ds-code-block.js +12 -0
- package/dist/react/ds-conversation-list-item.d.ts +14 -0
- package/dist/react/ds-conversation-list-item.js +12 -0
- package/dist/react/ds-conversation-list-section.d.ts +9 -0
- package/dist/react/ds-conversation-list-section.js +12 -0
- package/dist/react/ds-conversation-list.d.ts +9 -0
- package/dist/react/ds-conversation-list.js +12 -0
- package/dist/react/ds-markdown.d.ts +9 -0
- package/dist/react/ds-markdown.js +12 -0
- package/dist/react/ds-menu.d.ts +1 -0
- package/dist/react/ds-menu.js +1 -0
- package/dist/react/ds-message-bubble.d.ts +9 -0
- package/dist/react/ds-message-bubble.js +12 -0
- package/dist/react/ds-message-composer.d.ts +16 -0
- package/dist/react/ds-message-composer.js +16 -0
- package/dist/react/ds-message-scroller.d.ts +12 -0
- package/dist/react/ds-message-scroller.js +12 -0
- package/dist/react/ds-message.d.ts +9 -0
- package/dist/react/ds-message.js +12 -0
- package/dist/react/ds-panel-tool-header.d.ts +17 -0
- package/dist/react/ds-panel-tool-header.js +16 -0
- package/dist/react/ds-panel-tool-search.d.ts +14 -0
- package/dist/react/ds-panel-tool-search.js +16 -0
- package/dist/react/ds-panel-tools.d.ts +10 -0
- package/dist/react/ds-panel-tools.js +3 -0
- package/dist/types/components/AgentActivity/AgentActivity.d.ts +14 -0
- package/dist/types/components/AgentResponse/AgentResponse.d.ts +12 -0
- package/dist/types/components/AgentSourceList/AgentSourceList.d.ts +9 -0
- package/dist/types/components/AgentToolCall/AgentToolCall.d.ts +13 -0
- package/dist/types/components/AppShell/AppShell.d.ts +4 -0
- package/dist/types/components/AttachmentList/AttachmentList.d.ts +8 -0
- package/dist/types/components/Avatar/Avatar.d.ts +11 -0
- package/dist/types/components/BarNav/BarNav.d.ts +2 -0
- package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +2 -0
- package/dist/types/components/CodeBlock/CodeBlock.d.ts +11 -0
- package/dist/types/components/ConversationList/ConversationList.d.ts +4 -0
- package/dist/types/components/ConversationListItem/ConversationListItem.d.ts +24 -0
- package/dist/types/components/ConversationListSection/ConversationListSection.d.ts +9 -0
- package/dist/types/components/Markdown/Markdown.d.ts +15 -0
- package/dist/types/components/Menu/Menu.d.ts +9 -0
- package/dist/types/components/Menu/menu-placement.d.ts +13 -0
- package/dist/types/components/Menu/menu-types.d.ts +1 -1
- package/dist/types/components/Message/Message.d.ts +17 -0
- package/dist/types/components/MessageBubble/MessageBubble.d.ts +6 -0
- package/dist/types/components/MessageComposer/MessageComposer.d.ts +29 -0
- package/dist/types/components/MessageScroller/MessageScroller.d.ts +41 -0
- package/dist/types/components/PanelNav/PanelNav.d.ts +5 -0
- package/dist/types/components/PanelToolHeader/PanelToolHeader.d.ts +34 -0
- package/dist/types/components/PanelToolSearch/PanelToolSearch.d.ts +35 -0
- package/dist/types/components/PanelTools/PanelTools.d.ts +40 -1
- package/dist/types/components/PanelTools/panel-tools-types.d.ts +20 -0
- package/dist/types/components/PanelTools/panel-tools-utils.d.ts +2 -0
- package/dist/types/components/Slider/Slider.d.ts +1 -1
- package/dist/types/components/conversation-types.d.ts +55 -0
- package/dist/types/components.d.ts +1229 -14
- package/dist/types/shell/index.d.ts +1 -1
- package/dist/types/utils/choice-list-parts.d.ts +4 -1
- package/package.json +11 -11
- package/dist/components/p-BLzivrE3.js +0 -2
- package/dist/components/p-C7UFYvsO.js +0 -2
- package/dist/components/p-C7UFYvsO.js.map +0 -1
- package/dist/components/p-CXF8yd-g.js +0 -2
- package/dist/components/p-CXF8yd-g.js.map +0 -1
- package/dist/components/p-CbS_WWs2.js.map +0 -1
- package/dist/components/p-DyZj3k9S.js.map +0 -1
- package/dist/components/p-VKIsOVza.js +0 -2
- package/dist/components/p-VKIsOVza.js.map +0 -1
- package/dist/components/p-tQ1QHeOE.js +0 -2
- package/dist/components/p-tQ1QHeOE.js.map +0 -1
- /package/dist/components/{p-HBIxvS5C.js.map → p-B1pWGQn1.js.map} +0 -0
- /package/dist/components/{p-KRGBGTu5.js.map → p-BO6C8abO.js.map} +0 -0
- /package/dist/components/{p-CZ9wemOA.js.map → p-CJlgONwR.js.map} +0 -0
- /package/dist/components/{p-DT2MK8Kt.js.map → p-CblAABEo.js.map} +0 -0
- /package/dist/components/{p-BbV68F23.js.map → p-CiwdnKKp.js.map} +0 -0
- /package/dist/components/{p-B-zhgAvL.js.map → p-DnMCRAwx.js.map} +0 -0
- /package/dist/components/{p-C7RObioO.js.map → p-xB0GPG3-.js.map} +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "agent-source-list",
|
|
4
|
+
"title": "AgentSourceList",
|
|
5
|
+
"description": "Collapsible list of agent response sources with title, description, and validated external links.",
|
|
6
|
+
"type": "registry:ui",
|
|
7
|
+
"meta": {
|
|
8
|
+
"library": "@ds-mo/ui",
|
|
9
|
+
"distribution": "npm",
|
|
10
|
+
"storybook": "https://zainadeel.github.io/compomo/?path=/story/agent-source-list",
|
|
11
|
+
"source": "src/wc/components/AgentSourceList/AgentSourceList.tsx",
|
|
12
|
+
"intentStatus": "complete",
|
|
13
|
+
"intent": {
|
|
14
|
+
"audience": "specialized",
|
|
15
|
+
"status": "experimental",
|
|
16
|
+
"summary": "Collapsible list of agent response sources with title, description, and validated external links.",
|
|
17
|
+
"useWhen": [
|
|
18
|
+
"An agent response cites external material readers may inspect."
|
|
19
|
+
],
|
|
20
|
+
"avoidWhen": [
|
|
21
|
+
"The links are ordinary body links or are not sources for the response."
|
|
22
|
+
],
|
|
23
|
+
"commonlyComposedWith": [
|
|
24
|
+
"component:ds-agent-response",
|
|
25
|
+
"component:ds-markdown"
|
|
26
|
+
],
|
|
27
|
+
"patterns": [
|
|
28
|
+
"pattern:agent-chat"
|
|
29
|
+
],
|
|
30
|
+
"accessibility": [
|
|
31
|
+
"Each source uses descriptive linked text and visible supporting context.",
|
|
32
|
+
"Unsafe link schemes remain non-interactive text."
|
|
33
|
+
],
|
|
34
|
+
"responsiveBehavior": [
|
|
35
|
+
"Source titles and descriptions wrap within the response width."
|
|
36
|
+
],
|
|
37
|
+
"references": [
|
|
38
|
+
{
|
|
39
|
+
"label": "Storybook examples",
|
|
40
|
+
"path": "src/wc/components/MessageScroller/MessageScroller.stories.ts"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"api": {
|
|
45
|
+
"props": {
|
|
46
|
+
"heading": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"resolvedType": "string",
|
|
49
|
+
"attribute": "heading",
|
|
50
|
+
"default": "'Sources'",
|
|
51
|
+
"required": false,
|
|
52
|
+
"mutable": false
|
|
53
|
+
},
|
|
54
|
+
"items": {
|
|
55
|
+
"type": "AgentSource[]",
|
|
56
|
+
"resolvedType": "AgentSource[]",
|
|
57
|
+
"default": "[]",
|
|
58
|
+
"required": false,
|
|
59
|
+
"mutable": false
|
|
60
|
+
},
|
|
61
|
+
"open": {
|
|
62
|
+
"type": "boolean",
|
|
63
|
+
"resolvedType": "boolean",
|
|
64
|
+
"attribute": "open",
|
|
65
|
+
"default": "false",
|
|
66
|
+
"required": false,
|
|
67
|
+
"mutable": false
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"events": [],
|
|
71
|
+
"methods": [],
|
|
72
|
+
"slots": []
|
|
73
|
+
},
|
|
74
|
+
"props": {
|
|
75
|
+
"heading": {
|
|
76
|
+
"type": "string",
|
|
77
|
+
"resolvedType": "string",
|
|
78
|
+
"attribute": "heading",
|
|
79
|
+
"default": "'Sources'",
|
|
80
|
+
"required": false,
|
|
81
|
+
"mutable": false
|
|
82
|
+
},
|
|
83
|
+
"items": {
|
|
84
|
+
"type": "AgentSource[]",
|
|
85
|
+
"resolvedType": "AgentSource[]",
|
|
86
|
+
"default": "[]",
|
|
87
|
+
"required": false,
|
|
88
|
+
"mutable": false
|
|
89
|
+
},
|
|
90
|
+
"open": {
|
|
91
|
+
"type": "boolean",
|
|
92
|
+
"resolvedType": "boolean",
|
|
93
|
+
"attribute": "open",
|
|
94
|
+
"default": "false",
|
|
95
|
+
"required": false,
|
|
96
|
+
"mutable": false
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"events": [],
|
|
100
|
+
"methods": [],
|
|
101
|
+
"slots": [],
|
|
102
|
+
"exports": {
|
|
103
|
+
"customElement": "ds-agent-source-list",
|
|
104
|
+
"react": "DsAgentSourceList",
|
|
105
|
+
"angular": "DsAgentSourceList"
|
|
106
|
+
},
|
|
107
|
+
"consumption": {
|
|
108
|
+
"install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
|
|
109
|
+
"cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
|
|
110
|
+
"customElements": {
|
|
111
|
+
"import": "import '@ds-mo/ui/dist/components/ds-agent-source-list.js';",
|
|
112
|
+
"example": "<ds-agent-source-list></ds-agent-source-list>"
|
|
113
|
+
},
|
|
114
|
+
"react": {
|
|
115
|
+
"import": "import { DsAgentSourceList } from '@ds-mo/ui/react';",
|
|
116
|
+
"example": "<DsAgentSourceList />"
|
|
117
|
+
},
|
|
118
|
+
"angular": {
|
|
119
|
+
"import": "import { DsAgentSourceList } from '@ds-mo/ui/angular/ds-agent-source-list';",
|
|
120
|
+
"example": "<ds-agent-source-list></ds-agent-source-list>"
|
|
121
|
+
},
|
|
122
|
+
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: items.",
|
|
123
|
+
"peerDependencies": {
|
|
124
|
+
"required": [
|
|
125
|
+
"@ds-mo/tokens ^3.1.1",
|
|
126
|
+
"@ds-mo/icons ^6.2.0"
|
|
127
|
+
],
|
|
128
|
+
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"dependencies": [
|
|
133
|
+
"@ds-mo/ui",
|
|
134
|
+
"@ds-mo/tokens",
|
|
135
|
+
"@ds-mo/icons"
|
|
136
|
+
],
|
|
137
|
+
"registryDependencies": [
|
|
138
|
+
"icon",
|
|
139
|
+
"text"
|
|
140
|
+
],
|
|
141
|
+
"files": [
|
|
142
|
+
{
|
|
143
|
+
"path": "src/wc/components/AgentSourceList/AgentSourceList.css",
|
|
144
|
+
"content": ":host { display: block; }\n.agent-sources { border-block-start: var(--dimension-stroke-width-012) solid var(--color-border-tertiary); }\nsummary { align-items: center; cursor: pointer; display: flex; gap: var(--dimension-space-050); list-style: none; padding-block: var(--dimension-space-075); }\nsummary::-webkit-details-marker { display: none; }\ndetails[open] summary ds-icon { transform: rotate(90deg); }\nol { display: grid; gap: var(--dimension-space-075); margin: 0; padding: 0 0 var(--dimension-space-075) var(--dimension-space-150); }\nli { display: grid; gap: var(--dimension-space-025); }\na { align-items: center; color: inherit; display: inline-flex; gap: var(--dimension-space-025); width: fit-content; }\n\n@media (prefers-reduced-motion: no-preference) { summary ds-icon { transition: transform var(--effect-motion-short-2); } }\n",
|
|
145
|
+
"type": "registry:ui"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"path": "src/wc/components/AgentSourceList/AgentSourceList.tsx",
|
|
149
|
+
"content": "import { Component, Prop, h, Host } from '@stencil/core';\nimport type { AgentSource } from '../conversation-types';\n\n@Component({ tag: 'ds-agent-source-list', styleUrl: 'AgentSourceList.css', scoped: true })\nexport class AgentSourceList {\n @Prop() items: AgentSource[] = [];\n @Prop() heading: string = 'Sources';\n @Prop() open: boolean = false;\n\n private safeUrl(value: string) {\n try {\n const parsed = new URL(value, document.baseURI);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:' ? parsed.href : undefined;\n } catch { return undefined; }\n }\n\n render() {\n if (!this.items.length) return null;\n return (\n <Host>\n <details class=\"agent-sources\" open={this.open}>\n <summary>\n <ds-icon name=\"ChevronRight\" size=\"xs\" color=\"inherit\" />\n <ds-text variant=\"text-body-small\" emphasis>{this.heading} · {this.items.length}</ds-text>\n </summary>\n <ol>\n {this.items.map(source => {\n const href = this.safeUrl(source.url);\n return <li>\n {href\n ? <a href={href} target=\"_blank\" rel=\"noopener noreferrer\"><ds-text variant=\"text-body-small\" emphasis>{source.title}</ds-text><ds-icon name=\"ExternalLink\" size=\"xs\" color=\"inherit\" /></a>\n : <ds-text variant=\"text-body-small\" emphasis>{source.title}</ds-text>}\n {source.description ? <ds-text variant=\"text-caption\" color=\"secondary\">{source.description}</ds-text> : null}\n </li>;\n })}\n </ol>\n </details>\n </Host>\n );\n }\n}\n",
|
|
150
|
+
"type": "registry:ui"
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "agent-tool-call",
|
|
4
|
+
"title": "AgentToolCall",
|
|
5
|
+
"description": "Display-only disclosure for an agent tool call, its safe input or output, and execution status.",
|
|
6
|
+
"type": "registry:ui",
|
|
7
|
+
"meta": {
|
|
8
|
+
"library": "@ds-mo/ui",
|
|
9
|
+
"distribution": "npm",
|
|
10
|
+
"storybook": "https://zainadeel.github.io/compomo/?path=/story/agent-tool-call",
|
|
11
|
+
"source": "src/wc/components/AgentToolCall/AgentToolCall.tsx",
|
|
12
|
+
"intentStatus": "complete",
|
|
13
|
+
"intent": {
|
|
14
|
+
"audience": "specialized",
|
|
15
|
+
"status": "experimental",
|
|
16
|
+
"summary": "Display-only disclosure for an agent tool call, its safe input or output, and execution status.",
|
|
17
|
+
"useWhen": [
|
|
18
|
+
"A prototype or agent product needs to expose user-safe tool execution detail."
|
|
19
|
+
],
|
|
20
|
+
"avoidWhen": [
|
|
21
|
+
"A participant must approve, deny, edit, or retry the tool call; those are product controls outside this component."
|
|
22
|
+
],
|
|
23
|
+
"commonlyComposedWith": [
|
|
24
|
+
"component:ds-agent-response",
|
|
25
|
+
"component:ds-code-block"
|
|
26
|
+
],
|
|
27
|
+
"patterns": [
|
|
28
|
+
"pattern:agent-chat"
|
|
29
|
+
],
|
|
30
|
+
"accessibility": [
|
|
31
|
+
"Queued, running, success, error, and denied states are available as text.",
|
|
32
|
+
"The disclosure uses native keyboard and expanded-state semantics."
|
|
33
|
+
],
|
|
34
|
+
"states": [
|
|
35
|
+
"This component presents state but never executes a tool or owns approval policy."
|
|
36
|
+
],
|
|
37
|
+
"responsiveBehavior": [
|
|
38
|
+
"Structured detail wraps and scrolls without widening the transcript."
|
|
39
|
+
],
|
|
40
|
+
"references": [
|
|
41
|
+
{
|
|
42
|
+
"label": "Storybook examples",
|
|
43
|
+
"path": "src/wc/components/MessageScroller/MessageScroller.stories.ts"
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"api": {
|
|
48
|
+
"props": {
|
|
49
|
+
"error": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"resolvedType": "string | undefined",
|
|
52
|
+
"attribute": "error",
|
|
53
|
+
"required": false,
|
|
54
|
+
"mutable": false
|
|
55
|
+
},
|
|
56
|
+
"input": {
|
|
57
|
+
"type": "unknown",
|
|
58
|
+
"resolvedType": "unknown",
|
|
59
|
+
"required": false,
|
|
60
|
+
"mutable": false
|
|
61
|
+
},
|
|
62
|
+
"label": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"resolvedType": "string",
|
|
65
|
+
"attribute": "label",
|
|
66
|
+
"default": "''",
|
|
67
|
+
"required": false,
|
|
68
|
+
"mutable": false
|
|
69
|
+
},
|
|
70
|
+
"name": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"resolvedType": "string",
|
|
73
|
+
"attribute": "name",
|
|
74
|
+
"default": "''",
|
|
75
|
+
"required": false,
|
|
76
|
+
"mutable": false
|
|
77
|
+
},
|
|
78
|
+
"open": {
|
|
79
|
+
"type": "boolean",
|
|
80
|
+
"resolvedType": "boolean",
|
|
81
|
+
"attribute": "open",
|
|
82
|
+
"default": "false",
|
|
83
|
+
"required": false,
|
|
84
|
+
"mutable": false
|
|
85
|
+
},
|
|
86
|
+
"output": {
|
|
87
|
+
"type": "unknown",
|
|
88
|
+
"resolvedType": "unknown",
|
|
89
|
+
"required": false,
|
|
90
|
+
"mutable": false
|
|
91
|
+
},
|
|
92
|
+
"state": {
|
|
93
|
+
"type": "AgentToolState",
|
|
94
|
+
"resolvedType": "\"denied\" | \"error\" | \"queued\" | \"running\" | \"success\"",
|
|
95
|
+
"attribute": "state",
|
|
96
|
+
"default": "'queued'",
|
|
97
|
+
"required": false,
|
|
98
|
+
"mutable": false
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"events": [],
|
|
102
|
+
"methods": [],
|
|
103
|
+
"slots": []
|
|
104
|
+
},
|
|
105
|
+
"props": {
|
|
106
|
+
"error": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"resolvedType": "string | undefined",
|
|
109
|
+
"attribute": "error",
|
|
110
|
+
"required": false,
|
|
111
|
+
"mutable": false
|
|
112
|
+
},
|
|
113
|
+
"input": {
|
|
114
|
+
"type": "unknown",
|
|
115
|
+
"resolvedType": "unknown",
|
|
116
|
+
"required": false,
|
|
117
|
+
"mutable": false
|
|
118
|
+
},
|
|
119
|
+
"label": {
|
|
120
|
+
"type": "string",
|
|
121
|
+
"resolvedType": "string",
|
|
122
|
+
"attribute": "label",
|
|
123
|
+
"default": "''",
|
|
124
|
+
"required": false,
|
|
125
|
+
"mutable": false
|
|
126
|
+
},
|
|
127
|
+
"name": {
|
|
128
|
+
"type": "string",
|
|
129
|
+
"resolvedType": "string",
|
|
130
|
+
"attribute": "name",
|
|
131
|
+
"default": "''",
|
|
132
|
+
"required": false,
|
|
133
|
+
"mutable": false
|
|
134
|
+
},
|
|
135
|
+
"open": {
|
|
136
|
+
"type": "boolean",
|
|
137
|
+
"resolvedType": "boolean",
|
|
138
|
+
"attribute": "open",
|
|
139
|
+
"default": "false",
|
|
140
|
+
"required": false,
|
|
141
|
+
"mutable": false
|
|
142
|
+
},
|
|
143
|
+
"output": {
|
|
144
|
+
"type": "unknown",
|
|
145
|
+
"resolvedType": "unknown",
|
|
146
|
+
"required": false,
|
|
147
|
+
"mutable": false
|
|
148
|
+
},
|
|
149
|
+
"state": {
|
|
150
|
+
"type": "AgentToolState",
|
|
151
|
+
"resolvedType": "\"denied\" | \"error\" | \"queued\" | \"running\" | \"success\"",
|
|
152
|
+
"attribute": "state",
|
|
153
|
+
"default": "'queued'",
|
|
154
|
+
"required": false,
|
|
155
|
+
"mutable": false
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"events": [],
|
|
159
|
+
"methods": [],
|
|
160
|
+
"slots": [],
|
|
161
|
+
"exports": {
|
|
162
|
+
"customElement": "ds-agent-tool-call",
|
|
163
|
+
"react": "DsAgentToolCall",
|
|
164
|
+
"angular": "DsAgentToolCall"
|
|
165
|
+
},
|
|
166
|
+
"consumption": {
|
|
167
|
+
"install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
|
|
168
|
+
"cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
|
|
169
|
+
"customElements": {
|
|
170
|
+
"import": "import '@ds-mo/ui/dist/components/ds-agent-tool-call.js';",
|
|
171
|
+
"example": "<ds-agent-tool-call></ds-agent-tool-call>"
|
|
172
|
+
},
|
|
173
|
+
"react": {
|
|
174
|
+
"import": "import { DsAgentToolCall } from '@ds-mo/ui/react';",
|
|
175
|
+
"example": "<DsAgentToolCall />"
|
|
176
|
+
},
|
|
177
|
+
"angular": {
|
|
178
|
+
"import": "import { DsAgentToolCall } from '@ds-mo/ui/angular/ds-agent-tool-call';",
|
|
179
|
+
"example": "<ds-agent-tool-call></ds-agent-tool-call>"
|
|
180
|
+
},
|
|
181
|
+
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: input, output.",
|
|
182
|
+
"peerDependencies": {
|
|
183
|
+
"required": [
|
|
184
|
+
"@ds-mo/tokens ^3.1.1",
|
|
185
|
+
"@ds-mo/icons ^6.2.0"
|
|
186
|
+
],
|
|
187
|
+
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
"dependencies": [
|
|
192
|
+
"@ds-mo/ui",
|
|
193
|
+
"@ds-mo/tokens",
|
|
194
|
+
"@ds-mo/icons"
|
|
195
|
+
],
|
|
196
|
+
"registryDependencies": [
|
|
197
|
+
"icon",
|
|
198
|
+
"loader",
|
|
199
|
+
"text"
|
|
200
|
+
],
|
|
201
|
+
"files": [
|
|
202
|
+
{
|
|
203
|
+
"path": "src/wc/components/AgentToolCall/AgentToolCall.css",
|
|
204
|
+
"content": ":host { display: block; }\n.agent-tool { border: var(--dimension-stroke-width-012) solid var(--color-border-tertiary); border-radius: var(--dimension-radius-050); }\nsummary { align-items: center; cursor: pointer; display: grid; gap: var(--dimension-space-050); grid-template-columns: auto minmax(0, 1fr) auto; list-style: none; padding: var(--dimension-space-075) var(--dimension-space-100); }\nsummary::-webkit-details-marker { display: none; }\n.agent-tool__status { align-items: center; color: var(--color-foreground-faint-neutral); display: flex; }\n.agent-tool--running .agent-tool__status, .agent-tool--queued .agent-tool__status { color: var(--color-foreground-faint-brand); }\n.agent-tool--error .agent-tool__status, .agent-tool--denied .agent-tool__status { color: var(--color-foreground-bold-negative); }\n.agent-tool__title { display: grid; gap: var(--dimension-space-025); }\ndetails[open] .agent-tool__chevron { transform: rotate(90deg); }\n.agent-tool__details { display: grid; gap: var(--dimension-space-075); padding: 0 var(--dimension-space-100) var(--dimension-space-100); }\nsection { display: grid; gap: var(--dimension-space-025); }\npre { background: var(--color-background-secondary); border-radius: var(--dimension-radius-050); margin: 0; overflow: auto; padding: var(--dimension-space-075); white-space: pre-wrap; }\n\n@media (prefers-reduced-motion: no-preference) { .agent-tool__chevron { transition: transform var(--effect-motion-short-2); } }\n",
|
|
205
|
+
"type": "registry:ui"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"path": "src/wc/components/AgentToolCall/AgentToolCall.tsx",
|
|
209
|
+
"content": "import { Component, Prop, h, Host } from '@stencil/core';\nimport type { AgentToolState } from '../conversation-types';\n\n@Component({ tag: 'ds-agent-tool-call', styleUrl: 'AgentToolCall.css', scoped: true })\nexport class AgentToolCall {\n @Prop() name: string = '';\n @Prop() label: string = '';\n @Prop() state: AgentToolState = 'queued';\n @Prop() input?: unknown;\n @Prop() output?: unknown;\n @Prop() error?: string;\n @Prop() open: boolean = false;\n\n private serialize(value: unknown) {\n if (value === undefined) return '';\n if (typeof value === 'string') return value;\n try { return JSON.stringify(value, null, 2); } catch { return String(value); }\n }\n\n render() {\n const active = this.state === 'queued' || this.state === 'running';\n const status = this.state.charAt(0).toUpperCase() + this.state.slice(1);\n return (\n <Host>\n <details class={`agent-tool agent-tool--${this.state}`} open={this.open}>\n <summary>\n <span class=\"agent-tool__status\" aria-hidden=\"true\">\n {active ? <ds-loader size=\"xs\" color=\"inherit\" /> : <ds-icon name={this.state === 'success' ? 'Check' : 'ErrorTriangle'} size=\"xs\" color=\"inherit\" />}\n </span>\n <span class=\"agent-tool__title\">\n <ds-text variant=\"text-body-small\" emphasis>{this.label || this.name}</ds-text>\n <ds-text variant=\"text-caption\" color=\"secondary\">{status}</ds-text>\n </span>\n <ds-icon class=\"agent-tool__chevron\" name=\"ChevronRight\" size=\"xs\" color=\"inherit\" />\n </summary>\n <div class=\"agent-tool__details\">\n {this.input !== undefined ? <section><ds-text variant=\"text-caption\" emphasis>Input</ds-text><pre>{this.serialize(this.input)}</pre></section> : null}\n {this.output !== undefined ? <section><ds-text variant=\"text-caption\" emphasis>Output</ds-text><pre>{this.serialize(this.output)}</pre></section> : null}\n {this.error ? <section><ds-text variant=\"text-caption\" emphasis>Error</ds-text><pre>{this.error}</pre></section> : null}\n </div>\n </details>\n </Host>\n );\n }\n}\n",
|
|
210
|
+
"type": "registry:ui"
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
}
|
|
@@ -198,12 +198,12 @@
|
|
|
198
198
|
"files": [
|
|
199
199
|
{
|
|
200
200
|
"path": "src/wc/components/AppShell/AppShell.css",
|
|
201
|
-
"content": ":host {\n display: block;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n
|
|
201
|
+
"content": ":host {\n display: block;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n overflow: hidden;\n overscroll-behavior: none;\n --ds-shell-panel-tools-width: var(--dimension-panel-width-xs);\n}\n\n.app-shell {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n overflow: hidden;\n overscroll-behavior: none;\n font-family: var(--typography-font-family, system-ui);\n}\n\n:host {\n --_shell-chrome-bg: var(--color-background-secondary);\n}\n\n.app-shell__row {\n display: flex;\n flex: 1 1 auto;\n min-height: 0;\n height: 100%;\n position: relative;\n}\n\n/*\n * One chrome layer behind the shell row. Wash uses background-attachment: fixed\n * so the pattern is locked to the viewport — panel/tools collapse only changes the\n * transparent window, not the pattern phase. JS sets wash background-size from\n * readShellViewportDimensions(), not the shell element box.\n */\n.app-shell__chrome {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 0;\n background-color: var(--_shell-chrome-bg);\n}\n\n:host(.app-shell--gradient) .app-shell__chrome::before {\n content: '';\n position: absolute;\n inset: 0;\n pointer-events: none;\n background-position: 0 0;\n background-attachment: fixed;\n z-index: 1;\n opacity: var(--ds-shell-gradient-opacity, 1);\n background-image: var(--ds-shell-gradient-image, none);\n background-size: var(--ds-shell-gradient-size, auto);\n background-repeat: no-repeat;\n}\n\n.app-shell__panel {\n flex: 0 0 auto;\n min-height: 0;\n height: 100%;\n position: relative;\n /* Above main so resize handle line can paint over the workspace edge */\n z-index: 2;\n}\n\n.app-shell__panel ::slotted(ds-panel-nav) {\n display: block;\n height: 100%;\n}\n\n.app-shell__main {\n flex: 1 1 auto;\n min-width: 0;\n min-height: 0;\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n grid-template-rows: auto minmax(0, 1fr);\n grid-template-areas:\n 'bar tools'\n 'content tools';\n position: relative;\n z-index: 1;\n}\n\n.app-shell__bar {\n grid-area: bar;\n flex: 0 0 auto;\n min-width: 0;\n}\n\n.app-shell__bar ::slotted(ds-bar-nav) {\n display: block;\n}\n\n.app-shell__content {\n grid-area: content;\n flex: 1 1 auto;\n min-width: 0;\n min-height: 0;\n overflow: auto;\n overscroll-behavior: none;\n /* Limit reflow to the page column — not on __main (breaks tools flex shrink). */\n contain: layout;\n}\n\n/* Opaque page surface — masks the fixed chrome layer in the content column. */\n.app-shell__content {\n position: relative;\n z-index: 1;\n background-color: var(--color-background-primary);\n}\n\n.app-shell__tools {\n grid-area: tools;\n flex: 0 0 auto;\n min-width: 0;\n min-height: 0;\n height: 100%;\n display: flex;\n position: relative;\n z-index: 0;\n overflow: hidden;\n}\n\n.app-shell__tools ::slotted(ds-panel-tools) {\n display: block;\n height: 100%;\n min-height: 0;\n}\n\n:host(.app-shell--tools-fullscreen) .app-shell__panel,\n:host(.app-shell--tools-fullscreen) .app-shell__bar,\n:host(.app-shell--tools-fullscreen) .app-shell__content {\n visibility: hidden;\n}\n",
|
|
202
202
|
"type": "registry:ui"
|
|
203
203
|
},
|
|
204
204
|
{
|
|
205
205
|
"path": "src/wc/components/AppShell/AppShell.tsx",
|
|
206
|
-
"content": "import { Component, Prop, Element, Watch, Listen, h, Host } from '@stencil/core';\nimport type { NavChromeStyle } from '../../shell/nav-chrome';\nimport {\n isEditableShortcutTarget,\n resolveShellShortcut,\n} from '../../shell/shell-shortcuts';\nimport type { PanelToolsToolId } from '../PanelTools/panel-tools-types';\nimport {\n DEFAULT_SHELL_GRADIENT_PRESET,\n normalizeShellGradientPreset,\n type ShellGradientPreset,\n} from '../../shell/shell-gradient-presets';\nimport {\n CHROME_TRANSITION_END,\n CHROME_TRANSITION_START,\n ChromeTransitionDepth,\n createRafCoalescer,\n readChromeTransitionSource,\n} from '../../shell/chrome-transition';\nimport {\n isPanelNavCollapsed,\n panelWidthPxFromTokens,\n readPanelNavWidthTokens,\n type PanelNavWidthTokens,\n} from '../../shell/shell-chrome-metrics';\nimport {\n SHELL_GRADIENT_IMAGE_VAR,\n SHELL_GRADIENT_OPACITY_VAR,\n SHELL_GRADIENT_POSITION_BAR_VAR,\n SHELL_GRADIENT_POSITION_PANEL_VAR,\n SHELL_GRADIENT_SIZE_VAR,\n buildShellRadialGradient,\n readShellViewportDimensions,\n shellGradientPositionBar,\n shellGradientPositionPanel,\n shellGradientPresetOpacity,\n shellGradientSize,\n} from '../../shell/shell-gradient';\n\n@Component({\n tag: 'ds-app-shell',\n styleUrl: 'AppShell.css',\n scoped: true,\n})\nexport class AppShell {\n /** Chrome style propagated to slotted `ds-panel-nav` and `ds-bar-nav`. */\n @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'dashboard';\n\n /**\n * Shell chrome wash preset. `none` renders solid chrome; the remaining\n * presets use token-based washes that adapt to the active color theme.\n */\n @Prop({ attribute: 'gradient-preset', reflect: true }) gradientPreset: ShellGradientPreset =\n DEFAULT_SHELL_GRADIENT_PRESET;\n\n /** When `true` (default), registers global shell keyboard shortcuts. `[` toggles panel nav; `]` closes tools; K/A/S/M/N/? toggle tool drawers. Modifiers are ignored so browser chords like ⌘N stay native. */\n @Prop({ attribute: 'shortcuts-enabled' }) shortcutsEnabled: boolean = true;\n\n @Element() el!: HTMLElement;\n\n private resizeObserver: ResizeObserver | null = null;\n private readonly panelNavTransition = new ChromeTransitionDepth();\n private readonly chromeSyncCoalescer = createRafCoalescer(() => this.syncChrome());\n private panelWidthTokens: PanelNavWidthTokens = { expandedPx: 0, collapsedPx: 0 };\n private cachedViewportWidth = 0;\n private cachedViewportHeight = 0;\n private onWindowResize = () => {\n if (this.panelNavTransition.isActive) return;\n this.scheduleChromeSync();\n };\n private onVisualViewportChange = () => {\n if (this.panelNavTransition.isActive) return;\n this.scheduleChromeSync();\n };\n\n componentDidLoad() {\n this.syncSlottedNavStyle();\n this.connectMetricsObserver();\n this.connectViewportListeners();\n this.el.addEventListener(CHROME_TRANSITION_START, this.onChromeTransitionStart);\n this.el.addEventListener(CHROME_TRANSITION_END, this.onChromeTransitionEnd);\n requestAnimationFrame(() => {\n this.cachePanelWidthTokens();\n this.scheduleChromeSync();\n });\n }\n\n disconnectedCallback() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n this.disconnectViewportListeners();\n this.chromeSyncCoalescer.cancel();\n this.el.removeEventListener(CHROME_TRANSITION_START, this.onChromeTransitionStart);\n this.el.removeEventListener(CHROME_TRANSITION_END, this.onChromeTransitionEnd);\n }\n\n @Watch('navStyle')\n @Watch('gradientPreset')\n onShellPropsChange() {\n this.syncSlottedNavStyle();\n this.scheduleChromeSync();\n }\n\n private onChromeTransitionStart = (event: Event) => {\n if (readChromeTransitionSource(event) !== 'panel-nav') return;\n\n this.panelNavTransition.enter();\n const viewport = readShellViewportDimensions();\n this.cachedViewportWidth = viewport.width;\n this.cachedViewportHeight = viewport.height;\n this.syncChrome();\n };\n\n private onChromeTransitionEnd = (event: Event) => {\n if (readChromeTransitionSource(event) !== 'panel-nav') return;\n\n this.panelNavTransition.exit();\n if (!this.panelNavTransition.isActive) {\n this.scheduleChromeSync();\n }\n };\n\n /** Coalesce ResizeObserver bursts to one layout read per frame. */\n private scheduleChromeSync() {\n this.chromeSyncCoalescer.schedule();\n }\n\n private syncSlottedNavStyle() {\n const panel = this.el.querySelector('ds-panel-nav') as (HTMLElement & { navStyle: NavChromeStyle }) | null;\n const bar = this.el.querySelector('ds-bar-nav') as (HTMLElement & { navStyle: NavChromeStyle }) | null;\n if (panel) {\n panel.setAttribute('nav-style', this.navStyle);\n panel.navStyle = this.navStyle;\n }\n if (bar) {\n bar.setAttribute('nav-style', this.navStyle);\n bar.navStyle = this.navStyle;\n }\n }\n\n private connectMetricsObserver() {\n this.resizeObserver = new ResizeObserver(() => {\n if (this.panelNavTransition.isActive) return;\n this.scheduleChromeSync();\n });\n this.resizeObserver.observe(this.el);\n const panelWrap = this.el.querySelector('.app-shell__panel');\n if (panelWrap) this.resizeObserver.observe(panelWrap);\n }\n\n private connectViewportListeners() {\n if (typeof window === 'undefined') return;\n\n window.addEventListener('resize', this.onWindowResize, { passive: true });\n\n const visual = window.visualViewport;\n if (visual) {\n visual.addEventListener('resize', this.onVisualViewportChange, { passive: true });\n visual.addEventListener('scroll', this.onVisualViewportChange, { passive: true });\n }\n }\n\n private disconnectViewportListeners() {\n if (typeof window === 'undefined') return;\n\n window.removeEventListener('resize', this.onWindowResize);\n\n const visual = window.visualViewport;\n if (visual) {\n visual.removeEventListener('resize', this.onVisualViewportChange);\n visual.removeEventListener('scroll', this.onVisualViewportChange);\n }\n }\n\n private cachePanelWidthTokens() {\n const navRoot = this.el.querySelector('ds-panel-nav .panel-nav') as HTMLElement | null;\n if (!navRoot) return;\n this.panelWidthTokens = readPanelNavWidthTokens(navRoot);\n }\n\n private applyGradientVars(target: HTMLElement, vars: Record<string, string | null>) {\n const style = target.style;\n for (const [name, value] of Object.entries(vars)) {\n if (value === null) style.removeProperty(name);\n else style.setProperty(name, value);\n }\n }\n\n private clearGradientPaintVars(targets: HTMLElement[]) {\n const keys = [\n SHELL_GRADIENT_IMAGE_VAR,\n SHELL_GRADIENT_SIZE_VAR,\n SHELL_GRADIENT_OPACITY_VAR,\n ];\n for (const target of targets) {\n for (const key of keys) target.style.removeProperty(key);\n }\n }\n\n /** Panel/bar wash offsets for scroll fades and badge rings. */\n private syncChromeLayoutVars(\n panel: HTMLElement | null,\n bar: HTMLElement | null,\n panelPosition: string,\n barPosition: string,\n ) {\n if (panel) {\n panel.style.setProperty(SHELL_GRADIENT_POSITION_PANEL_VAR, panelPosition);\n }\n if (bar) {\n bar.style.setProperty(SHELL_GRADIENT_POSITION_BAR_VAR, barPosition);\n }\n }\n\n private resolvePanelWidthPx(panelNav: HTMLElement | null): number {\n const navRoot = panelNav?.querySelector('.panel-nav') as HTMLElement | null;\n\n if (this.panelNavTransition.isActive && this.panelWidthTokens.expandedPx > 0) {\n const collapsed = isPanelNavCollapsed(panelNav, navRoot);\n return panelWidthPxFromTokens(this.panelWidthTokens, collapsed);\n }\n\n const panelWrap = this.el.querySelector('.app-shell__panel') as HTMLElement | null;\n const measured = panelWrap?.getBoundingClientRect().width ?? 0;\n if (measured > 0) return measured;\n\n if (this.panelWidthTokens.expandedPx > 0) {\n const collapsed = isPanelNavCollapsed(panelNav, navRoot);\n return panelWidthPxFromTokens(this.panelWidthTokens, collapsed);\n }\n\n return 0;\n }\n\n /** Fixed-attachment wash/grid size — always the viewport, never the shell element box. */\n private resolveViewportDimensions(): { width: number; height: number } {\n if (this.panelNavTransition.isActive && this.cachedViewportWidth > 0) {\n return {\n width: this.cachedViewportWidth,\n height: this.cachedViewportHeight,\n };\n }\n\n return readShellViewportDimensions();\n }\n\n private chromeLayerActive(): boolean {\n return normalizeShellGradientPreset(this.gradientPreset) !== 'none';\n }\n\n @Listen('keydown', { target: 'window', capture: true })\n handleWindowKeyDown(e: KeyboardEvent) {\n if (!this.shortcutsEnabled) return;\n if (isEditableShortcutTarget(e.target)) return;\n\n const action = resolveShellShortcut(e);\n if (!action) return;\n\n e.preventDefault();\n\n const panel = this.el.querySelector('ds-panel-nav') as HTMLDsPanelNavElement | null;\n const tools = this.el.querySelector('ds-panel-tools') as HTMLDsPanelToolsElement | null;\n\n if (action === 'toggle-panel-nav') {\n void panel?.toggleCollapsed();\n return;\n }\n\n if (action === 'close-panel-tools') {\n void tools?.closeDrawer();\n return;\n }\n\n if (action.startsWith('open-tool:') && tools) {\n const toolId = action.slice('open-tool:'.length) as PanelToolsToolId;\n void tools.activateTool(toolId);\n }\n }\n\n private syncChrome() {\n const panelNav = this.el.querySelector('ds-panel-nav') as HTMLElement | null;\n const bar = this.el.querySelector('ds-bar-nav') as HTMLElement | null;\n const targets = [this.el, panelNav, bar].filter((el): el is HTMLElement => el !== null);\n\n const clearLayoutVars = () => {\n if (panelNav) panelNav.style.removeProperty(SHELL_GRADIENT_POSITION_PANEL_VAR);\n if (bar) bar.style.removeProperty(SHELL_GRADIENT_POSITION_BAR_VAR);\n };\n\n const preset = normalizeShellGradientPreset(this.gradientPreset);\n if (preset === 'none') {\n this.clearGradientPaintVars(targets);\n clearLayoutVars();\n return;\n }\n\n const viewport = this.resolveViewportDimensions();\n const panelWidth = this.resolvePanelWidthPx(panelNav);\n\n const panelPosition = shellGradientPositionPanel();\n const barPosition = shellGradientPositionBar(panelWidth);\n\n this.syncChromeLayoutVars(panelNav, bar, panelPosition, barPosition);\n\n const image = buildShellRadialGradient(preset);\n\n const size = shellGradientSize({\n width: viewport.width,\n height: viewport.height,\n });\n const opacity = shellGradientPresetOpacity(preset);\n\n for (const target of targets) {\n if (target === this.el) {\n this.applyGradientVars(target, {\n [SHELL_GRADIENT_IMAGE_VAR]: image,\n [SHELL_GRADIENT_SIZE_VAR]: size,\n [SHELL_GRADIENT_POSITION_PANEL_VAR]: panelPosition,\n [SHELL_GRADIENT_POSITION_BAR_VAR]: barPosition,\n [SHELL_GRADIENT_OPACITY_VAR]: opacity,\n });\n continue;\n }\n\n const isBar = target.tagName.toLowerCase() === 'ds-bar-nav';\n this.applyGradientVars(target, {\n [SHELL_GRADIENT_IMAGE_VAR]: image,\n [SHELL_GRADIENT_SIZE_VAR]: size,\n [SHELL_GRADIENT_OPACITY_VAR]: opacity,\n [SHELL_GRADIENT_POSITION_PANEL_VAR]: isBar ? null : panelPosition,\n [SHELL_GRADIENT_POSITION_BAR_VAR]: isBar ? barPosition : null,\n });\n }\n }\n\n render() {\n const chromeActive = this.chromeLayerActive();\n const shellCls: Record<string, boolean> = {\n 'app-shell': true,\n 'app-shell--gradient': chromeActive,\n [`app-shell--${this.navStyle}`]: true,\n };\n\n return (\n <Host class={shellCls}>\n <div class=\"app-shell__row\">\n <div class=\"app-shell__chrome\" aria-hidden=\"true\" />\n <div class=\"app-shell__panel\">\n <slot name=\"panel\" />\n </div>\n <div class=\"app-shell__main\">\n <div class=\"app-shell__bar\">\n <slot name=\"bar\" />\n </div>\n <div class=\"app-shell__tools\">\n <slot name=\"tools\" />\n </div>\n <div class=\"app-shell__content\">\n <slot />\n </div>\n </div>\n </div>\n </Host>\n );\n }\n}\n",
|
|
206
|
+
"content": "import { Component, Prop, Element, State, Watch, Listen, h, Host } from '@stencil/core';\nimport type { NavChromeStyle } from '../../shell/nav-chrome';\nimport {\n isEditableShortcutTarget,\n resolveShellShortcut,\n} from '../../shell/shell-shortcuts';\nimport type { PanelToolsToolId } from '../PanelTools/panel-tools-types';\nimport {\n DEFAULT_SHELL_GRADIENT_PRESET,\n normalizeShellGradientPreset,\n type ShellGradientPreset,\n} from '../../shell/shell-gradient-presets';\nimport {\n CHROME_TRANSITION_END,\n CHROME_TRANSITION_START,\n ChromeTransitionDepth,\n createRafCoalescer,\n readChromeTransitionSource,\n} from '../../shell/chrome-transition';\nimport {\n isPanelNavCollapsed,\n panelWidthPxFromTokens,\n readPanelNavWidthTokens,\n type PanelNavWidthTokens,\n} from '../../shell/shell-chrome-metrics';\nimport {\n SHELL_GRADIENT_IMAGE_VAR,\n SHELL_GRADIENT_OPACITY_VAR,\n SHELL_GRADIENT_POSITION_BAR_VAR,\n SHELL_GRADIENT_POSITION_PANEL_VAR,\n SHELL_GRADIENT_SIZE_VAR,\n buildShellRadialGradient,\n readShellViewportDimensions,\n shellGradientPositionBar,\n shellGradientPositionPanel,\n shellGradientPresetOpacity,\n shellGradientSize,\n} from '../../shell/shell-gradient';\n\n@Component({\n tag: 'ds-app-shell',\n styleUrl: 'AppShell.css',\n scoped: true,\n})\nexport class AppShell {\n /** Chrome style propagated to slotted `ds-panel-nav` and `ds-bar-nav`. */\n @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'dashboard';\n\n /**\n * Shell chrome wash preset. `none` renders solid chrome; the remaining\n * presets use token-based washes that adapt to the active color theme.\n */\n @Prop({ attribute: 'gradient-preset', reflect: true }) gradientPreset: ShellGradientPreset =\n DEFAULT_SHELL_GRADIENT_PRESET;\n\n /** When `true` (default), registers global shell keyboard shortcuts. `[` toggles panel nav; `]` closes tools; K/A/S/M/N/? toggle tool drawers. Modifiers are ignored so browser chords like ⌘N stay native. */\n @Prop({ attribute: 'shortcuts-enabled' }) shortcutsEnabled: boolean = true;\n\n @Element() el!: HTMLElement;\n @State() private toolsFullscreen = false;\n\n private resizeObserver: ResizeObserver | null = null;\n private readonly panelNavTransition = new ChromeTransitionDepth();\n private readonly chromeSyncCoalescer = createRafCoalescer(() => this.syncChrome());\n private panelWidthTokens: PanelNavWidthTokens = { expandedPx: 0, collapsedPx: 0 };\n private cachedViewportWidth = 0;\n private cachedViewportHeight = 0;\n private onWindowResize = () => {\n if (this.panelNavTransition.isActive) return;\n this.scheduleChromeSync();\n };\n private onVisualViewportChange = () => {\n if (this.panelNavTransition.isActive) return;\n this.scheduleChromeSync();\n };\n\n componentDidLoad() {\n this.syncSlottedNavStyle();\n this.connectMetricsObserver();\n this.connectViewportListeners();\n this.el.addEventListener(CHROME_TRANSITION_START, this.onChromeTransitionStart);\n this.el.addEventListener(CHROME_TRANSITION_END, this.onChromeTransitionEnd);\n requestAnimationFrame(() => {\n this.cachePanelWidthTokens();\n this.scheduleChromeSync();\n });\n const tools = this.el.querySelector('ds-panel-tools');\n this.toolsFullscreen = tools?.getAttribute('presentation') === 'fullscreen';\n }\n\n @Listen('dsPresentationChange')\n handleToolsPresentation(event: CustomEvent<{ presentation?: string }>) {\n this.toolsFullscreen = event.detail?.presentation === 'fullscreen';\n }\n\n disconnectedCallback() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n this.disconnectViewportListeners();\n this.chromeSyncCoalescer.cancel();\n this.el.removeEventListener(CHROME_TRANSITION_START, this.onChromeTransitionStart);\n this.el.removeEventListener(CHROME_TRANSITION_END, this.onChromeTransitionEnd);\n }\n\n @Watch('navStyle')\n @Watch('gradientPreset')\n onShellPropsChange() {\n this.syncSlottedNavStyle();\n this.scheduleChromeSync();\n }\n\n private onChromeTransitionStart = (event: Event) => {\n if (readChromeTransitionSource(event) !== 'panel-nav') return;\n\n this.panelNavTransition.enter();\n const viewport = readShellViewportDimensions();\n this.cachedViewportWidth = viewport.width;\n this.cachedViewportHeight = viewport.height;\n this.syncChrome();\n };\n\n private onChromeTransitionEnd = (event: Event) => {\n if (readChromeTransitionSource(event) !== 'panel-nav') return;\n\n this.panelNavTransition.exit();\n if (!this.panelNavTransition.isActive) {\n this.scheduleChromeSync();\n }\n };\n\n /** Coalesce ResizeObserver bursts to one layout read per frame. */\n private scheduleChromeSync() {\n this.chromeSyncCoalescer.schedule();\n }\n\n private syncSlottedNavStyle() {\n const panel = this.el.querySelector('ds-panel-nav') as (HTMLElement & { navStyle: NavChromeStyle }) | null;\n const bar = this.el.querySelector('ds-bar-nav') as (HTMLElement & { navStyle: NavChromeStyle }) | null;\n if (panel) {\n panel.setAttribute('nav-style', this.navStyle);\n panel.navStyle = this.navStyle;\n }\n if (bar) {\n bar.setAttribute('nav-style', this.navStyle);\n bar.navStyle = this.navStyle;\n }\n }\n\n private connectMetricsObserver() {\n this.resizeObserver = new ResizeObserver(() => {\n if (this.panelNavTransition.isActive) return;\n this.scheduleChromeSync();\n });\n this.resizeObserver.observe(this.el);\n const panelWrap = this.el.querySelector('.app-shell__panel');\n if (panelWrap) this.resizeObserver.observe(panelWrap);\n }\n\n private connectViewportListeners() {\n if (typeof window === 'undefined') return;\n\n window.addEventListener('resize', this.onWindowResize, { passive: true });\n\n const visual = window.visualViewport;\n if (visual) {\n visual.addEventListener('resize', this.onVisualViewportChange, { passive: true });\n visual.addEventListener('scroll', this.onVisualViewportChange, { passive: true });\n }\n }\n\n private disconnectViewportListeners() {\n if (typeof window === 'undefined') return;\n\n window.removeEventListener('resize', this.onWindowResize);\n\n const visual = window.visualViewport;\n if (visual) {\n visual.removeEventListener('resize', this.onVisualViewportChange);\n visual.removeEventListener('scroll', this.onVisualViewportChange);\n }\n }\n\n private cachePanelWidthTokens() {\n const navRoot = this.el.querySelector('ds-panel-nav .panel-nav') as HTMLElement | null;\n if (!navRoot) return;\n this.panelWidthTokens = readPanelNavWidthTokens(navRoot);\n }\n\n private applyGradientVars(target: HTMLElement, vars: Record<string, string | null>) {\n const style = target.style;\n for (const [name, value] of Object.entries(vars)) {\n if (value === null) style.removeProperty(name);\n else style.setProperty(name, value);\n }\n }\n\n private clearGradientPaintVars(targets: HTMLElement[]) {\n const keys = [\n SHELL_GRADIENT_IMAGE_VAR,\n SHELL_GRADIENT_SIZE_VAR,\n SHELL_GRADIENT_OPACITY_VAR,\n ];\n for (const target of targets) {\n for (const key of keys) target.style.removeProperty(key);\n }\n }\n\n /** Panel/bar wash offsets for scroll fades and badge rings. */\n private syncChromeLayoutVars(\n panel: HTMLElement | null,\n bar: HTMLElement | null,\n panelPosition: string,\n barPosition: string,\n ) {\n if (panel) {\n panel.style.setProperty(SHELL_GRADIENT_POSITION_PANEL_VAR, panelPosition);\n }\n if (bar) {\n bar.style.setProperty(SHELL_GRADIENT_POSITION_BAR_VAR, barPosition);\n }\n }\n\n private resolvePanelWidthPx(panelNav: HTMLElement | null): number {\n const navRoot = panelNav?.querySelector('.panel-nav') as HTMLElement | null;\n\n if (this.panelNavTransition.isActive && this.panelWidthTokens.expandedPx > 0) {\n const collapsed = isPanelNavCollapsed(panelNav, navRoot);\n return panelWidthPxFromTokens(this.panelWidthTokens, collapsed);\n }\n\n const panelWrap = this.el.querySelector('.app-shell__panel') as HTMLElement | null;\n const measured = panelWrap?.getBoundingClientRect().width ?? 0;\n if (measured > 0) return measured;\n\n if (this.panelWidthTokens.expandedPx > 0) {\n const collapsed = isPanelNavCollapsed(panelNav, navRoot);\n return panelWidthPxFromTokens(this.panelWidthTokens, collapsed);\n }\n\n return 0;\n }\n\n /** Fixed-attachment wash/grid size — always the viewport, never the shell element box. */\n private resolveViewportDimensions(): { width: number; height: number } {\n if (this.panelNavTransition.isActive && this.cachedViewportWidth > 0) {\n return {\n width: this.cachedViewportWidth,\n height: this.cachedViewportHeight,\n };\n }\n\n return readShellViewportDimensions();\n }\n\n private chromeLayerActive(): boolean {\n return normalizeShellGradientPreset(this.gradientPreset) !== 'none';\n }\n\n @Listen('keydown', { target: 'window', capture: true })\n handleWindowKeyDown(e: KeyboardEvent) {\n if (!this.shortcutsEnabled) return;\n if (isEditableShortcutTarget(e.target)) return;\n\n const action = resolveShellShortcut(e);\n if (!action) return;\n\n e.preventDefault();\n\n const panel = this.el.querySelector('ds-panel-nav') as HTMLDsPanelNavElement | null;\n const tools = this.el.querySelector('ds-panel-tools') as HTMLDsPanelToolsElement | null;\n\n if (action === 'toggle-panel-nav') {\n void panel?.toggleCollapsed();\n return;\n }\n\n if (action === 'close-panel-tools') {\n void tools?.closeDrawer();\n return;\n }\n\n if (action.startsWith('open-tool:') && tools) {\n const toolId = action.slice('open-tool:'.length) as PanelToolsToolId;\n void tools.activateTool(toolId);\n }\n }\n\n private syncChrome() {\n const panelNav = this.el.querySelector('ds-panel-nav') as HTMLElement | null;\n const bar = this.el.querySelector('ds-bar-nav') as HTMLElement | null;\n const targets = [this.el, panelNav, bar].filter((el): el is HTMLElement => el !== null);\n\n const clearLayoutVars = () => {\n if (panelNav) panelNav.style.removeProperty(SHELL_GRADIENT_POSITION_PANEL_VAR);\n if (bar) bar.style.removeProperty(SHELL_GRADIENT_POSITION_BAR_VAR);\n };\n\n const preset = normalizeShellGradientPreset(this.gradientPreset);\n if (preset === 'none') {\n this.clearGradientPaintVars(targets);\n clearLayoutVars();\n return;\n }\n\n const viewport = this.resolveViewportDimensions();\n const panelWidth = this.resolvePanelWidthPx(panelNav);\n\n const panelPosition = shellGradientPositionPanel();\n const barPosition = shellGradientPositionBar(panelWidth);\n\n this.syncChromeLayoutVars(panelNav, bar, panelPosition, barPosition);\n\n const image = buildShellRadialGradient(preset);\n\n const size = shellGradientSize({\n width: viewport.width,\n height: viewport.height,\n });\n const opacity = shellGradientPresetOpacity(preset);\n\n for (const target of targets) {\n if (target === this.el) {\n this.applyGradientVars(target, {\n [SHELL_GRADIENT_IMAGE_VAR]: image,\n [SHELL_GRADIENT_SIZE_VAR]: size,\n [SHELL_GRADIENT_POSITION_PANEL_VAR]: panelPosition,\n [SHELL_GRADIENT_POSITION_BAR_VAR]: barPosition,\n [SHELL_GRADIENT_OPACITY_VAR]: opacity,\n });\n continue;\n }\n\n const isBar = target.tagName.toLowerCase() === 'ds-bar-nav';\n this.applyGradientVars(target, {\n [SHELL_GRADIENT_IMAGE_VAR]: image,\n [SHELL_GRADIENT_SIZE_VAR]: size,\n [SHELL_GRADIENT_OPACITY_VAR]: opacity,\n [SHELL_GRADIENT_POSITION_PANEL_VAR]: isBar ? null : panelPosition,\n [SHELL_GRADIENT_POSITION_BAR_VAR]: isBar ? barPosition : null,\n });\n }\n }\n\n render() {\n const chromeActive = this.chromeLayerActive();\n const shellCls: Record<string, boolean> = {\n 'app-shell': true,\n 'app-shell--gradient': chromeActive,\n [`app-shell--${this.navStyle}`]: true,\n 'app-shell--tools-fullscreen': this.toolsFullscreen,\n };\n\n return (\n <Host class={shellCls}>\n <div class=\"app-shell__row\">\n <div class=\"app-shell__chrome\" aria-hidden=\"true\" />\n <div class=\"app-shell__panel\" aria-hidden={this.toolsFullscreen ? 'true' : undefined} inert={this.toolsFullscreen ? true : undefined}>\n <slot name=\"panel\" />\n </div>\n <div class=\"app-shell__main\">\n <div class=\"app-shell__bar\" aria-hidden={this.toolsFullscreen ? 'true' : undefined} inert={this.toolsFullscreen ? true : undefined}>\n <slot name=\"bar\" />\n </div>\n <div class=\"app-shell__tools\">\n <slot name=\"tools\" />\n </div>\n <div class=\"app-shell__content\" aria-hidden={this.toolsFullscreen ? 'true' : undefined} inert={this.toolsFullscreen ? true : undefined}>\n <slot />\n </div>\n </div>\n </div>\n </Host>\n );\n }\n}\n",
|
|
207
207
|
"type": "registry:ui"
|
|
208
208
|
}
|
|
209
209
|
]
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "attachment-list",
|
|
4
|
+
"title": "AttachmentList",
|
|
5
|
+
"description": "Channel-neutral list of message attachments with name, media type, size, and optional safe link.",
|
|
6
|
+
"type": "registry:ui",
|
|
7
|
+
"meta": {
|
|
8
|
+
"library": "@ds-mo/ui",
|
|
9
|
+
"distribution": "npm",
|
|
10
|
+
"storybook": "https://zainadeel.github.io/compomo/?path=/story/attachment-list",
|
|
11
|
+
"source": "src/wc/components/AttachmentList/AttachmentList.tsx",
|
|
12
|
+
"intentStatus": "complete",
|
|
13
|
+
"intent": {
|
|
14
|
+
"audience": "general",
|
|
15
|
+
"status": "experimental",
|
|
16
|
+
"summary": "Channel-neutral list of message attachments with name, media type, size, and optional safe link.",
|
|
17
|
+
"useWhen": [
|
|
18
|
+
"A conversation message needs to display already-known attachment metadata."
|
|
19
|
+
],
|
|
20
|
+
"avoidWhen": [
|
|
21
|
+
"Users need to choose, upload, remove, or edit files; those controls belong to the product workflow."
|
|
22
|
+
],
|
|
23
|
+
"commonlyComposedWith": [
|
|
24
|
+
"component:ds-message",
|
|
25
|
+
"component:ds-message-bubble"
|
|
26
|
+
],
|
|
27
|
+
"patterns": [
|
|
28
|
+
"pattern:conversation"
|
|
29
|
+
],
|
|
30
|
+
"accessibility": [
|
|
31
|
+
"Attachment name remains visible and is the link text when a safe URL is available.",
|
|
32
|
+
"Media type and size are supporting metadata, never the only identifier."
|
|
33
|
+
],
|
|
34
|
+
"responsiveBehavior": [
|
|
35
|
+
"Long names wrap or truncate without overflowing the message surface."
|
|
36
|
+
],
|
|
37
|
+
"references": [
|
|
38
|
+
{
|
|
39
|
+
"label": "Storybook examples",
|
|
40
|
+
"path": "src/wc/components/MessageScroller/MessageScroller.stories.ts"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"api": {
|
|
45
|
+
"props": {
|
|
46
|
+
"items": {
|
|
47
|
+
"type": "ConversationAttachment[]",
|
|
48
|
+
"resolvedType": "ConversationAttachment[]",
|
|
49
|
+
"default": "[]",
|
|
50
|
+
"required": false,
|
|
51
|
+
"mutable": false
|
|
52
|
+
},
|
|
53
|
+
"label": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"resolvedType": "string",
|
|
56
|
+
"attribute": "label",
|
|
57
|
+
"default": "'Attachments'",
|
|
58
|
+
"required": false,
|
|
59
|
+
"mutable": false
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"events": [],
|
|
63
|
+
"methods": [],
|
|
64
|
+
"slots": []
|
|
65
|
+
},
|
|
66
|
+
"props": {
|
|
67
|
+
"items": {
|
|
68
|
+
"type": "ConversationAttachment[]",
|
|
69
|
+
"resolvedType": "ConversationAttachment[]",
|
|
70
|
+
"default": "[]",
|
|
71
|
+
"required": false,
|
|
72
|
+
"mutable": false
|
|
73
|
+
},
|
|
74
|
+
"label": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"resolvedType": "string",
|
|
77
|
+
"attribute": "label",
|
|
78
|
+
"default": "'Attachments'",
|
|
79
|
+
"required": false,
|
|
80
|
+
"mutable": false
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"events": [],
|
|
84
|
+
"methods": [],
|
|
85
|
+
"slots": [],
|
|
86
|
+
"exports": {
|
|
87
|
+
"customElement": "ds-attachment-list",
|
|
88
|
+
"react": "DsAttachmentList",
|
|
89
|
+
"angular": "DsAttachmentList"
|
|
90
|
+
},
|
|
91
|
+
"consumption": {
|
|
92
|
+
"install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
|
|
93
|
+
"cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
|
|
94
|
+
"customElements": {
|
|
95
|
+
"import": "import '@ds-mo/ui/dist/components/ds-attachment-list.js';",
|
|
96
|
+
"example": "<ds-attachment-list></ds-attachment-list>"
|
|
97
|
+
},
|
|
98
|
+
"react": {
|
|
99
|
+
"import": "import { DsAttachmentList } from '@ds-mo/ui/react';",
|
|
100
|
+
"example": "<DsAttachmentList />"
|
|
101
|
+
},
|
|
102
|
+
"angular": {
|
|
103
|
+
"import": "import { DsAttachmentList } from '@ds-mo/ui/angular/ds-attachment-list';",
|
|
104
|
+
"example": "<ds-attachment-list></ds-attachment-list>"
|
|
105
|
+
},
|
|
106
|
+
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: items.",
|
|
107
|
+
"peerDependencies": {
|
|
108
|
+
"required": [
|
|
109
|
+
"@ds-mo/tokens ^3.1.1",
|
|
110
|
+
"@ds-mo/icons ^6.2.0"
|
|
111
|
+
],
|
|
112
|
+
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"dependencies": [
|
|
117
|
+
"@ds-mo/ui",
|
|
118
|
+
"@ds-mo/tokens",
|
|
119
|
+
"@ds-mo/icons"
|
|
120
|
+
],
|
|
121
|
+
"registryDependencies": [
|
|
122
|
+
"icon",
|
|
123
|
+
"text"
|
|
124
|
+
],
|
|
125
|
+
"files": [
|
|
126
|
+
{
|
|
127
|
+
"path": "src/wc/components/AttachmentList/AttachmentList.css",
|
|
128
|
+
"content": ":host {\n display: block;\n min-width: 0;\n box-sizing: border-box;\n}\n\n.attachment-list {\n display: flex;\n flex-wrap: wrap;\n gap: var(--dimension-space-050);\n}\n\n.attachment-list__item {\n display: flex;\n max-width: var(--dimension-form-width-sm);\n padding: var(--dimension-space-075);\n border-radius: var(--dimension-radius-025);\n background: var(--color-background-secondary);\n color: inherit;\n box-shadow: inset 0 0 0 var(--dimension-stroke-width-012) var(--color-border-tertiary);\n text-decoration: none;\n box-sizing: border-box;\n}\n\na.attachment-list__item:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-border-bold-brand);\n outline-offset: var(--dimension-stroke-width-012);\n}\n\n.attachment-list__item-content {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-075);\n min-width: 0;\n}\n\n.attachment-list__copy {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n",
|
|
129
|
+
"type": "registry:ui"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"path": "src/wc/components/AttachmentList/AttachmentList.tsx",
|
|
133
|
+
"content": "import { Component, h, Host, Prop } from '@stencil/core';\nimport type { ConversationAttachment } from '../conversation-types';\n\nfunction safeAttachmentUrl(value: string | undefined): string | undefined {\n if (!value) return undefined;\n try {\n const url = new URL(value, document.baseURI);\n return ['http:', 'https:', 'blob:'].includes(url.protocol) ? url.href : undefined;\n } catch {\n return undefined;\n }\n}\n\n@Component({\n tag: 'ds-attachment-list',\n styleUrl: 'AttachmentList.css',\n scoped: true,\n})\nexport class AttachmentList {\n @Prop() items: ConversationAttachment[] = [];\n @Prop() label: string = 'Attachments';\n\n private renderItem(item: ConversationAttachment) {\n const url = safeAttachmentUrl(item.url);\n const content = (\n <span class=\"attachment-list__item-content\">\n <ds-icon name=\"Document\" size=\"sm\" color=\"secondary\" />\n <span class=\"attachment-list__copy\">\n <ds-text as=\"span\" variant=\"text-body-small\" emphasis color=\"primary\" lineTruncation={1}>{item.name}</ds-text>\n {item.mediaType || item.size ? (\n <ds-text as=\"span\" variant=\"text-caption\" color=\"secondary\">\n {[item.mediaType, item.size].filter(Boolean).join(' · ')}\n </ds-text>\n ) : null}\n </span>\n </span>\n );\n return url ? (\n <a class=\"attachment-list__item\" href={url} target=\"_blank\" rel=\"noopener noreferrer\">{content}</a>\n ) : (\n <div class=\"attachment-list__item\">{content}</div>\n );\n }\n\n render() {\n return (\n <Host>\n <div class=\"attachment-list\" role=\"list\" aria-label={this.label}>\n {this.items.map(item => <div role=\"listitem\" key={item.id}>{this.renderItem(item)}</div>)}\n </div>\n </Host>\n );\n }\n}\n",
|
|
134
|
+
"type": "registry:ui"
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
}
|