@ds-mo/ui 12.9.0 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/.package-ready.json +1 -0
- package/dist/agent-patterns.json +124 -135
- package/dist/agent.json +249 -1108
- package/dist/angular/ds-bar-nav.d.ts +1 -1
- package/dist/angular/ds-bar-nav.js +3 -3
- package/dist/angular/ds-button-filled.d.ts +1 -1
- package/dist/angular/ds-button-filled.js +3 -3
- package/dist/angular/ds-card-data-viz.d.ts +18 -0
- package/dist/angular/{ds-card-data-viz-donut.js → ds-card-data-viz.js} +12 -12
- package/dist/angular/ds-card-overview.d.ts +1 -1
- package/dist/angular/ds-card-overview.js +3 -3
- package/dist/angular/ds-chart-bar.d.ts +1 -1
- package/dist/angular/ds-chart-bar.js +3 -3
- package/dist/angular/ds-menu.d.ts +1 -7
- package/dist/angular/ds-menu.js +2 -5
- package/dist/angular/ds-mobile-header.d.ts +1 -1
- package/dist/angular/ds-mobile-header.js +3 -3
- package/dist/angular/ds-mobile-section-switcher.d.ts +1 -1
- package/dist/angular/ds-mobile-section-switcher.js +3 -3
- package/dist/angular/ds-panel-tools.d.ts +1 -1
- package/dist/angular/ds-panel-tools.js +3 -3
- package/dist/angular/ds-select.d.ts +5 -4
- package/dist/angular/ds-select.js +3 -3
- package/dist/angular/ds-shell-app.d.ts +90 -1
- package/dist/angular/ds-shell-app.js +44 -4
- package/dist/angular/ds-shell-tools.d.ts +1 -1
- package/dist/angular/ds-shell-tools.js +3 -3
- package/dist/angular/index.d.ts +1 -1
- package/dist/angular/index.js +1 -8
- package/dist/angular/proxies.d.ts +1 -8
- package/dist/angular/proxies.js +1 -8
- package/dist/components/ds-agent-activity.js +1 -1
- package/dist/components/ds-agent-response.js +1 -1
- package/dist/components/ds-agent-source-list.js +1 -1
- package/dist/components/ds-agent-tool-call.js +1 -1
- package/dist/components/ds-attachment-list.js +1 -1
- package/dist/components/ds-badge.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-bar-title.js +1 -1
- package/dist/components/ds-bar-title.js.map +1 -1
- package/dist/components/ds-bar-workflow.js +1 -1
- package/dist/components/ds-breadcrumb.js +1 -1
- package/dist/components/ds-button-filled.js +1 -1
- package/dist/components/ds-button-unfilled.js +1 -1
- package/dist/components/{ds-select-multi.d.ts → ds-card-data-viz.d.ts} +4 -4
- package/dist/components/ds-card-data-viz.js +2 -0
- package/dist/components/ds-card-data-viz.js.map +1 -0
- package/dist/components/ds-card-overview.js +1 -1
- package/dist/components/ds-card-overview.js.map +1 -1
- package/dist/components/ds-card-setting.js +1 -1
- package/dist/components/ds-chart-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-legend.js.map +1 -1
- package/dist/components/ds-chart-line.js +1 -1
- package/dist/components/ds-chart-line.js.map +1 -1
- package/dist/components/ds-checkbox.js +1 -1
- package/dist/components/ds-chip.js +1 -1
- package/dist/components/ds-code-block.js +1 -1
- package/dist/components/ds-conversation-list-item.js +1 -1
- package/dist/components/ds-conversation-list-item.js.map +1 -1
- package/dist/components/ds-conversation-list-section.js +1 -1
- package/dist/components/ds-conversation-list.js +1 -1
- package/dist/components/ds-divider.js +1 -1
- package/dist/components/ds-empty-state.js +1 -1
- package/dist/components/ds-field.js +1 -1
- package/dist/components/ds-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-bubble.js +1 -1
- package/dist/components/ds-message-composer.js +1 -1
- package/dist/components/ds-message-composer.js.map +1 -1
- package/dist/components/ds-message-scroller.js +1 -1
- package/dist/components/ds-message.js +1 -1
- package/dist/components/ds-mobile-bar-nav.js +1 -1
- package/dist/components/ds-mobile-bar-nav.js.map +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-mobile-sheet-nav.js.map +1 -1
- 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.js +1 -1
- package/dist/components/ds-panel-tool-search.js +1 -1
- package/dist/components/ds-panel-tools.js +1 -1
- package/dist/components/ds-radio.js +1 -1
- package/dist/components/ds-radio.js.map +1 -1
- package/dist/components/ds-scroll-overlay.js +1 -1
- package/dist/components/ds-select.js +1 -1
- package/dist/components/ds-select.js.map +1 -1
- package/dist/components/ds-shell-app.js +1 -1
- package/dist/components/ds-shell-app.js.map +1 -1
- package/dist/components/ds-shell-page.js +1 -1
- package/dist/components/ds-shell-page.js.map +1 -1
- package/dist/components/ds-shell-tools.js +1 -1
- package/dist/components/ds-shell-tools.js.map +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-tag.js +1 -1
- package/dist/components/ds-text.js +1 -1
- package/dist/components/ds-toast.js +1 -1
- package/dist/components/ds-tooltip-data-viz.js +1 -1
- package/dist/components/ds-tooltip.js +1 -1
- package/dist/components/ds-typing-indicator.js +1 -1
- package/dist/components/{p-CgEYdMee.js → p-6qXDqCj_.js} +2 -2
- package/dist/components/{p-Cr3tEx7o.js → p-Ay1AX7Ql.js} +2 -2
- package/dist/components/p-B-qDb_Zo.js +2 -0
- package/dist/components/p-B-qDb_Zo.js.map +1 -0
- package/dist/components/{p-BOCfICln.js → p-B1cbQ0SG.js} +2 -2
- package/dist/components/{p-BKOlvCGS.js → p-BUZXuod2.js} +2 -2
- package/dist/components/{p-DCvA3Dc9.js → p-BaUsq_VK.js} +2 -2
- package/dist/components/p-BbMJTilO.js +2 -0
- package/dist/components/p-BbMJTilO.js.map +1 -0
- package/dist/components/{p-BO5aqZcf.js → p-BcTYhmku.js} +2 -2
- package/dist/components/p-Bkv3UjZz.js +2 -0
- package/dist/components/p-Bkv3UjZz.js.map +1 -0
- package/dist/components/p-BnQXAbif.js +2 -0
- package/dist/components/p-BnQXAbif.js.map +1 -0
- package/dist/components/p-BnbbnuVC.js +2 -0
- package/dist/components/p-BnbbnuVC.js.map +1 -0
- package/dist/components/{p-BDKtu6Wb.js → p-BroVnDzE.js} +2 -2
- package/dist/components/{p-CIiBpjCn.js → p-BsoqsbBh.js} +2 -2
- package/dist/components/p-BwT6B5Fi.js +2 -0
- package/dist/components/p-BwT6B5Fi.js.map +1 -0
- package/dist/components/p-BybqPD8K.js +2 -0
- package/dist/components/p-BybqPD8K.js.map +1 -0
- package/dist/components/p-C-vRkDyn.js +2 -0
- package/dist/components/p-C-vRkDyn.js.map +1 -0
- package/dist/components/p-C3ArcO50.js +2 -0
- package/dist/components/p-C3ArcO50.js.map +1 -0
- package/dist/components/p-C4uYvyq6.js +2 -0
- package/dist/components/p-C4uYvyq6.js.map +1 -0
- package/dist/components/{p-C8HU4W8q.js → p-CBazaRlE.js} +2 -2
- package/dist/components/{p-BhV5e6vF.js → p-CHuh71-U.js} +2 -2
- package/dist/components/{p-CChcuL04.js → p-CMWata9g.js} +2 -2
- package/dist/components/p-CS6CHlHK.js +2 -0
- package/dist/components/p-CS6CHlHK.js.map +1 -0
- package/dist/components/p-CTTnM7cE.js +2 -0
- package/dist/components/p-CTTnM7cE.js.map +1 -0
- package/dist/components/{p-CCzG5xDD.js → p-CWoXKe_h.js} +2 -2
- package/dist/components/p-CWoXKe_h.js.map +1 -0
- package/dist/components/p-CwwuSGER.js +2 -0
- package/dist/components/p-CwwuSGER.js.map +1 -0
- package/dist/components/p-D09HINr_.js +2 -0
- package/dist/components/p-D09HINr_.js.map +1 -0
- package/dist/components/p-D2xWcVv6.js +2 -0
- package/dist/components/p-D2xWcVv6.js.map +1 -0
- package/dist/components/p-DAW6G8Sl.js +2 -0
- package/dist/components/p-DAW6G8Sl.js.map +1 -0
- package/dist/components/p-DEaszb15.js +2 -0
- package/dist/components/p-DEaszb15.js.map +1 -0
- package/dist/components/{p-BgGP65Nn.js → p-DOUk4KoT.js} +1 -1
- package/dist/components/p-DOUk4KoT.js.map +1 -0
- package/dist/components/p-DbQr7Kwr.js +2 -0
- package/dist/components/p-DbQr7Kwr.js.map +1 -0
- package/dist/components/p-DdvEZyX4.js +2 -0
- package/dist/components/p-DdvEZyX4.js.map +1 -0
- package/dist/components/{p-DRnIuCiT.js → p-DeQwkbT1.js} +2 -2
- package/dist/components/{p-Cuih680v.js → p-Df17mJqI.js} +2 -2
- package/dist/components/p-Dg1LBXJ2.js +2 -0
- package/dist/components/p-Dg1LBXJ2.js.map +1 -0
- package/dist/components/p-DsiCDzoF.js +2 -0
- package/dist/components/p-DsiCDzoF.js.map +1 -0
- package/dist/components/p-_DzUXA86.js +2 -0
- package/dist/components/p-_DzUXA86.js.map +1 -0
- package/dist/components/p-lyZNvRvO.js +2 -0
- package/dist/components/p-lyZNvRvO.js.map +1 -0
- package/dist/components/{p-YR1XeuZf.js → p-ohsLFap_.js} +2 -2
- package/dist/components/{p-DjbTFy2B.js → p-ymtdhOU5.js} +1 -1
- package/dist/components/p-ymtdhOU5.js.map +1 -0
- package/dist/components/p-z5RIrXuX.js +2 -0
- package/dist/components/p-z5RIrXuX.js.map +1 -0
- package/dist/docs/components.json +929 -2371
- package/dist/framework/angular.d.ts +0 -1
- package/dist/framework/angular.js +0 -1
- package/dist/lib/components/BarTitle/bar-title-types.d.ts +28 -0
- package/dist/lib/components/Breadcrumb/breadcrumb-types.d.ts +16 -0
- package/dist/lib/components/ButtonFilled/ButtonFilled.d.ts +83 -0
- package/dist/lib/components/MobileHeader/mobile-header-types.d.ts +4 -0
- package/dist/lib/components/PanelTools/panel-tools-types.d.ts +21 -7
- package/dist/lib/components/ShellApp/shell-app-types.d.ts +91 -0
- package/dist/lib/shell/index.d.ts +5 -13
- package/dist/lib/shell/index.js +87 -358
- package/dist/lib/shell/index.js.map +3 -3
- package/dist/lib/shell/shell-responsive.d.ts +2 -1
- package/dist/lib/utils/button-render.d.ts +17 -0
- package/dist/lib/utils/button-types.d.ts +10 -0
- package/dist/lib/utils/choice-list.d.ts +25 -0
- package/dist/lib/utils/control-press.d.ts +8 -0
- package/dist/lib/utils/form-association.d.ts +22 -0
- package/dist/lib/utils/index.d.ts +4 -0
- package/dist/lib/utils/index.js +63 -0
- package/dist/lib/utils/index.js.map +3 -3
- package/dist/lib/utils/required-validity.d.ts +1 -1
- package/dist/lib/utils/safe-url.d.ts +11 -0
- package/dist/mcp/cli.js +38 -10
- package/dist/mcp-data/registry/agent-source-list.json +1 -1
- package/dist/mcp-data/registry/attachment-list.json +1 -1
- package/dist/mcp-data/registry/bar-nav.json +3 -21
- package/dist/mcp-data/registry/breadcrumb.json +1 -1
- package/dist/mcp-data/registry/button-filled.json +4 -19
- package/dist/mcp-data/registry/button-unfilled.json +14 -11
- package/dist/mcp-data/registry/card-data-viz.json +241 -0
- package/dist/mcp-data/registry/card-overview.json +38 -10
- package/dist/mcp-data/registry/card-setting.json +2 -2
- package/dist/mcp-data/registry/chart-bar.json +66 -18
- package/dist/mcp-data/registry/chart-donut.json +5 -5
- package/dist/mcp-data/registry/chart-legend.json +7 -9
- package/dist/mcp-data/registry/chart-line.json +1 -2
- package/dist/mcp-data/registry/checkbox.json +2 -2
- package/dist/mcp-data/registry/conversation-list-item.json +1 -1
- package/dist/mcp-data/registry/field.json +2 -3
- package/dist/mcp-data/registry/input.json +1 -1
- package/dist/mcp-data/registry/markdown.json +1 -1
- package/dist/mcp-data/registry/menu.json +10 -21
- package/dist/mcp-data/registry/mobile-bar-nav.json +1 -1
- package/dist/mcp-data/registry/mobile-header.json +1 -37
- package/dist/mcp-data/registry/mobile-section-switcher.json +1 -19
- package/dist/mcp-data/registry/panel-nav.json +2 -2
- package/dist/mcp-data/registry/panel-tool-search.json +1 -1
- package/dist/mcp-data/registry/panel-tools.json +19 -55
- package/dist/mcp-data/registry/radio.json +1 -1
- package/dist/mcp-data/registry/registry.json +294 -1174
- package/dist/mcp-data/registry/select.json +59 -25
- package/dist/mcp-data/registry/shell-app.json +345 -20
- package/dist/mcp-data/registry/shell-page.json +1 -1
- package/dist/mcp-data/registry/shell-tools.json +12 -43
- package/dist/mcp-data/registry/slider.json +1 -1
- package/dist/mcp-data/registry/switch.json +1 -1
- package/dist/react/components.d.ts +1 -8
- package/dist/react/components.js +1 -8
- package/dist/react/ds-card-data-viz.d.ts +12 -0
- package/dist/react/ds-card-data-viz.js +12 -0
- package/dist/react/ds-menu.d.ts +1 -2
- package/dist/react/ds-menu.js +0 -1
- package/dist/react/ds-select.d.ts +2 -2
- package/dist/react/ds-shell-app.d.ts +24 -1
- package/dist/react/ds-shell-app.js +16 -1
- package/dist/types/components/AgentSourceList/AgentSourceList.d.ts +0 -1
- package/dist/types/components/BarNav/BarNav.d.ts +0 -2
- package/dist/types/components/BarNav/bar-nav-utils.d.ts +2 -4
- package/dist/types/components/ButtonFilled/ButtonFilled.d.ts +5 -11
- package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +13 -10
- package/dist/types/components/CardDataViz/CardDataViz.d.ts +32 -0
- package/dist/types/components/CardDataViz/index.d.ts +2 -0
- package/dist/types/components/CardOverview/CardOverview.d.ts +17 -0
- package/dist/types/components/CardOverview/card-overview-controller.d.ts +16 -0
- package/dist/types/components/ChartBar/ChartBar.d.ts +12 -1
- package/dist/types/components/ChartBar/index.d.ts +2 -1
- package/dist/types/components/Menu/Menu.d.ts +0 -4
- package/dist/types/components/Menu/menu-sections.d.ts +4 -0
- package/dist/types/components/Menu/menu-types.d.ts +2 -11
- package/dist/types/components/MobileHeader/MobileHeader.d.ts +0 -5
- package/dist/types/components/MobileSectionSwitcher/MobileSectionSwitcher.d.ts +0 -2
- package/dist/types/components/PanelTools/PanelTools.d.ts +0 -4
- package/dist/types/components/PanelTools/index.d.ts +1 -1
- package/dist/types/components/PanelTools/panel-tools-types.d.ts +21 -7
- package/dist/types/components/PanelTools/panel-tools-utils.d.ts +1 -1
- package/dist/types/components/Select/Select.d.ts +12 -4
- package/dist/types/components/Select/index.d.ts +1 -1
- package/dist/types/components/ShellApp/ShellApp.d.ts +98 -0
- package/dist/types/components/ShellApp/shell-app-types.d.ts +92 -0
- package/dist/types/components/ShellPage/ShellPage.d.ts +5 -0
- package/dist/types/components/ShellTools/ShellTools.d.ts +2 -2
- package/dist/types/components.d.ts +210 -889
- package/dist/types/shell/index.d.ts +5 -13
- package/dist/types/shell/shell-responsive.d.ts +2 -1
- package/dist/types/utils/button-render.d.ts +18 -0
- package/dist/types/utils/button-story-foundation.d.ts +9 -0
- package/dist/types/utils/button-types.d.ts +11 -0
- package/dist/types/utils/form-association.d.ts +23 -0
- package/dist/types/utils/index.d.ts +4 -0
- package/dist/types/utils/required-validity.d.ts +1 -1
- package/dist/types/utils/safe-url.d.ts +12 -0
- package/dist/types/utils/select-controller.d.ts +1 -1
- package/package.json +16 -8
- package/dist/.build-stamp +0 -1
- package/dist/angular/ds-card-data-viz-bar.d.ts +0 -18
- package/dist/angular/ds-card-data-viz-bar.js +0 -42
- package/dist/angular/ds-card-data-viz-donut.d.ts +0 -18
- package/dist/angular/ds-card-data-viz-line.d.ts +0 -18
- package/dist/angular/ds-card-data-viz-line.js +0 -42
- package/dist/angular/ds-card-shell-data-viz.d.ts +0 -12
- package/dist/angular/ds-card-shell-data-viz.js +0 -38
- package/dist/angular/ds-chart-bar-stacked.d.ts +0 -12
- package/dist/angular/ds-chart-bar-stacked.js +0 -38
- package/dist/angular/ds-select-multi.d.ts +0 -28
- package/dist/angular/ds-select-multi.js +0 -49
- package/dist/angular/ds-shell-gradient-picker.d.ts +0 -16
- package/dist/angular/ds-shell-gradient-picker.js +0 -42
- package/dist/angular/ds-shell-gradient-swatch.d.ts +0 -16
- package/dist/angular/ds-shell-gradient-swatch.js +0 -42
- package/dist/components/ds-card-data-viz-bar.d.ts +0 -11
- package/dist/components/ds-card-data-viz-bar.js +0 -2
- package/dist/components/ds-card-data-viz-bar.js.map +0 -1
- package/dist/components/ds-card-data-viz-donut.d.ts +0 -11
- package/dist/components/ds-card-data-viz-donut.js +0 -2
- package/dist/components/ds-card-data-viz-donut.js.map +0 -1
- package/dist/components/ds-card-data-viz-line.d.ts +0 -11
- package/dist/components/ds-card-data-viz-line.js +0 -2
- package/dist/components/ds-card-data-viz-line.js.map +0 -1
- package/dist/components/ds-card-shell-data-viz.d.ts +0 -11
- package/dist/components/ds-card-shell-data-viz.js +0 -2
- package/dist/components/ds-card-shell-data-viz.js.map +0 -1
- package/dist/components/ds-chart-bar-stacked.d.ts +0 -11
- package/dist/components/ds-chart-bar-stacked.js +0 -2
- package/dist/components/ds-chart-bar-stacked.js.map +0 -1
- package/dist/components/ds-select-multi.js +0 -2
- package/dist/components/ds-select-multi.js.map +0 -1
- package/dist/components/ds-shell-gradient-picker.d.ts +0 -11
- package/dist/components/ds-shell-gradient-picker.js +0 -2
- package/dist/components/ds-shell-gradient-picker.js.map +0 -1
- package/dist/components/ds-shell-gradient-swatch.d.ts +0 -11
- package/dist/components/ds-shell-gradient-swatch.js +0 -2
- package/dist/components/ds-shell-gradient-swatch.js.map +0 -1
- package/dist/components/p-2foAUsDN.js +0 -2
- package/dist/components/p-2foAUsDN.js.map +0 -1
- package/dist/components/p-8GK7B7K4.js +0 -2
- package/dist/components/p-8GK7B7K4.js.map +0 -1
- package/dist/components/p-B5tMlca-.js +0 -2
- package/dist/components/p-B5tMlca-.js.map +0 -1
- package/dist/components/p-B88n0pO3.js +0 -2
- package/dist/components/p-B88n0pO3.js.map +0 -1
- package/dist/components/p-BBePKRHC.js +0 -2
- package/dist/components/p-BBePKRHC.js.map +0 -1
- package/dist/components/p-BOQnc-M4.js +0 -2
- package/dist/components/p-BOQnc-M4.js.map +0 -1
- package/dist/components/p-BgGP65Nn.js.map +0 -1
- package/dist/components/p-BrusnEYP.js +0 -2
- package/dist/components/p-BrusnEYP.js.map +0 -1
- package/dist/components/p-C61yJkfr.js +0 -2
- package/dist/components/p-C61yJkfr.js.map +0 -1
- package/dist/components/p-CCzG5xDD.js.map +0 -1
- package/dist/components/p-CGVXbXv9.js +0 -2
- package/dist/components/p-CGVXbXv9.js.map +0 -1
- package/dist/components/p-CH3w-P2H.js +0 -2
- package/dist/components/p-CH3w-P2H.js.map +0 -1
- package/dist/components/p-Cuqxh-Tq.js +0 -2
- package/dist/components/p-Cuqxh-Tq.js.map +0 -1
- package/dist/components/p-D1HFMTdC.js +0 -2
- package/dist/components/p-D1HFMTdC.js.map +0 -1
- package/dist/components/p-D2x17ei-.js +0 -2
- package/dist/components/p-D2x17ei-.js.map +0 -1
- package/dist/components/p-DLZm_-sU.js +0 -2
- package/dist/components/p-DLZm_-sU.js.map +0 -1
- package/dist/components/p-DjKkSqrG.js +0 -2
- package/dist/components/p-DjKkSqrG.js.map +0 -1
- package/dist/components/p-DjbTFy2B.js.map +0 -1
- package/dist/components/p-DlscFn2m.js +0 -2
- package/dist/components/p-DlscFn2m.js.map +0 -1
- package/dist/components/p-DxkEC0hR.js +0 -2
- package/dist/components/p-DxkEC0hR.js.map +0 -1
- package/dist/components/p-Re2kPrXm.js +0 -2
- package/dist/components/p-Re2kPrXm.js.map +0 -1
- package/dist/components/p-XMZCaXs7.js +0 -2
- package/dist/components/p-XMZCaXs7.js.map +0 -1
- package/dist/components/p-dyUp3Adm.js +0 -2
- package/dist/components/p-dyUp3Adm.js.map +0 -1
- package/dist/components/p-nkYN0Bub.js +0 -2
- package/dist/components/p-nkYN0Bub.js.map +0 -1
- package/dist/framework/select-multi-value-accessor.d.ts +0 -9
- package/dist/framework/select-multi-value-accessor.js +0 -40
- package/dist/lib/shell/badge-gradient-ring.d.ts +0 -27
- package/dist/lib/shell/chrome-transition.d.ts +0 -32
- package/dist/lib/shell/shell-chrome-metrics.d.ts +0 -11
- package/dist/lib/shell/shell-gradient.d.ts +0 -41
- package/dist/lib/shell/shell-view-transition.d.ts +0 -23
- package/dist/mcp-data/registry/card-data-viz-bar.json +0 -213
- package/dist/mcp-data/registry/card-data-viz-donut.json +0 -214
- package/dist/mcp-data/registry/card-data-viz-line.json +0 -207
- package/dist/mcp-data/registry/card-shell-data-viz.json +0 -180
- package/dist/mcp-data/registry/chart-bar-stacked.json +0 -230
- package/dist/mcp-data/registry/select-multi.json +0 -758
- package/dist/mcp-data/registry/shell-gradient-picker.json +0 -195
- package/dist/mcp-data/registry/shell-gradient-swatch.json +0 -215
- package/dist/react/ds-card-data-viz-bar.d.ts +0 -12
- package/dist/react/ds-card-data-viz-bar.js +0 -12
- package/dist/react/ds-card-data-viz-donut.d.ts +0 -12
- package/dist/react/ds-card-data-viz-donut.js +0 -12
- package/dist/react/ds-card-data-viz-line.d.ts +0 -12
- package/dist/react/ds-card-data-viz-line.js +0 -12
- package/dist/react/ds-card-shell-data-viz.d.ts +0 -9
- package/dist/react/ds-card-shell-data-viz.js +0 -12
- package/dist/react/ds-chart-bar-stacked.d.ts +0 -9
- package/dist/react/ds-chart-bar-stacked.js +0 -12
- package/dist/react/ds-select-multi.d.ts +0 -14
- package/dist/react/ds-select-multi.js +0 -16
- package/dist/react/ds-shell-gradient-picker.d.ts +0 -12
- package/dist/react/ds-shell-gradient-picker.js +0 -12
- package/dist/react/ds-shell-gradient-swatch.d.ts +0 -12
- package/dist/react/ds-shell-gradient-swatch.js +0 -12
- package/dist/types/components/CardDataVizBar/CardDataVizBar.d.ts +0 -24
- package/dist/types/components/CardDataVizBar/index.d.ts +0 -2
- package/dist/types/components/CardDataVizDonut/CardDataVizDonut.d.ts +0 -28
- package/dist/types/components/CardDataVizDonut/index.d.ts +0 -2
- package/dist/types/components/CardDataVizLine/CardDataVizLine.d.ts +0 -24
- package/dist/types/components/CardDataVizLine/index.d.ts +0 -2
- package/dist/types/components/CardShellDataViz/CardShellDataViz.d.ts +0 -13
- package/dist/types/components/CardShellDataViz/index.d.ts +0 -2
- package/dist/types/components/ChartBarStacked/ChartBarStacked.d.ts +0 -26
- package/dist/types/components/ChartBarStacked/index.d.ts +0 -3
- package/dist/types/components/SelectMulti/SelectMulti.d.ts +0 -121
- package/dist/types/components/SelectMulti/index.d.ts +0 -2
- package/dist/types/components/ShellGradientPicker/ShellGradientPicker.d.ts +0 -12
- package/dist/types/components/ShellGradientSwatch/ShellGradientSwatch.d.ts +0 -15
- package/dist/types/components/ShellGradientSwatch/shell-gradient-swatch-types.d.ts +0 -4
- /package/dist/components/{p-CgEYdMee.js.map → p-6qXDqCj_.js.map} +0 -0
- /package/dist/components/{p-Cr3tEx7o.js.map → p-Ay1AX7Ql.js.map} +0 -0
- /package/dist/components/{p-BOCfICln.js.map → p-B1cbQ0SG.js.map} +0 -0
- /package/dist/components/{p-BKOlvCGS.js.map → p-BUZXuod2.js.map} +0 -0
- /package/dist/components/{p-DCvA3Dc9.js.map → p-BaUsq_VK.js.map} +0 -0
- /package/dist/components/{p-BO5aqZcf.js.map → p-BcTYhmku.js.map} +0 -0
- /package/dist/components/{p-BDKtu6Wb.js.map → p-BroVnDzE.js.map} +0 -0
- /package/dist/components/{p-CIiBpjCn.js.map → p-BsoqsbBh.js.map} +0 -0
- /package/dist/components/{p-C8HU4W8q.js.map → p-CBazaRlE.js.map} +0 -0
- /package/dist/components/{p-BhV5e6vF.js.map → p-CHuh71-U.js.map} +0 -0
- /package/dist/components/{p-CChcuL04.js.map → p-CMWata9g.js.map} +0 -0
- /package/dist/components/{p-DRnIuCiT.js.map → p-DeQwkbT1.js.map} +0 -0
- /package/dist/components/{p-Cuih680v.js.map → p-Df17mJqI.js.map} +0 -0
- /package/dist/components/{p-YR1XeuZf.js.map → p-ohsLFap_.js.map} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
3
|
"name": "chart-bar",
|
|
4
4
|
"title": "ChartBar",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Bar chart for single-series magnitude, additive stacked totals, or normalized 0–100% composition across categories.",
|
|
6
6
|
"type": "registry:ui",
|
|
7
7
|
"meta": {
|
|
8
8
|
"library": "@ds-mo/ui",
|
|
@@ -13,24 +13,20 @@
|
|
|
13
13
|
"intent": {
|
|
14
14
|
"audience": "specialized",
|
|
15
15
|
"status": "experimental",
|
|
16
|
-
"summary": "
|
|
16
|
+
"summary": "Bar chart for single-series magnitude, additive stacked totals, or normalized 0–100% composition across categories.",
|
|
17
17
|
"useWhen": [
|
|
18
18
|
"Users need to compare one numeric measure across a small set of categories.",
|
|
19
19
|
"Values are grouped into ordered time buckets such as hours, days, weeks, or months and equal visual spacing is appropriate.",
|
|
20
|
-
"A data-viz card needs a compact magnitude comparison rather than a continuous trend."
|
|
20
|
+
"A data-viz card needs a compact magnitude comparison rather than a continuous trend.",
|
|
21
|
+
"Several consistent series contribute to each category total or its normalized composition."
|
|
21
22
|
],
|
|
22
23
|
"avoidWhen": [
|
|
23
24
|
"Timestamp positions must reflect irregular elapsed time; pre-bucket the data or use a future continuous time-scale chart.",
|
|
24
|
-
"The visualization needs
|
|
25
|
+
"The visualization needs grouped bars or precise comparison of each individual series across categories.",
|
|
25
26
|
"The interaction requires selection, drill-down, brushing, or zoom.",
|
|
26
27
|
"The data communicates a part-to-whole relationship."
|
|
27
28
|
],
|
|
28
29
|
"alternatives": [
|
|
29
|
-
{
|
|
30
|
-
"when": "Each category contains several additive series or needs normalized composition.",
|
|
31
|
-
"component": "component:ds-chart-bar-stacked",
|
|
32
|
-
"reason": "ChartBarStacked compares raw stacked totals or normalized 0–100% composition."
|
|
33
|
-
},
|
|
34
30
|
{
|
|
35
31
|
"when": "Users need to follow one or more trends across ordered categories.",
|
|
36
32
|
"component": "component:ds-chart-line",
|
|
@@ -43,8 +39,8 @@
|
|
|
43
39
|
}
|
|
44
40
|
],
|
|
45
41
|
"commonlyComposedWith": [
|
|
46
|
-
"component:ds-chart-
|
|
47
|
-
"component:ds-card-
|
|
42
|
+
"component:ds-chart-legend",
|
|
43
|
+
"component:ds-card-data-viz",
|
|
48
44
|
"component:ds-tooltip-data-viz"
|
|
49
45
|
],
|
|
50
46
|
"accessibility": [
|
|
@@ -53,7 +49,9 @@
|
|
|
53
49
|
"A future interactive tooltip must supplement rather than replace the chart's accessible value representation."
|
|
54
50
|
],
|
|
55
51
|
"states": [
|
|
56
|
-
"The chart is
|
|
52
|
+
"The chart is static without hover, selection, loading, or empty-state policy.",
|
|
53
|
+
"Single mode reads data. Stacked and percentage modes read aligned series and categories.",
|
|
54
|
+
"Stacked mode preserves raw totals; percentage mode normalizes every non-empty category to 100%.",
|
|
57
55
|
"An empty dataset renders no bars; the owning card or product supplies meaningful empty-state messaging.",
|
|
58
56
|
"Bars use 2px top corner radii while the lower corners touching the zero axis remain square.",
|
|
59
57
|
"Use one consistent bar color across time buckets when every bar is the same measure at a different interval; categorical color changes are for genuinely distinct categories.",
|
|
@@ -67,13 +65,13 @@
|
|
|
67
65
|
],
|
|
68
66
|
"frameworkCaveats": {
|
|
69
67
|
"customElements": [
|
|
70
|
-
"Assign data as
|
|
68
|
+
"Assign data, series, and categories as JavaScript properties; arrays are not supported as HTML attributes."
|
|
71
69
|
],
|
|
72
70
|
"react": [
|
|
73
|
-
"Pass
|
|
71
|
+
"Pass stable data or series/category arrays; width and height provide standalone intrinsic dimensions while constrained containers reflow automatically."
|
|
74
72
|
],
|
|
75
73
|
"angular": [
|
|
76
|
-
"Bind data as
|
|
74
|
+
"Bind data or series/categories as properties; width and height provide standalone intrinsic dimensions while constrained containers reflow automatically."
|
|
77
75
|
]
|
|
78
76
|
},
|
|
79
77
|
"references": [
|
|
@@ -85,6 +83,14 @@
|
|
|
85
83
|
},
|
|
86
84
|
"api": {
|
|
87
85
|
"props": {
|
|
86
|
+
"categories": {
|
|
87
|
+
"type": "string[]",
|
|
88
|
+
"resolvedType": "string[]",
|
|
89
|
+
"default": "[]",
|
|
90
|
+
"required": false,
|
|
91
|
+
"mutable": false,
|
|
92
|
+
"description": "X-axis labels for stacked and percentage variants. Set as a JS property."
|
|
93
|
+
},
|
|
88
94
|
"data": {
|
|
89
95
|
"type": "ChartDatum[]",
|
|
90
96
|
"resolvedType": "ChartDatum[]",
|
|
@@ -102,6 +108,23 @@
|
|
|
102
108
|
"mutable": false,
|
|
103
109
|
"description": "Standalone intrinsic height. Container constraints reflow the plot at rendered pixel size."
|
|
104
110
|
},
|
|
111
|
+
"series": {
|
|
112
|
+
"type": "ChartSeries[]",
|
|
113
|
+
"resolvedType": "ChartSeries[]",
|
|
114
|
+
"default": "[]",
|
|
115
|
+
"required": false,
|
|
116
|
+
"mutable": false,
|
|
117
|
+
"description": "Ordered stack series for stacked and percentage variants. Set as a JS property."
|
|
118
|
+
},
|
|
119
|
+
"variant": {
|
|
120
|
+
"type": "ChartBarVariant",
|
|
121
|
+
"resolvedType": "\"percentage\" | \"single\" | \"stacked\"",
|
|
122
|
+
"attribute": "variant",
|
|
123
|
+
"default": "'single'",
|
|
124
|
+
"required": false,
|
|
125
|
+
"mutable": false,
|
|
126
|
+
"description": "Rendering model. Single uses `data`; stacked and percentage use `series` and `categories`."
|
|
127
|
+
},
|
|
105
128
|
"width": {
|
|
106
129
|
"type": "number",
|
|
107
130
|
"resolvedType": "number",
|
|
@@ -117,6 +140,14 @@
|
|
|
117
140
|
"slots": []
|
|
118
141
|
},
|
|
119
142
|
"props": {
|
|
143
|
+
"categories": {
|
|
144
|
+
"type": "string[]",
|
|
145
|
+
"resolvedType": "string[]",
|
|
146
|
+
"default": "[]",
|
|
147
|
+
"required": false,
|
|
148
|
+
"mutable": false,
|
|
149
|
+
"description": "X-axis labels for stacked and percentage variants. Set as a JS property."
|
|
150
|
+
},
|
|
120
151
|
"data": {
|
|
121
152
|
"type": "ChartDatum[]",
|
|
122
153
|
"resolvedType": "ChartDatum[]",
|
|
@@ -134,6 +165,23 @@
|
|
|
134
165
|
"mutable": false,
|
|
135
166
|
"description": "Standalone intrinsic height. Container constraints reflow the plot at rendered pixel size."
|
|
136
167
|
},
|
|
168
|
+
"series": {
|
|
169
|
+
"type": "ChartSeries[]",
|
|
170
|
+
"resolvedType": "ChartSeries[]",
|
|
171
|
+
"default": "[]",
|
|
172
|
+
"required": false,
|
|
173
|
+
"mutable": false,
|
|
174
|
+
"description": "Ordered stack series for stacked and percentage variants. Set as a JS property."
|
|
175
|
+
},
|
|
176
|
+
"variant": {
|
|
177
|
+
"type": "ChartBarVariant",
|
|
178
|
+
"resolvedType": "\"percentage\" | \"single\" | \"stacked\"",
|
|
179
|
+
"attribute": "variant",
|
|
180
|
+
"default": "'single'",
|
|
181
|
+
"required": false,
|
|
182
|
+
"mutable": false,
|
|
183
|
+
"description": "Rendering model. Single uses `data`; stacked and percentage use `series` and `categories`."
|
|
184
|
+
},
|
|
137
185
|
"width": {
|
|
138
186
|
"type": "number",
|
|
139
187
|
"resolvedType": "number",
|
|
@@ -167,7 +215,7 @@
|
|
|
167
215
|
"import": "import { DsChartBar } from '@ds-mo/ui/angular/ds-chart-bar';",
|
|
168
216
|
"example": "<ds-chart-bar></ds-chart-bar>"
|
|
169
217
|
},
|
|
170
|
-
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: data.",
|
|
218
|
+
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: categories, data, series.",
|
|
171
219
|
"peerDependencies": {
|
|
172
220
|
"required": [
|
|
173
221
|
"@ds-mo/tokens ^5.0.0",
|
|
@@ -185,12 +233,12 @@
|
|
|
185
233
|
"files": [
|
|
186
234
|
{
|
|
187
235
|
"path": "src/wc/components/ChartBar/ChartBar.css",
|
|
188
|
-
"content": ":host {\n display: inline-block;\n max-width: 100%;\n font-family: var(--typography-font-family);\n}\n\n.chart-bar__svg {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.chart-bar__gridline {\n stroke: var(--color-border-tertiary);\n stroke-width: var(--dimension-stroke-width-012);\n vector-effect: non-scaling-stroke;\n}\n\n/* Matches ds-text text-caption regular (SVG cannot host ds-text). */\n.chart-bar__axis-label {\n fill: var(--color-foreground-secondary);\n font-family: var(--typography-font-family);\n font-size: var(--typography-fontsize-xs);\n font-weight: var(--typography-weight-medium);\n letter-spacing: var(--typography-letterspacing-positive);\n text-transform: uppercase;\n}\n\n.chart-bar__bar--rounded {\n rx: var(--dimension-radius-025);\n}\n",
|
|
236
|
+
"content": ":host {\n display: inline-block;\n max-width: 100%;\n font-family: var(--typography-font-family);\n}\n\n.chart-bar__svg {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.chart-bar__gridline {\n stroke: var(--color-border-tertiary);\n stroke-width: var(--dimension-stroke-width-012);\n vector-effect: non-scaling-stroke;\n}\n\n/* Matches ds-text text-caption regular (SVG cannot host ds-text). */\n.chart-bar__axis-label {\n fill: var(--color-foreground-secondary);\n font-family: var(--typography-font-family);\n font-size: var(--typography-fontsize-xs);\n font-weight: var(--typography-weight-medium);\n letter-spacing: var(--typography-letterspacing-positive);\n text-transform: uppercase;\n}\n\n.chart-bar__bar--rounded {\n rx: var(--dimension-radius-025);\n}\n\n.chart-bar__segment-shape--rounded {\n rx: var(--dimension-radius-025);\n}\n\n.chart-bar__segment-separator {\n stroke: var(--color-background-primary);\n stroke-width: var(--dimension-stroke-width-012);\n stroke-linecap: butt;\n vector-effect: non-scaling-stroke;\n}\n",
|
|
189
237
|
"type": "registry:ui"
|
|
190
238
|
},
|
|
191
239
|
{
|
|
192
240
|
"path": "src/wc/components/ChartBar/ChartBar.tsx",
|
|
193
|
-
"content": "import { Component, Prop, State, Watch, h, Host } from '@stencil/core';\nimport { scaleBand, scaleLinear } from 'd3-scale';\nimport { max } from 'd3-array';\nimport { categoryColor } from '../../utils/chart-colors';\nimport { resolveCartesianChartLayout } from '../../utils/cartesian-chart-layout';\nimport {\n ChartViewportController,\n type ChartViewportSize,\n} from '../../utils/chart-viewport-controller';\nimport type { ChartDatum } from '../../utils/chart-types';\n\n@Component({\n tag: 'ds-chart-bar',\n styleUrl: 'ChartBar.css',\n scoped: true,\n})\nexport class ChartBar {\n /** Bars to render. Set as a JS property (not an HTML attribute). */\n @Prop() data: ChartDatum[] = [];\n /** Standalone intrinsic width. Container constraints reflow the plot at rendered pixel size. */\n @Prop() width: number = 480;\n /** Standalone intrinsic height. Container constraints reflow the plot at rendered pixel size. */\n @Prop() height: number = 240;\n\n @State() private viewport: ChartViewportSize | undefined;\n\n private viewportController: ChartViewportController | null = null;\n private svgEl: SVGElement | null = null;\n\n componentDidLoad() {\n this.connectViewportController();\n }\n\n connectedCallback() {\n if (this.svgEl && !this.viewportController) this.connectViewportController();\n }\n\n componentDidRender() {\n if (!this.viewportController) this.connectViewportController();\n }\n\n private connectViewportController() {\n if (!this.svgEl) return;\n this.viewportController = new ChartViewportController(this.svgEl, viewport => {\n if (\n viewport.width !== this.viewport?.width ||\n viewport.height !== this.viewport?.height\n ) {\n this.viewport = viewport;\n }\n });\n this.viewportController.connect();\n }\n\n disconnectedCallback() {\n this.viewportController?.disconnect();\n this.viewportController = null;\n }\n\n @Watch('width')\n @Watch('height')\n handleIntrinsicSizeChange() {\n this.viewport = undefined;\n if (typeof requestAnimationFrame === 'function') {\n requestAnimationFrame(() => this.viewportController?.measure());\n }\n }\n\n render() {\n const viewportWidth = this.viewport?.width ?? this.width;\n const viewportHeight = this.viewport?.height ?? this.height;\n const { margin, axisLabelGap, categoryLabelOffset } =\n resolveCartesianChartLayout();\n const innerWidth = Math.max(0, viewportWidth - margin.left - margin.right);\n const innerHeight = Math.max(0, viewportHeight - margin.top - margin.bottom);\n\n const yMax = max(this.data, d => d.value) ?? 0;\n\n const xScale = scaleBand()\n .domain(this.data.map(d => d.label))\n .range([0, innerWidth])\n .padding(0.35);\n\n const yScale = scaleLinear()\n .domain([0, yMax || 1])\n .range([innerHeight, 0])\n .nice();\n\n const yTicks = yScale.ticks(4);\n\n return (\n <Host class=\"chart-bar\">\n <svg\n class=\"chart-bar__svg\"\n ref={element => {\n this.svgEl = element ?? null;\n }}\n width={viewportWidth}\n height={viewportHeight}\n role=\"img\"\n aria-label={this.data.map(d => `${d.label}: ${d.value}`).join(', ')}\n >\n <g transform={`translate(${margin.left}, ${margin.top})`}>\n {yTicks.map(tick => (\n <g key={`grid-${tick}`} transform={`translate(0, ${yScale(tick)})`}>\n <line class=\"chart-bar__gridline\" x1={0} x2={innerWidth} />\n <text\n class=\"chart-bar__axis-label\"\n x={-axisLabelGap}\n text-anchor=\"end\"\n dominant-baseline=\"middle\"\n >\n {tick}\n </text>\n </g>\n ))}\n\n {this.data.map((d, i) => {\n const barWidth = xScale.bandwidth();\n const barX = xScale(d.label) ?? 0;\n const barY = yScale(d.value);\n const barHeight = innerHeight - barY;\n const squareBaseY = barY + barHeight / 2;\n const squareBaseHeight = barHeight / 2;\n const fill = d.color ?? categoryColor(i);\n return (\n <g key={d.label}>\n <rect\n class=\"chart-bar__bar chart-bar__bar--rounded\"\n x={barX}\n y={barY}\n width={barWidth}\n height={barHeight}\n fill={fill}\n />\n <rect\n class=\"chart-bar__bar chart-bar__bar--square-base\"\n x={barX}\n y={squareBaseY}\n width={barWidth}\n height={squareBaseHeight}\n fill={fill}\n />\n <text\n class=\"chart-bar__axis-label\"\n x={barX + barWidth / 2}\n y={innerHeight + categoryLabelOffset}\n text-anchor=\"middle\"\n >\n {d.label}\n </text>\n </g>\n );\n })}\n </g>\n </svg>\n </Host>\n );\n }\n}\n",
|
|
241
|
+
"content": "import { Component, Prop, State, Watch, h, Host } from '@stencil/core';\nimport { scaleBand, scaleLinear } from 'd3-scale';\nimport { max } from 'd3-array';\nimport { categoryColor } from '../../utils/chart-colors';\nimport { formatPercentage } from '../../utils';\nimport { resolveCartesianChartLayout } from '../../utils/cartesian-chart-layout';\nimport {\n ChartViewportController,\n type ChartViewportSize,\n} from '../../utils/chart-viewport-controller';\nimport type { ChartDatum, ChartSeries } from '../../utils/chart-types';\n\nexport type ChartBarVariant = 'single' | 'stacked' | 'percentage';\n\nconst PERCENTAGE_TICKS = [0, 25, 50, 75, 100];\n\n@Component({\n tag: 'ds-chart-bar',\n styleUrl: 'ChartBar.css',\n scoped: true,\n})\nexport class ChartBar {\n /** Rendering model. Single uses `data`; stacked and percentage use `series` and `categories`. */\n @Prop() variant: ChartBarVariant = 'single';\n /** Bars to render. Set as a JS property (not an HTML attribute). */\n @Prop() data: ChartDatum[] = [];\n /** Ordered stack series for stacked and percentage variants. Set as a JS property. */\n @Prop() series: ChartSeries[] = [];\n /** X-axis labels for stacked and percentage variants. Set as a JS property. */\n @Prop() categories: string[] = [];\n /** Standalone intrinsic width. Container constraints reflow the plot at rendered pixel size. */\n @Prop() width: number = 480;\n /** Standalone intrinsic height. Container constraints reflow the plot at rendered pixel size. */\n @Prop() height: number = 240;\n\n @State() private viewport: ChartViewportSize | undefined;\n\n private viewportController: ChartViewportController | null = null;\n private svgEl: SVGElement | null = null;\n\n componentDidLoad() {\n this.connectViewportController();\n }\n\n connectedCallback() {\n if (this.svgEl && !this.viewportController) this.connectViewportController();\n }\n\n componentDidRender() {\n if (!this.viewportController) this.connectViewportController();\n }\n\n private connectViewportController() {\n if (!this.svgEl) return;\n this.viewportController = new ChartViewportController(this.svgEl, viewport => {\n if (\n viewport.width !== this.viewport?.width ||\n viewport.height !== this.viewport?.height\n ) {\n this.viewport = viewport;\n }\n });\n this.viewportController.connect();\n }\n\n disconnectedCallback() {\n this.viewportController?.disconnect();\n this.viewportController = null;\n }\n\n @Watch('width')\n @Watch('height')\n handleIntrinsicSizeChange() {\n this.viewport = undefined;\n if (typeof requestAnimationFrame === 'function') {\n requestAnimationFrame(() => this.viewportController?.measure());\n }\n }\n\n private renderSingle(\n innerWidth: number,\n innerHeight: number,\n axisLabelGap: number,\n categoryLabelOffset: number\n ) {\n const yMax = max(this.data, d => d.value) ?? 0;\n const xScale = scaleBand()\n .domain(this.data.map(d => d.label))\n .range([0, innerWidth])\n .padding(0.35);\n const yScale = scaleLinear()\n .domain([0, yMax || 1])\n .range([innerHeight, 0])\n .nice();\n const yTicks = yScale.ticks(4);\n\n return (\n <g>\n {yTicks.map(tick => (\n <g key={`grid-${tick}`} transform={`translate(0, ${yScale(tick)})`}>\n <line class=\"chart-bar__gridline\" x1={0} x2={innerWidth} />\n <text\n class=\"chart-bar__axis-label\"\n x={-axisLabelGap}\n text-anchor=\"end\"\n dominant-baseline=\"middle\"\n >\n {tick}\n </text>\n </g>\n ))}\n\n {this.data.map((datum, index) => {\n const barWidth = xScale.bandwidth();\n const barX = xScale(datum.label) ?? 0;\n const barY = yScale(datum.value);\n const barHeight = innerHeight - barY;\n const squareBaseY = barY + barHeight / 2;\n const squareBaseHeight = barHeight / 2;\n const fill = datum.color ?? categoryColor(index);\n return (\n <g key={datum.label}>\n <rect\n class=\"chart-bar__bar chart-bar__bar--rounded\"\n x={barX}\n y={barY}\n width={barWidth}\n height={barHeight}\n fill={fill}\n />\n <rect\n class=\"chart-bar__bar chart-bar__bar--square-base\"\n x={barX}\n y={squareBaseY}\n width={barWidth}\n height={squareBaseHeight}\n fill={fill}\n />\n <text\n class=\"chart-bar__axis-label\"\n x={barX + barWidth / 2}\n y={innerHeight + categoryLabelOffset}\n text-anchor=\"middle\"\n >\n {datum.label}\n </text>\n </g>\n );\n })}\n </g>\n );\n }\n\n private valuesForCategory(categoryIndex: number) {\n return this.series.map(series => Math.max(0, series.data[categoryIndex] ?? 0));\n }\n\n private stackedAccessibleLabel() {\n return this.categories\n .map((category, categoryIndex) => {\n const values = this.valuesForCategory(categoryIndex);\n const total = values.reduce((sum, value) => sum + value, 0);\n const details = this.series\n .map((series, seriesIndex) => {\n const value = values[seriesIndex];\n const visibleValue =\n this.variant === 'percentage'\n ? formatPercentage(total ? value / total : 0, 1)\n : String(value);\n return `${series.name}: ${visibleValue}`;\n })\n .join(', ');\n return `${category}: ${details}`;\n })\n .join('; ');\n }\n\n private renderStacked(\n innerWidth: number,\n innerHeight: number,\n axisLabelGap: number,\n categoryLabelOffset: number\n ) {\n const categoryValues = this.categories.map((_, index) =>\n this.valuesForCategory(index)\n );\n const totals = categoryValues.map(values =>\n values.reduce((sum, value) => sum + value, 0)\n );\n const yMax = this.variant === 'percentage' ? 100 : Math.max(0, ...totals);\n const xScale = scaleBand()\n .domain(this.categories)\n .range([0, innerWidth])\n .padding(0.35);\n const yScale = scaleLinear()\n .domain([0, yMax || 1])\n .range([innerHeight, 0])\n .nice();\n const yTicks =\n this.variant === 'percentage' ? PERCENTAGE_TICKS : yScale.ticks(4);\n\n return (\n <g>\n {yTicks.map(tick => (\n <g key={`grid-${tick}`} transform={`translate(0, ${yScale(tick)})`}>\n <line class=\"chart-bar__gridline\" x1={0} x2={innerWidth} />\n <text\n class=\"chart-bar__axis-label\"\n x={-axisLabelGap}\n text-anchor=\"end\"\n dominant-baseline=\"middle\"\n >\n {this.variant === 'percentage' ? `${tick}%` : tick}\n </text>\n </g>\n ))}\n\n {this.categories.map((category, categoryIndex) => {\n const barWidth = xScale.bandwidth();\n const barX = xScale(category) ?? 0;\n const values = categoryValues[categoryIndex];\n const total = totals[categoryIndex];\n const topSeriesIndex = values.reduce(\n (topIndex, value, seriesIndex) =>\n value > 0 ? seriesIndex : topIndex,\n -1\n );\n let cumulativeValue = 0;\n\n return (\n <g class=\"chart-bar__stack\" data-category={category} key={category}>\n {this.series.map((series, seriesIndex) => {\n const rawValue = values[seriesIndex];\n const value =\n this.variant === 'percentage'\n ? total\n ? (rawValue / total) * 100\n : 0\n : rawValue;\n const segmentStart = cumulativeValue;\n const segmentEnd = cumulativeValue + value;\n cumulativeValue = segmentEnd;\n const segmentY = yScale(segmentEnd);\n const segmentBottom = yScale(segmentStart);\n const segmentHeight = Math.max(0, segmentBottom - segmentY);\n if (!segmentHeight) return null;\n\n const fill = series.color ?? categoryColor(seriesIndex);\n const hasRoundedTop =\n this.variant === 'stacked' && seriesIndex === topSeriesIndex;\n const squareBaseY = segmentY + segmentHeight / 2;\n const squareBaseHeight = segmentHeight / 2;\n\n return (\n <g\n class=\"chart-bar__segment\"\n data-series={series.name}\n key={series.name}\n >\n <rect\n class={{\n 'chart-bar__segment-shape': true,\n 'chart-bar__segment-shape--rounded': hasRoundedTop,\n }}\n x={barX}\n y={segmentY}\n width={barWidth}\n height={segmentHeight}\n fill={fill}\n />\n {hasRoundedTop ? (\n <rect\n class=\"chart-bar__segment-square-base\"\n x={barX}\n y={squareBaseY}\n width={barWidth}\n height={squareBaseHeight}\n fill={fill}\n />\n ) : null}\n {segmentStart > 0 ? (\n <line\n class=\"chart-bar__segment-separator\"\n x1={barX}\n x2={barX + barWidth}\n y1={segmentBottom}\n y2={segmentBottom}\n vector-effect=\"non-scaling-stroke\"\n />\n ) : null}\n </g>\n );\n })}\n <text\n class=\"chart-bar__axis-label\"\n x={barX + barWidth / 2}\n y={innerHeight + categoryLabelOffset}\n text-anchor=\"middle\"\n >\n {category}\n </text>\n </g>\n );\n })}\n </g>\n );\n }\n\n render() {\n const viewportWidth = this.viewport?.width ?? this.width;\n const viewportHeight = this.viewport?.height ?? this.height;\n const { margin, axisLabelGap, categoryLabelOffset } =\n resolveCartesianChartLayout();\n const innerWidth = Math.max(0, viewportWidth - margin.left - margin.right);\n const innerHeight = Math.max(0, viewportHeight - margin.top - margin.bottom);\n const isSingle = this.variant === 'single';\n const accessibleLabel = isSingle\n ? this.data.map(datum => `${datum.label}: ${datum.value}`).join(', ')\n : this.stackedAccessibleLabel();\n\n return (\n <Host\n class={{\n 'chart-bar': true,\n [`chart-bar--${this.variant}`]: true,\n }}\n >\n <svg\n class=\"chart-bar__svg\"\n ref={element => {\n this.svgEl = element ?? null;\n }}\n width={viewportWidth}\n height={viewportHeight}\n role=\"img\"\n aria-label={accessibleLabel}\n >\n <g transform={`translate(${margin.left}, ${margin.top})`}>\n {isSingle\n ? this.renderSingle(\n innerWidth,\n innerHeight,\n axisLabelGap,\n categoryLabelOffset\n )\n : this.renderStacked(\n innerWidth,\n innerHeight,\n axisLabelGap,\n categoryLabelOffset\n )}\n </g>\n </svg>\n </Host>\n );\n }\n}\n",
|
|
194
242
|
"type": "registry:ui"
|
|
195
243
|
}
|
|
196
244
|
]
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"alternatives": [
|
|
28
28
|
{
|
|
29
29
|
"when": "The product needs the canonical card, filter action, visible legend, and built-in hover synchronization.",
|
|
30
|
-
"component": "component:ds-card-data-viz
|
|
31
|
-
"reason": "The
|
|
30
|
+
"component": "component:ds-card-data-viz",
|
|
31
|
+
"reason": "The donut card variant owns that complete composition and suppresses redundant slice tooltips."
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
"when": "Users need to compare independent category magnitudes.",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"commonlyComposedWith": [
|
|
40
40
|
"component:ds-chart-legend",
|
|
41
41
|
"component:ds-tooltip-data-viz",
|
|
42
|
-
"component:ds-card-data-viz
|
|
42
|
+
"component:ds-card-data-viz"
|
|
43
43
|
],
|
|
44
44
|
"accessibility": [
|
|
45
45
|
"Every non-empty slice remains keyboard focusable and exposes its label and value without depending on the visual tooltip.",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
],
|
|
50
50
|
"states": [
|
|
51
51
|
"Genuine local pointer or keyboard focus may show a chart-owned tooltip; externally synchronized highlight never opens it.",
|
|
52
|
-
"When a visible legend already owns label and value detail, suppress the redundant donut tooltip.
|
|
52
|
+
"When a visible legend already owns label and value detail, suppress the redundant donut tooltip. CardDataViz donut mode does this automatically.",
|
|
53
53
|
"Local hover and external highlight remain separate while both may dim non-matching slices.",
|
|
54
54
|
"Zero or negative totals render a neutral empty ring without interactive slices.",
|
|
55
55
|
"Center value and caption truncate when they exceed the safe inner-circle measure."
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
],
|
|
63
63
|
"frameworkCaveats": {
|
|
64
64
|
"customElements": [
|
|
65
|
-
"Assign data as a JavaScript property and wire slice-hover detail to a sibling legend only when not using
|
|
65
|
+
"Assign data as a JavaScript property and wire slice-hover detail to a sibling legend only when not using CardDataViz donut mode."
|
|
66
66
|
],
|
|
67
67
|
"react": [
|
|
68
68
|
"Keep synchronized highlight controlled by the composition and disable slice tooltips when a sibling legend continuously shows the same details."
|
|
@@ -32,22 +32,20 @@
|
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
"when": "The donut belongs in the canonical dashboard card.",
|
|
35
|
-
"component": "component:ds-card-data-viz
|
|
36
|
-
"reason": "The
|
|
35
|
+
"component": "component:ds-card-data-viz",
|
|
36
|
+
"reason": "The donut variant places the legend and handles bidirectional highlight synchronization."
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"when": "A static line chart and series key belong in the canonical dashboard card.",
|
|
40
|
-
"component": "component:ds-card-data-viz
|
|
41
|
-
"reason": "The
|
|
40
|
+
"component": "component:ds-card-data-viz",
|
|
41
|
+
"reason": "The line variant places the horizontal legend and disables decorative local hover highlighting."
|
|
42
42
|
}
|
|
43
43
|
],
|
|
44
44
|
"commonlyComposedWith": [
|
|
45
45
|
"component:ds-chart-donut",
|
|
46
|
-
"component:ds-chart-bar
|
|
46
|
+
"component:ds-chart-bar",
|
|
47
47
|
"component:ds-chart-line",
|
|
48
|
-
"component:ds-card-data-viz
|
|
49
|
-
"component:ds-card-data-viz-line",
|
|
50
|
-
"component:ds-card-shell-data-viz"
|
|
48
|
+
"component:ds-card-data-viz"
|
|
51
49
|
],
|
|
52
50
|
"accessibility": [
|
|
53
51
|
"Rows remain non-interactive unless the item supplies an actual link destination.",
|
|
@@ -298,7 +296,7 @@
|
|
|
298
296
|
},
|
|
299
297
|
{
|
|
300
298
|
"path": "src/wc/components/ChartLegend/ChartLegend.tsx",
|
|
301
|
-
"content": "import { Component, Prop, State, Event, EventEmitter, h, Host, Watch } from '@stencil/core';\nimport { categoryColor } from '../../utils/chart-colors';\nimport { formatCompactNumber, formatPercentage } from '../../utils';\nimport type { ChartLegendItem } from '../../utils/chart-types';\n\nexport type ChartLegendDirection = 'vertical' | 'horizontal';\nexport type ChartLegendPercentageDecimals = 1 | 2;\n\nconst DIMMED_OPACITY = 0.
|
|
299
|
+
"content": "import { Component, Prop, State, Event, EventEmitter, h, Host, Watch } from '@stencil/core';\nimport { categoryColor } from '../../utils/chart-colors';\nimport { formatCompactNumber, formatPercentage, resolveSafeUrl } from '../../utils';\nimport type { ChartLegendItem } from '../../utils/chart-types';\n\nexport type ChartLegendDirection = 'vertical' | 'horizontal';\nexport type ChartLegendPercentageDecimals = 1 | 2;\n\nconst DIMMED_OPACITY = 0.5;\n\n/**\n * Base legend for `ds-chart-*` components. Webapp's Overview widgets each style\n * legends differently (list w/ values, compact chips, bare swatches, external\n * stat callouts) — this covers the common \"swatch + label + optional value\" case.\n * Consumers who need a different treatment skip this component entirely and\n * render their own markup against the same `ChartDatum[]` data.\n */\n@Component({\n tag: 'ds-chart-legend',\n styleUrl: 'ChartLegend.css',\n scoped: true,\n})\nexport class ChartLegend {\n @Prop() locale: string | undefined;\n /** Legend entries. Set as a JS property (not an HTML attribute). */\n @Prop() items: ChartLegendItem[] = [];\n @Prop() direction: ChartLegendDirection = 'vertical';\n /** Show each item's share of the total (of items with a `value`) alongside its count. */\n @Prop() showPercentage: boolean = true;\n /** Fixed number of decimal places shown for percentages. */\n @Prop() percentageDecimals: ChartLegendPercentageDecimals = 1;\n /** Let local pointer/focus movement highlight one item and emit `dsItemHover`. */\n @Prop() highlightOnHover: boolean = true;\n /**\n * Externally controlled highlight, matched by `label` — e.g. drive this from a sibling\n * chart's `dsSliceHover` event to keep chart and legend hover in sync. Only dims the other\n * rows' opacity (like a chart dimming its other slices) — it never shows the hover-fill,\n * since that's reserved for a real pointer/keyboard interaction on this row.\n */\n @Prop() activeLabel: string | null = null;\n\n /** Own pointer/focus hover, kept separate from `activeLabel` so the hover-fill (a \"you can\n * click here\" affordance) never shows just because an external row was synced in. */\n @State() private hoveredLabel: string | null = null;\n\n /** Fires on row hover/focus with the item, or `null` on leave/blur. */\n @Event() dsItemHover!: EventEmitter<ChartLegendItem | null>;\n /** Fires when a deep-linkable row (`item.href` set) is activated. */\n @Event() dsItemClick!: EventEmitter<{ item: ChartLegendItem; originalEvent: MouseEvent }>;\n\n @Watch('highlightOnHover')\n handleHighlightOnHoverChange(enabled: boolean) {\n if (!enabled) this.hoveredLabel = null;\n }\n\n private handleHover(item: ChartLegendItem | null) {\n this.hoveredLabel = item?.label ?? null;\n this.dsItemHover.emit(item);\n }\n\n private handleClick = (item: ChartLegendItem, originalEvent: MouseEvent) => {\n this.dsItemClick.emit({ item, originalEvent });\n };\n\n render() {\n const total = this.items.reduce((sum, item) => sum + (item.value ?? 0), 0);\n // Highlight/dim from either this component's own hover or an externally-synced label\n // (e.g. a sibling ds-chart-donut slice) — same mechanism ds-chart-donut uses for its slices.\n const highlightLabel = this.activeLabel ?? (this.highlightOnHover ? this.hoveredLabel : null);\n\n return (\n <Host\n class={{\n 'chart-legend': true,\n [`chart-legend--${this.direction}`]: true,\n 'chart-legend--show-percentage': this.showPercentage,\n }}\n >\n {/* mouseleave lives on the list, not each row — the row-gap between items is still\n inside the list's box, so crossing it while moving between rows never fires this.\n Only actually leaving the whole list does, and that clears with no delay. */}\n <ul\n class=\"chart-legend__list\"\n onMouseLeave={this.highlightOnHover ? () => this.handleHover(null) : undefined}\n >\n {this.items.map((item, i) => {\n const isDimmed = highlightLabel != null && item.label !== highlightLabel;\n const href = resolveSafeUrl(item.href);\n const RowTag = href ? 'a' : 'div';\n const percentage = item.value != null\n ? formatPercentage(total ? item.value / total : 0, this.percentageDecimals, this.locale)\n : '';\n\n return (\n <li class=\"chart-legend__list-item\" key={item.label}>\n <RowTag\n class={{\n 'chart-legend__item': true,\n 'chart-legend__item--interactive': !!href,\n 'ds-control--md': true,\n 'ds-interaction-fill': this.highlightOnHover || !!href,\n 'ds-focus-ring-inset': !!href,\n }}\n style={{ opacity: isDimmed ? String(DIMMED_OPACITY) : '1' }}\n href={href}\n onClick={href ? (e: MouseEvent) => this.handleClick(item, e) : undefined}\n onMouseEnter={\n this.highlightOnHover ? () => this.handleHover(item) : undefined\n }\n onFocus={this.highlightOnHover ? () => this.handleHover(item) : undefined}\n onBlur={this.highlightOnHover ? () => this.handleHover(null) : undefined}\n >\n <span class=\"chart-legend__swatch-box\">\n <span class=\"chart-legend__swatch\" style={{ backgroundColor: item.color ?? categoryColor(i) }} />\n </span>\n <ds-text\n class=\"chart-legend__label\"\n as=\"span\"\n variant=\"text-body-medium\"\n color=\"secondary\"\n lineTruncation={1}\n title={item.label}\n >\n {item.label}\n </ds-text>\n {item.value != null && (\n <ds-text\n class=\"chart-legend__value\"\n as=\"span\"\n variant=\"text-body-medium\"\n color=\"primary\"\n lineTruncation={1}\n align=\"right\"\n fontFeature=\"tabular-nums\"\n title={String(item.value)}\n >\n {formatCompactNumber(item.value, this.locale)}\n </ds-text>\n )}\n {item.value != null && this.showPercentage && (\n <ds-text\n class=\"chart-legend__percentage\"\n as=\"span\"\n variant=\"text-body-medium\"\n color=\"primary\"\n lineTruncation={1}\n align=\"right\"\n fontFeature=\"tabular-nums\"\n title={percentage}\n >\n {percentage}\n </ds-text>\n )}\n </RowTag>\n </li>\n );\n })}\n </ul>\n </Host>\n );\n }\n}\n",
|
|
302
300
|
"type": "registry:ui"
|
|
303
301
|
}
|
|
304
302
|
]
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
],
|
|
44
44
|
"commonlyComposedWith": [
|
|
45
45
|
"component:ds-field",
|
|
46
|
-
"component:ds-select
|
|
46
|
+
"component:ds-select",
|
|
47
47
|
"component:ds-text"
|
|
48
48
|
],
|
|
49
49
|
"accessibility": [
|
|
@@ -354,7 +354,7 @@
|
|
|
354
354
|
},
|
|
355
355
|
{
|
|
356
356
|
"path": "src/wc/components/Checkbox/Checkbox.tsx",
|
|
357
|
-
"content": "import { AttachInternals, Component, Prop, State, Event, EventEmitter, Watch, h, Host } from '@stencil/core';\nimport {
|
|
357
|
+
"content": "import { AttachInternals, Component, Prop, State, Event, EventEmitter, Watch, h, Host } from '@stencil/core';\nimport {\n CONTROL_TEXT_VARIANT,\n DEFAULT_REQUIRED_MESSAGE,\n setFormControlValue,\n setRequiredValidity,\n} from '../../utils';\n\nexport type CheckboxSize = 'lg' | 'md' | 'sm' | 'xs';\n\nlet idCounter = 0;\n\n@Component({\n tag: 'ds-checkbox',\n styleUrl: 'Checkbox.css',\n scoped: true,\n formAssociated: true,\n})\nexport class Checkbox {\n @AttachInternals() internals!: ElementInternals;\n private labelId = `ds-checkbox-label-${++idCounter}`;\n\n /** Visible label and accessible name. Omitted only in presentation mode. */\n @Prop() label!: string;\n /** Current checked state. */\n @Prop({ mutable: true }) checked: boolean = false;\n /** Visual and placement density. */\n @Prop() size: CheckboxSize = 'md';\n /** Native form field name. */\n @Prop({ reflect: true }) name: string | undefined;\n /** Submitted value when checked. */\n @Prop() value: string = 'on';\n /** Native disabled state. */\n @Prop({ reflect: true }) disabled: boolean = false;\n /** Require the checkbox to be checked for form validity. */\n @Prop({ reflect: true }) required: boolean = false;\n /** Validation message used when a required checkbox is unchecked. */\n @Prop() requiredMessage: string = DEFAULT_REQUIRED_MESSAGE;\n /** Mixed visual state. Activation clears it before toggling checked. */\n @Prop({ mutable: true }) indeterminate: boolean = false;\n /** Design-system inactive state. */\n @Prop() isInactive: boolean = false;\n /** Visual-only indicator for a composite control that owns selection semantics. */\n @Prop() presentation: boolean = false;\n\n /** Emitted after user activation with the new checked state. */\n @Event() dsChange!: EventEmitter<boolean>;\n\n private initialChecked = false;\n private initialIndeterminate = false;\n @State() private formDisabled = false;\n\n componentWillLoad() {\n this.initialChecked = this.checked;\n this.initialIndeterminate = this.indeterminate;\n this.syncFormValue();\n }\n\n @Watch('checked')\n @Watch('value')\n @Watch('disabled')\n @Watch('isInactive')\n @Watch('required')\n @Watch('presentation')\n syncFormValue() {\n const inactive = this.isInactive || this.disabled || this.formDisabled || this.presentation;\n setFormControlValue(this.internals, this.checked ? this.value : null, { inactive });\n const missing = this.required && !inactive && !this.checked;\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.checked = this.initialChecked;\n this.indeterminate = this.initialIndeterminate;\n }\n\n private handleActivate = () => {\n if (this.isInactive || this.disabled || this.formDisabled || this.presentation) return;\n if (this.indeterminate) this.indeterminate = false;\n this.checked = !this.checked;\n this.dsChange.emit(this.checked);\n };\n\n private handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this.handleActivate();\n }\n };\n\n render() {\n const inactive = this.isInactive || this.disabled || this.formDisabled;\n const isMarked = this.checked || this.indeterminate;\n const invalid = this.required && !inactive && !this.checked;\n\n return (\n <Host\n role={this.presentation ? undefined : 'checkbox'}\n aria-checked={this.presentation ? undefined : this.indeterminate ? 'mixed' : String(this.checked)}\n aria-disabled={!this.presentation && inactive ? 'true' : undefined}\n aria-required={!this.presentation && this.required ? 'true' : undefined}\n aria-invalid={!this.presentation && invalid ? 'true' : undefined}\n aria-labelledby={this.presentation ? undefined : this.labelId}\n aria-hidden={this.presentation ? 'true' : undefined}\n tabIndex={this.presentation || inactive ? -1 : 0}\n class={{\n checkbox: true,\n 'checkbox--presentation': this.presentation,\n [`checkbox--${this.size}`]: true,\n [`ds-control--${this.size}`]: true,\n 'ds-control-inactive': inactive && !this.presentation,\n 'ds-focus-ring-inset': !this.presentation,\n 'ds-interaction-fill': !inactive && !this.presentation,\n }}\n onClick={this.presentation ? undefined : this.handleActivate}\n onKeyDown={this.presentation ? undefined : this.handleKeyDown}\n >\n <span class=\"checkbox__placement ds-interaction-fill__content\" aria-hidden=\"true\">\n <span class={{ box: true, 'box--marked': isMarked }}>\n {isMarked && (\n // eslint-disable-next-line local/prefer-ds-icon -- Checkbox owns this density-specific state mark and its optical stroke.\n <svg\n class={{\n checkbox__mark: true,\n 'checkbox__mark--checked': !this.indeterminate,\n }}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n focusable=\"false\"\n >\n <path\n d={this.indeterminate ? 'M4 8H12' : 'M3.5 8.25L6.75 11.5L12.5 4.75'}\n vector-effect=\"non-scaling-stroke\"\n />\n </svg>\n )}\n </span>\n </span>\n {!this.presentation && (\n <ds-text\n class=\"checkbox__label ds-interaction-fill__content\"\n as=\"span\"\n variant={CONTROL_TEXT_VARIANT[this.size]}\n textId={this.labelId}\n >\n {this.label}\n </ds-text>\n )}\n </Host>\n );\n }\n}\n",
|
|
358
358
|
"type": "registry:ui"
|
|
359
359
|
}
|
|
360
360
|
]
|
|
@@ -277,7 +277,7 @@
|
|
|
277
277
|
},
|
|
278
278
|
{
|
|
279
279
|
"path": "src/wc/components/ConversationListItem/ConversationListItem.tsx",
|
|
280
|
-
"content": "
|
|
280
|
+
"content": "/* eslint-disable local/no-selected-fill-emphasis-change -- Unread emphasis is message state, independent of the selected-row fill state. */\nimport { Component, Element, Event, EventEmitter, h, Host, Prop } from '@stencil/core';\nimport type { ConversationItemState } from '../conversation-types';\n\n@Component({\n tag: 'ds-conversation-list-item',\n styleUrl: 'ConversationListItem.css',\n scoped: true,\n})\nexport class ConversationListItem {\n @Element() el!: HTMLElement;\n\n @Prop() conversationId: string = '';\n /** Visible conversation title. Named to avoid the native HTMLElement.title contract. */\n @Prop() conversationTitle: string = '';\n @Prop() preview: string = '';\n /** ISO timestamp for semantic activity metadata. */\n @Prop() updatedAt: string = '';\n @Prop() selected: boolean = false;\n @Prop() state: ConversationItemState = 'default';\n @Prop() statusLabel: string = '';\n @Prop() unreadCount: number = 0;\n /** Keep the contextual-actions surface visible while its popup is open or closing. */\n @Prop({ reflect: true }) actionsOpen: boolean = false;\n\n @Event() dsSelect!: EventEmitter<{ id: string }>;\n\n private handleClick = () => this.dsSelect.emit({ id: this.conversationId });\n\n private handleActionsSlotChange = (event: Event) => {\n const slot = event.target as HTMLSlotElement;\n this.el.classList.toggle(\n 'conversation-list-item--has-actions',\n slot.assignedElements().length > 0\n );\n };\n\n render() {\n const busy = this.state === 'busy';\n const subtext = busy && this.statusLabel ? this.statusLabel : this.preview;\n const accessibleName = [\n this.conversationTitle,\n subtext,\n this.unreadCount > 0 ? `${this.unreadCount} unread` : '',\n ]\n .filter(Boolean)\n .join('. ');\n\n return (\n <Host\n role=\"listitem\"\n class={{ 'conversation-list-item--actions-open': this.actionsOpen }}\n >\n <div class=\"conversation-list-item__row\">\n <button\n type=\"button\"\n class={{\n 'conversation-list-item': true,\n 'ds-choice-item': true,\n 'ds-control-frame': true,\n 'ds-control--md': true,\n 'ds-focus-ring-inset': true,\n 'ds-interaction-fill': true,\n 'ds-interaction-fill--selected': this.selected,\n 'conversation-list-item--error': this.state === 'error',\n }}\n aria-label={accessibleName}\n aria-current={this.selected ? 'true' : undefined}\n aria-busy={busy ? 'true' : undefined}\n onClick={this.handleClick}\n >\n <span class=\"conversation-list-item__leading ds-choice-item__icon ds-control-icon-box ds-interaction-fill__content\">\n <slot name=\"leading\" />\n </span>\n <span class=\"conversation-list-item__content ds-choice-item__content ds-interaction-fill__content\">\n <span class=\"conversation-list-item__title-row\">\n <ds-text\n class=\"conversation-list-item__title ds-choice-item__label ds-control-label-box\"\n as=\"span\"\n variant=\"text-body-medium\"\n emphasis={this.unreadCount > 0}\n color={this.unreadCount > 0 ? 'primary' : 'secondary'}\n lineTruncation={1}\n >\n {this.conversationTitle}\n </ds-text>\n {this.unreadCount > 0 ? (\n <span class=\"conversation-list-item__unread\">\n <ds-badge variant=\"dot\" surface=\"secondary\" hasRing={false} />\n </span>\n ) : null}\n </span>\n <span class=\"conversation-list-item__preview-row\">\n {busy ? <ds-loader size=\"sm\" color=\"secondary\" /> : null}\n <ds-text\n class=\"conversation-list-item__preview ds-choice-item__subtext ds-control-label-box\"\n as=\"span\"\n variant=\"text-body-small\"\n color={this.state === 'error' ? 'negative' : 'secondary'}\n lineTruncation={1}\n >\n {subtext}\n </ds-text>\n </span>\n {this.updatedAt ? (\n <time class=\"conversation-list-item__time ds-visually-hidden\" dateTime={this.updatedAt}>\n {this.updatedAt}\n </time>\n ) : null}\n </span>\n <span class=\"conversation-list-item__trailing ds-interaction-fill__content\">\n <slot name=\"trailing\" />\n </span>\n </button>\n <div class=\"conversation-list-item__actions ds-control-elevation ds-control-elevation--md ds-control-elevation--press-scale\">\n <slot name=\"actions\" onSlotchange={this.handleActionsSlotChange} />\n </div>\n </div>\n </Host>\n );\n }\n}\n",
|
|
281
281
|
"type": "registry:ui"
|
|
282
282
|
}
|
|
283
283
|
]
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"status": "stable",
|
|
16
16
|
"summary": "Accessible form-field composition that gives one Input or Select a persistent label, optional guidance, shared error presentation, stable IDs, and observable interaction state.",
|
|
17
17
|
"useWhen": [
|
|
18
|
-
"An Input
|
|
18
|
+
"An Input or Select needs a persistent visible label in a form.",
|
|
19
19
|
"Help text or an error message must be programmatically associated with one control.",
|
|
20
20
|
"A form layout needs one consistent label-control-message rhythm."
|
|
21
21
|
],
|
|
@@ -34,7 +34,6 @@
|
|
|
34
34
|
"commonlyComposedWith": [
|
|
35
35
|
"component:ds-input",
|
|
36
36
|
"component:ds-select",
|
|
37
|
-
"component:ds-select-multi",
|
|
38
37
|
"component:ds-text"
|
|
39
38
|
],
|
|
40
39
|
"accessibility": [
|
|
@@ -61,7 +60,7 @@
|
|
|
61
60
|
"Assign child component values and option arrays through their normal JavaScript properties."
|
|
62
61
|
],
|
|
63
62
|
"react": [
|
|
64
|
-
"Compose one DsInput
|
|
63
|
+
"Compose one DsInput or DsSelect child and control validation timing in the form owner."
|
|
65
64
|
],
|
|
66
65
|
"angular": [
|
|
67
66
|
"Compose the generated Field adapter around the control adapter and its matching Angular value accessor."
|
|
@@ -591,7 +591,7 @@
|
|
|
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 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 this.internals.
|
|
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 || this.error,\n 'input-control--error': 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
|
]
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
141
|
"path": "src/wc/components/Markdown/Markdown.tsx",
|
|
142
|
-
"content": "import { Component, h, Host, Prop, State, VNode, Watch } from '@stencil/core';\nimport type { Nodes, Root } from 'mdast';\n\ntype MarkdownRender = VNode | string | null | MarkdownRender[];\ntype MarkdownParser = {\n fromMarkdown: typeof import('mdast-util-from-markdown').fromMarkdown;\n gfmFromMarkdown: typeof import('mdast-util-gfm').gfmFromMarkdown;\n gfm: typeof import('micromark-extension-gfm').gfm;\n};\n\nlet parserPromise: Promise<MarkdownParser> | undefined;\n\nfunction loadParser(): Promise<MarkdownParser> {\n parserPromise ??= Promise.all([\n import('mdast-util-from-markdown'),\n import('mdast-util-gfm'),\n import('micromark-extension-gfm'),\n ]).then(([fromMarkdownModule, gfmFromMarkdownModule, gfmModule]) => ({\n fromMarkdown: fromMarkdownModule.fromMarkdown,\n gfmFromMarkdown: gfmFromMarkdownModule.gfmFromMarkdown,\n gfm: gfmModule.gfm,\n }));\n return parserPromise;\n}\n\
|
|
142
|
+
"content": "import { Component, h, Host, Prop, State, VNode, Watch } from '@stencil/core';\nimport type { Nodes, Root } from 'mdast';\nimport { resolveSafeUrl } from '../../utils';\n\ntype MarkdownRender = VNode | string | null | MarkdownRender[];\ntype MarkdownParser = {\n fromMarkdown: typeof import('mdast-util-from-markdown').fromMarkdown;\n gfmFromMarkdown: typeof import('mdast-util-gfm').gfmFromMarkdown;\n gfm: typeof import('micromark-extension-gfm').gfm;\n};\n\nlet parserPromise: Promise<MarkdownParser> | undefined;\n\nfunction loadParser(): Promise<MarkdownParser> {\n parserPromise ??= Promise.all([\n import('mdast-util-from-markdown'),\n import('mdast-util-gfm'),\n import('micromark-extension-gfm'),\n ]).then(([fromMarkdownModule, gfmFromMarkdownModule, gfmModule]) => ({\n fromMarkdown: fromMarkdownModule.fromMarkdown,\n gfmFromMarkdown: gfmFromMarkdownModule.gfmFromMarkdown,\n gfm: gfmModule.gfm,\n }));\n return parserPromise;\n}\n\n@Component({\n tag: 'ds-markdown',\n styleUrl: 'Markdown.css',\n scoped: true,\n})\nexport class Markdown {\n @Prop() content: string = '';\n @Prop() streaming: boolean = false;\n\n @State() private tree: Root | null = null;\n private parseFrame?: number;\n private parseRevision = 0;\n\n componentWillLoad() {\n // The browser-targeted named-character decoder used by the Markdown parser\n // creates a DOM element when its module is evaluated. Keep public package\n // imports server-safe by loading that parser only in a browser context.\n if (typeof document !== 'undefined') return this.parse();\n }\n\n disconnectedCallback() {\n this.parseRevision += 1;\n if (this.parseFrame && typeof cancelAnimationFrame === 'function') {\n cancelAnimationFrame(this.parseFrame);\n }\n }\n\n @Watch('content')\n scheduleParse() {\n if (typeof requestAnimationFrame !== 'function') return;\n if (this.parseFrame) cancelAnimationFrame(this.parseFrame);\n this.parseFrame = requestAnimationFrame(() => {\n this.parseFrame = undefined;\n void this.parse();\n });\n }\n\n private async parse() {\n const revision = ++this.parseRevision;\n try {\n const { fromMarkdown, gfmFromMarkdown, gfm } = await loadParser();\n const tree = fromMarkdown(this.content, {\n extensions: [gfm()],\n mdastExtensions: [gfmFromMarkdown()],\n });\n if (revision === this.parseRevision) this.tree = tree;\n } catch {\n if (revision === this.parseRevision) this.tree = null;\n }\n }\n\n private children(node: Nodes): MarkdownRender[] {\n if (!('children' in node)) return [];\n return node.children.map(child => this.renderNode(child));\n }\n\n private renderNode(node: Nodes): MarkdownRender {\n switch (node.type) {\n case 'root':\n return this.children(node);\n case 'text':\n // Keep prose text on an element boundary. Besides giving streaming updates a\n // stable render target, this avoids axe-core treating a bare Stencil text\n // vnode as an element while it generates a contrast-result selector.\n return <span class=\"markdown__text\">{node.value}</span>;\n case 'paragraph':\n return <p class=\"markdown__paragraph\">{this.children(node)}</p>;\n case 'heading': {\n const Tag = `h${node.depth}`;\n return <Tag class=\"markdown__heading\">{this.children(node)}</Tag>;\n }\n case 'strong':\n return <strong class=\"markdown__strong\">{this.children(node)}</strong>;\n case 'emphasis':\n return <em class=\"markdown__emphasis\">{this.children(node)}</em>;\n case 'delete':\n return <del class=\"markdown__delete\">{this.children(node)}</del>;\n case 'blockquote':\n return <blockquote class=\"markdown__blockquote\">{this.children(node)}</blockquote>;\n case 'break':\n return <br class=\"markdown__break\" />;\n case 'thematicBreak':\n return <hr class=\"markdown__thematic-break\" />;\n case 'inlineCode':\n return <code class=\"markdown__inline-code\">{node.value}</code>;\n case 'code':\n return (\n <ds-code-block\n class=\"markdown__code-block\"\n data-ds-prose=\"off\"\n code={node.value}\n language={node.lang ?? ''}\n filename={node.meta ?? ''}\n />\n );\n case 'link': {\n const href = resolveSafeUrl(node.url, {\n protocols: ['http:', 'https:', 'mailto:'],\n });\n return href ? (\n <a class=\"markdown__link\" href={href} target=\"_blank\" rel=\"noopener noreferrer\">\n {this.children(node)}\n </a>\n ) : (\n this.children(node)\n );\n }\n case 'list': {\n const Tag = node.ordered ? 'ol' : 'ul';\n return (\n <Tag class=\"markdown__list\" start={node.ordered && node.start ? node.start : undefined}>\n {this.children(node)}\n </Tag>\n );\n }\n case 'listItem':\n return (\n <li class=\"markdown__list-item\">\n {typeof node.checked === 'boolean' ? (\n <input\n class=\"markdown__task-indicator\"\n type=\"checkbox\"\n checked={node.checked}\n disabled\n aria-hidden=\"true\"\n tabIndex={-1}\n />\n ) : null}\n {this.children(node)}\n </li>\n );\n case 'table': {\n const [heading, ...rows] = node.children;\n return (\n <div class=\"markdown__table-wrap ds-prose__table-scroll\" tabIndex={0}>\n <table class=\"markdown__table\">\n {heading ? (\n <thead class=\"markdown__table-head\">\n <tr class=\"markdown__table-row\">\n {heading.children.map(cell => (\n <th class=\"markdown__table-heading\" scope=\"col\">\n {this.children(cell)}\n </th>\n ))}\n </tr>\n </thead>\n ) : null}\n <tbody class=\"markdown__table-body\">{rows.map(row => this.renderNode(row))}</tbody>\n </table>\n </div>\n );\n }\n case 'tableRow':\n return <tr class=\"markdown__table-row\">{this.children(node)}</tr>;\n case 'tableCell':\n return <td class=\"markdown__table-cell\">{this.children(node)}</td>;\n case 'image': {\n const href = resolveSafeUrl(node.url, {\n protocols: ['http:', 'https:', 'mailto:'],\n });\n return href ? (\n <a class=\"markdown__image-link\" href={href} target=\"_blank\" rel=\"noopener noreferrer\">\n {node.alt || 'View image'}\n </a>\n ) : (\n node.alt || null\n );\n }\n case 'html':\n case 'definition':\n case 'footnoteDefinition':\n return null;\n case 'footnoteReference':\n return <sup class=\"markdown__footnote\">{node.label}</sup>;\n default:\n return this.children(node);\n }\n }\n\n render() {\n return (\n <Host aria-busy={this.streaming ? 'true' : undefined}>\n <div class=\"markdown ds-prose\">\n {this.tree ? (\n this.renderNode(this.tree)\n ) : (\n <p class=\"markdown__paragraph\">\n <span class=\"markdown__text\">{this.content}</span>\n </p>\n )}\n </div>\n </Host>\n );\n }\n}\n",
|
|
143
143
|
"type": "registry:ui"
|
|
144
144
|
}
|
|
145
145
|
]
|