@ds-mo/ui 15.1.1 → 15.3.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 (414) hide show
  1. package/dist/.package-ready.json +1 -1
  2. package/dist/agent-patterns.json +4 -4
  3. package/dist/agent.json +711 -48
  4. package/dist/angular/ds-card-setting.d.ts +1 -1
  5. package/dist/angular/ds-card-setting.js +3 -3
  6. package/dist/angular/ds-input-time.d.ts +1 -1
  7. package/dist/angular/ds-input-time.js +3 -3
  8. package/dist/angular/ds-input.d.ts +5 -1
  9. package/dist/angular/ds-input.js +10 -4
  10. package/dist/angular/ds-map-cluster-marker.d.ts +18 -0
  11. package/dist/angular/ds-map-cluster-marker.js +43 -0
  12. package/dist/angular/ds-map-entity-marker.d.ts +18 -0
  13. package/dist/angular/ds-map-entity-marker.js +43 -0
  14. package/dist/angular/ds-radio-tile.d.ts +15 -0
  15. package/dist/angular/ds-radio-tile.js +43 -0
  16. package/dist/angular/ds-setting-row.d.ts +18 -0
  17. package/dist/angular/ds-setting-row.js +42 -0
  18. package/dist/angular/ds-slider.d.ts +1 -1
  19. package/dist/angular/ds-slider.js +3 -3
  20. package/dist/angular/ds-textarea.d.ts +1 -1
  21. package/dist/angular/ds-textarea.js +3 -3
  22. package/dist/angular/ds-time-picker.d.ts +1 -1
  23. package/dist/angular/ds-time-picker.js +3 -3
  24. package/dist/angular/index.d.ts +1 -1
  25. package/dist/angular/index.js +4 -0
  26. package/dist/angular/number-value-accessor.d.ts +9 -0
  27. package/dist/angular/number-value-accessor.js +39 -0
  28. package/dist/angular/proxies.d.ts +4 -0
  29. package/dist/angular/proxies.js +4 -0
  30. package/dist/angular/radio-value-accessor.d.ts +1 -1
  31. package/dist/angular/radio-value-accessor.js +2 -2
  32. package/dist/angular/select-value-accessor.d.ts +1 -1
  33. package/dist/angular/select-value-accessor.js +2 -2
  34. package/dist/angular/text-value-accessor.d.ts +1 -1
  35. package/dist/angular/text-value-accessor.js +2 -2
  36. package/dist/components/ds-agent-activity.js +1 -1
  37. package/dist/components/ds-agent-questionnaire.js +1 -1
  38. package/dist/components/ds-agent-response.js +1 -1
  39. package/dist/components/ds-agent-source-list.js +1 -1
  40. package/dist/components/ds-agent-tool-call.js +1 -1
  41. package/dist/components/ds-attachment-list.js +1 -1
  42. package/dist/components/ds-badge.js +1 -1
  43. package/dist/components/ds-banner.js +1 -1
  44. package/dist/components/ds-bar-action.js +1 -1
  45. package/dist/components/ds-bar-nav.js +1 -1
  46. package/dist/components/ds-bar-page-title.js +1 -1
  47. package/dist/components/ds-bar-title.js +1 -1
  48. package/dist/components/ds-bar-workflow.js +1 -1
  49. package/dist/components/ds-breadcrumb.js +1 -1
  50. package/dist/components/ds-button-filled.js +1 -1
  51. package/dist/components/ds-button-inverted.js +1 -1
  52. package/dist/components/ds-button-unfilled.js +1 -1
  53. package/dist/components/ds-calendar.js +1 -1
  54. package/dist/components/ds-card-action-center.js +1 -1
  55. package/dist/components/ds-card-chart.js +1 -1
  56. package/dist/components/ds-card-navigation.js +1 -1
  57. package/dist/components/ds-card-overview.js +1 -1
  58. package/dist/components/ds-card-setting.js +1 -1
  59. package/dist/components/ds-card-setting.js.map +1 -1
  60. package/dist/components/ds-card-settings-scope.js +1 -1
  61. package/dist/components/ds-chart-legend.js +1 -1
  62. package/dist/components/ds-chart.js +1 -1
  63. package/dist/components/ds-checkbox.js +1 -1
  64. package/dist/components/ds-chip.js +1 -1
  65. package/dist/components/ds-code-block.js +1 -1
  66. package/dist/components/ds-conversation-list-item.js +1 -1
  67. package/dist/components/ds-conversation-list-section.js +1 -1
  68. package/dist/components/ds-conversation-list.js +1 -1
  69. package/dist/components/ds-data-customize.js +1 -1
  70. package/dist/components/ds-data-customize.js.map +1 -1
  71. package/dist/components/ds-data-filter.js +1 -1
  72. package/dist/components/ds-data-filter.js.map +1 -1
  73. package/dist/components/ds-data-group.js +1 -1
  74. package/dist/components/ds-data-preferences.js +1 -1
  75. package/dist/components/ds-data-preferences.js.map +1 -1
  76. package/dist/components/ds-data-saved-views.js +1 -1
  77. package/dist/components/ds-data-saved-views.js.map +1 -1
  78. package/dist/components/ds-data-search.js +1 -1
  79. package/dist/components/ds-data-search.js.map +1 -1
  80. package/dist/components/ds-data-sort.js +1 -1
  81. package/dist/components/ds-data-toolbar.js +1 -1
  82. package/dist/components/ds-empty-state.js +1 -1
  83. package/dist/components/ds-field.js +1 -1
  84. package/dist/components/ds-filter-menu.js +1 -1
  85. package/dist/components/ds-input-date.js +1 -1
  86. package/dist/components/ds-input-date.js.map +1 -1
  87. package/dist/components/ds-input-time.js +1 -1
  88. package/dist/components/ds-input-time.js.map +1 -1
  89. package/dist/components/ds-input.js +1 -1
  90. package/dist/components/ds-map-cluster-marker.d.ts +11 -0
  91. package/dist/components/ds-map-cluster-marker.js +2 -0
  92. package/dist/components/ds-map-cluster-marker.js.map +1 -0
  93. package/dist/components/ds-map-entity-marker.d.ts +11 -0
  94. package/dist/components/ds-map-entity-marker.js +2 -0
  95. package/dist/components/ds-map-entity-marker.js.map +1 -0
  96. package/dist/components/ds-markdown.js +1 -1
  97. package/dist/components/ds-menu.js +1 -1
  98. package/dist/components/ds-message-actions.js +1 -1
  99. package/dist/components/ds-message-bubble.js +1 -1
  100. package/dist/components/ds-message-bubble.js.map +1 -1
  101. package/dist/components/ds-message-composer.js +1 -1
  102. package/dist/components/ds-message-scroller.js +1 -1
  103. package/dist/components/ds-message.js +1 -1
  104. package/dist/components/ds-mobile-bar-nav.js +1 -1
  105. package/dist/components/ds-mobile-header.js +1 -1
  106. package/dist/components/ds-mobile-section-switcher.js +1 -1
  107. package/dist/components/ds-mobile-sheet-nav.js +1 -1
  108. package/dist/components/ds-modal.js +1 -1
  109. package/dist/components/ds-pagination.js +1 -1
  110. package/dist/components/ds-panel-nav.js +1 -1
  111. package/dist/components/ds-panel-sub-nav.js +1 -1
  112. package/dist/components/ds-panel-tool-header.js +1 -1
  113. package/dist/components/ds-panel-tool-search.js +1 -1
  114. package/dist/components/ds-panel-tool-search.js.map +1 -1
  115. package/dist/components/ds-panel-tools.js +1 -1
  116. package/dist/components/ds-paper-texture.js +1 -1
  117. package/dist/components/ds-radio-tile.d.ts +11 -0
  118. package/dist/components/ds-radio-tile.js +2 -0
  119. package/dist/components/ds-radio-tile.js.map +1 -0
  120. package/dist/components/ds-radio.js +1 -1
  121. package/dist/components/ds-score.js +1 -1
  122. package/dist/components/ds-scroll-overlay.js +1 -1
  123. package/dist/components/ds-select.js +1 -1
  124. package/dist/components/ds-setting-row.d.ts +11 -0
  125. package/dist/components/ds-setting-row.js +2 -0
  126. package/dist/components/ds-setting-row.js.map +1 -0
  127. package/dist/components/ds-shell-app.js +1 -1
  128. package/dist/components/ds-shell-page.js +1 -1
  129. package/dist/components/ds-shell-tools.js +1 -1
  130. package/dist/components/ds-skeleton.js +1 -1
  131. package/dist/components/ds-slider.js +1 -1
  132. package/dist/components/ds-slider.js.map +1 -1
  133. package/dist/components/ds-swatch-picker.js +1 -1
  134. package/dist/components/ds-switch.js +1 -1
  135. package/dist/components/ds-tab-group.js +1 -1
  136. package/dist/components/ds-table.js +1 -1
  137. package/dist/components/ds-table.js.map +1 -1
  138. package/dist/components/ds-tag.js +1 -1
  139. package/dist/components/ds-text.js +1 -1
  140. package/dist/components/ds-textarea.js +1 -1
  141. package/dist/components/ds-textarea.js.map +1 -1
  142. package/dist/components/ds-time-picker.js +1 -1
  143. package/dist/components/ds-toast.js +1 -1
  144. package/dist/components/ds-tooltip-chart.js +1 -1
  145. package/dist/components/ds-tooltip.js +1 -1
  146. package/dist/components/ds-typing-indicator.js +1 -1
  147. package/dist/components/{p-etifxiDc.js → p-3bsypMrY.js} +2 -2
  148. package/dist/components/{p-Bm7rqs3C.js → p-AM_ht6Im.js} +2 -2
  149. package/dist/components/{p-Bm7rqs3C.js.map → p-AM_ht6Im.js.map} +1 -1
  150. package/dist/components/{p-Bn8I7iw6.js → p-AmT4GlhM.js} +2 -2
  151. package/dist/components/{p-FIBCluwV.js → p-B-HOVYoH.js} +2 -2
  152. package/dist/components/{p-CmexIVnE.js → p-B7QEpaMe.js} +2 -2
  153. package/dist/components/{p-CUcUHwI3.js → p-B7bXN-vf.js} +2 -2
  154. package/dist/components/p-BHI4LcGK.js +2 -0
  155. package/dist/components/p-BHI4LcGK.js.map +1 -0
  156. package/dist/components/{p-BhJXmuRA.js → p-BSuMDPaV.js} +2 -2
  157. package/dist/components/{p-0FYD2bev.js → p-BU1B6NW8.js} +2 -2
  158. package/dist/components/{p-Do2FJd1y.js → p-BVwg5XVz.js} +2 -2
  159. package/dist/components/{p-CYzFfFcH.js → p-BXSHN1OK.js} +2 -2
  160. package/dist/components/{p-ljbw3UMZ.js → p-BYJtvRQm.js} +2 -2
  161. package/dist/components/{p-CzIpquvw.js → p-Bh1Fx0aW.js} +2 -2
  162. package/dist/components/{p-CiJ1WR11.js → p-Bm3KWMe4.js} +2 -2
  163. package/dist/components/{p-DVINzOoK.js → p-Bo7GxFBh.js} +2 -2
  164. package/dist/components/{p-8yBdCXCn.js → p-BsM37Prt.js} +2 -2
  165. package/dist/components/p-Bu4OmhKK.js +2 -0
  166. package/dist/components/{p-CdGXzRP8.js.map → p-Bu4OmhKK.js.map} +1 -1
  167. package/dist/components/{p-DpoTwJAR.js → p-BugKaVWc.js} +2 -2
  168. package/dist/components/p-C-c8SJ00.js +2 -0
  169. package/dist/components/p-C-c8SJ00.js.map +1 -0
  170. package/dist/components/{p-Bpd6YCo4.js → p-C3-dcROG.js} +2 -2
  171. package/dist/components/p-C4VeD49U.js +2 -0
  172. package/dist/components/{p-BKZdqJQB.js.map → p-C4VeD49U.js.map} +1 -1
  173. package/dist/components/{p-CNxvnQ6A.js → p-CCpJT31M.js} +2 -2
  174. package/dist/components/p-CCpJT31M.js.map +1 -0
  175. package/dist/components/{p-Dzndkdx5.js → p-CI7c9kp-.js} +2 -2
  176. package/dist/components/{p-CdgOLWX9.js → p-CJD0kLeV.js} +2 -2
  177. package/dist/components/{p-BeNa6tw5.js → p-C_gJD8l3.js} +2 -2
  178. package/dist/components/{p-DwbcNDJF.js → p-Cihjy4WY.js} +2 -2
  179. package/dist/components/{p-BgQMEHRa.js → p-Co5MiPNa.js} +2 -2
  180. package/dist/components/{p-CD4DZPy_.js → p-CrL9wxZg.js} +2 -2
  181. package/dist/components/{p-CGidq1iC.js → p-CuwopElg.js} +2 -2
  182. package/dist/components/p-CwUXroLs.js +2 -0
  183. package/dist/components/{p-etg-Uk1u.js.map → p-CwUXroLs.js.map} +1 -1
  184. package/dist/components/{p-Cqc2U1ZQ.js → p-CzQ_JF6A.js} +2 -2
  185. package/dist/components/{p-BciTtTwx.js → p-CztB8Pbq.js} +2 -2
  186. package/dist/components/{p-BciTtTwx.js.map → p-CztB8Pbq.js.map} +1 -1
  187. package/dist/components/{p-ZhP2tVmM.js → p-D0KD-Nr_.js} +2 -2
  188. package/dist/components/{p-DOAybCp0.js → p-DCLRAH5i.js} +2 -2
  189. package/dist/components/{p-Dn9QHL4O.js → p-DFkw6wrS.js} +2 -2
  190. package/dist/components/{p-D1vQGJzc.js → p-DHapI2sf.js} +2 -2
  191. package/dist/components/p-DQPzqcYR.js +2 -0
  192. package/dist/components/p-DQPzqcYR.js.map +1 -0
  193. package/dist/components/{p-DHICPS4n.js → p-DWmYCOKz.js} +2 -2
  194. package/dist/components/p-DX2RyZba.js +2 -0
  195. package/dist/components/{p-C-3YqeTb.js.map → p-DX2RyZba.js.map} +1 -1
  196. package/dist/components/{p-vfCu7XSc.js → p-DZ58Sg5a.js} +2 -2
  197. package/dist/components/{p-D0y7Sja6.js → p-Dcn1eDVt.js} +2 -2
  198. package/dist/components/{p-E5W27Fu_.js → p-DcrdyDRw.js} +2 -2
  199. package/dist/components/p-DhKvqh5G.js +2 -0
  200. package/dist/components/p-DhKvqh5G.js.map +1 -0
  201. package/dist/components/p-Fkkd3gMB.js +2 -0
  202. package/dist/components/{p-DEW7r0U9.js.map → p-Fkkd3gMB.js.map} +1 -1
  203. package/dist/components/{p-xdmJCPCg.js → p-Gb-vTuXr.js} +2 -2
  204. package/dist/components/p-TVkFIMXz.js +2 -0
  205. package/dist/components/p-TVkFIMXz.js.map +1 -0
  206. package/dist/components/p-cuZva5tl.js +2 -0
  207. package/dist/components/{p-Dw9sE6Iw.js.map → p-cuZva5tl.js.map} +1 -1
  208. package/dist/components/p-fYZK3zqM.js +2 -0
  209. package/dist/components/{p-C6xVxqOn.js.map → p-fYZK3zqM.js.map} +1 -1
  210. package/dist/components/{p-CiH4GG6r.js → p-iGNHXFZA.js} +2 -2
  211. package/dist/components/{p-5URekSny.js → p-lADW-TI8.js} +2 -2
  212. package/dist/components/{p-D922f6Tb.js → p-p_MwknM3.js} +2 -2
  213. package/dist/components/{p-Dfs98tpL.js → p-tJaC01aE.js} +2 -2
  214. package/dist/components/{p-B_jdoM7e.js → p-z8L-YMi3.js} +2 -2
  215. package/dist/docs/components.json +1909 -44
  216. package/dist/framework/angular.d.ts +1 -0
  217. package/dist/framework/angular.js +1 -0
  218. package/dist/lint/index.js +1 -1
  219. package/dist/mcp-data/registry/agent-activity.json +2 -2
  220. package/dist/mcp-data/registry/agent-questionnaire.json +2 -2
  221. package/dist/mcp-data/registry/agent-response.json +2 -2
  222. package/dist/mcp-data/registry/agent-source-list.json +2 -2
  223. package/dist/mcp-data/registry/agent-tool-call.json +2 -2
  224. package/dist/mcp-data/registry/attachment-list.json +2 -2
  225. package/dist/mcp-data/registry/avatar.json +2 -2
  226. package/dist/mcp-data/registry/badge.json +2 -2
  227. package/dist/mcp-data/registry/banner.json +2 -2
  228. package/dist/mcp-data/registry/bar-action.json +2 -2
  229. package/dist/mcp-data/registry/bar-nav.json +2 -2
  230. package/dist/mcp-data/registry/bar-page-title.json +2 -2
  231. package/dist/mcp-data/registry/bar-title.json +4 -4
  232. package/dist/mcp-data/registry/bar-workflow.json +2 -2
  233. package/dist/mcp-data/registry/breadcrumb.json +2 -2
  234. package/dist/mcp-data/registry/button-filled.json +2 -2
  235. package/dist/mcp-data/registry/button-inverted.json +2 -2
  236. package/dist/mcp-data/registry/button-unfilled.json +2 -2
  237. package/dist/mcp-data/registry/calendar.json +2 -2
  238. package/dist/mcp-data/registry/card-action-center.json +2 -2
  239. package/dist/mcp-data/registry/card-chart.json +2 -2
  240. package/dist/mcp-data/registry/card-navigation.json +2 -2
  241. package/dist/mcp-data/registry/card-overview.json +2 -2
  242. package/dist/mcp-data/registry/card-setting.json +36 -15
  243. package/dist/mcp-data/registry/card-settings-scope.json +2 -2
  244. package/dist/mcp-data/registry/chart-legend.json +2 -2
  245. package/dist/mcp-data/registry/chart.json +2 -2
  246. package/dist/mcp-data/registry/checkbox.json +2 -2
  247. package/dist/mcp-data/registry/chip.json +2 -2
  248. package/dist/mcp-data/registry/code-block.json +2 -2
  249. package/dist/mcp-data/registry/conversation-list-item.json +2 -2
  250. package/dist/mcp-data/registry/conversation-list-section.json +2 -2
  251. package/dist/mcp-data/registry/conversation-list.json +2 -2
  252. package/dist/mcp-data/registry/data-customize.json +3 -3
  253. package/dist/mcp-data/registry/data-filter.json +2 -2
  254. package/dist/mcp-data/registry/data-group.json +2 -2
  255. package/dist/mcp-data/registry/data-preferences.json +2 -2
  256. package/dist/mcp-data/registry/data-saved-views.json +2 -2
  257. package/dist/mcp-data/registry/data-search.json +2 -2
  258. package/dist/mcp-data/registry/data-sort.json +2 -2
  259. package/dist/mcp-data/registry/data-toolbar.json +2 -2
  260. package/dist/mcp-data/registry/divider.json +2 -2
  261. package/dist/mcp-data/registry/empty-state.json +27 -14
  262. package/dist/mcp-data/registry/field.json +6 -5
  263. package/dist/mcp-data/registry/filter-menu.json +2 -2
  264. package/dist/mcp-data/registry/icon.json +2 -2
  265. package/dist/mcp-data/registry/input-date.json +2 -2
  266. package/dist/mcp-data/registry/input-time.json +26 -7
  267. package/dist/mcp-data/registry/input.json +265 -15
  268. package/dist/mcp-data/registry/loader.json +2 -2
  269. package/dist/mcp-data/registry/map-cluster-marker.json +263 -0
  270. package/dist/mcp-data/registry/map-entity-marker.json +321 -0
  271. package/dist/mcp-data/registry/markdown.json +2 -2
  272. package/dist/mcp-data/registry/menu.json +2 -2
  273. package/dist/mcp-data/registry/message-actions.json +2 -2
  274. package/dist/mcp-data/registry/message-bubble.json +2 -2
  275. package/dist/mcp-data/registry/message-composer.json +2 -2
  276. package/dist/mcp-data/registry/message-scroller.json +2 -2
  277. package/dist/mcp-data/registry/message.json +2 -2
  278. package/dist/mcp-data/registry/mobile-bar-nav.json +2 -2
  279. package/dist/mcp-data/registry/mobile-header.json +2 -2
  280. package/dist/mcp-data/registry/mobile-section-switcher.json +2 -2
  281. package/dist/mcp-data/registry/mobile-sheet-nav.json +2 -2
  282. package/dist/mcp-data/registry/modal.json +2 -2
  283. package/dist/mcp-data/registry/pagination.json +2 -2
  284. package/dist/mcp-data/registry/panel-nav.json +2 -2
  285. package/dist/mcp-data/registry/panel-sub-nav.json +2 -2
  286. package/dist/mcp-data/registry/panel-tool-header.json +2 -2
  287. package/dist/mcp-data/registry/panel-tool-search.json +2 -2
  288. package/dist/mcp-data/registry/panel-tools.json +2 -2
  289. package/dist/mcp-data/registry/paper-texture.json +2 -2
  290. package/dist/mcp-data/registry/radio-tile.json +398 -0
  291. package/dist/mcp-data/registry/radio.json +2 -2
  292. package/dist/mcp-data/registry/registry.json +724 -49
  293. package/dist/mcp-data/registry/score.json +2 -2
  294. package/dist/mcp-data/registry/scroll-overlay.json +2 -2
  295. package/dist/mcp-data/registry/select.json +2 -2
  296. package/dist/mcp-data/registry/setting-row.json +213 -0
  297. package/dist/mcp-data/registry/shell-app.json +3 -3
  298. package/dist/mcp-data/registry/shell-page.json +5 -5
  299. package/dist/mcp-data/registry/shell-tools.json +2 -2
  300. package/dist/mcp-data/registry/skeleton.json +2 -2
  301. package/dist/mcp-data/registry/slider.json +32 -12
  302. package/dist/mcp-data/registry/swatch-picker.json +2 -2
  303. package/dist/mcp-data/registry/switch.json +2 -2
  304. package/dist/mcp-data/registry/tab-group.json +2 -2
  305. package/dist/mcp-data/registry/table.json +5 -5
  306. package/dist/mcp-data/registry/tag.json +2 -2
  307. package/dist/mcp-data/registry/text.json +2 -2
  308. package/dist/mcp-data/registry/textarea.json +72 -5
  309. package/dist/mcp-data/registry/time-picker.json +28 -9
  310. package/dist/mcp-data/registry/toast.json +2 -2
  311. package/dist/mcp-data/registry/tooltip-chart.json +2 -2
  312. package/dist/mcp-data/registry/tooltip.json +2 -2
  313. package/dist/mcp-data/registry/typing-indicator.json +2 -2
  314. package/dist/react/components.d.ts +4 -0
  315. package/dist/react/components.js +4 -0
  316. package/dist/react/ds-input.d.ts +2 -0
  317. package/dist/react/ds-input.js +2 -0
  318. package/dist/react/ds-map-cluster-marker.d.ts +12 -0
  319. package/dist/react/ds-map-cluster-marker.js +12 -0
  320. package/dist/react/ds-map-entity-marker.d.ts +12 -0
  321. package/dist/react/ds-map-entity-marker.js +12 -0
  322. package/dist/react/ds-radio-tile.d.ts +12 -0
  323. package/dist/react/ds-radio-tile.js +12 -0
  324. package/dist/react/ds-setting-row.d.ts +12 -0
  325. package/dist/react/ds-setting-row.js +12 -0
  326. package/dist/types/components/CardSetting/CardSetting.d.ts +5 -3
  327. package/dist/types/components/CardSetting/index.d.ts +1 -1
  328. package/dist/types/components/EmptyState/EmptyState.d.ts +3 -0
  329. package/dist/types/components/Field/Field.d.ts +4 -0
  330. package/dist/types/components/Input/Input.d.ts +50 -1
  331. package/dist/types/components/InputTime/InputTime.d.ts +3 -0
  332. package/dist/types/components/MapClusterMarker/MapClusterMarker.d.ts +19 -0
  333. package/dist/types/components/MapEntityMarker/MapEntityMarker.d.ts +26 -0
  334. package/dist/types/components/RadioTile/RadioTile.d.ts +40 -0
  335. package/dist/types/components/RadioTile/index.d.ts +2 -0
  336. package/dist/types/components/SettingRow/SettingRow.d.ts +18 -0
  337. package/dist/types/components/Slider/Slider.d.ts +8 -1
  338. package/dist/types/components/Slider/index.d.ts +1 -1
  339. package/dist/types/components/Textarea/Textarea.d.ts +12 -0
  340. package/dist/types/components/TimePicker/TimePicker.d.ts +4 -0
  341. package/dist/types/components.d.ts +627 -11
  342. package/dist/types/utils/text-constraints.d.ts +20 -0
  343. package/dist/vue/components.d.ts +4 -0
  344. package/dist/vue/components.js +4 -0
  345. package/dist/vue/ds-card-setting.js +1 -0
  346. package/dist/vue/ds-input-time.js +1 -0
  347. package/dist/vue/ds-input.js +17 -0
  348. package/dist/vue/ds-map-cluster-marker.d.ts +3 -0
  349. package/dist/vue/ds-map-cluster-marker.js +14 -0
  350. package/dist/vue/ds-map-entity-marker.d.ts +3 -0
  351. package/dist/vue/ds-map-entity-marker.js +17 -0
  352. package/dist/vue/ds-radio-tile.d.ts +3 -0
  353. package/dist/vue/ds-radio-tile.js +24 -0
  354. package/dist/vue/ds-setting-row.d.ts +3 -0
  355. package/dist/vue/ds-setting-row.js +14 -0
  356. package/dist/vue/ds-slider.d.ts +1 -1
  357. package/dist/vue/ds-slider.js +2 -1
  358. package/dist/vue/ds-textarea.js +4 -0
  359. package/dist/vue/ds-time-picker.js +1 -0
  360. package/package.json +5 -5
  361. package/dist/components/p-0qY_HDId.js +0 -2
  362. package/dist/components/p-0qY_HDId.js.map +0 -1
  363. package/dist/components/p-BKZdqJQB.js +0 -2
  364. package/dist/components/p-C-3YqeTb.js +0 -2
  365. package/dist/components/p-C6xVxqOn.js +0 -2
  366. package/dist/components/p-CNxvnQ6A.js.map +0 -1
  367. package/dist/components/p-CdGXzRP8.js +0 -2
  368. package/dist/components/p-DEW7r0U9.js +0 -2
  369. package/dist/components/p-DVOjjuXc.js +0 -2
  370. package/dist/components/p-DVOjjuXc.js.map +0 -1
  371. package/dist/components/p-Di5FH7eh.js +0 -2
  372. package/dist/components/p-Di5FH7eh.js.map +0 -1
  373. package/dist/components/p-Dw9sE6Iw.js +0 -2
  374. package/dist/components/p-etg-Uk1u.js +0 -2
  375. package/dist/components/p-xtGGIZmU.js +0 -2
  376. package/dist/components/p-xtGGIZmU.js.map +0 -1
  377. /package/dist/components/{p-etifxiDc.js.map → p-3bsypMrY.js.map} +0 -0
  378. /package/dist/components/{p-Bn8I7iw6.js.map → p-AmT4GlhM.js.map} +0 -0
  379. /package/dist/components/{p-FIBCluwV.js.map → p-B-HOVYoH.js.map} +0 -0
  380. /package/dist/components/{p-CmexIVnE.js.map → p-B7QEpaMe.js.map} +0 -0
  381. /package/dist/components/{p-CUcUHwI3.js.map → p-B7bXN-vf.js.map} +0 -0
  382. /package/dist/components/{p-BhJXmuRA.js.map → p-BSuMDPaV.js.map} +0 -0
  383. /package/dist/components/{p-0FYD2bev.js.map → p-BU1B6NW8.js.map} +0 -0
  384. /package/dist/components/{p-Do2FJd1y.js.map → p-BVwg5XVz.js.map} +0 -0
  385. /package/dist/components/{p-CYzFfFcH.js.map → p-BXSHN1OK.js.map} +0 -0
  386. /package/dist/components/{p-ljbw3UMZ.js.map → p-BYJtvRQm.js.map} +0 -0
  387. /package/dist/components/{p-CzIpquvw.js.map → p-Bh1Fx0aW.js.map} +0 -0
  388. /package/dist/components/{p-CiJ1WR11.js.map → p-Bm3KWMe4.js.map} +0 -0
  389. /package/dist/components/{p-DVINzOoK.js.map → p-Bo7GxFBh.js.map} +0 -0
  390. /package/dist/components/{p-8yBdCXCn.js.map → p-BsM37Prt.js.map} +0 -0
  391. /package/dist/components/{p-DpoTwJAR.js.map → p-BugKaVWc.js.map} +0 -0
  392. /package/dist/components/{p-Bpd6YCo4.js.map → p-C3-dcROG.js.map} +0 -0
  393. /package/dist/components/{p-Dzndkdx5.js.map → p-CI7c9kp-.js.map} +0 -0
  394. /package/dist/components/{p-CdgOLWX9.js.map → p-CJD0kLeV.js.map} +0 -0
  395. /package/dist/components/{p-BeNa6tw5.js.map → p-C_gJD8l3.js.map} +0 -0
  396. /package/dist/components/{p-DwbcNDJF.js.map → p-Cihjy4WY.js.map} +0 -0
  397. /package/dist/components/{p-BgQMEHRa.js.map → p-Co5MiPNa.js.map} +0 -0
  398. /package/dist/components/{p-CD4DZPy_.js.map → p-CrL9wxZg.js.map} +0 -0
  399. /package/dist/components/{p-CGidq1iC.js.map → p-CuwopElg.js.map} +0 -0
  400. /package/dist/components/{p-Cqc2U1ZQ.js.map → p-CzQ_JF6A.js.map} +0 -0
  401. /package/dist/components/{p-ZhP2tVmM.js.map → p-D0KD-Nr_.js.map} +0 -0
  402. /package/dist/components/{p-DOAybCp0.js.map → p-DCLRAH5i.js.map} +0 -0
  403. /package/dist/components/{p-Dn9QHL4O.js.map → p-DFkw6wrS.js.map} +0 -0
  404. /package/dist/components/{p-D1vQGJzc.js.map → p-DHapI2sf.js.map} +0 -0
  405. /package/dist/components/{p-DHICPS4n.js.map → p-DWmYCOKz.js.map} +0 -0
  406. /package/dist/components/{p-vfCu7XSc.js.map → p-DZ58Sg5a.js.map} +0 -0
  407. /package/dist/components/{p-D0y7Sja6.js.map → p-Dcn1eDVt.js.map} +0 -0
  408. /package/dist/components/{p-E5W27Fu_.js.map → p-DcrdyDRw.js.map} +0 -0
  409. /package/dist/components/{p-xdmJCPCg.js.map → p-Gb-vTuXr.js.map} +0 -0
  410. /package/dist/components/{p-CiH4GG6r.js.map → p-iGNHXFZA.js.map} +0 -0
  411. /package/dist/components/{p-5URekSny.js.map → p-lADW-TI8.js.map} +0 -0
  412. /package/dist/components/{p-D922f6Tb.js.map → p-p_MwknM3.js.map} +0 -0
  413. /package/dist/components/{p-Dfs98tpL.js.map → p-tJaC01aE.js.map} +0 -0
  414. /package/dist/components/{p-B_jdoM7e.js.map → p-z8L-YMi3.js.map} +0 -0
@@ -59,14 +59,15 @@
59
59
  "Assign a two-number array through the JavaScript value property to create a range; values are ordered, clamped, stepped, and prevented from crossing.",
60
60
  "minStepsBetweenValues reserves a minimum stepped distance between range thumbs.",
61
61
  "The initial normalized value is the native form-reset baseline and range values submit as repeated entries under the same name.",
62
- "Focused, filled, dirty, touched, dragging, valid, disabled, read-only, and orientation data hooks expose interaction state without changing the value contract."
62
+ "Focused, filled, dirty, touched, dragging, valid, disabled, read-only, and orientation data hooks expose interaction state without changing the value contract.",
63
+ "Explicit ticks define the only selectable snap points and may carry labels. Marks sit below a horizontal track, or beside a vertical track, with labels beyond the marks. Horizontal labels center on their marks and shift inward only when they reach the control edges. Without ticks, step=\"any\" permits smooth adjustment; ordinary stepped behavior remains available. Arrow keys traverse adjacent ticks and Home/End reach the available extremes."
63
64
  ],
64
65
  "responsiveBehavior": [
65
66
  "The visible label uses the same primary emphasized text-body-small recipe as Field at every density; the value uses the same primary metric without emphasis.",
66
67
  "Horizontal Slider fills the width supplied by its parent; the parent chooses an appropriate readable track length.",
67
68
  "Vertical Slider owns a token-based default length that may be overridden with --ds-slider-vertical-length in layout-specific compositions.",
68
69
  "Use md in ordinary forms and sm or xs only when the surrounding control density uses the same recipe.",
69
- "Track thickness scales with density: 8px at md, 6px at sm, and 4px at xs. The unfilled track is transparent with a tertiary-foreground inset outline, the filled range is brand, and the square thumb uses a 2px radius with a 1.5px brand inset ring.",
70
+ "Track thickness scales with density. The unfilled track has a neutral border, the filled range uses brand color, and the thumb uses the primary surface with subtle elevation.",
70
71
  "Horizontal value direction is left-to-right; the design system does not author RTL-specific component behavior."
71
72
  ],
72
73
  "frameworkCaveats": {
@@ -78,7 +79,10 @@
78
79
  "Use DsSlider with a number or two-number value array and handle onDsChange and onDsCommit custom events."
79
80
  ],
80
81
  "angular": [
81
- "Use DsSlider with property binding for range arrays; the generated number value accessor is appropriate only for a single numeric value."
82
+ "Use DsSlider with SelectValueAccessor for Angular Forms; it preserves either a number or a two-number array."
83
+ ],
84
+ "vue": [
85
+ "Use v-model for a number or a two-number array. Assign ticks through property binding."
82
86
  ]
83
87
  },
84
88
  "references": [
@@ -307,8 +311,8 @@
307
311
  "description": "Accessible label for the lower thumb in a range slider."
308
312
  },
309
313
  "step": {
310
- "type": "number",
311
- "resolvedType": "number",
314
+ "type": "number | 'any'",
315
+ "resolvedType": "\"any\" | number",
312
316
  "attribute": "step",
313
317
  "default": "1",
314
318
  "required": false,
@@ -323,6 +327,14 @@
323
327
  "mutable": false,
324
328
  "description": "Align the thumb edge with full-width rail endpoints, or its center with inset rail endpoints."
325
329
  },
330
+ "ticks": {
331
+ "type": "SliderTick[]",
332
+ "resolvedType": "SliderTick[]",
333
+ "default": "[]",
334
+ "required": false,
335
+ "mutable": false,
336
+ "description": "Explicit ticks are the selectable snap points. Empty ticks with step='any' allow smooth adjustment."
337
+ },
326
338
  "value": {
327
339
  "type": "SliderValue",
328
340
  "resolvedType": "number | number[]",
@@ -564,8 +576,8 @@
564
576
  "description": "Accessible label for the lower thumb in a range slider."
565
577
  },
566
578
  "step": {
567
- "type": "number",
568
- "resolvedType": "number",
579
+ "type": "number | 'any'",
580
+ "resolvedType": "\"any\" | number",
569
581
  "attribute": "step",
570
582
  "default": "1",
571
583
  "required": false,
@@ -580,6 +592,14 @@
580
592
  "mutable": false,
581
593
  "description": "Align the thumb edge with full-width rail endpoints, or its center with inset rail endpoints."
582
594
  },
595
+ "ticks": {
596
+ "type": "SliderTick[]",
597
+ "resolvedType": "SliderTick[]",
598
+ "default": "[]",
599
+ "required": false,
600
+ "mutable": false,
601
+ "description": "Explicit ticks are the selectable snap points. Empty ticks with step='any' allow smooth adjustment."
602
+ },
583
603
  "value": {
584
604
  "type": "SliderValue",
585
605
  "resolvedType": "number | number[]",
@@ -672,11 +692,11 @@
672
692
  "import": "import { DsSlider } from '@ds-mo/ui/angular/ds-slider';",
673
693
  "example": "<ds-slider></ds-slider>"
674
694
  },
675
- "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: formatOptions, valueTexts.",
695
+ "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: formatOptions, ticks, valueTexts.",
676
696
  "peerDependencies": {
677
697
  "required": [
678
- "@ds-mo/tokens ^6.5.1",
679
- "@ds-mo/icons ^8.1.0"
698
+ "@ds-mo/tokens ^6.5.2",
699
+ "@ds-mo/icons ^8.1.1"
680
700
  ],
681
701
  "frameworks": "Custom Elements; React 18/19 wrappers; Vue 3 wrappers; Angular 19-22 standalone adapters."
682
702
  }
@@ -692,12 +712,12 @@
692
712
  "files": [
693
713
  {
694
714
  "path": "src/wc/components/Slider/Slider.css",
695
- "content": "@import '../../utils/control-inactive.css';\n@import '../../utils/field-stack.css';\n@import '../../utils/forced-colors.css';\n\n:host {\n --ds-slider-control-size: var(--dimension-size-400);\n --ds-slider-thumb-size: var(--dimension-size-200);\n --ds-slider-track-size: var(--dimension-size-100);\n --ds-slider-track-stroke: var(--dimension-stroke-width-012);\n --ds-slider-vertical-length: calc(var(--dimension-size-800) * 3);\n box-sizing: border-box;\n width: 100%;\n color: var(--color-foreground-primary);\n}\n\n:host(.slider--sm) {\n --ds-slider-control-size: var(--dimension-size-300);\n --ds-slider-thumb-size: var(--dimension-size-150);\n --ds-slider-track-size: var(--dimension-size-075);\n}\n\n:host(.slider--xs) {\n --ds-slider-control-size: var(--dimension-size-200);\n --ds-slider-thumb-size: var(--dimension-size-100);\n --ds-slider-track-size: var(--dimension-size-050);\n}\n\n:host(.slider--vertical) {\n width: fit-content;\n min-width: var(--dimension-form-width-xs);\n}\n\n.slider__label-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--dimension-space-100);\n min-width: 0;\n}\n\n.slider__label {\n min-width: 0;\n}\n\n.slider__value {\n flex-shrink: 0;\n}\n\n.slider__control {\n position: relative;\n width: 100%;\n height: var(--ds-slider-control-size);\n border-radius: var(--dimension-radius-half);\n cursor: default;\n touch-action: none;\n user-select: none;\n}\n\n:host(.slider--vertical) .slider__control {\n align-self: center;\n width: var(--ds-slider-control-size);\n height: var(--ds-slider-vertical-length);\n}\n\n:host(.slider--readonly) .slider__control {\n cursor: default;\n}\n\n/* Inactive: `.ds-control-inactive` (50% opacity) on the host. */\n:host(.ds-control-inactive) .slider__control {\n cursor: not-allowed;\n}\n\n.slider__rail {\n position: absolute;\n top: 50%;\n right: 0;\n left: 0;\n height: var(--ds-slider-track-size);\n overflow: hidden;\n border-radius: var(--dimension-radius-025);\n background-color: transparent;\n box-shadow: inset 0 0 0 var(--ds-slider-track-stroke) var(--color-border-secondary);\n transform: translateY(-50%);\n pointer-events: none;\n}\n\n:host(.slider--thumb-center) .slider__rail {\n right: calc(var(--ds-slider-thumb-size) / 2);\n left: calc(var(--ds-slider-thumb-size) / 2);\n}\n\n.slider__indicator {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: calc(\n var(--ds-slider-thumb-size) / 2 + (var(--ds-slider-end-pct, 0) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n border-radius: inherit;\n background-color: var(--color-background-bold-brand);\n}\n\n:host(.slider--range) .slider__indicator {\n left: calc(\n var(--ds-slider-thumb-size) / 2 + (var(--ds-slider-start-pct, 0) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n width: calc(\n ((var(--ds-slider-end-pct, 0) - var(--ds-slider-start-pct, 0)) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n}\n\n:host(.slider--thumb-center) .slider__indicator {\n left: calc(var(--ds-slider-start-pct, 0) * 1%);\n width: calc((var(--ds-slider-end-pct, 0) - var(--ds-slider-start-pct, 0)) * 1%);\n}\n\n.slider__thumb {\n position: absolute;\n top: 50%;\n left: calc((var(--ds-slider-thumb-pct, 0) / 100) * (100% - var(--ds-slider-thumb-size)));\n width: var(--ds-slider-thumb-size);\n height: var(--ds-slider-thumb-size);\n transform: translateY(-50%);\n z-index: 1;\n}\n\n.slider__thumb--active {\n z-index: 2;\n}\n\n.slider__input {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n border: 0;\n opacity: 0;\n appearance: none;\n pointer-events: none;\n z-index: 2;\n}\n\n.slider__thumb-visual {\n position: absolute;\n inset: 0;\n box-sizing: border-box;\n overflow: visible;\n border-radius: var(--dimension-radius-025);\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-sm);\n pointer-events: none;\n transition:\n background-color var(--effect-motion-short-2),\n box-shadow var(--effect-motion-short-2);\n}\n\n.slider__thumb-wash {\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background-color: transparent;\n transition: background-color var(--effect-motion-short-2);\n}\n\n@media (hover: hover) and (pointer: fine) {\n :host(:not(.slider--readonly):not(.ds-control-inactive))\n .slider__thumb:hover\n .slider__thumb-wash {\n background-color: var(--color-interaction-hover);\n }\n}\n\n:host([data-dragging]:not(.slider--readonly):not(.ds-control-inactive))\n .slider__thumb--active\n .slider__thumb-wash {\n background-color: var(--color-interaction-pressed);\n}\n\n.slider__input:focus-visible + .slider__thumb-visual,\n:host([data-review-focus]) .slider__thumb[data-index='0'] .slider__thumb-visual {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n:host(.slider--vertical) .slider__rail {\n top: 0;\n right: auto;\n bottom: 0;\n left: 50%;\n width: var(--ds-slider-track-size);\n height: auto;\n transform: translateX(-50%);\n}\n\n:host(.slider--vertical.slider--thumb-center) .slider__rail {\n top: calc(var(--ds-slider-thumb-size) / 2);\n bottom: calc(var(--ds-slider-thumb-size) / 2);\n}\n\n:host(.slider--vertical) .slider__indicator {\n top: auto;\n right: 0;\n bottom: 0;\n left: 0;\n width: auto;\n height: calc(\n var(--ds-slider-thumb-size) / 2 + (var(--ds-slider-end-pct, 0) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n}\n\n:host(.slider--vertical.slider--range) .slider__indicator {\n bottom: calc(\n var(--ds-slider-thumb-size) / 2 + (var(--ds-slider-start-pct, 0) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n height: calc(\n ((var(--ds-slider-end-pct, 0) - var(--ds-slider-start-pct, 0)) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n}\n\n:host(.slider--vertical.slider--thumb-center) .slider__indicator {\n bottom: calc(var(--ds-slider-start-pct, 0) * 1%);\n height: calc((var(--ds-slider-end-pct, 0) - var(--ds-slider-start-pct, 0)) * 1%);\n}\n\n:host(.slider--vertical) .slider__thumb {\n top: auto;\n bottom: calc((var(--ds-slider-thumb-pct, 0) / 100) * (100% - var(--ds-slider-thumb-size)));\n left: 50%;\n transform: translateX(-50%);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .slider__thumb-visual,\n .slider__thumb-wash {\n transition: none;\n }\n}\n\n@media (forced-colors: active) {\n .slider__rail {\n border: var(--ds-slider-track-stroke) solid var(--ds-forced-color-content);\n box-shadow: none;\n }\n\n .slider__indicator {\n background-color: var(--ds-forced-color-selected);\n }\n\n .slider__thumb-visual {\n border: var(--dimension-stroke-width-012) solid var(--ds-forced-color-control-boundary);\n background-color: var(--ds-forced-color-surface);\n box-shadow: none;\n }\n\n .slider__input:focus-visible + .slider__thumb-visual,\n :host([data-review-focus]) .slider__thumb[data-index='0'] .slider__thumb-visual {\n outline-color: var(--ds-forced-color-selected);\n }\n}\n",
715
+ "content": "@import '../../utils/control-inactive.css';\n@import '../../utils/field-stack.css';\n@import '../../utils/forced-colors.css';\n\n:host {\n --ds-slider-control-size: var(--dimension-size-400);\n --ds-slider-thumb-size: var(--dimension-size-200);\n --ds-slider-track-size: var(--dimension-size-100);\n --ds-slider-track-stroke: var(--dimension-stroke-width-012);\n --ds-slider-vertical-length: calc(var(--dimension-size-800) * 3);\n box-sizing: border-box;\n width: 100%;\n color: var(--color-foreground-primary);\n}\n\n:host(.slider--sm) {\n --ds-slider-control-size: var(--dimension-size-300);\n --ds-slider-thumb-size: var(--dimension-size-150);\n --ds-slider-track-size: var(--dimension-size-075);\n}\n\n:host(.slider--xs) {\n --ds-slider-control-size: var(--dimension-size-200);\n --ds-slider-thumb-size: var(--dimension-size-100);\n --ds-slider-track-size: var(--dimension-size-050);\n}\n\n:host(.slider--vertical) {\n width: fit-content;\n min-width: var(--dimension-form-width-xs);\n}\n\n.slider__label-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--dimension-space-100);\n min-width: 0;\n}\n\n.slider__label {\n min-width: 0;\n}\n\n.slider__value {\n flex-shrink: 0;\n}\n\n.slider__control {\n position: relative;\n width: 100%;\n height: var(--ds-slider-control-size);\n border-radius: var(--dimension-radius-half);\n cursor: default;\n touch-action: none;\n user-select: none;\n}\n\n:host(.slider--vertical) .slider__control {\n align-self: center;\n width: var(--ds-slider-control-size);\n height: var(--ds-slider-vertical-length);\n}\n\n:host(.slider--readonly) .slider__control {\n cursor: default;\n}\n\n/* Inactive: `.ds-control-inactive` (50% opacity) on the host. */\n:host(.ds-control-inactive) .slider__control {\n cursor: not-allowed;\n}\n\n.slider__rail {\n position: absolute;\n top: 50%;\n right: 0;\n left: 0;\n height: var(--ds-slider-track-size);\n overflow: hidden;\n border-radius: var(--dimension-radius-025);\n background-color: transparent;\n box-shadow: inset 0 0 0 var(--ds-slider-track-stroke) var(--color-border-secondary);\n transform: translateY(-50%);\n pointer-events: none;\n}\n\n:host(.slider--thumb-center) .slider__rail {\n right: calc(var(--ds-slider-thumb-size) / 2);\n left: calc(var(--ds-slider-thumb-size) / 2);\n}\n\n.slider__indicator {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: calc(\n var(--ds-slider-thumb-size) / 2 + (var(--ds-slider-end-pct, 0) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n border-radius: inherit;\n background-color: var(--color-background-bold-brand);\n}\n\n:host(.slider--range) .slider__indicator {\n left: calc(\n var(--ds-slider-thumb-size) / 2 + (var(--ds-slider-start-pct, 0) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n width: calc(\n ((var(--ds-slider-end-pct, 0) - var(--ds-slider-start-pct, 0)) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n}\n\n:host(.slider--thumb-center) .slider__indicator {\n left: calc(var(--ds-slider-start-pct, 0) * 1%);\n width: calc((var(--ds-slider-end-pct, 0) - var(--ds-slider-start-pct, 0)) * 1%);\n}\n\n.slider__thumb {\n position: absolute;\n top: 50%;\n left: calc((var(--ds-slider-thumb-pct, 0) / 100) * (100% - var(--ds-slider-thumb-size)));\n width: var(--ds-slider-thumb-size);\n height: var(--ds-slider-thumb-size);\n transform: translateY(-50%);\n z-index: 1;\n}\n\n.slider__thumb--active {\n z-index: 2;\n}\n\n.slider__input {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n padding: 0;\n border: 0;\n opacity: 0;\n appearance: none;\n pointer-events: none;\n z-index: 2;\n}\n\n.slider__thumb-visual {\n position: absolute;\n inset: 0;\n box-sizing: border-box;\n overflow: visible;\n border-radius: var(--dimension-radius-025);\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-sm);\n pointer-events: none;\n transition:\n background-color var(--effect-motion-short-2),\n box-shadow var(--effect-motion-short-2);\n}\n\n.slider__thumb-wash {\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background-color: transparent;\n transition: background-color var(--effect-motion-short-2);\n}\n\n@media (hover: hover) and (pointer: fine) {\n :host(:not(.slider--readonly):not(.ds-control-inactive))\n .slider__thumb:hover\n .slider__thumb-wash {\n background-color: var(--color-interaction-hover);\n }\n}\n\n:host([data-dragging]:not(.slider--readonly):not(.ds-control-inactive))\n .slider__thumb--active\n .slider__thumb-wash {\n background-color: var(--color-interaction-pressed);\n}\n\n.slider__input:focus-visible + .slider__thumb-visual,\n:host([data-review-focus]) .slider__thumb[data-index='0'] .slider__thumb-visual {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n:host(.slider--vertical) .slider__rail {\n top: 0;\n right: auto;\n bottom: 0;\n left: 50%;\n width: var(--ds-slider-track-size);\n height: auto;\n transform: translateX(-50%);\n}\n\n:host(.slider--vertical.slider--thumb-center) .slider__rail {\n top: calc(var(--ds-slider-thumb-size) / 2);\n bottom: calc(var(--ds-slider-thumb-size) / 2);\n}\n\n:host(.slider--vertical) .slider__indicator {\n top: auto;\n right: 0;\n bottom: 0;\n left: 0;\n width: auto;\n height: calc(\n var(--ds-slider-thumb-size) / 2 + (var(--ds-slider-end-pct, 0) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n}\n\n:host(.slider--vertical.slider--range) .slider__indicator {\n bottom: calc(\n var(--ds-slider-thumb-size) / 2 + (var(--ds-slider-start-pct, 0) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n height: calc(\n ((var(--ds-slider-end-pct, 0) - var(--ds-slider-start-pct, 0)) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n}\n\n:host(.slider--vertical.slider--thumb-center) .slider__indicator {\n bottom: calc(var(--ds-slider-start-pct, 0) * 1%);\n height: calc((var(--ds-slider-end-pct, 0) - var(--ds-slider-start-pct, 0)) * 1%);\n}\n\n:host(.slider--vertical) .slider__thumb {\n top: auto;\n bottom: calc((var(--ds-slider-thumb-pct, 0) / 100) * (100% - var(--ds-slider-thumb-size)));\n left: 50%;\n transform: translateX(-50%);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .slider__thumb-visual,\n .slider__thumb-wash {\n transition: none;\n }\n}\n\n@media (forced-colors: active) {\n .slider__rail {\n border: var(--ds-slider-track-stroke) solid var(--ds-forced-color-content);\n box-shadow: none;\n }\n\n .slider__indicator {\n background-color: var(--ds-forced-color-selected);\n }\n\n .slider__thumb-visual {\n border: var(--dimension-stroke-width-012) solid var(--ds-forced-color-control-boundary);\n background-color: var(--ds-forced-color-surface);\n box-shadow: none;\n }\n\n .slider__input:focus-visible + .slider__thumb-visual,\n :host([data-review-focus]) .slider__thumb[data-index='0'] .slider__thumb-visual {\n outline-color: var(--ds-forced-color-selected);\n }\n}\n\n.slider__tick {\n position: absolute;\n top: calc(\n 50% + var(--ds-slider-track-size) / 2 + var(--dimension-space-050) + var(--dimension-space-012)\n );\n left: calc(\n var(--ds-slider-thumb-size) / 2 + (var(--ds-slider-tick-pct) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n transform: translateX(-50%);\n pointer-events: none;\n}\n.slider__tick-mark {\n display: block;\n width: var(--dimension-stroke-width-025);\n height: var(--dimension-stroke-width-025);\n border-radius: var(--dimension-radius-half);\n background: var(--color-foreground-tertiary);\n}\n.slider__tick-label {\n width: max-content;\n max-width: none;\n position: absolute;\n top: calc(100% + var(--dimension-space-050));\n left: 50%;\n transform: translateX(-50%);\n white-space: nowrap;\n}\n:host(:not(.slider--vertical)) .slider__control {\n container-type: inline-size;\n}\n:host(:not(.slider--vertical)) .slider__tick-label {\n /* Center on the tick, clamping only when the text reaches the control edges. */\n --ds-slider-label-anchor: calc(\n var(--ds-slider-thumb-size) / 2 + (var(--ds-slider-tick-pct) / 100) *\n (100cqw - var(--ds-slider-thumb-size))\n );\n transform: translateX(\n clamp(\n calc(-1 * var(--ds-slider-label-anchor)),\n -50%,\n calc(100cqw - var(--ds-slider-label-anchor) - 100%)\n )\n );\n}\n:host(.slider--tick-labels:not(.slider--vertical)) .slider__control {\n margin-bottom: var(--dimension-space-200);\n}\n:host(.slider--vertical) .slider__tick {\n top: auto;\n bottom: calc(\n var(--ds-slider-thumb-size) / 2 + (var(--ds-slider-tick-pct) / 100) *\n (100% - var(--ds-slider-thumb-size))\n );\n left: calc(50% + var(--ds-slider-track-size) / 2 + var(--dimension-space-050));\n transform: translateY(50%);\n}\n:host(.slider--vertical) .slider__tick-label {\n top: 50%;\n left: calc(100% + var(--dimension-space-050));\n transform: translateY(-50%);\n}\n",
696
716
  "type": "registry:ui"
697
717
  },
698
718
  {
699
719
  "path": "src/wc/components/Slider/Slider.tsx",
700
- "content": "import {\n AttachInternals,\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Host,\n Method,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\nimport {\n restoreNumberArrayFormState,\n restoreStringFormState,\n setFormControlValue,\n setRepeatedFormControlValue,\n} from '../../utils';\n\nexport type SliderValue = number | number[];\nexport type SliderSize = 'md' | 'sm' | 'xs';\nexport type SliderOrientation = 'horizontal' | 'vertical';\nexport type SliderThumbAlignment = 'edge' | 'center';\n\nlet sliderId = 0;\nlet sliderExternalLabelId = 0;\n\n@Component({\n tag: 'ds-slider',\n styleUrl: 'Slider.css',\n scoped: true,\n formAssociated: true,\n})\nexport class Slider {\n @Element() el!: HTMLElement;\n @AttachInternals() internals!: ElementInternals;\n\n /** Current value. Assign a two-number array through the JavaScript property for a range slider. */\n @Prop({ mutable: true }) value: SliderValue = 0;\n @Prop() min: number = 0;\n @Prop() max: number = 100;\n @Prop() step: number = 1;\n /** Minimum number of steps kept between two range thumbs. */\n @Prop() minStepsBetweenValues: number = 0;\n /** Visible field label. Supply aria-label when the label is intentionally hidden. */\n @Prop() label: string | undefined;\n /** Show the formatted current value beside the visible label. */\n @Prop() showValue: boolean = true;\n @Prop() size: SliderSize = 'md';\n @Prop() orientation: SliderOrientation = 'horizontal';\n /** Align the thumb edge with full-width rail endpoints, or its center with inset rail endpoints. */\n @Prop() thumbAlignment: SliderThumbAlignment = 'edge';\n @Prop({ reflect: true }) name: string | undefined;\n @Prop({ reflect: true }) form: string | undefined;\n @Prop({ reflect: true }) disabled: boolean = false;\n /** Keep the value focusable and submittable while preventing changes. */\n @Prop({ reflect: true }) readOnly: boolean = false;\n @Prop() isInactive: boolean = false;\n /** Direct accessible name for a single-thumb slider without a visible label. */\n @Prop({ attribute: 'aria-label' }) ariaLabel: string | null = null;\n /** Id references for a visible single-thumb slider label. */\n @Prop({ attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined;\n /** Id references for supporting guidance or error text. */\n @Prop({ attribute: 'aria-describedby' }) ariaDescribedby: string | undefined;\n /** Accessible label for the lower thumb in a range slider. */\n @Prop() startLabel: string = 'Minimum value';\n /** Accessible label for the upper thumb in a range slider. */\n @Prop() endLabel: string = 'Maximum value';\n /** Human-readable value text for a single slider or both range thumbs. */\n @Prop() valueText: string | undefined;\n /** Per-thumb human-readable value text for a range slider. Assign through the JavaScript property. */\n @Prop() valueTexts: string[] = [];\n /** Locale used by Intl.NumberFormat for the visible value. */\n @Prop() locale: string | undefined;\n /** Intl.NumberFormat options. Assign objects through the JavaScript property. */\n @Prop() formatOptions: Intl.NumberFormatOptions | undefined;\n @Prop() valuePrefix: string = '';\n @Prop() valueSuffix: string = '';\n @Prop() rangeSeparator: string = '–';\n /** Id applied to the first native range input. */\n @Prop() inputId: string | undefined;\n\n /** Emitted continuously while the value changes. */\n @Event() dsChange!: EventEmitter<SliderValue>;\n /** Emitted when a pointer or keyboard value change is committed. */\n @Event() dsCommit!: EventEmitter<SliderValue>;\n\n @State() private formDisabled = false;\n @State() private dragging = false;\n @State() private focused = false;\n @State() private touched = false;\n @State() private activeThumbIndex = 0;\n @State() private externalLabelledby: string | undefined;\n\n private readonly generatedId = `ds-slider-${++sliderId}`;\n private readonly labelId = `${this.generatedId}-label`;\n private initialValue: SliderValue = 0;\n private lastCommittedValue: SliderValue = 0;\n private pointerId: number | null = null;\n private pointerStartValue: SliderValue = 0;\n private controlEl: HTMLDivElement | null = null;\n\n componentWillLoad() {\n this.initialValue = this.cloneValue(this.publicValue);\n this.lastCommittedValue = this.cloneValue(this.publicValue);\n this.syncFormValue();\n }\n\n componentDidLoad() {\n this.syncNativeLabels();\n }\n\n @Watch('value')\n @Watch('min')\n @Watch('max')\n @Watch('step')\n @Watch('minStepsBetweenValues')\n @Watch('name')\n @Watch('disabled')\n @Watch('isInactive')\n syncFormValue() {\n const values = this.resolvedValues;\n if (this.isRange) {\n setRepeatedFormControlValue(this.internals, this.name, values, {\n inactive: this.isDisabled,\n });\n } else {\n const value = String(values[0]);\n setFormControlValue(this.internals, this.name ? value : null, {\n inactive: this.isDisabled,\n state: value,\n });\n }\n }\n\n formDisabledCallback(disabled: boolean) {\n this.formDisabled = disabled;\n this.syncFormValue();\n }\n\n formResetCallback() {\n this.value = this.cloneValue(this.initialValue);\n this.lastCommittedValue = this.cloneValue(this.initialValue);\n this.dragging = false;\n this.focused = false;\n this.touched = false;\n }\n\n formStateRestoreCallback(state: string | File | FormData | null) {\n if (this.isRange) {\n const restored = restoreNumberArrayFormState(state, 2);\n this.value = restored.length ? restored : this.cloneValue(this.initialValue);\n } else {\n const restored = Number(restoreStringFormState(state, 'NaN'));\n if (Number.isFinite(restored)) this.value = restored;\n }\n this.lastCommittedValue = this.cloneValue(this.publicValue);\n }\n\n @Method()\n async setFocus(index: number = 0) {\n const inputs = this.el.querySelectorAll<HTMLInputElement>('.slider__input');\n inputs[Math.max(0, Math.min(index, inputs.length - 1))]?.focus();\n }\n\n private get isDisabled(): boolean {\n return this.disabled || this.isInactive || this.formDisabled;\n }\n\n private get isRange(): boolean {\n return Array.isArray(this.value);\n }\n\n private get safeStep(): number {\n return Number.isFinite(this.step) && this.step > 0 ? this.step : 1;\n }\n\n private get safeMin(): number {\n return Number.isFinite(this.min) ? this.min : 0;\n }\n\n private get safeMax(): number {\n const minimum = this.safeMin;\n return Number.isFinite(this.max) && this.max > minimum ? this.max : minimum + this.safeStep;\n }\n\n private get minimumGap(): number {\n const steps = Number.isFinite(this.minStepsBetweenValues)\n ? Math.max(0, Math.floor(this.minStepsBetweenValues))\n : 0;\n return steps * this.safeStep;\n }\n\n private get resolvedValues(): number[] {\n const minimum = this.safeMin;\n const maximum = this.safeMax;\n if (!this.isRange) return [this.snap(Number(this.value))];\n\n const raw = this.value as number[];\n let lower = this.snap(Number(raw[0] ?? minimum));\n let upper = this.snap(Number(raw[1] ?? maximum));\n if (lower > upper) [lower, upper] = [upper, lower];\n\n const gap = Math.min(this.minimumGap, maximum - minimum);\n if (upper - lower < gap) {\n upper = Math.min(maximum, this.snap(lower + gap));\n lower = Math.max(minimum, this.snap(upper - gap));\n }\n return [lower, upper];\n }\n\n private get publicValue(): SliderValue {\n const values = this.resolvedValues;\n return this.isRange ? [...values] : values[0];\n }\n\n private cloneValue(value: SliderValue): SliderValue {\n return Array.isArray(value) ? [...value] : value;\n }\n\n private valuesEqual(a: SliderValue, b: SliderValue): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.length === b.length && a.every((value, index) => value === b[index]);\n }\n return !Array.isArray(a) && !Array.isArray(b) && a === b;\n }\n\n private decimalPlaces(value: number): number {\n const text = String(value).toLowerCase();\n if (text.includes('e-')) return Number(text.split('e-')[1]) || 0;\n return text.includes('.') ? text.split('.')[1].length : 0;\n }\n\n private snap(value: number): number {\n const minimum = this.safeMin;\n const maximum = this.safeMax;\n const candidate = Number.isFinite(value) ? value : minimum;\n const stepped = minimum + Math.round((candidate - minimum) / this.safeStep) * this.safeStep;\n const precision = Math.min(\n 10,\n Math.max(\n this.decimalPlaces(minimum),\n this.decimalPlaces(maximum),\n this.decimalPlaces(this.safeStep)\n )\n );\n return Number(Math.min(maximum, Math.max(minimum, stepped)).toFixed(precision));\n }\n\n private percent(value: number): number {\n return ((value - this.safeMin) / (this.safeMax - this.safeMin)) * 100;\n }\n\n private allowedMin(index: number, values = this.resolvedValues): number {\n return this.isRange && index === 1\n ? Math.min(this.safeMax, values[0] + this.minimumGap)\n : this.safeMin;\n }\n\n private allowedMax(index: number, values = this.resolvedValues): number {\n return this.isRange && index === 0\n ? Math.max(this.safeMin, values[1] - this.minimumGap)\n : this.safeMax;\n }\n\n private setValueAt(index: number, next: number): boolean {\n const previous = this.publicValue;\n const values = this.resolvedValues;\n const constrained = Math.min(\n this.allowedMax(index, values),\n Math.max(this.allowedMin(index, values), this.snap(next))\n );\n values[index] = constrained;\n const nextValue: SliderValue = this.isRange ? [...values] : values[0];\n if (this.valuesEqual(previous, nextValue)) return false;\n\n this.value = nextValue;\n this.dsChange.emit(this.cloneValue(nextValue));\n return true;\n }\n\n private commitIfChanged() {\n const current = this.publicValue;\n if (this.valuesEqual(current, this.lastCommittedValue)) return;\n this.lastCommittedValue = this.cloneValue(current);\n this.dsCommit.emit(this.cloneValue(current));\n }\n\n private syncNativeLabels() {\n if (this.label || this.ariaLabel || this.ariaLabelledby || this.isRange) return;\n const ids = (Array.from(this.internals.labels) as HTMLLabelElement[]).map(label => {\n if (!label.id) label.id = `ds-slider-label-${++sliderExternalLabelId}`;\n return label.id;\n });\n if (ids.length) this.externalLabelledby = ids.join(' ');\n }\n\n private formattedValue(value: number, index: number): string {\n const authored = this.valueTexts[index] ?? this.valueText;\n if (authored) return authored;\n let number: string;\n try {\n number = new Intl.NumberFormat(this.locale, this.formatOptions).format(value);\n } catch {\n number = String(value);\n }\n return `${this.valuePrefix}${number}${this.valueSuffix}`;\n }\n\n private ariaValueText(value: number, index: number): string | undefined {\n if (\n this.valueTexts[index] ||\n this.valueText ||\n this.valuePrefix ||\n this.valueSuffix ||\n this.formatOptions\n ) {\n return this.formattedValue(value, index);\n }\n return undefined;\n }\n\n private handleNativeInput = (event: Event, index: number) => {\n const input = event.target as HTMLInputElement;\n this.activeThumbIndex = index;\n if (this.readOnly || this.isDisabled) {\n input.value = String(this.resolvedValues[index]);\n return;\n }\n this.setValueAt(index, Number(input.value));\n };\n\n private handleNativeChange = () => {\n if (!this.readOnly && !this.isDisabled) this.commitIfChanged();\n };\n\n private handleKeyDown = (event: KeyboardEvent) => {\n if (!this.readOnly) return;\n if (\n [\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n 'Home',\n 'End',\n 'PageUp',\n 'PageDown',\n ].includes(event.key)\n ) {\n event.preventDefault();\n }\n };\n\n private handleFocus = (index: number) => {\n this.activeThumbIndex = index;\n this.focused = true;\n };\n\n private handleBlur = (event: FocusEvent) => {\n const next = event.relatedTarget;\n if (next instanceof Node && this.el.contains(next)) return;\n this.focused = false;\n this.touched = true;\n };\n\n private handleHostClick = (event: MouseEvent) => {\n if (event.target !== this.el || this.isDisabled) return;\n const inputs = this.el.querySelectorAll<HTMLInputElement>('.slider__input');\n inputs[Math.min(this.activeThumbIndex, inputs.length - 1)]?.focus();\n };\n\n private pointerPercent(event: PointerEvent): number {\n const control = this.controlEl;\n if (!control) return 0;\n const rect = control.getBoundingClientRect();\n const thumb = this.el.querySelector<HTMLElement>('.slider__thumb');\n const thumbSize = thumb\n ? this.orientation === 'horizontal'\n ? thumb.offsetWidth\n : thumb.offsetHeight\n : 0;\n // Both alignment modes keep the complete thumb inside the control. Edge\n // alignment lets the rail span the control while center alignment insets\n // the rail to the same thumb-center travel.\n const inset = thumbSize / 2;\n\n if (this.orientation === 'vertical') {\n const travel = Math.max(1, rect.height - inset * 2);\n return Math.min(1, Math.max(0, (rect.bottom - inset - event.clientY) / travel));\n }\n\n const travel = Math.max(1, rect.width - inset * 2);\n const percent = (event.clientX - rect.left - inset) / travel;\n return Math.min(1, Math.max(0, percent));\n }\n\n private valueFromPointer(event: PointerEvent): number {\n return this.snap(this.safeMin + this.pointerPercent(event) * (this.safeMax - this.safeMin));\n }\n\n private closestThumbIndex(value: number, target: EventTarget | null): number {\n const targetElement =\n target instanceof HTMLElement ? target.closest<HTMLElement>('.slider__thumb') : null;\n if (targetElement?.dataset['index']) return Number(targetElement.dataset['index']);\n if (!this.isRange) return 0;\n\n const values = this.resolvedValues;\n const lowerDistance = Math.abs(value - values[0]);\n const upperDistance = Math.abs(value - values[1]);\n if (lowerDistance === upperDistance) return value >= values[0] ? 1 : 0;\n return lowerDistance < upperDistance ? 0 : 1;\n }\n\n private handlePointerDown = (event: PointerEvent) => {\n if (event.button !== 0 || this.isDisabled || this.readOnly) return;\n event.preventDefault();\n const value = this.valueFromPointer(event);\n const index = this.closestThumbIndex(value, event.target);\n this.activeThumbIndex = index;\n this.pointerId = event.pointerId;\n this.pointerStartValue = this.cloneValue(this.publicValue);\n this.dragging = true;\n this.setValueAt(index, value);\n this.controlEl?.setPointerCapture(event.pointerId);\n requestAnimationFrame(() => {\n const input = this.el.querySelectorAll<HTMLInputElement>('.slider__input')[index];\n input?.focus({ preventScroll: true });\n });\n };\n\n private handlePointerMove = (event: PointerEvent) => {\n if (this.pointerId !== event.pointerId || !this.dragging) return;\n event.preventDefault();\n this.setValueAt(this.activeThumbIndex, this.valueFromPointer(event));\n };\n\n private endPointerInteraction(event: PointerEvent, canceled: boolean) {\n if (this.pointerId !== event.pointerId) return;\n if (this.controlEl?.hasPointerCapture(event.pointerId))\n this.controlEl.releasePointerCapture(event.pointerId);\n this.pointerId = null;\n this.dragging = false;\n this.touched = true;\n if (!canceled && !this.valuesEqual(this.pointerStartValue, this.publicValue))\n this.commitIfChanged();\n }\n\n private renderThumb(value: number, index: number) {\n const inputId =\n index === 0\n ? (this.inputId ?? `${this.generatedId}-input`)\n : `${this.inputId ?? `${this.generatedId}-input`}-end`;\n const rangeLabel = index === 0 ? this.startLabel : this.endLabel;\n const labelledby = this.isRange\n ? undefined\n : (this.ariaLabelledby ?? (this.label ? this.labelId : this.externalLabelledby));\n const directLabel = this.isRange ? rangeLabel : labelledby ? undefined : this.ariaLabel;\n\n return (\n <div\n class={{\n slider__thumb: true,\n 'slider__thumb--active': index === this.activeThumbIndex,\n }}\n data-index={String(index)}\n style={{ '--ds-slider-thumb-pct': String(this.percent(value)) } as Record<string, string>}\n >\n <input\n class=\"slider__input\"\n type=\"range\"\n id={inputId}\n min={this.allowedMin(index)}\n max={this.allowedMax(index)}\n step={this.safeStep}\n value={value}\n disabled={this.isDisabled}\n aria-label={directLabel}\n aria-labelledby={labelledby}\n aria-describedby={this.ariaDescribedby}\n aria-valuetext={this.ariaValueText(value, index)}\n aria-orientation={this.orientation === 'vertical' ? 'vertical' : undefined}\n aria-readonly={this.readOnly ? 'true' : undefined}\n onInput={(event: Event) => this.handleNativeInput(event, index)}\n onChange={this.handleNativeChange}\n onKeyDown={this.handleKeyDown}\n onFocus={() => this.handleFocus(index)}\n onBlur={this.handleBlur}\n />\n <span class=\"slider__thumb-visual\" aria-hidden=\"true\">\n <span class=\"slider__thumb-wash\" />\n </span>\n </div>\n );\n }\n\n render() {\n const values = this.resolvedValues;\n const first = values[0];\n const last = values[values.length - 1];\n const firstInputId = this.inputId ?? `${this.generatedId}-input`;\n const dirty = !this.valuesEqual(this.publicValue, this.initialValue);\n const valueDisplay = values\n .map((value, index) => this.formattedValue(value, index))\n .join(` ${this.rangeSeparator} `);\n\n return (\n <Host\n aria-disabled={this.isDisabled ? 'true' : undefined}\n class={{\n slider: true,\n 'ds-field-stack': true,\n [`slider--${this.size}`]: true,\n [`slider--${this.orientation}`]: true,\n [`slider--thumb-${this.thumbAlignment}`]: true,\n 'slider--range': this.isRange,\n 'slider--readonly': this.readOnly,\n 'ds-control-inactive': this.isDisabled,\n }}\n data-orientation={this.orientation}\n data-disabled={this.isDisabled ? '' : undefined}\n data-readonly={this.readOnly ? '' : undefined}\n data-dragging={this.dragging ? '' : undefined}\n data-focused={this.focused ? '' : undefined}\n data-filled=\"\"\n data-dirty={dirty ? '' : undefined}\n data-touched={this.touched ? '' : undefined}\n data-valid={!this.isDisabled ? '' : undefined}\n onClick={this.handleHostClick}\n >\n {(this.label || this.showValue) && (\n <div class=\"slider__label-row\">\n {this.label && (\n <ds-text\n class=\"slider__label\"\n as=\"label\"\n variant=\"text-body-small\"\n color=\"primary\"\n emphasis\n for={firstInputId}\n textId={this.labelId}\n >\n {this.label}\n </ds-text>\n )}\n {this.showValue && (\n <ds-text\n class=\"slider__value\"\n as=\"span\"\n variant=\"text-body-small\"\n color=\"primary\"\n fontFeature=\"tabular-nums\"\n >\n {valueDisplay}\n </ds-text>\n )}\n </div>\n )}\n <div\n class=\"slider__control\"\n ref={element => {\n this.controlEl = element ?? null;\n }}\n style={\n {\n '--ds-slider-start-pct': String(this.isRange ? this.percent(first) : 0),\n '--ds-slider-end-pct': String(this.percent(last)),\n } as Record<string, string>\n }\n onPointerDown={this.handlePointerDown}\n onPointerMove={this.handlePointerMove}\n onPointerUp={(event: PointerEvent) => this.endPointerInteraction(event, false)}\n onPointerCancel={(event: PointerEvent) => this.endPointerInteraction(event, true)}\n >\n <div class=\"slider__rail\" aria-hidden=\"true\">\n <div class=\"slider__indicator\" />\n </div>\n {values.map((value, index) => this.renderThumb(value, index))}\n </div>\n </Host>\n );\n }\n}\n",
720
+ "content": "import {\n AttachInternals,\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Host,\n Method,\n Prop,\n State,\n Watch,\n} from '@stencil/core';\nimport {\n restoreNumberArrayFormState,\n restoreStringFormState,\n setFormControlValue,\n setRepeatedFormControlValue,\n} from '../../utils';\n\nexport interface SliderTick {\n value: number;\n label?: string;\n}\n\nexport type SliderValue = number | number[];\nexport type SliderSize = 'md' | 'sm' | 'xs';\nexport type SliderOrientation = 'horizontal' | 'vertical';\nexport type SliderThumbAlignment = 'edge' | 'center';\n\nlet sliderId = 0;\nlet sliderExternalLabelId = 0;\n\n@Component({\n tag: 'ds-slider',\n styleUrl: 'Slider.css',\n scoped: true,\n formAssociated: true,\n})\nexport class Slider {\n @Element() el!: HTMLElement;\n @AttachInternals() internals!: ElementInternals;\n\n /** Current value. Assign a two-number array through the JavaScript property for a range slider. */\n @Prop({ mutable: true }) value: SliderValue = 0;\n @Prop() min: number = 0;\n @Prop() max: number = 100;\n @Prop() step: number | 'any' = 1;\n /** Explicit ticks are the selectable snap points. Empty ticks with step='any' allow smooth adjustment. */\n @Prop() ticks: SliderTick[] = [];\n /** Minimum number of steps kept between two range thumbs. */\n @Prop() minStepsBetweenValues: number = 0;\n /** Visible field label. Supply aria-label when the label is intentionally hidden. */\n @Prop() label: string | undefined;\n /** Show the formatted current value beside the visible label. */\n @Prop() showValue: boolean = true;\n @Prop() size: SliderSize = 'md';\n @Prop() orientation: SliderOrientation = 'horizontal';\n /** Align the thumb edge with full-width rail endpoints, or its center with inset rail endpoints. */\n @Prop() thumbAlignment: SliderThumbAlignment = 'edge';\n @Prop({ reflect: true }) name: string | undefined;\n @Prop({ reflect: true }) form: string | undefined;\n @Prop({ reflect: true }) disabled: boolean = false;\n /** Keep the value focusable and submittable while preventing changes. */\n @Prop({ reflect: true }) readOnly: boolean = false;\n @Prop() isInactive: boolean = false;\n /** Direct accessible name for a single-thumb slider without a visible label. */\n @Prop({ attribute: 'aria-label' }) ariaLabel: string | null = null;\n /** Id references for a visible single-thumb slider label. */\n @Prop({ attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined;\n /** Id references for supporting guidance or error text. */\n @Prop({ attribute: 'aria-describedby' }) ariaDescribedby: string | undefined;\n /** Accessible label for the lower thumb in a range slider. */\n @Prop() startLabel: string = 'Minimum value';\n /** Accessible label for the upper thumb in a range slider. */\n @Prop() endLabel: string = 'Maximum value';\n /** Human-readable value text for a single slider or both range thumbs. */\n @Prop() valueText: string | undefined;\n /** Per-thumb human-readable value text for a range slider. Assign through the JavaScript property. */\n @Prop() valueTexts: string[] = [];\n /** Locale used by Intl.NumberFormat for the visible value. */\n @Prop() locale: string | undefined;\n /** Intl.NumberFormat options. Assign objects through the JavaScript property. */\n @Prop() formatOptions: Intl.NumberFormatOptions | undefined;\n @Prop() valuePrefix: string = '';\n @Prop() valueSuffix: string = '';\n @Prop() rangeSeparator: string = '–';\n /** Id applied to the first native range input. */\n @Prop() inputId: string | undefined;\n\n /** Emitted continuously while the value changes. */\n @Event() dsChange!: EventEmitter<SliderValue>;\n /** Emitted when a pointer or keyboard value change is committed. */\n @Event() dsCommit!: EventEmitter<SliderValue>;\n\n @State() private formDisabled = false;\n @State() private dragging = false;\n @State() private focused = false;\n @State() private touched = false;\n @State() private activeThumbIndex = 0;\n @State() private externalLabelledby: string | undefined;\n\n private readonly generatedId = `ds-slider-${++sliderId}`;\n private readonly labelId = `${this.generatedId}-label`;\n private initialValue: SliderValue = 0;\n private lastCommittedValue: SliderValue = 0;\n private pointerId: number | null = null;\n private pointerStartValue: SliderValue = 0;\n private controlEl: HTMLDivElement | null = null;\n\n componentWillLoad() {\n this.initialValue = this.cloneValue(this.publicValue);\n this.lastCommittedValue = this.cloneValue(this.publicValue);\n this.syncFormValue();\n }\n\n componentDidLoad() {\n this.syncNativeLabels();\n }\n\n @Watch('value')\n @Watch('min')\n @Watch('max')\n @Watch('step')\n @Watch('ticks')\n @Watch('minStepsBetweenValues')\n @Watch('name')\n @Watch('disabled')\n @Watch('isInactive')\n syncFormValue() {\n const values = this.resolvedValues;\n if (this.isRange) {\n setRepeatedFormControlValue(this.internals, this.name, values, {\n inactive: this.isDisabled,\n });\n } else {\n const value = String(values[0]);\n setFormControlValue(this.internals, this.name ? value : null, {\n inactive: this.isDisabled,\n state: value,\n });\n }\n }\n\n formDisabledCallback(disabled: boolean) {\n this.formDisabled = disabled;\n this.syncFormValue();\n }\n\n formResetCallback() {\n this.value = this.cloneValue(this.initialValue);\n this.lastCommittedValue = this.cloneValue(this.initialValue);\n this.dragging = false;\n this.focused = false;\n this.touched = false;\n }\n\n formStateRestoreCallback(state: string | File | FormData | null) {\n if (this.isRange) {\n const restored = restoreNumberArrayFormState(state, 2);\n this.value = restored.length ? restored : this.cloneValue(this.initialValue);\n } else {\n const restored = Number(restoreStringFormState(state, 'NaN'));\n if (Number.isFinite(restored)) this.value = restored;\n }\n this.lastCommittedValue = this.cloneValue(this.publicValue);\n }\n\n @Method()\n async setFocus(index: number = 0) {\n const inputs = this.el.querySelectorAll<HTMLInputElement>('.slider__input');\n inputs[Math.max(0, Math.min(index, inputs.length - 1))]?.focus();\n }\n\n private get isDisabled(): boolean {\n return this.disabled || this.isInactive || this.formDisabled;\n }\n\n private get isRange(): boolean {\n return Array.isArray(this.value);\n }\n\n private get safeStep(): number {\n const step = Number(this.step);\n return Number.isFinite(step) && step > 0 ? step : 1;\n }\n\n private get resolvedTicks(): SliderTick[] {\n const unique = new Map<number, SliderTick>();\n for (const tick of this.ticks) {\n if (Number.isFinite(tick.value) && tick.value >= this.safeMin && tick.value <= this.safeMax)\n unique.set(tick.value, tick);\n }\n return [...unique.values()].sort((a, b) => a.value - b.value);\n }\n\n private get safeMin(): number {\n return Number.isFinite(this.min) ? this.min : 0;\n }\n\n private get safeMax(): number {\n const minimum = this.safeMin;\n return Number.isFinite(this.max) && this.max > minimum ? this.max : minimum + this.safeStep;\n }\n\n private get minimumGap(): number {\n const steps = Number.isFinite(this.minStepsBetweenValues)\n ? Math.max(0, Math.floor(this.minStepsBetweenValues))\n : 0;\n const ticks = this.resolvedTicks;\n const span = ticks.length\n ? ticks[ticks.length - 1].value - ticks[0].value\n : this.safeMax - this.safeMin;\n return Math.min(span, steps * this.safeStep);\n }\n\n private get resolvedValues(): number[] {\n const minimum = this.safeMin;\n const maximum = this.safeMax;\n if (!this.isRange) return [this.snap(Number(this.value))];\n\n const raw = this.value as number[];\n let lower = this.snap(Number(raw[0] ?? minimum));\n let upper = this.snap(Number(raw[1] ?? maximum));\n if (lower > upper) [lower, upper] = [upper, lower];\n\n const gap = Math.min(this.minimumGap, maximum - minimum);\n if (upper - lower < gap) {\n upper = Math.min(maximum, this.snap(lower + gap));\n lower = Math.max(minimum, this.snap(upper - gap));\n const ticks = this.resolvedTicks;\n if (ticks.length && upper - lower < gap) {\n upper =\n ticks.find(tick => tick.value >= lower + gap)?.value ?? ticks[ticks.length - 1].value;\n lower =\n [...ticks].reverse().find(tick => tick.value <= upper - gap)?.value ?? ticks[0].value;\n }\n }\n return [lower, upper];\n }\n\n private get publicValue(): SliderValue {\n const values = this.resolvedValues;\n return this.isRange ? [...values] : values[0];\n }\n\n private cloneValue(value: SliderValue): SliderValue {\n return Array.isArray(value) ? [...value] : value;\n }\n\n private valuesEqual(a: SliderValue, b: SliderValue): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.length === b.length && a.every((value, index) => value === b[index]);\n }\n return !Array.isArray(a) && !Array.isArray(b) && a === b;\n }\n\n private decimalPlaces(value: number): number {\n const text = String(value).toLowerCase();\n if (text.includes('e-')) return Number(text.split('e-')[1]) || 0;\n return text.includes('.') ? text.split('.')[1].length : 0;\n }\n\n private snap(value: number, minimum = this.safeMin, maximum = this.safeMax): number {\n const ticks = this.resolvedTicks.filter(tick => tick.value >= minimum && tick.value <= maximum);\n if (ticks.length)\n return ticks.reduce((nearest, tick) =>\n Math.abs(tick.value - value) < Math.abs(nearest.value - value) ? tick : nearest\n ).value;\n if (this.step === 'any')\n return Math.min(maximum, Math.max(minimum, Number.isFinite(value) ? value : minimum));\n const candidate = Number.isFinite(value) ? value : minimum;\n const stepped = minimum + Math.round((candidate - minimum) / this.safeStep) * this.safeStep;\n const precision = Math.min(\n 10,\n Math.max(\n this.decimalPlaces(minimum),\n this.decimalPlaces(maximum),\n this.decimalPlaces(this.safeStep)\n )\n );\n return Number(Math.min(maximum, Math.max(minimum, stepped)).toFixed(precision));\n }\n\n private percent(value: number): number {\n return ((value - this.safeMin) / (this.safeMax - this.safeMin)) * 100;\n }\n\n private allowedMin(index: number, values = this.resolvedValues): number {\n return this.isRange && index === 1\n ? Math.min(this.safeMax, values[0] + this.minimumGap)\n : this.safeMin;\n }\n\n private allowedMax(index: number, values = this.resolvedValues): number {\n return this.isRange && index === 0\n ? Math.max(this.safeMin, values[1] - this.minimumGap)\n : this.safeMax;\n }\n\n private setValueAt(index: number, next: number): boolean {\n const previous = this.publicValue;\n const values = this.resolvedValues;\n const constrained = Math.min(\n this.allowedMax(index, values),\n Math.max(\n this.allowedMin(index, values),\n this.snap(next, this.allowedMin(index, values), this.allowedMax(index, values))\n )\n );\n values[index] = constrained;\n const nextValue: SliderValue = this.isRange ? [...values] : values[0];\n if (this.valuesEqual(previous, nextValue)) return false;\n\n this.value = nextValue;\n this.dsChange.emit(this.cloneValue(nextValue));\n return true;\n }\n\n private commitIfChanged() {\n const current = this.publicValue;\n if (this.valuesEqual(current, this.lastCommittedValue)) return;\n this.lastCommittedValue = this.cloneValue(current);\n this.dsCommit.emit(this.cloneValue(current));\n }\n\n private syncNativeLabels() {\n if (this.label || this.ariaLabel || this.ariaLabelledby || this.isRange) return;\n const ids = (Array.from(this.internals.labels) as HTMLLabelElement[]).map(label => {\n if (!label.id) label.id = `ds-slider-label-${++sliderExternalLabelId}`;\n return label.id;\n });\n if (ids.length) this.externalLabelledby = ids.join(' ');\n }\n\n private formattedValue(value: number, index: number): string {\n const authored =\n this.valueTexts[index] ??\n this.valueText ??\n this.resolvedTicks.find(tick => tick.value === value)?.label;\n if (authored) return authored;\n let number: string;\n try {\n number = new Intl.NumberFormat(this.locale, this.formatOptions).format(value);\n } catch {\n number = String(value);\n }\n return `${this.valuePrefix}${number}${this.valueSuffix}`;\n }\n\n private ariaValueText(value: number, index: number): string | undefined {\n if (\n this.resolvedTicks.some(tick => tick.value === value && tick.label) ||\n this.valueTexts[index] ||\n this.valueText ||\n this.valuePrefix ||\n this.valueSuffix ||\n this.formatOptions\n ) {\n return this.formattedValue(value, index);\n }\n return undefined;\n }\n\n private handleNativeInput = (event: Event, index: number) => {\n const input = event.target as HTMLInputElement;\n this.activeThumbIndex = index;\n if (this.readOnly || this.isDisabled) {\n input.value = String(this.resolvedValues[index]);\n return;\n }\n this.setValueAt(index, Number(input.value));\n };\n\n private handleNativeChange = () => {\n if (!this.readOnly && !this.isDisabled) this.commitIfChanged();\n };\n\n private handleKeyDown = (event: KeyboardEvent, index: number) => {\n const keys = [\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n 'Home',\n 'End',\n 'PageUp',\n 'PageDown',\n ];\n if (!this.readOnly && this.resolvedTicks.length && keys.includes(event.key)) {\n event.preventDefault();\n if (this.isDisabled) return;\n const ticks = this.resolvedTicks.filter(\n tick => tick.value >= this.allowedMin(index) && tick.value <= this.allowedMax(index)\n );\n const current = this.resolvedValues[index];\n const forward = ['ArrowRight', 'ArrowUp', 'PageUp'].includes(event.key);\n const next =\n event.key === 'Home'\n ? ticks[0]\n : event.key === 'End'\n ? ticks[ticks.length - 1]\n : forward\n ? ticks.find(tick => tick.value > current)\n : [...ticks].reverse().find(tick => tick.value < current);\n if (next && this.setValueAt(index, next.value)) this.commitIfChanged();\n return;\n }\n if (!this.readOnly) return;\n if (\n [\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n 'Home',\n 'End',\n 'PageUp',\n 'PageDown',\n ].includes(event.key)\n ) {\n event.preventDefault();\n }\n };\n\n private handleFocus = (index: number) => {\n this.activeThumbIndex = index;\n this.focused = true;\n };\n\n private handleBlur = (event: FocusEvent) => {\n const next = event.relatedTarget;\n if (next instanceof Node && this.el.contains(next)) return;\n this.focused = false;\n this.touched = true;\n };\n\n private handleHostClick = (event: MouseEvent) => {\n if (event.target !== this.el || this.isDisabled) return;\n const inputs = this.el.querySelectorAll<HTMLInputElement>('.slider__input');\n inputs[Math.min(this.activeThumbIndex, inputs.length - 1)]?.focus();\n };\n\n private pointerPercent(event: PointerEvent): number {\n const control = this.controlEl;\n if (!control) return 0;\n const rect = control.getBoundingClientRect();\n const thumb = this.el.querySelector<HTMLElement>('.slider__thumb');\n const thumbSize = thumb\n ? this.orientation === 'horizontal'\n ? thumb.offsetWidth\n : thumb.offsetHeight\n : 0;\n // Both alignment modes keep the complete thumb inside the control. Edge\n // alignment lets the rail span the control while center alignment insets\n // the rail to the same thumb-center travel.\n const inset = thumbSize / 2;\n\n if (this.orientation === 'vertical') {\n const travel = Math.max(1, rect.height - inset * 2);\n return Math.min(1, Math.max(0, (rect.bottom - inset - event.clientY) / travel));\n }\n\n const travel = Math.max(1, rect.width - inset * 2);\n const percent = (event.clientX - rect.left - inset) / travel;\n return Math.min(1, Math.max(0, percent));\n }\n\n private valueFromPointer(event: PointerEvent): number {\n return this.snap(this.safeMin + this.pointerPercent(event) * (this.safeMax - this.safeMin));\n }\n\n private closestThumbIndex(value: number, target: EventTarget | null): number {\n const targetElement =\n target instanceof HTMLElement ? target.closest<HTMLElement>('.slider__thumb') : null;\n if (targetElement?.dataset['index']) return Number(targetElement.dataset['index']);\n if (!this.isRange) return 0;\n\n const values = this.resolvedValues;\n const lowerDistance = Math.abs(value - values[0]);\n const upperDistance = Math.abs(value - values[1]);\n if (lowerDistance === upperDistance) return value >= values[0] ? 1 : 0;\n return lowerDistance < upperDistance ? 0 : 1;\n }\n\n private handlePointerDown = (event: PointerEvent) => {\n if (event.button !== 0 || this.isDisabled || this.readOnly) return;\n event.preventDefault();\n const value = this.valueFromPointer(event);\n const index = this.closestThumbIndex(value, event.target);\n this.activeThumbIndex = index;\n this.pointerId = event.pointerId;\n this.pointerStartValue = this.cloneValue(this.publicValue);\n this.dragging = true;\n this.setValueAt(index, value);\n this.controlEl?.setPointerCapture(event.pointerId);\n requestAnimationFrame(() => {\n const input = this.el.querySelectorAll<HTMLInputElement>('.slider__input')[index];\n input?.focus({ preventScroll: true });\n });\n };\n\n private handlePointerMove = (event: PointerEvent) => {\n if (this.pointerId !== event.pointerId || !this.dragging) return;\n event.preventDefault();\n this.setValueAt(this.activeThumbIndex, this.valueFromPointer(event));\n };\n\n private endPointerInteraction(event: PointerEvent, canceled: boolean) {\n if (this.pointerId !== event.pointerId) return;\n if (this.controlEl?.hasPointerCapture(event.pointerId))\n this.controlEl.releasePointerCapture(event.pointerId);\n this.pointerId = null;\n this.dragging = false;\n this.touched = true;\n if (!canceled && !this.valuesEqual(this.pointerStartValue, this.publicValue))\n this.commitIfChanged();\n }\n\n private renderThumb(value: number, index: number) {\n const inputId =\n index === 0\n ? (this.inputId ?? `${this.generatedId}-input`)\n : `${this.inputId ?? `${this.generatedId}-input`}-end`;\n const rangeLabel = index === 0 ? this.startLabel : this.endLabel;\n const labelledby = this.isRange\n ? undefined\n : (this.ariaLabelledby ?? (this.label ? this.labelId : this.externalLabelledby));\n const directLabel = this.isRange ? rangeLabel : labelledby ? undefined : this.ariaLabel;\n\n return (\n <div\n class={{\n slider__thumb: true,\n 'slider__thumb--active': index === this.activeThumbIndex,\n }}\n data-index={String(index)}\n style={{ '--ds-slider-thumb-pct': String(this.percent(value)) } as Record<string, string>}\n >\n <input\n class=\"slider__input\"\n type=\"range\"\n id={inputId}\n min={this.allowedMin(index)}\n max={this.allowedMax(index)}\n step={this.resolvedTicks.length || this.step === 'any' ? 'any' : this.safeStep}\n value={value}\n disabled={this.isDisabled}\n aria-label={directLabel}\n aria-labelledby={labelledby}\n aria-describedby={this.ariaDescribedby}\n aria-valuetext={this.ariaValueText(value, index)}\n aria-orientation={this.orientation === 'vertical' ? 'vertical' : undefined}\n aria-readonly={this.readOnly ? 'true' : undefined}\n onInput={(event: Event) => this.handleNativeInput(event, index)}\n onChange={this.handleNativeChange}\n onKeyDown={event => this.handleKeyDown(event, index)}\n onFocus={() => this.handleFocus(index)}\n onBlur={this.handleBlur}\n />\n <span class=\"slider__thumb-visual\" aria-hidden=\"true\">\n <span class=\"slider__thumb-wash\" />\n </span>\n </div>\n );\n }\n\n render() {\n const values = this.resolvedValues;\n const first = values[0];\n const last = values[values.length - 1];\n const firstInputId = this.inputId ?? `${this.generatedId}-input`;\n const dirty = !this.valuesEqual(this.publicValue, this.initialValue);\n const valueDisplay = values\n .map((value, index) => this.formattedValue(value, index))\n .join(` ${this.rangeSeparator} `);\n\n return (\n <Host\n aria-disabled={this.isDisabled ? 'true' : undefined}\n class={{\n slider: true,\n 'ds-field-stack': true,\n [`slider--${this.size}`]: true,\n [`slider--${this.orientation}`]: true,\n [`slider--thumb-${this.thumbAlignment}`]: true,\n 'slider--range': this.isRange,\n 'slider--ticks': this.resolvedTicks.length > 0,\n 'slider--tick-labels': this.resolvedTicks.some(tick => Boolean(tick.label)),\n 'slider--readonly': this.readOnly,\n 'ds-control-inactive': this.isDisabled,\n }}\n data-orientation={this.orientation}\n data-disabled={this.isDisabled ? '' : undefined}\n data-readonly={this.readOnly ? '' : undefined}\n data-dragging={this.dragging ? '' : undefined}\n data-focused={this.focused ? '' : undefined}\n data-filled=\"\"\n data-dirty={dirty ? '' : undefined}\n data-touched={this.touched ? '' : undefined}\n data-valid={!this.isDisabled ? '' : undefined}\n onClick={this.handleHostClick}\n >\n {(this.label || this.showValue) && (\n <div class=\"slider__label-row\">\n {this.label && (\n <ds-text\n class=\"slider__label\"\n as=\"label\"\n variant=\"text-body-small\"\n color=\"primary\"\n emphasis\n for={firstInputId}\n textId={this.labelId}\n >\n {this.label}\n </ds-text>\n )}\n {this.showValue && (\n <ds-text\n class=\"slider__value\"\n as=\"span\"\n variant=\"text-body-small\"\n color=\"primary\"\n fontFeature=\"tabular-nums\"\n >\n {valueDisplay}\n </ds-text>\n )}\n </div>\n )}\n <div\n class=\"slider__control\"\n ref={element => {\n this.controlEl = element ?? null;\n }}\n style={\n {\n '--ds-slider-start-pct': String(this.isRange ? this.percent(first) : 0),\n '--ds-slider-end-pct': String(this.percent(last)),\n } as Record<string, string>\n }\n onPointerDown={this.handlePointerDown}\n onPointerMove={this.handlePointerMove}\n onPointerUp={(event: PointerEvent) => this.endPointerInteraction(event, false)}\n onPointerCancel={(event: PointerEvent) => this.endPointerInteraction(event, true)}\n >\n <div class=\"slider__rail\" aria-hidden=\"true\">\n <div class=\"slider__indicator\" />\n </div>\n {this.resolvedTicks.map(tick => (\n <span\n class=\"slider__tick\"\n data-edge={\n tick.value === this.safeMin\n ? 'start'\n : tick.value === this.safeMax\n ? 'end'\n : undefined\n }\n aria-hidden=\"true\"\n style={{ '--ds-slider-tick-pct': String(this.percent(tick.value)) }}\n >\n <span class=\"slider__tick-mark\" />\n {tick.label && (\n <ds-text\n class=\"slider__tick-label\"\n as=\"span\"\n variant=\"text-caption\"\n color=\"secondary\"\n >\n {tick.label}\n </ds-text>\n )}\n </span>\n ))}\n {values.map((value, index) => this.renderThumb(value, index))}\n </div>\n </Host>\n );\n }\n}\n",
701
721
  "type": "registry:ui"
702
722
  }
703
723
  ]
@@ -227,8 +227,8 @@
227
227
  "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: options, sections.",
228
228
  "peerDependencies": {
229
229
  "required": [
230
- "@ds-mo/tokens ^6.5.1",
231
- "@ds-mo/icons ^8.1.0"
230
+ "@ds-mo/tokens ^6.5.2",
231
+ "@ds-mo/icons ^8.1.1"
232
232
  ],
233
233
  "frameworks": "Custom Elements; React 18/19 wrappers; Vue 3 wrappers; Angular 19-22 standalone adapters."
234
234
  }
@@ -378,8 +378,8 @@
378
378
  },
379
379
  "peerDependencies": {
380
380
  "required": [
381
- "@ds-mo/tokens ^6.5.1",
382
- "@ds-mo/icons ^8.1.0"
381
+ "@ds-mo/tokens ^6.5.2",
382
+ "@ds-mo/icons ^8.1.1"
383
383
  ],
384
384
  "frameworks": "Custom Elements; React 18/19 wrappers; Vue 3 wrappers; Angular 19-22 standalone adapters."
385
385
  }
@@ -346,8 +346,8 @@
346
346
  "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: tabs.",
347
347
  "peerDependencies": {
348
348
  "required": [
349
- "@ds-mo/tokens ^6.5.1",
350
- "@ds-mo/icons ^8.1.0"
349
+ "@ds-mo/tokens ^6.5.2",
350
+ "@ds-mo/icons ^8.1.1"
351
351
  ],
352
352
  "frameworks": "Custom Elements; React 18/19 wrappers; Vue 3 wrappers; Angular 19-22 standalone adapters."
353
353
  }