@adia-ai/web-components 0.5.2 → 0.5.4
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/USAGE.md +42 -0
- package/components/accordion/accordion.a2ui.json +8 -2
- package/components/accordion/accordion.d.ts +7 -2
- package/components/accordion/accordion.yaml +8 -2
- package/components/accordion/class.js +6 -0
- package/components/agent-questions/agent-questions.yaml +2 -0
- package/components/agent-questions/class.js +6 -0
- package/components/agent-reasoning/agent-reasoning.yaml +5 -0
- package/components/agent-reasoning/class.js +6 -0
- package/components/agent-trace/agent-trace.js +6 -0
- package/components/agent-trace/agent-trace.yaml +3 -0
- package/components/calendar-picker/calendar-picker.yaml +4 -0
- package/components/calendar-picker/class.js +7 -0
- package/components/canvas/canvas.a2ui.json +1 -10
- package/components/canvas/canvas.d.ts +0 -6
- package/components/canvas/canvas.yaml +1 -7
- package/components/card/card.a2ui.json +1 -5
- package/components/card/card.d.ts +0 -9
- package/components/card/card.yaml +1 -3
- package/components/chat-thread/chat-input.a2ui.json +158 -0
- package/components/chat-thread/chat-input.yaml +251 -0
- package/components/check/class.js +1 -0
- package/components/color-picker/class.js +6 -0
- package/components/color-picker/color-picker.yaml +2 -0
- package/components/command/class.js +6 -0
- package/components/command/command.yaml +2 -0
- package/components/drawer/class.js +25 -3
- package/components/drawer/drawer.a2ui.json +13 -1
- package/components/drawer/drawer.d.ts +6 -1
- package/components/drawer/drawer.yaml +11 -1
- package/components/feed/feed-item.a2ui.json +86 -0
- package/components/pane/class.js +6 -0
- package/components/pane/pane.yaml +2 -0
- package/components/radio/class.js +1 -0
- package/components/row/row.a2ui.json +1 -5
- package/components/row/row.d.ts +0 -9
- package/components/row/row.yaml +1 -3
- package/components/select/class.js +7 -0
- package/components/select/select.yaml +2 -0
- package/components/slider/class.js +25 -0
- package/components/switch/class.js +1 -0
- package/components/table/class.js +6 -0
- package/components/table/table.a2ui.json +13 -0
- package/components/table/table.d.ts +9 -0
- package/components/table/table.yaml +13 -0
- package/components/tag/class.js +6 -0
- package/components/tag/tag.yaml +2 -0
- package/components/textarea/class.js +1 -0
- package/components/tree/class.js +6 -0
- package/components/tree/tree.yaml +2 -0
- package/components/upload/class.js +1 -0
- package/core/icons.d.ts +148 -0
- package/core/icons.js +148 -5
- package/core/icons.test.js +187 -0
- package/core/template.js +59 -3
- package/package.json +16 -2
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# Edit this file; run `npm run build:components` to regenerate a2ui.json.
|
|
2
|
+
#
|
|
3
|
+
# §172 (v0.5.4): authored to close the chat-input redundant-send-button
|
|
4
|
+
# regression diagnosed 2026-05-14. Pre-§172 the runtime registry declared
|
|
5
|
+
# `ChatInput → chat-input-ui` but the component had no yaml/sidecar/catalog
|
|
6
|
+
# entry — `<chat-input-ui>` lived as a sibling file inside `chat-thread/`
|
|
7
|
+
# rather than its own folder. The build scanner only looked for canonical
|
|
8
|
+
# `<name>/<name>.yaml`, so this component was invisible to the catalog +
|
|
9
|
+
# system prompt + audit pipeline.
|
|
10
|
+
#
|
|
11
|
+
# Result: the LLM saw `ChatInput` in the type registry but had no schema
|
|
12
|
+
# describing what the element stamps. When users asked for "chat interface
|
|
13
|
+
# with chat-input", the LLM defensively added a sibling Button (primary
|
|
14
|
+
# variant) for "send" — duplicating the built-in send button the
|
|
15
|
+
# component already stamps. The user's ticket
|
|
16
|
+
# (20260514045025-chatinput-training-data-unclea) flagged this.
|
|
17
|
+
#
|
|
18
|
+
# The scanner was extended in §172 to pick up sibling yamls in the same
|
|
19
|
+
# component dir. This file now flows through the build to the v0.9 catalog,
|
|
20
|
+
# the LLM system prompt's CORPUS CONTEXT block, and the audit-script family.
|
|
21
|
+
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
22
|
+
name: UIChatInput
|
|
23
|
+
tag: chat-input-ui
|
|
24
|
+
component: ChatInput
|
|
25
|
+
category: agent
|
|
26
|
+
version: 1
|
|
27
|
+
description: |
|
|
28
|
+
Composable chat input bar — a self-contained chat-message composer
|
|
29
|
+
that stamps its OWN inner structure (textarea + model picker + send
|
|
30
|
+
button) when authored as a bare `<chat-input-ui>` tag.
|
|
31
|
+
|
|
32
|
+
IMPORTANT (closes the 2026-05-14 redundant-send-button class): the
|
|
33
|
+
component stamps a built-in send button (paper-plane-right icon,
|
|
34
|
+
primary variant). DO NOT add a separate Button sibling for "send" —
|
|
35
|
+
the user gets two send buttons. The submit event fires on Enter or
|
|
36
|
+
send-button click; `detail` is `{ text, model }`.
|
|
37
|
+
|
|
38
|
+
Inner stamped structure (default):
|
|
39
|
+
<chat-input-ui>
|
|
40
|
+
<textarea-ui placeholder="Type a message..." rows="1"></textarea-ui>
|
|
41
|
+
<div slot="toolbar">
|
|
42
|
+
<select-ui slot="model" placeholder="Model">...</select-ui>
|
|
43
|
+
<button-ui icon="paper-plane-right" variant="primary" slot="send"></button-ui>
|
|
44
|
+
</div>
|
|
45
|
+
</chat-input-ui>
|
|
46
|
+
|
|
47
|
+
Layout:
|
|
48
|
+
┌──────────────────────────────────┐
|
|
49
|
+
│ textarea (grows vertically) │
|
|
50
|
+
├──────────────────────────────────┤
|
|
51
|
+
│ [model ▾] [⏎ send] │ ← toolbar (model picker + built-in send)
|
|
52
|
+
└──────────────────────────────────┘
|
|
53
|
+
|
|
54
|
+
Composite wrapper, not a form field itself. The inner textarea-ui
|
|
55
|
+
is form-associated via UIFormElement and submits through the parent
|
|
56
|
+
form. `chat-input-ui`'s `disabled` / `placeholder` props propagate
|
|
57
|
+
to the inner textarea.
|
|
58
|
+
|
|
59
|
+
For module-tier composer surfaces (slot vocabulary for file attach,
|
|
60
|
+
autocomplete, trailing/leading controls), wrap inside
|
|
61
|
+
`<chat-composer>` — see ChatComposer for the module-tier shape.
|
|
62
|
+
|
|
63
|
+
props:
|
|
64
|
+
disabled:
|
|
65
|
+
description: |
|
|
66
|
+
Disable the entire input. Textarea becomes contenteditable=false;
|
|
67
|
+
send button disabled.
|
|
68
|
+
type: boolean
|
|
69
|
+
default: false
|
|
70
|
+
reflect: true
|
|
71
|
+
loading:
|
|
72
|
+
description: |
|
|
73
|
+
In-flight / streaming state. Send button disabled, submit events
|
|
74
|
+
suppressed, but textarea stays editable so the user can draft a
|
|
75
|
+
follow-up while the model is still responding.
|
|
76
|
+
type: boolean
|
|
77
|
+
default: false
|
|
78
|
+
reflect: true
|
|
79
|
+
placeholder:
|
|
80
|
+
description: Textarea placeholder. Defaults to "Type a message...".
|
|
81
|
+
type: string
|
|
82
|
+
default: "Type a message..."
|
|
83
|
+
reflect: true
|
|
84
|
+
model:
|
|
85
|
+
description: |
|
|
86
|
+
Currently selected model value (reflected, two-way with inner
|
|
87
|
+
`<select-ui slot="model">`). Empty when no model picker is shown.
|
|
88
|
+
type: string
|
|
89
|
+
default: ""
|
|
90
|
+
reflect: true
|
|
91
|
+
models:
|
|
92
|
+
description: |
|
|
93
|
+
JSON array of model options for the inner model picker —
|
|
94
|
+
[{value, label}] or [{label, options: [...]}] groups. Empty array
|
|
95
|
+
hides the model picker.
|
|
96
|
+
type: array
|
|
97
|
+
default: []
|
|
98
|
+
|
|
99
|
+
events:
|
|
100
|
+
submit:
|
|
101
|
+
description: >-
|
|
102
|
+
Fires when the user presses Enter (without Shift) in the textarea
|
|
103
|
+
OR clicks the built-in send button. The composer suppresses
|
|
104
|
+
submission while `[loading]` is set.
|
|
105
|
+
detail:
|
|
106
|
+
text:
|
|
107
|
+
type: string
|
|
108
|
+
description: Submitted message text from the inner textarea.
|
|
109
|
+
model:
|
|
110
|
+
type: string
|
|
111
|
+
description: Currently selected model value (empty if no model picker).
|
|
112
|
+
|
|
113
|
+
slots:
|
|
114
|
+
toolbar:
|
|
115
|
+
description: >-
|
|
116
|
+
Override slot for the entire toolbar row (model picker + send
|
|
117
|
+
button). Most authors should NOT override this — the built-in
|
|
118
|
+
toolbar handles model selection + send. Use this only when
|
|
119
|
+
custom toolbar layout is required.
|
|
120
|
+
send:
|
|
121
|
+
description: >-
|
|
122
|
+
Override slot for the send button only. The default stamped send
|
|
123
|
+
button has `[icon="paper-plane-right"] [variant="primary"]`. Most
|
|
124
|
+
authors should NOT override this — the built-in send button IS
|
|
125
|
+
the send control. Adding a separate Button sibling for "send"
|
|
126
|
+
duplicates this functionality.
|
|
127
|
+
model:
|
|
128
|
+
description: >-
|
|
129
|
+
Override slot for the model picker. Most authors should NOT
|
|
130
|
+
override this — set the `models` prop instead.
|
|
131
|
+
|
|
132
|
+
states:
|
|
133
|
+
- name: idle
|
|
134
|
+
description: Default, accepting input. Send button enabled when textarea has content.
|
|
135
|
+
- name: disabled
|
|
136
|
+
attribute: disabled
|
|
137
|
+
description: Input fully disabled (typically during initial form setup).
|
|
138
|
+
- name: loading
|
|
139
|
+
attribute: loading
|
|
140
|
+
description: >-
|
|
141
|
+
LLM is responding. Send button disabled + submit events suppressed,
|
|
142
|
+
but textarea stays editable for follow-up drafts.
|
|
143
|
+
|
|
144
|
+
traits: []
|
|
145
|
+
|
|
146
|
+
a2ui:
|
|
147
|
+
rules:
|
|
148
|
+
- >-
|
|
149
|
+
ChatInput is a self-contained composer — it stamps its own
|
|
150
|
+
textarea + model picker + send button. DO NOT add a separate
|
|
151
|
+
Button sibling for "send" inside the same parent. The user
|
|
152
|
+
gets two send buttons (one built-in, one redundant).
|
|
153
|
+
- >-
|
|
154
|
+
For chat interfaces emit ChatInput as the sole input
|
|
155
|
+
component inside the chat shell. The submit event fires on
|
|
156
|
+
Enter or send-button click; `detail` is `{ text, model }`.
|
|
157
|
+
- >-
|
|
158
|
+
To customize models, set the `models` prop with an array of
|
|
159
|
+
{value, label} option objects. Do not stamp a separate Select
|
|
160
|
+
next to ChatInput for model selection — the built-in model
|
|
161
|
+
picker handles it.
|
|
162
|
+
|
|
163
|
+
anti_patterns:
|
|
164
|
+
- description: >-
|
|
165
|
+
Adding a separate Button(primary) sibling next to ChatInput for
|
|
166
|
+
"send". The component stamps its own send button (paper-plane-right
|
|
167
|
+
icon). Two send buttons render side-by-side, confusing users.
|
|
168
|
+
- description: >-
|
|
169
|
+
Stamping a Select next to ChatInput for model picker. The component
|
|
170
|
+
has a built-in model picker driven by the `models` prop. Set
|
|
171
|
+
`models=[{value, label}, ...]` instead of stamping a separate Select.
|
|
172
|
+
- description: >-
|
|
173
|
+
Wrapping ChatInput inside <field-ui label="..."> for label
|
|
174
|
+
association. ChatInput is a composite container, not a form
|
|
175
|
+
field. For a labeled composer surface, use <chat-composer> +
|
|
176
|
+
slot label markup.
|
|
177
|
+
|
|
178
|
+
examples:
|
|
179
|
+
- name: basic-chat-input
|
|
180
|
+
description: >-
|
|
181
|
+
Minimal chat input — placeholder, no model picker. Sits inside
|
|
182
|
+
a chat shell footer.
|
|
183
|
+
a2ui: |-
|
|
184
|
+
[
|
|
185
|
+
{"id": "root", "component": "ChatInput", "placeholder": "Ask me anything..."}
|
|
186
|
+
]
|
|
187
|
+
- name: chat-input-with-models
|
|
188
|
+
description: >-
|
|
189
|
+
Chat input with model selection. The `models` prop drives the
|
|
190
|
+
built-in model picker — DO NOT add a separate Select sibling.
|
|
191
|
+
a2ui: |-
|
|
192
|
+
[
|
|
193
|
+
{
|
|
194
|
+
"id": "root",
|
|
195
|
+
"component": "ChatInput",
|
|
196
|
+
"placeholder": "Type a message...",
|
|
197
|
+
"model": "claude-opus-4-7",
|
|
198
|
+
"models": [
|
|
199
|
+
{"value": "claude-opus-4-7", "label": "Claude Opus 4.7"},
|
|
200
|
+
{"value": "claude-haiku-4-5", "label": "Claude Haiku 4.5"},
|
|
201
|
+
{"value": "claude-sonnet-4-5", "label": "Claude Sonnet 4.5"}
|
|
202
|
+
]
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
- name: chat-input-loading-state
|
|
206
|
+
description: >-
|
|
207
|
+
Streaming response state. `[loading]` reflects on the host;
|
|
208
|
+
send button disables; textarea stays editable so the user can
|
|
209
|
+
draft a follow-up while the LLM is responding.
|
|
210
|
+
a2ui: |-
|
|
211
|
+
[
|
|
212
|
+
{
|
|
213
|
+
"id": "root",
|
|
214
|
+
"component": "ChatInput",
|
|
215
|
+
"placeholder": "Drafting follow-up while streaming...",
|
|
216
|
+
"loading": true
|
|
217
|
+
}
|
|
218
|
+
]
|
|
219
|
+
- name: chat-shell-with-chat-input
|
|
220
|
+
description: >-
|
|
221
|
+
Full chat shell — header + thread + ChatInput in the footer.
|
|
222
|
+
Note: ChatInput is the sole footer child; no separate send
|
|
223
|
+
button.
|
|
224
|
+
a2ui: |-
|
|
225
|
+
[
|
|
226
|
+
{"id": "root", "component": "ChatShell", "children": ["header", "thread", "input"]},
|
|
227
|
+
{"id": "header", "component": "ChatHeader", "title": "Chat"},
|
|
228
|
+
{"id": "thread", "component": "ChatThread"},
|
|
229
|
+
{"id": "input", "component": "ChatInput", "placeholder": "Send a message..."}
|
|
230
|
+
]
|
|
231
|
+
|
|
232
|
+
keywords:
|
|
233
|
+
- chat-input
|
|
234
|
+
- chat
|
|
235
|
+
- message-input
|
|
236
|
+
- composer
|
|
237
|
+
- send-message
|
|
238
|
+
- conversation
|
|
239
|
+
- prompt
|
|
240
|
+
- submit
|
|
241
|
+
|
|
242
|
+
synonyms:
|
|
243
|
+
message-input: [conversation-input, prompt-input, send-bar]
|
|
244
|
+
|
|
245
|
+
related:
|
|
246
|
+
- ChatShell
|
|
247
|
+
- ChatThread
|
|
248
|
+
- ChatComposer
|
|
249
|
+
- ChatHeader
|
|
250
|
+
- TextArea
|
|
251
|
+
- Input
|
|
@@ -20,6 +20,7 @@ import { UIFormElement } from '../../core/form.js';
|
|
|
20
20
|
import { html } from '../../core/element.js';
|
|
21
21
|
|
|
22
22
|
export class UICheck extends UIFormElement {
|
|
23
|
+
static labelDeprecated = false; // §170 (v0.5.4): label is first-class per check.yaml
|
|
23
24
|
static properties = {
|
|
24
25
|
...UIFormElement.properties,
|
|
25
26
|
checked: { type: Boolean, default: false, reflect: true },
|
|
@@ -123,6 +123,12 @@ function gamutMapChroma(L, C, H) {
|
|
|
123
123
|
// ── Component ────────────────────────────────────────────
|
|
124
124
|
|
|
125
125
|
export class UIColorPicker extends UIFormElement {
|
|
126
|
+
// §154 (v0.5.3): Phosphor icons this primitive auto-stamps (without
|
|
127
|
+
// consumer markup). Aggregated by installIconLoadersForRegistered()
|
|
128
|
+
// across all defined elements. Audited by check-required-icons.mjs
|
|
129
|
+
// (slot 11). Per FEEDBACK-06 §4 + FEEDBACK-07 §4.
|
|
130
|
+
static requiredIcons = ['copy'];
|
|
131
|
+
|
|
126
132
|
static properties = {
|
|
127
133
|
...UIFormElement.properties,
|
|
128
134
|
value: { type: String, default: '#3b82f6', reflect: true },
|
|
@@ -34,6 +34,12 @@ import { UIElement } from '../../core/element.js';
|
|
|
34
34
|
* dismiss — Escape pressed
|
|
35
35
|
*/
|
|
36
36
|
export class UICommand extends UIElement {
|
|
37
|
+
// §154 (v0.5.3): Phosphor icons this primitive auto-stamps (without
|
|
38
|
+
// consumer markup). Aggregated by installIconLoadersForRegistered()
|
|
39
|
+
// across all defined elements. Audited by check-required-icons.mjs
|
|
40
|
+
// (slot 11). Per FEEDBACK-06 §4 + FEEDBACK-07 §4.
|
|
41
|
+
static requiredIcons = ['magnifying-glass'];
|
|
42
|
+
|
|
37
43
|
static properties = {
|
|
38
44
|
placeholder: { type: String, default: 'Type a command...', reflect: true },
|
|
39
45
|
open: { type: Boolean, default: false, reflect: true },
|
|
@@ -50,6 +50,13 @@ export class UIDrawer extends UIElement {
|
|
|
50
50
|
#previousFocus = null;
|
|
51
51
|
#closeTimer = null;
|
|
52
52
|
#dialogRef = null;
|
|
53
|
+
// §156 (v0.5.3): track the reason the drawer closed so the dispatched
|
|
54
|
+
// `close` CustomEvent carries `detail.reason`. Set at each entry point
|
|
55
|
+
// (escape → 'escape', backdrop → 'backdrop', close-button → 'close-button',
|
|
56
|
+
// any other path defaults to 'programmatic'). Reset to 'programmatic'
|
|
57
|
+
// after dispatch so a subsequent .open=false from consumer code
|
|
58
|
+
// doesn't carry a stale reason. Per FEEDBACK-06 §2.
|
|
59
|
+
#closeReason = 'programmatic';
|
|
53
60
|
|
|
54
61
|
static properties = {
|
|
55
62
|
text: { type: String, default: '', reflect: true },
|
|
@@ -95,11 +102,15 @@ export class UIDrawer extends UIElement {
|
|
|
95
102
|
}
|
|
96
103
|
|
|
97
104
|
#onPress = (e) => {
|
|
98
|
-
if (e.target.closest('[slot="close"]'))
|
|
105
|
+
if (e.target.closest('[slot="close"]')) {
|
|
106
|
+
this.#closeReason = 'close-button';
|
|
107
|
+
this.open = false;
|
|
108
|
+
}
|
|
99
109
|
};
|
|
100
110
|
|
|
101
111
|
#onDialogCancel = (e) => {
|
|
102
112
|
e.preventDefault();
|
|
113
|
+
this.#closeReason = 'escape';
|
|
103
114
|
if (!this.permanent) this.open = false;
|
|
104
115
|
};
|
|
105
116
|
|
|
@@ -107,11 +118,22 @@ export class UIDrawer extends UIElement {
|
|
|
107
118
|
this.open = false;
|
|
108
119
|
this.#previousFocus?.focus();
|
|
109
120
|
this.#previousFocus = null;
|
|
110
|
-
|
|
121
|
+
// §156 (v0.5.3): emit a CustomEvent with typed detail.reason. Capture
|
|
122
|
+
// and reset #closeReason so a subsequent programmatic close doesn't
|
|
123
|
+
// inherit the prior reason. Per FEEDBACK-06 §2.
|
|
124
|
+
const reason = this.#closeReason;
|
|
125
|
+
this.#closeReason = 'programmatic';
|
|
126
|
+
this.dispatchEvent(new CustomEvent('close', {
|
|
127
|
+
detail: { reason },
|
|
128
|
+
bubbles: true,
|
|
129
|
+
}));
|
|
111
130
|
};
|
|
112
131
|
|
|
113
132
|
#onDialogClick = (e) => {
|
|
114
|
-
if (e.target === this.#dialogRef && !this.permanent)
|
|
133
|
+
if (e.target === this.#dialogRef && !this.permanent) {
|
|
134
|
+
this.#closeReason = 'backdrop';
|
|
135
|
+
this.open = false;
|
|
136
|
+
}
|
|
115
137
|
};
|
|
116
138
|
|
|
117
139
|
connected() {
|
|
@@ -63,7 +63,19 @@
|
|
|
63
63
|
"composes": [],
|
|
64
64
|
"events": {
|
|
65
65
|
"close": {
|
|
66
|
-
"description": "Fired when the drawer
|
|
66
|
+
"description": "Fired when the drawer closes via any path (close button, backdrop, Escape key, or programmatic `.open = false`). The `detail.reason` field distinguishes which.",
|
|
67
|
+
"detail": {
|
|
68
|
+
"reason": {
|
|
69
|
+
"description": "`'escape'` (Escape key) / `'backdrop'` (backdrop click) / `'close-button'` ([slot=\"close\"] button click) / `'programmatic'` (consumer set `.open = false` from JS). Defaults to `'programmatic'` when no event-driven path captured a reason. Added v0.5.3 §156 per FEEDBACK-06 §2.",
|
|
70
|
+
"type": "string",
|
|
71
|
+
"enum": [
|
|
72
|
+
"escape",
|
|
73
|
+
"backdrop",
|
|
74
|
+
"close-button",
|
|
75
|
+
"programmatic"
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
67
79
|
}
|
|
68
80
|
},
|
|
69
81
|
"examples": [
|
|
@@ -12,7 +12,12 @@
|
|
|
12
12
|
|
|
13
13
|
import { UIElement } from '../../core/element.js';
|
|
14
14
|
|
|
15
|
-
export
|
|
15
|
+
export interface DrawerCloseEventDetail {
|
|
16
|
+
/** `'escape'` (Escape key) / `'backdrop'` (backdrop click) / `'close-button'` ([slot="close"] button click) / `'programmatic'` (consumer set `.open = false` from JS). Defaults to `'programmatic'` when no event-driven path captured a reason. Added v0.5.3 §156 per FEEDBACK-06 §2. */
|
|
17
|
+
reason: 'escape' | 'backdrop' | 'close-button' | 'programmatic';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type DrawerCloseEvent = CustomEvent<DrawerCloseEventDetail>;
|
|
16
21
|
|
|
17
22
|
export class UIDrawer extends UIElement {
|
|
18
23
|
/** Controls visibility. When false, backdrop and panel are removed from DOM. */
|
|
@@ -49,7 +49,17 @@ props:
|
|
|
49
49
|
default: ""
|
|
50
50
|
events:
|
|
51
51
|
close:
|
|
52
|
-
description: Fired when the drawer
|
|
52
|
+
description: Fired when the drawer closes via any path (close button, backdrop, Escape key, or programmatic `.open = false`). The `detail.reason` field distinguishes which.
|
|
53
|
+
detail:
|
|
54
|
+
reason:
|
|
55
|
+
type: string
|
|
56
|
+
enum: [escape, backdrop, close-button, programmatic]
|
|
57
|
+
description: >-
|
|
58
|
+
`'escape'` (Escape key) / `'backdrop'` (backdrop click) /
|
|
59
|
+
`'close-button'` ([slot="close"] button click) /
|
|
60
|
+
`'programmatic'` (consumer set `.open = false` from JS).
|
|
61
|
+
Defaults to `'programmatic'` when no event-driven path
|
|
62
|
+
captured a reason. Added v0.5.3 §156 per FEEDBACK-06 §2.
|
|
53
63
|
slots:
|
|
54
64
|
backdrop:
|
|
55
65
|
description: Scrim overlay behind the drawer (stamped by the component).
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/FeedItem.json",
|
|
4
|
+
"title": "FeedItem",
|
|
5
|
+
"description": "Atomic feed entry inside a `<feed-ui>` lane. Three dismiss policies are inferred from the prop shape — auto-fade (duration > 0 + no action), sticky-dismissible (duration null/0), action-required (duration null/0 + action; future phase). Posted via `UIFeed.post()` rather than authored directly.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"component": {
|
|
17
|
+
"const": "FeedItem"
|
|
18
|
+
},
|
|
19
|
+
"dismissible": {
|
|
20
|
+
"description": "Render an x close button (default true for sticky, false for auto-fade)",
|
|
21
|
+
"type": "boolean",
|
|
22
|
+
"default": false
|
|
23
|
+
},
|
|
24
|
+
"duration": {
|
|
25
|
+
"description": "Auto-fade timer in ms; null/0 = sticky (requires user input)",
|
|
26
|
+
"type": "number",
|
|
27
|
+
"default": 4000
|
|
28
|
+
},
|
|
29
|
+
"heading": {
|
|
30
|
+
"description": "Optional emphasis line above text",
|
|
31
|
+
"type": "string",
|
|
32
|
+
"default": ""
|
|
33
|
+
},
|
|
34
|
+
"icon": {
|
|
35
|
+
"description": "Optional leading icon name",
|
|
36
|
+
"type": "string",
|
|
37
|
+
"default": ""
|
|
38
|
+
},
|
|
39
|
+
"text": {
|
|
40
|
+
"description": "Body copy",
|
|
41
|
+
"type": "string",
|
|
42
|
+
"default": ""
|
|
43
|
+
},
|
|
44
|
+
"variant": {
|
|
45
|
+
"description": "Semantic variant",
|
|
46
|
+
"type": "string",
|
|
47
|
+
"enum": [
|
|
48
|
+
"default",
|
|
49
|
+
"info",
|
|
50
|
+
"success",
|
|
51
|
+
"warning",
|
|
52
|
+
"danger"
|
|
53
|
+
],
|
|
54
|
+
"default": "default"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"required": [
|
|
58
|
+
"component"
|
|
59
|
+
],
|
|
60
|
+
"unevaluatedProperties": false,
|
|
61
|
+
"x-adiaui": {
|
|
62
|
+
"anti_patterns": [],
|
|
63
|
+
"category": "feedback",
|
|
64
|
+
"composes": [],
|
|
65
|
+
"events": {
|
|
66
|
+
"close": {
|
|
67
|
+
"description": "Fired after the item finishes its exit animation"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"examples": [],
|
|
71
|
+
"keywords": [],
|
|
72
|
+
"name": "UIFeedItem",
|
|
73
|
+
"related": [],
|
|
74
|
+
"slots": {
|
|
75
|
+
"body": {
|
|
76
|
+
"description": "Default content slot (also accepts the `text` / `heading` props)"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"states": {},
|
|
80
|
+
"synonyms": {},
|
|
81
|
+
"tag": "feed-item-ui",
|
|
82
|
+
"tokens": {},
|
|
83
|
+
"traits": [],
|
|
84
|
+
"version": 1
|
|
85
|
+
}
|
|
86
|
+
}
|
package/components/pane/class.js
CHANGED
|
@@ -47,6 +47,12 @@
|
|
|
47
47
|
import { UIElement } from '../../core/element.js';
|
|
48
48
|
|
|
49
49
|
export class UIPane extends UIElement {
|
|
50
|
+
// §154 (v0.5.3): Phosphor icons this primitive auto-stamps (without
|
|
51
|
+
// consumer markup). Aggregated by installIconLoadersForRegistered()
|
|
52
|
+
// across all defined elements. Audited by check-required-icons.mjs
|
|
53
|
+
// (slot 11). Per FEEDBACK-06 §4 + FEEDBACK-07 §4.
|
|
54
|
+
static requiredIcons = ['caret-right'];
|
|
55
|
+
|
|
50
56
|
static properties = {
|
|
51
57
|
collapsed: { type: Boolean, default: false, reflect: true },
|
|
52
58
|
resizable: { type: Boolean, default: false, reflect: true },
|
|
@@ -20,6 +20,7 @@ import { UIFormElement } from '../../core/form.js';
|
|
|
20
20
|
import { html } from '../../core/element.js';
|
|
21
21
|
|
|
22
22
|
export class UIRadio extends UIFormElement {
|
|
23
|
+
static labelDeprecated = false; // §170 (v0.5.4): label is first-class per radio.yaml
|
|
23
24
|
static properties = {
|
|
24
25
|
...UIFormElement.properties,
|
|
25
26
|
checked: { type: Boolean, default: false, reflect: true },
|
|
@@ -55,11 +55,7 @@
|
|
|
55
55
|
"anti_patterns": [],
|
|
56
56
|
"category": "layout",
|
|
57
57
|
"composes": [],
|
|
58
|
-
"events": {
|
|
59
|
-
"drag-end": {
|
|
60
|
-
"description": "Fired when a drag completes."
|
|
61
|
-
}
|
|
62
|
-
},
|
|
58
|
+
"events": {},
|
|
63
59
|
"examples": [
|
|
64
60
|
{
|
|
65
61
|
"description": "Chat interface with message bubbles containing avatar and text pairs, plus an input footer.",
|
package/components/row/row.d.ts
CHANGED
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
|
|
13
13
|
import { UIElement } from '../../core/element.js';
|
|
14
14
|
|
|
15
|
-
export type RowDragEndEvent = CustomEvent<unknown>;
|
|
16
|
-
|
|
17
15
|
export class UIRow extends UIElement {
|
|
18
16
|
/** Align items */
|
|
19
17
|
align: string;
|
|
@@ -27,11 +25,4 @@ export class UIRow extends UIElement {
|
|
|
27
25
|
justify: string;
|
|
28
26
|
/** Enable flex wrap */
|
|
29
27
|
wrap: boolean;
|
|
30
|
-
|
|
31
|
-
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
32
|
-
type: K,
|
|
33
|
-
listener: (this: UIRow, ev: HTMLElementEventMap[K]) => unknown,
|
|
34
|
-
options?: boolean | AddEventListenerOptions,
|
|
35
|
-
): void;
|
|
36
|
-
addEventListener(type: 'drag-end', listener: (ev: RowDragEndEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
37
28
|
}
|
package/components/row/row.yaml
CHANGED
|
@@ -19,6 +19,13 @@ function escapeHTML(s) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export class UISelect extends UIFormElement {
|
|
22
|
+
static labelDeprecated = false; // §170 (v0.5.4): label is first-class per select.yaml
|
|
23
|
+
// §154 (v0.5.3): Phosphor icons this primitive auto-stamps (without
|
|
24
|
+
// consumer markup). Aggregated by installIconLoadersForRegistered()
|
|
25
|
+
// across all defined elements. Audited by check-required-icons.mjs
|
|
26
|
+
// (slot 11). Per FEEDBACK-06 §4 + FEEDBACK-07 §4.
|
|
27
|
+
static requiredIcons = ['caret-up-down'];
|
|
28
|
+
|
|
22
29
|
static properties = {
|
|
23
30
|
...UIFormElement.properties,
|
|
24
31
|
placeholder: { type: String, default: 'Select...', reflect: true },
|
|
@@ -95,6 +95,31 @@ export class UISlider extends UIFormElement {
|
|
|
95
95
|
render() {
|
|
96
96
|
if (!this.#trackEl) return;
|
|
97
97
|
|
|
98
|
+
// §153 (v0.5.3): function-typed `.value` runtime guard. Per FEEDBACK-07
|
|
99
|
+
// §3, consumers sometimes pass `() => signal.value * 100` expecting
|
|
100
|
+
// auto-subscribe; AdiaUI's reactive system (template.js `isFn` branch)
|
|
101
|
+
// does wrap functions in effects + call them per dep change, but the
|
|
102
|
+
// result of `v()` must be a number for `#pct` / `#format` to work.
|
|
103
|
+
// When the function returns non-number (e.g. doesn't read a signal,
|
|
104
|
+
// returns object/string) OR when consumers bypass the template engine
|
|
105
|
+
// (manual `sliderEl.value = someFunction`), `this.value` ends up as
|
|
106
|
+
// the function itself — `#pct` does NaN math, thumb stays at 0%,
|
|
107
|
+
// silent fail. Warn loudly + skip render so the bug class is
|
|
108
|
+
// diagnosable in dev. See USAGE.md "Reactive binding" for the
|
|
109
|
+
// documented patterns.
|
|
110
|
+
if (typeof this.value === 'function') {
|
|
111
|
+
// eslint-disable-next-line no-console
|
|
112
|
+
console.warn(
|
|
113
|
+
'[slider-ui] .value received a function. Did you mean:\n' +
|
|
114
|
+
' .value=${fn()} ← call the function to get the current value\n' +
|
|
115
|
+
' .value=${signal.value} ← read the signal\'s current value\n' +
|
|
116
|
+
'Functions are not auto-invoked at render time; the slider reads\n' +
|
|
117
|
+
'.value synchronously. See USAGE.md "Reactive binding" for the\n' +
|
|
118
|
+
'parent-template-re-read pattern that works across frameworks.'
|
|
119
|
+
);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
98
123
|
const pct = this.#pct;
|
|
99
124
|
const fill = this.querySelector('[slot="fill"]');
|
|
100
125
|
if (fill) fill.style.width = `${pct}%`;
|
|
@@ -20,6 +20,7 @@ import { UIFormElement } from '../../core/form.js';
|
|
|
20
20
|
import { html } from '../../core/element.js';
|
|
21
21
|
|
|
22
22
|
export class UISwitch extends UIFormElement {
|
|
23
|
+
static labelDeprecated = false; // §170 (v0.5.4): label is first-class per switch.yaml
|
|
23
24
|
static properties = {
|
|
24
25
|
...UIFormElement.properties,
|
|
25
26
|
checked: { type: Boolean, default: false, reflect: true },
|
|
@@ -91,6 +91,12 @@ function csvEscape(val) {
|
|
|
91
91
|
// ── Component ────────────────────────────────────────────────────────────────
|
|
92
92
|
|
|
93
93
|
export class UITable extends UIElement {
|
|
94
|
+
// §154 (v0.5.3): Phosphor icons this primitive auto-stamps (without
|
|
95
|
+
// consumer markup). Aggregated by installIconLoadersForRegistered()
|
|
96
|
+
// across all defined elements. Audited by check-required-icons.mjs
|
|
97
|
+
// (slot 11). Per FEEDBACK-06 §4 + FEEDBACK-07 §4.
|
|
98
|
+
static requiredIcons = ['caret-right', 'caret-up-down', 'table'];
|
|
99
|
+
|
|
94
100
|
static properties = {
|
|
95
101
|
sortable: { type: Boolean, default: false, reflect: true },
|
|
96
102
|
selectable: { type: Boolean, default: false, reflect: true },
|