@adia-ai/web-components 0.4.5 → 0.4.7

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 (316) hide show
  1. package/README.md +63 -24
  2. package/USAGE.md +604 -0
  3. package/components/accordion/accordion.d.ts +17 -0
  4. package/components/accordion/accordion.js +10 -117
  5. package/components/accordion/class.js +132 -0
  6. package/components/action-list/action-list.d.ts +15 -0
  7. package/components/action-list/action-list.js +9 -140
  8. package/components/action-list/class.js +156 -0
  9. package/components/agent-artifact/agent-artifact.d.ts +25 -0
  10. package/components/agent-artifact/agent-artifact.js +8 -181
  11. package/components/agent-artifact/class.js +200 -0
  12. package/components/agent-feedback-bar/agent-feedback-bar.d.ts +21 -0
  13. package/components/agent-feedback-bar/agent-feedback-bar.js +8 -143
  14. package/components/agent-feedback-bar/class.js +162 -0
  15. package/components/agent-questions/agent-questions.d.ts +23 -0
  16. package/components/agent-questions/agent-questions.js +8 -180
  17. package/components/agent-questions/class.js +199 -0
  18. package/components/agent-reasoning/agent-reasoning.d.ts +23 -0
  19. package/components/agent-reasoning/agent-reasoning.js +8 -494
  20. package/components/agent-reasoning/class.js +513 -0
  21. package/components/agent-suggestions/agent-suggestions.d.ts +21 -0
  22. package/components/agent-suggestions/agent-suggestions.js +8 -78
  23. package/components/agent-suggestions/class.js +97 -0
  24. package/components/agent-trace/agent-trace.d.ts +19 -0
  25. package/components/alert/alert.d.ts +29 -0
  26. package/components/alert/alert.js +8 -175
  27. package/components/alert/class.js +194 -0
  28. package/components/avatar/avatar.d.ts +27 -0
  29. package/components/avatar/avatar.js +9 -159
  30. package/components/avatar/class.js +173 -0
  31. package/components/badge/badge.d.ts +27 -0
  32. package/components/badge/badge.js +9 -75
  33. package/components/badge/class.js +93 -0
  34. package/components/block/block.d.ts +19 -0
  35. package/components/block/block.js +9 -15
  36. package/components/block/class.js +33 -0
  37. package/components/breadcrumb/breadcrumb.d.ts +23 -0
  38. package/components/breadcrumb/breadcrumb.js +8 -113
  39. package/components/breadcrumb/class.js +132 -0
  40. package/components/button/button.d.ts +34 -0
  41. package/components/button/button.js +15 -66
  42. package/components/button/class.js +80 -0
  43. package/components/calendar-picker/calendar-picker.a2ui.json +6 -1
  44. package/components/calendar-picker/calendar-picker.d.ts +27 -0
  45. package/components/calendar-picker/calendar-picker.js +8 -332
  46. package/components/calendar-picker/calendar-picker.yaml +51 -177
  47. package/components/calendar-picker/class.js +351 -0
  48. package/components/canvas/canvas.a2ui.json +6 -1
  49. package/components/canvas/canvas.d.ts +17 -0
  50. package/components/canvas/canvas.yaml +19 -36
  51. package/components/card/card.a2ui.json +3 -0
  52. package/components/card/card.d.ts +27 -0
  53. package/components/card/card.js +9 -50
  54. package/components/card/card.yaml +171 -433
  55. package/components/card/class.js +68 -0
  56. package/components/chart/chart.d.ts +41 -0
  57. package/components/chart/chart.js +8 -2131
  58. package/components/chart/class.js +2150 -0
  59. package/components/chart-legend/chart-legend.d.ts +27 -0
  60. package/components/chart-legend/chart-legend.js +8 -197
  61. package/components/chart-legend/class.js +215 -0
  62. package/components/chat-thread/chat-thread.d.ts +17 -0
  63. package/components/chat-thread/chat-thread.js +8 -157
  64. package/components/chat-thread/class.js +176 -0
  65. package/components/check/check.d.ts +30 -0
  66. package/components/check/check.js +11 -52
  67. package/components/check/class.js +68 -0
  68. package/components/code/class.js +501 -0
  69. package/components/code/code.d.ts +39 -0
  70. package/components/code/code.js +8 -482
  71. package/components/col/class.js +30 -0
  72. package/components/col/col.d.ts +23 -0
  73. package/components/col/col.js +10 -13
  74. package/components/color-picker/class.js +550 -0
  75. package/components/color-picker/color-picker.d.ts +37 -0
  76. package/components/color-picker/color-picker.js +8 -531
  77. package/components/command/class.js +364 -0
  78. package/components/command/command.a2ui.json +3 -0
  79. package/components/command/command.d.ts +19 -0
  80. package/components/command/command.js +8 -345
  81. package/components/command/command.yaml +105 -124
  82. package/components/demo-toggle/class.js +153 -0
  83. package/components/demo-toggle/demo-toggle.d.ts +23 -0
  84. package/components/demo-toggle/demo-toggle.js +8 -135
  85. package/components/description-list/class.js +86 -0
  86. package/components/description-list/description-list.d.ts +21 -0
  87. package/components/description-list/description-list.js +8 -67
  88. package/components/divider/class.js +57 -0
  89. package/components/divider/divider.d.ts +19 -0
  90. package/components/divider/divider.js +10 -40
  91. package/components/drawer/class.js +306 -0
  92. package/components/drawer/drawer.d.ts +25 -0
  93. package/components/drawer/drawer.js +8 -287
  94. package/components/embed/class.js +73 -0
  95. package/components/embed/embed.d.ts +23 -0
  96. package/components/embed/embed.js +9 -55
  97. package/components/empty-state/class.js +108 -0
  98. package/components/empty-state/empty-state.d.ts +21 -0
  99. package/components/empty-state/empty-state.js +9 -90
  100. package/components/feed/class.js +381 -0
  101. package/components/feed/feed.d.ts +19 -0
  102. package/components/feed/feed.js +9 -367
  103. package/components/field/class.js +266 -0
  104. package/components/field/field.d.ts +23 -0
  105. package/components/field/field.js +8 -247
  106. package/components/fields/class.js +106 -0
  107. package/components/fields/fields.d.ts +19 -0
  108. package/components/fields/fields.js +8 -87
  109. package/components/grid/class.js +31 -0
  110. package/components/grid/grid.d.ts +23 -0
  111. package/components/grid/grid.js +10 -14
  112. package/components/heatmap/class.js +305 -0
  113. package/components/heatmap/heatmap.d.ts +31 -0
  114. package/components/heatmap/heatmap.js +8 -286
  115. package/components/icon/class.js +54 -0
  116. package/components/icon/icon.d.ts +23 -0
  117. package/components/icon/icon.js +13 -40
  118. package/components/image/class.js +112 -0
  119. package/components/image/image.d.ts +33 -0
  120. package/components/image/image.js +9 -94
  121. package/components/index.js +1 -0
  122. package/components/input/class.js +773 -0
  123. package/components/input/input.a2ui.json +3 -0
  124. package/components/input/input.d.ts +61 -0
  125. package/components/input/input.js +8 -755
  126. package/components/input/input.yaml +171 -442
  127. package/components/inspector/class.js +142 -0
  128. package/components/inspector/inspector.a2ui.json +8 -1
  129. package/components/inspector/inspector.d.ts +17 -0
  130. package/components/inspector/inspector.js +8 -124
  131. package/components/inspector/inspector.yaml +15 -30
  132. package/components/kbd/class.js +34 -0
  133. package/components/kbd/kbd.a2ui.json +3 -0
  134. package/components/kbd/kbd.d.ts +17 -0
  135. package/components/kbd/kbd.js +10 -17
  136. package/components/kbd/kbd.yaml +54 -185
  137. package/components/link/class.js +187 -0
  138. package/components/link/link.d.ts +55 -0
  139. package/components/link/link.js +8 -168
  140. package/components/list/class.js +249 -0
  141. package/components/list/list.d.ts +23 -0
  142. package/components/list/list.js +9 -231
  143. package/components/menu/class.js +332 -0
  144. package/components/menu/menu.d.ts +21 -0
  145. package/components/menu/menu.js +11 -316
  146. package/components/modal/class.js +231 -0
  147. package/components/modal/modal.a2ui.json +5 -1
  148. package/components/modal/modal.d.ts +23 -0
  149. package/components/modal/modal.js +8 -212
  150. package/components/modal/modal.yaml +19 -39
  151. package/components/nav/class.js +150 -0
  152. package/components/nav/nav.d.ts +31 -0
  153. package/components/nav/nav.js +8 -131
  154. package/components/nav-group/class.js +152 -0
  155. package/components/nav-group/nav-group.d.ts +35 -0
  156. package/components/nav-group/nav-group.js +9 -134
  157. package/components/nav-item/class.js +86 -0
  158. package/components/nav-item/nav-item.d.ts +37 -0
  159. package/components/nav-item/nav-item.js +10 -69
  160. package/components/noodles/class.js +510 -0
  161. package/components/noodles/noodles.d.ts +33 -0
  162. package/components/noodles/noodles.js +9 -493
  163. package/components/option-card/class.js +167 -0
  164. package/components/option-card/option-card.d.ts +30 -0
  165. package/components/option-card/option-card.js +8 -149
  166. package/components/otp-input/class.js +180 -0
  167. package/components/otp-input/otp-input.a2ui.json +5 -1
  168. package/components/otp-input/otp-input.d.ts +25 -0
  169. package/components/otp-input/otp-input.js +9 -162
  170. package/components/otp-input/otp-input.yaml +45 -174
  171. package/components/page/class.js +97 -0
  172. package/components/page/page.d.ts +46 -0
  173. package/components/page/page.js +8 -79
  174. package/components/pagination/class.js +195 -0
  175. package/components/pagination/pagination.d.ts +23 -0
  176. package/components/pagination/pagination.js +9 -177
  177. package/components/pane/class.js +186 -0
  178. package/components/pane/pane.a2ui.json +12 -1
  179. package/components/pane/pane.css +10 -0
  180. package/components/pane/pane.d.ts +31 -0
  181. package/components/pane/pane.js +8 -143
  182. package/components/pane/pane.yaml +57 -157
  183. package/components/pipeline-status/class.js +189 -0
  184. package/components/pipeline-status/pipeline-status.a2ui.json +7 -1
  185. package/components/pipeline-status/pipeline-status.d.ts +21 -0
  186. package/components/pipeline-status/pipeline-status.js +9 -172
  187. package/components/pipeline-status/pipeline-status.yaml +34 -72
  188. package/components/popover/class.js +194 -0
  189. package/components/popover/popover.d.ts +23 -0
  190. package/components/popover/popover.js +9 -176
  191. package/components/progress/class.js +74 -0
  192. package/components/progress/progress.a2ui.json +3 -0
  193. package/components/progress/progress.d.ts +19 -0
  194. package/components/progress/progress.js +10 -57
  195. package/components/progress/progress.yaml +124 -287
  196. package/components/progress-row/class.js +110 -0
  197. package/components/progress-row/progress-row.d.ts +23 -0
  198. package/components/progress-row/progress-row.js +8 -92
  199. package/components/radio/class.js +83 -0
  200. package/components/radio/radio.d.ts +28 -0
  201. package/components/radio/radio.js +11 -67
  202. package/components/range/class.js +194 -0
  203. package/components/range/range.d.ts +31 -0
  204. package/components/range/range.js +9 -176
  205. package/components/rating/class.js +148 -0
  206. package/components/rating/rating.d.ts +33 -0
  207. package/components/rating/rating.js +9 -130
  208. package/components/richtext/class.js +87 -0
  209. package/components/richtext/richtext.a2ui.json +7 -1
  210. package/components/richtext/richtext.d.ts +19 -0
  211. package/components/richtext/richtext.js +8 -68
  212. package/components/richtext/richtext.yaml +30 -65
  213. package/components/row/class.js +50 -0
  214. package/components/row/row.d.ts +27 -0
  215. package/components/row/row.js +10 -33
  216. package/components/search/class.js +134 -0
  217. package/components/search/search.d.ts +35 -0
  218. package/components/search/search.js +10 -117
  219. package/components/segment/class.js +62 -0
  220. package/components/segment/segment.d.ts +25 -0
  221. package/components/segment/segment.js +10 -45
  222. package/components/segmented/class.js +165 -0
  223. package/components/segmented/segmented.a2ui.json +4 -0
  224. package/components/segmented/segmented.d.ts +24 -0
  225. package/components/segmented/segmented.js +10 -148
  226. package/components/segmented/segmented.yaml +41 -59
  227. package/components/select/class.js +408 -0
  228. package/components/select/select.d.ts +57 -0
  229. package/components/select/select.js +15 -396
  230. package/components/skeleton/class.js +52 -0
  231. package/components/skeleton/skeleton.d.ts +23 -0
  232. package/components/skeleton/skeleton.js +8 -34
  233. package/components/slider/class.js +184 -0
  234. package/components/slider/slider.d.ts +31 -0
  235. package/components/slider/slider.js +9 -166
  236. package/components/stack/class.js +28 -0
  237. package/components/stack/stack.d.ts +17 -0
  238. package/components/stack/stack.js +10 -11
  239. package/components/step-progress/class.js +98 -0
  240. package/components/step-progress/step-progress.d.ts +27 -0
  241. package/components/step-progress/step-progress.js +8 -79
  242. package/components/stepper/class.js +126 -0
  243. package/components/stepper/stepper.d.ts +19 -0
  244. package/components/stepper/stepper.js +9 -112
  245. package/components/stream/class.js +109 -0
  246. package/components/stream/stream.d.ts +19 -0
  247. package/components/stream/stream.js +8 -90
  248. package/components/swatch/class.js +131 -0
  249. package/components/swatch/swatch.d.ts +28 -0
  250. package/components/swatch/swatch.js +8 -112
  251. package/components/swiper/class.js +373 -0
  252. package/components/swiper/swiper.a2ui.json +4 -0
  253. package/components/swiper/swiper.d.ts +31 -0
  254. package/components/swiper/swiper.js +8 -354
  255. package/components/swiper/swiper.yaml +68 -212
  256. package/components/switch/class.js +63 -0
  257. package/components/switch/switch.a2ui.json +6 -1
  258. package/components/switch/switch.d.ts +30 -0
  259. package/components/switch/switch.js +11 -47
  260. package/components/switch/switch.yaml +70 -265
  261. package/components/table/class.js +1453 -0
  262. package/components/table/table.d.ts +37 -0
  263. package/components/table/table.js +8 -1435
  264. package/components/table-toolbar/class.js +680 -0
  265. package/components/table-toolbar/table-toolbar.d.ts +33 -0
  266. package/components/table-toolbar/table-toolbar.js +8 -689
  267. package/components/tabs/class.js +242 -0
  268. package/components/tabs/tabs.d.ts +21 -0
  269. package/components/tabs/tabs.js +8 -223
  270. package/components/tag/class.js +99 -0
  271. package/components/tag/tag.d.ts +27 -0
  272. package/components/tag/tag.js +8 -80
  273. package/components/text/class.js +46 -0
  274. package/components/text/text.d.ts +25 -0
  275. package/components/text/text.js +9 -28
  276. package/components/textarea/class.js +134 -0
  277. package/components/textarea/textarea.d.ts +31 -0
  278. package/components/textarea/textarea.js +11 -118
  279. package/components/timeline/class.js +176 -0
  280. package/components/timeline/timeline.d.ts +19 -0
  281. package/components/timeline/timeline.js +9 -162
  282. package/components/toast/class.js +92 -0
  283. package/components/toast/toast.d.ts +23 -0
  284. package/components/toast/toast.js +9 -76
  285. package/components/toggle-group/class.js +154 -0
  286. package/components/toggle-group/toggle-group.d.ts +19 -0
  287. package/components/toggle-group/toggle-group.js +11 -140
  288. package/components/toggle-scheme/class.js +286 -0
  289. package/components/toggle-scheme/toggle-scheme.a2ui.json +197 -0
  290. package/components/toggle-scheme/toggle-scheme.css +20 -0
  291. package/components/toggle-scheme/toggle-scheme.d.ts +41 -0
  292. package/components/toggle-scheme/toggle-scheme.js +17 -0
  293. package/components/toggle-scheme/toggle-scheme.yaml +173 -0
  294. package/components/toolbar/class.js +388 -0
  295. package/components/toolbar/toolbar.d.ts +23 -0
  296. package/components/toolbar/toolbar.js +10 -376
  297. package/components/tooltip/class.js +299 -0
  298. package/components/tooltip/tooltip.d.ts +27 -0
  299. package/components/tooltip/tooltip.js +8 -280
  300. package/components/tree/class.js +245 -0
  301. package/components/tree/tree.d.ts +15 -0
  302. package/components/tree/tree.js +9 -244
  303. package/components/upload/class.js +199 -0
  304. package/components/upload/upload.d.ts +27 -0
  305. package/components/upload/upload.js +11 -183
  306. package/core/element.d.ts +174 -0
  307. package/core/form.d.ts +108 -0
  308. package/core/index.d.ts +11 -0
  309. package/core/index.js +1 -0
  310. package/core/register.d.ts +25 -0
  311. package/core/register.js +58 -0
  312. package/core/signals.d.ts +94 -0
  313. package/core/template.d.ts +70 -0
  314. package/index.d.ts +315 -0
  315. package/package.json +25 -6
  316. package/traits/CATEGORIES.md +1 -1
package/USAGE.md ADDED
@@ -0,0 +1,604 @@
1
+ # Using `@adia-ai/web-components` — Consumer Guide
2
+
3
+ The complete reference for engineers and agents **integrating** AdiaUI into an app. For authoring new primitives (contributing to the library), see [`README.md`](./README.md) § "Authoring a primitive".
4
+
5
+ > This document answers the five most-common questions consumers ask. If something here is wrong, surprising, or missing, that's a bug — open an issue with the surface it describes.
6
+
7
+ ---
8
+
9
+ ## Contents
10
+
11
+ 1. [Install](#install)
12
+ 2. [The mental model](#the-mental-model)
13
+ 3. [Property reactivity (signal-backed)](#property-reactivity-signal-backed)
14
+ 4. [Property binding patterns (templates / framework integration)](#property-binding-patterns)
15
+ 5. [Event contract — `CustomEvent` with `detail`](#event-contract)
16
+ 6. [Form participation — `UIFormElement` + `ElementInternals`](#form-participation)
17
+ 7. [Lifecycle — `connected` / `render` / `updated` / `disconnected`](#lifecycle)
18
+ 8. [Theming, density, size](#theming-density-size)
19
+ 9. [Registration — auto vs explicit](#registration--auto-vs-explicit)
20
+ 10. [TypeScript](#typescript)
21
+ 11. [Anti-patterns](#anti-patterns)
22
+
23
+ ---
24
+
25
+ ## Install
26
+
27
+ ```bash
28
+ npm install @adia-ai/web-components
29
+ ```
30
+
31
+ Pair with [`@adia-ai/web-modules`](../web-modules) for composite shells (admin / chat / editor / simple / theme):
32
+
33
+ ```bash
34
+ npm install @adia-ai/web-components @adia-ai/web-modules
35
+ ```
36
+
37
+ ### Importing
38
+
39
+ The package is ESM-only — works under any modern bundler (Vite, esbuild, webpack 5+, Rollup) or plain `<script type="module">`.
40
+
41
+ ```js
42
+ // Everything — registers every *-ui tag (95 primitives)
43
+ import '@adia-ai/web-components';
44
+ import '@adia-ai/web-components/css';
45
+
46
+ // Or per-component for tree-shaking-conscious bundles
47
+ import '@adia-ai/web-components/components/button';
48
+ import '@adia-ai/web-components/components/button.css';
49
+ ```
50
+
51
+ Subpath exports also available:
52
+
53
+ ```js
54
+ // Core utilities — signals, templating, base classes
55
+ import { signal, computed, effect, html, UIElement, UIFormElement } from '@adia-ai/web-components/core';
56
+
57
+ // Traits — composable behavior decorators
58
+ import '@adia-ai/web-components/traits';
59
+ ```
60
+
61
+ ---
62
+
63
+ ## The mental model
64
+
65
+ Every AdiaUI primitive is a **standard light-DOM custom element**. There's no shadow DOM, no compiler, no framework — just `customElements.define()` extending a small `UIElement` base class. The base class wires a signal-backed property system on top.
66
+
67
+ The contract every primitive obeys:
68
+
69
+ | Surface | What it is | How to use |
70
+ |---|---|---|
71
+ | **Properties** | Reactive — every prop in `static properties` is backed by a signal. Setting `el.prop = v` triggers a re-render. | `slider.value = 75` |
72
+ | **Attributes** | Mirror of properties (where `reflect: true`). Setting `[attr]` round-trips through the property setter. | `<slider-ui value="50">` |
73
+ | **Events** | `CustomEvent` with typed `detail` payload. Bubbling unless noted otherwise. | `slider.addEventListener('change', e => e.detail.value)` |
74
+ | **Slots** | Light-DOM children projected by attribute selectors (`:scope > [slot="icon"]`). No `<slot>` element. | `<card-ui><span slot="heading">Title</span></card-ui>` |
75
+
76
+ This is the entire surface. There are no magic helpers; no proprietary state-management; no compiler. If you know vanilla web components + standard DOM, you know AdiaUI.
77
+
78
+ ---
79
+
80
+ ## Property reactivity (signal-backed)
81
+
82
+ Every property declared in a primitive's `static properties` map is **signal-backed**. The setter mutates an internal `signal()`; the host's render effect subscribes to all signals and re-runs on every property change. So:
83
+
84
+ ```js
85
+ const slider = document.querySelector('slider-ui');
86
+
87
+ slider.value = 75; // thumb moves to 75%, readout updates, aria-valuenow reflects
88
+ slider.value = 10; // thumb moves to 10%
89
+ slider.disabled = true; // [disabled] reflects, click handlers no-op
90
+ ```
91
+
92
+ This works for **every primitive**. There's no "is this prop reactive?" question — they all are.
93
+
94
+ ### Attributes round-trip
95
+
96
+ Setting an attribute also propagates. `attributeChangedCallback` writes back into the property setter, which mutates the signal, which fires the render effect:
97
+
98
+ ```js
99
+ slider.setAttribute('value', '25'); // same effect as slider.value = 25
100
+ ```
101
+
102
+ This means you can drive a primitive from either side. Whatever your tooling sets — properties or attributes — works.
103
+
104
+ ### Why this matters
105
+
106
+ Consumers sometimes assume that property changes only update the DOM if explicitly subscribed to via `attributeChangedCallback`. **That's not the case here.** The signal-backed property system means every property is reactive by default, with zero per-component opt-in. If you set a property and the DOM doesn't update, it's a bug in the primitive, not a missing subscription on your side.
107
+
108
+ ---
109
+
110
+ ## Property binding patterns
111
+
112
+ When wiring a primitive's property to external state (your own signals, framework state, RxJS observables, etc.), the binding pattern matters. **An eagerly-evaluated value snapshot is one-shot**, not reactive.
113
+
114
+ ### Using the built-in `html` template
115
+
116
+ The package ships its own lightweight template tag at `@adia-ai/web-components/core`. It detects signals and functions as bound values and wraps them in effects:
117
+
118
+ ```js
119
+ import { html, signal, stamp } from '@adia-ai/web-components/core';
120
+
121
+ const minL = signal(0.5);
122
+
123
+ // ✅ Reactive — signal passed directly. Re-fires on every minL.value mutation.
124
+ const tpl1 = html`<slider-ui .value=${minL} min="0" max="1" step="0.01"></slider-ui>`;
125
+
126
+ // ✅ Reactive with transform — function-as-value. Function re-runs on dependency change.
127
+ const tpl2 = html`<slider-ui .value=${() => minL.value * 100} min="0" max="100"></slider-ui>`;
128
+
129
+ // ❌ NON-REACTIVE — eagerly evaluated. Snapshots at render time only.
130
+ const tpl3 = html`<slider-ui .value=${minL.value * 100} min="0" max="100"></slider-ui>`;
131
+ // ^^^^^^^^^^^^^^^^^^^^^^^^
132
+ // evaluates to a number now; nothing to subscribe to
133
+ ```
134
+
135
+ The `.prop=` syntax sets the JS property (not the attribute). The `attr=` syntax sets an attribute. Both round-trip through the signal-backed setter, so either works for reactive updates from your side.
136
+
137
+ ### Using React, Lit, Vue, Svelte, etc.
138
+
139
+ When the binding system isn't AdiaUI's `html` tag, the rule generalizes:
140
+
141
+ **Set the primitive's property inside whatever effect/watcher hook your framework provides.** The property setter mutates the signal, the host re-renders. Don't try to "bind" the value via attributes alone — properties are the reactive path.
142
+
143
+ ```jsx
144
+ // React example
145
+ function MinLSlider({ minL, onMinLChange }) {
146
+ const ref = useRef(null);
147
+ useEffect(() => {
148
+ if (ref.current) ref.current.value = minL * 100;
149
+ }, [minL]);
150
+ return <slider-ui ref={ref} min="0" max="100" onChange={e => onMinLChange(e.detail.value / 100)} />;
151
+ }
152
+ ```
153
+
154
+ ```html
155
+ <!-- Lit example -->
156
+ <slider-ui .value=${this.minL * 100} @change=${e => this.minL = e.detail.value / 100}></slider-ui>
157
+ ```
158
+
159
+ ```html
160
+ <!-- Vue example -->
161
+ <slider-ui :value="minL * 100" @change="onMinLChange($event.detail.value / 100)"></slider-ui>
162
+ ```
163
+
164
+ ```svelte
165
+ <!-- Svelte example -->
166
+ <slider-ui value={minL * 100} on:change={e => minL = e.detail.value / 100}></slider-ui>
167
+ ```
168
+
169
+ ### The eager-evaluation trap
170
+
171
+ Reported real-world bug: a consumer wrote `.value=${signal.value * 100}` and reported "the slider doesn't move on undo." The slider IS reactive; the binding pattern wasn't. `signal.value * 100` evaluates eagerly to a number; the template system never sees the signal, so it can't subscribe.
172
+
173
+ **Fix:** pass `${signal}` (signal direct) or `${() => signal.value * 100}` (function as value). Both get effect-wrapped.
174
+
175
+ ---
176
+
177
+ ## Event contract
178
+
179
+ Every interactive primitive emits **`CustomEvent` with a `detail` payload**. Since v0.4.5, this is uniform across all 17 form-bearing primitives.
180
+
181
+ | Event | Fires on | Detail shape |
182
+ |---|---|---|
183
+ | `change` | Value commit (blur, drag end, keystroke commit) | `{ value }` or `{ value, checked }` for boolean primitives |
184
+ | `input` | Every value tick (typing, dragging) | `{ value }` |
185
+ | `submit` | Enter without shift in `<textarea-ui>` | (none — `event.preventDefault()` to suppress form submission) |
186
+ | Component-specific | See per-component yaml | Per-component detail |
187
+
188
+ ### Listening
189
+
190
+ ```js
191
+ // Typed payload (canonical)
192
+ slider.addEventListener('change', (e) => {
193
+ console.log(e.detail.value); // canonical reading path
194
+ });
195
+
196
+ // Untyped (backwards-compatible — `this.value = v` runs before dispatch)
197
+ slider.addEventListener('change', (e) => {
198
+ console.log(e.target.value); // also valid
199
+ });
200
+ ```
201
+
202
+ Both paths return the same value. Pick whichever your tooling makes ergonomic.
203
+
204
+ ### Value-semantic vs boolean-semantic
205
+
206
+ | Class | Components | Detail |
207
+ |---|---|---|
208
+ | Value-semantic | input, select, slider, textarea, range, rating, search, otp-input, calendar-picker | `{ value }` |
209
+ | Boolean-semantic | switch, check, radio, option-card | `{ value, checked }` |
210
+ | Special | upload | `{ value, files }` |
211
+
212
+ For boolean primitives, `value` is the form-submission string ("on" by default; the form value attribute if set), and `checked` is the actual checked state.
213
+
214
+ ### Component-specific events
215
+
216
+ Some primitives emit named events beyond `change`/`input`:
217
+
218
+ - `<select-ui>` — emits `action` for option-callbacks with `detail.action`
219
+ - `<search-ui>` — emits `search` after debounce with `detail.value`
220
+ - `<chat-composer>` — emits `composer-submit` on Enter with `detail.value`
221
+ - `<color-picker-ui>` — emits multiple typed events (`input`, `change`, `format-change`) with structured detail
222
+
223
+ Each primitive's yaml lists its complete event surface. Live demos at `https://ui-kit.exe.xyz/site/components/<name>`.
224
+
225
+ ### Bubbling
226
+
227
+ All standard events bubble. Internal-routing collisions (e.g. a trait listening for an event then re-emitting one with the same name) are avoided by name discipline — see the `event-name-collision` memory entry for the lesson.
228
+
229
+ ---
230
+
231
+ ## Form participation
232
+
233
+ 15 primitives extend `UIFormElement` and participate in standard forms via `ElementInternals`:
234
+
235
+ ```
236
+ input, select, slider, switch, segmented, check, radio, textarea,
237
+ range, color-picker, rating, option-card, search, otp-input, code
238
+ ```
239
+
240
+ They behave like native form controls:
241
+
242
+ ```html
243
+ <form id="settings">
244
+ <input-ui name="username" type="text" value="alice"></input-ui>
245
+ <select-ui name="theme" value="ocean">…</select-ui>
246
+ <slider-ui name="density" value="50" min="0" max="100"></slider-ui>
247
+ <switch-ui name="notifications" checked></switch-ui>
248
+ <button-ui type="submit" text="Save"></button-ui>
249
+ </form>
250
+ ```
251
+
252
+ ```js
253
+ const form = document.getElementById('settings');
254
+ const data = new FormData(form);
255
+ // → { username: "alice", theme: "ocean", density: "50", notifications: "on" }
256
+ ```
257
+
258
+ ### Validation
259
+
260
+ The full validation surface from native form controls works:
261
+
262
+ ```js
263
+ input.checkValidity(); // boolean
264
+ input.reportValidity(); // boolean + shows error UI
265
+ input.setInvalid('Custom'); // mark invalid with custom message
266
+ input.setValid(); // clear error state
267
+ input.validity; // ValidityState — { valid, valueMissing, patternMismatch, ... }
268
+ input.validationMessage; // localized error message
269
+ input.willValidate; // boolean
270
+ ```
271
+
272
+ Constraint attributes (`required`, `pattern`, `minlength`, `maxlength`) work natively. CSS pseudo-classes (`:valid`, `:invalid`, `:required`, `:disabled`) work in your own CSS without any opt-in.
273
+
274
+ ### Custom validation timing
275
+
276
+ `UIFormElement` validates **on blur if dirty** and **on form reset**. Override the timing via:
277
+
278
+ ```js
279
+ const input = document.querySelector('input-ui');
280
+ input.addEventListener('blur', () => {
281
+ if (!input.value.includes('@')) {
282
+ input.setInvalid('Must be an email');
283
+ } else {
284
+ input.setValid();
285
+ }
286
+ });
287
+ ```
288
+
289
+ ### Form events
290
+
291
+ Submit events bubble normally:
292
+
293
+ ```js
294
+ form.addEventListener('submit', (e) => {
295
+ e.preventDefault();
296
+ const data = new FormData(form);
297
+ fetch('/api/save', { method: 'POST', body: data });
298
+ });
299
+ ```
300
+
301
+ ---
302
+
303
+ ## Lifecycle
304
+
305
+ `UIElement` exposes four overridable lifecycle methods. Defaults are no-ops. Override what you need:
306
+
307
+ ```js
308
+ import { UIElement } from '@adia-ai/web-components/core';
309
+
310
+ class MyWidget extends UIElement {
311
+ static properties = {
312
+ label: { type: String, default: '' },
313
+ };
314
+
315
+ #onKeydown = (e) => { // stable arrow field — required for remove
316
+ if (e.key === 'Escape') this.label = '';
317
+ };
318
+
319
+ connected() {
320
+ // Called once per insertion.
321
+ // Set up listeners on document / external targets here.
322
+ document.addEventListener('keydown', this.#onKeydown);
323
+ }
324
+
325
+ render() {
326
+ // Called every time any property signal mutates.
327
+ // Update internal DOM here. Reading `this.foo` subscribes the host's
328
+ // render effect to that signal.
329
+ this.textContent = this.label || 'Empty';
330
+ }
331
+
332
+ updated(changed) {
333
+ // Called after `render()`.
334
+ // `changed` is a Map<propName, oldValue> for this tick.
335
+ if (changed.has('label')) {
336
+ this.dispatchEvent(new CustomEvent('label-change', {
337
+ bubbles: true, detail: { value: this.label }
338
+ }));
339
+ }
340
+ }
341
+
342
+ disconnected() {
343
+ // Called once per removal.
344
+ // Clean up listeners + intervals + observers here.
345
+ document.removeEventListener('keydown', this.#onKeydown);
346
+ }
347
+ }
348
+
349
+ customElements.define('my-widget', MyWidget);
350
+ ```
351
+
352
+ ### Why the `#field` arrow pattern
353
+
354
+ `addEventListener('event', fn)` and `removeEventListener('event', fn)` only match when `fn` is the same reference. Inline arrows allocate a fresh closure every call, so the remove never fires:
355
+
356
+ ```js
357
+ // ❌ Wrong — different reference each call
358
+ connected() { document.addEventListener('click', (e) => this.foo()); }
359
+ disconnected() { document.removeEventListener('click', (e) => this.foo()); } // doesn't remove
360
+
361
+ // ✅ Correct — stable reference
362
+ #onClick = (e) => this.foo();
363
+ connected() { document.addEventListener('click', this.#onClick); }
364
+ disconnected() { document.removeEventListener('click', this.#onClick); }
365
+ ```
366
+
367
+ The same applies to `bind()` — call it once in the constructor or use a field, not at the listener site.
368
+
369
+ ### Order of operations
370
+
371
+ 1. `constructor()` — `installProps()` defines reactive getters/setters from `static properties`
372
+ 2. Element inserted into DOM → `connectedCallback()` fires
373
+ 3. `connected()` (the overridable hook) runs in `untracked()` so reads don't subscribe outer effects
374
+ 4. Host's main render effect installs: subscribes to all property signals, calls `template()` + `render()`
375
+ 5. On any property change: effect re-runs, re-stamps template, calls `render()` then `updated(changed)`
376
+ 6. Element removed → `disconnectedCallback()` fires → `disconnected()` (overridable)
377
+
378
+ ---
379
+
380
+ ## Theming, density, size
381
+
382
+ AdiaUI is parametric. Three attributes drive global appearance:
383
+
384
+ ```html
385
+ <div data-theme="ocean" density="compact" size="sm">
386
+ <!-- all descendants re-theme / re-densify / re-scale -->
387
+ </div>
388
+ ```
389
+
390
+ | Attribute | Values | Effect |
391
+ |---|---|---|
392
+ | `[data-theme]` | `default`, `ocean`, `forest`, `sunset`, `lavender`, `rose`, `slate`, `midnight` | Swaps the OKLCH color ramp |
393
+ | `[density]` | `compact` (0.85×), `spacious` (1.15×) | Multiplies `--a-density` token |
394
+ | `[size]` | `sm`, `md`, `lg` | Shifts typescale + component dimensions |
395
+ | `[radius]` | `sharp` (0), `rounded` (1), `round` (2) | Multiplies `--a-radius-k` token |
396
+
397
+ Each is a CSS-variable override; no class toggles, no re-imports. Set on any ancestor → applies to that subtree.
398
+
399
+ For a control surface to let users change these at runtime, use [`<theme-panel>`](https://ui-kit.exe.xyz/site/components/theme-panel) from `@adia-ai/web-modules/theme`.
400
+
401
+ ---
402
+
403
+ ## Registration — auto vs explicit
404
+
405
+ ### Auto-register (default)
406
+
407
+ Importing a primitive's `.js` file immediately runs `customElements.define('button-ui', UIButton)`. This is the canonical path — once imported, the tag works everywhere:
408
+
409
+ ```js
410
+ import '@adia-ai/web-components/components/button';
411
+ // <button-ui> is now usable in any markup
412
+ ```
413
+
414
+ The `sideEffects` field in `package.json` keeps this path tree-shake-safe.
415
+
416
+ ### Conflict-safe registration (`defineIfFree`)
417
+
418
+ Multiple packages may try to register the same tag (e.g. when a host page imports the AdiaUI bundle AND a downstream consumer imports per-component subpaths). Native `customElements.define` throws `NotSupportedError` on duplicate registration. The package ships a no-op-on-duplicate helper:
419
+
420
+ ```js
421
+ import { defineIfFree, isRegistered, register } from '@adia-ai/web-components/core';
422
+
423
+ class MyWidget extends HTMLElement { /* … */ }
424
+
425
+ // Registers if free; returns false (no throw) if already taken
426
+ const ok = defineIfFree('my-widget', MyWidget);
427
+
428
+ // Check before registering
429
+ if (!isRegistered('my-widget')) {
430
+ register('my-widget', MyWidget);
431
+ }
432
+ ```
433
+
434
+ When subclassing an AdiaUI primitive under a different tag name:
435
+
436
+ ```js
437
+ import { UISlider } from '@adia-ai/web-components/components/slider';
438
+ import { register } from '@adia-ai/web-components/core';
439
+
440
+ class MySlider extends UISlider {
441
+ static properties = { ...UISlider.properties, custom: { type: String } };
442
+ }
443
+ register('my-slider', MySlider);
444
+ ```
445
+
446
+ The `slider-ui` import auto-registers, but that doesn't interfere — `my-slider` is a distinct tag that hosts your subclass.
447
+
448
+ ### Non-side-effect class imports (since v0.4.7)
449
+
450
+ Every component ships a sibling `class` subpath that exports the class **without** running `customElements.define`. Use it when you need test isolation, tag-name override, or selective composition:
451
+
452
+ ```js
453
+ // Auto-register (default; tag registered immediately):
454
+ import '@adia-ai/web-components/components/slider';
455
+
456
+ // Class import (no auto-register; you decide when to define):
457
+ import { UISlider } from '@adia-ai/web-components/components/slider/class';
458
+
459
+ // Subclass + register under a different tag
460
+ class MySlider extends UISlider {
461
+ static properties = { ...UISlider.properties, custom: { type: String } };
462
+ }
463
+ customElements.define('my-slider', MySlider);
464
+ ```
465
+
466
+ **Test isolation example** — register the class under a unique per-test tag so subclass tests don't clobber the global registration:
467
+
468
+ ```js
469
+ import { UISlider } from '@adia-ai/web-components/components/slider/class';
470
+ import { defineIfFree } from '@adia-ai/web-components/core';
471
+
472
+ beforeEach(() => {
473
+ const tag = `slider-ui-test-${Math.random().toString(36).slice(2, 8)}`;
474
+ defineIfFree(tag, class extends UISlider { /* test overrides */ });
475
+ });
476
+ ```
477
+
478
+ The class subpath is available for every component that has an `<x-ui>` tag (~95 primitives). TypeScript types are picked up from the same per-primitive `.d.ts` files used by the auto-register path — no separate `.d.ts` per subpath needed.
479
+
480
+ ---
481
+
482
+ ## TypeScript
483
+
484
+ Since v0.4.6, the package ships `.d.ts` declarations. v0.4.6 covered the 17 form-bearing primitives (input/select/slider/etc.) with hand-authored rich event types; v0.4.7 codegen extended coverage to the remaining 73 non-form primitives (button/card/table/chart/etc.) from each component's `.a2ui.json` sidecar. **90 of 95** primitives that ship a JS class are now typed (the 5 CSS-only "elements" — `header`, `footer`, `section`, etc. — have no class). Adding the package to your dependencies automatically picks up:
485
+
486
+ - Typed properties on every primitive (e.g. `el.value` is `number` on `<slider-ui>`, `boolean` on `<switch-ui>`)
487
+ - Typed events — `addEventListener('change', e => e.detail.value)` infers the detail shape
488
+ - `HTMLElementTagNameMap` augmentation — `document.querySelector('slider-ui')` returns `UISlider`
489
+ - Public types for `UIElement`, `UIFormElement`, signal, computed, effect, html, stamp
490
+
491
+ ```ts
492
+ import type { UISlider, SliderChangeEvent } from '@adia-ai/web-components';
493
+
494
+ const slider: UISlider = document.querySelector('slider-ui')!;
495
+ slider.value = 75; // typed Number — string would error
496
+
497
+ slider.addEventListener('change', (e: SliderChangeEvent) => {
498
+ console.log(e.detail.value); // number, inferred
499
+ });
500
+
501
+ slider.addEventListener('change', (e) => { // also inferred
502
+ e.detail.value.toFixed(2); // ok — Number.prototype is in scope
503
+ });
504
+ ```
505
+
506
+ For older bundlers without `exports` field support, add to `tsconfig.json`:
507
+
508
+ ```json
509
+ {
510
+ "compilerOptions": {
511
+ "moduleResolution": "bundler"
512
+ }
513
+ }
514
+ ```
515
+
516
+ ---
517
+
518
+ ## Anti-patterns
519
+
520
+ Things to avoid, with why:
521
+
522
+ ### ❌ Don't bind eagerly-evaluated values to reactive props
523
+
524
+ ```js
525
+ // BREAKS — value is a number, not a signal
526
+ <slider-ui .value=${signal.value * 100}></slider-ui>
527
+
528
+ // WORKS — pass the signal or a function
529
+ <slider-ui .value=${signal}></slider-ui>
530
+ <slider-ui .value=${() => signal.value * 100}></slider-ui>
531
+ ```
532
+
533
+ ### ❌ Don't subscribe via `attributeChangedCallback` to a primitive's attributes
534
+
535
+ The base class already handles this. Use the property setter instead:
536
+
537
+ ```js
538
+ // BREAKS — fragile, duplicates the base class's mirror
539
+ const observer = new MutationObserver(...);
540
+ observer.observe(slider, { attributes: ['value'] });
541
+
542
+ // WORKS — set the property; signals propagate
543
+ slider.value = 75;
544
+ ```
545
+
546
+ ### ❌ Don't use shadow DOM patterns
547
+
548
+ AdiaUI is light-DOM. `::part()`, `::slotted()`, `<slot>` elements don't exist:
549
+
550
+ ```js
551
+ // BREAKS — no shadow tree
552
+ slider.shadowRoot.querySelector('.thumb');
553
+
554
+ // WORKS — children are real DOM
555
+ slider.querySelector('[slot="thumb"]');
556
+ ```
557
+
558
+ ### ❌ Don't add inline event handlers via `onchange=`
559
+
560
+ The HTML `on*` attributes don't pick up the typed `detail`:
561
+
562
+ ```html
563
+ <!-- BREAKS — fires but no typed handler signature -->
564
+ <slider-ui onchange="console.log(this.value)"></slider-ui>
565
+
566
+ <!-- WORKS — addEventListener gets the CustomEvent -->
567
+ <slider-ui id="s"></slider-ui>
568
+ <script>
569
+ document.getElementById('s').addEventListener('change', e => console.log(e.detail.value));
570
+ </script>
571
+ ```
572
+
573
+ ### ❌ Don't try to register a tag name twice
574
+
575
+ `customElements.define()` throws on re-registration. The auto-register pattern handles this for you. If you import a primitive twice (e.g. via two different paths), the bundler de-dupes; if it doesn't, the first define wins and the second throws.
576
+
577
+ ### ❌ Don't write `static properties` with un-typed defaults
578
+
579
+ ```js
580
+ // BREAKS — undefined defaults cause attribute parsing surprises
581
+ static properties = { value: {} };
582
+
583
+ // WORKS — declare type + default
584
+ static properties = {
585
+ value: { type: Number, default: 0, reflect: true },
586
+ };
587
+ ```
588
+
589
+ ### ❌ Don't read property values from inside `constructor()`
590
+
591
+ Properties are installed by `installProps()` in `super()`, but the host's render effect doesn't install until `connectedCallback()`. Reading properties in the constructor returns defaults; mutating them is fine, but if you depend on the rendered DOM existing, do it in `connected()` or later.
592
+
593
+ ---
594
+
595
+ ## More
596
+
597
+ - [`README.md`](./README.md) — package overview + authoring guide
598
+ - [Component yaml contracts](./components/) — every primitive's complete API (props, events, slots, examples)
599
+ - [Live demos](https://ui-kit.exe.xyz/site/components/) — every primitive in action
600
+ - [`docs/specs/component-token-contract.md`](../../docs/specs/component-token-contract.md) — full authoring contract
601
+ - [`docs/specs/component-implementation-patterns.md`](../../docs/specs/component-implementation-patterns.md) — render strategies
602
+ - [`docs/specs/traits.md`](../../docs/specs/traits.md) — composable behaviors
603
+
604
+ For consumer questions not covered here, file an issue against [adiahealth/gen-ui-kit](https://github.com/adiahealth/gen-ui-kit/issues). This document is the canonical answer — if it doesn't have your answer, it's a doc gap worth fixing.
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `<accordion-ui>` — Accordion container managing single/multiple open states.
3
+ *
4
+ * @see https://ui-kit.exe.xyz/site/components/accordion
5
+ *
6
+ * Type declarations generated by scripts/build/dts-codegen.mjs from
7
+ * the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
8
+ * run `npm run components`, then `npm run codegen:dts` to regenerate;
9
+ * or hand-author this file fully if rich event types are needed.
10
+ */
11
+
12
+ import { UIElement } from '../../core/element.js';
13
+
14
+ export class UIAccordion extends UIElement {
15
+ /** Allow multiple panels to be open simultaneously */
16
+ multiple: boolean;
17
+ }