@adia-ai/web-components 0.6.4 → 0.6.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 (107) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/USAGE.md +100 -5
  3. package/bin/doc.mjs +379 -0
  4. package/components/accordion/accordion.examples.md +49 -0
  5. package/components/action-list/action-list.examples.md +33 -0
  6. package/components/agent-artifact/agent-artifact.examples.md +28 -0
  7. package/components/agent-feedback-bar/agent-feedback-bar.examples.md +24 -0
  8. package/components/agent-questions/agent-questions.examples.md +13 -0
  9. package/components/agent-reasoning/agent-reasoning.examples.md +28 -0
  10. package/components/agent-suggestions/agent-suggestions.examples.md +19 -0
  11. package/components/agent-trace/agent-trace.examples.md +19 -0
  12. package/components/alert/alert.examples.md +19 -0
  13. package/components/aside/aside.examples.md +38 -0
  14. package/components/avatar/avatar.examples.md +19 -0
  15. package/components/badge/badge.examples.md +19 -0
  16. package/components/block/block.examples.md +29 -0
  17. package/components/breadcrumb/breadcrumb.examples.md +32 -0
  18. package/components/button/button.examples.md +19 -0
  19. package/components/calendar-picker/calendar-picker.examples.md +23 -0
  20. package/components/canvas/canvas.examples.md +49 -0
  21. package/components/card/card.examples.md +25 -0
  22. package/components/chart/chart.examples.md +19 -0
  23. package/components/chart-legend/chart-legend.examples.md +22 -0
  24. package/components/chat-thread/chat-thread.examples.md +35 -0
  25. package/components/check/check.examples.md +19 -0
  26. package/components/code/code.examples.md +31 -0
  27. package/components/col/col.examples.md +11 -0
  28. package/components/color-input/color-input.examples.md +19 -0
  29. package/components/color-picker/color-picker.examples.md +19 -0
  30. package/components/command/command.examples.md +58 -0
  31. package/components/demo-toggle/demo-toggle.examples.md +19 -0
  32. package/components/description-list/description-list.examples.md +37 -0
  33. package/components/divider/divider.examples.md +31 -0
  34. package/components/drawer/drawer.examples.md +63 -0
  35. package/components/embed/embed.examples.md +19 -0
  36. package/components/empty-state/empty-state.examples.md +21 -0
  37. package/components/feed/feed.examples.md +19 -0
  38. package/components/field/class.js +5 -4
  39. package/components/field/field.a2ui.json +9 -0
  40. package/components/field/field.css +10 -0
  41. package/components/field/field.d.ts +2 -0
  42. package/components/field/field.examples.md +29 -0
  43. package/components/field/field.test.js +43 -0
  44. package/components/field/field.yaml +11 -0
  45. package/components/fields/fields.examples.md +58 -0
  46. package/components/footer/footer.examples.md +18 -0
  47. package/components/grid/grid.examples.md +21 -0
  48. package/components/header/header.examples.md +32 -0
  49. package/components/heatmap/heatmap.examples.md +19 -0
  50. package/components/icon/icon.examples.md +19 -0
  51. package/components/image/image.examples.md +19 -0
  52. package/components/input/input.examples.md +21 -0
  53. package/components/inspector/inspector.examples.md +27 -0
  54. package/components/kbd/kbd.examples.md +29 -0
  55. package/components/link/link.examples.md +25 -0
  56. package/components/list/list.examples.md +33 -0
  57. package/components/menu/menu.examples.md +37 -0
  58. package/components/modal/modal.examples.md +43 -0
  59. package/components/nav/nav.examples.md +39 -0
  60. package/components/nav-group/nav-group.examples.md +35 -0
  61. package/components/nav-item/nav-item.examples.md +25 -0
  62. package/components/noodles/noodles.examples.md +30 -0
  63. package/components/option-card/option-card.examples.md +47 -0
  64. package/components/otp-input/otp-input.examples.md +19 -0
  65. package/components/page/page.examples.md +46 -0
  66. package/components/pagination/pagination.examples.md +19 -0
  67. package/components/pane/pane.examples.md +40 -0
  68. package/components/pipeline-status/pipeline-status.examples.md +19 -0
  69. package/components/popover/popover.examples.md +34 -0
  70. package/components/progress/progress.examples.md +19 -0
  71. package/components/progress-row/progress-row.examples.md +19 -0
  72. package/components/radio/radio.examples.md +19 -0
  73. package/components/range/range.examples.md +19 -0
  74. package/components/rating/rating.examples.md +19 -0
  75. package/components/richtext/richtext.examples.md +19 -0
  76. package/components/row/row.examples.md +11 -0
  77. package/components/search/search.examples.md +19 -0
  78. package/components/section/section.examples.md +37 -0
  79. package/components/segment/segment.examples.md +32 -0
  80. package/components/segmented/segmented.examples.md +31 -0
  81. package/components/select/select.examples.md +49 -0
  82. package/components/skeleton/skeleton.examples.md +19 -0
  83. package/components/slider/slider.examples.md +21 -0
  84. package/components/stack/stack.examples.md +10 -0
  85. package/components/stat/stat.examples.md +19 -0
  86. package/components/step-progress/step-progress.examples.md +19 -0
  87. package/components/stepper/stepper.examples.md +37 -0
  88. package/components/stream/stream.examples.md +19 -0
  89. package/components/swatch/swatch.examples.md +23 -0
  90. package/components/swiper/swiper.examples.md +139 -0
  91. package/components/switch/switch.examples.md +19 -0
  92. package/components/table/table.examples.md +19 -0
  93. package/components/table-toolbar/table-toolbar.examples.md +12 -0
  94. package/components/tabs/tabs.examples.md +49 -0
  95. package/components/tag/tag.examples.md +19 -0
  96. package/components/text/text.examples.md +19 -0
  97. package/components/textarea/textarea.examples.md +23 -0
  98. package/components/timeline/timeline.examples.md +35 -0
  99. package/components/toast/toast.examples.md +19 -0
  100. package/components/toggle-group/toggle-group.examples.md +33 -0
  101. package/components/toggle-scheme/toggle-scheme.examples.md +19 -0
  102. package/components/toolbar/toolbar.examples.md +46 -0
  103. package/components/tooltip/tooltip.examples.md +25 -0
  104. package/components/tree/tree.examples.md +57 -0
  105. package/components/upload/upload.examples.md +19 -0
  106. package/custom-elements.json +9012 -0
  107. package/package.json +7 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog — @adia-ai/web-components
2
2
 
3
+ ## [0.6.7] — 2026-05-19
4
+
5
+ ### Added
6
+ - **`<name>.examples.md` ships in npm package** (96 components, ~67KB total).
7
+ Generated by `scripts/build/generate-examples-md.mjs` from `<name>.examples.html`.
8
+ External consumers can now read canonical markup fragments directly from
9
+ `node_modules/@adia-ai/web-components/components/<name>/<name>.examples.md`.
10
+ - **`custom-elements.json` ships in npm package** (W3C Custom Elements Manifest v2.1.0).
11
+ Generated from per-component yaml files. Enables IDE LSP autocomplete and
12
+ cross-tool interop (Storybook, VS Code WC extensions).
13
+ - **`npx @adia-ai/web-components doc <name>` CLI** prints yaml summary + live
14
+ demo URL + first example fragment for any component. Bare `doc` lists all.
15
+ - **`USAGE.md § Data binding with data-stream-*`** new top-level section
16
+ covering the declarative `data-stream-*` attribute family (was previously
17
+ undocumented despite being used in 12+ components).
18
+
19
+ ## [0.6.6] — 2026-05-18
20
+
21
+ ### Added
22
+ - `<field-ui align="end">` — new `align` prop (reflected string, enum: `start`|`end`).
23
+ `start` is the current default (no visual change). `end` right-aligns the label
24
+ within its grid cell (`justify-self: end; text-align: end`), useful in multi-field
25
+ forms where labels share a visual column and trailing-flush alignment aids scanability
26
+ (right-to-input reading path). CSS-only; no JS logic change. §304.
27
+ ## [0.6.5] — 2026-05-18
28
+
29
+ ### Changed
30
+ - Lockstep version bump for TS Phase 6 sealing (ADR-0029).
3
31
  Follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
4
32
  [Semantic Versioning](https://semver.org/).
5
33
 
package/USAGE.md CHANGED
@@ -14,11 +14,12 @@ The complete reference for engineers and agents **integrating** AdiaUI into an a
14
14
  4. [Property binding patterns (templates / framework integration)](#property-binding-patterns)
15
15
  5. [Event contract — `CustomEvent` with `detail`](#event-contract)
16
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)
17
+ 7. [Data binding with `data-stream-*`](#data-binding-with-data-stream-)
18
+ 8. [Lifecycle `connected` / `render` / `updated` / `disconnected`](#lifecycle)
19
+ 9. [Theming, density, size](#theming-density-size)
20
+ 10. [Registration — auto vs explicit](#registration--auto-vs-explicit)
21
+ 11. [TypeScript](#typescript)
22
+ 12. [Anti-patterns](#anti-patterns)
22
23
 
23
24
  ---
24
25
 
@@ -461,6 +462,100 @@ form.addEventListener('submit', (e) => {
461
462
 
462
463
  ---
463
464
 
465
+ ## Data binding with `data-stream-*`
466
+
467
+ Many AdiaUI components (`<chart-ui>`, `<heatmap-ui>`, `<table-ui>`, `<stat-ui>`, `<progress-row-ui>`, and ~7 others) support **declarative remote-data binding** via the `data-stream-*` attribute family. You point a component at a URL, and it self-fetches (REST poll) or self-subscribes (SSE) and pushes the result into one of its properties. No JS glue required.
468
+
469
+ This is the canonical "wire a component to a backend" pattern in AdiaUI. Reach for it before writing a `fetch()` loop in your app code.
470
+
471
+ ### Concept
472
+
473
+ A component that opts in watches its `data-stream-*` attributes. When `data-stream-src` is set on a connected element, the component starts a transport (poll, SSE, or manual) and assigns each payload to a target property (e.g. `data` on `<table-ui>`, `value` on `<stat-ui>`). Change the attribute and the transport restarts; remove the attribute (or disconnect the element) and the transport tears down.
474
+
475
+ Because the binding is attribute-driven, it survives SSR, server-rendered partials, htmx swaps, framework hydration, and templating engines that have no concept of property assignment.
476
+
477
+ ### Attribute reference
478
+
479
+ | Attribute | Purpose | Default |
480
+ |---|---|---|
481
+ | `data-stream-src` | URL — REST endpoint or SSE source. Setting this activates the binding. | (required) |
482
+ | `data-stream-mode` | `"poll"`, `"sse"`, or `"manual"`. `manual` fetches once on connect and on attribute change. | `"poll"` |
483
+ | `data-stream-interval` | Poll interval in milliseconds. Ignored for `sse` / `manual`. | `5000` |
484
+ | `data-stream-path` | Dot-path into the JSON response to extract before binding (e.g. `claims` extracts `response.claims`; `data.items` extracts `response.data.items`). | (whole response) |
485
+ | `data-stream-target` | Which component property receives the payload. | component-specific (`data` for `<table-ui>`, `value` for `<stat-ui>`, `data` for `<chart-ui>`, …) |
486
+ | `data-stream-method` | HTTP method for REST mode. `POST` is supported when you need a request body via headers/config. | `"GET"` |
487
+ | `data-stream-headers` | JSON-stringified object of request headers (e.g. `'{"Authorization":"Bearer …"}'`). | `null` |
488
+ | `data-stream-id` | Logical transport key. Multiple elements with the same `data-stream-id` share one underlying fetch/SSE connection. | (per-element) |
489
+
490
+ ### REST polling
491
+
492
+ ```html
493
+ <table-ui
494
+ data-stream-src="/api/claims"
495
+ data-stream-interval="10000"
496
+ data-stream-target="data"
497
+ ></table-ui>
498
+ ```
499
+
500
+ The table fetches `/api/claims` every 10s and assigns the response to its `data` property. If the response is wrapped (e.g. `{ claims: [...] }`), add `data-stream-path="claims"` to drill in.
501
+
502
+ ### SSE streaming
503
+
504
+ ```html
505
+ <stat-ui
506
+ label="Active"
507
+ data-stream-src="/api/active-count"
508
+ data-stream-mode="sse"
509
+ data-stream-target="value"
510
+ ></stat-ui>
511
+ ```
512
+
513
+ Opens an `EventSource` against `/api/active-count`. Each SSE message's `data` field is JSON-parsed (when possible) and pushed into the stat's `value`. The connection closes on disconnect.
514
+
515
+ ### Shared transport
516
+
517
+ When two or more components need the same source, give them a matching `data-stream-id` and they will share a single fetch/SSE subscription:
518
+
519
+ ```html
520
+ <table-ui
521
+ data-stream-src="/api/claims"
522
+ data-stream-id="shared-claims"
523
+ data-stream-target="data"
524
+ ></table-ui>
525
+
526
+ <stat-ui
527
+ label="Total"
528
+ data-stream-src="/api/claims"
529
+ data-stream-id="shared-claims"
530
+ data-stream-path="length"
531
+ data-stream-target="value"
532
+ ></stat-ui>
533
+ ```
534
+
535
+ One request feeds both. Each element still applies its own `data-stream-path` and `data-stream-target` independently. The shared transport is reference-counted; the last element to disconnect tears it down.
536
+
537
+ ### SSR / server rendering
538
+
539
+ `data-stream-*` is **client-only**. Server-rendered markup that contains these attributes is safe — the attributes are just strings on the element — and the transport only activates once the component is upgraded in the browser. This means you can:
540
+
541
+ - Server-render the initial empty/skeleton state of a `<table-ui>` and let the client take over.
542
+ - Emit `data-stream-*` from any templating layer (Jinja, ERB, Handlebars, htmx fragments) without server-side coupling to the data-stream runtime.
543
+ - Hydrate framework apps without special-casing — React/Vue/Svelte just need to render the attribute; they do not need to subscribe.
544
+
545
+ If you need a server-rendered first paint of *real* data, render it normally (slot or attribute) — the data-stream binding will replace it on first successful payload.
546
+
547
+ ### Authoritative source
548
+
549
+ The implementation lives at:
550
+
551
+ ```
552
+ packages/web-components/core/data-stream.js
553
+ ```
554
+
555
+ A component opts in by declaring a `data_stream:` block in its YAML descriptor (see `packages/web-components/components/*/*.yaml`). That block is the source of truth for which target properties are bindable and which defaults apply for that specific component. When in doubt, read the component's YAML and `core/data-stream.js` — this document is a discoverability summary, not a spec.
556
+
557
+ ---
558
+
464
559
  ## Lifecycle
465
560
 
466
561
  `UIElement` exposes four overridable lifecycle methods. Defaults are no-ops. Override what you need:
package/bin/doc.mjs ADDED
@@ -0,0 +1,379 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Usage:
4
+ * npx @adia-ai/web-components doc button
5
+ * npx @adia-ai/web-components doc field
6
+ * npx @adia-ai/web-components doc # list all components
7
+ *
8
+ * Prints a quick summary + live demo URL + first example fragment for any
9
+ * AdiaUI component. Reads from the installed package's yaml/.examples.md
10
+ * (falls back to <name>.examples.html if .md is not present).
11
+ *
12
+ * No external yaml dependency — uses a minimal regex-based parser scoped
13
+ * to the small subset of fields we need: name, tag, component,
14
+ * description, props, slots, events.
15
+ */
16
+
17
+ import { readFileSync, existsSync, readdirSync, statSync } from 'node:fs';
18
+ import { resolve, dirname, join } from 'node:path';
19
+ import { fileURLToPath } from 'node:url';
20
+
21
+ const __filename = fileURLToPath(import.meta.url);
22
+ const __dirname = dirname(__filename);
23
+
24
+ // bin/ lives at packages/web-components/bin/, components/ is one level up
25
+ const COMPONENTS_DIR = resolve(__dirname, '..', 'components');
26
+ const DEMO_BASE = 'https://ui-kit.exe.xyz/site/components';
27
+
28
+ /* ------------------------------------------------------------------ */
29
+ /* Minimal YAML extractor */
30
+ /* ------------------------------------------------------------------ */
31
+ /**
32
+ * Parses just the subset of YAML used by AdiaUI component yaml files:
33
+ * - top-level scalar keys (name, tag, component, description, …)
34
+ * - top-level mapping keys whose values are mappings of leaf scalars
35
+ * (props, slots, events)
36
+ *
37
+ * Returns:
38
+ * {
39
+ * name, tag, component, description,
40
+ * props: { propName: { description, type, default, enum?, ... } },
41
+ * slots: { slotName: { description } },
42
+ * events: { eventName: { description, type? } },
43
+ * }
44
+ *
45
+ * Defensive: any parse error returns a partial object plus an `_errors`
46
+ * array — the caller decides how to surface failures.
47
+ */
48
+ function parseYaml(source) {
49
+ const out = {
50
+ name: '',
51
+ tag: '',
52
+ component: '',
53
+ description: '',
54
+ props: {},
55
+ slots: {},
56
+ events: {},
57
+ _errors: [],
58
+ };
59
+
60
+ // Strip comments + trailing whitespace, keep blank lines for block detection
61
+ const rawLines = source.split(/\r?\n/);
62
+ const lines = rawLines.map((l) => {
63
+ // strip line comments unless inside a quoted string (rough heuristic)
64
+ const m = l.match(/^([^#"']*)(#.*)?$/);
65
+ return m ? m[1].replace(/\s+$/, '') : l;
66
+ });
67
+
68
+ /** Find the line range of a top-level key block (indent === 0). */
69
+ function blockRange(key) {
70
+ const startRe = new RegExp(`^${key}\\s*:\\s*(.*)$`);
71
+ let start = -1;
72
+ let inlineValue = null;
73
+ for (let i = 0; i < lines.length; i++) {
74
+ const m = lines[i].match(startRe);
75
+ if (m && !lines[i].startsWith(' ') && !lines[i].startsWith('\t')) {
76
+ start = i;
77
+ inlineValue = m[1];
78
+ break;
79
+ }
80
+ }
81
+ if (start === -1) return null;
82
+
83
+ let end = lines.length;
84
+ for (let i = start + 1; i < lines.length; i++) {
85
+ const l = lines[i];
86
+ if (l === '') continue;
87
+ // next top-level key (no leading whitespace, contains ':')
88
+ if (!/^\s/.test(l) && /^[A-Za-z_$][\w$-]*\s*:/.test(l)) {
89
+ end = i;
90
+ break;
91
+ }
92
+ }
93
+ return { start, end, inlineValue };
94
+ }
95
+
96
+ /** Unquote a yaml scalar value (handles "…", '…', |, >, bare). */
97
+ function unquote(v) {
98
+ if (v == null) return '';
99
+ let s = String(v).trim();
100
+ if (s === '') return '';
101
+ if (
102
+ (s.startsWith('"') && s.endsWith('"')) ||
103
+ (s.startsWith("'") && s.endsWith("'"))
104
+ ) {
105
+ return s.slice(1, -1);
106
+ }
107
+ return s;
108
+ }
109
+
110
+ /** Extract a top-level scalar field (single-line OR block scalar). */
111
+ function scalar(key) {
112
+ const r = blockRange(key);
113
+ if (!r) return '';
114
+ const head = r.inlineValue.trim();
115
+ // block scalar? `description: >-` / `>` / `|`
116
+ if (head === '>' || head === '>-' || head === '|' || head === '|-') {
117
+ const buf = [];
118
+ for (let i = r.start + 1; i < r.end; i++) {
119
+ const l = lines[i];
120
+ if (l === '') {
121
+ buf.push('');
122
+ continue;
123
+ }
124
+ if (!/^\s/.test(l)) break;
125
+ buf.push(l.replace(/^\s+/, ''));
126
+ }
127
+ const joined = buf.join(' ').replace(/\s+/g, ' ').trim();
128
+ return joined;
129
+ }
130
+ return unquote(head);
131
+ }
132
+
133
+ out.name = scalar('name');
134
+ out.tag = scalar('tag');
135
+ out.component = scalar('component');
136
+ out.description = scalar('description');
137
+
138
+ /**
139
+ * Parse a mapping-of-mappings block (props/slots/events).
140
+ * Each child key is a 2-space-indented identifier, its value is a
141
+ * 4-space-indented mapping of leaf scalars.
142
+ */
143
+ function mappingOfMappings(key) {
144
+ const r = blockRange(key);
145
+ if (!r) return {};
146
+ const result = {};
147
+ let currentKey = null;
148
+ let currentField = null; // for block-scalar accumulation
149
+ let currentBuf = null;
150
+ let currentIndent = 0;
151
+
152
+ const flushBlockScalar = () => {
153
+ if (currentKey && currentField && currentBuf) {
154
+ const joined = currentBuf.join(' ').replace(/\s+/g, ' ').trim();
155
+ result[currentKey][currentField] = joined;
156
+ }
157
+ currentField = null;
158
+ currentBuf = null;
159
+ };
160
+
161
+ for (let i = r.start + 1; i < r.end; i++) {
162
+ const l = lines[i];
163
+ if (l === '') continue;
164
+ const indent = l.match(/^( *)/)[0].length;
165
+
166
+ // 2-space child key: " propName:" or " propName: value"
167
+ if (indent === 2) {
168
+ flushBlockScalar();
169
+ const m = l.match(/^ {2}([^:\s]+)\s*:\s*(.*)$/);
170
+ if (m) {
171
+ currentKey = m[1];
172
+ result[currentKey] = {};
173
+ const v = m[2].trim();
174
+ if (v && v !== '>' && v !== '>-' && v !== '|' && v !== '|-') {
175
+ // shorthand " prop: desc"
176
+ result[currentKey].description = unquote(v);
177
+ }
178
+ }
179
+ continue;
180
+ }
181
+
182
+ // 4-space leaf field: " description: …"
183
+ if (indent === 4 && currentKey) {
184
+ flushBlockScalar();
185
+ const m = l.match(/^ {4}([^:\s]+)\s*:\s*(.*)$/);
186
+ if (m) {
187
+ const fk = m[1];
188
+ const v = m[2].trim();
189
+ if (v === '>' || v === '>-' || v === '|' || v === '|-') {
190
+ currentField = fk;
191
+ currentBuf = [];
192
+ currentIndent = 6;
193
+ } else {
194
+ result[currentKey][fk] = unquote(v);
195
+ }
196
+ }
197
+ continue;
198
+ }
199
+
200
+ // continuation of a block scalar (indent >= currentIndent)
201
+ if (currentField && currentBuf && indent >= currentIndent) {
202
+ currentBuf.push(l.slice(currentIndent));
203
+ continue;
204
+ }
205
+
206
+ // 6-space (or deeper) list/enum entries we ignore for now, but
207
+ // capture enum lists for props (best-effort).
208
+ if (indent >= 6 && currentKey) {
209
+ const em = l.match(/^\s+-\s+(.*)$/);
210
+ if (em && currentField === 'enum') {
211
+ currentBuf = currentBuf || [];
212
+ // we don't really store enum lists here; left for the
213
+ // manifest generator which re-parses with its own logic.
214
+ }
215
+ }
216
+ }
217
+ flushBlockScalar();
218
+ return result;
219
+ }
220
+
221
+ try {
222
+ out.props = mappingOfMappings('props');
223
+ } catch (e) {
224
+ out._errors.push(`props: ${e.message}`);
225
+ }
226
+ try {
227
+ out.slots = mappingOfMappings('slots');
228
+ } catch (e) {
229
+ out._errors.push(`slots: ${e.message}`);
230
+ }
231
+ try {
232
+ out.events = mappingOfMappings('events');
233
+ } catch (e) {
234
+ out._errors.push(`events: ${e.message}`);
235
+ }
236
+
237
+ return out;
238
+ }
239
+
240
+ /* ------------------------------------------------------------------ */
241
+ /* Pretty-print helpers */
242
+ /* ------------------------------------------------------------------ */
243
+ function wrap(s, width = 76, indent = ' ') {
244
+ if (!s) return '';
245
+ const words = String(s).split(/\s+/);
246
+ const lines = [];
247
+ let line = '';
248
+ for (const w of words) {
249
+ if ((line + ' ' + w).trim().length > width) {
250
+ lines.push(line);
251
+ line = w;
252
+ } else {
253
+ line = (line ? line + ' ' : '') + w;
254
+ }
255
+ }
256
+ if (line) lines.push(line);
257
+ return lines.map((l) => indent + l).join('\n');
258
+ }
259
+
260
+ function printSection(title, entries, keyLabel) {
261
+ const keys = Object.keys(entries || {});
262
+ if (keys.length === 0) return;
263
+ console.log(`${title} (${keys.length})`);
264
+ for (const k of keys) {
265
+ const e = entries[k] || {};
266
+ const meta = [];
267
+ if (e.type) meta.push(e.type);
268
+ if (e.default !== undefined && e.default !== '') meta.push(`default: ${e.default}`);
269
+ const head = meta.length ? ` • ${k} [${meta.join(', ')}]` : ` • ${k}`;
270
+ console.log(head);
271
+ if (e.description) console.log(wrap(e.description, 72, ' '));
272
+ }
273
+ console.log('');
274
+ }
275
+
276
+ function firstExampleFragment(md) {
277
+ // First markdown ## … block, or whole file if no headings.
278
+ const lines = md.split(/\r?\n/);
279
+ let start = -1;
280
+ let end = lines.length;
281
+ for (let i = 0; i < lines.length; i++) {
282
+ if (/^##\s+/.test(lines[i])) {
283
+ if (start === -1) {
284
+ start = i;
285
+ } else {
286
+ end = i;
287
+ break;
288
+ }
289
+ }
290
+ }
291
+ if (start === -1) return md.trim();
292
+ return lines.slice(start, end).join('\n').trim();
293
+ }
294
+
295
+ function firstHtmlFragment(html) {
296
+ // Heuristic: first <section> … </section>, else first <!-- example: --> … next, else first ~30 lines.
297
+ const sect = html.match(/<section[\s\S]*?<\/section>/i);
298
+ if (sect) return sect[0].trim();
299
+ const lines = html.split(/\r?\n/);
300
+ return lines.slice(0, 30).join('\n').trim();
301
+ }
302
+
303
+ /* ------------------------------------------------------------------ */
304
+ /* Main */
305
+ /* ------------------------------------------------------------------ */
306
+ function listComponents() {
307
+ let entries;
308
+ try {
309
+ entries = readdirSync(COMPONENTS_DIR);
310
+ } catch (e) {
311
+ console.error(`Cannot read components directory: ${COMPONENTS_DIR}`);
312
+ process.exit(1);
313
+ }
314
+ const names = [];
315
+ for (const d of entries) {
316
+ let s;
317
+ try { s = statSync(join(COMPONENTS_DIR, d)); } catch { continue; }
318
+ if (!s.isDirectory()) continue;
319
+ const yamlPath = join(COMPONENTS_DIR, d, `${d}.yaml`);
320
+ if (existsSync(yamlPath)) names.push(d);
321
+ }
322
+ names.sort();
323
+ console.log(`AdiaUI — ${names.length} components\n`);
324
+ for (const c of names) console.log(` ${c}`);
325
+ console.log(`\nRun: npx @adia-ai/web-components doc <name>\n`);
326
+ }
327
+
328
+ const name = process.argv[2];
329
+ if (!name) {
330
+ listComponents();
331
+ process.exit(0);
332
+ }
333
+
334
+ const yamlPath = join(COMPONENTS_DIR, name, `${name}.yaml`);
335
+ if (!existsSync(yamlPath)) {
336
+ console.error(`Component '${name}' not found in catalog.`);
337
+ console.error(`Try: npx @adia-ai/web-components doc # list all`);
338
+ process.exit(1);
339
+ }
340
+
341
+ const source = readFileSync(yamlPath, 'utf-8');
342
+ const data = parseYaml(source);
343
+
344
+ console.log('');
345
+ console.log(`${data.name || name} <${data.tag || name + '-ui'}>`);
346
+ console.log('─'.repeat(60));
347
+ if (data.description) {
348
+ console.log(wrap(data.description, 76, ''));
349
+ console.log('');
350
+ }
351
+
352
+ printSection('Props', data.props, 'prop');
353
+ printSection('Slots', data.slots, 'slot');
354
+ printSection('Events', data.events, 'event');
355
+
356
+ if (data._errors && data._errors.length) {
357
+ console.log('Parse warnings:');
358
+ for (const e of data._errors) console.log(` - ${e}`);
359
+ console.log('');
360
+ }
361
+
362
+ console.log(`Live demo: ${DEMO_BASE}/${name}`);
363
+ console.log('');
364
+
365
+ const examplesMdPath = join(COMPONENTS_DIR, name, `${name}.examples.md`);
366
+ const examplesHtmlPath = join(COMPONENTS_DIR, name, `${name}.examples.html`);
367
+ if (existsSync(examplesMdPath)) {
368
+ const src = readFileSync(examplesMdPath, 'utf-8');
369
+ console.log('Example');
370
+ console.log('─'.repeat(60));
371
+ console.log(firstExampleFragment(src));
372
+ console.log('');
373
+ } else if (existsSync(examplesHtmlPath)) {
374
+ const src = readFileSync(examplesHtmlPath, 'utf-8');
375
+ console.log('Example (HTML)');
376
+ console.log('─'.repeat(60));
377
+ console.log(firstHtmlFragment(src));
378
+ console.log('');
379
+ }
@@ -0,0 +1,49 @@
1
+ # accordion — Examples
2
+
3
+ ## basic
4
+
5
+ ```html
6
+ <accordion-ui>
7
+ <accordion-item-ui text="What is AdiaUI?">
8
+ <p>AdiaUI is a zero-dependency vanilla JS web component library for building modern interfaces. It uses native custom elements, OKLCH colors, and @scope CSS isolation.</p>
9
+ </accordion-item-ui>
10
+ <accordion-item-ui text="Do I need a build tool?">
11
+ <p>No. AdiaUI components are plain ES modules. Import them directly in a script tag or from a module bundler -- both work without configuration.</p>
12
+ </accordion-item-ui>
13
+ <accordion-item-ui text="How are styles scoped?">
14
+ <p>Each component uses CSS @scope blocks keyed to the element tag name. This provides isolation without Shadow DOM, keeping components inspectable in DevTools.</p>
15
+ </accordion-item-ui>
16
+ </accordion-ui>
17
+ ```
18
+
19
+ ## multiple
20
+
21
+ ```html
22
+ <accordion-ui multiple>
23
+ <accordion-item-ui text="Section A" open>
24
+ <p>This section starts open and remains open when you expand other sections.</p>
25
+ </accordion-item-ui>
26
+ <accordion-item-ui text="Section B">
27
+ <p>Open this alongside Section A to see multiple open behavior.</p>
28
+ </accordion-item-ui>
29
+ <accordion-item-ui text="Section C">
30
+ <p>All three can be expanded at the same time.</p>
31
+ </accordion-item-ui>
32
+ </accordion-ui>
33
+ ```
34
+
35
+ ## pre-opened
36
+
37
+ ```html
38
+ <accordion-ui>
39
+ <accordion-item-ui text="Closed by default">
40
+ <p>This item is collapsed initially.</p>
41
+ </accordion-item-ui>
42
+ <accordion-item-ui text="Open by default" open>
43
+ <p>This item renders expanded because it has the open attribute.</p>
44
+ </accordion-item-ui>
45
+ <accordion-item-ui text="Also closed">
46
+ <p>Another collapsed item.</p>
47
+ </accordion-item-ui>
48
+ </accordion-ui>
49
+ ```
@@ -0,0 +1,33 @@
1
+ # action-list — Examples
2
+
3
+ ## Basic
4
+
5
+ ```html
6
+ <action-list-ui>
7
+ <action-item-ui text="New Project" value="new"></action-item-ui>
8
+ <action-item-ui text="Import Data" value="import"></action-item-ui>
9
+ <action-item-ui text="Export Report" value="export"></action-item-ui>
10
+ </action-list-ui>
11
+ ```
12
+
13
+ ## With Icons
14
+
15
+ ```html
16
+ <action-list-ui>
17
+ <action-item-ui icon="plus" text="New Project" value="new"></action-item-ui>
18
+ <action-item-ui icon="users" text="Invite Team" value="invite"></action-item-ui>
19
+ <action-item-ui icon="download" text="Export Data" value="export"></action-item-ui>
20
+ <action-item-ui icon="gear" text="Settings" value="settings"></action-item-ui>
21
+ </action-list-ui>
22
+ ```
23
+
24
+ ## Destructive Items
25
+
26
+ ```html
27
+ <action-list-ui>
28
+ <action-item-ui icon="pencil" text="Edit" value="edit"></action-item-ui>
29
+ <action-item-ui icon="copy" text="Duplicate" value="duplicate"></action-item-ui>
30
+ <action-item-ui icon="archive" text="Archive" value="archive"></action-item-ui>
31
+ <action-item-ui icon="trash" text="Delete" value="delete" variant="danger"></action-item-ui>
32
+ </action-list-ui>
33
+ ```
@@ -0,0 +1,28 @@
1
+ # agent-artifact — Examples
2
+
3
+ ## code body
4
+
5
+ ```html
6
+ <agent-artifact-ui title="product-card-v2" kind="A2UI" icon="layout">
7
+ <button-ui slot="primary" text="Open in canvas" icon="arrows-out-simple" variant="outline" size="sm"></button-ui>
8
+ <button-ui slot="secondary" text="Copy" icon="copy" variant="ghost" size="sm"></button-ui>
9
+ </agent-artifact-ui>
10
+ ```
11
+
12
+ ## tones
13
+
14
+ ```html
15
+ <agent-artifact-ui title="validation-failed" kind="TICKET" icon="warning" tone="warning">
16
+ <button-ui slot="secondary" text="Download" icon="download" variant="ghost" size="sm"></button-ui>
17
+ <div style="font-size: var(--a-ui-sm); color: var(--a-fg-muted); line-height: 1.5;">Validation score 62/100 — the output is missing a price badge and has an unlabeled button. Retrying would help.</div>
18
+ </agent-artifact-ui>
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```html
24
+ <agent-artifact-ui title="product-card" kind="A2UI" icon="layout">
25
+ <button-ui slot="primary" text="Open in canvas" icon="arrows-out-simple"></button-ui>
26
+ <button-ui slot="secondary" text="Copy" icon="copy"></button-ui>
27
+ </agent-artifact-ui>
28
+ ```
@@ -0,0 +1,24 @@
1
+ # agent-feedback-bar — Examples
2
+
3
+ ## thumbs only
4
+
5
+ ```html
6
+ <agent-feedback-bar-ui id="demo-basic"></agent-feedback-bar-ui>
7
+ ```
8
+
9
+ ## with save
10
+
11
+ ```html
12
+ <agent-feedback-bar-ui id="demo-save" save-label="Save pattern"></agent-feedback-bar-ui>
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```html
18
+ <agent-feedback-bar-ui save-label="Save pattern"></agent-feedback-bar-ui>
19
+ el.addEventListener('feedback-rate', (e) => persist(e.detail.rating));
20
+ el.addEventListener('feedback-save', async () => {
21
+ const name = await savePattern(...);
22
+ el.setStatus(`Saved as "${name}"`, { lock: 'save' });
23
+ });
24
+ ```
@@ -0,0 +1,13 @@
1
+ # agent-questions — Examples
2
+
3
+ ## single select
4
+
5
+ ```html
6
+ <agent-questions-ui id="demo-single" question="Which direction fits best?" helper="Pick one — we can revisit later."></agent-questions-ui>
7
+ ```
8
+
9
+ ## multi select
10
+
11
+ ```html
12
+ <agent-questions-ui id="demo-multi" multi question="Which features should we include?" helper="Select any that apply." submit-label="Generate"></agent-questions-ui>
13
+ ```