@adia-ai/web-components 0.8.36 → 0.8.38
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.
- package/CHANGELOG.md +29 -0
- package/MIGRATION.md +248 -45
- package/README.md +3 -3
- package/bin/doc.mjs +27 -5
- package/components/card/card.css +1 -1
- package/components/drilldown/drilldown.a2ui.json +242 -0
- package/components/drilldown/drilldown.class.js +542 -0
- package/components/drilldown/drilldown.css +305 -0
- package/components/drilldown/drilldown.d.ts +68 -0
- package/components/drilldown/drilldown.examples.md +20 -0
- package/components/drilldown/drilldown.js +17 -0
- package/components/drilldown/drilldown.yaml +271 -0
- package/components/index.js +1 -0
- package/components/inspector/inspector.class.js +1 -1
- package/components/nav/nav.class.js +11 -8
- package/components/nav-item/nav-item.class.js +9 -6
- package/components/page/page.a2ui.json +13 -1
- package/components/page/page.css +113 -0
- package/components/page/page.yaml +30 -3
- package/components/table-toolbar/table-toolbar.examples.md +3 -3
- package/core/streams-bridge.d.ts +2 -2
- package/core/streams-bridge.js +1 -1
- package/custom-elements.json +183 -26
- package/dist/theme-provider.min.js +1 -1
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +103 -84
- package/dist/web-components.sheet.js +1 -1
- package/package.json +3 -3
- package/patterns/admin-keys-and-export/admin-keys-and-export.examples.html +8 -8
- package/patterns/agent-cost/agent-cost.examples.html +3 -3
- package/patterns/agent-memory/agent-memory.examples.html +4 -4
- package/patterns/agent-prompt-library/agent-prompt-library.examples.html +8 -8
- package/patterns/approvals/approvals.examples.html +2 -2
- package/patterns/bulk-action-toolbar/bulk-action-toolbar.examples.html +1 -1
- package/patterns/changelog-feed/changelog-feed.examples.html +1 -1
- package/patterns/comments-and-collaboration/comments-and-collaboration.examples.html +7 -7
- package/patterns/data-tables-inline-edit-and-tree/data-tables-inline-edit-and-tree.examples.html +4 -4
- package/patterns/diff-review/diff-review.examples.html +6 -6
- package/patterns/filter-bar/filter-bar.examples.html +5 -5
- package/patterns/inline-dialog/inline-dialog.examples.html +1 -1
- package/patterns/kanban-board/kanban-board.examples.html +12 -12
- package/patterns/layout/layout.examples.html +3 -3
- package/patterns/marketing-engagement/marketing-engagement.examples.html +13 -13
- package/patterns/notifications-bell-and-digest/notifications-bell-and-digest.examples.html +1 -1
- package/patterns/permissions-matrix/permissions-matrix.examples.html +1 -1
- package/patterns/permissions-role-picker/permissions-role-picker.examples.html +1 -1
- package/patterns/permissions-sharing/permissions-sharing.examples.html +3 -3
- package/patterns/profile-public-and-verification/profile-public-and-verification.examples.html +2 -2
- package/patterns/search-discovery/search-discovery.examples.html +15 -15
- package/styles/components.css +1 -0
- package/styles/type/scale.css +2 -1
- package/traits/view-transition/view-transition.js +7 -0
|
@@ -91,9 +91,14 @@ export class UINav extends UIElement {
|
|
|
91
91
|
|
|
92
92
|
select(item) {
|
|
93
93
|
const prev = this.selectedItem;
|
|
94
|
-
|
|
94
|
+
// gh#1254: re-selecting the already-selected item is a no-op — no
|
|
95
|
+
// attribute churn, no hover flush, no event. Selection genuinely
|
|
96
|
+
// unchanged is not a selection event.
|
|
97
|
+
if (prev === item) return;
|
|
98
|
+
if (prev) prev.removeAttribute('selected');
|
|
95
99
|
if (item) {
|
|
96
100
|
item.setAttribute('selected', '');
|
|
101
|
+
this.#flushHoverState();
|
|
97
102
|
this.dispatchEvent(new CustomEvent('nav-select', {
|
|
98
103
|
bubbles: true,
|
|
99
104
|
detail: { item, text: item.text, value: item.value },
|
|
@@ -107,13 +112,11 @@ export class UINav extends UIElement {
|
|
|
107
112
|
}
|
|
108
113
|
|
|
109
114
|
#onClick = (e) => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
115
|
+
// gh#1254: <nav-item-ui> owns its own click + keyboard activation
|
|
116
|
+
// (nav-item.class.js #onClick calls parent.select(this) directly) —
|
|
117
|
+
// delegating the same selection here too double-invoked select() per
|
|
118
|
+
// click (the layered handlers the issue reports). Do NOT re-add an
|
|
119
|
+
// item branch here; this listener is for group expand/popover only.
|
|
117
120
|
|
|
118
121
|
// Group expand/popover — primary variant only.
|
|
119
122
|
if (this.variant === 'section') return;
|
|
@@ -18,8 +18,10 @@
|
|
|
18
18
|
*
|
|
19
19
|
* Supports icon, label, optional badge, selected/disabled state, and
|
|
20
20
|
* keyboard activation (Enter/Space). Selection is managed by the parent
|
|
21
|
-
* <nav-ui>; clicking or keyboard-activating an item calls nav.select(this)
|
|
22
|
-
*
|
|
21
|
+
* <nav-ui>; clicking or keyboard-activating an item calls nav.select(this),
|
|
22
|
+
* which dispatches `nav-select` (bubbles from <nav-ui>, detail: { item,
|
|
23
|
+
* text, value }) exactly once when selection actually changes — see
|
|
24
|
+
* nav.class.js#select. This class does not dispatch its own copy (gh#1254).
|
|
23
25
|
*/
|
|
24
26
|
|
|
25
27
|
import { UIElement } from '../../core/element.js';
|
|
@@ -39,12 +41,13 @@ export class UINavItem extends UIElement {
|
|
|
39
41
|
|
|
40
42
|
#onClick = (e) => {
|
|
41
43
|
if (this.disabled) { e.preventDefault(); return; }
|
|
44
|
+
// gh#1254: nav.select() is the single source of `nav-select` — it
|
|
45
|
+
// dispatches (bubbling from <nav-ui>) only when selection actually
|
|
46
|
+
// changes, and is a no-op re-clicking the already-selected item.
|
|
47
|
+
// A second dispatch here duplicated the event on every click and
|
|
48
|
+
// fired again even on a no-op reselect.
|
|
42
49
|
const parent = this.closest('nav-ui');
|
|
43
50
|
parent?.select?.(this);
|
|
44
|
-
this.dispatchEvent(new CustomEvent('nav-select', {
|
|
45
|
-
bubbles: true,
|
|
46
|
-
detail: { item: this, text: this.text, value: this.value },
|
|
47
|
-
}));
|
|
48
51
|
};
|
|
49
52
|
|
|
50
53
|
#onKey = (e) => {
|
|
@@ -85,8 +85,20 @@
|
|
|
85
85
|
"footer"
|
|
86
86
|
],
|
|
87
87
|
"slots": {
|
|
88
|
+
"description": {
|
|
89
|
+
"description": "Secondary metadata — grid row 2 beneath the heading inside the page header. Also accepts bare `<p>` / `<small>` / body-variant `<text-ui>` as direct children without slot=\"description\"."
|
|
90
|
+
},
|
|
88
91
|
"default": {
|
|
89
|
-
"description": "Composes from the slot primitives — `<header-ui>` (page header),\n`<section-ui>` (main content), optional `<footer-ui>`. Native\n`<header>` / `<section>` / `<footer>` also work; the @scope rules\ntarget both via `:where(header, header-ui)
|
|
92
|
+
"description": "Composes from the slot primitives — `<header-ui>` (page header),\n`<section-ui>` (main content), optional `<footer-ui>`. Native\n`<header>` / `<section>` / `<footer>` also work; the @scope rules\ntarget both via `:where(header, header-ui)`. The page header\nalso activates the named slot-gated grid (`slot=\"icon\"` /\n`slot=\"heading\"` / `slot=\"description\"` / `slot=\"action\"`) once\nany DIRECT header child carries a `slot` attribute — same\ncontract as `<card-ui>`'s header (gh#1253).\n"
|
|
93
|
+
},
|
|
94
|
+
"action": {
|
|
95
|
+
"description": "Trailing control cluster inside the page header (icon-buttons, menu trigger, scheme toggle, more-options). Aligns to the flex-end edge — the fix for gh#1253's dropped `<toggle-scheme-ui>`."
|
|
96
|
+
},
|
|
97
|
+
"heading": {
|
|
98
|
+
"description": "Primary title — grid row 1 inside the page header. Also accepts bare `<h1>`–`<h6>` tags (or A2UI's transpiled display/title/heading/subsection `<text-ui>` variants) as direct children without slot=\"heading\". A slot=\"heading\" wrapper can contain inline badges or metadata alongside the title text."
|
|
99
|
+
},
|
|
100
|
+
"icon": {
|
|
101
|
+
"description": "Leading icon for the page header — status, brand, or type marker. Placed in column 1 of the header grid when present; heading + description shift to column 2. Direct child of `<header>` / `<header-ui>` only, per the :has(> [slot=\"icon\"]) gate."
|
|
90
102
|
}
|
|
91
103
|
},
|
|
92
104
|
"states": [
|
package/components/page/page.css
CHANGED
|
@@ -26,6 +26,12 @@
|
|
|
26
26
|
--page-sticky-bg: var(--a-canvas-0);
|
|
27
27
|
--page-sticky-border: 1px solid var(--md-sys-color-neutral-outline-variant);
|
|
28
28
|
--page-sticky-shadow: var(--a-shadow-sm);
|
|
29
|
+
|
|
30
|
+
/* ── Header slot-gated grid (gh#1253) — matches card-ui's header pair ── */
|
|
31
|
+
--page-header-gap: var(--a-space-2);
|
|
32
|
+
--page-heading-fg: var(--a-fg-strong);
|
|
33
|
+
--page-heading-size: var(--a-ui-lg);
|
|
34
|
+
--page-heading-weight: var(--a-weight-semibold);
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
:scope {
|
|
@@ -118,4 +124,111 @@
|
|
|
118
124
|
border-block-end: var(--page-sticky-border);
|
|
119
125
|
box-shadow: var(--page-sticky-shadow);
|
|
120
126
|
}
|
|
127
|
+
|
|
128
|
+
/* ═══════ Header slot-gated grid (gh#1253) ═══════
|
|
129
|
+
card-ui / drawer-ui / modal-ui already wire the slot vocabulary
|
|
130
|
+
(`slot="icon"` / `slot="heading"` / `slot="action"`) into a header grid
|
|
131
|
+
(ADR-0009: "the slot vocabulary unifies ... Card, Drawer, Modal, AND
|
|
132
|
+
app-shell-ui / page-ui"); page-ui never shipped its half — the docs
|
|
133
|
+
(page.examples.html's "Slot vocabulary" section) promised it, but the
|
|
134
|
+
page's own @scope had no rule keying on `[slot]`. Mirrors card.css's
|
|
135
|
+
`& > header` rules verbatim — same guard (`:has(> [slot])` on a DIRECT
|
|
136
|
+
child only, so a nested [slot="icon"] inside e.g. an <avatar-ui> can't
|
|
137
|
+
falsely activate the grid), same column templates, same row
|
|
138
|
+
placement. */
|
|
139
|
+
:scope > :where(header, header-ui):has(> [slot]) {
|
|
140
|
+
display: grid;
|
|
141
|
+
gap: var(--page-header-gap);
|
|
142
|
+
align-items: center;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
:scope > :where(header, header-ui):has(> [slot="icon"]):has(> [slot="action"]) { grid-template-columns: max-content 1fr auto; }
|
|
146
|
+
:scope > :where(header, header-ui):has(> [slot="icon"]):not(:has(> [slot="action"])) { grid-template-columns: max-content 1fr; }
|
|
147
|
+
:scope > :where(header, header-ui):not(:has(> [slot="icon"])):has(> [slot="action"]) { grid-template-columns: 1fr auto; }
|
|
148
|
+
:scope > :where(header, header-ui):not(:has(> [slot="icon"])):not(:has(> [slot="action"])) { grid-template-columns: 1fr; }
|
|
149
|
+
|
|
150
|
+
/* Unslotted children stack above the heading/description/action grid,
|
|
151
|
+
full-width — same escape hatch as card.css (zettel fragment injection,
|
|
152
|
+
logos, banners) without needing to know the slot vocabulary. */
|
|
153
|
+
:scope > :where(header, header-ui):has(> [slot]) > *:not([slot]):not(h1):not(h2):not(h3):not(h4):not(h5):not(h6):not(p):not(small):not(text-ui) {
|
|
154
|
+
grid-column: 1 / -1;
|
|
155
|
+
justify-self: center;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Icon — first column. Spans both rows (anchored to start) once a
|
|
159
|
+
description row exists, matching card.css. */
|
|
160
|
+
:scope > :where(header, header-ui) > [slot="icon"] {
|
|
161
|
+
grid-column: 1;
|
|
162
|
+
grid-row: 1;
|
|
163
|
+
align-self: center;
|
|
164
|
+
display: flex;
|
|
165
|
+
align-items: center;
|
|
166
|
+
justify-content: center;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* :not([slot]) on the bare-tag branches (gh#1253 review) — a native <p>/
|
|
170
|
+
<small>/body-caption text-ui carrying its OWN slot (e.g. slot="heading")
|
|
171
|
+
must not also count as "there's a description row" just because the tag
|
|
172
|
+
matches; only an actual [slot="description"] or an unslotted bare tag
|
|
173
|
+
does. */
|
|
174
|
+
:scope > :where(header, header-ui):has(> :is([slot="description"], p:not([slot]), small:not([slot]), text-ui[variant="body"]:not([slot]), text-ui[variant="caption"]:not([slot]))) > [slot="icon"] {
|
|
175
|
+
grid-row: 1 / span 2;
|
|
176
|
+
align-self: start;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* Heading — row 1. Matches native h1-h6 and the A2UI-transpiled text-ui
|
|
180
|
+
heading variants, only when unslotted (an explicit slot="heading"
|
|
181
|
+
always wins) — same as card.css. */
|
|
182
|
+
:scope > :where(header, header-ui) > :is([slot="heading"], h1, h2, h3, h4, h5, h6),
|
|
183
|
+
:scope > :where(header, header-ui) > :is(text-ui[variant="display"], text-ui[variant="title"], text-ui[variant="heading"], text-ui[variant="subsection"]):not([slot]),
|
|
184
|
+
:scope > :where(header, header-ui) > [slot="heading"] :is(h1, h2, h3, h4, h5, h6) {
|
|
185
|
+
grid-row: 1;
|
|
186
|
+
line-height: 1.3;
|
|
187
|
+
margin: 0;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
:scope > :where(header, header-ui) > [slot="heading"] {
|
|
191
|
+
display: flex;
|
|
192
|
+
align-items: center;
|
|
193
|
+
gap: var(--page-header-gap);
|
|
194
|
+
color: var(--page-heading-fg);
|
|
195
|
+
}
|
|
196
|
+
:scope > :where(header, header-ui) > [slot="heading"]:not(:is(h1, h2, h3, h4, h5, h6, text-ui)) {
|
|
197
|
+
font-size: var(--page-heading-size);
|
|
198
|
+
font-weight: var(--page-heading-weight);
|
|
199
|
+
}
|
|
200
|
+
:scope > :where(header, header-ui):has(> [slot="icon"]) > :is([slot="heading"], h1, h2, h3, h4, h5, h6) { grid-column: 2; }
|
|
201
|
+
:scope > :where(header, header-ui):has(> [slot="icon"]) > :is(text-ui[variant="display"], text-ui[variant="title"], text-ui[variant="heading"], text-ui[variant="subsection"]):not([slot]) { grid-column: 2; }
|
|
202
|
+
:scope > :where(header, header-ui):not(:has(> [slot="icon"])) > :is([slot="heading"], h1, h2, h3, h4, h5, h6) { grid-column: 1; }
|
|
203
|
+
:scope > :where(header, header-ui):not(:has(> [slot="icon"])) > :is(text-ui[variant="display"], text-ui[variant="title"], text-ui[variant="heading"], text-ui[variant="subsection"]):not([slot]) { grid-column: 1; }
|
|
204
|
+
|
|
205
|
+
/* Description — row 2. :not([slot]) so a bare <p>/<small> carrying its
|
|
206
|
+
own slot (e.g. slot="heading") doesn't ALSO match the fallback here —
|
|
207
|
+
equal specificity + later source order would otherwise let this rule
|
|
208
|
+
win and drop it to row 2 (gh#1253 review). */
|
|
209
|
+
:scope > :where(header, header-ui) > :is([slot="description"], p:not([slot]), small:not([slot])),
|
|
210
|
+
:scope > :where(header, header-ui) > :is(text-ui[variant="body"], text-ui[variant="caption"]):not([slot]) {
|
|
211
|
+
grid-row: 2;
|
|
212
|
+
grid-column: 1 / -1;
|
|
213
|
+
line-height: 1.4;
|
|
214
|
+
margin: 0;
|
|
215
|
+
}
|
|
216
|
+
:scope > :where(header, header-ui):has(> [slot="icon"]) > :is([slot="description"], p:not([slot]), small:not([slot])) { grid-column: 2 / -1; }
|
|
217
|
+
:scope > :where(header, header-ui):has(> [slot="icon"]) > :is(text-ui[variant="body"], text-ui[variant="caption"]):not([slot]) { grid-column: 2 / -1; }
|
|
218
|
+
|
|
219
|
+
/* Action — row 1, last column. Flex container so it can hold badge +
|
|
220
|
+
button + anything inline (e.g. <toggle-scheme-ui> — gh#1253's probe).
|
|
221
|
+
Direct-child `>` (gh#1253 review) — a deeply-nested [slot="action"]
|
|
222
|
+
(e.g. inside an unrelated composite) must not pick up header-grid
|
|
223
|
+
flex/alignment styling; only a DIRECT header child activates it. */
|
|
224
|
+
:scope > :where(header, header-ui) > [slot="action"] {
|
|
225
|
+
justify-self: end;
|
|
226
|
+
align-self: center;
|
|
227
|
+
grid-row: 1;
|
|
228
|
+
grid-column: -2 / -1;
|
|
229
|
+
display: flex;
|
|
230
|
+
align-items: center;
|
|
231
|
+
gap: var(--page-header-gap);
|
|
232
|
+
min-width: 0;
|
|
233
|
+
}
|
|
121
234
|
}
|
|
@@ -66,7 +66,34 @@ slots:
|
|
|
66
66
|
Composes from the slot primitives — `<header-ui>` (page header),
|
|
67
67
|
`<section-ui>` (main content), optional `<footer-ui>`. Native
|
|
68
68
|
`<header>` / `<section>` / `<footer>` also work; the @scope rules
|
|
69
|
-
target both via `:where(header, header-ui)`.
|
|
69
|
+
target both via `:where(header, header-ui)`. The page header
|
|
70
|
+
also activates the named slot-gated grid (`slot="icon"` /
|
|
71
|
+
`slot="heading"` / `slot="description"` / `slot="action"`) once
|
|
72
|
+
any DIRECT header child carries a `slot` attribute — same
|
|
73
|
+
contract as `<card-ui>`'s header (gh#1253).
|
|
74
|
+
icon:
|
|
75
|
+
description: >-
|
|
76
|
+
Leading icon for the page header — status, brand, or type marker.
|
|
77
|
+
Placed in column 1 of the header grid when present; heading +
|
|
78
|
+
description shift to column 2. Direct child of `<header>` /
|
|
79
|
+
`<header-ui>` only, per the :has(> [slot="icon"]) gate.
|
|
80
|
+
heading:
|
|
81
|
+
description: >-
|
|
82
|
+
Primary title — grid row 1 inside the page header. Also accepts
|
|
83
|
+
bare `<h1>`–`<h6>` tags (or A2UI's transpiled display/title/heading/subsection
|
|
84
|
+
`<text-ui>` variants) as direct children without slot="heading".
|
|
85
|
+
A slot="heading" wrapper can contain inline badges or metadata
|
|
86
|
+
alongside the title text.
|
|
87
|
+
description:
|
|
88
|
+
description: >-
|
|
89
|
+
Secondary metadata — grid row 2 beneath the heading inside the
|
|
90
|
+
page header. Also accepts bare `<p>` / `<small>` / body-variant
|
|
91
|
+
`<text-ui>` as direct children without slot="description".
|
|
92
|
+
action:
|
|
93
|
+
description: >-
|
|
94
|
+
Trailing control cluster inside the page header (icon-buttons,
|
|
95
|
+
menu trigger, scheme toggle, more-options). Aligns to the
|
|
96
|
+
flex-end edge — the fix for gh#1253's dropped `<toggle-scheme-ui>`.
|
|
70
97
|
states:
|
|
71
98
|
- name: idle
|
|
72
99
|
description: Default, ready for interaction.
|
|
@@ -78,8 +105,8 @@ a2ui:
|
|
|
78
105
|
rules:
|
|
79
106
|
- rule: 'Top-level page container — wraps an entire route''s content surface.'
|
|
80
107
|
reason: 'Page-level chrome primitive.'
|
|
81
|
-
- rule: 'Inside <admin-shell-ui>, <chat-shell-ui>, or <editor-shell-ui>,
|
|
82
|
-
reason: 'Shell hosting precedence.'
|
|
108
|
+
- rule: 'Inside <admin-shell-ui>, <chat-shell-ui>, or <editor-shell-ui>, page-ui still composes — nest it in the shell''s content column with [scroll] omitted (the shell already owns scrolling) to get page-ui''s max-width clamp, padding scale, and region rhythm. Skip page-ui only when the shell''s own header/body slots already give you everything you need.'
|
|
109
|
+
reason: 'Shell hosting precedence — the shell owns scroll; page-ui supplies layout, not a second scroll surface.'
|
|
83
110
|
- rule: 'Hosts arbitrary children — no enforced child contract.'
|
|
84
111
|
reason: 'Generic container.'
|
|
85
112
|
anti_patterns: []
|
|
@@ -32,21 +32,21 @@
|
|
|
32
32
|
<td>Maya Chen</td>
|
|
33
33
|
<td>Designer</td>
|
|
34
34
|
<td>
|
|
35
|
-
<tag-ui
|
|
35
|
+
<tag-ui variant="success">Active</tag-ui>
|
|
36
36
|
</td>
|
|
37
37
|
</tr>
|
|
38
38
|
<tr>
|
|
39
39
|
<td>Alex Park</td>
|
|
40
40
|
<td>Engineer</td>
|
|
41
41
|
<td>
|
|
42
|
-
<tag-ui
|
|
42
|
+
<tag-ui variant="success">Active</tag-ui>
|
|
43
43
|
</td>
|
|
44
44
|
</tr>
|
|
45
45
|
<tr>
|
|
46
46
|
<td>Jordan Lee</td>
|
|
47
47
|
<td>Product</td>
|
|
48
48
|
<td>
|
|
49
|
-
<tag-ui
|
|
49
|
+
<tag-ui variant="warning">Away</tag-ui>
|
|
50
50
|
</td>
|
|
51
51
|
</tr>
|
|
52
52
|
</tbody>
|
package/core/streams-bridge.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* The bridge duck-types the renderer (it needs `.process()`, nothing
|
|
6
6
|
* else), so it works with any A2UI-protocol consumer — the actual
|
|
7
|
-
* `A2UIRenderer` from `@adia-ai/a2ui
|
|
7
|
+
* `A2UIRenderer` from `@adia-ai/a2ui`, a custom renderer, or
|
|
8
8
|
* a test stub.
|
|
9
9
|
*
|
|
10
10
|
* Contract:
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Minimal renderer contract the bridge requires. The actual
|
|
30
|
-
* `A2UIRenderer` from `@adia-ai/a2ui
|
|
30
|
+
* `A2UIRenderer` from `@adia-ai/a2ui` satisfies this surface,
|
|
31
31
|
* as does any custom renderer that handles
|
|
32
32
|
* `{ type: 'updateDataModel', ... }` actions.
|
|
33
33
|
*/
|
package/core/streams-bridge.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* the dependency direction is web-components → a2ui-utils, not the
|
|
13
13
|
* reverse. The bridge duck-types the renderer (it needs `.process()`,
|
|
14
14
|
* nothing else), so it works with any A2UI-protocol consumer — the
|
|
15
|
-
* actual `A2UIRenderer` from `@adia-ai/a2ui
|
|
15
|
+
* actual `A2UIRenderer` from `@adia-ai/a2ui`, a custom renderer,
|
|
16
16
|
* or a test stub.
|
|
17
17
|
*
|
|
18
18
|
* Contract:
|