@adia-ai/web-components 0.6.33 → 0.6.35

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 (391) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/color/index.js +1 -1
  3. package/components/accordion/accordion-item.yaml +2 -2
  4. package/components/accordion/accordion.css +2 -2
  5. package/components/accordion/accordion.js +1 -1
  6. package/components/action-list/action-item.yaml +2 -2
  7. package/components/action-list/action-list.css +2 -2
  8. package/components/action-list/action-list.js +1 -1
  9. package/components/agent-artifact/{class.js → agent-artifact.class.js} +1 -1
  10. package/components/agent-artifact/agent-artifact.css +31 -31
  11. package/components/agent-artifact/agent-artifact.js +1 -1
  12. package/components/agent-feedback-bar/agent-feedback-bar.css +10 -10
  13. package/components/agent-feedback-bar/agent-feedback-bar.js +1 -1
  14. package/components/agent-questions/agent-questions.css +57 -57
  15. package/components/agent-questions/agent-questions.js +1 -1
  16. package/components/agent-reasoning/agent-reasoning.css +62 -62
  17. package/components/agent-reasoning/agent-reasoning.js +1 -1
  18. package/components/agent-suggestions/agent-suggestions.css +4 -4
  19. package/components/agent-suggestions/agent-suggestions.js +1 -1
  20. package/components/agent-trace/agent-trace.css +53 -53
  21. package/components/alert/alert.a2ui.json +64 -1
  22. package/components/alert/{class.js → alert.class.js} +189 -2
  23. package/components/alert/alert.css +119 -41
  24. package/components/alert/alert.d.ts +14 -0
  25. package/components/alert/alert.js +1 -1
  26. package/components/alert/alert.test.js +184 -0
  27. package/components/alert/alert.yaml +114 -1
  28. package/components/avatar/avatar-group.yaml +2 -2
  29. package/components/avatar/avatar.css +27 -27
  30. package/components/avatar/avatar.js +1 -1
  31. package/components/badge/badge.css +27 -27
  32. package/components/badge/badge.js +1 -1
  33. package/components/block/block.css +16 -16
  34. package/components/block/block.js +1 -1
  35. package/components/breadcrumb/breadcrumb.css +23 -23
  36. package/components/breadcrumb/breadcrumb.js +1 -1
  37. package/components/button/button.css +101 -91
  38. package/components/button/button.js +1 -1
  39. package/components/calendar-grid/calendar-grid.a2ui.json +146 -0
  40. package/components/calendar-grid/calendar-grid.class.js +326 -0
  41. package/components/calendar-grid/calendar-grid.css +246 -0
  42. package/components/calendar-grid/calendar-grid.d.ts +41 -0
  43. package/components/calendar-grid/calendar-grid.js +17 -0
  44. package/components/calendar-grid/calendar-grid.yaml +136 -0
  45. package/components/calendar-picker/calendar-picker.css +139 -139
  46. package/components/calendar-picker/calendar-picker.js +1 -1
  47. package/components/canvas/canvas.css +12 -12
  48. package/components/card/card.css +83 -83
  49. package/components/card/card.js +1 -1
  50. package/components/chart/chart.css +224 -224
  51. package/components/chart/chart.js +1 -1
  52. package/components/chart-legend/chart-legend.css +26 -26
  53. package/components/chart-legend/chart-legend.js +1 -1
  54. package/components/chat-thread/chat-input.a2ui.json +1 -1
  55. package/components/chat-thread/chat-input.js +6 -1
  56. package/components/chat-thread/chat-input.yaml +4 -1
  57. package/components/chat-thread/chat-thread.js +1 -1
  58. package/components/check/check.css +40 -40
  59. package/components/check/check.js +1 -1
  60. package/components/code/code.css +125 -125
  61. package/components/code/code.js +1 -1
  62. package/components/col/col.css +15 -15
  63. package/components/col/col.js +1 -1
  64. package/components/color-input/color-input.js +1 -1
  65. package/components/color-picker/color-picker.css +55 -55
  66. package/components/color-picker/color-picker.js +1 -1
  67. package/components/combobox/combobox.a2ui.json +363 -0
  68. package/components/combobox/combobox.class.js +861 -0
  69. package/components/combobox/combobox.css +244 -0
  70. package/components/combobox/combobox.d.ts +113 -0
  71. package/components/combobox/combobox.examples.md +59 -0
  72. package/components/combobox/combobox.js +17 -0
  73. package/components/combobox/combobox.test.js +181 -0
  74. package/components/combobox/combobox.yaml +369 -0
  75. package/components/command/command.css +90 -90
  76. package/components/command/command.js +1 -1
  77. package/components/date-range-picker/date-range-picker.a2ui.json +300 -0
  78. package/components/date-range-picker/date-range-picker.class.js +791 -0
  79. package/components/date-range-picker/date-range-picker.css +224 -0
  80. package/components/date-range-picker/date-range-picker.d.ts +82 -0
  81. package/components/date-range-picker/date-range-picker.examples.md +37 -0
  82. package/components/date-range-picker/date-range-picker.js +17 -0
  83. package/components/date-range-picker/date-range-picker.test.js +387 -0
  84. package/components/date-range-picker/date-range-picker.yaml +285 -0
  85. package/components/datetime-picker/datetime-picker.a2ui.json +334 -0
  86. package/components/datetime-picker/datetime-picker.class.js +706 -0
  87. package/components/datetime-picker/datetime-picker.css +150 -0
  88. package/components/datetime-picker/datetime-picker.d.ts +86 -0
  89. package/components/datetime-picker/datetime-picker.examples.md +46 -0
  90. package/components/datetime-picker/datetime-picker.js +17 -0
  91. package/components/datetime-picker/datetime-picker.test.js +454 -0
  92. package/components/datetime-picker/datetime-picker.yaml +332 -0
  93. package/components/demo-toggle/demo-toggle.css +27 -27
  94. package/components/demo-toggle/demo-toggle.js +1 -1
  95. package/components/description-list/description-list.css +18 -18
  96. package/components/description-list/description-list.js +1 -1
  97. package/components/divider/divider.css +24 -24
  98. package/components/divider/divider.js +1 -1
  99. package/components/drawer/drawer.js +1 -1
  100. package/components/embed/embed.css +6 -6
  101. package/components/embed/embed.js +1 -1
  102. package/components/empty-state/empty-state.css +27 -27
  103. package/components/empty-state/empty-state.js +1 -1
  104. package/components/feed/feed.css +12 -12
  105. package/components/feed/feed.js +1 -1
  106. package/components/field/field.css +28 -28
  107. package/components/field/field.js +1 -1
  108. package/components/field/field.test.js +1 -1
  109. package/components/fields/fields.css +5 -5
  110. package/components/fields/fields.js +1 -1
  111. package/components/grid/grid.css +5 -5
  112. package/components/grid/grid.js +1 -1
  113. package/components/heatmap/heatmap.css +63 -63
  114. package/components/heatmap/heatmap.js +1 -1
  115. package/components/icon/icon.css +12 -12
  116. package/components/icon/icon.js +1 -1
  117. package/components/image/image.css +14 -14
  118. package/components/image/image.js +1 -1
  119. package/components/index.js +11 -0
  120. package/components/inline-message/inline-message.a2ui.json +143 -0
  121. package/components/inline-message/inline-message.class.js +169 -0
  122. package/components/inline-message/inline-message.css +75 -0
  123. package/components/inline-message/inline-message.d.ts +31 -0
  124. package/components/inline-message/inline-message.examples.md +19 -0
  125. package/components/inline-message/inline-message.js +17 -0
  126. package/components/inline-message/inline-message.test.js +203 -0
  127. package/components/inline-message/inline-message.yaml +205 -0
  128. package/components/input/input.css +67 -67
  129. package/components/input/input.js +1 -1
  130. package/components/input/input.yaml +5 -4
  131. package/components/inspector/inspector.css +6 -6
  132. package/components/inspector/inspector.js +1 -1
  133. package/components/integration-card/integration-card.a2ui.json +268 -0
  134. package/components/integration-card/integration-card.class.js +410 -0
  135. package/components/integration-card/integration-card.css +169 -0
  136. package/components/integration-card/integration-card.d.ts +63 -0
  137. package/components/integration-card/integration-card.examples.md +41 -0
  138. package/components/integration-card/integration-card.js +17 -0
  139. package/components/integration-card/integration-card.test.js +306 -0
  140. package/components/integration-card/integration-card.yaml +280 -0
  141. package/components/kbd/kbd.css +32 -32
  142. package/components/kbd/kbd.js +1 -1
  143. package/components/link/link.css +12 -12
  144. package/components/link/link.js +1 -1
  145. package/components/list/list-item.yaml +2 -2
  146. package/components/list/list.css +8 -8
  147. package/components/list/list.js +1 -1
  148. package/components/list-window/list-window.a2ui.json +277 -0
  149. package/components/list-window/list-window.class.js +688 -0
  150. package/components/list-window/list-window.css +124 -0
  151. package/components/list-window/list-window.d.ts +84 -0
  152. package/components/list-window/list-window.examples.md +73 -0
  153. package/components/list-window/list-window.js +17 -0
  154. package/components/list-window/list-window.test.js +303 -0
  155. package/components/list-window/list-window.yaml +270 -0
  156. package/components/loading-overlay/loading-overlay.a2ui.json +176 -0
  157. package/components/loading-overlay/loading-overlay.class.js +203 -0
  158. package/components/loading-overlay/loading-overlay.css +81 -0
  159. package/components/loading-overlay/loading-overlay.d.ts +24 -0
  160. package/components/loading-overlay/loading-overlay.examples.md +50 -0
  161. package/components/loading-overlay/loading-overlay.js +17 -0
  162. package/components/loading-overlay/loading-overlay.test.js +257 -0
  163. package/components/loading-overlay/loading-overlay.yaml +260 -0
  164. package/components/menu/menu-divider.yaml +1 -1
  165. package/components/menu/menu-item.yaml +1 -1
  166. package/components/menu/menu.a2ui.json +3 -0
  167. package/components/menu/menu.css +8 -8
  168. package/components/menu/menu.js +1 -1
  169. package/components/menu/menu.yaml +7 -0
  170. package/components/modal/{class.js → modal.class.js} +12 -1
  171. package/components/modal/modal.css +54 -44
  172. package/components/modal/modal.js +1 -1
  173. package/components/nav/nav.css +40 -40
  174. package/components/nav/nav.js +1 -1
  175. package/components/nav-group/nav-group.css +52 -52
  176. package/components/nav-group/nav-group.js +1 -1
  177. package/components/nav-item/nav-item.css +44 -44
  178. package/components/nav-item/nav-item.js +1 -1
  179. package/components/noodles/noodles.css +31 -31
  180. package/components/noodles/noodles.js +1 -1
  181. package/components/option-card/option-card.css +69 -69
  182. package/components/option-card/option-card.js +1 -1
  183. package/components/otp-input/otp-input.css +30 -30
  184. package/components/otp-input/otp-input.js +1 -1
  185. package/components/page/page.css +18 -18
  186. package/components/page/page.js +1 -1
  187. package/components/pagination/pagination.css +61 -61
  188. package/components/pagination/pagination.js +1 -1
  189. package/components/pane/pane.css +57 -57
  190. package/components/pane/pane.js +1 -1
  191. package/components/pipeline-status/pipeline-status.css +65 -65
  192. package/components/pipeline-status/pipeline-status.js +1 -1
  193. package/components/popover/popover.a2ui.json +8 -1
  194. package/components/popover/popover.css +17 -17
  195. package/components/popover/popover.js +1 -1
  196. package/components/popover/popover.yaml +14 -1
  197. package/components/progress/progress.css +23 -23
  198. package/components/progress/progress.js +1 -1
  199. package/components/progress-row/progress-row.css +17 -17
  200. package/components/progress-row/progress-row.js +1 -1
  201. package/components/radio/radio.css +39 -39
  202. package/components/radio/radio.js +1 -1
  203. package/components/range/range.css +55 -55
  204. package/components/range/range.js +1 -1
  205. package/components/rating/rating.css +28 -28
  206. package/components/rating/rating.js +1 -1
  207. package/components/richtext/richtext.css +133 -133
  208. package/components/richtext/richtext.js +1 -1
  209. package/components/row/row.css +19 -19
  210. package/components/row/row.js +1 -1
  211. package/components/search/search.css +5 -5
  212. package/components/search/search.js +1 -1
  213. package/components/segment/segment.css +24 -24
  214. package/components/segment/segment.js +1 -1
  215. package/components/segmented/segmented.css +25 -25
  216. package/components/segmented/segmented.js +1 -1
  217. package/components/select/select.a2ui.json +58 -4
  218. package/components/select/{class.js → select.class.js} +415 -6
  219. package/components/select/select.css +242 -84
  220. package/components/select/select.d.ts +31 -1
  221. package/components/select/select.js +1 -1
  222. package/components/select/select.test.js +202 -0
  223. package/components/select/select.yaml +126 -5
  224. package/components/skeleton/skeleton.css +14 -14
  225. package/components/skeleton/skeleton.js +1 -1
  226. package/components/slider/slider.css +46 -46
  227. package/components/slider/slider.js +1 -1
  228. package/components/spinner/spinner.a2ui.json +198 -0
  229. package/components/spinner/spinner.class.js +99 -0
  230. package/components/spinner/spinner.css +221 -0
  231. package/components/spinner/spinner.d.ts +26 -0
  232. package/components/spinner/spinner.examples.md +26 -0
  233. package/components/spinner/spinner.js +17 -0
  234. package/components/spinner/spinner.test.js +272 -0
  235. package/components/spinner/spinner.yaml +238 -0
  236. package/components/stack/stack.css +11 -11
  237. package/components/stack/stack.js +1 -1
  238. package/components/stat/stat.css +25 -25
  239. package/components/step-progress/step-progress.css +20 -20
  240. package/components/step-progress/step-progress.js +1 -1
  241. package/components/stepper/stepper-item.yaml +1 -1
  242. package/components/stepper/stepper.css +29 -29
  243. package/components/stepper/stepper.js +1 -1
  244. package/components/stream/stream.css +12 -12
  245. package/components/stream/stream.js +1 -1
  246. package/components/swatch/swatch.css +68 -68
  247. package/components/swatch/swatch.js +1 -1
  248. package/components/swiper/swiper.css +57 -57
  249. package/components/swiper/swiper.js +1 -1
  250. package/components/switch/switch.css +52 -52
  251. package/components/switch/switch.js +1 -1
  252. package/components/table/table.css +163 -163
  253. package/components/table/table.js +1 -1
  254. package/components/table-toolbar/{class.js → table-toolbar.class.js} +1 -1
  255. package/components/table-toolbar/table-toolbar.css +32 -32
  256. package/components/table-toolbar/table-toolbar.js +1 -1
  257. package/components/tabs/tab.yaml +2 -2
  258. package/components/tabs/tabs.css +51 -51
  259. package/components/tabs/tabs.js +1 -1
  260. package/components/tag/tag.css +48 -48
  261. package/components/tag/tag.js +1 -1
  262. package/components/tags-input/tags-input.a2ui.json +337 -0
  263. package/components/tags-input/tags-input.class.js +776 -0
  264. package/components/tags-input/tags-input.css +201 -0
  265. package/components/tags-input/tags-input.d.ts +120 -0
  266. package/components/tags-input/tags-input.examples.md +92 -0
  267. package/components/tags-input/tags-input.js +17 -0
  268. package/components/tags-input/tags-input.test.js +368 -0
  269. package/components/tags-input/tags-input.yaml +367 -0
  270. package/components/text/text.css +44 -44
  271. package/components/text/text.js +1 -1
  272. package/components/textarea/textarea.a2ui.json +1 -1
  273. package/components/textarea/textarea.css +46 -46
  274. package/components/textarea/textarea.js +1 -1
  275. package/components/textarea/textarea.yaml +11 -8
  276. package/components/time-picker/time-picker.a2ui.json +267 -0
  277. package/components/time-picker/time-picker.class.js +693 -0
  278. package/components/time-picker/time-picker.css +122 -0
  279. package/components/time-picker/time-picker.d.ts +75 -0
  280. package/components/time-picker/time-picker.examples.md +35 -0
  281. package/components/time-picker/time-picker.js +17 -0
  282. package/components/time-picker/time-picker.test.js +287 -0
  283. package/components/time-picker/time-picker.yaml +256 -0
  284. package/components/timeline/timeline-item.yaml +2 -2
  285. package/components/timeline/{class.js → timeline.class.js} +1 -1
  286. package/components/timeline/timeline.css +50 -50
  287. package/components/timeline/timeline.js +1 -1
  288. package/components/toast/toast.css +58 -58
  289. package/components/toast/toast.js +1 -1
  290. package/components/toggle-group/toggle-group.css +6 -6
  291. package/components/toggle-group/toggle-group.js +1 -1
  292. package/components/toggle-group/toggle-option.yaml +1 -1
  293. package/components/toggle-scheme/toggle-scheme.css +2 -2
  294. package/components/toggle-scheme/toggle-scheme.js +1 -1
  295. package/components/toolbar/toolbar-group.yaml +1 -1
  296. package/components/toolbar/toolbar.css +17 -17
  297. package/components/toolbar/toolbar.js +1 -1
  298. package/components/tooltip/tooltip.css +2 -2
  299. package/components/tooltip/tooltip.js +1 -1
  300. package/components/tree/tree-item.yaml +1 -1
  301. package/components/tree/tree.css +37 -37
  302. package/components/tree/tree.js +1 -1
  303. package/components/upload/upload.css +49 -49
  304. package/components/upload/upload.js +1 -1
  305. package/dist/web-components.min.css +1 -1
  306. package/dist/web-components.min.js +146 -87
  307. package/package.json +3 -3
  308. package/styles/components.css +11 -0
  309. /package/components/accordion/{class.js → accordion.class.js} +0 -0
  310. /package/components/action-list/{class.js → action-list.class.js} +0 -0
  311. /package/components/agent-feedback-bar/{class.js → agent-feedback-bar.class.js} +0 -0
  312. /package/components/agent-questions/{class.js → agent-questions.class.js} +0 -0
  313. /package/components/agent-reasoning/{class.js → agent-reasoning.class.js} +0 -0
  314. /package/components/agent-suggestions/{class.js → agent-suggestions.class.js} +0 -0
  315. /package/components/avatar/{class.js → avatar.class.js} +0 -0
  316. /package/components/badge/{class.js → badge.class.js} +0 -0
  317. /package/components/block/{class.js → block.class.js} +0 -0
  318. /package/components/breadcrumb/{class.js → breadcrumb.class.js} +0 -0
  319. /package/components/button/{class.js → button.class.js} +0 -0
  320. /package/components/calendar-picker/{class.js → calendar-picker.class.js} +0 -0
  321. /package/components/card/{class.js → card.class.js} +0 -0
  322. /package/components/chart/{class.js → chart.class.js} +0 -0
  323. /package/components/chart-legend/{class.js → chart-legend.class.js} +0 -0
  324. /package/components/chat-thread/{class.js → chat-thread.class.js} +0 -0
  325. /package/components/check/{class.js → check.class.js} +0 -0
  326. /package/components/code/{class.js → code.class.js} +0 -0
  327. /package/components/col/{class.js → col.class.js} +0 -0
  328. /package/components/color-input/{class.js → color-input.class.js} +0 -0
  329. /package/components/color-picker/{class.js → color-picker.class.js} +0 -0
  330. /package/components/command/{class.js → command.class.js} +0 -0
  331. /package/components/demo-toggle/{class.js → demo-toggle.class.js} +0 -0
  332. /package/components/description-list/{class.js → description-list.class.js} +0 -0
  333. /package/components/divider/{class.js → divider.class.js} +0 -0
  334. /package/components/drawer/{class.js → drawer.class.js} +0 -0
  335. /package/components/embed/{class.js → embed.class.js} +0 -0
  336. /package/components/empty-state/{class.js → empty-state.class.js} +0 -0
  337. /package/components/feed/{class.js → feed.class.js} +0 -0
  338. /package/components/field/{class.js → field.class.js} +0 -0
  339. /package/components/fields/{class.js → fields.class.js} +0 -0
  340. /package/components/grid/{class.js → grid.class.js} +0 -0
  341. /package/components/heatmap/{class.js → heatmap.class.js} +0 -0
  342. /package/components/icon/{class.js → icon.class.js} +0 -0
  343. /package/components/image/{class.js → image.class.js} +0 -0
  344. /package/components/input/{class.js → input.class.js} +0 -0
  345. /package/components/inspector/{class.js → inspector.class.js} +0 -0
  346. /package/components/kbd/{class.js → kbd.class.js} +0 -0
  347. /package/components/link/{class.js → link.class.js} +0 -0
  348. /package/components/list/{class.js → list.class.js} +0 -0
  349. /package/components/menu/{class.js → menu.class.js} +0 -0
  350. /package/components/nav/{class.js → nav.class.js} +0 -0
  351. /package/components/nav-group/{class.js → nav-group.class.js} +0 -0
  352. /package/components/nav-item/{class.js → nav-item.class.js} +0 -0
  353. /package/components/noodles/{class.js → noodles.class.js} +0 -0
  354. /package/components/option-card/{class.js → option-card.class.js} +0 -0
  355. /package/components/otp-input/{class.js → otp-input.class.js} +0 -0
  356. /package/components/page/{class.js → page.class.js} +0 -0
  357. /package/components/pagination/{class.js → pagination.class.js} +0 -0
  358. /package/components/pane/{class.js → pane.class.js} +0 -0
  359. /package/components/pipeline-status/{class.js → pipeline-status.class.js} +0 -0
  360. /package/components/popover/{class.js → popover.class.js} +0 -0
  361. /package/components/progress/{class.js → progress.class.js} +0 -0
  362. /package/components/progress-row/{class.js → progress-row.class.js} +0 -0
  363. /package/components/radio/{class.js → radio.class.js} +0 -0
  364. /package/components/range/{class.js → range.class.js} +0 -0
  365. /package/components/rating/{class.js → rating.class.js} +0 -0
  366. /package/components/richtext/{class.js → richtext.class.js} +0 -0
  367. /package/components/row/{class.js → row.class.js} +0 -0
  368. /package/components/search/{class.js → search.class.js} +0 -0
  369. /package/components/segment/{class.js → segment.class.js} +0 -0
  370. /package/components/segmented/{class.js → segmented.class.js} +0 -0
  371. /package/components/skeleton/{class.js → skeleton.class.js} +0 -0
  372. /package/components/slider/{class.js → slider.class.js} +0 -0
  373. /package/components/stack/{class.js → stack.class.js} +0 -0
  374. /package/components/step-progress/{class.js → step-progress.class.js} +0 -0
  375. /package/components/stepper/{class.js → stepper.class.js} +0 -0
  376. /package/components/stream/{class.js → stream.class.js} +0 -0
  377. /package/components/swatch/{class.js → swatch.class.js} +0 -0
  378. /package/components/swiper/{class.js → swiper.class.js} +0 -0
  379. /package/components/switch/{class.js → switch.class.js} +0 -0
  380. /package/components/table/{class.js → table.class.js} +0 -0
  381. /package/components/tabs/{class.js → tabs.class.js} +0 -0
  382. /package/components/tag/{class.js → tag.class.js} +0 -0
  383. /package/components/text/{class.js → text.class.js} +0 -0
  384. /package/components/textarea/{class.js → textarea.class.js} +0 -0
  385. /package/components/toast/{class.js → toast.class.js} +0 -0
  386. /package/components/toggle-group/{class.js → toggle-group.class.js} +0 -0
  387. /package/components/toggle-scheme/{class.js → toggle-scheme.class.js} +0 -0
  388. /package/components/toolbar/{class.js → toolbar.class.js} +0 -0
  389. /package/components/tooltip/{class.js → tooltip.class.js} +0 -0
  390. /package/components/tree/{class.js → tree.class.js} +0 -0
  391. /package/components/upload/{class.js → upload.class.js} +0 -0
@@ -86,4 +86,206 @@ describe('select-ui', () => {
86
86
 
87
87
  expect(selected).toEqual(['b']);
88
88
  });
89
+
90
+ // ── SPEC-040 (multi-select) ──
91
+
92
+ it('multi-select: [multiple] sets data-multi-chips and renders tag-ui chips per selected value', async () => {
93
+ const s = mount(`
94
+ <select-ui multiple value="a,c">
95
+ <option value="a">Alpha</option>
96
+ <option value="b">Beta</option>
97
+ <option value="c">Gamma</option>
98
+ </select-ui>
99
+ `);
100
+ await tick();
101
+ expect(s.hasAttribute('data-multi-chips')).toBe(true);
102
+ const chips = s.querySelectorAll('[slot="trigger"] [data-chips] tag-ui');
103
+ expect(chips.length).toBe(2);
104
+ const chipValues = Array.from(chips).map((c) => c.dataset.chipValue);
105
+ expect(chipValues).toContain('a');
106
+ expect(chipValues).toContain('c');
107
+ });
108
+
109
+ it('multi-select: aria-multiselectable=true is set on the listbox', async () => {
110
+ const s = mount(`
111
+ <select-ui multiple open>
112
+ <option value="a">Alpha</option>
113
+ <option value="b">Beta</option>
114
+ </select-ui>
115
+ `);
116
+ await tick();
117
+ const lb = s.querySelector('[slot="listbox"]');
118
+ expect(lb).toBeTruthy();
119
+ expect(lb.getAttribute('aria-multiselectable')).toBe('true');
120
+ });
121
+
122
+ it('multi-select: clicking an option toggles selection without closing the popover', async () => {
123
+ const s = mount(`
124
+ <select-ui multiple open>
125
+ <option value="a">Alpha</option>
126
+ <option value="b">Beta</option>
127
+ <option value="c">Gamma</option>
128
+ </select-ui>
129
+ `);
130
+ await tick();
131
+ const opts = s.querySelectorAll('[role="option"]');
132
+ const optA = Array.from(opts).find((o) => o.getAttribute('data-value') === 'a');
133
+ optA.click();
134
+ await tick();
135
+ expect(s.open).toBe(true); // still open
136
+ expect(s.value).toBe('a');
137
+
138
+ const optC = Array.from(s.querySelectorAll('[role="option"]')).find((o) => o.getAttribute('data-value') === 'c');
139
+ optC.click();
140
+ await tick();
141
+ expect(s.open).toBe(true);
142
+ const parts = new Set(s.value.split(','));
143
+ expect(parts.has('a')).toBe(true);
144
+ expect(parts.has('c')).toBe(true);
145
+ });
146
+
147
+ it('multi-select: Backspace from the trigger removes the last chip', async () => {
148
+ const s = mount(`
149
+ <select-ui multiple value="a,b">
150
+ <option value="a">Alpha</option>
151
+ <option value="b">Beta</option>
152
+ </select-ui>
153
+ `);
154
+ await tick();
155
+ const ev = new KeyboardEvent('keydown', { key: 'Backspace', bubbles: true });
156
+ s.dispatchEvent(ev);
157
+ await tick();
158
+ expect(s.value).toBe('a');
159
+ });
160
+
161
+ it('multi-select: toggle(id) is a public API', async () => {
162
+ const s = mount(`
163
+ <select-ui multiple>
164
+ <option value="a">Alpha</option>
165
+ <option value="b">Beta</option>
166
+ </select-ui>
167
+ `);
168
+ await tick();
169
+ s.toggle('a');
170
+ await tick();
171
+ expect(s.value).toBe('a');
172
+ s.toggle('a');
173
+ await tick();
174
+ expect(s.value).toBe('');
175
+ });
176
+
177
+ it('multi-select: [max] suppresses further selection and fires invalid', async () => {
178
+ const s = mount(`
179
+ <select-ui multiple max="2" value="a,b">
180
+ <option value="a">Alpha</option>
181
+ <option value="b">Beta</option>
182
+ <option value="c">Gamma</option>
183
+ </select-ui>
184
+ `);
185
+ await tick();
186
+ let invalidFired = null;
187
+ s.addEventListener('invalid', (e) => { invalidFired = e.detail; });
188
+ s.toggle('c');
189
+ await tick();
190
+ expect(invalidFired).toBeTruthy();
191
+ expect(invalidFired.reason).toBe('max');
192
+ expect(s.value).toBe('a,b'); // unchanged
193
+ });
194
+
195
+ it('multi-select: clear() empties value and fires change with removed array', async () => {
196
+ const s = mount(`
197
+ <select-ui multiple value="a,b">
198
+ <option value="a">Alpha</option>
199
+ <option value="b">Beta</option>
200
+ </select-ui>
201
+ `);
202
+ await tick();
203
+ let changed = null;
204
+ s.addEventListener('change', (e) => { changed = e.detail; });
205
+ s.clear();
206
+ await tick();
207
+ expect(s.value).toBe('');
208
+ expect(changed.removed).toEqual(['a', 'b']);
209
+ });
210
+
211
+ it('multi-select: selectAllOptions() selects every non-disabled option', async () => {
212
+ const s = mount(`
213
+ <select-ui multiple>
214
+ <option value="a">Alpha</option>
215
+ <option value="b">Beta</option>
216
+ <option value="c" disabled>Gamma</option>
217
+ </select-ui>
218
+ `);
219
+ await tick();
220
+ s.selectAllOptions();
221
+ await tick();
222
+ const parts = new Set(s.value.split(','));
223
+ expect(parts.has('a')).toBe(true);
224
+ expect(parts.has('b')).toBe(true);
225
+ expect(parts.has('c')).toBe(false); // disabled
226
+ });
227
+
228
+ it('multi-select: [max-chips] shows "+N more" pill when exceeded', async () => {
229
+ const s = mount(`
230
+ <select-ui multiple max-chips="2" value="a,b,c,d">
231
+ <option value="a">Alpha</option>
232
+ <option value="b">Beta</option>
233
+ <option value="c">Gamma</option>
234
+ <option value="d">Delta</option>
235
+ </select-ui>
236
+ `);
237
+ await tick();
238
+ const chips = s.querySelectorAll('[slot="trigger"] [data-chips] tag-ui');
239
+ expect(chips.length).toBe(2);
240
+ const more = s.querySelector('[slot="trigger"] [data-more]');
241
+ expect(more).toBeTruthy();
242
+ expect(more.textContent).toBe('+2 more');
243
+ });
244
+
245
+ it('multi-select: [clearable] reveals the clear-all button when chips present', async () => {
246
+ const s = mount(`
247
+ <select-ui multiple clearable value="a">
248
+ <option value="a">Alpha</option>
249
+ <option value="b">Beta</option>
250
+ </select-ui>
251
+ `);
252
+ await tick();
253
+ const clearBtn = s.querySelector('[data-clear-all]');
254
+ expect(clearBtn).toBeTruthy();
255
+ expect(clearBtn.hasAttribute('hidden')).toBe(false);
256
+ });
257
+
258
+ it('multi-select: [select-all] renders the bulk-action header', async () => {
259
+ const s = mount(`
260
+ <select-ui multiple select-all open>
261
+ <option value="a">Alpha</option>
262
+ <option value="b">Beta</option>
263
+ </select-ui>
264
+ `);
265
+ await tick();
266
+ const header = s.querySelector('[slot="listbox"] [data-select-all]');
267
+ expect(header).toBeTruthy();
268
+ const btn = header.querySelector('[data-select-all-btn]');
269
+ expect(btn).toBeTruthy();
270
+ expect(btn.textContent).toBe('Select all');
271
+ });
272
+
273
+ it('multi-select: chip remove event empties that selection from value', async () => {
274
+ const s = mount(`
275
+ <select-ui multiple value="a,b">
276
+ <option value="a">Alpha</option>
277
+ <option value="b">Beta</option>
278
+ </select-ui>
279
+ `);
280
+ await tick();
281
+ const chipA = s.querySelector('tag-ui[data-chip-value="a"]');
282
+ expect(chipA).toBeTruthy();
283
+ // Simulate tag-ui's remove event (bubbles, with detail.text)
284
+ chipA.dispatchEvent(new CustomEvent('remove', {
285
+ bubbles: true,
286
+ detail: { text: 'Alpha', value: 'Alpha' },
287
+ }));
288
+ await tick();
289
+ expect(s.value).toBe('b');
290
+ });
89
291
  });
@@ -8,17 +8,23 @@ component: Select
8
8
  category: input
9
9
  version: 1
10
10
  description: |
11
- Single-select dropdown primitive — the canonical AdiaUI select
12
- control. Form-bearing via UIFormElement: [name], [value],
11
+ Single- and multi-select dropdown primitive — the canonical AdiaUI
12
+ select control. Form-bearing via UIFormElement: [name], [value],
13
13
  [required], [disabled], fires `change`. Options via native
14
14
  <option> / <optgroup> children, programmatic `.options` array, or
15
15
  JSON [data-options] (hydrated by <editor-shell>'s wireSelects).
16
16
  Use for single-select with > 4 options; for ≤ 4 options use
17
- <segmented-ui> or <radio-ui>. Multi-select via [multiple searchable].
17
+ <segmented-ui> or <radio-ui>. Multi-select via [multiple]: trigger
18
+ renders <tag-ui> chips per selection, popover shows checkbox-style
19
+ option list, Backspace removes the last chip, [select-all] adds
20
+ bulk controls, [max-chips] caps the visible chip count with a
21
+ "+N more" pill. Form value stays a comma-separated string under
22
+ [name] for native <form> compatibility (parse with .split(',')).
18
23
  # Per ADR-0027 — primitives that programmatically create other primitives
19
24
  # do NOT auto-import them. Consumer (or demo shell) must explicitly import.
20
25
  composes:
21
- - icon-ui # chevron + option-row affixes (created in render)
26
+ - icon-ui # chevron + option-row affixes (created in render)
27
+ - tag-ui # multi-select chip per selected option in the trigger
22
28
  props:
23
29
  name:
24
30
  description: Form control name for form data submission
@@ -89,9 +95,56 @@ props:
89
95
  type: number
90
96
  default: null
91
97
  multiple:
92
- description: Enables multi-select (comma-separated values)
98
+ description: |
99
+ Enables multi-select. Trigger renders <tag-ui> chips per selection
100
+ (not comma-separated text); popover renders checkbox-style option
101
+ rows where clicks toggle without closing; Backspace from the
102
+ trigger removes the last chip. Form value remains comma-separated
103
+ under [name] for native <form> compatibility.
93
104
  type: boolean
94
105
  default: false
106
+ reflect: true
107
+ max-chips:
108
+ description: |
109
+ Multi-select only. Caps the number of chips visible in the
110
+ trigger. When `value.length > max-chips`, the first N chips
111
+ render plus a "+M more" pill that opens the popover on click.
112
+ `0` (default) = unlimited.
113
+ type: number
114
+ default: 0
115
+ reflect: true
116
+ min:
117
+ description: |
118
+ Multi-select only. Minimum required selections. Below this floor
119
+ the host's form validity goes invalid (valueMissing) and the
120
+ `invalid` event fires.
121
+ type: number
122
+ default: 0
123
+ reflect: true
124
+ max:
125
+ description: |
126
+ Multi-select only. Maximum allowed selections. Toggling past the
127
+ cap is suppressed; the `invalid` event fires with reason="max".
128
+ `0` (default) = unlimited.
129
+ type: number
130
+ default: 0
131
+ reflect: true
132
+ select-all:
133
+ description: |
134
+ Multi-select only. Renders a "Select all" / "Clear" control row
135
+ above the option list. Click selects every non-disabled option;
136
+ when already all selected, click clears.
137
+ type: boolean
138
+ default: false
139
+ reflect: true
140
+ clearable:
141
+ description: |
142
+ Multi-select only. Adds a clear-all `x` affordance to the trigger
143
+ when at least one chip is present. Click empties value and fires
144
+ `change`.
145
+ type: boolean
146
+ default: false
147
+ reflect: true
95
148
  open:
96
149
  description: Whether the listbox is open
97
150
  type: boolean
@@ -128,6 +181,10 @@ props:
128
181
  events:
129
182
  change:
130
183
  description: Fired when selected value changes
184
+ invalid:
185
+ description: |
186
+ Multi-select only. Fired when a toggle is suppressed by [min] or
187
+ [max] constraints. detail = { value, reason: 'min' | 'max' }.
131
188
  usage: |-
132
189
  §225 (v0.5.9) — Consumer-authored children must be native `<option>` or
133
190
  `<optgroup>`. The `#parseOptions()` walker reads only those two tag names;
@@ -173,6 +230,9 @@ traits: []
173
230
  tokens: {}
174
231
  requiredIcons:
175
232
  - caret-up-down
233
+ - check # checkbox indicator on each option in [multiple] mode
234
+ - x # chip dismiss + clear-all affordance ([multiple] + [clearable])
235
+ - magnifying-glass # search-input prefix ([searchable])
176
236
  a2ui:
177
237
  rules:
178
238
  - >-
@@ -200,6 +260,18 @@ a2ui:
200
260
  unmatched values are valid (tag entry, email-with-suggestion).
201
261
  Use [multiple searchable] for multi-select rather than
202
262
  authoring a separate multi-select primitive.
263
+ - >-
264
+ For multi-select, set [multiple] — the trigger automatically
265
+ renders <tag-ui> chips per selected option; the popover renders
266
+ checkbox-style option rows where clicks toggle membership
267
+ without closing. Form value is comma-separated under [name].
268
+ There is NO `<multi-select-ui>` tag — that name does not exist.
269
+ - >-
270
+ Multi-select bulk controls: [select-all] renders a "Select all" /
271
+ "Clear" control above the option list; [clearable] adds a
272
+ clear-all `x` affordance to the trigger. [max-chips] caps the
273
+ visible chip count and renders "+N more". [min] / [max] gate
274
+ form validity.
203
275
  anti_patterns: []
204
276
  examples:
205
277
  - name: bleed-design-settings
@@ -341,6 +413,37 @@ examples:
341
413
  "variant": "primary"
342
414
  }
343
415
  ]
416
+ - name: multi-select-tags
417
+ description: Multi-select with chip trigger + checkbox option list (SPEC-040).
418
+ a2ui: >-
419
+ [
420
+ {
421
+ "id": "root",
422
+ "component": "Card",
423
+ "children": ["sec"]
424
+ },
425
+ {
426
+ "id": "sec",
427
+ "component": "Section",
428
+ "children": ["col"]
429
+ },
430
+ {
431
+ "id": "col",
432
+ "component": "Column",
433
+ "children": ["tags"],
434
+ "gap": "3"
435
+ },
436
+ {
437
+ "id": "tags",
438
+ "component": "Select",
439
+ "multiple": true,
440
+ "selectAll": true,
441
+ "label": "Tags",
442
+ "name": "tags",
443
+ "placeholder": "Pick tags...",
444
+ "value": "urgent,backend"
445
+ }
446
+ ]
344
447
  - name: create-form
345
448
  description: Simple account creation form with text fields, select, and action buttons.
346
449
  a2ui: >-
@@ -443,6 +546,12 @@ keywords:
443
546
  - dropdown
444
547
  - combobox
445
548
  - autocomplete
549
+ - multi-select
550
+ - multiple
551
+ - chips
552
+ - tokens
553
+ - tags
554
+ - picker
446
555
  synonyms:
447
556
  autocomplete:
448
557
  - combobox
@@ -461,6 +570,18 @@ synonyms:
461
570
  - menu
462
571
  - select
463
572
  - form
573
+ multi-select:
574
+ - multiselect
575
+ - multi-pick
576
+ - chips
577
+ - tokens
578
+ - tags
579
+ - multiple
580
+ multiple:
581
+ - multi-select
582
+ - multiselect
583
+ - chips
584
+ - select-many
464
585
  related:
465
586
  - image
466
587
  - button
@@ -1,11 +1,11 @@
1
1
  @scope (skeleton-ui) {
2
2
  :where(:scope) {
3
3
  /* ── Tokens ── */
4
- --skeleton-bg: var(--a-bg-muted);
5
- --skeleton-highlight: var(--a-bg-subtle);
6
- --skeleton-radius: var(--a-radius-sm);
7
- --skeleton-duration: 1.5s;
8
- --skeleton-easing: var(--a-easing);
4
+ --skeleton-bg-default: var(--a-bg-muted);
5
+ --skeleton-highlight-default: var(--a-bg-subtle);
6
+ --skeleton-radius-default: var(--a-radius-sm);
7
+ --skeleton-duration-default: 1.5s;
8
+ --skeleton-easing-default: var(--a-easing);
9
9
  }
10
10
 
11
11
  :scope {
@@ -14,16 +14,16 @@
14
14
  display: block;
15
15
  position: relative;
16
16
  overflow: hidden;
17
- background: var(--skeleton-bg);
18
- border-radius: var(--skeleton-radius);
17
+ background: var(--skeleton-bg, var(--skeleton-bg-default));
18
+ border-radius: var(--skeleton-radius, var(--skeleton-radius-default));
19
19
  }
20
20
 
21
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); }
22
+ :scope[radius="none"] { --skeleton-radius-default: 0; }
23
+ :scope[radius="sm"] { --skeleton-radius-default: var(--a-radius-sm); }
24
+ :scope[radius="md"] { --skeleton-radius-default: var(--a-radius-md); }
25
+ :scope[radius="lg"] { --skeleton-radius-default: var(--a-radius-lg); }
26
+ :scope[radius="full"] { --skeleton-radius-default: var(--a-radius-full); }
27
27
 
28
28
  /* ── Shimmer animation (default; suppress with [static]) ── */
29
29
  :scope:not([static])::after {
@@ -33,11 +33,11 @@
33
33
  background: linear-gradient(
34
34
  90deg,
35
35
  transparent 25%,
36
- var(--skeleton-highlight) 50%,
36
+ var(--skeleton-highlight, var(--skeleton-highlight-default)) 50%,
37
37
  transparent 75%
38
38
  );
39
39
  background-size: 200% 100%;
40
- animation: skeleton-shimmer var(--skeleton-duration) var(--skeleton-easing) infinite;
40
+ animation: skeleton-shimmer var(--skeleton-duration, var(--skeleton-duration-default)) var(--skeleton-easing, var(--skeleton-easing-default)) infinite;
41
41
  }
42
42
 
43
43
  @keyframes skeleton-shimmer {
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UISkeleton } from './class.js';
13
+ import { UISkeleton } from './skeleton.class.js';
14
14
 
15
15
  defineIfFree('skeleton-ui', UISkeleton);
16
16
 
@@ -7,8 +7,8 @@
7
7
  Variables
8
8
  W = track width (100% of the track element)
9
9
  t = thumb width (full outer width including internal padding)
10
- h = track height (var(--slider-track-height))
11
- pad = internal padding on the thumb (var(--slider-thumb-padding))
10
+ h = track height (var(--slider-track-height, var(--slider-track-height-default)))
11
+ pad = internal padding on the thumb (var(--slider-thumb-padding, var(--slider-thumb-padding-default)))
12
12
  p = progress (0.0 → 1.0, written by JS as --slider-pct)
13
13
 
14
14
  The thumb consists of two layers:
@@ -44,8 +44,8 @@
44
44
  In CSS (percentages relative to W):
45
45
 
46
46
  left = calc(t/2 + p · (W − t))
47
- = calc(var(--slider-thumb-width) / 2
48
- + var(--slider-pct) * (100% - var(--slider-thumb-width)))
47
+ = calc(var(--slider-thumb-width, var(--slider-thumb-width-default)) / 2
48
+ + var(--slider-pct, var(--slider-pct-default)) * (100% - var(--slider-thumb-width, var(--slider-thumb-width-default))))
49
49
 
50
50
  The element is shifted back by 50% via transform so its
51
51
  geometric center lands on the computed point.
@@ -60,50 +60,50 @@
60
60
  ═══════════════════════════════════════════════════════════════ */
61
61
 
62
62
  /* ── Layout ── */
63
- --slider-gap: var(--a-space-1);
64
- --slider-readout-gap: var(--a-space-0-5);
65
- --slider-radius: var(--a-radius-full);
63
+ --slider-gap-default: var(--a-space-1);
64
+ --slider-readout-gap-default: var(--a-space-0-5);
65
+ --slider-radius-default: var(--a-radius-full);
66
66
 
67
67
  /* Track height scales with the universal [size] attribute
68
68
  via --a-toggle-size: 16 sm / 20 md / 24 lg at density=1.
69
69
  Override --slider-track-height directly for custom sizes. */
70
- --slider-track-height: var(--a-toggle-size);
70
+ --slider-track-height-default: var(--a-toggle-size);
71
71
 
72
72
  /* Thumb padding: internal breathing room on all sides.
73
73
  The visual pill sits pad px away from the container edge. */
74
- --slider-thumb-padding: 2px;
74
+ --slider-thumb-padding-default: 2px;
75
75
 
76
76
  /* Visual thumb height: track height minus top and bottom padding. */
77
- --slider-thumb-visual-h: calc(var(--slider-track-height) - 2 * var(--slider-thumb-padding));
77
+ --slider-thumb-visual-h-default: calc(var(--slider-track-height, var(--slider-track-height-default)) - 2 * var(--slider-thumb-padding, var(--slider-thumb-padding-default)));
78
78
 
79
79
  /* Visual thumb width: 2×1 pill ratio. */
80
- --slider-thumb-visual-w: calc(var(--slider-thumb-visual-h) * 2);
80
+ --slider-thumb-visual-w-default: calc(var(--slider-thumb-visual-h, var(--slider-thumb-visual-h-default)) * 2);
81
81
 
82
82
  /* Container / geometry thumb width: visual width plus left and
83
83
  right padding. This is the width used in the travel equation. */
84
- --slider-thumb-width: calc(var(--slider-thumb-visual-w) + 2 * var(--slider-thumb-padding));
84
+ --slider-thumb-width-default: calc(var(--slider-thumb-visual-w, var(--slider-thumb-visual-w-default)) + 2 * var(--slider-thumb-padding, var(--slider-thumb-padding-default)));
85
85
 
86
86
  /* Progress fraction (0.0 → 1.0) written by JS. */
87
- --slider-pct: 0;
87
+ --slider-pct-default: 0;
88
88
 
89
89
  /* ── Colors ──
90
90
  Track: dim recessed surface | Fill: primary | Thumb: white chrome */
91
- --slider-track-bg: var(--a-bg-muted);
92
- --slider-fill-bg: var(--a-primary-bg);
93
- --slider-thumb-bg: var(--a-chrome-light);
94
- --slider-fill-bg-disabled: var(--a-border-subtle);
95
- --slider-thumb-bg-disabled: var(--a-fg-muted);
91
+ --slider-track-bg-default: var(--a-bg-muted);
92
+ --slider-fill-bg-default: var(--a-primary-bg);
93
+ --slider-thumb-bg-default: var(--a-chrome-light);
94
+ --slider-fill-bg-disabled-default: var(--a-border-subtle);
95
+ --slider-thumb-bg-disabled-default: var(--a-fg-muted);
96
96
 
97
97
  /* ── Typography ── */
98
- --slider-font-size: var(--a-ui-size);
99
- --slider-value-weight: var(--a-weight-bold);
98
+ --slider-font-size-default: var(--a-ui-size);
99
+ --slider-value-weight-default: var(--a-weight-bold);
100
100
 
101
101
  /* ── Transition ── */
102
- --slider-duration: var(--a-duration-fast);
103
- --slider-easing: var(--a-easing);
102
+ --slider-duration-default: var(--a-duration-fast);
103
+ --slider-easing-default: var(--a-easing);
104
104
 
105
105
  /* ── Focus ── */
106
- --slider-focus-ring: var(--a-focus-ring);
106
+ --slider-focus-ring-default: var(--a-focus-ring);
107
107
  text-align: start; /* §text-align-reset — blocks inheritance from centered ancestors */
108
108
  }
109
109
 
@@ -112,7 +112,7 @@
112
112
  box-sizing: border-box;
113
113
  display: flex;
114
114
  flex-direction: column;
115
- gap: var(--slider-gap);
115
+ gap: var(--slider-gap, var(--slider-gap-default));
116
116
  }
117
117
 
118
118
  :scope[data-direction="row"] {
@@ -126,7 +126,7 @@
126
126
  display: flex;
127
127
  align-items: baseline;
128
128
  justify-content: space-between;
129
- font-size: var(--slider-font-size);
129
+ font-size: var(--slider-font-size, var(--slider-font-size-default));
130
130
  }
131
131
 
132
132
  [slot="label"] {
@@ -136,12 +136,12 @@
136
136
  [slot="readout"] {
137
137
  display: flex;
138
138
  align-items: baseline;
139
- gap: var(--slider-readout-gap);
139
+ gap: var(--slider-readout-gap, var(--slider-readout-gap-default));
140
140
  }
141
141
 
142
142
  [slot="value"] {
143
143
  color: var(--a-fg);
144
- font-weight: var(--slider-value-weight);
144
+ font-weight: var(--slider-value-weight, var(--slider-value-weight-default));
145
145
  font-variant-numeric: tabular-nums;
146
146
  }
147
147
 
@@ -152,9 +152,9 @@
152
152
  /* Track: the reference frame W for all geometry calculations. */
153
153
  [slot="track"] {
154
154
  position: relative;
155
- height: var(--slider-track-height);
156
- border-radius: var(--slider-radius);
157
- background: var(--slider-track-bg);
155
+ height: var(--slider-track-height, var(--slider-track-height-default));
156
+ border-radius: var(--slider-radius, var(--slider-radius-default));
157
+ background: var(--slider-track-bg, var(--slider-track-bg-default));
158
158
  cursor: pointer;
159
159
  touch-action: none;
160
160
  }
@@ -166,10 +166,10 @@
166
166
  left: 0;
167
167
  height: 100%;
168
168
  border-radius: inherit;
169
- background: var(--slider-fill-bg);
169
+ background: var(--slider-fill-bg, var(--slider-fill-bg-default));
170
170
  pointer-events: none;
171
- width: calc(var(--slider-thumb-width)
172
- + var(--slider-pct) * (100% - var(--slider-thumb-width)));
171
+ width: calc(var(--slider-thumb-width, var(--slider-thumb-width-default))
172
+ + var(--slider-pct, var(--slider-pct-default)) * (100% - var(--slider-thumb-width, var(--slider-thumb-width-default))));
173
173
  }
174
174
 
175
175
  /* Thumb CONTAINER: full track height, geometry width.
@@ -178,18 +178,18 @@
178
178
  [slot="thumb"] {
179
179
  position: absolute;
180
180
  top: 50%;
181
- left: calc(var(--slider-thumb-width) / 2
182
- + var(--slider-pct) * (100% - var(--slider-thumb-width)));
183
- width: var(--slider-thumb-width);
184
- height: var(--slider-track-height);
185
- border-radius: var(--slider-radius);
181
+ left: calc(var(--slider-thumb-width, var(--slider-thumb-width-default)) / 2
182
+ + var(--slider-pct, var(--slider-pct-default)) * (100% - var(--slider-thumb-width, var(--slider-thumb-width-default))));
183
+ width: var(--slider-thumb-width, var(--slider-thumb-width-default));
184
+ height: var(--slider-track-height, var(--slider-track-height-default));
185
+ border-radius: var(--slider-radius, var(--slider-radius-default));
186
186
  background: transparent;
187
187
  transform: translate(-50%, -50%);
188
188
  cursor: grab;
189
189
  touch-action: none;
190
190
  transition:
191
- left var(--slider-duration) var(--slider-easing),
192
- transform var(--slider-duration) var(--slider-easing);
191
+ left var(--slider-duration, var(--slider-duration-default)) var(--slider-easing, var(--slider-easing-default)),
192
+ transform var(--slider-duration, var(--slider-duration-default)) var(--slider-easing, var(--slider-easing-default));
193
193
  z-index: 1;
194
194
  }
195
195
 
@@ -200,15 +200,15 @@
200
200
  [slot="thumb"]::before {
201
201
  content: '';
202
202
  position: absolute;
203
- inset: var(--slider-thumb-padding);
203
+ inset: var(--slider-thumb-padding, var(--slider-thumb-padding-default));
204
204
  border-radius: inherit;
205
- background: var(--slider-thumb-bg);
205
+ background: var(--slider-thumb-bg, var(--slider-thumb-bg-default));
206
206
  }
207
207
 
208
208
  /* During drag: kill the left transition so the thumb follows
209
209
  the pointer frame-by-frame without CSS interpolation lag. */
210
210
  :scope[data-dragging] [slot="thumb"] {
211
- transition: transform var(--slider-duration) var(--slider-easing);
211
+ transition: transform var(--slider-duration, var(--slider-duration-default)) var(--slider-easing, var(--slider-easing-default));
212
212
  }
213
213
 
214
214
  [slot="thumb"]:hover {
@@ -221,13 +221,13 @@
221
221
  }
222
222
 
223
223
  :scope:focus-visible { outline: none; }
224
- :scope:focus-visible [slot="thumb"] { box-shadow: var(--slider-focus-ring); }
224
+ :scope:focus-visible [slot="thumb"] { box-shadow: var(--slider-focus-ring, var(--slider-focus-ring-default)); }
225
225
 
226
226
  /* Disabled */
227
227
  :scope[disabled] [slot="track"] { cursor: not-allowed; }
228
- :scope[disabled] [slot="fill"] { background: var(--slider-fill-bg-disabled); }
228
+ :scope[disabled] [slot="fill"] { background: var(--slider-fill-bg-disabled, var(--slider-fill-bg-disabled-default)); }
229
229
  :scope[disabled] [slot="thumb"]::before {
230
- background: var(--slider-thumb-bg-disabled);
230
+ background: var(--slider-thumb-bg-disabled, var(--slider-thumb-bg-disabled-default));
231
231
  }
232
232
 
233
233
  /* ── Hint (§184, v0.5.5, FEEDBACK-08 §7) ── */