@adia-ai/web-components 0.8.40 → 0.8.41

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 (378) hide show
  1. package/CHANGELOG.md +50 -3
  2. package/MIGRATION.md +1042 -16
  3. package/README.md +25 -30
  4. package/USAGE.md +26 -0
  5. package/bin/audit-template-children.mjs +556 -0
  6. package/components/accordion/accordion-item.a2ui.json +4 -0
  7. package/components/accordion/accordion-item.yaml +2 -0
  8. package/components/accordion/accordion.a2ui.json +4 -0
  9. package/components/accordion/accordion.yaml +2 -0
  10. package/components/action-list/action-item.a2ui.json +24 -2
  11. package/components/action-list/action-item.yaml +28 -3
  12. package/components/action-list/action-list.a2ui.json +6 -1
  13. package/components/action-list/action-list.class.js +52 -11
  14. package/components/action-list/action-list.css +43 -3
  15. package/components/action-list/action-list.d.ts +4 -2
  16. package/components/action-list/action-list.yaml +5 -0
  17. package/components/adia-mark/adia-mark.a2ui.json +1 -0
  18. package/components/adia-wordmark/adia-wordmark.a2ui.json +1 -0
  19. package/components/agent-artifact/agent-artifact.a2ui.json +1 -0
  20. package/components/agent-feedback-bar/agent-feedback-bar.a2ui.json +6 -5
  21. package/components/agent-feedback-bar/agent-feedback-bar.yaml +6 -2
  22. package/components/agent-questions/agent-questions.a2ui.json +1 -0
  23. package/components/agent-reasoning/agent-reasoning.a2ui.json +6 -5
  24. package/components/agent-reasoning/agent-reasoning.yaml +6 -2
  25. package/components/agent-suggestions/agent-suggestions.a2ui.json +11 -2
  26. package/components/agent-suggestions/agent-suggestions.class.js +2 -1
  27. package/components/agent-suggestions/agent-suggestions.d.ts +4 -4
  28. package/components/agent-suggestions/agent-suggestions.yaml +4 -2
  29. package/components/agent-trace/agent-trace.a2ui.json +6 -5
  30. package/components/agent-trace/agent-trace.yaml +6 -2
  31. package/components/alert/alert.a2ui.json +1 -0
  32. package/components/alert/alert.css +1 -1
  33. package/components/anchor-bar/anchor-bar.a2ui.json +1 -0
  34. package/components/aside/aside.a2ui.json +1 -0
  35. package/components/avatar/avatar-group.a2ui.json +7 -1
  36. package/components/avatar/avatar-group.yaml +1 -0
  37. package/components/avatar/avatar.a2ui.json +12 -11
  38. package/components/avatar/avatar.d.ts +1 -1
  39. package/components/avatar/avatar.yaml +4 -4
  40. package/components/badge/badge.a2ui.json +1 -0
  41. package/components/block/block.a2ui.json +1 -0
  42. package/components/blockquote/blockquote.a2ui.json +1 -0
  43. package/components/breadcrumb/breadcrumb.a2ui.json +1 -0
  44. package/components/button/button.a2ui.json +1 -3
  45. package/components/button/button.yaml +1 -3
  46. package/components/calendar-grid/calendar-grid.a2ui.json +1 -0
  47. package/components/calendar-grid/calendar-grid.class.js +2 -1
  48. package/components/calendar-picker/calendar-picker.a2ui.json +143 -24
  49. package/components/calendar-picker/calendar-picker.class.js +490 -197
  50. package/components/calendar-picker/calendar-picker.css +120 -171
  51. package/components/calendar-picker/calendar-picker.yaml +225 -47
  52. package/components/canvas/canvas.a2ui.json +6 -5
  53. package/components/canvas/canvas.d.ts +37 -0
  54. package/components/canvas/canvas.js +72 -3
  55. package/components/canvas/canvas.yaml +6 -2
  56. package/components/card/card.a2ui.json +25 -2
  57. package/components/card/card.class.js +3 -0
  58. package/components/card/card.css +31 -1
  59. package/components/card/card.d.ts +2 -2
  60. package/components/card/card.examples.md +3 -3
  61. package/components/card/card.yaml +28 -4
  62. package/components/chart/chart.a2ui.json +9 -4
  63. package/components/chart/chart.class.js +6 -6
  64. package/components/chart/chart.css +6 -4
  65. package/components/chart/chart.d.ts +1 -1
  66. package/components/chart/chart.yaml +5 -3
  67. package/components/chart-legend/chart-legend.a2ui.json +1 -0
  68. package/components/chat-thread/chat-input.a2ui.json +1 -0
  69. package/components/chat-thread/chat-thread.a2ui.json +10 -9
  70. package/components/chat-thread/chat-thread.yaml +13 -20
  71. package/components/check/check.a2ui.json +10 -9
  72. package/components/check/check.yaml +4 -4
  73. package/components/code/code.a2ui.json +1 -0
  74. package/components/col/col.a2ui.json +1 -0
  75. package/components/color-input/color-input.a2ui.json +1 -0
  76. package/components/color-picker/color-picker.a2ui.json +1 -0
  77. package/components/combobox/combobox.a2ui.json +3 -2
  78. package/components/combobox/combobox.yaml +2 -2
  79. package/components/command/command.a2ui.json +12 -10
  80. package/components/command/command.class.js +3 -2
  81. package/components/command/command.yaml +17 -4
  82. package/components/context-menu/context-menu.a2ui.json +1 -0
  83. package/components/date-range-picker/date-range-picker.a2ui.json +2 -1
  84. package/components/date-range-picker/date-range-picker.yaml +1 -1
  85. package/components/datetime-picker/datetime-picker.a2ui.json +15 -108
  86. package/components/datetime-picker/datetime-picker.class.js +37 -690
  87. package/components/datetime-picker/datetime-picker.css +11 -183
  88. package/components/datetime-picker/datetime-picker.d.ts +4 -5
  89. package/components/datetime-picker/datetime-picker.yaml +44 -135
  90. package/components/demo-toggle/demo-toggle.a2ui.json +1 -0
  91. package/components/demo-toggle/demo-toggle.css +1 -1
  92. package/components/description-list/description-list.a2ui.json +1 -0
  93. package/components/display-field/display-field.a2ui.json +1 -0
  94. package/components/divider/divider.a2ui.json +1 -0
  95. package/components/drawer/drawer.a2ui.json +1 -3
  96. package/components/drawer/drawer.css +1 -1
  97. package/components/drawer/drawer.yaml +0 -2
  98. package/components/drilldown/drilldown.a2ui.json +22 -20
  99. package/components/drilldown/drilldown.class.js +4 -3
  100. package/components/drilldown/drilldown.css +6 -6
  101. package/components/drilldown/drilldown.yaml +40 -9
  102. package/components/embed/embed.a2ui.json +6 -5
  103. package/components/embed/embed.yaml +2 -2
  104. package/components/empty-state/empty-state.a2ui.json +1 -0
  105. package/components/feed/feed-item.a2ui.json +25 -5
  106. package/components/feed/feed-item.yaml +28 -7
  107. package/components/feed/feed.a2ui.json +9 -2
  108. package/components/feed/feed.class.js +19 -12
  109. package/components/feed/feed.css +8 -8
  110. package/components/feed/feed.yaml +14 -1
  111. package/components/field/field.a2ui.json +1 -0
  112. package/components/field/field.examples.md +1 -1
  113. package/components/fields/fields.a2ui.json +1 -0
  114. package/components/fields/fields.examples.md +1 -1
  115. package/components/footer/footer.a2ui.json +1 -0
  116. package/components/frame/frame.a2ui.json +1 -0
  117. package/components/grid/grid.a2ui.json +1 -0
  118. package/components/header/header.a2ui.json +3 -2
  119. package/components/header/header.yaml +3 -3
  120. package/components/heatmap/heatmap.a2ui.json +2 -1
  121. package/components/heatmap/heatmap.class.js +1 -1
  122. package/components/heatmap/heatmap.css +4 -4
  123. package/components/heatmap/heatmap.yaml +1 -1
  124. package/components/icon/icon.a2ui.json +1 -0
  125. package/components/image/image.a2ui.json +28 -14
  126. package/components/image/image.class.js +38 -23
  127. package/components/image/image.css +18 -8
  128. package/components/image/image.d.ts +2 -2
  129. package/components/image/image.examples.md +3 -3
  130. package/components/image/image.yaml +23 -7
  131. package/components/inline-edit/inline-edit.a2ui.json +1 -0
  132. package/components/inline-message/inline-message.a2ui.json +3 -1
  133. package/components/inline-message/inline-message.class.js +3 -1
  134. package/components/inline-message/inline-message.d.ts +2 -2
  135. package/components/inline-message/inline-message.yaml +2 -1
  136. package/components/input/input.a2ui.json +66 -16
  137. package/components/input/input.class.js +64 -7
  138. package/components/input/input.css +14 -14
  139. package/components/input/input.d.ts +9 -4
  140. package/components/input/input.yaml +83 -10
  141. package/components/inspector/inspector.a2ui.json +1 -0
  142. package/components/integration-card/integration-card.a2ui.json +1 -0
  143. package/components/kbd/kbd.a2ui.json +1 -0
  144. package/components/link/link.a2ui.json +2 -1
  145. package/components/link/link.yaml +1 -1
  146. package/components/list/list-item.a2ui.json +9 -0
  147. package/components/list/list-item.yaml +12 -0
  148. package/components/list/list.a2ui.json +9 -3
  149. package/components/list/list.class.js +14 -1
  150. package/components/list/list.css +12 -1
  151. package/components/list/list.d.ts +7 -5
  152. package/components/list/list.yaml +16 -6
  153. package/components/list-window/list-window.a2ui.json +1 -0
  154. package/components/list-window/list-window.class.js +2 -1
  155. package/components/loading-overlay/loading-overlay.a2ui.json +1 -0
  156. package/components/mark/mark.a2ui.json +2 -1
  157. package/components/mark/mark.yaml +1 -1
  158. package/components/menu/menu-divider.a2ui.json +1 -0
  159. package/components/menu/menu-item.a2ui.json +3 -1
  160. package/components/menu/menu-item.yaml +6 -0
  161. package/components/menu/menu-label.a2ui.json +1 -0
  162. package/components/menu/menu.a2ui.json +3 -2
  163. package/components/menu/menu.class.js +2 -2
  164. package/components/menu/menu.d.ts +2 -2
  165. package/components/menu/menu.yaml +3 -3
  166. package/components/modal/modal.a2ui.json +1 -0
  167. package/components/nav/nav.a2ui.json +1 -0
  168. package/components/nav/nav.class.js +14 -3
  169. package/components/nav-group/nav-group.a2ui.json +1 -0
  170. package/components/nav-group/nav-group.class.js +3 -1
  171. package/components/nav-item/nav-item.a2ui.json +1 -0
  172. package/components/noodles/noodles.a2ui.json +1 -0
  173. package/components/noodles/noodles.class.js +5 -1
  174. package/components/number-format/number-format.a2ui.json +1 -0
  175. package/components/option-card/option-card.a2ui.json +1 -0
  176. package/components/otp-input/otp-input.a2ui.json +3 -2
  177. package/components/otp-input/otp-input.yaml +9 -2
  178. package/components/page/page.a2ui.json +13 -0
  179. package/components/page/page.d.ts +1 -1
  180. package/components/page/page.yaml +1 -0
  181. package/components/pagination/pagination.a2ui.json +1 -0
  182. package/components/pagination/pagination.class.js +3 -2
  183. package/components/pane/pane.a2ui.json +6 -0
  184. package/components/pane/pane.class.js +3 -3
  185. package/components/pane/pane.css +2 -2
  186. package/components/pane/pane.yaml +3 -0
  187. package/components/password-strength/password-strength.a2ui.json +1 -0
  188. package/components/pipeline-status/pipeline-status.a2ui.json +1 -0
  189. package/components/popover/popover.a2ui.json +7 -6
  190. package/components/popover/popover.class.js +2 -2
  191. package/components/popover/popover.d.ts +2 -2
  192. package/components/popover/popover.yaml +4 -4
  193. package/components/preview/preview.a2ui.json +1 -0
  194. package/components/preview/preview.class.js +5 -1
  195. package/components/progress/progress.a2ui.json +47 -24
  196. package/components/progress/progress.class.js +66 -11
  197. package/components/progress/progress.css +44 -26
  198. package/components/progress/progress.d.ts +7 -5
  199. package/components/progress/progress.examples.md +2 -2
  200. package/components/progress/progress.yaml +235 -53
  201. package/components/progress-row/progress-row.a2ui.json +16 -12
  202. package/components/progress-row/progress-row.d.ts +2 -2
  203. package/components/progress-row/progress-row.examples.md +2 -14
  204. package/components/progress-row/progress-row.yaml +28 -36
  205. package/components/qr-code/qr-code.a2ui.json +3 -2
  206. package/components/qr-code/qr-code.class.js +4 -4
  207. package/components/qr-code/qr-code.css +1 -1
  208. package/components/qr-code/qr-code.yaml +5 -3
  209. package/components/radio/radio.a2ui.json +8 -7
  210. package/components/radio/radio.class.js +8 -0
  211. package/components/radio/radio.yaml +3 -3
  212. package/components/radio-group/radio-group.a2ui.json +5 -3
  213. package/components/radio-group/radio-group.class.js +11 -0
  214. package/components/radio-group/radio-group.yaml +7 -1
  215. package/components/range/range.a2ui.json +6 -0
  216. package/components/range/range.class.js +2 -2
  217. package/components/range/range.css +2 -2
  218. package/components/range/range.yaml +3 -0
  219. package/components/rating/rating.a2ui.json +1 -0
  220. package/components/relative-time/relative-time.a2ui.json +1 -0
  221. package/components/richtext/richtext.a2ui.json +2 -1
  222. package/components/richtext/richtext.yaml +1 -1
  223. package/components/row/row.a2ui.json +1 -0
  224. package/components/search/search.a2ui.json +1 -0
  225. package/components/search/search.class.js +4 -1
  226. package/components/section/section.a2ui.json +1 -0
  227. package/components/segment/segment.a2ui.json +21 -10
  228. package/components/segment/segment.css +15 -0
  229. package/components/segment/segment.d.ts +2 -1
  230. package/components/segment/segment.yaml +20 -13
  231. package/components/segmented/segmented.a2ui.json +36 -7
  232. package/components/segmented/segmented.class.js +113 -22
  233. package/components/segmented/segmented.css +3 -0
  234. package/components/segmented/segmented.d.ts +3 -1
  235. package/components/segmented/segmented.yaml +80 -8
  236. package/components/select/select.a2ui.json +18 -13
  237. package/components/select/select.class.js +61 -37
  238. package/components/select/select.css +15 -13
  239. package/components/select/select.yaml +18 -7
  240. package/components/skeleton/skeleton.a2ui.json +8 -7
  241. package/components/skeleton/skeleton.class.js +8 -7
  242. package/components/skeleton/skeleton.css +21 -6
  243. package/components/skeleton/skeleton.d.ts +2 -2
  244. package/components/skeleton/skeleton.examples.md +2 -2
  245. package/components/skeleton/skeleton.yaml +3 -2
  246. package/components/skip-nav/skip-nav.a2ui.json +1 -0
  247. package/components/slider/slider.a2ui.json +6 -0
  248. package/components/slider/slider.class.js +20 -3
  249. package/components/slider/slider.css +2 -2
  250. package/components/slider/slider.yaml +3 -0
  251. package/components/spinner/spinner.a2ui.json +1 -0
  252. package/components/stack/stack.a2ui.json +1 -0
  253. package/components/stat/stat.a2ui.json +1 -0
  254. package/components/stat/stat.js +2 -2
  255. package/components/step-progress/step-progress.a2ui.json +1 -0
  256. package/components/step-progress/step-progress.yaml +1 -1
  257. package/components/stepper/stepper-item.a2ui.json +7 -3
  258. package/components/stepper/stepper-item.yaml +15 -5
  259. package/components/stepper/stepper.a2ui.json +5 -1
  260. package/components/stepper/stepper.class.js +31 -16
  261. package/components/stepper/stepper.d.ts +1 -1
  262. package/components/stepper/stepper.yaml +4 -2
  263. package/components/stream/stream.a2ui.json +1 -0
  264. package/components/swatch/swatch.a2ui.json +1 -0
  265. package/components/swiper/swiper.a2ui.json +1 -0
  266. package/components/swiper/swiper.class.js +5 -1
  267. package/components/switch/switch.a2ui.json +12 -11
  268. package/components/switch/switch.css +1 -1
  269. package/components/switch/switch.yaml +6 -6
  270. package/components/table/table.a2ui.json +1 -0
  271. package/components/table/table.class.js +14 -12
  272. package/components/table/table.css +11 -9
  273. package/components/table-toolbar/table-toolbar.a2ui.json +1 -0
  274. package/components/table-toolbar/table-toolbar.class.js +38 -19
  275. package/components/table-toolbar/table-toolbar.css +1 -1
  276. package/components/tabs/tab.a2ui.json +9 -0
  277. package/components/tabs/tab.js +4 -0
  278. package/components/tabs/tab.yaml +15 -0
  279. package/components/tabs/tabs.a2ui.json +9 -4
  280. package/components/tabs/tabs.class.js +13 -1
  281. package/components/tabs/tabs.css +8 -0
  282. package/components/tabs/tabs.d.ts +2 -0
  283. package/components/tabs/tabs.yaml +9 -2
  284. package/components/tag/tag.a2ui.json +1 -0
  285. package/components/tags-input/tags-input.a2ui.json +22 -17
  286. package/components/tags-input/tags-input.class.js +13 -11
  287. package/components/tags-input/tags-input.css +10 -6
  288. package/components/tags-input/tags-input.d.ts +16 -7
  289. package/components/tags-input/tags-input.examples.md +2 -2
  290. package/components/tags-input/tags-input.yaml +25 -8
  291. package/components/text/text.a2ui.json +6 -5
  292. package/components/text/text.css +10 -5
  293. package/components/text/text.d.ts +2 -2
  294. package/components/text/text.yaml +9 -4
  295. package/components/textarea/textarea.a2ui.json +2 -1
  296. package/components/textarea/textarea.yaml +1 -1
  297. package/components/theme-provider/theme-provider.a2ui.json +2 -1
  298. package/components/theme-provider/theme-provider.d.ts +5 -3
  299. package/components/theme-provider/theme-provider.yaml +5 -3
  300. package/components/time-picker/time-picker.a2ui.json +1 -0
  301. package/components/time-picker/time-picker.class.js +4 -2
  302. package/components/timeline/timeline-item.a2ui.json +26 -3
  303. package/components/timeline/timeline-item.yaml +22 -7
  304. package/components/timeline/timeline.a2ui.json +4 -0
  305. package/components/timeline/timeline.class.js +29 -18
  306. package/components/timeline/timeline.d.ts +3 -3
  307. package/components/timeline/timeline.yaml +2 -0
  308. package/components/toast/toast.a2ui.json +10 -3
  309. package/components/toast/toast.yaml +20 -13
  310. package/components/toc/toc.a2ui.json +1 -0
  311. package/components/toggle-group/toggle-group.a2ui.json +7 -3
  312. package/components/toggle-group/toggle-group.class.js +40 -1
  313. package/components/toggle-group/toggle-group.css +6 -1
  314. package/components/toggle-group/toggle-group.d.ts +2 -2
  315. package/components/toggle-group/toggle-group.yaml +21 -12
  316. package/components/toggle-group/toggle-option.a2ui.json +7 -3
  317. package/components/toggle-group/toggle-option.yaml +13 -7
  318. package/components/toggle-scheme/toggle-scheme.a2ui.json +2 -1
  319. package/components/toggle-scheme/toggle-scheme.yaml +1 -1
  320. package/components/toolbar/toolbar-group.a2ui.json +1 -0
  321. package/components/toolbar/toolbar.a2ui.json +1 -0
  322. package/components/toolbar/toolbar.class.js +3 -0
  323. package/components/tooltip/tooltip.a2ui.json +1 -0
  324. package/components/tour/tour-step.a2ui.json +4 -0
  325. package/components/tour/tour-step.yaml +2 -0
  326. package/components/tour/tour.a2ui.json +4 -0
  327. package/components/tour/tour.yaml +2 -0
  328. package/components/tree/tree-item.a2ui.json +5 -0
  329. package/components/tree/tree-item.yaml +3 -0
  330. package/components/tree/tree.a2ui.json +4 -0
  331. package/components/tree/tree.class.js +2 -1
  332. package/components/tree/tree.yaml +2 -0
  333. package/components/upload/upload.a2ui.json +8 -1
  334. package/components/upload/upload.class.js +35 -5
  335. package/components/upload/upload.css +28 -0
  336. package/components/upload/upload.d.ts +16 -0
  337. package/components/upload/upload.yaml +27 -7
  338. package/components/visually-hidden/visually-hidden.a2ui.json +1 -0
  339. package/core/dom.d.ts +11 -0
  340. package/core/dom.js +34 -0
  341. package/core/form.js +7 -0
  342. package/core/index.d.ts +1 -0
  343. package/core/index.js +1 -0
  344. package/core/responsive.js +16 -4
  345. package/core/template.js +2 -1
  346. package/custom-elements.json +437 -489
  347. package/dist/host.min.css +1 -1
  348. package/dist/host.sheet.js +1 -1
  349. package/dist/theme-provider.min.js +5 -5
  350. package/dist/web-components.min.css +1 -1
  351. package/dist/web-components.min.js +91 -104
  352. package/dist/web-components.sheet.js +1 -1
  353. package/package.json +4 -2
  354. package/patterns/conversion-funnel/conversion-funnel.examples.html +15 -15
  355. package/patterns/inline-dialog/inline-dialog.examples.html +2 -2
  356. package/patterns/inline-dialog/inline-dialog.html +4 -0
  357. package/patterns/timezone-selector/timezone-selector.examples.html +1 -1
  358. package/patterns/timezone-selector/timezone-selector.html +2 -2
  359. package/styles/api/text.css +7 -0
  360. package/traits/_catalog.json +129 -41
  361. package/traits/anchor-positioning/anchor-positioning.js +1 -0
  362. package/traits/announcer/announcer.js +1 -0
  363. package/traits/arrow-grid-nav/arrow-grid-nav.js +1 -0
  364. package/traits/attention-pulse/attention-pulse.js +1 -0
  365. package/traits/count-up/count-up.js +1 -0
  366. package/traits/define.js +78 -0
  367. package/traits/focus-restore/focus-restore.js +2 -1
  368. package/traits/haptic-feedback/haptic-feedback.js +1 -0
  369. package/traits/input-mask/input-mask.js +1 -0
  370. package/traits/intersection-observer/intersection-observer.js +1 -0
  371. package/traits/layout-animation/layout-animation.js +1 -0
  372. package/traits/noise-texture/noise-texture.js +1 -0
  373. package/traits/resize-observer/resize-observer.js +1 -0
  374. package/traits/scroll-progress/scroll-progress.js +1 -0
  375. package/traits/snap-to-grid/snap-to-grid.js +1 -0
  376. package/traits/sound-feedback/sound-feedback.js +1 -0
  377. package/traits/spring-animate/spring-animate.js +1 -0
  378. package/traits/validation/validation.js +1 -0
@@ -147,7 +147,7 @@ props:
147
147
  form for narrow triggers (filter bars) where wrapping chips
148
148
  would balloon the control.
149
149
  type: string
150
- default: null
150
+ default: ''
151
151
  reflect: true
152
152
  min:
153
153
  description: |
@@ -251,17 +251,28 @@ usage: |-
251
251
  </script>
252
252
  ```
253
253
  slots:
254
- label:
255
- description: Label element above the trigger
256
- listbox:
257
- description: Popover container for options (role=listbox)
258
254
  trigger:
259
- description: Button that opens the listbox
255
+ description: >-
256
+ Button that opens the listbox. Stamped only if no consumer-authored
257
+ [slot="trigger"] is already present at first render (adopt-or-stamp) —
258
+ a genuine light-DOM insertion point.
259
+ parts:
260
+ listbox:
261
+ description: >-
262
+ Popover container for options (role=listbox) — template-owned anatomy
263
+ part, not a light-DOM insertion point (gh#1454). Its contents are
264
+ always wiped (`innerHTML = ''`) and rebuilt wholesale from `.options`/
265
+ parsed `<option>` children on every options render.
260
266
  hint:
261
267
  description: >-
262
268
  Override slot for hint markup richer than the plain [hint] attribute
263
269
  string (inline links, code spans). Renders beneath the trigger at
264
- body-subtle typography. Mutually exclusive with [hint].
270
+ body-subtle typography. Mutually exclusive with [hint] per this
271
+ description, but template-owned in practice (gh#1454): the trigger
272
+ stamp is an unconditional `this.innerHTML = …` with no
273
+ capture-before-wipe for `hint` (unlike `leading`/`trailing` on
274
+ input-ui), so any pre-existing [slot="hint"] content is discarded, not
275
+ adopted, on first render.
265
276
  states:
266
277
  - name: idle
267
278
  description: Default, ready for interaction.
@@ -16,13 +16,8 @@
16
16
  "component": {
17
17
  "const": "Skeleton"
18
18
  },
19
- "height": {
20
- "description": "Height of the placeholder.",
21
- "type": "string",
22
- "default": "1.2em"
23
- },
24
- "radius": {
25
- "description": "Border radius",
19
+ "cornerRadius": {
20
+ "description": "Border radius. Renamed from `[radius]` (gh#1335) — a preset-enum can't share a name with the global Enum·preset `[radius]` attribute (`sharp`/`rounded`/`round`), whose vocabulary is unrelated (ADR-0053); mirrors chart-ui's own `[corner-radius]` fix (ADR-0054).",
26
21
  "type": "string",
27
22
  "enum": [
28
23
  "none",
@@ -33,6 +28,11 @@
33
28
  ],
34
29
  "default": "sm"
35
30
  },
31
+ "height": {
32
+ "description": "Height of the placeholder.",
33
+ "type": "string",
34
+ "default": "1.2em"
35
+ },
36
36
  "static": {
37
37
  "description": "When true, suppress the shimmer animation.",
38
38
  "type": "boolean",
@@ -68,6 +68,7 @@
68
68
  "shimmer"
69
69
  ],
70
70
  "name": "UISkeleton",
71
+ "parts": {},
71
72
  "related": [
72
73
  "EmptyState",
73
74
  "Card",
@@ -12,8 +12,8 @@
12
12
  */
13
13
 
14
14
  /**
15
- * <skeleton-ui width="200px" height="1.2em" radius="sm"></skeleton-ui>
16
- * <skeleton-ui width="100%" height="3rem" radius="md" static></skeleton-ui>
15
+ * <skeleton-ui width="200px" height="1.2em" corner-radius="sm"></skeleton-ui>
16
+ * <skeleton-ui width="100%" height="3rem" corner-radius="md" static></skeleton-ui>
17
17
  *
18
18
  * Placeholder shimmer for loading states.
19
19
  * Purely presentational — no DOM stamping needed.
@@ -21,17 +21,18 @@
21
21
  * Props (attributes):
22
22
  * static — suppress the shimmer animation (default: false — shimmer on)
23
23
  *
24
- * Radius: none, sm (default), md, lg, full
24
+ * Corner radius: none, sm (default), md, lg, full. Renamed from `[radius]`
25
+ * (gh#1335) — see skeleton.yaml.
25
26
  */
26
27
 
27
28
  import { UIElement } from '../../core/element.js';
28
29
 
29
30
  export class UISkeleton extends UIElement {
30
31
  static properties = {
31
- width: { type: String, default: '100%', reflect: true },
32
- height: { type: String, default: '1.2em', reflect: true },
33
- radius: { type: String, default: 'sm', reflect: true },
34
- static: { type: Boolean, default: false, reflect: true },
32
+ width: { type: String, default: '100%', reflect: true },
33
+ height: { type: String, default: '1.2em', reflect: true },
34
+ cornerRadius: { type: String, default: 'sm', reflect: true, attribute: 'corner-radius' },
35
+ static: { type: Boolean, default: false, reflect: true },
35
36
  };
36
37
 
37
38
  static template = () => null;
@@ -18,12 +18,27 @@
18
18
  border-radius: var(--skeleton-radius);
19
19
  }
20
20
 
21
- /* ── Radius variants ── */
22
- :scope[radius="none"] { --skeleton-radius: 0; }
23
- :scope[radius="sm"] { --skeleton-radius: var(--a-radius-sm); }
24
- :scope[radius="md"] { --skeleton-radius: var(--a-radius-md); }
25
- :scope[radius="lg"] { --skeleton-radius: var(--a-radius-lg); }
26
- :scope[radius="full"] { --skeleton-radius: var(--a-radius-full); }
21
+ /* ── Overlay mode (gh#1362) ──
22
+ Set by a composing parent (e.g. image-ui) that wants this element
23
+ positioned absolutely over itself. Declared here, inside skeleton-ui's
24
+ OWN `@scope` block, so it competes at skeleton-ui's own proximity (0)
25
+ against the base `:scope { position: relative }` rule above — an
26
+ equal-proximity tie the higher-specificity attribute selector wins
27
+ outright. A parent's own `@scope` overlay rule (image-ui's included)
28
+ can NEVER win this by raising its own specificity: `@scope` proximity
29
+ is resolved before specificity, and that parent's scoping root is one
30
+ level further away (proximity 1) — see CSS Cascade & Inheritance L6. */
31
+ :scope[data-overlay] {
32
+ position: absolute;
33
+ inset: 0;
34
+ }
35
+
36
+ /* ── Corner-radius variants (attribute renamed from [radius], gh#1335) ── */
37
+ :scope[corner-radius="none"] { --skeleton-radius: 0; }
38
+ :scope[corner-radius="sm"] { --skeleton-radius: var(--a-radius-sm); }
39
+ :scope[corner-radius="md"] { --skeleton-radius: var(--a-radius-md); }
40
+ :scope[corner-radius="lg"] { --skeleton-radius: var(--a-radius-lg); }
41
+ :scope[corner-radius="full"] { --skeleton-radius: var(--a-radius-full); }
27
42
 
28
43
  /* ── Shimmer animation (default; suppress with [static]) ── */
29
44
  :scope:not([static])::after {
@@ -13,10 +13,10 @@
13
13
  import { UIElement } from '../../core/element.js';
14
14
 
15
15
  export class UISkeleton extends UIElement {
16
+ /** Border radius. Renamed from `[radius]` (gh#1335) — a preset-enum can't share a name with the global Enum·preset `[radius]` attribute (`sharp`/`rounded`/`round`), whose vocabulary is unrelated (ADR-0053); mirrors chart-ui's own `[corner-radius]` fix (ADR-0054). */
17
+ cornerRadius: 'none' | 'sm' | 'md' | 'lg' | 'full';
16
18
  /** Height of the placeholder. */
17
19
  height: string;
18
- /** Border radius */
19
- radius: 'none' | 'sm' | 'md' | 'lg' | 'full';
20
20
  /** When true, suppress the shimmer animation. */
21
21
  static: boolean;
22
22
  /** Width of the placeholder. */
@@ -6,10 +6,10 @@
6
6
  <skeleton-ui width="100px" height="1em"></skeleton-ui>
7
7
  ```
8
8
 
9
- ## radius
9
+ ## corner-radius
10
10
 
11
11
  ```html
12
- <skeleton-ui width="120px" height="2em" radius="none"></skeleton-ui>
12
+ <skeleton-ui width="120px" height="2em" corner-radius="none"></skeleton-ui>
13
13
  ```
14
14
 
15
15
  ## static
@@ -17,10 +17,11 @@ props:
17
17
  description: Height of the placeholder.
18
18
  type: string
19
19
  default: 1.2em
20
- radius:
21
- description: Border radius
20
+ cornerRadius:
21
+ description: Border radius. Renamed from `[radius]` (gh#1335) — a preset-enum can't share a name with the global Enum·preset `[radius]` attribute (`sharp`/`rounded`/`round`), whose vocabulary is unrelated (ADR-0053); mirrors chart-ui's own `[corner-radius]` fix (ADR-0054).
22
22
  type: string
23
23
  default: sm
24
+ attribute: corner-radius
24
25
  enum:
25
26
  - none
26
27
  - sm
@@ -58,6 +58,7 @@
58
58
  "keyboard-navigation"
59
59
  ],
60
60
  "name": "UISkipNav",
61
+ "parts": {},
61
62
  "related": [
62
63
  "visually-hidden"
63
64
  ],
@@ -126,6 +126,7 @@
126
126
  "volume"
127
127
  ],
128
128
  "name": "UISlider",
129
+ "parts": {},
129
130
  "related": [
130
131
  "input",
131
132
  "select",
@@ -151,6 +152,11 @@
151
152
  "description": "Default, ready for interaction.",
152
153
  "name": "idle"
153
154
  },
155
+ {
156
+ "description": "A thumb is mid-drag (pointer down through pointerup).",
157
+ "attribute": "dragging",
158
+ "name": "dragging"
159
+ },
154
160
  {
155
161
  "description": "Non-interactive; dimmed.",
156
162
  "attribute": "disabled",
@@ -317,7 +317,7 @@ export class UISlider extends UIFormElement {
317
317
  if (this.disabled) return;
318
318
  e.preventDefault();
319
319
  this.#dragging = true;
320
- this.setAttribute('data-dragging', '');
320
+ this.setAttribute('dragging', '');
321
321
 
322
322
  let thumb;
323
323
  if (this.dual) {
@@ -343,6 +343,12 @@ export class UISlider extends UIFormElement {
343
343
  thumb.setPointerCapture(e.pointerId);
344
344
  thumb.addEventListener('pointermove', this.#onPointerMove);
345
345
  thumb.addEventListener('pointerup', this.#onPointerUp);
346
+ // A drag can end without pointerup: touch interruptions (incoming call,
347
+ // OS gesture steal) fire pointercancel, and losing the capture for any
348
+ // other reason fires lostpointercapture. Without these, [dragging] and
349
+ // the move/up listeners stay stuck (gh#1332 review follow-up).
350
+ thumb.addEventListener('pointercancel', this.#onPointerCancel);
351
+ thumb.addEventListener('lostpointercapture', this.#onPointerCancel);
346
352
  };
347
353
 
348
354
  #onPointerMove = (e) => {
@@ -357,16 +363,27 @@ export class UISlider extends UIFormElement {
357
363
  }
358
364
  };
359
365
 
366
+ #onPointerCancel = (e) => {
367
+ // lostpointercapture also fires after a normal pointerup's
368
+ // releasePointerCapture — the #dragging guard makes that a no-op.
369
+ if (!this.#dragging) return;
370
+ this.#onPointerUp(e);
371
+ };
372
+
360
373
  #onPointerUp = (e) => {
361
374
  this.#dragging = false;
362
375
  this.#dragOffset = 0;
363
- this.removeAttribute('data-dragging');
376
+ this.removeAttribute('dragging');
364
377
  const thumb = this.dual
365
378
  ? (this.#draggingThumb === 'lower' ? this.#thumbLowerEl : this.#thumbUpperEl)
366
379
  : this.#thumbEl;
367
- thumb?.releasePointerCapture(e.pointerId);
380
+ // On pointercancel the capture is already gone; releasing a
381
+ // no-longer-captured pointer throws NotFoundError in some engines.
382
+ try { thumb?.releasePointerCapture(e.pointerId); } catch { /* already released */ }
368
383
  thumb?.removeEventListener('pointermove', this.#onPointerMove);
369
384
  thumb?.removeEventListener('pointerup', this.#onPointerUp);
385
+ thumb?.removeEventListener('pointercancel', this.#onPointerCancel);
386
+ thumb?.removeEventListener('lostpointercapture', this.#onPointerCancel);
370
387
  // Drop the active marker — but only after emitting change, so any
371
388
  // mid-drag z-index lift stays painted through the up event.
372
389
  thumb?.removeAttribute('data-active');
@@ -264,7 +264,7 @@
264
264
 
265
265
  /* During drag: kill the left transition so the thumb follows
266
266
  the pointer frame-by-frame without CSS interpolation lag. */
267
- :scope[data-dragging] [slot="thumb"] {
267
+ :scope[dragging] [slot="thumb"] {
268
268
  transition: transform var(--slider-duration) var(--slider-easing);
269
269
  }
270
270
 
@@ -332,6 +332,6 @@
332
332
  margin-top: var(--slider-hint-mt, var(--a-space-1));
333
333
  font-size: var(--slider-hint-size, var(--a-ui-xs));
334
334
  color: var(--slider-hint-fg, var(--a-fg-muted));
335
- line-height: var(--slider-hint-lh, 1.4);
335
+ line-height: var(--slider-hint-lh, var(--a-font-leading-normal));
336
336
  }
337
337
  }
@@ -107,6 +107,9 @@ slots:
107
107
  states:
108
108
  - name: idle
109
109
  description: Default, ready for interaction.
110
+ - name: dragging
111
+ description: A thumb is mid-drag (pointer down through pointerup).
112
+ attribute: dragging
110
113
  - name: disabled
111
114
  description: Non-interactive; dimmed.
112
115
  attribute: disabled
@@ -112,6 +112,7 @@
112
112
  "circular"
113
113
  ],
114
114
  "name": "UISpinner",
115
+ "parts": {},
115
116
  "related": [
116
117
  "Progress",
117
118
  "Skeleton",
@@ -53,6 +53,7 @@
53
53
  "stack"
54
54
  ],
55
55
  "name": "UIStack",
56
+ "parts": {},
56
57
  "related": [
57
58
  "Col",
58
59
  "Row",
@@ -99,6 +99,7 @@
99
99
  "scoreboard"
100
100
  ],
101
101
  "name": "UIStat",
102
+ "parts": {},
102
103
  "related": [
103
104
  "Card",
104
105
  "Badge",
@@ -110,12 +110,12 @@ class UIStat extends UIElement {
110
110
  // Width 60% / 40% / 2em / 1em chosen to roughly mirror the rendered
111
111
  // value+change visual mass without being so wide as to look like text.
112
112
  this.#valueEl.textContent = '';
113
- this.#valueEl.innerHTML = '<skeleton-ui width="60%" height="2em" radius="sm"></skeleton-ui>';
113
+ this.#valueEl.innerHTML = '<skeleton-ui width="60%" height="2em" corner-radius="sm"></skeleton-ui>';
114
114
  // Skeleton replaces the trend icon + text children wholesale; the
115
115
  // non-loading branch below detects the detached refs (parentNode
116
116
  // check) and re-inserts them once real data arrives.
117
117
  this.#changeEl.textContent = '';
118
- this.#changeEl.innerHTML = '<skeleton-ui width="40%" height="1em" radius="sm"></skeleton-ui>';
118
+ this.#changeEl.innerHTML = '<skeleton-ui width="40%" height="1em" corner-radius="sm"></skeleton-ui>';
119
119
  this.#changeEl.hidden = false;
120
120
  // Icon stays as-is (metadata, not data).
121
121
  if (this.icon) {
@@ -68,6 +68,7 @@
68
68
  "indicator"
69
69
  ],
70
70
  "name": "UIStepProgress",
71
+ "parts": {},
71
72
  "related": [
72
73
  "progress-ui",
73
74
  "stepper-ui"
@@ -51,7 +51,7 @@ a2ui:
51
51
  reason: 'Minimal stepper visualization.'
52
52
  - rule: 'Different from <stepper-ui> (labeled, expanded) — step-progress is dense and label-free.'
53
53
  reason: 'Density boundary.'
54
- - rule: 'For multi-task progress bars (multiple labeled rows) use <progress-row-ui> stack.'
54
+ - rule: 'For multi-task progress bars (multiple labeled rows) use a stack of <progress-ui> with `label` set (absorbed the row layout from the now-deprecated progress-row-ui).'
55
55
  reason: 'Different layout.'
56
56
  anti_patterns: []
57
57
 
@@ -53,6 +53,9 @@
53
53
  ],
54
54
  "unevaluatedProperties": false,
55
55
  "x-adiaui": {
56
+ "allowedParents": [
57
+ "Stepper"
58
+ ],
56
59
  "anti_patterns": [],
57
60
  "category": "navigation",
58
61
  "composes": [],
@@ -66,6 +69,7 @@
66
69
  "step-row"
67
70
  ],
68
71
  "name": "UIStepperItem",
72
+ "parts": {},
69
73
  "related": [
70
74
  "Stepper",
71
75
  "Timeline",
@@ -73,13 +77,13 @@
73
77
  ],
74
78
  "slots": {
75
79
  "description": {
76
- "description": "Custom description content; falls through to `[description]` prop if not slotted."
80
+ "description": "Custom secondary-line content; falls through to [description] prop if not slotted. Same adopt-or-stamp guard as `label` (gh#1462)."
77
81
  },
78
82
  "icon": {
79
- "description": "Override the step-status glyph with a custom slotted element. By default the step renders a numeral / check / x indicator based on [status]; slot an `<icon-ui>` or image to customize."
83
+ "description": "Override the step-status glyph with a custom slotted element (custom icon-ui, image). Mutually exclusive with the [icon] attribute a consumer-authored slot child wins and is never renamed or removed by render() (gh#1462 adopt-or-stamp guard)."
80
84
  },
81
85
  "label": {
82
- "description": "Custom label content; falls through to `[text]` prop if not slotted."
86
+ "description": "Custom label content; falls through to [text] prop if not slotted. Adopt-or-stamp guarded (gh#1462): render() only writes into the component-stamped fallback span — a consumer-authored `[slot=\"label\"]` child is adopted as source of truth and never overwritten."
83
87
  }
84
88
  },
85
89
  "states": [],
@@ -50,14 +50,22 @@ props:
50
50
  default: false
51
51
  slots:
52
52
  label:
53
- description: Custom label content; falls through to `[text]` prop if not slotted.
53
+ description: >-
54
+ Custom label content; falls through to [text] prop if not slotted.
55
+ Adopt-or-stamp guarded (gh#1462): render() only writes into the
56
+ component-stamped fallback span — a consumer-authored
57
+ `[slot="label"]` child is adopted as source of truth and never
58
+ overwritten.
54
59
  description:
55
- description: Custom description content; falls through to `[description]` prop if not slotted.
60
+ description: >-
61
+ Custom secondary-line content; falls through to [description] prop
62
+ if not slotted. Same adopt-or-stamp guard as `label` (gh#1462).
56
63
  icon:
57
64
  description: >-
58
- Override the step-status glyph with a custom slotted element. By default
59
- the step renders a numeral / check / x indicator based on [status];
60
- slot an `<icon-ui>` or image to customize.
65
+ Override the step-status glyph with a custom slotted element (custom
66
+ icon-ui, image). Mutually exclusive with the [icon] attribute a
67
+ consumer-authored slot child wins and is never renamed or removed by
68
+ render() (gh#1462 adopt-or-stamp guard).
61
69
 
62
70
  keywords:
63
71
  - stepper-item
@@ -75,6 +83,8 @@ related:
75
83
  - StepProgress
76
84
 
77
85
  a2ui:
86
+ allowedParents:
87
+ - Stepper
78
88
  rules:
79
89
  - rule: 'Child of <stepper-ui> — one numbered step with label + complete/current/upcoming state.'
80
90
  reason: 'Cluster contract.'
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://adiaui.dev/a2ui/v0_9/components/Stepper.json",
4
4
  "title": "Stepper",
5
- "description": "Wizard / process stepper — parent step index drives numbered children's complete/current/upcoming states automatically. Renders horizontally as a labeled step bar with connectors. Use for multi-step forms, onboarding, or pipelines; for read-only event history use <timeline-ui> instead. Add [interactive] to opt into click-to-navigate + roving- tabindex keyboard (arrow keys / Home / End) — the host still owns whether navigation is permitted: listen for the cancelable [step-request] event and call preventDefault() to veto a step before it lands, or set [disabled] on a stepper-item-ui to phase-gate it out of reach entirely.",
5
+ "description": "Wizard / process stepper — parent step index drives numbered children's complete/current/upcoming states automatically. Renders horizontally as a labeled step bar with connectors. Use for multi-step forms, onboarding, or pipelines; for read-only event history use <timeline-ui> instead. Add [interactive] to opt into click-to-navigate + roving-tabindex keyboard (arrow keys / Home / End) — the host still owns whether navigation is permitted: listen for the cancelable [step-request] event and call preventDefault() to veto a step before it lands, or set [disabled] on a stepper-item-ui to phase-gate it out of reach entirely.",
6
6
  "type": "object",
7
7
  "allOf": [
8
8
  {
@@ -37,6 +37,9 @@
37
37
  ],
38
38
  "unevaluatedProperties": false,
39
39
  "x-adiaui": {
40
+ "allowedChildren": [
41
+ "StepperItem"
42
+ ],
40
43
  "anti_patterns": [],
41
44
  "category": "navigation",
42
45
  "composes": [
@@ -89,6 +92,7 @@
89
92
  "click-to-navigate"
90
93
  ],
91
94
  "name": "UIStepper",
95
+ "parts": {},
92
96
  "related": [
93
97
  "timeline-ui",
94
98
  "progress-ui"
@@ -108,7 +108,9 @@ export class UIStepper extends UIElement {
108
108
  connected() {
109
109
  this.addEventListener('click', this.#handleClick);
110
110
  this.addEventListener('keydown', this.#handleKeydown);
111
- if (!this.#childObserver) {
111
+ // Guarded like the other Observer sites (gh#285 §1 pattern) — SSR shims
112
+ // have no MutationObserver; teardown already uses `?.disconnect()`.
113
+ if (!this.#childObserver && typeof MutationObserver !== 'undefined') {
112
114
  this.#childObserver = new MutationObserver(this.#onChildMutation);
113
115
  this.#childObserver.observe(this, {
114
116
  childList: true,
@@ -293,31 +295,44 @@ export class UIStepperItem extends UIElement {
293
295
 
294
296
  static template = () => null;
295
297
 
298
+ // Adopt-or-stamp (gh#1462): a fallback child stamped from a prop is
299
+ // marked, and render() only ever writes into marked elements — a
300
+ // consumer-authored slot="label"/"description"/"icon" child is adopted
301
+ // as source of truth and never overwritten or removed. Mirrors
302
+ // action-item-ui/menu-item-ui's stamp-marking (PR #1429).
303
+ #stampMark(el) { el.dataset.stepperItemStamped = '1'; return el; }
304
+ #wasStamped(el) { return el?.dataset?.stepperItemStamped === '1'; }
305
+
296
306
  connected() {
297
- if (!this.querySelector('[slot="label"]')) {
298
- this.innerHTML = `
299
- <span slot="label"></span>
300
- <span slot="description"></span>
301
- `;
307
+ // Each slot's adopt-or-stamp decision is independent per slot key —
308
+ // an authored label must not suppress the prop-driven description
309
+ // fallback (mirrors action-item-ui's per-part stamping, PR #1429).
310
+ for (const name of ['label', 'description']) {
311
+ if (this.querySelector(`[slot="${name}"]`)) continue;
312
+ const span = this.#stampMark(document.createElement('span'));
313
+ span.setAttribute('slot', name);
314
+ this.appendChild(span);
302
315
  }
303
316
  }
304
317
 
305
318
  render() {
306
319
  const label = this.querySelector('[slot="label"]');
307
320
  const desc = this.querySelector('[slot="description"]');
308
- if (label) label.textContent = this.text;
309
- if (desc) desc.textContent = this.description;
321
+ if (this.#wasStamped(label)) label.textContent = this.text;
322
+ if (this.#wasStamped(desc)) desc.textContent = this.description;
310
323
 
324
+ const iconEl = this.querySelector('[slot="icon"]');
311
325
  if (this.icon) {
312
- let iconEl = this.querySelector('[slot="icon"]');
313
- if (!iconEl) {
314
- iconEl = document.createElement('icon-ui');
315
- iconEl.setAttribute('slot', 'icon');
316
- this.prepend(iconEl);
326
+ if (iconEl) {
327
+ if (this.#wasStamped(iconEl)) iconEl.setAttribute('name', this.icon);
328
+ } else {
329
+ const el = this.#stampMark(document.createElement('icon-ui'));
330
+ el.setAttribute('slot', 'icon');
331
+ el.setAttribute('name', this.icon);
332
+ this.prepend(el);
317
333
  }
318
- iconEl.setAttribute('name', this.icon);
319
- } else {
320
- this.querySelector('[slot="icon"]')?.remove();
334
+ } else if (this.#wasStamped(iconEl)) {
335
+ iconEl.remove();
321
336
  }
322
337
  }
323
338
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `<stepper-ui>` — Wizard / process stepper — parent step index drives numbered children's complete/current/upcoming states automatically. Renders horizontally as a labeled step bar with connectors. Use for multi-step forms, onboarding, or pipelines; for read-only event history use <timeline-ui> instead. Add [interactive] to opt into click-to-navigate + roving- tabindex keyboard (arrow keys / Home / End) — the host still owns whether navigation is permitted: listen for the cancelable [step-request] event and call preventDefault() to veto a step before it lands, or set [disabled] on a stepper-item-ui to phase-gate it out of reach entirely.
2
+ * `<stepper-ui>` — Wizard / process stepper — parent step index drives numbered children's complete/current/upcoming states automatically. Renders horizontally as a labeled step bar with connectors. Use for multi-step forms, onboarding, or pipelines; for read-only event history use <timeline-ui> instead. Add [interactive] to opt into click-to-navigate + roving-tabindex keyboard (arrow keys / Home / End) — the host still owns whether navigation is permitted: listen for the cancelable [step-request] event and call preventDefault() to veto a step before it lands, or set [disabled] on a stepper-item-ui to phase-gate it out of reach entirely.
3
3
  *
4
4
  * @see https://ui-kit.exe.xyz/site/components/stepper
5
5
  *
@@ -12,8 +12,8 @@ description: >-
12
12
  complete/current/upcoming states automatically. Renders horizontally as
13
13
  a labeled step bar with connectors. Use for multi-step forms,
14
14
  onboarding, or pipelines; for read-only event history use <timeline-ui>
15
- instead. Add [interactive] to opt into click-to-navigate + roving-
16
- tabindex keyboard (arrow keys / Home / End) — the host still owns
15
+ instead. Add [interactive] to opt into click-to-navigate + roving-tabindex
16
+ keyboard (arrow keys / Home / End) — the host still owns
17
17
  whether navigation is permitted: listen for the cancelable
18
18
  [step-request] event and call preventDefault() to veto a step before
19
19
  it lands, or set [disabled] on a stepper-item-ui to phase-gate it
@@ -73,6 +73,8 @@ states:
73
73
  traits: []
74
74
  tokens: {}
75
75
  a2ui:
76
+ allowedChildren:
77
+ - StepperItem
76
78
  rules:
77
79
  - rule: 'Hosts <stepper-item-ui> children with a parent active-index driving complete/current/upcoming states.'
78
80
  reason: 'Process visualization cluster.'
@@ -68,6 +68,7 @@
68
68
  "stream"
69
69
  ],
70
70
  "name": "UIStream",
71
+ "parts": {},
71
72
  "related": [
72
73
  "ChatThreadUI",
73
74
  "Text",
@@ -145,6 +145,7 @@
145
145
  "token"
146
146
  ],
147
147
  "name": "UISwatch",
148
+ "parts": {},
148
149
  "related": [
149
150
  "chart-legend-ui",
150
151
  "tag-ui"
@@ -141,6 +141,7 @@
141
141
  "swiper"
142
142
  ],
143
143
  "name": "UISwiper",
144
+ "parts": {},
144
145
  "related": [
145
146
  "image-gallery",
146
147
  "hero-section",
@@ -196,7 +196,11 @@ export class UISwiper extends UIElement {
196
196
 
197
197
  play() {
198
198
  this.pause();
199
- if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
199
+ // Feature-detect (gh#1430): SSR shims have no `matchMedia`, so treat "can't
200
+ // read the motion preference" like "reduce" — no viewport to animate, and
201
+ // a server-side setInterval would only leak.
202
+ if (typeof matchMedia !== 'function' ||
203
+ matchMedia('(prefers-reduced-motion: reduce)').matches) return;
200
204
 
201
205
  this.#timer = setInterval(() => {
202
206
  const lastPage = this.#getPageCount() - 1;