@adia-ai/web-components 0.4.6 → 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 (284) hide show
  1. package/USAGE.md +29 -9
  2. package/components/accordion/accordion.d.ts +17 -0
  3. package/components/accordion/accordion.js +10 -117
  4. package/components/accordion/class.js +132 -0
  5. package/components/action-list/action-list.d.ts +15 -0
  6. package/components/action-list/action-list.js +9 -140
  7. package/components/action-list/class.js +156 -0
  8. package/components/agent-artifact/agent-artifact.d.ts +25 -0
  9. package/components/agent-artifact/agent-artifact.js +8 -181
  10. package/components/agent-artifact/class.js +200 -0
  11. package/components/agent-feedback-bar/agent-feedback-bar.d.ts +21 -0
  12. package/components/agent-feedback-bar/agent-feedback-bar.js +8 -143
  13. package/components/agent-feedback-bar/class.js +162 -0
  14. package/components/agent-questions/agent-questions.d.ts +23 -0
  15. package/components/agent-questions/agent-questions.js +8 -180
  16. package/components/agent-questions/class.js +199 -0
  17. package/components/agent-reasoning/agent-reasoning.d.ts +23 -0
  18. package/components/agent-reasoning/agent-reasoning.js +8 -494
  19. package/components/agent-reasoning/class.js +513 -0
  20. package/components/agent-suggestions/agent-suggestions.d.ts +21 -0
  21. package/components/agent-suggestions/agent-suggestions.js +8 -78
  22. package/components/agent-suggestions/class.js +97 -0
  23. package/components/agent-trace/agent-trace.d.ts +19 -0
  24. package/components/alert/alert.d.ts +29 -0
  25. package/components/alert/alert.js +8 -175
  26. package/components/alert/class.js +194 -0
  27. package/components/avatar/avatar.d.ts +27 -0
  28. package/components/avatar/avatar.js +9 -159
  29. package/components/avatar/class.js +173 -0
  30. package/components/badge/badge.d.ts +27 -0
  31. package/components/badge/badge.js +9 -75
  32. package/components/badge/class.js +93 -0
  33. package/components/block/block.d.ts +19 -0
  34. package/components/block/block.js +9 -15
  35. package/components/block/class.js +33 -0
  36. package/components/breadcrumb/breadcrumb.d.ts +23 -0
  37. package/components/breadcrumb/breadcrumb.js +8 -113
  38. package/components/breadcrumb/class.js +132 -0
  39. package/components/button/button.d.ts +34 -0
  40. package/components/button/button.js +15 -66
  41. package/components/button/class.js +80 -0
  42. package/components/calendar-picker/calendar-picker.a2ui.json +6 -1
  43. package/components/calendar-picker/calendar-picker.js +8 -332
  44. package/components/calendar-picker/calendar-picker.yaml +51 -177
  45. package/components/calendar-picker/class.js +351 -0
  46. package/components/canvas/canvas.a2ui.json +6 -1
  47. package/components/canvas/canvas.d.ts +17 -0
  48. package/components/canvas/canvas.yaml +19 -36
  49. package/components/card/card.a2ui.json +3 -0
  50. package/components/card/card.d.ts +27 -0
  51. package/components/card/card.js +9 -50
  52. package/components/card/card.yaml +171 -433
  53. package/components/card/class.js +68 -0
  54. package/components/chart/chart.d.ts +41 -0
  55. package/components/chart/chart.js +8 -2131
  56. package/components/chart/class.js +2150 -0
  57. package/components/chart-legend/chart-legend.d.ts +27 -0
  58. package/components/chart-legend/chart-legend.js +8 -197
  59. package/components/chart-legend/class.js +215 -0
  60. package/components/chat-thread/chat-thread.d.ts +17 -0
  61. package/components/chat-thread/chat-thread.js +8 -157
  62. package/components/chat-thread/class.js +176 -0
  63. package/components/check/check.js +11 -52
  64. package/components/check/class.js +68 -0
  65. package/components/code/class.js +501 -0
  66. package/components/code/code.js +8 -482
  67. package/components/col/class.js +30 -0
  68. package/components/col/col.d.ts +23 -0
  69. package/components/col/col.js +10 -13
  70. package/components/color-picker/class.js +550 -0
  71. package/components/color-picker/color-picker.js +8 -531
  72. package/components/command/class.js +364 -0
  73. package/components/command/command.a2ui.json +3 -0
  74. package/components/command/command.d.ts +19 -0
  75. package/components/command/command.js +8 -345
  76. package/components/command/command.yaml +105 -124
  77. package/components/demo-toggle/class.js +153 -0
  78. package/components/demo-toggle/demo-toggle.d.ts +23 -0
  79. package/components/demo-toggle/demo-toggle.js +8 -135
  80. package/components/description-list/class.js +86 -0
  81. package/components/description-list/description-list.d.ts +21 -0
  82. package/components/description-list/description-list.js +8 -67
  83. package/components/divider/class.js +57 -0
  84. package/components/divider/divider.d.ts +19 -0
  85. package/components/divider/divider.js +10 -40
  86. package/components/drawer/class.js +306 -0
  87. package/components/drawer/drawer.d.ts +25 -0
  88. package/components/drawer/drawer.js +8 -287
  89. package/components/embed/class.js +73 -0
  90. package/components/embed/embed.d.ts +23 -0
  91. package/components/embed/embed.js +9 -55
  92. package/components/empty-state/class.js +108 -0
  93. package/components/empty-state/empty-state.d.ts +21 -0
  94. package/components/empty-state/empty-state.js +9 -90
  95. package/components/feed/class.js +381 -0
  96. package/components/feed/feed.d.ts +19 -0
  97. package/components/feed/feed.js +9 -367
  98. package/components/field/class.js +266 -0
  99. package/components/field/field.d.ts +23 -0
  100. package/components/field/field.js +8 -247
  101. package/components/fields/class.js +106 -0
  102. package/components/fields/fields.d.ts +19 -0
  103. package/components/fields/fields.js +8 -87
  104. package/components/grid/class.js +31 -0
  105. package/components/grid/grid.d.ts +23 -0
  106. package/components/grid/grid.js +10 -14
  107. package/components/heatmap/class.js +305 -0
  108. package/components/heatmap/heatmap.d.ts +31 -0
  109. package/components/heatmap/heatmap.js +8 -286
  110. package/components/icon/class.js +54 -0
  111. package/components/icon/icon.d.ts +23 -0
  112. package/components/icon/icon.js +13 -40
  113. package/components/image/class.js +112 -0
  114. package/components/image/image.d.ts +33 -0
  115. package/components/image/image.js +9 -94
  116. package/components/input/class.js +773 -0
  117. package/components/input/input.a2ui.json +3 -0
  118. package/components/input/input.js +8 -755
  119. package/components/input/input.yaml +171 -442
  120. package/components/inspector/class.js +142 -0
  121. package/components/inspector/inspector.a2ui.json +8 -1
  122. package/components/inspector/inspector.d.ts +17 -0
  123. package/components/inspector/inspector.js +8 -124
  124. package/components/inspector/inspector.yaml +15 -30
  125. package/components/kbd/class.js +34 -0
  126. package/components/kbd/kbd.a2ui.json +3 -0
  127. package/components/kbd/kbd.d.ts +17 -0
  128. package/components/kbd/kbd.js +10 -17
  129. package/components/kbd/kbd.yaml +54 -185
  130. package/components/link/class.js +187 -0
  131. package/components/link/link.d.ts +55 -0
  132. package/components/link/link.js +8 -168
  133. package/components/list/class.js +249 -0
  134. package/components/list/list.d.ts +23 -0
  135. package/components/list/list.js +9 -231
  136. package/components/menu/class.js +332 -0
  137. package/components/menu/menu.d.ts +21 -0
  138. package/components/menu/menu.js +11 -316
  139. package/components/modal/class.js +231 -0
  140. package/components/modal/modal.a2ui.json +5 -1
  141. package/components/modal/modal.d.ts +23 -0
  142. package/components/modal/modal.js +8 -212
  143. package/components/modal/modal.yaml +19 -39
  144. package/components/nav/class.js +150 -0
  145. package/components/nav/nav.d.ts +31 -0
  146. package/components/nav/nav.js +8 -131
  147. package/components/nav-group/class.js +152 -0
  148. package/components/nav-group/nav-group.d.ts +35 -0
  149. package/components/nav-group/nav-group.js +9 -134
  150. package/components/nav-item/class.js +86 -0
  151. package/components/nav-item/nav-item.d.ts +37 -0
  152. package/components/nav-item/nav-item.js +10 -69
  153. package/components/noodles/class.js +510 -0
  154. package/components/noodles/noodles.d.ts +33 -0
  155. package/components/noodles/noodles.js +9 -493
  156. package/components/option-card/class.js +167 -0
  157. package/components/option-card/option-card.js +8 -149
  158. package/components/otp-input/class.js +180 -0
  159. package/components/otp-input/otp-input.a2ui.json +5 -1
  160. package/components/otp-input/otp-input.js +9 -162
  161. package/components/otp-input/otp-input.yaml +45 -174
  162. package/components/page/class.js +97 -0
  163. package/components/page/page.d.ts +46 -0
  164. package/components/page/page.js +8 -79
  165. package/components/pagination/class.js +195 -0
  166. package/components/pagination/pagination.d.ts +23 -0
  167. package/components/pagination/pagination.js +9 -177
  168. package/components/pane/class.js +186 -0
  169. package/components/pane/pane.a2ui.json +12 -1
  170. package/components/pane/pane.d.ts +31 -0
  171. package/components/pane/pane.js +8 -167
  172. package/components/pane/pane.yaml +57 -157
  173. package/components/pipeline-status/class.js +189 -0
  174. package/components/pipeline-status/pipeline-status.a2ui.json +7 -1
  175. package/components/pipeline-status/pipeline-status.d.ts +21 -0
  176. package/components/pipeline-status/pipeline-status.js +9 -172
  177. package/components/pipeline-status/pipeline-status.yaml +34 -72
  178. package/components/popover/class.js +194 -0
  179. package/components/popover/popover.d.ts +23 -0
  180. package/components/popover/popover.js +9 -176
  181. package/components/progress/class.js +74 -0
  182. package/components/progress/progress.a2ui.json +3 -0
  183. package/components/progress/progress.d.ts +19 -0
  184. package/components/progress/progress.js +10 -57
  185. package/components/progress/progress.yaml +124 -287
  186. package/components/progress-row/class.js +110 -0
  187. package/components/progress-row/progress-row.d.ts +23 -0
  188. package/components/progress-row/progress-row.js +8 -92
  189. package/components/radio/class.js +83 -0
  190. package/components/radio/radio.js +11 -67
  191. package/components/range/class.js +194 -0
  192. package/components/range/range.js +9 -176
  193. package/components/rating/class.js +148 -0
  194. package/components/rating/rating.js +9 -130
  195. package/components/richtext/class.js +87 -0
  196. package/components/richtext/richtext.a2ui.json +7 -1
  197. package/components/richtext/richtext.d.ts +19 -0
  198. package/components/richtext/richtext.js +8 -68
  199. package/components/richtext/richtext.yaml +30 -65
  200. package/components/row/class.js +50 -0
  201. package/components/row/row.d.ts +27 -0
  202. package/components/row/row.js +10 -33
  203. package/components/search/class.js +134 -0
  204. package/components/search/search.js +10 -117
  205. package/components/segment/class.js +62 -0
  206. package/components/segment/segment.d.ts +25 -0
  207. package/components/segment/segment.js +10 -45
  208. package/components/segmented/class.js +165 -0
  209. package/components/segmented/segmented.a2ui.json +4 -0
  210. package/components/segmented/segmented.js +10 -148
  211. package/components/segmented/segmented.yaml +41 -59
  212. package/components/select/class.js +408 -0
  213. package/components/select/select.js +15 -396
  214. package/components/skeleton/class.js +52 -0
  215. package/components/skeleton/skeleton.d.ts +23 -0
  216. package/components/skeleton/skeleton.js +8 -34
  217. package/components/slider/class.js +184 -0
  218. package/components/slider/slider.js +9 -166
  219. package/components/stack/class.js +28 -0
  220. package/components/stack/stack.d.ts +17 -0
  221. package/components/stack/stack.js +10 -11
  222. package/components/step-progress/class.js +98 -0
  223. package/components/step-progress/step-progress.d.ts +27 -0
  224. package/components/step-progress/step-progress.js +8 -79
  225. package/components/stepper/class.js +126 -0
  226. package/components/stepper/stepper.d.ts +19 -0
  227. package/components/stepper/stepper.js +9 -112
  228. package/components/stream/class.js +109 -0
  229. package/components/stream/stream.d.ts +19 -0
  230. package/components/stream/stream.js +8 -90
  231. package/components/swatch/class.js +131 -0
  232. package/components/swatch/swatch.d.ts +28 -0
  233. package/components/swatch/swatch.js +8 -112
  234. package/components/swiper/class.js +373 -0
  235. package/components/swiper/swiper.a2ui.json +4 -0
  236. package/components/swiper/swiper.d.ts +31 -0
  237. package/components/swiper/swiper.js +8 -354
  238. package/components/swiper/swiper.yaml +68 -212
  239. package/components/switch/class.js +63 -0
  240. package/components/switch/switch.a2ui.json +6 -1
  241. package/components/switch/switch.js +11 -47
  242. package/components/switch/switch.yaml +70 -265
  243. package/components/table/class.js +1453 -0
  244. package/components/table/table.d.ts +37 -0
  245. package/components/table/table.js +8 -1435
  246. package/components/table-toolbar/class.js +680 -0
  247. package/components/table-toolbar/table-toolbar.d.ts +33 -0
  248. package/components/table-toolbar/table-toolbar.js +8 -689
  249. package/components/tabs/class.js +242 -0
  250. package/components/tabs/tabs.d.ts +21 -0
  251. package/components/tabs/tabs.js +8 -223
  252. package/components/tag/class.js +99 -0
  253. package/components/tag/tag.d.ts +27 -0
  254. package/components/tag/tag.js +8 -80
  255. package/components/text/class.js +46 -0
  256. package/components/text/text.d.ts +25 -0
  257. package/components/text/text.js +9 -28
  258. package/components/textarea/class.js +134 -0
  259. package/components/textarea/textarea.js +11 -118
  260. package/components/timeline/class.js +176 -0
  261. package/components/timeline/timeline.d.ts +19 -0
  262. package/components/timeline/timeline.js +9 -162
  263. package/components/toast/class.js +92 -0
  264. package/components/toast/toast.d.ts +23 -0
  265. package/components/toast/toast.js +9 -76
  266. package/components/toggle-group/class.js +154 -0
  267. package/components/toggle-group/toggle-group.d.ts +19 -0
  268. package/components/toggle-group/toggle-group.js +11 -140
  269. package/components/toggle-scheme/class.js +286 -0
  270. package/components/toggle-scheme/toggle-scheme.d.ts +41 -0
  271. package/components/toggle-scheme/toggle-scheme.js +8 -268
  272. package/components/toolbar/class.js +388 -0
  273. package/components/toolbar/toolbar.d.ts +23 -0
  274. package/components/toolbar/toolbar.js +10 -376
  275. package/components/tooltip/class.js +299 -0
  276. package/components/tooltip/tooltip.d.ts +27 -0
  277. package/components/tooltip/tooltip.js +8 -280
  278. package/components/tree/class.js +245 -0
  279. package/components/tree/tree.d.ts +15 -0
  280. package/components/tree/tree.js +9 -244
  281. package/components/upload/class.js +199 -0
  282. package/components/upload/upload.js +11 -183
  283. package/index.d.ts +159 -5
  284. package/package.json +5 -1
package/USAGE.md CHANGED
@@ -445,33 +445,53 @@ register('my-slider', MySlider);
445
445
 
446
446
  The `slider-ui` import auto-registers, but that doesn't interfere — `my-slider` is a distinct tag that hosts your subclass.
447
447
 
448
- ### Roadmap — non-side-effect class imports
448
+ ### Non-side-effect class imports (since v0.4.7)
449
449
 
450
- A future v0.4.x release will ship a non-side-effect `class` subpath per component:
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:
451
467
 
452
468
  ```js
453
- // FUTURE — not available yet (v0.4.7+)
454
469
  import { UISlider } from '@adia-ai/web-components/components/slider/class';
455
- // imports the class without running customElements.define
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
+ });
456
476
  ```
457
477
 
458
- This will enable test isolation (register the class under a different tag in unit tests without clobbering the global) + true tree-shaking elimination of un-used primitives. Until then, importing the auto-register subpath is the canonical path, and `defineIfFree` covers conflict avoidance.
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.
459
479
 
460
480
  ---
461
481
 
462
482
  ## TypeScript
463
483
 
464
- Since v0.4.6, the package ships hand-written `.d.ts` declarations. Adding the package to your dependencies automatically picks up:
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:
465
485
 
466
486
  - Typed properties on every primitive (e.g. `el.value` is `number` on `<slider-ui>`, `boolean` on `<switch-ui>`)
467
487
  - Typed events — `addEventListener('change', e => e.detail.value)` infers the detail shape
468
- - `HTMLElementTagNameMap` augmentation — `document.querySelector('slider-ui')` returns `UISliderElement`
488
+ - `HTMLElementTagNameMap` augmentation — `document.querySelector('slider-ui')` returns `UISlider`
469
489
  - Public types for `UIElement`, `UIFormElement`, signal, computed, effect, html, stamp
470
490
 
471
491
  ```ts
472
- import type { UISliderElement, SliderChangeEvent } from '@adia-ai/web-components';
492
+ import type { UISlider, SliderChangeEvent } from '@adia-ai/web-components';
473
493
 
474
- const slider: UISliderElement = document.querySelector('slider-ui')!;
494
+ const slider: UISlider = document.querySelector('slider-ui')!;
475
495
  slider.value = 75; // typed Number — string would error
476
496
 
477
497
  slider.addEventListener('change', (e: SliderChangeEvent) => {
@@ -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
+ }
@@ -1,125 +1,18 @@
1
1
  /**
2
- * <accordion-ui>
3
- * <accordion-item-ui text="Section 1">Content for section 1</accordion-item-ui>
4
- * <accordion-item-ui text="Section 2">Content for section 2</accordion-item-ui>
5
- * </accordion-ui>
2
+ * `<accordion-ui>` — auto-registers the tag on import.
6
3
  *
7
- * Accordion container + item pair.
8
- * Container manages single/multiple open states.
9
- * Items handle their own expand/collapse toggle.
4
+ * For non-side-effect class import (test isolation, tag override), use
5
+ * the `class` subpath:
10
6
  *
11
- * Events (on accordion-item-ui):
12
- * toggle — { detail: { open } }
7
+ * import { UIAccordion, UIAccordionItem } from '@adia-ai/web-components/components/accordion/class';
8
+ *
9
+ * @see ../../USAGE.md#registration--auto-vs-explicit
13
10
  */
14
11
 
15
- import { UIElement } from '../../core/element.js';
16
-
17
- // ── Accordion Container ────────────────────────────────────────
18
-
19
- class UIAccordion extends UIElement {
20
- static properties = {
21
- multiple: { type: Boolean, default: false, reflect: true },
22
- };
23
-
24
- static template = () => null;
25
-
26
- connected() {
27
- this.addEventListener('toggle', this.#onItemToggle);
28
- }
29
-
30
- disconnected() {
31
- this.removeEventListener('toggle', this.#onItemToggle);
32
- }
33
-
34
- #onItemToggle = (e) => {
35
- if (this.multiple) return;
36
-
37
- const target = e.target;
38
- if (!target.open) return;
39
-
40
- // Close other items
41
- const items = this.querySelectorAll('accordion-item-ui');
42
- for (const item of items) {
43
- if (item !== target && item.open) {
44
- item.open = false;
45
- }
46
- }
47
- };
48
- }
49
- customElements.define('accordion-ui', UIAccordion);
50
-
51
- // ── Accordion Item ─────────────────────────────────────────────
52
-
53
- class UIAccordionItem extends UIElement {
54
- static properties = {
55
- text: { type: String, default: '', reflect: true },
56
- open: { type: Boolean, default: false, reflect: true },
57
- };
58
-
59
- static template = () => null;
60
-
61
- #bound = false;
62
-
63
- connected() {
64
- // Stamp header if not present
65
- if (!this.querySelector('[slot="header"]')) {
66
- const header = document.createElement('div');
67
- header.setAttribute('slot', 'header');
68
-
69
- const label = document.createElement('span');
70
- label.setAttribute('slot', 'header-text');
71
- header.appendChild(label);
72
-
73
- const caret = document.createElement('icon-ui');
74
- caret.setAttribute('name', 'caret-down');
75
- caret.setAttribute('slot', 'caret');
76
- header.appendChild(caret);
77
-
78
- this.prepend(header);
79
- }
80
-
81
- // Stamp content wrapper if not present
82
- if (!this.querySelector('[slot="body"]')) {
83
- const body = document.createElement('div');
84
- body.setAttribute('slot', 'body');
85
-
86
- // Move non-slotted children into body
87
- const children = [...this.childNodes].filter(n => {
88
- if (n.nodeType === 1) return !n.hasAttribute('slot');
89
- return n.nodeType === 3 && n.textContent.trim();
90
- });
91
- for (const child of children) body.appendChild(child);
92
-
93
- this.appendChild(body);
94
- }
95
-
96
- if (!this.#bound) {
97
- this.#bound = true;
98
- this.addEventListener('click', this.#onClick);
99
- }
100
- }
101
-
102
- disconnected() {
103
- this.removeEventListener('click', this.#onClick);
104
- this.#bound = false;
105
- }
106
-
107
- render() {
108
- const label = this.querySelector('[slot="header-text"]');
109
- if (label) label.textContent = this.text;
110
- }
111
-
112
- #onClick = (e) => {
113
- const header = this.querySelector('[slot="header"]');
114
- if (!header || !header.contains(e.target)) return;
12
+ import { defineIfFree } from '../../core/register.js';
13
+ import { UIAccordion, UIAccordionItem } from './class.js';
115
14
 
116
- this.open = !this.open;
117
- this.dispatchEvent(new CustomEvent('toggle', {
118
- bubbles: true,
119
- detail: { open: this.open },
120
- }));
121
- };
122
- }
123
- customElements.define('accordion-item-ui', UIAccordionItem);
15
+ defineIfFree('accordion-ui', UIAccordion);
16
+ defineIfFree('accordion-item-ui', UIAccordionItem);
124
17
 
125
18
  export { UIAccordion, UIAccordionItem };
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Non-side-effect class export for `<accordion-ui>` (+ co-located primitives).
3
+ *
4
+ * Importing this file gives you the class(es) without auto-registering the tag.
5
+ * Useful for test isolation, subclassing with tag-name override, or selective
6
+ * composition.
7
+ *
8
+ * The auto-register path stays at `@adia-ai/web-components/components/accordion`
9
+ * (which imports this file + calls `defineIfFree()`).
10
+ *
11
+ * @see ../../USAGE.md#registration--auto-vs-explicit
12
+ */
13
+
14
+ /**
15
+ * <accordion-ui>
16
+ * <accordion-item-ui text="Section 1">Content for section 1</accordion-item-ui>
17
+ * <accordion-item-ui text="Section 2">Content for section 2</accordion-item-ui>
18
+ * </accordion-ui>
19
+ *
20
+ * Accordion container + item pair.
21
+ * Container manages single/multiple open states.
22
+ * Items handle their own expand/collapse toggle.
23
+ *
24
+ * Events (on accordion-item-ui):
25
+ * toggle — { detail: { open } }
26
+ */
27
+
28
+ import { UIElement } from '../../core/element.js';
29
+
30
+ // ── Accordion Container ────────────────────────────────────────
31
+
32
+ export class UIAccordion extends UIElement {
33
+ static properties = {
34
+ multiple: { type: Boolean, default: false, reflect: true },
35
+ };
36
+
37
+ static template = () => null;
38
+
39
+ connected() {
40
+ this.addEventListener('toggle', this.#onItemToggle);
41
+ }
42
+
43
+ disconnected() {
44
+ this.removeEventListener('toggle', this.#onItemToggle);
45
+ }
46
+
47
+ #onItemToggle = (e) => {
48
+ if (this.multiple) return;
49
+
50
+ const target = e.target;
51
+ if (!target.open) return;
52
+
53
+ // Close other items
54
+ const items = this.querySelectorAll('accordion-item-ui');
55
+ for (const item of items) {
56
+ if (item !== target && item.open) {
57
+ item.open = false;
58
+ }
59
+ }
60
+ };
61
+ }
62
+
63
+ export class UIAccordionItem extends UIElement {
64
+ static properties = {
65
+ text: { type: String, default: '', reflect: true },
66
+ open: { type: Boolean, default: false, reflect: true },
67
+ };
68
+
69
+ static template = () => null;
70
+
71
+ #bound = false;
72
+
73
+ connected() {
74
+ // Stamp header if not present
75
+ if (!this.querySelector('[slot="header"]')) {
76
+ const header = document.createElement('div');
77
+ header.setAttribute('slot', 'header');
78
+
79
+ const label = document.createElement('span');
80
+ label.setAttribute('slot', 'header-text');
81
+ header.appendChild(label);
82
+
83
+ const caret = document.createElement('icon-ui');
84
+ caret.setAttribute('name', 'caret-down');
85
+ caret.setAttribute('slot', 'caret');
86
+ header.appendChild(caret);
87
+
88
+ this.prepend(header);
89
+ }
90
+
91
+ // Stamp content wrapper if not present
92
+ if (!this.querySelector('[slot="body"]')) {
93
+ const body = document.createElement('div');
94
+ body.setAttribute('slot', 'body');
95
+
96
+ // Move non-slotted children into body
97
+ const children = [...this.childNodes].filter(n => {
98
+ if (n.nodeType === 1) return !n.hasAttribute('slot');
99
+ return n.nodeType === 3 && n.textContent.trim();
100
+ });
101
+ for (const child of children) body.appendChild(child);
102
+
103
+ this.appendChild(body);
104
+ }
105
+
106
+ if (!this.#bound) {
107
+ this.#bound = true;
108
+ this.addEventListener('click', this.#onClick);
109
+ }
110
+ }
111
+
112
+ disconnected() {
113
+ this.removeEventListener('click', this.#onClick);
114
+ this.#bound = false;
115
+ }
116
+
117
+ render() {
118
+ const label = this.querySelector('[slot="header-text"]');
119
+ if (label) label.textContent = this.text;
120
+ }
121
+
122
+ #onClick = (e) => {
123
+ const header = this.querySelector('[slot="header"]');
124
+ if (!header || !header.contains(e.target)) return;
125
+
126
+ this.open = !this.open;
127
+ this.dispatchEvent(new CustomEvent('toggle', {
128
+ bubbles: true,
129
+ detail: { open: this.open },
130
+ }));
131
+ };
132
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `<action-list-ui>` — Inline list of command actions with keyboard navigation. Fires action event when an item is clicked or activated via keyboard.
3
+ *
4
+ * @see https://ui-kit.exe.xyz/site/components/action-list
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 UIActionList extends UIElement {
15
+ }
@@ -1,149 +1,18 @@
1
1
  /**
2
- * <action-list-ui>
3
- * <action-item-ui icon="plus" text="New Project" value="new"></action-item-ui>
4
- * <action-item-ui icon="users" text="Invite Team" value="invite"></action-item-ui>
5
- * <action-item-ui icon="download" text="Export Data" value="export"></action-item-ui>
6
- * </action-list-ui>
2
+ * `<action-list-ui>` — auto-registers the tag on import.
7
3
  *
8
- * Inline (non-dropdown) list of command actions. Think of it as a menu that
9
- * stays open — useful for quick-actions cards, settings rails, sidebar shortcuts.
4
+ * For non-side-effect class import (test isolation, tag override), use
5
+ * the `class` subpath:
10
6
  *
11
- * Differs from <menu-ui> (which renders in a popover) and <list-ui> (which is
12
- * passive — no hover/click semantics).
7
+ * import { UIActionList, UIActionItem } from '@adia-ai/web-components/components/action-list/class';
13
8
  *
14
- * Fires `action` CustomEvent with { value, text, item } when an item is clicked
15
- * or activated via keyboard (Enter / Space). Keyboard nav: ArrowUp/Down, Home/End.
9
+ * @see ../../USAGE.md#registration--auto-vs-explicit
16
10
  */
17
11
 
18
- import { UIElement } from '../../core/element.js';
12
+ import { defineIfFree } from '../../core/register.js';
13
+ import { UIActionList, UIActionItem } from './class.js';
19
14
 
20
- class UIActionList extends UIElement {
21
- static properties = {};
22
- static template = () => null;
23
-
24
- #bound = false;
25
-
26
- connected() {
27
- this.setAttribute('role', 'list');
28
- if (!this.#bound) {
29
- this.#bound = true;
30
- this.addEventListener('click', this.#onClick);
31
- this.addEventListener('keydown', this.#onKey);
32
- }
33
- }
34
-
35
- disconnected() {
36
- this.removeEventListener('click', this.#onClick);
37
- this.removeEventListener('keydown', this.#onKey);
38
- this.#bound = false;
39
- }
40
-
41
- #items() {
42
- return Array.from(this.querySelectorAll(':scope > action-item-ui:not([disabled])'));
43
- }
44
-
45
- #onClick = (e) => {
46
- const item = e.target.closest('action-item-ui');
47
- if (!item || item.hasAttribute('disabled')) return;
48
- if (!this.contains(item)) return;
49
- this.dispatchEvent(new CustomEvent('action', {
50
- bubbles: true,
51
- detail: { value: item.getAttribute('value') || '', text: item.getAttribute('text') || item.textContent.trim(), item },
52
- }));
53
- };
54
-
55
- #onKey = (e) => {
56
- const items = this.#items();
57
- if (!items.length) return;
58
- const active = document.activeElement?.closest?.('action-item-ui');
59
- const i = active ? items.indexOf(active) : -1;
60
- const focus = (idx) => {
61
- const next = items[(idx + items.length) % items.length];
62
- next?.focus?.({ preventScroll: true });
63
- };
64
- switch (e.key) {
65
- case 'ArrowDown': e.preventDefault(); focus(i + 1); break;
66
- case 'ArrowUp': e.preventDefault(); focus(i - 1); break;
67
- case 'Home': e.preventDefault(); focus(0); break;
68
- case 'End': e.preventDefault(); focus(items.length - 1); break;
69
- case 'Enter':
70
- case ' ': {
71
- if (active) { e.preventDefault(); active.click(); }
72
- break;
73
- }
74
- }
75
- };
76
- }
77
-
78
- customElements.define('action-list-ui', UIActionList);
79
-
80
- class UIActionItem extends UIElement {
81
- static properties = {
82
- icon: { type: String, default: '', reflect: true },
83
- text: { type: String, default: '', reflect: true },
84
- value: { type: String, default: '', reflect: true },
85
- variant: { type: String, default: 'default', reflect: true },
86
- disabled: { type: Boolean, default: false, reflect: true },
87
- };
88
-
89
- static template = () => null;
90
-
91
- connected() {
92
- this.setAttribute('role', 'listitem');
93
- if (!this.hasAttribute('tabindex')) this.setAttribute('tabindex', '0');
94
- this.#stamp();
95
- this.#syncAria();
96
- }
97
-
98
- #stamp() {
99
- if (this.querySelector('[slot="text"]')) return;
100
-
101
- if (this.icon) {
102
- const iconEl = document.createElement('icon-ui');
103
- iconEl.setAttribute('slot', 'icon');
104
- iconEl.setAttribute('name', this.icon);
105
- this.appendChild(iconEl);
106
- }
107
-
108
- if (this.text) {
109
- const span = document.createElement('span');
110
- span.setAttribute('slot', 'text');
111
- span.textContent = this.text;
112
- this.appendChild(span);
113
- }
114
- }
115
-
116
- #syncAria() {
117
- if (this.disabled) {
118
- this.setAttribute('aria-disabled', 'true');
119
- this.setAttribute('tabindex', '-1');
120
- } else {
121
- this.removeAttribute('aria-disabled');
122
- this.setAttribute('tabindex', '0');
123
- }
124
- }
125
-
126
- render() {
127
- const iconEl = this.querySelector('[slot="icon"]');
128
- if (this.icon) {
129
- if (iconEl) iconEl.setAttribute('name', this.icon);
130
- else {
131
- const el = document.createElement('icon-ui');
132
- el.setAttribute('slot', 'icon');
133
- el.setAttribute('name', this.icon);
134
- this.prepend(el);
135
- }
136
- } else if (iconEl) {
137
- iconEl.remove();
138
- }
139
-
140
- const textEl = this.querySelector('[slot="text"]');
141
- if (textEl) textEl.textContent = this.text;
142
-
143
- this.#syncAria();
144
- }
145
- }
146
-
147
- customElements.define('action-item-ui', UIActionItem);
15
+ defineIfFree('action-list-ui', UIActionList);
16
+ defineIfFree('action-item-ui', UIActionItem);
148
17
 
149
18
  export { UIActionList, UIActionItem };
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Non-side-effect class export for `<action-list-ui>` (+ co-located primitives).
3
+ *
4
+ * Importing this file gives you the class(es) without auto-registering the tag.
5
+ * Useful for test isolation, subclassing with tag-name override, or selective
6
+ * composition.
7
+ *
8
+ * The auto-register path stays at `@adia-ai/web-components/components/action-list`
9
+ * (which imports this file + calls `defineIfFree()`).
10
+ *
11
+ * @see ../../USAGE.md#registration--auto-vs-explicit
12
+ */
13
+
14
+ /**
15
+ * <action-list-ui>
16
+ * <action-item-ui icon="plus" text="New Project" value="new"></action-item-ui>
17
+ * <action-item-ui icon="users" text="Invite Team" value="invite"></action-item-ui>
18
+ * <action-item-ui icon="download" text="Export Data" value="export"></action-item-ui>
19
+ * </action-list-ui>
20
+ *
21
+ * Inline (non-dropdown) list of command actions. Think of it as a menu that
22
+ * stays open — useful for quick-actions cards, settings rails, sidebar shortcuts.
23
+ *
24
+ * Differs from <menu-ui> (which renders in a popover) and <list-ui> (which is
25
+ * passive — no hover/click semantics).
26
+ *
27
+ * Fires `action` CustomEvent with { value, text, item } when an item is clicked
28
+ * or activated via keyboard (Enter / Space). Keyboard nav: ArrowUp/Down, Home/End.
29
+ */
30
+
31
+ import { UIElement } from '../../core/element.js';
32
+
33
+ export class UIActionList extends UIElement {
34
+ static properties = {};
35
+ static template = () => null;
36
+
37
+ #bound = false;
38
+
39
+ connected() {
40
+ this.setAttribute('role', 'list');
41
+ if (!this.#bound) {
42
+ this.#bound = true;
43
+ this.addEventListener('click', this.#onClick);
44
+ this.addEventListener('keydown', this.#onKey);
45
+ }
46
+ }
47
+
48
+ disconnected() {
49
+ this.removeEventListener('click', this.#onClick);
50
+ this.removeEventListener('keydown', this.#onKey);
51
+ this.#bound = false;
52
+ }
53
+
54
+ #items() {
55
+ return Array.from(this.querySelectorAll(':scope > action-item-ui:not([disabled])'));
56
+ }
57
+
58
+ #onClick = (e) => {
59
+ const item = e.target.closest('action-item-ui');
60
+ if (!item || item.hasAttribute('disabled')) return;
61
+ if (!this.contains(item)) return;
62
+ this.dispatchEvent(new CustomEvent('action', {
63
+ bubbles: true,
64
+ detail: { value: item.getAttribute('value') || '', text: item.getAttribute('text') || item.textContent.trim(), item },
65
+ }));
66
+ };
67
+
68
+ #onKey = (e) => {
69
+ const items = this.#items();
70
+ if (!items.length) return;
71
+ const active = document.activeElement?.closest?.('action-item-ui');
72
+ const i = active ? items.indexOf(active) : -1;
73
+ const focus = (idx) => {
74
+ const next = items[(idx + items.length) % items.length];
75
+ next?.focus?.({ preventScroll: true });
76
+ };
77
+ switch (e.key) {
78
+ case 'ArrowDown': e.preventDefault(); focus(i + 1); break;
79
+ case 'ArrowUp': e.preventDefault(); focus(i - 1); break;
80
+ case 'Home': e.preventDefault(); focus(0); break;
81
+ case 'End': e.preventDefault(); focus(items.length - 1); break;
82
+ case 'Enter':
83
+ case ' ': {
84
+ if (active) { e.preventDefault(); active.click(); }
85
+ break;
86
+ }
87
+ }
88
+ };
89
+ }
90
+
91
+ export class UIActionItem extends UIElement {
92
+ static properties = {
93
+ icon: { type: String, default: '', reflect: true },
94
+ text: { type: String, default: '', reflect: true },
95
+ value: { type: String, default: '', reflect: true },
96
+ variant: { type: String, default: 'default', reflect: true },
97
+ disabled: { type: Boolean, default: false, reflect: true },
98
+ };
99
+
100
+ static template = () => null;
101
+
102
+ connected() {
103
+ this.setAttribute('role', 'listitem');
104
+ if (!this.hasAttribute('tabindex')) this.setAttribute('tabindex', '0');
105
+ this.#stamp();
106
+ this.#syncAria();
107
+ }
108
+
109
+ #stamp() {
110
+ if (this.querySelector('[slot="text"]')) return;
111
+
112
+ if (this.icon) {
113
+ const iconEl = document.createElement('icon-ui');
114
+ iconEl.setAttribute('slot', 'icon');
115
+ iconEl.setAttribute('name', this.icon);
116
+ this.appendChild(iconEl);
117
+ }
118
+
119
+ if (this.text) {
120
+ const span = document.createElement('span');
121
+ span.setAttribute('slot', 'text');
122
+ span.textContent = this.text;
123
+ this.appendChild(span);
124
+ }
125
+ }
126
+
127
+ #syncAria() {
128
+ if (this.disabled) {
129
+ this.setAttribute('aria-disabled', 'true');
130
+ this.setAttribute('tabindex', '-1');
131
+ } else {
132
+ this.removeAttribute('aria-disabled');
133
+ this.setAttribute('tabindex', '0');
134
+ }
135
+ }
136
+
137
+ render() {
138
+ const iconEl = this.querySelector('[slot="icon"]');
139
+ if (this.icon) {
140
+ if (iconEl) iconEl.setAttribute('name', this.icon);
141
+ else {
142
+ const el = document.createElement('icon-ui');
143
+ el.setAttribute('slot', 'icon');
144
+ el.setAttribute('name', this.icon);
145
+ this.prepend(el);
146
+ }
147
+ } else if (iconEl) {
148
+ iconEl.remove();
149
+ }
150
+
151
+ const textEl = this.querySelector('[slot="text"]');
152
+ if (textEl) textEl.textContent = this.text;
153
+
154
+ this.#syncAria();
155
+ }
156
+ }