@ds-mo/ui 9.0.0 → 9.2.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.
Files changed (385) hide show
  1. package/README.md +28 -0
  2. package/dist/.build-stamp +1 -1
  3. package/dist/agent-patterns.json +397 -0
  4. package/dist/agent.json +2347 -735
  5. package/dist/angular/ds-agent-activity.d.ts +12 -0
  6. package/dist/angular/ds-agent-activity.js +38 -0
  7. package/dist/angular/ds-agent-response.d.ts +12 -0
  8. package/dist/angular/ds-agent-response.js +38 -0
  9. package/dist/angular/ds-agent-source-list.d.ts +12 -0
  10. package/dist/angular/ds-agent-source-list.js +38 -0
  11. package/dist/angular/ds-agent-tool-call.d.ts +12 -0
  12. package/dist/angular/ds-agent-tool-call.js +38 -0
  13. package/dist/angular/ds-attachment-list.d.ts +12 -0
  14. package/dist/angular/ds-attachment-list.js +38 -0
  15. package/dist/angular/ds-avatar.d.ts +12 -0
  16. package/dist/angular/ds-avatar.js +38 -0
  17. package/dist/angular/ds-code-block.d.ts +12 -0
  18. package/dist/angular/ds-code-block.js +38 -0
  19. package/dist/angular/ds-conversation-list-item.d.ts +19 -0
  20. package/dist/angular/ds-conversation-list-item.js +42 -0
  21. package/dist/angular/ds-conversation-list-section.d.ts +12 -0
  22. package/dist/angular/ds-conversation-list-section.js +38 -0
  23. package/dist/angular/ds-conversation-list.d.ts +12 -0
  24. package/dist/angular/ds-conversation-list.js +37 -0
  25. package/dist/angular/ds-markdown.d.ts +12 -0
  26. package/dist/angular/ds-markdown.js +38 -0
  27. package/dist/angular/ds-menu.d.ts +6 -1
  28. package/dist/angular/ds-menu.js +7 -4
  29. package/dist/angular/ds-message-bubble.d.ts +12 -0
  30. package/dist/angular/ds-message-bubble.js +38 -0
  31. package/dist/angular/ds-message-composer.d.ts +23 -0
  32. package/dist/angular/ds-message-composer.js +49 -0
  33. package/dist/angular/ds-message-scroller.d.ts +15 -0
  34. package/dist/angular/ds-message-scroller.js +43 -0
  35. package/dist/angular/ds-message.d.ts +12 -0
  36. package/dist/angular/ds-message.js +38 -0
  37. package/dist/angular/ds-panel-tool-header.d.ts +25 -0
  38. package/dist/angular/ds-panel-tool-header.js +49 -0
  39. package/dist/angular/ds-panel-tool-search.d.ts +19 -0
  40. package/dist/angular/ds-panel-tool-search.js +49 -0
  41. package/dist/angular/ds-panel-tools.d.ts +30 -1
  42. package/dist/angular/ds-panel-tools.js +14 -5
  43. package/dist/angular/ds-swatch-picker.d.ts +15 -0
  44. package/dist/angular/ds-swatch-picker.js +42 -0
  45. package/dist/angular/index.d.ts +1 -1
  46. package/dist/angular/index.js +18 -0
  47. package/dist/angular/proxies.d.ts +18 -0
  48. package/dist/angular/proxies.js +18 -0
  49. package/dist/components/ds-agent-activity.d.ts +11 -0
  50. package/dist/components/ds-agent-activity.js +2 -0
  51. package/dist/components/ds-agent-activity.js.map +1 -0
  52. package/dist/components/ds-agent-response.d.ts +11 -0
  53. package/dist/components/ds-agent-response.js +2 -0
  54. package/dist/components/ds-agent-response.js.map +1 -0
  55. package/dist/components/ds-agent-source-list.d.ts +11 -0
  56. package/dist/components/ds-agent-source-list.js +2 -0
  57. package/dist/components/ds-agent-source-list.js.map +1 -0
  58. package/dist/components/ds-agent-tool-call.d.ts +11 -0
  59. package/dist/components/ds-agent-tool-call.js +2 -0
  60. package/dist/components/ds-agent-tool-call.js.map +1 -0
  61. package/dist/components/ds-app-shell.js +1 -1
  62. package/dist/components/ds-app-shell.js.map +1 -1
  63. package/dist/components/ds-attachment-list.d.ts +11 -0
  64. package/dist/components/ds-attachment-list.js +2 -0
  65. package/dist/components/ds-attachment-list.js.map +1 -0
  66. package/dist/components/ds-avatar.d.ts +11 -0
  67. package/dist/components/ds-avatar.js +2 -0
  68. package/dist/components/ds-avatar.js.map +1 -0
  69. package/dist/components/ds-badge.js +1 -1
  70. package/dist/components/ds-banner.js +1 -1
  71. package/dist/components/ds-bar-nav.js +1 -1
  72. package/dist/components/ds-bar-nav.js.map +1 -1
  73. package/dist/components/ds-button-filled.js +1 -1
  74. package/dist/components/ds-button-unfilled.js +1 -1
  75. package/dist/components/ds-card-data-viz-donut.js +1 -1
  76. package/dist/components/ds-card-setting.js +1 -1
  77. package/dist/components/ds-card-shell-data-viz.js +1 -1
  78. package/dist/components/ds-card.js +1 -1
  79. package/dist/components/ds-chart-bar.js +1 -1
  80. package/dist/components/ds-chart-bar.js.map +1 -1
  81. package/dist/components/ds-chart-donut.js +1 -1
  82. package/dist/components/ds-chart-legend.js +1 -1
  83. package/dist/components/ds-chart-line.js +1 -1
  84. package/dist/components/ds-checkbox.js +1 -1
  85. package/dist/components/ds-chip.js +1 -1
  86. package/dist/components/ds-code-block.d.ts +11 -0
  87. package/dist/components/ds-code-block.js +2 -0
  88. package/dist/components/ds-code-block.js.map +1 -0
  89. package/dist/components/ds-conversation-list-item.d.ts +11 -0
  90. package/dist/components/ds-conversation-list-item.js +2 -0
  91. package/dist/components/ds-conversation-list-item.js.map +1 -0
  92. package/dist/components/ds-conversation-list-section.d.ts +11 -0
  93. package/dist/components/ds-conversation-list-section.js +2 -0
  94. package/dist/components/ds-conversation-list-section.js.map +1 -0
  95. package/dist/components/ds-conversation-list.d.ts +11 -0
  96. package/dist/components/ds-conversation-list.js +2 -0
  97. package/dist/components/ds-conversation-list.js.map +1 -0
  98. package/dist/components/ds-divider.js +1 -1
  99. package/dist/components/ds-divider.js.map +1 -1
  100. package/dist/components/ds-empty-state.js +1 -1
  101. package/dist/components/ds-field.js +1 -1
  102. package/dist/components/ds-icon.js +1 -1
  103. package/dist/components/ds-input.js +1 -1
  104. package/dist/components/ds-markdown.d.ts +11 -0
  105. package/dist/components/ds-markdown.js +2 -0
  106. package/dist/components/ds-markdown.js.map +1 -0
  107. package/dist/components/ds-menu.js +1 -1
  108. package/dist/components/ds-message-bubble.d.ts +11 -0
  109. package/dist/components/ds-message-bubble.js +2 -0
  110. package/dist/components/ds-message-bubble.js.map +1 -0
  111. package/dist/components/ds-message-composer.d.ts +11 -0
  112. package/dist/components/ds-message-composer.js +2 -0
  113. package/dist/components/ds-message-composer.js.map +1 -0
  114. package/dist/components/ds-message-scroller.d.ts +11 -0
  115. package/dist/components/ds-message-scroller.js +2 -0
  116. package/dist/components/ds-message-scroller.js.map +1 -0
  117. package/dist/components/ds-message.d.ts +11 -0
  118. package/dist/components/ds-message.js +2 -0
  119. package/dist/components/ds-message.js.map +1 -0
  120. package/dist/components/ds-modal.js +1 -1
  121. package/dist/components/ds-panel-nav.js +1 -1
  122. package/dist/components/ds-panel-nav.js.map +1 -1
  123. package/dist/components/ds-panel-sub-nav.js +1 -1
  124. package/dist/components/ds-panel-tool-header.d.ts +11 -0
  125. package/dist/components/ds-panel-tool-header.js +2 -0
  126. package/dist/components/ds-panel-tool-header.js.map +1 -0
  127. package/dist/components/ds-panel-tool-search.d.ts +11 -0
  128. package/dist/components/ds-panel-tool-search.js +2 -0
  129. package/dist/components/ds-panel-tool-search.js.map +1 -0
  130. package/dist/components/ds-panel-tools.js +1 -1
  131. package/dist/components/ds-panel-tools.js.map +1 -1
  132. package/dist/components/ds-radio.js +1 -1
  133. package/dist/components/ds-select-multi.js +1 -1
  134. package/dist/components/ds-select-multi.js.map +1 -1
  135. package/dist/components/ds-select.js +1 -1
  136. package/dist/components/ds-select.js.map +1 -1
  137. package/dist/components/ds-shell-gradient-picker.js +1 -1
  138. package/dist/components/ds-shell-gradient-picker.js.map +1 -1
  139. package/dist/components/ds-shell-gradient-swatch.js +1 -1
  140. package/dist/components/ds-shell-gradient-swatch.js.map +1 -1
  141. package/dist/components/ds-skeleton.js +1 -1
  142. package/dist/components/ds-slider.js +1 -1
  143. package/dist/components/ds-slider.js.map +1 -1
  144. package/dist/components/ds-swatch-picker.d.ts +11 -0
  145. package/dist/components/ds-swatch-picker.js +2 -0
  146. package/dist/components/ds-swatch-picker.js.map +1 -0
  147. package/dist/components/ds-switch.js +1 -1
  148. package/dist/components/ds-tab-group.js +1 -1
  149. package/dist/components/ds-tab-group.js.map +1 -1
  150. package/dist/components/ds-tag.js +1 -1
  151. package/dist/components/ds-text.js +1 -1
  152. package/dist/components/ds-tooltip-data-viz.js +1 -1
  153. package/dist/components/ds-tooltip.js +1 -1
  154. package/dist/components/index.d.ts +14 -0
  155. package/dist/components/p--KbMQblZ.js +2 -0
  156. package/dist/components/p--KbMQblZ.js.map +1 -0
  157. package/dist/components/p-2br9YDbG.js +2 -0
  158. package/dist/components/p-2br9YDbG.js.map +1 -0
  159. package/dist/components/p-41UAx2eq.js +2 -0
  160. package/dist/components/p-41UAx2eq.js.map +1 -0
  161. package/dist/components/p-B1pWGQn1.js +2 -0
  162. package/dist/components/p-B1pWGQn1.js.map +1 -0
  163. package/dist/components/p-B7NbIYjS.js +2 -0
  164. package/dist/components/p-B7NbIYjS.js.map +1 -0
  165. package/dist/components/p-BBu_Svz7.js +2 -0
  166. package/dist/components/p-BBu_Svz7.js.map +1 -0
  167. package/dist/components/p-BEQB8EnB.js +2 -0
  168. package/dist/components/p-BEQB8EnB.js.map +1 -0
  169. package/dist/components/{p-CZ9wemOA.js → p-BFWC17em.js} +2 -2
  170. package/dist/components/{p-KRGBGTu5.js → p-BO6C8abO.js} +2 -2
  171. package/dist/components/{p-CbS_WWs2.js → p-BSOZXagj.js} +2 -2
  172. package/dist/components/p-BSOZXagj.js.map +1 -0
  173. package/dist/components/{p-DT2MK8Kt.js → p-BZAEZENv.js} +2 -2
  174. package/dist/components/p-BhC1YyId.js +2 -0
  175. package/dist/components/p-BhC1YyId.js.map +1 -0
  176. package/dist/components/p-BjtXYFhw.js +2 -0
  177. package/dist/components/p-BjtXYFhw.js.map +1 -0
  178. package/dist/components/{p-B-zhgAvL.js → p-Bo5wikia.js} +2 -2
  179. package/dist/components/p-Bx1G7P6W.js +2 -0
  180. package/dist/components/p-Bx1G7P6W.js.map +1 -0
  181. package/dist/components/p-C0sq948W.js +2 -0
  182. package/dist/components/p-C0sq948W.js.map +1 -0
  183. package/dist/components/p-CC1C8s6m.js +2 -0
  184. package/dist/components/p-CC1C8s6m.js.map +1 -0
  185. package/dist/components/p-CKaJx0IX.js +2 -0
  186. package/dist/components/p-CKaJx0IX.js.map +1 -0
  187. package/dist/components/{p-DyZj3k9S.js → p-CZMEhdlA.js} +2 -2
  188. package/dist/components/{p-BbV68F23.js → p-CiwdnKKp.js} +2 -2
  189. package/dist/components/{p-BLzivrE3.js → p-CnM9SW_8.js} +2 -2
  190. package/dist/components/{p-C7UFYvsO.js → p-CuKn9I5f.js} +2 -2
  191. package/dist/components/p-D1HFMTdC.js +2 -0
  192. package/dist/components/p-D1HFMTdC.js.map +1 -0
  193. package/dist/components/p-DFMM60My.js +2 -0
  194. package/dist/components/p-DFMM60My.js.map +1 -0
  195. package/dist/components/p-DIsDiGcp.js +2 -0
  196. package/dist/components/p-DIsDiGcp.js.map +1 -0
  197. package/dist/components/p-DVsje4AY.js +2 -0
  198. package/dist/components/p-DVsje4AY.js.map +1 -0
  199. package/dist/components/p-Di-ThR90.js +2 -0
  200. package/dist/components/p-Di-ThR90.js.map +1 -0
  201. package/dist/components/{p-C7RObioO.js → p-Di4HBckb.js} +2 -2
  202. package/dist/components/p-a9nGf1s6.js +2 -0
  203. package/dist/components/p-a9nGf1s6.js.map +1 -0
  204. package/dist/components/p-gidVv1FX.js +2 -0
  205. package/dist/components/p-gidVv1FX.js.map +1 -0
  206. package/dist/components/p-l6PmnW_P.js +2 -0
  207. package/dist/components/p-l6PmnW_P.js.map +1 -0
  208. package/dist/components/p-rEe-3KR_.js +2 -0
  209. package/dist/components/p-rEe-3KR_.js.map +1 -0
  210. package/dist/components/p-t9Ei1kHP.js +2 -0
  211. package/dist/components/p-t9Ei1kHP.js.map +1 -0
  212. package/dist/docs/components.json +8097 -3924
  213. package/dist/lib/components/Menu/menu-placement.d.ts +19 -3
  214. package/dist/lib/shell/index.d.ts +3 -3
  215. package/dist/lib/shell/index.js +48 -39
  216. package/dist/lib/shell/index.js.map +3 -3
  217. package/dist/lib/shell/shell-gradient-presets.d.ts +15 -0
  218. package/dist/lib/utils/choice-popup-alignment.d.ts +20 -0
  219. package/dist/lib/utils/index.d.ts +2 -0
  220. package/dist/lib/utils/index.js +16 -0
  221. package/dist/lib/utils/index.js.map +3 -3
  222. package/dist/mcp/cli.js +31409 -0
  223. package/dist/mcp-data/registry/agent-activity.json +158 -0
  224. package/dist/mcp-data/registry/agent-response.json +211 -0
  225. package/dist/mcp-data/registry/agent-source-list.json +153 -0
  226. package/dist/mcp-data/registry/agent-tool-call.json +213 -0
  227. package/dist/mcp-data/registry/app-shell.json +210 -0
  228. package/dist/mcp-data/registry/attachment-list.json +137 -0
  229. package/dist/mcp-data/registry/avatar.json +136 -0
  230. package/dist/mcp-data/registry/badge.json +289 -0
  231. package/dist/mcp-data/registry/banner.json +206 -0
  232. package/dist/mcp-data/registry/bar-nav.json +341 -0
  233. package/dist/mcp-data/registry/button-filled.json +386 -0
  234. package/dist/mcp-data/registry/button-unfilled.json +537 -0
  235. package/dist/mcp-data/registry/card-data-viz-donut.json +143 -0
  236. package/dist/mcp-data/registry/card-setting.json +194 -0
  237. package/dist/mcp-data/registry/card-shell-data-viz.json +173 -0
  238. package/dist/mcp-data/registry/card.json +126 -0
  239. package/dist/mcp-data/registry/chart-bar.json +121 -0
  240. package/dist/mcp-data/registry/chart-donut.json +257 -0
  241. package/dist/mcp-data/registry/chart-legend.json +209 -0
  242. package/dist/mcp-data/registry/chart-line.json +153 -0
  243. package/dist/mcp-data/registry/checkbox.json +361 -0
  244. package/dist/mcp-data/registry/chip.json +276 -0
  245. package/dist/mcp-data/registry/code-block.json +150 -0
  246. package/dist/mcp-data/registry/conversation-list-item.json +265 -0
  247. package/dist/mcp-data/registry/conversation-list-section.json +139 -0
  248. package/dist/mcp-data/registry/conversation-list.json +101 -0
  249. package/dist/mcp-data/registry/divider.json +225 -0
  250. package/dist/mcp-data/registry/empty-state.json +197 -0
  251. package/dist/mcp-data/registry/field.json +222 -0
  252. package/dist/mcp-data/registry/icon.json +242 -0
  253. package/dist/mcp-data/registry/input.json +597 -0
  254. package/dist/mcp-data/registry/loader.json +192 -0
  255. package/dist/mcp-data/registry/markdown.json +141 -0
  256. package/dist/mcp-data/registry/menu.json +479 -0
  257. package/dist/mcp-data/registry/message-bubble.json +119 -0
  258. package/dist/mcp-data/registry/message-composer.json +265 -0
  259. package/dist/mcp-data/registry/message-scroller.json +217 -0
  260. package/dist/mcp-data/registry/message.json +255 -0
  261. package/dist/mcp-data/registry/modal.json +150 -0
  262. package/dist/mcp-data/registry/panel-nav.json +622 -0
  263. package/dist/mcp-data/registry/panel-sub-nav.json +249 -0
  264. package/dist/mcp-data/registry/panel-tool-header.json +342 -0
  265. package/dist/mcp-data/registry/panel-tool-search.json +387 -0
  266. package/dist/mcp-data/registry/panel-tools.json +514 -0
  267. package/dist/mcp-data/registry/radio.json +374 -0
  268. package/dist/mcp-data/registry/registry.json +6916 -0
  269. package/dist/mcp-data/registry/select-multi.json +755 -0
  270. package/dist/mcp-data/registry/select.json +740 -0
  271. package/dist/mcp-data/registry/shell-gradient-picker.json +195 -0
  272. package/dist/mcp-data/registry/shell-gradient-swatch.json +215 -0
  273. package/dist/mcp-data/registry/skeleton.json +282 -0
  274. package/dist/mcp-data/registry/slider.json +657 -0
  275. package/dist/mcp-data/registry/swatch-picker.json +231 -0
  276. package/dist/mcp-data/registry/switch.json +361 -0
  277. package/dist/mcp-data/registry/tab-group.json +255 -0
  278. package/dist/mcp-data/registry/tag.json +352 -0
  279. package/dist/mcp-data/registry/text.json +371 -0
  280. package/dist/mcp-data/registry/tooltip-data-viz.json +158 -0
  281. package/dist/mcp-data/registry/tooltip.json +311 -0
  282. package/dist/react/components.d.ts +18 -0
  283. package/dist/react/components.js +18 -0
  284. package/dist/react/ds-agent-activity.d.ts +9 -0
  285. package/dist/react/ds-agent-activity.js +12 -0
  286. package/dist/react/ds-agent-response.d.ts +9 -0
  287. package/dist/react/ds-agent-response.js +12 -0
  288. package/dist/react/ds-agent-source-list.d.ts +9 -0
  289. package/dist/react/ds-agent-source-list.js +12 -0
  290. package/dist/react/ds-agent-tool-call.d.ts +9 -0
  291. package/dist/react/ds-agent-tool-call.js +12 -0
  292. package/dist/react/ds-attachment-list.d.ts +9 -0
  293. package/dist/react/ds-attachment-list.js +12 -0
  294. package/dist/react/ds-avatar.d.ts +9 -0
  295. package/dist/react/ds-avatar.js +12 -0
  296. package/dist/react/ds-code-block.d.ts +9 -0
  297. package/dist/react/ds-code-block.js +12 -0
  298. package/dist/react/ds-conversation-list-item.d.ts +14 -0
  299. package/dist/react/ds-conversation-list-item.js +12 -0
  300. package/dist/react/ds-conversation-list-section.d.ts +9 -0
  301. package/dist/react/ds-conversation-list-section.js +12 -0
  302. package/dist/react/ds-conversation-list.d.ts +9 -0
  303. package/dist/react/ds-conversation-list.js +12 -0
  304. package/dist/react/ds-markdown.d.ts +9 -0
  305. package/dist/react/ds-markdown.js +12 -0
  306. package/dist/react/ds-menu.d.ts +1 -0
  307. package/dist/react/ds-menu.js +2 -1
  308. package/dist/react/ds-message-bubble.d.ts +9 -0
  309. package/dist/react/ds-message-bubble.js +12 -0
  310. package/dist/react/ds-message-composer.d.ts +16 -0
  311. package/dist/react/ds-message-composer.js +16 -0
  312. package/dist/react/ds-message-scroller.d.ts +12 -0
  313. package/dist/react/ds-message-scroller.js +12 -0
  314. package/dist/react/ds-message.d.ts +9 -0
  315. package/dist/react/ds-message.js +12 -0
  316. package/dist/react/ds-panel-tool-header.d.ts +17 -0
  317. package/dist/react/ds-panel-tool-header.js +16 -0
  318. package/dist/react/ds-panel-tool-search.d.ts +14 -0
  319. package/dist/react/ds-panel-tool-search.js +16 -0
  320. package/dist/react/ds-panel-tools.d.ts +10 -0
  321. package/dist/react/ds-panel-tools.js +3 -0
  322. package/dist/react/ds-swatch-picker.d.ts +12 -0
  323. package/dist/react/ds-swatch-picker.js +12 -0
  324. package/dist/types/components/AgentActivity/AgentActivity.d.ts +14 -0
  325. package/dist/types/components/AgentResponse/AgentResponse.d.ts +12 -0
  326. package/dist/types/components/AgentSourceList/AgentSourceList.d.ts +9 -0
  327. package/dist/types/components/AgentToolCall/AgentToolCall.d.ts +13 -0
  328. package/dist/types/components/AppShell/AppShell.d.ts +4 -0
  329. package/dist/types/components/AttachmentList/AttachmentList.d.ts +8 -0
  330. package/dist/types/components/Avatar/Avatar.d.ts +8 -0
  331. package/dist/types/components/CodeBlock/CodeBlock.d.ts +11 -0
  332. package/dist/types/components/ConversationList/ConversationList.d.ts +4 -0
  333. package/dist/types/components/ConversationListItem/ConversationListItem.d.ts +22 -0
  334. package/dist/types/components/ConversationListSection/ConversationListSection.d.ts +9 -0
  335. package/dist/types/components/Markdown/Markdown.d.ts +15 -0
  336. package/dist/types/components/Menu/Menu.d.ts +10 -1
  337. package/dist/types/components/Menu/menu-placement.d.ts +19 -3
  338. package/dist/types/components/Menu/menu-types.d.ts +15 -2
  339. package/dist/types/components/Message/Message.d.ts +17 -0
  340. package/dist/types/components/MessageBubble/MessageBubble.d.ts +6 -0
  341. package/dist/types/components/MessageComposer/MessageComposer.d.ts +29 -0
  342. package/dist/types/components/MessageScroller/MessageScroller.d.ts +37 -0
  343. package/dist/types/components/PanelNav/PanelNav.d.ts +3 -0
  344. package/dist/types/components/PanelToolHeader/PanelToolHeader.d.ts +34 -0
  345. package/dist/types/components/PanelToolSearch/PanelToolSearch.d.ts +35 -0
  346. package/dist/types/components/PanelTools/PanelTools.d.ts +40 -1
  347. package/dist/types/components/PanelTools/panel-tools-types.d.ts +20 -0
  348. package/dist/types/components/PanelTools/panel-tools-utils.d.ts +2 -0
  349. package/dist/types/components/ShellGradientPicker/ShellGradientPicker.d.ts +2 -5
  350. package/dist/types/components/ShellGradientSwatch/ShellGradientSwatch.d.ts +1 -0
  351. package/dist/types/components/Slider/Slider.d.ts +1 -1
  352. package/dist/types/components/SwatchPicker/SwatchPicker.d.ts +21 -0
  353. package/dist/types/components/SwatchPicker/swatch-picker-types.d.ts +26 -0
  354. package/dist/types/components/conversation-types.d.ts +55 -0
  355. package/dist/types/components.d.ts +1298 -4
  356. package/dist/types/shell/index.d.ts +3 -3
  357. package/dist/types/shell/shell-gradient-presets.d.ts +15 -0
  358. package/dist/types/utils/choice-list-parts.d.ts +4 -1
  359. package/dist/types/utils/choice-popup-alignment.d.ts +21 -0
  360. package/dist/types/utils/index.d.ts +2 -0
  361. package/package.json +9 -2
  362. package/dist/components/p-Bafp65bw.js +0 -2
  363. package/dist/components/p-Bafp65bw.js.map +0 -1
  364. package/dist/components/p-BdnR3jxi.js +0 -2
  365. package/dist/components/p-BdnR3jxi.js.map +0 -1
  366. package/dist/components/p-CXF8yd-g.js +0 -2
  367. package/dist/components/p-CXF8yd-g.js.map +0 -1
  368. package/dist/components/p-C_cu-HIT.js +0 -2
  369. package/dist/components/p-C_cu-HIT.js.map +0 -1
  370. package/dist/components/p-CbS_WWs2.js.map +0 -1
  371. package/dist/components/p-D0B9uDTP.js +0 -2
  372. package/dist/components/p-D0B9uDTP.js.map +0 -1
  373. package/dist/components/p-DF0yLZG_.js +0 -2
  374. package/dist/components/p-DF0yLZG_.js.map +0 -1
  375. package/dist/components/p-VKIsOVza.js +0 -2
  376. package/dist/components/p-VKIsOVza.js.map +0 -1
  377. /package/dist/components/{p-CZ9wemOA.js.map → p-BFWC17em.js.map} +0 -0
  378. /package/dist/components/{p-KRGBGTu5.js.map → p-BO6C8abO.js.map} +0 -0
  379. /package/dist/components/{p-DT2MK8Kt.js.map → p-BZAEZENv.js.map} +0 -0
  380. /package/dist/components/{p-B-zhgAvL.js.map → p-Bo5wikia.js.map} +0 -0
  381. /package/dist/components/{p-DyZj3k9S.js.map → p-CZMEhdlA.js.map} +0 -0
  382. /package/dist/components/{p-BbV68F23.js.map → p-CiwdnKKp.js.map} +0 -0
  383. /package/dist/components/{p-BLzivrE3.js.map → p-CnM9SW_8.js.map} +0 -0
  384. /package/dist/components/{p-C7UFYvsO.js.map → p-CuKn9I5f.js.map} +0 -0
  385. /package/dist/components/{p-C7RObioO.js.map → p-Di4HBckb.js.map} +0 -0
@@ -0,0 +1,121 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "chart-bar",
4
+ "title": "ChartBar",
5
+ "description": "ChartBar component from @ds-mo/ui.",
6
+ "type": "registry:ui",
7
+ "meta": {
8
+ "library": "@ds-mo/ui",
9
+ "distribution": "npm",
10
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/chart-bar",
11
+ "source": "src/wc/components/ChartBar/ChartBar.tsx",
12
+ "intentStatus": "migration-pending",
13
+ "intent": null,
14
+ "api": {
15
+ "props": {
16
+ "data": {
17
+ "type": "ChartDatum[]",
18
+ "resolvedType": "ChartDatum[]",
19
+ "default": "[]",
20
+ "required": false,
21
+ "mutable": false,
22
+ "description": "Bars to render. Set as a JS property (not an HTML attribute)."
23
+ },
24
+ "height": {
25
+ "type": "number",
26
+ "resolvedType": "number",
27
+ "attribute": "height",
28
+ "default": "240",
29
+ "required": false,
30
+ "mutable": false
31
+ },
32
+ "width": {
33
+ "type": "number",
34
+ "resolvedType": "number",
35
+ "attribute": "width",
36
+ "default": "480",
37
+ "required": false,
38
+ "mutable": false
39
+ }
40
+ },
41
+ "events": [],
42
+ "methods": [],
43
+ "slots": []
44
+ },
45
+ "props": {
46
+ "data": {
47
+ "type": "ChartDatum[]",
48
+ "resolvedType": "ChartDatum[]",
49
+ "default": "[]",
50
+ "required": false,
51
+ "mutable": false,
52
+ "description": "Bars to render. Set as a JS property (not an HTML attribute)."
53
+ },
54
+ "height": {
55
+ "type": "number",
56
+ "resolvedType": "number",
57
+ "attribute": "height",
58
+ "default": "240",
59
+ "required": false,
60
+ "mutable": false
61
+ },
62
+ "width": {
63
+ "type": "number",
64
+ "resolvedType": "number",
65
+ "attribute": "width",
66
+ "default": "480",
67
+ "required": false,
68
+ "mutable": false
69
+ }
70
+ },
71
+ "events": [],
72
+ "methods": [],
73
+ "slots": [],
74
+ "exports": {
75
+ "customElement": "ds-chart-bar",
76
+ "react": "DsChartBar",
77
+ "angular": "DsChartBar"
78
+ },
79
+ "consumption": {
80
+ "install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
81
+ "cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
82
+ "customElements": {
83
+ "import": "import '@ds-mo/ui/dist/components/ds-chart-bar.js';",
84
+ "example": "<ds-chart-bar></ds-chart-bar>"
85
+ },
86
+ "react": {
87
+ "import": "import { DsChartBar } from '@ds-mo/ui/react';",
88
+ "example": "<DsChartBar />"
89
+ },
90
+ "angular": {
91
+ "import": "import { DsChartBar } from '@ds-mo/ui/angular/ds-chart-bar';",
92
+ "example": "<ds-chart-bar></ds-chart-bar>"
93
+ },
94
+ "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: data.",
95
+ "peerDependencies": {
96
+ "required": [
97
+ "@ds-mo/tokens ^3.1.1",
98
+ "@ds-mo/icons ^6.2.0"
99
+ ],
100
+ "frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
101
+ }
102
+ }
103
+ },
104
+ "dependencies": [
105
+ "@ds-mo/ui",
106
+ "@ds-mo/tokens"
107
+ ],
108
+ "registryDependencies": [],
109
+ "files": [
110
+ {
111
+ "path": "src/wc/components/ChartBar/ChartBar.css",
112
+ "content": ":host {\n display: inline-flex;\n font-family: var(--typography-font-family);\n}\n\n.chart-bar__gridline {\n stroke: var(--color-border-tertiary);\n stroke-width: 1;\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 {\n rx: var(--dimension-radius-050);\n}\n",
113
+ "type": "registry:ui"
114
+ },
115
+ {
116
+ "path": "src/wc/components/ChartBar/ChartBar.tsx",
117
+ "content": "import { Component, Prop, h, Host } from '@stencil/core';\nimport { scaleBand, scaleLinear } from 'd3-scale';\nimport { max } from 'd3-array';\nimport { categoryColor } from '../../utils/chart-colors';\nimport type { ChartDatum } from '../../utils/chart-types';\n\nconst MARGIN = { top: 16, right: 16, bottom: 24, left: 32 };\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 @Prop() width: number = 480;\n @Prop() height: number = 240;\n\n render() {\n const innerWidth = this.width - MARGIN.left - MARGIN.right;\n const innerHeight = this.height - 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 viewBox={`0 0 ${this.width} ${this.height}`}\n width={this.width}\n height={this.height}\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 class=\"chart-bar__axis-label\" x={-8} text-anchor=\"end\" dominant-baseline=\"middle\">\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 return (\n <g key={d.label}>\n <rect\n class=\"chart-bar__bar\"\n x={barX}\n y={barY}\n width={barWidth}\n height={innerHeight - barY}\n fill={d.color ?? categoryColor(i)}\n />\n <text\n class=\"chart-bar__axis-label\"\n x={barX + barWidth / 2}\n y={innerHeight + 16}\n text-anchor=\"middle\"\n >\n {d.label}\n </text>\n </g>\n );\n })}\n </g>\n </svg>\n </Host>\n );\n }\n}\n",
118
+ "type": "registry:ui"
119
+ }
120
+ ]
121
+ }
@@ -0,0 +1,257 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "chart-donut",
4
+ "title": "ChartDonut",
5
+ "description": "ChartDonut component from @ds-mo/ui.",
6
+ "type": "registry:ui",
7
+ "meta": {
8
+ "library": "@ds-mo/ui",
9
+ "distribution": "npm",
10
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/chart-donut",
11
+ "source": "src/wc/components/ChartDonut/ChartDonut.tsx",
12
+ "intentStatus": "migration-pending",
13
+ "intent": null,
14
+ "api": {
15
+ "props": {
16
+ "activeLabel": {
17
+ "type": "string | null",
18
+ "resolvedType": "null | string",
19
+ "attribute": "active-label",
20
+ "default": "null",
21
+ "required": false,
22
+ "mutable": false,
23
+ "description": "Externally controlled highlight, matched by `label` — e.g. drive this from a sibling\n`ds-chart-legend`'s `dsItemHover` event to keep chart and legend hover in sync.\nFalls back to this component's own pointer/focus hover when unset.\nSlice hover dims peer slices and emits `dsSliceHover` for legend sync — no data-viz\ntooltip (the legend already surfaces label/value)."
24
+ },
25
+ "centerCaption": {
26
+ "type": "string | undefined",
27
+ "resolvedType": "string | undefined",
28
+ "attribute": "center-caption",
29
+ "required": false,
30
+ "mutable": false,
31
+ "description": "Secondary caption below the center value (e.g. \"Total\", \"Normal\"). Rendered uppercase."
32
+ },
33
+ "centerValue": {
34
+ "type": "string | undefined",
35
+ "resolvedType": "string | undefined",
36
+ "attribute": "center-value",
37
+ "required": false,
38
+ "mutable": false,
39
+ "description": "Primary center value; defaults to the sum of `data` values (e.g. \"187\", \"40.9%\")."
40
+ },
41
+ "cornerRadius": {
42
+ "type": "number | string",
43
+ "resolvedType": "number | string",
44
+ "attribute": "corner-radius",
45
+ "default": "TOKEN_DEFAULTS.radius025",
46
+ "required": false,
47
+ "mutable": false,
48
+ "description": "Corner radius on each slice — number (px) or TokoMo length. Defaults to `--dimension-radius-025` (2px)."
49
+ },
50
+ "data": {
51
+ "type": "ChartDatum[]",
52
+ "resolvedType": "ChartDatum[]",
53
+ "default": "[]",
54
+ "required": false,
55
+ "mutable": false,
56
+ "description": "Slices to render. Set as a JS property (not an HTML attribute)."
57
+ },
58
+ "gap": {
59
+ "type": "number",
60
+ "resolvedType": "number",
61
+ "attribute": "gap",
62
+ "default": "1",
63
+ "required": false,
64
+ "mutable": false,
65
+ "description": "Gap between slices, in degrees."
66
+ },
67
+ "locale": {
68
+ "type": "string | undefined",
69
+ "resolvedType": "string | undefined",
70
+ "attribute": "locale",
71
+ "required": false,
72
+ "mutable": false
73
+ },
74
+ "noDataLabel": {
75
+ "type": "string",
76
+ "resolvedType": "string",
77
+ "attribute": "no-data-label",
78
+ "default": "'No data'",
79
+ "required": false,
80
+ "mutable": false
81
+ },
82
+ "size": {
83
+ "type": "number | undefined",
84
+ "resolvedType": "number | undefined",
85
+ "attribute": "size",
86
+ "required": false,
87
+ "mutable": false,
88
+ "description": "Explicit diameter in px. When unset, the donut sizes to its container\n(ResizeObserver) clamped between `--dimension-size-base * 16` (128px) and\n`* 24` (192px), and stays centered in the leftover space. Prefer unset\ninside card layouts."
89
+ },
90
+ "thickness": {
91
+ "type": "number | string",
92
+ "resolvedType": "number | string",
93
+ "attribute": "thickness",
94
+ "default": "TOKEN_DEFAULTS.size200",
95
+ "required": false,
96
+ "mutable": false,
97
+ "description": "Ring thickness — number (px) or TokoMo length. Defaults to `--dimension-size-200` (16px)."
98
+ }
99
+ },
100
+ "events": [
101
+ {
102
+ "name": "dsSliceHover",
103
+ "detail": "ChartDatum | null",
104
+ "bubbles": true,
105
+ "cancelable": true,
106
+ "composed": true,
107
+ "description": "Fires with the hovered/focused slice's datum, or `null` on leave/blur."
108
+ }
109
+ ],
110
+ "methods": [],
111
+ "slots": []
112
+ },
113
+ "props": {
114
+ "activeLabel": {
115
+ "type": "string | null",
116
+ "resolvedType": "null | string",
117
+ "attribute": "active-label",
118
+ "default": "null",
119
+ "required": false,
120
+ "mutable": false,
121
+ "description": "Externally controlled highlight, matched by `label` — e.g. drive this from a sibling\n`ds-chart-legend`'s `dsItemHover` event to keep chart and legend hover in sync.\nFalls back to this component's own pointer/focus hover when unset.\nSlice hover dims peer slices and emits `dsSliceHover` for legend sync — no data-viz\ntooltip (the legend already surfaces label/value)."
122
+ },
123
+ "centerCaption": {
124
+ "type": "string | undefined",
125
+ "resolvedType": "string | undefined",
126
+ "attribute": "center-caption",
127
+ "required": false,
128
+ "mutable": false,
129
+ "description": "Secondary caption below the center value (e.g. \"Total\", \"Normal\"). Rendered uppercase."
130
+ },
131
+ "centerValue": {
132
+ "type": "string | undefined",
133
+ "resolvedType": "string | undefined",
134
+ "attribute": "center-value",
135
+ "required": false,
136
+ "mutable": false,
137
+ "description": "Primary center value; defaults to the sum of `data` values (e.g. \"187\", \"40.9%\")."
138
+ },
139
+ "cornerRadius": {
140
+ "type": "number | string",
141
+ "resolvedType": "number | string",
142
+ "attribute": "corner-radius",
143
+ "default": "TOKEN_DEFAULTS.radius025",
144
+ "required": false,
145
+ "mutable": false,
146
+ "description": "Corner radius on each slice — number (px) or TokoMo length. Defaults to `--dimension-radius-025` (2px)."
147
+ },
148
+ "data": {
149
+ "type": "ChartDatum[]",
150
+ "resolvedType": "ChartDatum[]",
151
+ "default": "[]",
152
+ "required": false,
153
+ "mutable": false,
154
+ "description": "Slices to render. Set as a JS property (not an HTML attribute)."
155
+ },
156
+ "gap": {
157
+ "type": "number",
158
+ "resolvedType": "number",
159
+ "attribute": "gap",
160
+ "default": "1",
161
+ "required": false,
162
+ "mutable": false,
163
+ "description": "Gap between slices, in degrees."
164
+ },
165
+ "locale": {
166
+ "type": "string | undefined",
167
+ "resolvedType": "string | undefined",
168
+ "attribute": "locale",
169
+ "required": false,
170
+ "mutable": false
171
+ },
172
+ "noDataLabel": {
173
+ "type": "string",
174
+ "resolvedType": "string",
175
+ "attribute": "no-data-label",
176
+ "default": "'No data'",
177
+ "required": false,
178
+ "mutable": false
179
+ },
180
+ "size": {
181
+ "type": "number | undefined",
182
+ "resolvedType": "number | undefined",
183
+ "attribute": "size",
184
+ "required": false,
185
+ "mutable": false,
186
+ "description": "Explicit diameter in px. When unset, the donut sizes to its container\n(ResizeObserver) clamped between `--dimension-size-base * 16` (128px) and\n`* 24` (192px), and stays centered in the leftover space. Prefer unset\ninside card layouts."
187
+ },
188
+ "thickness": {
189
+ "type": "number | string",
190
+ "resolvedType": "number | string",
191
+ "attribute": "thickness",
192
+ "default": "TOKEN_DEFAULTS.size200",
193
+ "required": false,
194
+ "mutable": false,
195
+ "description": "Ring thickness — number (px) or TokoMo length. Defaults to `--dimension-size-200` (16px)."
196
+ }
197
+ },
198
+ "events": [
199
+ {
200
+ "name": "dsSliceHover",
201
+ "detail": "ChartDatum | null",
202
+ "bubbles": true,
203
+ "cancelable": true,
204
+ "composed": true,
205
+ "description": "Fires with the hovered/focused slice's datum, or `null` on leave/blur."
206
+ }
207
+ ],
208
+ "methods": [],
209
+ "slots": [],
210
+ "exports": {
211
+ "customElement": "ds-chart-donut",
212
+ "react": "DsChartDonut",
213
+ "angular": "DsChartDonut"
214
+ },
215
+ "consumption": {
216
+ "install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
217
+ "cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
218
+ "customElements": {
219
+ "import": "import '@ds-mo/ui/dist/components/ds-chart-donut.js';",
220
+ "example": "<ds-chart-donut></ds-chart-donut>"
221
+ },
222
+ "react": {
223
+ "import": "import { DsChartDonut } from '@ds-mo/ui/react';",
224
+ "example": "<DsChartDonut />"
225
+ },
226
+ "angular": {
227
+ "import": "import { DsChartDonut } from '@ds-mo/ui/angular/ds-chart-donut';",
228
+ "example": "<ds-chart-donut></ds-chart-donut>"
229
+ },
230
+ "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: data.",
231
+ "peerDependencies": {
232
+ "required": [
233
+ "@ds-mo/tokens ^3.1.1",
234
+ "@ds-mo/icons ^6.2.0"
235
+ ],
236
+ "frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
237
+ }
238
+ }
239
+ },
240
+ "dependencies": [
241
+ "@ds-mo/ui",
242
+ "@ds-mo/tokens"
243
+ ],
244
+ "registryDependencies": [],
245
+ "files": [
246
+ {
247
+ "path": "src/wc/components/ChartDonut/ChartDonut.css",
248
+ "content": ":host {\n display: inline-block;\n font-family: var(--typography-font-family);\n user-select: none;\n}\n\n:host(.chart-donut--fill) {\n display: block;\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n}\n\n.chart-donut__wrapper {\n position: relative;\n}\n\n:host(.chart-donut--fill) .chart-donut__wrapper {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.chart-donut__svg path {\n cursor: default;\n transition: opacity var(--effect-motion-short-2);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .chart-donut__svg path {\n transition: none;\n }\n}\n\n.chart-donut__svg path:focus-visible {\n outline: none;\n stroke: var(--color-interaction-focus);\n stroke-width: 2;\n}\n\n/* Matches ds-text text-title-large + emphasis (SVG cannot host ds-text). */\n.chart-donut__center-value {\n fill: var(--color-foreground-primary);\n font-family: var(--typography-font-family);\n font-size: var(--typography-fontsize-xl);\n line-height: var(--typography-lineheight-xl);\n font-weight: var(--typography-weight-semibold);\n letter-spacing: var(--typography-letterspacing-negative-double);\n cursor: default;\n}\n\n/* Matches ds-text text-body-medium regular. */\n.chart-donut__center-caption {\n fill: var(--color-foreground-secondary);\n font-family: var(--typography-font-family);\n font-size: var(--typography-fontsize-md);\n line-height: var(--typography-lineheight-md);\n font-weight: var(--typography-weight-regular);\n letter-spacing: var(--typography-letterspacing-negative-half);\n cursor: default;\n}\n",
249
+ "type": "registry:ui"
250
+ },
251
+ {
252
+ "path": "src/wc/components/ChartDonut/ChartDonut.tsx",
253
+ "content": "import { Component, Prop, State, Event, EventEmitter, Element, Watch, h, Host } from '@stencil/core';\nimport { arc, pie } from 'd3-shape';\nimport { categoryColor } from '../../utils/chart-colors';\nimport { formatCompactNumber, resolveCssLengthPx, truncateSvgTextToWidth, TOKEN_DEFAULTS } from '../../utils';\nimport type { ChartDatum } from '../../utils/chart-types';\n\nconst DIMMED_OPACITY = 0.25;\n/** Gap between the center value and caption line boxes. */\nconst CENTER_GAP_PX = 0;\n/** Fraction of the inner-circle diameter center text is allowed to use before truncating. */\nconst CENTER_TEXT_SAFE_WIDTH_RATIO = 0.82;\n/** Fallback when filling before the first ResizeObserver measurement (matches fill min). */\nconst FILL_FALLBACK_PX = 128;\n\n@Component({\n tag: 'ds-chart-donut',\n styleUrl: 'ChartDonut.css',\n scoped: true,\n})\nexport class ChartDonut {\n @Prop() locale: string | undefined;\n @Prop() noDataLabel: string = 'No data';\n @Element() el!: HTMLElement;\n\n /** Slices to render. Set as a JS property (not an HTML attribute). */\n @Prop() data: ChartDatum[] = [];\n /**\n * Explicit diameter in px. When unset, the donut sizes to its container\n * (ResizeObserver) clamped between `--dimension-size-base * 16` (128px) and\n * `* 24` (192px), and stays centered in the leftover space. Prefer unset\n * inside card layouts.\n */\n @Prop() size: number | undefined;\n /** Ring thickness — number (px) or TokoMo length. Defaults to `--dimension-size-200` (16px). */\n @Prop() thickness: number | string = TOKEN_DEFAULTS.size200;\n /** Corner radius on each slice — number (px) or TokoMo length. Defaults to `--dimension-radius-025` (2px). */\n @Prop() cornerRadius: number | string = TOKEN_DEFAULTS.radius025;\n /** Gap between slices, in degrees. */\n @Prop() gap: number = 1;\n /** Primary center value; defaults to the sum of `data` values (e.g. \"187\", \"40.9%\"). */\n @Prop() centerValue: string | undefined;\n /** Secondary caption below the center value (e.g. \"Total\", \"Normal\"). Rendered uppercase. */\n @Prop() centerCaption: string | undefined;\n /**\n * Externally controlled highlight, matched by `label` — e.g. drive this from a sibling\n * `ds-chart-legend`'s `dsItemHover` event to keep chart and legend hover in sync.\n * Falls back to this component's own pointer/focus hover when unset.\n * Slice hover dims peer slices and emits `dsSliceHover` for legend sync — no data-viz\n * tooltip (the legend already surfaces label/value).\n */\n @Prop() activeLabel: string | null = null;\n\n @State() private hoveredLabel: string | null = null;\n /** Center text, truncated with an ellipsis if it doesn't fit inside the inner circle. */\n @State() private displayedValueText: string = '';\n @State() private displayedCaptionText: string = '';\n /** Measured fill diameter when `size` is unset. */\n @State() private measuredSize: number = FILL_FALLBACK_PX;\n\n /** Fires with the hovered/focused slice's datum, or `null` on leave/blur. */\n @Event() dsSliceHover!: EventEmitter<ChartDatum | null>;\n\n private valueTextEl?: SVGTextElement;\n private captionTextEl?: SVGTextElement;\n private resizeObserver: ResizeObserver | null = null;\n\n private get isFillMode(): boolean {\n return this.size == null || !Number.isFinite(this.size) || this.size <= 0;\n }\n\n private get fillMinPx(): number {\n return resolveCssLengthPx(TOKEN_DEFAULTS.donutFillMin, FILL_FALLBACK_PX);\n }\n\n private get fillMaxPx(): number {\n return resolveCssLengthPx(TOKEN_DEFAULTS.donutFillMax, 192);\n }\n\n /** Clamp available square side into the fill min/max band. */\n private clampFillSize(availablePx: number): number {\n const minPx = this.fillMinPx;\n const maxPx = this.fillMaxPx;\n if (!(availablePx > 0)) return minPx;\n return Math.round(Math.min(maxPx, Math.max(minPx, availablePx)));\n }\n\n private get resolvedSize(): number {\n if (!this.isFillMode) return this.size as number;\n return this.clampFillSize(this.measuredSize);\n }\n\n componentDidLoad() {\n this.syncResizeObserver();\n }\n\n @Watch('size')\n onSizePropChange() {\n this.syncResizeObserver();\n }\n\n disconnectedCallback() {\n this.teardownResizeObserver();\n }\n\n private syncResizeObserver() {\n this.teardownResizeObserver();\n if (!this.isFillMode) return;\n // Observe the host (which fills its parent), not the wrapper — the wrapper\n // only wraps the SVG and would collapse to the clamped size, locking fill at min.\n const target = this.el;\n if (!target || typeof ResizeObserver === 'undefined') return;\n\n this.resizeObserver = new ResizeObserver(entries => {\n const entry = entries[0];\n if (!entry) return;\n this.applyAvailableSize(entry.contentRect.width, entry.contentRect.height);\n });\n this.resizeObserver.observe(target);\n this.measureHost();\n }\n\n private measureHost() {\n const rect = this.el.getBoundingClientRect();\n this.applyAvailableSize(rect.width, rect.height);\n }\n\n private applyAvailableSize(width: number, height: number) {\n const available = Math.floor(Math.min(width, height));\n if (available > 0 && available !== this.measuredSize) {\n this.measuredSize = available;\n }\n }\n\n private teardownResizeObserver() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n }\n\n private handleHover(datum: ChartDatum | null) {\n this.hoveredLabel = datum?.label ?? null;\n this.dsSliceHover.emit(datum);\n }\n\n componentDidRender() {\n // Re-bind after HMR when DidLoad's observer was dropped.\n if (this.isFillMode && !this.resizeObserver) {\n this.syncResizeObserver();\n }\n\n const size = this.resolvedSize;\n const radius = size / 2;\n const thicknessPx = resolveCssLengthPx(this.thickness, TOKEN_DEFAULTS.size200);\n const innerRadius = radius - thicknessPx;\n const maxWidth = innerRadius * 2 * CENTER_TEXT_SAFE_WIDTH_RATIO;\n const total = this.data.reduce((sum, d) => sum + d.value, 0);\n\n const fullValueText = this.centerValue ?? formatCompactNumber(total, this.locale);\n if (this.valueTextEl) {\n const truncated = truncateSvgTextToWidth(this.valueTextEl, fullValueText, maxWidth);\n if (truncated !== this.displayedValueText) this.displayedValueText = truncated;\n else this.valueTextEl.textContent = truncated;\n }\n\n const fullCaptionText = this.centerCaption ?? '';\n if (this.captionTextEl && fullCaptionText) {\n const truncated = truncateSvgTextToWidth(this.captionTextEl, fullCaptionText, maxWidth);\n if (truncated !== this.displayedCaptionText) this.displayedCaptionText = truncated;\n else this.captionTextEl.textContent = truncated;\n }\n }\n\n render() {\n const size = this.resolvedSize;\n const radius = size / 2;\n const thicknessPx = resolveCssLengthPx(this.thickness, TOKEN_DEFAULTS.size200);\n const cornerRadiusPx = resolveCssLengthPx(this.cornerRadius, TOKEN_DEFAULTS.radius025);\n const innerRadius = radius - thicknessPx;\n const total = this.data.reduce((sum, d) => sum + d.value, 0);\n // d3's pie() divides each value by the total to get an angle — with an all-zero total\n // that's 0/0, producing NaN angles and broken paths. Render a flat neutral ring instead.\n const isEmpty = total <= 0;\n // Highlight/dim from either this component's own hover or an externally-synced label\n // (e.g. a sibling ds-chart-legend row).\n const highlightLabel = this.activeLabel ?? this.hoveredLabel;\n\n const arcGenerator = arc<{ startAngle: number; endAngle: number }>()\n .innerRadius(innerRadius)\n .outerRadius(radius)\n .cornerRadius(cornerRadiusPx)\n .padAngle((this.gap * Math.PI) / 180);\n\n const slices = isEmpty\n ? []\n : pie<ChartDatum>()\n .value(d => d.value)\n .sort(null)(this.data);\n\n const emptyRingPath = isEmpty\n ? arc<{ startAngle: number; endAngle: number }>()\n .innerRadius(innerRadius)\n .outerRadius(radius)({ startAngle: 0, endAngle: Math.PI * 2 })\n : null;\n\n // Precise vertical centering for the two-line center text, using the real line-height of\n // text-title-large (value) and text-body-medium (caption) rather than eyeballed em offsets.\n const valueLineHeight = resolveCssLengthPx(TOKEN_DEFAULTS.lineheightXl, 32);\n const captionLineHeight = resolveCssLengthPx(TOKEN_DEFAULTS.lineheightMd, 20);\n const centerValueY = this.centerCaption ? radius - (CENTER_GAP_PX + captionLineHeight) / 2 : radius;\n const centerCaptionY = radius + (valueLineHeight + CENTER_GAP_PX) / 2;\n\n // Show the full text before the post-render truncation pass has measured it (avoids a blank first paint).\n const fullValueText = this.centerValue ?? formatCompactNumber(total, this.locale);\n const fullCaptionText = this.centerCaption ?? '';\n const fill = this.isFillMode;\n\n return (\n <Host\n class={{\n 'chart-donut': true,\n 'chart-donut--fill': fill,\n 'chart-donut--fixed': !fill,\n }}\n style={!fill ? { width: `${size}px`, height: `${size}px` } : undefined}\n >\n <div\n class=\"chart-donut__wrapper\"\n style={!fill ? { width: `${size}px`, height: `${size}px` } : undefined}\n >\n <svg\n class=\"chart-donut__svg\"\n viewBox={`0 0 ${size} ${size}`}\n width={size}\n height={size}\n role={isEmpty ? 'img' : undefined}\n aria-label={isEmpty ? this.noDataLabel : undefined}\n >\n <g transform={`translate(${radius}, ${radius})`}>\n {isEmpty ? (\n <path d={emptyRingPath ?? undefined} fill=\"var(--color-background-faint-neutral)\" aria-hidden=\"true\" />\n ) : (\n slices.map((slice, i) => {\n const datum = this.data[i];\n const isDimmed = highlightLabel != null && datum.label !== highlightLabel;\n return (\n <path\n key={datum.label}\n d={arcGenerator(slice) ?? undefined}\n fill={datum.color ?? categoryColor(i)}\n opacity={isDimmed ? DIMMED_OPACITY : 1}\n tabindex={0}\n role=\"img\"\n aria-label={`${datum.label}: ${datum.value}`}\n onMouseEnter={() => this.handleHover(datum)}\n onMouseLeave={() => this.handleHover(null)}\n onFocus={() => this.handleHover(datum)}\n onBlur={() => this.handleHover(null)}\n />\n );\n })\n )}\n </g>\n <text\n class=\"chart-donut__center-value\"\n x={radius}\n y={centerValueY}\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n ref={el => {\n this.valueTextEl = (el as SVGTextElement) ?? undefined;\n }}\n >\n {this.displayedValueText || fullValueText}\n </text>\n {fullCaptionText && (\n <text\n class=\"chart-donut__center-caption\"\n x={radius}\n y={centerCaptionY}\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n ref={el => {\n this.captionTextEl = (el as SVGTextElement) ?? undefined;\n }}\n >\n {this.displayedCaptionText || fullCaptionText}\n </text>\n )}\n </svg>\n </div>\n </Host>\n );\n }\n}\n",
254
+ "type": "registry:ui"
255
+ }
256
+ ]
257
+ }
@@ -0,0 +1,209 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "chart-legend",
4
+ "title": "ChartLegend",
5
+ "description": "Base legend for `ds-chart-*` components. Webapp's Overview widgets each style\nlegends differently (list w/ values, compact chips, bare swatches, external\nstat callouts) — this covers the common \"swatch + label + optional value\" case.\nConsumers who need a different treatment skip this component entirely and\nrender their own markup against the same `ChartDatum[]` data.",
6
+ "type": "registry:ui",
7
+ "meta": {
8
+ "library": "@ds-mo/ui",
9
+ "distribution": "npm",
10
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/chart-legend",
11
+ "source": "src/wc/components/ChartLegend/ChartLegend.tsx",
12
+ "intentStatus": "migration-pending",
13
+ "intent": null,
14
+ "api": {
15
+ "props": {
16
+ "activeLabel": {
17
+ "type": "string | null",
18
+ "resolvedType": "null | string",
19
+ "attribute": "active-label",
20
+ "default": "null",
21
+ "required": false,
22
+ "mutable": false,
23
+ "description": "Externally controlled highlight, matched by `label` — e.g. drive this from a sibling\nchart's `dsSliceHover` event to keep chart and legend hover in sync. Only dims the other\nrows' opacity (like a chart dimming its other slices) — it never shows the hover-fill,\nsince that's reserved for a real pointer/keyboard interaction on this row."
24
+ },
25
+ "direction": {
26
+ "type": "ChartLegendDirection",
27
+ "resolvedType": "\"horizontal\" | \"vertical\"",
28
+ "attribute": "direction",
29
+ "default": "'vertical'",
30
+ "required": false,
31
+ "mutable": false
32
+ },
33
+ "items": {
34
+ "type": "ChartLegendItem[]",
35
+ "resolvedType": "ChartLegendItem[]",
36
+ "default": "[]",
37
+ "required": false,
38
+ "mutable": false,
39
+ "description": "Legend entries. Set as a JS property (not an HTML attribute)."
40
+ },
41
+ "locale": {
42
+ "type": "string | undefined",
43
+ "resolvedType": "string | undefined",
44
+ "attribute": "locale",
45
+ "required": false,
46
+ "mutable": false
47
+ },
48
+ "percentageDecimals": {
49
+ "type": "ChartLegendPercentageDecimals",
50
+ "resolvedType": "1 | 2",
51
+ "attribute": "percentage-decimals",
52
+ "default": "1",
53
+ "required": false,
54
+ "mutable": false,
55
+ "description": "Fixed number of decimal places shown for percentages."
56
+ },
57
+ "showPercentage": {
58
+ "type": "boolean",
59
+ "resolvedType": "boolean",
60
+ "attribute": "show-percentage",
61
+ "default": "true",
62
+ "required": false,
63
+ "mutable": false,
64
+ "description": "Show each item's share of the total (of items with a `value`) alongside its count."
65
+ }
66
+ },
67
+ "events": [
68
+ {
69
+ "name": "dsItemClick",
70
+ "detail": "{ item: ChartLegendItem; originalEvent: MouseEvent }",
71
+ "bubbles": true,
72
+ "cancelable": true,
73
+ "composed": true,
74
+ "description": "Fires when a deep-linkable row (`item.href` set) is activated."
75
+ },
76
+ {
77
+ "name": "dsItemHover",
78
+ "detail": "ChartLegendItem | null",
79
+ "bubbles": true,
80
+ "cancelable": true,
81
+ "composed": true,
82
+ "description": "Fires on row hover/focus with the item, or `null` on leave/blur."
83
+ }
84
+ ],
85
+ "methods": [],
86
+ "slots": []
87
+ },
88
+ "props": {
89
+ "activeLabel": {
90
+ "type": "string | null",
91
+ "resolvedType": "null | string",
92
+ "attribute": "active-label",
93
+ "default": "null",
94
+ "required": false,
95
+ "mutable": false,
96
+ "description": "Externally controlled highlight, matched by `label` — e.g. drive this from a sibling\nchart's `dsSliceHover` event to keep chart and legend hover in sync. Only dims the other\nrows' opacity (like a chart dimming its other slices) — it never shows the hover-fill,\nsince that's reserved for a real pointer/keyboard interaction on this row."
97
+ },
98
+ "direction": {
99
+ "type": "ChartLegendDirection",
100
+ "resolvedType": "\"horizontal\" | \"vertical\"",
101
+ "attribute": "direction",
102
+ "default": "'vertical'",
103
+ "required": false,
104
+ "mutable": false
105
+ },
106
+ "items": {
107
+ "type": "ChartLegendItem[]",
108
+ "resolvedType": "ChartLegendItem[]",
109
+ "default": "[]",
110
+ "required": false,
111
+ "mutable": false,
112
+ "description": "Legend entries. Set as a JS property (not an HTML attribute)."
113
+ },
114
+ "locale": {
115
+ "type": "string | undefined",
116
+ "resolvedType": "string | undefined",
117
+ "attribute": "locale",
118
+ "required": false,
119
+ "mutable": false
120
+ },
121
+ "percentageDecimals": {
122
+ "type": "ChartLegendPercentageDecimals",
123
+ "resolvedType": "1 | 2",
124
+ "attribute": "percentage-decimals",
125
+ "default": "1",
126
+ "required": false,
127
+ "mutable": false,
128
+ "description": "Fixed number of decimal places shown for percentages."
129
+ },
130
+ "showPercentage": {
131
+ "type": "boolean",
132
+ "resolvedType": "boolean",
133
+ "attribute": "show-percentage",
134
+ "default": "true",
135
+ "required": false,
136
+ "mutable": false,
137
+ "description": "Show each item's share of the total (of items with a `value`) alongside its count."
138
+ }
139
+ },
140
+ "events": [
141
+ {
142
+ "name": "dsItemClick",
143
+ "detail": "{ item: ChartLegendItem; originalEvent: MouseEvent }",
144
+ "bubbles": true,
145
+ "cancelable": true,
146
+ "composed": true,
147
+ "description": "Fires when a deep-linkable row (`item.href` set) is activated."
148
+ },
149
+ {
150
+ "name": "dsItemHover",
151
+ "detail": "ChartLegendItem | null",
152
+ "bubbles": true,
153
+ "cancelable": true,
154
+ "composed": true,
155
+ "description": "Fires on row hover/focus with the item, or `null` on leave/blur."
156
+ }
157
+ ],
158
+ "methods": [],
159
+ "slots": [],
160
+ "exports": {
161
+ "customElement": "ds-chart-legend",
162
+ "react": "DsChartLegend",
163
+ "angular": "DsChartLegend"
164
+ },
165
+ "consumption": {
166
+ "install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
167
+ "cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
168
+ "customElements": {
169
+ "import": "import '@ds-mo/ui/dist/components/ds-chart-legend.js';",
170
+ "example": "<ds-chart-legend></ds-chart-legend>"
171
+ },
172
+ "react": {
173
+ "import": "import { DsChartLegend } from '@ds-mo/ui/react';",
174
+ "example": "<DsChartLegend />"
175
+ },
176
+ "angular": {
177
+ "import": "import { DsChartLegend } from '@ds-mo/ui/angular/ds-chart-legend';",
178
+ "example": "<ds-chart-legend></ds-chart-legend>"
179
+ },
180
+ "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: items.",
181
+ "peerDependencies": {
182
+ "required": [
183
+ "@ds-mo/tokens ^3.1.1",
184
+ "@ds-mo/icons ^6.2.0"
185
+ ],
186
+ "frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
187
+ }
188
+ }
189
+ },
190
+ "dependencies": [
191
+ "@ds-mo/ui",
192
+ "@ds-mo/tokens"
193
+ ],
194
+ "registryDependencies": [
195
+ "text"
196
+ ],
197
+ "files": [
198
+ {
199
+ "path": "src/wc/components/ChartLegend/ChartLegend.css",
200
+ "content": "@import '../../utils/control-density.css';\n@import '../../utils/interaction-fill.css';\n@import '../../utils/focus-ring.css';\n\n:host {\n display: block;\n font-family: var(--typography-font-family);\n user-select: none;\n}\n\n.chart-legend__list {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n/* Non-visual wrapper — the real box is .chart-legend__item so it can be hovered/clicked\n as a whole row while its children still align to the list's shared grid columns. */\n.chart-legend__list-item {\n display: contents;\n}\n\n:host(.chart-legend--vertical) .chart-legend__list {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) var(--dimension-size-600);\n column-gap: var(--dimension-space-075);\n row-gap: var(--dimension-space-050);\n}\n\n:host(.chart-legend--vertical.chart-legend--show-percentage) .chart-legend__list {\n grid-template-columns: auto minmax(0, 1fr) var(--dimension-size-600) var(--dimension-size-800);\n}\n\n:host(.chart-legend--vertical) .chart-legend__item {\n grid-column: 1 / -1;\n display: grid;\n grid-template-columns: subgrid;\n}\n\n:host(.chart-legend--horizontal) .chart-legend__list {\n display: flex;\n flex-wrap: wrap;\n gap: var(--dimension-space-200);\n}\n\n:host(.chart-legend--horizontal) .chart-legend__item {\n display: flex;\n gap: var(--dimension-space-100);\n}\n\n/*\n * Density: md control recipe (height / pad / radius / label inset).\n * Hover/press: `.ds-interaction-fill` (token overlay on ::after).\n */\n.chart-legend__item {\n box-sizing: border-box;\n height: var(--ds-control-height, var(--dimension-size-400));\n align-items: center;\n padding: 0 var(--ds-control-padding-inline, var(--dimension-space-075));\n border-radius: var(--ds-control-radius, var(--dimension-radius-025));\n text-decoration: none;\n color: inherit;\n transition: opacity var(--effect-motion-short-2);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .chart-legend__item {\n transition: none;\n }\n}\n\n.chart-legend__item--interactive {\n cursor: pointer;\n}\n\n/* Raise row content above interaction fills (positive z-index on util layers). */\n.chart-legend__item > * {\n position: relative;\n z-index: 2;\n}\n\n.chart-legend__swatch-box {\n width: var(--dimension-size-250);\n height: var(--dimension-size-250);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.chart-legend__swatch {\n width: var(--dimension-space-150);\n height: var(--dimension-space-150);\n border-radius: var(--dimension-radius-025);\n flex-shrink: 0;\n}\n\n.chart-legend__label {\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n.chart-legend__percentage {\n width: 100%;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n text-align: right;\n}\n\n.chart-legend__value {\n width: 100%;\n text-align: right;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n",
201
+ "type": "registry:ui"
202
+ },
203
+ {
204
+ "path": "src/wc/components/ChartLegend/ChartLegend.tsx",
205
+ "content": "import { Component, Prop, State, Event, EventEmitter, h, Host } 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.25;\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 /**\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 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.hoveredLabel;\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 class=\"chart-legend__list\" onMouseLeave={() => this.handleHover(null)}>\n {this.items.map((item, i) => {\n const isDimmed = highlightLabel != null && item.label !== highlightLabel;\n const RowTag = item.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': !!item.href,\n 'ds-control--md': true,\n 'ds-interaction-fill': true,\n 'ds-focus-ring-inset': !!item.href,\n }}\n style={{ opacity: isDimmed ? String(DIMMED_OPACITY) : '1' }}\n href={item.href}\n onClick={item.href ? (e: MouseEvent) => this.handleClick(item, e) : undefined}\n onMouseEnter={() => this.handleHover(item)}\n onFocus={() => this.handleHover(item)}\n onBlur={() => this.handleHover(null)}\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",
206
+ "type": "registry:ui"
207
+ }
208
+ ]
209
+ }