@adia-ai/web-components 0.8.39 → 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 (424) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/MIGRATION.md +1269 -3
  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-artifact/agent-artifact.css +1 -1
  21. package/components/agent-feedback-bar/agent-feedback-bar.a2ui.json +6 -5
  22. package/components/agent-feedback-bar/agent-feedback-bar.yaml +6 -2
  23. package/components/agent-questions/agent-questions.a2ui.json +1 -0
  24. package/components/agent-reasoning/agent-reasoning.a2ui.json +6 -5
  25. package/components/agent-reasoning/agent-reasoning.css +2 -2
  26. package/components/agent-reasoning/agent-reasoning.yaml +6 -2
  27. package/components/agent-suggestions/agent-suggestions.a2ui.json +11 -2
  28. package/components/agent-suggestions/agent-suggestions.class.js +2 -1
  29. package/components/agent-suggestions/agent-suggestions.d.ts +4 -4
  30. package/components/agent-suggestions/agent-suggestions.yaml +4 -2
  31. package/components/agent-trace/agent-trace.a2ui.json +6 -5
  32. package/components/agent-trace/agent-trace.css +3 -3
  33. package/components/agent-trace/agent-trace.yaml +6 -2
  34. package/components/alert/alert.a2ui.json +1 -0
  35. package/components/alert/alert.css +2 -2
  36. package/components/anchor-bar/anchor-bar.a2ui.json +1 -0
  37. package/components/aside/aside.a2ui.json +1 -0
  38. package/components/avatar/avatar-group.a2ui.json +7 -1
  39. package/components/avatar/avatar-group.yaml +1 -0
  40. package/components/avatar/avatar.a2ui.json +12 -11
  41. package/components/avatar/avatar.css +1 -1
  42. package/components/avatar/avatar.d.ts +1 -1
  43. package/components/avatar/avatar.yaml +4 -4
  44. package/components/badge/badge.a2ui.json +1 -0
  45. package/components/badge/badge.css +1 -1
  46. package/components/block/block.a2ui.json +1 -0
  47. package/components/blockquote/blockquote.a2ui.json +1 -0
  48. package/components/breadcrumb/breadcrumb.a2ui.json +1 -0
  49. package/components/button/button.a2ui.json +1 -3
  50. package/components/button/button.css +6 -5
  51. package/components/button/button.yaml +1 -3
  52. package/components/calendar-grid/calendar-grid.a2ui.json +1 -0
  53. package/components/calendar-grid/calendar-grid.class.js +2 -1
  54. package/components/calendar-picker/calendar-picker.a2ui.json +143 -24
  55. package/components/calendar-picker/calendar-picker.class.js +490 -197
  56. package/components/calendar-picker/calendar-picker.css +121 -172
  57. package/components/calendar-picker/calendar-picker.yaml +225 -47
  58. package/components/canvas/canvas.a2ui.json +6 -5
  59. package/components/canvas/canvas.d.ts +37 -0
  60. package/components/canvas/canvas.js +72 -3
  61. package/components/canvas/canvas.yaml +6 -2
  62. package/components/card/card.a2ui.json +25 -2
  63. package/components/card/card.class.js +3 -0
  64. package/components/card/card.css +34 -4
  65. package/components/card/card.d.ts +2 -2
  66. package/components/card/card.examples.md +3 -3
  67. package/components/card/card.yaml +28 -4
  68. package/components/chart/chart.a2ui.json +13 -8
  69. package/components/chart/chart.class.js +10 -10
  70. package/components/chart/chart.css +12 -10
  71. package/components/chart/chart.d.ts +2 -2
  72. package/components/chart/chart.yaml +8 -5
  73. package/components/chart-legend/chart-legend.a2ui.json +1 -0
  74. package/components/chat-thread/chat-input.a2ui.json +1 -0
  75. package/components/chat-thread/chat-thread.a2ui.json +10 -9
  76. package/components/chat-thread/chat-thread.css +1 -1
  77. package/components/chat-thread/chat-thread.yaml +13 -20
  78. package/components/check/check.a2ui.json +10 -9
  79. package/components/check/check.yaml +4 -4
  80. package/components/code/code.a2ui.json +1 -0
  81. package/components/code/code.css +6 -6
  82. package/components/col/col.a2ui.json +1 -0
  83. package/components/color-input/color-input.a2ui.json +1 -0
  84. package/components/color-picker/color-picker.a2ui.json +1 -0
  85. package/components/combobox/combobox.a2ui.json +3 -2
  86. package/components/combobox/combobox.css +2 -2
  87. package/components/combobox/combobox.yaml +2 -2
  88. package/components/command/command.a2ui.json +12 -10
  89. package/components/command/command.class.js +3 -2
  90. package/components/command/command.css +3 -3
  91. package/components/command/command.yaml +17 -4
  92. package/components/context-menu/context-menu.a2ui.json +1 -0
  93. package/components/date-range-picker/date-range-picker.a2ui.json +2 -1
  94. package/components/date-range-picker/date-range-picker.css +1 -1
  95. package/components/date-range-picker/date-range-picker.yaml +1 -1
  96. package/components/datetime-picker/datetime-picker.a2ui.json +15 -108
  97. package/components/datetime-picker/datetime-picker.class.js +37 -690
  98. package/components/datetime-picker/datetime-picker.css +11 -183
  99. package/components/datetime-picker/datetime-picker.d.ts +4 -5
  100. package/components/datetime-picker/datetime-picker.yaml +44 -135
  101. package/components/demo-toggle/demo-toggle.a2ui.json +1 -0
  102. package/components/demo-toggle/demo-toggle.css +1 -1
  103. package/components/description-list/description-list.a2ui.json +1 -0
  104. package/components/description-list/description-list.css +2 -2
  105. package/components/display-field/display-field.a2ui.json +1 -0
  106. package/components/display-field/display-field.css +3 -3
  107. package/components/divider/divider.a2ui.json +1 -0
  108. package/components/divider/divider.css +1 -1
  109. package/components/drawer/drawer.a2ui.json +1 -3
  110. package/components/drawer/drawer.css +3 -3
  111. package/components/drawer/drawer.yaml +0 -2
  112. package/components/drilldown/drilldown.a2ui.json +22 -20
  113. package/components/drilldown/drilldown.class.js +4 -3
  114. package/components/drilldown/drilldown.css +8 -8
  115. package/components/drilldown/drilldown.yaml +40 -9
  116. package/components/embed/embed.a2ui.json +6 -5
  117. package/components/embed/embed.yaml +2 -2
  118. package/components/empty-state/empty-state.a2ui.json +1 -0
  119. package/components/empty-state/empty-state.css +2 -2
  120. package/components/feed/feed-item.a2ui.json +25 -5
  121. package/components/feed/feed-item.yaml +28 -7
  122. package/components/feed/feed.a2ui.json +9 -2
  123. package/components/feed/feed.class.js +19 -12
  124. package/components/feed/feed.css +8 -8
  125. package/components/feed/feed.yaml +14 -1
  126. package/components/field/field.a2ui.json +1 -0
  127. package/components/field/field.css +1 -1
  128. package/components/field/field.examples.md +1 -1
  129. package/components/fields/fields.a2ui.json +1 -0
  130. package/components/fields/fields.examples.md +1 -1
  131. package/components/footer/footer.a2ui.json +1 -0
  132. package/components/frame/frame.a2ui.json +1 -0
  133. package/components/grid/grid.a2ui.json +1 -0
  134. package/components/header/header.a2ui.json +3 -2
  135. package/components/header/header.yaml +3 -3
  136. package/components/heatmap/heatmap.a2ui.json +2 -1
  137. package/components/heatmap/heatmap.class.js +1 -1
  138. package/components/heatmap/heatmap.css +6 -6
  139. package/components/heatmap/heatmap.yaml +1 -1
  140. package/components/icon/icon.a2ui.json +1 -0
  141. package/components/image/image.a2ui.json +28 -14
  142. package/components/image/image.class.js +38 -23
  143. package/components/image/image.css +18 -8
  144. package/components/image/image.d.ts +2 -2
  145. package/components/image/image.examples.md +3 -3
  146. package/components/image/image.yaml +23 -7
  147. package/components/inline-edit/inline-edit.a2ui.json +1 -0
  148. package/components/inline-message/inline-message.a2ui.json +3 -1
  149. package/components/inline-message/inline-message.class.js +3 -1
  150. package/components/inline-message/inline-message.css +1 -1
  151. package/components/inline-message/inline-message.d.ts +2 -2
  152. package/components/inline-message/inline-message.yaml +2 -1
  153. package/components/input/input.a2ui.json +66 -16
  154. package/components/input/input.class.js +64 -7
  155. package/components/input/input.css +19 -18
  156. package/components/input/input.d.ts +9 -4
  157. package/components/input/input.yaml +83 -10
  158. package/components/inspector/inspector.a2ui.json +1 -0
  159. package/components/integration-card/integration-card.a2ui.json +1 -0
  160. package/components/integration-card/integration-card.css +4 -4
  161. package/components/kbd/kbd.a2ui.json +1 -0
  162. package/components/kbd/kbd.css +1 -1
  163. package/components/link/link.a2ui.json +2 -1
  164. package/components/link/link.yaml +1 -1
  165. package/components/list/list-item.a2ui.json +9 -0
  166. package/components/list/list-item.yaml +12 -0
  167. package/components/list/list.a2ui.json +9 -3
  168. package/components/list/list.class.js +14 -1
  169. package/components/list/list.css +14 -3
  170. package/components/list/list.d.ts +7 -5
  171. package/components/list/list.yaml +16 -6
  172. package/components/list-window/list-window.a2ui.json +1 -0
  173. package/components/list-window/list-window.class.js +2 -1
  174. package/components/loading-overlay/loading-overlay.a2ui.json +1 -0
  175. package/components/mark/mark.a2ui.json +2 -1
  176. package/components/mark/mark.yaml +1 -1
  177. package/components/menu/menu-divider.a2ui.json +1 -0
  178. package/components/menu/menu-item.a2ui.json +3 -1
  179. package/components/menu/menu-item.yaml +6 -0
  180. package/components/menu/menu-label.a2ui.json +1 -0
  181. package/components/menu/menu.a2ui.json +3 -2
  182. package/components/menu/menu.class.js +2 -2
  183. package/components/menu/menu.d.ts +2 -2
  184. package/components/menu/menu.yaml +3 -3
  185. package/components/modal/modal.a2ui.json +1 -0
  186. package/components/nav/nav.a2ui.json +1 -0
  187. package/components/nav/nav.class.js +14 -3
  188. package/components/nav/nav.css +2 -2
  189. package/components/nav-group/nav-group.a2ui.json +1 -0
  190. package/components/nav-group/nav-group.class.js +3 -1
  191. package/components/nav-group/nav-group.css +3 -3
  192. package/components/nav-item/nav-item.a2ui.json +1 -0
  193. package/components/nav-item/nav-item.css +2 -2
  194. package/components/noodles/noodles.a2ui.json +1 -0
  195. package/components/noodles/noodles.class.js +5 -1
  196. package/components/number-format/number-format.a2ui.json +1 -0
  197. package/components/option-card/option-card.a2ui.json +1 -0
  198. package/components/option-card/option-card.css +1 -1
  199. package/components/otp-input/otp-input.a2ui.json +3 -2
  200. package/components/otp-input/otp-input.css +1 -1
  201. package/components/otp-input/otp-input.yaml +9 -2
  202. package/components/page/page.a2ui.json +13 -0
  203. package/components/page/page.css +2 -2
  204. package/components/page/page.d.ts +1 -1
  205. package/components/page/page.yaml +1 -0
  206. package/components/pagination/pagination.a2ui.json +1 -0
  207. package/components/pagination/pagination.class.js +3 -2
  208. package/components/pagination/pagination.css +1 -1
  209. package/components/pane/pane.a2ui.json +6 -0
  210. package/components/pane/pane.class.js +3 -3
  211. package/components/pane/pane.css +3 -3
  212. package/components/pane/pane.yaml +3 -0
  213. package/components/password-strength/password-strength.a2ui.json +1 -0
  214. package/components/pipeline-status/pipeline-status.a2ui.json +1 -0
  215. package/components/popover/popover.a2ui.json +7 -6
  216. package/components/popover/popover.class.js +2 -2
  217. package/components/popover/popover.d.ts +2 -2
  218. package/components/popover/popover.yaml +4 -4
  219. package/components/preview/preview.a2ui.json +1 -0
  220. package/components/preview/preview.class.js +5 -1
  221. package/components/progress/progress.a2ui.json +47 -24
  222. package/components/progress/progress.class.js +66 -11
  223. package/components/progress/progress.css +44 -26
  224. package/components/progress/progress.d.ts +7 -5
  225. package/components/progress/progress.examples.md +2 -2
  226. package/components/progress/progress.yaml +235 -53
  227. package/components/progress-row/progress-row.a2ui.json +16 -12
  228. package/components/progress-row/progress-row.css +2 -2
  229. package/components/progress-row/progress-row.d.ts +2 -2
  230. package/components/progress-row/progress-row.examples.md +2 -14
  231. package/components/progress-row/progress-row.yaml +28 -36
  232. package/components/qr-code/qr-code.a2ui.json +13 -12
  233. package/components/qr-code/qr-code.class.js +7 -7
  234. package/components/qr-code/qr-code.css +1 -1
  235. package/components/qr-code/qr-code.d.ts +10 -7
  236. package/components/qr-code/qr-code.yaml +18 -12
  237. package/components/radio/radio.a2ui.json +8 -7
  238. package/components/radio/radio.class.js +8 -0
  239. package/components/radio/radio.yaml +3 -3
  240. package/components/radio-group/radio-group.a2ui.json +5 -3
  241. package/components/radio-group/radio-group.class.js +11 -0
  242. package/components/radio-group/radio-group.yaml +7 -1
  243. package/components/range/range.a2ui.json +6 -0
  244. package/components/range/range.class.js +2 -2
  245. package/components/range/range.css +3 -3
  246. package/components/range/range.yaml +3 -0
  247. package/components/rating/rating.a2ui.json +1 -0
  248. package/components/rating/rating.css +1 -1
  249. package/components/relative-time/relative-time.a2ui.json +1 -0
  250. package/components/richtext/richtext.a2ui.json +2 -1
  251. package/components/richtext/richtext.css +3 -3
  252. package/components/richtext/richtext.yaml +1 -1
  253. package/components/row/row.a2ui.json +1 -0
  254. package/components/search/search.a2ui.json +1 -0
  255. package/components/search/search.class.js +4 -1
  256. package/components/section/section.a2ui.json +1 -0
  257. package/components/segment/segment.a2ui.json +21 -10
  258. package/components/segment/segment.css +20 -4
  259. package/components/segment/segment.d.ts +2 -1
  260. package/components/segment/segment.yaml +20 -13
  261. package/components/segmented/segmented.a2ui.json +36 -7
  262. package/components/segmented/segmented.class.js +113 -22
  263. package/components/segmented/segmented.css +3 -0
  264. package/components/segmented/segmented.d.ts +3 -1
  265. package/components/segmented/segmented.yaml +80 -8
  266. package/components/select/select.a2ui.json +18 -13
  267. package/components/select/select.class.js +61 -37
  268. package/components/select/select.css +18 -16
  269. package/components/select/select.yaml +18 -7
  270. package/components/skeleton/skeleton.a2ui.json +8 -7
  271. package/components/skeleton/skeleton.class.js +8 -7
  272. package/components/skeleton/skeleton.css +21 -6
  273. package/components/skeleton/skeleton.d.ts +2 -2
  274. package/components/skeleton/skeleton.examples.md +2 -2
  275. package/components/skeleton/skeleton.yaml +3 -2
  276. package/components/skip-nav/skip-nav.a2ui.json +1 -0
  277. package/components/slider/slider.a2ui.json +6 -0
  278. package/components/slider/slider.class.js +20 -3
  279. package/components/slider/slider.css +2 -2
  280. package/components/slider/slider.yaml +3 -0
  281. package/components/spinner/spinner.a2ui.json +1 -0
  282. package/components/spinner/spinner.css +1 -1
  283. package/components/stack/stack.a2ui.json +1 -0
  284. package/components/stat/stat.a2ui.json +1 -0
  285. package/components/stat/stat.css +3 -3
  286. package/components/stat/stat.js +2 -2
  287. package/components/step-progress/step-progress.a2ui.json +1 -0
  288. package/components/step-progress/step-progress.css +1 -1
  289. package/components/step-progress/step-progress.yaml +1 -1
  290. package/components/stepper/stepper-item.a2ui.json +7 -3
  291. package/components/stepper/stepper-item.yaml +15 -5
  292. package/components/stepper/stepper.a2ui.json +5 -1
  293. package/components/stepper/stepper.class.js +31 -16
  294. package/components/stepper/stepper.css +2 -2
  295. package/components/stepper/stepper.d.ts +1 -1
  296. package/components/stepper/stepper.yaml +4 -2
  297. package/components/stream/stream.a2ui.json +1 -0
  298. package/components/swatch/swatch.a2ui.json +1 -0
  299. package/components/swatch/swatch.css +2 -2
  300. package/components/swiper/swiper.a2ui.json +1 -0
  301. package/components/swiper/swiper.class.js +5 -1
  302. package/components/switch/switch.a2ui.json +12 -11
  303. package/components/switch/switch.css +1 -1
  304. package/components/switch/switch.yaml +6 -6
  305. package/components/table/table.a2ui.json +1 -10
  306. package/components/table/table.class.js +18 -16
  307. package/components/table/table.css +17 -18
  308. package/components/table/table.d.ts +0 -2
  309. package/components/table/table.yaml +0 -9
  310. package/components/table-toolbar/table-toolbar.a2ui.json +1 -0
  311. package/components/table-toolbar/table-toolbar.class.js +38 -19
  312. package/components/table-toolbar/table-toolbar.css +2 -2
  313. package/components/tabs/tab.a2ui.json +9 -0
  314. package/components/tabs/tab.js +4 -0
  315. package/components/tabs/tab.yaml +15 -0
  316. package/components/tabs/tabs.a2ui.json +9 -4
  317. package/components/tabs/tabs.class.js +13 -1
  318. package/components/tabs/tabs.css +9 -1
  319. package/components/tabs/tabs.d.ts +2 -0
  320. package/components/tabs/tabs.yaml +9 -2
  321. package/components/tag/tag.a2ui.json +1 -0
  322. package/components/tag/tag.css +2 -2
  323. package/components/tags-input/tags-input.a2ui.json +22 -17
  324. package/components/tags-input/tags-input.class.js +13 -11
  325. package/components/tags-input/tags-input.css +11 -7
  326. package/components/tags-input/tags-input.d.ts +16 -7
  327. package/components/tags-input/tags-input.examples.md +2 -2
  328. package/components/tags-input/tags-input.yaml +25 -8
  329. package/components/text/text.a2ui.json +6 -5
  330. package/components/text/text.css +10 -5
  331. package/components/text/text.d.ts +2 -2
  332. package/components/text/text.yaml +9 -4
  333. package/components/textarea/textarea.a2ui.json +2 -1
  334. package/components/textarea/textarea.css +1 -1
  335. package/components/textarea/textarea.yaml +1 -1
  336. package/components/theme-provider/theme-provider.a2ui.json +2 -1
  337. package/components/theme-provider/theme-provider.d.ts +5 -3
  338. package/components/theme-provider/theme-provider.yaml +5 -3
  339. package/components/time-picker/time-picker.a2ui.json +1 -0
  340. package/components/time-picker/time-picker.class.js +4 -2
  341. package/components/time-picker/time-picker.css +1 -1
  342. package/components/timeline/timeline-item.a2ui.json +26 -3
  343. package/components/timeline/timeline-item.yaml +22 -7
  344. package/components/timeline/timeline.a2ui.json +4 -0
  345. package/components/timeline/timeline.class.js +29 -18
  346. package/components/timeline/timeline.css +4 -4
  347. package/components/timeline/timeline.d.ts +3 -3
  348. package/components/timeline/timeline.yaml +2 -0
  349. package/components/toast/toast.a2ui.json +10 -3
  350. package/components/toast/toast.yaml +20 -13
  351. package/components/toc/toc.a2ui.json +1 -0
  352. package/components/toc/toc.css +1 -1
  353. package/components/toggle-group/toggle-group.a2ui.json +7 -3
  354. package/components/toggle-group/toggle-group.class.js +43 -12
  355. package/components/toggle-group/toggle-group.css +7 -4
  356. package/components/toggle-group/toggle-group.d.ts +3 -4
  357. package/components/toggle-group/toggle-group.yaml +22 -16
  358. package/components/toggle-group/toggle-option.a2ui.json +8 -4
  359. package/components/toggle-group/toggle-option.yaml +15 -13
  360. package/components/toggle-scheme/toggle-scheme.a2ui.json +2 -1
  361. package/components/toggle-scheme/toggle-scheme.yaml +1 -1
  362. package/components/toolbar/toolbar-group.a2ui.json +1 -0
  363. package/components/toolbar/toolbar.a2ui.json +1 -0
  364. package/components/toolbar/toolbar.class.js +3 -0
  365. package/components/tooltip/tooltip.a2ui.json +1 -0
  366. package/components/tooltip/tooltip.css +1 -1
  367. package/components/tour/tour-step.a2ui.json +4 -0
  368. package/components/tour/tour-step.yaml +2 -0
  369. package/components/tour/tour.a2ui.json +4 -0
  370. package/components/tour/tour.css +2 -2
  371. package/components/tour/tour.yaml +2 -0
  372. package/components/tree/tree-item.a2ui.json +5 -0
  373. package/components/tree/tree-item.yaml +3 -0
  374. package/components/tree/tree.a2ui.json +4 -0
  375. package/components/tree/tree.class.js +2 -1
  376. package/components/tree/tree.css +1 -1
  377. package/components/tree/tree.yaml +2 -0
  378. package/components/upload/upload.a2ui.json +8 -1
  379. package/components/upload/upload.class.js +35 -5
  380. package/components/upload/upload.css +28 -0
  381. package/components/upload/upload.d.ts +16 -0
  382. package/components/upload/upload.yaml +27 -7
  383. package/components/visually-hidden/visually-hidden.a2ui.json +1 -0
  384. package/core/dom.d.ts +11 -0
  385. package/core/dom.js +34 -0
  386. package/core/form.js +7 -0
  387. package/core/index.d.ts +1 -0
  388. package/core/index.js +1 -0
  389. package/core/responsive.js +16 -4
  390. package/core/template.js +2 -1
  391. package/custom-elements.json +442 -502
  392. package/dist/host.min.css +1 -1
  393. package/dist/host.sheet.js +1 -1
  394. package/dist/theme-provider.min.js +5 -5
  395. package/dist/web-components.min.css +1 -1
  396. package/dist/web-components.min.js +91 -104
  397. package/dist/web-components.sheet.js +1 -1
  398. package/package.json +4 -2
  399. package/patterns/conversion-funnel/conversion-funnel.examples.html +15 -15
  400. package/patterns/inline-dialog/inline-dialog.examples.html +2 -2
  401. package/patterns/inline-dialog/inline-dialog.html +4 -0
  402. package/patterns/timezone-selector/timezone-selector.examples.html +1 -1
  403. package/patterns/timezone-selector/timezone-selector.html +2 -2
  404. package/styles/api/text.css +7 -0
  405. package/styles/type/scale.css +6 -7
  406. package/traits/_catalog.json +129 -41
  407. package/traits/anchor-positioning/anchor-positioning.js +1 -0
  408. package/traits/announcer/announcer.js +1 -0
  409. package/traits/arrow-grid-nav/arrow-grid-nav.js +1 -0
  410. package/traits/attention-pulse/attention-pulse.js +1 -0
  411. package/traits/count-up/count-up.js +1 -0
  412. package/traits/define.js +78 -0
  413. package/traits/focus-restore/focus-restore.js +2 -1
  414. package/traits/haptic-feedback/haptic-feedback.js +1 -0
  415. package/traits/input-mask/input-mask.js +1 -0
  416. package/traits/intersection-observer/intersection-observer.js +1 -0
  417. package/traits/layout-animation/layout-animation.js +1 -0
  418. package/traits/noise-texture/noise-texture.js +1 -0
  419. package/traits/resize-observer/resize-observer.js +1 -0
  420. package/traits/scroll-progress/scroll-progress.js +1 -0
  421. package/traits/snap-to-grid/snap-to-grid.js +1 -0
  422. package/traits/sound-feedback/sound-feedback.js +1 -0
  423. package/traits/spring-animate/spring-animate.js +1 -0
  424. package/traits/validation/validation.js +1 -0
@@ -28,6 +28,14 @@ props:
28
28
  description:
29
29
  description: Secondary line below the primary text. Subtle color.
30
30
  type: string
31
+ selected:
32
+ description: >-
33
+ Whether this row is the current selection. Managed by the parent
34
+ <list-ui>[selectable] — don't set directly; the parent's
35
+ [selectedKey] is the single source of truth (ADR-0056).
36
+ type: boolean
37
+ default: false
38
+ reflect: true
31
39
 
32
40
  slots:
33
41
  text:
@@ -78,6 +86,8 @@ related:
78
86
  - TreeItem
79
87
 
80
88
  a2ui:
89
+ allowedParents:
90
+ - List
81
91
  rules:
82
92
  - rule: 'Child of <list-ui> — one row of generic-list content.'
83
93
  reason: 'Cluster contract.'
@@ -85,3 +95,5 @@ a2ui:
85
95
  reason: 'Per-context list-row primitives — list-item is generic.'
86
96
  - rule: 'Interactive list-items should have role=''button'' or be wrapped in <button-ui>; default is non-interactive.'
87
97
  reason: 'Accessibility — semantic clarity.'
98
+ - rule: '[selected] reflects the row current-selection state under <list-ui selectable> — it is parent-managed (ADR-0056); drive selection via the parent''s [selectedKey], never [selected] directly.'
99
+ reason: 'Single source of truth stays on the parent, mirroring <segment-ui>.'
@@ -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/List.json",
4
4
  "title": "List",
5
- "description": "Styled flat list with optional row dividers and icons — each row\nis a <list-item-ui> child. Selectable mode via [selectable] +\n[selectedKey] / `select` event. Composes <icon-ui> for row leading\nglyphs. Distinct from <nav-ui> (sidebar navigation, route-aware),\n<tree-ui> (hierarchical with arbitrary nesting), and <table-ui>\n(tabular data with columns). Use list-ui for non-navigable,\nnon-tabular vertical rows — comment lists, file lists, message\nstreams outside chat-shell.\n",
5
+ "description": "Styled flat list with optional row dividers and icons — each row\nis a <list-item-ui> child. Selectable mode via [selectable] +\n[selectedKey] / `selection-change` event. Composes <icon-ui> for row\nleading glyphs. Distinct from <nav-ui> (sidebar navigation, route-aware),\n<tree-ui> (hierarchical with arbitrary nesting), and <table-ui>\n(tabular data with columns). Use list-ui for non-navigable,\nnon-tabular vertical rows — comment lists, file lists, message\nstreams outside chat-shell.\n",
6
6
  "type": "object",
7
7
  "allOf": [
8
8
  {
@@ -32,13 +32,18 @@
32
32
  "default": false
33
33
  },
34
34
  "selectedKey": {
35
- "description": "ID (or data-key) of the currently-selected child listitem.",
35
+ "description": "ID (or data-key) of the currently-selected child listitem — drives each child's [selected] reflected prop (ADR-0056, #1363 B7). Kept as `selectedKey` rather than renamed to `value` (segmented/tabs/ select's parent-selection prop name): list rows are identified by DOM id/data-key, not an option value, and ADR-0056 itself governs only the child's own [selected] state surface, not this naming — a cross-family rename has no ratifying ADR (B5/B9-shaped follow-up).",
36
36
  "type": "string",
37
37
  "default": ""
38
38
  },
39
39
  "spacing": {
40
- "description": "Item spacing",
40
+ "description": "Item spacing scale — `sm`/`lg` modulate the per-item inset; `md` (default) is the base inset.",
41
41
  "type": "string",
42
+ "enum": [
43
+ "sm",
44
+ "md",
45
+ "lg"
46
+ ],
42
47
  "default": "md"
43
48
  }
44
49
  },
@@ -84,6 +89,7 @@
84
89
  "star"
85
90
  ],
86
91
  "name": "UIList",
92
+ "parts": {},
87
93
  "related": [
88
94
  "ListItem",
89
95
  "Tree",
@@ -28,7 +28,9 @@
28
28
  * When `selectable`:
29
29
  * - Children (role="listitem") become keyboard-focusable via roving tabindex.
30
30
  * - Click selects the child; key is its id or data-key.
31
- * - aria-selected is set on all children.
31
+ * - [selected] (ADR-0056, #1363 B7) and aria-selected are both set on
32
+ * all children — [selected] is the declared API state, aria-selected
33
+ * is wiring.
32
34
  * - Fires `selection-change` with { key, previousKey }.
33
35
  */
34
36
 
@@ -73,6 +75,7 @@ export class UIList extends UIElement {
73
75
  // (patient-visit rail's roving tabindex, gh#746).
74
76
  if (this.#stampedSelection) {
75
77
  for (const ch of this.#items()) {
78
+ ch.removeAttribute('selected');
76
79
  ch.removeAttribute('aria-selected');
77
80
  ch.removeAttribute('tabindex');
78
81
  }
@@ -87,6 +90,11 @@ export class UIList extends UIElement {
87
90
  for (const ch of items) {
88
91
  const k = this.#keyOf(ch);
89
92
  const selected = k && k === key;
93
+ // [selected] (ADR-0056, #1363 B7) is the declared, reflected API
94
+ // surface — parent-managed, mirrors <segment-ui>. aria-selected
95
+ // stays as-is: ARIA is wiring, not API.
96
+ if (selected) ch.setAttribute('selected', '');
97
+ else ch.removeAttribute('selected');
90
98
  ch.setAttribute('aria-selected', selected ? 'true' : 'false');
91
99
  ch.setAttribute('tabindex', selected ? '0' : '-1');
92
100
  if (selected) focusTarget = ch;
@@ -173,6 +181,11 @@ export class UIListItem extends UIElement {
173
181
  icon: { type: String, default: '', reflect: true },
174
182
  text: { type: String, default: '', reflect: true },
175
183
  description: { type: String, default: '', reflect: true },
184
+ // ADR-0056 (gh#1303, #1363 B7): declared reflected selection-item
185
+ // state, parent-managed — <list-ui>[selectable] stamps this instead
186
+ // of leaving selection visible only via aria-selected. Mirrors
187
+ // <segment-ui>'s [selected].
188
+ selected: { type: Boolean, default: false, reflect: true },
176
189
  };
177
190
 
178
191
  static template = () => null;
@@ -67,7 +67,18 @@
67
67
  background: var(--a-bg-hover);
68
68
  }
69
69
 
70
- :scope[selectable] > [role="listitem"][aria-selected="true"] {
70
+ /* [selected] is the declared, reflected state hook (ADR-0056, #1363 B7)
71
+ — list.class.js stamps it in lockstep with aria-selected; ARIA stays
72
+ wiring, not the style hook. Matched on the tag directly (not only
73
+ [role="listitem"]): UIList's adopt-or-stamp (gh#753) lets a
74
+ consumer-authored role (e.g. role="button") survive on <list-item-ui>
75
+ — #items() still selects/stamps it by TAG, so the style hook must
76
+ too, or a role-overridden selected row silently loses its selected
77
+ colors. The role fallback stays for non-list-item-ui children that
78
+ opt into role="listitem" themselves (list-ui also hosts "arbitrary
79
+ children", list.yaml). */
80
+ :scope[selectable] > list-item-ui[selected],
81
+ :scope[selectable] > [role="listitem"][selected] {
71
82
  background: var(--list-bg-selected);
72
83
  color: var(--list-fg-selected);
73
84
  border-inline-start-color: var(--list-border-selected);
@@ -125,7 +136,7 @@
125
136
  row-gap: var(--list-item-gap-row);
126
137
  font-size: var(--list-item-font-size);
127
138
  color: var(--list-item-text-color);
128
- line-height: 1.4;
139
+ line-height: var(--a-font-leading-normal);
129
140
  /* Defensive floor: empty list-item-ui (no text/icon/children) collapses
130
141
  to 0 height and disappears. Keep a visible row instead. */
131
142
  min-height: var(--a-space-6);
@@ -175,7 +186,7 @@
175
186
  grid-row: 2;
176
187
  color: var(--list-item-desc-color);
177
188
  font-size: var(--list-item-desc-font-size);
178
- line-height: 1.3;
189
+ line-height: var(--a-font-leading-normal);
179
190
  }
180
191
 
181
192
  /* When a [slot="action"] child is present, the grid becomes 3-column:
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * `<list-ui>` — Styled flat list with optional row dividers and icons — each row
3
3
  is a <list-item-ui> child. Selectable mode via [selectable] +
4
- [selectedKey] / `select` event. Composes <icon-ui> for row leading
5
- glyphs. Distinct from <nav-ui> (sidebar navigation, route-aware),
4
+ [selectedKey] / `selection-change` event. Composes <icon-ui> for row
5
+ leading glyphs. Distinct from <nav-ui> (sidebar navigation, route-aware),
6
6
  <tree-ui> (hierarchical with arbitrary nesting), and <table-ui>
7
7
  (tabular data with columns). Use list-ui for non-navigable,
8
8
  non-tabular vertical rows — comment lists, file lists, message
@@ -41,10 +41,10 @@ so content sits at the list-ui edges (canonical edge-to-edge style).
41
41
  divider: boolean;
42
42
  /** Enable selection on child listitems (roving tabindex + aria-selected). */
43
43
  selectable: boolean;
44
- /** ID (or data-key) of the currently-selected child listitem. */
44
+ /** ID (or data-key) of the currently-selected child listitem — drives each child's [selected] reflected prop (ADR-0056, #1363 B7). Kept as `selectedKey` rather than renamed to `value` (segmented/tabs/ select's parent-selection prop name): list rows are identified by DOM id/data-key, not an option value, and ADR-0056 itself governs only the child's own [selected] state surface, not this naming — a cross-family rename has no ratifying ADR (B5/B9-shaped follow-up). */
45
45
  selectedKey: string;
46
- /** Item spacing */
47
- spacing: string;
46
+ /** Item spacing scale — `sm`/`lg` modulate the per-item inset; `md` (default) is the base inset. */
47
+ spacing: 'sm' | 'md' | 'lg';
48
48
 
49
49
  addEventListener(type: 'selection-change', listener: (ev: ListSelectionChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
50
50
  addEventListener<K extends keyof HTMLElementEventMap>(
@@ -59,6 +59,8 @@ export class UIListItem extends UIElement {
59
59
  description: string;
60
60
  /** Optional leading icon name (Phosphor). */
61
61
  icon: string;
62
+ /** Whether this row is the current selection. Managed by the parent <list-ui>[selectable] — don't set directly; the parent's [selectedKey] is the single source of truth (ADR-0056). */
63
+ selected: boolean;
62
64
  /** Primary text. Renders as semibold inline body. */
63
65
  text: string;
64
66
  }
@@ -10,8 +10,8 @@ version: 1
10
10
  description: |
11
11
  Styled flat list with optional row dividers and icons — each row
12
12
  is a <list-item-ui> child. Selectable mode via [selectable] +
13
- [selectedKey] / `select` event. Composes <icon-ui> for row leading
14
- glyphs. Distinct from <nav-ui> (sidebar navigation, route-aware),
13
+ [selectedKey] / `selection-change` event. Composes <icon-ui> for row
14
+ leading glyphs. Distinct from <nav-ui> (sidebar navigation, route-aware),
15
15
  <tree-ui> (hierarchical with arbitrary nesting), and <table-ui>
16
16
  (tabular data with columns). Use list-ui for non-navigable,
17
17
  non-tabular vertical rows — comment lists, file lists, message
@@ -40,14 +40,22 @@ props:
40
40
  type: boolean
41
41
  default: false
42
42
  selectedKey:
43
- description: ID (or data-key) of the currently-selected child listitem.
43
+ description: >-
44
+ ID (or data-key) of the currently-selected child listitem — drives
45
+ each child's [selected] reflected prop (ADR-0056, #1363 B7). Kept
46
+ as `selectedKey` rather than renamed to `value` (segmented/tabs/
47
+ select's parent-selection prop name): list rows are identified by
48
+ DOM id/data-key, not an option value, and ADR-0056 itself governs
49
+ only the child's own [selected] state surface, not this naming —
50
+ a cross-family rename has no ratifying ADR (B5/B9-shaped follow-up).
44
51
  type: string
45
52
  default: ""
46
53
  attribute: selected-key
47
54
  spacing:
48
- description: Item spacing
55
+ description: Item spacing scale — `sm`/`lg` modulate the per-item inset; `md` (default) is the base inset.
49
56
  type: string
50
57
  default: md
58
+ enum: [sm, md, lg]
51
59
  events:
52
60
  selection-change:
53
61
  description: "Fired on selection-change."
@@ -68,10 +76,12 @@ a2ui:
68
76
  rules:
69
77
  - rule: 'Generic vertical list container — hosts <list-item-ui> or arbitrary children.'
70
78
  reason: 'Lowest-friction list primitive.'
71
- - rule: 'For interactive selection lists use <nav-ui> (single-select navigation) or <menu-ui> (action menu); list-ui is content display.'
72
- reason: 'Different interaction contracts.'
79
+ - rule: 'list-ui supports single selection natively via [selectable] + [selectedKey] (ADR-0056, #1363 B7) — the parent stamps the matching <list-item-ui>''s [selected] + aria-selected and fires selection-change. For route-aware navigation use <nav-ui> instead; for a popover action menu use <menu-ui> instead both have different interaction contracts than a plain selectable list.'
80
+ reason: 'list-ui selectable is the supported non-navigation, non-menu selection surface; nav-ui/menu-ui remain the right choice for their own contracts.'
73
81
  - rule: 'For data-grid / sortable / sticky-header needs use <table-ui> instead.'
74
82
  reason: 'Table has different semantics.'
83
+ - rule: 'list-ui carries no fire-and-forget "action" mode. [selectable] keeps a persisted single selection (`selectedKey` / `aria-selected`, roving tabindex); for rows that activate immediately with no persisted selection state use <action-list-ui> + <action-item-ui> instead.'
84
+ reason: 'Container-level decision (#1363 C5): kept separate rather than absorbed as a mode axis — stateful selection and fire-and-forget activation are genuinely different interaction contracts, and list-item-ui''s selection state is under active convergence elsewhere (#1379); rationale in gh#1374 Findings.'
75
85
  anti_patterns: []
76
86
  examples:
77
87
  - name: basic-list
@@ -179,6 +179,7 @@
179
179
  "10k-rows"
180
180
  ],
181
181
  "name": "UIListWindow",
182
+ "parts": {},
182
183
  "related": [
183
184
  "List",
184
185
  "ListItem",
@@ -44,6 +44,7 @@
44
44
  */
45
45
 
46
46
  import { UIElement } from '../../core/element.js';
47
+ import { isNode } from '../../core/dom.js';
47
48
 
48
49
  export class UIListWindow extends UIElement {
49
50
  static properties = {
@@ -616,7 +617,7 @@ export class UIListWindow extends UIElement {
616
617
  try { content = renderFn(item, index); }
617
618
  catch (err) { console.warn('[list-window-ui] render() threw:', err); }
618
619
  }
619
- if (content instanceof Node) {
620
+ if (isNode(content)) {
620
621
  row.appendChild(content);
621
622
  } else if (content != null) {
622
623
  row.textContent = String(content);
@@ -88,6 +88,7 @@
88
88
  "wait"
89
89
  ],
90
90
  "name": "UILoadingOverlay",
91
+ "parts": {},
91
92
  "related": [
92
93
  "Spinner",
93
94
  "Skeleton",
@@ -40,7 +40,7 @@
40
40
  "wrong": "<mark>matched</mark>"
41
41
  }
42
42
  ],
43
- "category": "typography",
43
+ "category": "display",
44
44
  "composes": [],
45
45
  "events": {},
46
46
  "examples": [
@@ -57,6 +57,7 @@
57
57
  "emphasis"
58
58
  ],
59
59
  "name": "UIMark",
60
+ "parts": {},
60
61
  "related": [
61
62
  "text",
62
63
  "tag"
@@ -3,7 +3,7 @@ name: UIMark
3
3
  tag: mark-ui
4
4
  status: stable
5
5
  component: Mark
6
- category: typography
6
+ category: display
7
7
  version: 1
8
8
  description: |
9
9
  Highlighted inline text — token-driven theme-aware wrapper around the
@@ -33,6 +33,7 @@
33
33
  "menu-rule"
34
34
  ],
35
35
  "name": "UIMenuDivider",
36
+ "parts": {},
36
37
  "related": [
37
38
  "Menu",
38
39
  "MenuItem",
@@ -68,11 +68,13 @@
68
68
  "dropdown-item"
69
69
  ],
70
70
  "name": "UIMenuItem",
71
+ "parts": {},
71
72
  "related": [
72
73
  "Menu",
73
74
  "MenuDivider",
74
75
  "Button",
75
- "NavItem"
76
+ "NavItem",
77
+ "ActionItem"
76
78
  ],
77
79
  "slots": {
78
80
  "icon": {
@@ -79,6 +79,11 @@ a2ui:
79
79
  Use slot="icon" / slot="text" only when you need custom markup
80
80
  (e.g. <avatar-ui slot="icon">, <kbd slot="trailing"> shortcut
81
81
  hint).
82
+ - >-
83
+ <action-item-ui> (child of <action-list-ui>) shares this row contract
84
+ (icon/text/subtitle/value/variant/disabled props, icon/text/subtitle/
85
+ trailing slot overrides) for inline, non-popover command rows — use
86
+ it instead when the surface isn't a <menu-ui> popover (#1363 C5).
82
87
 
83
88
  keywords:
84
89
  - menu-item
@@ -91,6 +96,7 @@ related:
91
96
  - MenuDivider
92
97
  - Button
93
98
  - NavItem
99
+ - ActionItem
94
100
 
95
101
  synonyms:
96
102
  menu-item: [dropdown-item, menu-row, popover-action]
@@ -39,6 +39,7 @@
39
39
  "menu-heading"
40
40
  ],
41
41
  "name": "UIMenuLabel",
42
+ "parts": {},
42
43
  "related": [
43
44
  "Menu",
44
45
  "MenuItem",
@@ -16,8 +16,8 @@
16
16
  "component": {
17
17
  "const": "Menu"
18
18
  },
19
- "gap": {
20
- "description": "Gap in px",
19
+ "offset": {
20
+ "description": "Pixel offset between the anchor (trigger) and the menu popover. Renamed from `[gap]` (gh#1335) — a raw-px number can't share a name with the global Scale-grammar `[gap]` attribute (ADR-0053); matches popover-ui's own `[offset]` (same anchorPopover() helper).",
21
21
  "type": "number",
22
22
  "default": 4
23
23
  },
@@ -81,6 +81,7 @@
81
81
  "right-click"
82
82
  ],
83
83
  "name": "UIMenu",
84
+ "parts": {},
84
85
  "related": [
85
86
  "MenuItem",
86
87
  "MenuDivider",
@@ -35,7 +35,7 @@ export class UIMenu extends UIElement {
35
35
  static properties = {
36
36
  open: { type: Boolean, default: false, reflect: true },
37
37
  placement: { type: String, default: 'bottom-start', reflect: true },
38
- gap: { type: Number, default: 4, reflect: true },
38
+ offset: { type: Number, default: 4, reflect: true },
39
39
  };
40
40
 
41
41
  static template = () => null;
@@ -103,7 +103,7 @@ export class UIMenu extends UIElement {
103
103
  this.#anchorCleanup?.();
104
104
  this.#anchorCleanup = anchorPopover(trigger, pop, {
105
105
  placement: this.placement,
106
- gap: this.gap,
106
+ gap: this.offset,
107
107
  });
108
108
 
109
109
  // Focus first enabled item (only when opened via keyboard).
@@ -22,8 +22,8 @@ export interface MenuActionEventDetail {
22
22
  export type MenuActionEvent = CustomEvent<MenuActionEventDetail>;
23
23
 
24
24
  export class UIMenu extends UIElement {
25
- /** Gap in px */
26
- gap: number;
25
+ /** Pixel offset between the anchor (trigger) and the menu popover. Renamed from `[gap]` (gh#1335) — a raw-px number can't share a name with the global Scale-grammar `[gap]` attribute (ADR-0053); matches popover-ui's own `[offset]` (same anchorPopover() helper). */
26
+ offset: number;
27
27
  /** Controls visibility via popover API */
28
28
  open: boolean;
29
29
  /** Preferred position relative to the anchor element */
@@ -13,8 +13,8 @@ description: Dropdown action menu with roving focus and keyboard navigation. Use
13
13
  composes:
14
14
  - icon-ui # leading affordances on menu items (created in render)
15
15
  props:
16
- gap:
17
- description: Gap in px
16
+ offset:
17
+ description: Pixel offset between the anchor (trigger) and the menu popover. Renamed from `[gap]` (gh#1335) — a raw-px number can't share a name with the global Scale-grammar `[gap]` attribute (ADR-0053); matches popover-ui's own `[offset]` (same anchorPopover() helper).
18
18
  type: number
19
19
  default: 4
20
20
  open:
@@ -83,7 +83,7 @@ a2ui:
83
83
  Set [placement="top-start"] or [placement="top-end"] when the
84
84
  trigger sits near the bottom of the viewport (statusbar / footer
85
85
  menus); default [placement="bottom-start"] otherwise. Adjust
86
- [gap] (default 4px) only when chrome demands it.
86
+ [offset] (default 4px) only when chrome demands it.
87
87
  anti_patterns: []
88
88
  examples:
89
89
  - name: basic-menu
@@ -66,6 +66,7 @@
66
66
  "modal"
67
67
  ],
68
68
  "name": "UIModal",
69
+ "parts": {},
69
70
  "related": [
70
71
  "Drawer",
71
72
  "Card",
@@ -98,6 +98,7 @@
98
98
  "links"
99
99
  ],
100
100
  "name": "UINav",
101
+ "parts": {},
101
102
  "related": [
102
103
  "NavGroup",
103
104
  "NavItem",
@@ -78,8 +78,20 @@ export class UINav extends UIElement {
78
78
  if (this.variant !== 'section') this.#updateTooltips();
79
79
  }
80
80
 
81
+ /**
82
+ * Collapsed = explicit [collapsed], or a rail narrower than 96px.
83
+ * linkedom (SSR — gh#1436's render sweep) has no getBoundingClientRect
84
+ * at all, so only the attribute can answer there. (A ZERO rect from a
85
+ * real pre-layout connect is the separate, unswept shape-3 question in
86
+ * ssr-compatibility's failure-shapes.md — not decided here.)
87
+ */
88
+ get #isCollapsed() {
89
+ return this.collapsed ||
90
+ (typeof this.getBoundingClientRect === 'function' && this.getBoundingClientRect().width <= 96);
91
+ }
92
+
81
93
  #updateTooltips() {
82
- const isCollapsed = this.collapsed || this.getBoundingClientRect().width <= 96;
94
+ const isCollapsed = this.#isCollapsed;
83
95
  for (const group of this.querySelectorAll(':scope > nav-group-ui')) {
84
96
  const header = group.querySelector(':scope > [slot="header"]');
85
97
  if (header) header.title = isCollapsed ? group.text : '';
@@ -143,8 +155,7 @@ export class UINav extends UIElement {
143
155
 
144
156
  const group = e.target.closest('nav-group-ui');
145
157
  if (group && this.contains(group)) {
146
- const isCollapsed = this.collapsed || this.getBoundingClientRect().width <= 96;
147
- if (isCollapsed) {
158
+ if (this.#isCollapsed) {
148
159
  // The flyout popover is appended INSIDE the group, so an option
149
160
  // click bubbles here after the option's own handler has selected
150
161
  // and hidePopover()'d — re-showing would instantly reopen the
@@ -80,7 +80,7 @@
80
80
  font-weight: var(--nav-label-weight);
81
81
  color: var(--nav-label-fg);
82
82
  text-transform: uppercase;
83
- letter-spacing: 0.06em;
83
+ letter-spacing: var(--a-font-tracking-wider);
84
84
  white-space: nowrap;
85
85
  overflow: hidden;
86
86
  }
@@ -134,7 +134,7 @@
134
134
  font-weight: var(--nav-label-weight);
135
135
  color: var(--nav-label-fg);
136
136
  text-transform: uppercase;
137
- letter-spacing: 0.06em;
137
+ letter-spacing: var(--a-font-tracking-wider);
138
138
  white-space: nowrap;
139
139
  overflow: hidden;
140
140
  }
@@ -92,6 +92,7 @@
92
92
  "menu"
93
93
  ],
94
94
  "name": "UINavGroup",
95
+ "parts": {},
95
96
  "related": [
96
97
  "Nav",
97
98
  "NavItem",
@@ -99,7 +99,9 @@ export class UINavGroup extends UIElement {
99
99
  // whole subtree includes this host's own [selected], which render()
100
100
  // reads anyway; render() writes only the icon's [weight], which the
101
101
  // attributeFilter excludes, so the observer can't feed back.
102
- if (!this.#selectionObserver) {
102
+ // Guarded like the other Observer sites (gh#285 §1 pattern) — SSR shims
103
+ // have no MutationObserver; teardown already uses `?.disconnect()`.
104
+ if (!this.#selectionObserver && typeof MutationObserver !== 'undefined') {
103
105
  this.#selectionObserver = new MutationObserver(this.#onChildSelection);
104
106
  this.#selectionObserver.observe(this, {
105
107
  subtree: true,
@@ -169,7 +169,7 @@
169
169
  background: var(--nav-group-badge-bg);
170
170
  padding: 1px var(--nav-group-badge-px);
171
171
  border-radius: var(--nav-group-badge-radius);
172
- line-height: 1.4;
172
+ line-height: var(--a-font-leading-normal);
173
173
  }
174
174
 
175
175
  [slot="header"] [slot="caret"] {
@@ -313,7 +313,7 @@ nav-group-ui [slot="popover-label"] {
313
313
  color: var(--nav-group-fg-muted);
314
314
  font-size: var(--a-ui-tiny);
315
315
  text-transform: uppercase;
316
- letter-spacing: 0.06em;
316
+ letter-spacing: var(--a-font-tracking-wider);
317
317
  }
318
318
 
319
319
  nav-group-ui [slot="popover"] [role="option"] {
@@ -364,7 +364,7 @@ nav-ui[variant="section"] > nav-group-ui:not([variant]) > [slot="header"] {
364
364
  font-weight: var(--a-weight-medium);
365
365
  color: var(--nav-group-fg-muted);
366
366
  text-transform: uppercase;
367
- letter-spacing: 0.06em;
367
+ letter-spacing: var(--a-font-tracking-wider);
368
368
  cursor: default;
369
369
  border-radius: 0;
370
370
  }
@@ -96,6 +96,7 @@
96
96
  "sidebar"
97
97
  ],
98
98
  "name": "UINavItem",
99
+ "parts": {},
99
100
  "related": [
100
101
  "Nav",
101
102
  "NavGroup",
@@ -136,7 +136,7 @@ nav-item-ui[selected] [slot="icon"]:empty::before {
136
136
  background: var(--nav-item-badge-bg);
137
137
  padding: 1px var(--nav-item-badge-px);
138
138
  border-radius: var(--nav-item-badge-radius);
139
- line-height: 1.4;
139
+ line-height: var(--a-font-leading-normal);
140
140
  margin-inline-start: auto;
141
141
  }
142
142
 
@@ -147,7 +147,7 @@ nav-item-ui[selected] [slot="icon"]:empty::before {
147
147
  border: 1px solid var(--nav-item-trailing-border);
148
148
  border-radius: var(--nav-item-trailing-radius);
149
149
  padding: 0 var(--nav-item-trailing-px);
150
- line-height: 1.6;
150
+ line-height: var(--a-font-leading-loose);
151
151
  flex-shrink: 0;
152
152
  }
153
153
 
@@ -156,6 +156,7 @@
156
156
  "noodles"
157
157
  ],
158
158
  "name": "UINoodles",
159
+ "parts": {},
159
160
  "related": [
160
161
  "Canvas",
161
162
  "EditorCanvas"
@@ -24,6 +24,7 @@
24
24
  */
25
25
 
26
26
  import { UIElement } from '../../core/element.js';
27
+ import { isElement } from '../../core/dom.js';
27
28
 
28
29
  let nextId = 0;
29
30
 
@@ -159,6 +160,9 @@ export class UINoodles extends UIElement {
159
160
 
160
161
  #scheduleUpdate() {
161
162
  if (this.#rafId) return;
163
+ // No rAF (SSR shim — gh#1436's render sweep) → no frame and no layout
164
+ // to measure connectors against; the client redraws on hydrate.
165
+ if (typeof requestAnimationFrame !== 'function') return;
162
166
  this.#rafId = requestAnimationFrame(() => {
163
167
  this.#rafId = null;
164
168
  this.#performUpdate();
@@ -251,7 +255,7 @@ export class UINoodles extends UIElement {
251
255
  // ── Element resolution ──────────────────────────────────────
252
256
 
253
257
  #resolveElement(ref) {
254
- if (ref instanceof HTMLElement) return ref;
258
+ if (isElement(ref)) return ref;
255
259
  if (typeof ref === 'string') return this.querySelector(`#${CSS.escape(ref)}`);
256
260
  if (typeof ref === 'number') return this.#getPortChildren()[ref] ?? null;
257
261
  return null;
@@ -143,6 +143,7 @@
143
143
  "intl"
144
144
  ],
145
145
  "name": "UINumberFormat",
146
+ "parts": {},
146
147
  "related": [
147
148
  "stat",
148
149
  "text",
@@ -101,6 +101,7 @@
101
101
  "registration"
102
102
  ],
103
103
  "name": "UIOptionCard",
104
+ "parts": {},
104
105
  "related": [
105
106
  "radio",
106
107
  "card",
@@ -77,7 +77,7 @@ option-card-ui[checked] [slot="icon"] {
77
77
  --option-card-heading-size: var(--a-ui-size);
78
78
  --option-card-desc-color: var(--a-fg-muted);
79
79
  --option-card-desc-size: var(--a-ui-sm);
80
- --option-card-desc-line-height: 1.4;
80
+ --option-card-desc-line-height: var(--a-font-leading-relaxed);
81
81
  --option-card-icon-color: var(--md-sys-color-neutral-on-surface-variant);
82
82
  --option-card-icon-color-checked: var(--a-fg-strong);
83
83
  --option-card-icon-size: 1.5rem;