@adia-ai/web-components 0.5.3 → 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/components/calendar-picker/class.js +1 -0
- 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/feed/feed-item.a2ui.json +86 -0
- package/components/radio/class.js +1 -0
- package/components/select/class.js +1 -0
- package/components/switch/class.js +1 -0
- package/components/textarea/class.js +1 -0
- package/components/upload/class.js +1 -0
- package/core/icons.d.ts +148 -0
- package/package.json +1 -1
|
@@ -53,6 +53,7 @@ function sameDay(a, b) {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
export class UICalendarPicker extends UIFormElement {
|
|
56
|
+
static labelDeprecated = false; // §170 (v0.5.4): label is first-class per calendar-picker.yaml
|
|
56
57
|
// §154 (v0.5.3): Phosphor icons this primitive auto-stamps (without
|
|
57
58
|
// consumer markup). Aggregated by installIconLoadersForRegistered()
|
|
58
59
|
// across all defined elements. Audited by check-required-icons.mjs
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/ChatInput.json",
|
|
4
|
+
"title": "ChatInput",
|
|
5
|
+
"description": "Composable chat input bar — a self-contained chat-message composer\nthat stamps its OWN inner structure (textarea + model picker + send\nbutton) when authored as a bare `<chat-input-ui>` tag.\n\nIMPORTANT (closes the 2026-05-14 redundant-send-button class): the\ncomponent stamps a built-in send button (paper-plane-right icon,\nprimary variant). DO NOT add a separate Button sibling for \"send\" —\nthe user gets two send buttons. The submit event fires on Enter or\nsend-button click; `detail` is `{ text, model }`.\n\nInner stamped structure (default):\n <chat-input-ui>\n <textarea-ui placeholder=\"Type a message...\" rows=\"1\"></textarea-ui>\n <div slot=\"toolbar\">\n <select-ui slot=\"model\" placeholder=\"Model\">...</select-ui>\n <button-ui icon=\"paper-plane-right\" variant=\"primary\" slot=\"send\"></button-ui>\n </div>\n </chat-input-ui>\n\nLayout:\n ┌──────────────────────────────────┐\n │ textarea (grows vertically) │\n ├──────────────────────────────────┤\n │ [model ▾] [⏎ send] │ ← toolbar (model picker + built-in send)\n └──────────────────────────────────┘\n\nComposite wrapper, not a form field itself. The inner textarea-ui\nis form-associated via UIFormElement and submits through the parent\nform. `chat-input-ui`'s `disabled` / `placeholder` props propagate\nto the inner textarea.\n\nFor module-tier composer surfaces (slot vocabulary for file attach,\nautocomplete, trailing/leading controls), wrap inside\n`<chat-composer>` — see ChatComposer for the module-tier shape.\n",
|
|
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": "ChatInput"
|
|
18
|
+
},
|
|
19
|
+
"disabled": {
|
|
20
|
+
"description": "Disable the entire input. Textarea becomes contenteditable=false;\nsend button disabled.\n",
|
|
21
|
+
"type": "boolean",
|
|
22
|
+
"default": false
|
|
23
|
+
},
|
|
24
|
+
"loading": {
|
|
25
|
+
"description": "In-flight / streaming state. Send button disabled, submit events\nsuppressed, but textarea stays editable so the user can draft a\nfollow-up while the model is still responding.\n",
|
|
26
|
+
"type": "boolean",
|
|
27
|
+
"default": false
|
|
28
|
+
},
|
|
29
|
+
"model": {
|
|
30
|
+
"description": "Currently selected model value (reflected, two-way with inner\n`<select-ui slot=\"model\">`). Empty when no model picker is shown.\n",
|
|
31
|
+
"type": "string",
|
|
32
|
+
"default": ""
|
|
33
|
+
},
|
|
34
|
+
"models": {
|
|
35
|
+
"description": "JSON array of model options for the inner model picker —\n[{value, label}] or [{label, options: [...]}] groups. Empty array\nhides the model picker.\n",
|
|
36
|
+
"type": "array",
|
|
37
|
+
"default": []
|
|
38
|
+
},
|
|
39
|
+
"placeholder": {
|
|
40
|
+
"description": "Textarea placeholder. Defaults to \"Type a message...\".",
|
|
41
|
+
"type": "string",
|
|
42
|
+
"default": "Type a message..."
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"required": [
|
|
46
|
+
"component"
|
|
47
|
+
],
|
|
48
|
+
"unevaluatedProperties": false,
|
|
49
|
+
"x-adiaui": {
|
|
50
|
+
"anti_patterns": [
|
|
51
|
+
{
|
|
52
|
+
"description": "Adding a separate Button(primary) sibling next to ChatInput for \"send\". The component stamps its own send button (paper-plane-right icon). Two send buttons render side-by-side, confusing users."
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"description": "Stamping a Select next to ChatInput for model picker. The component has a built-in model picker driven by the `models` prop. Set `models=[{value, label}, ...]` instead of stamping a separate Select."
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"description": "Wrapping ChatInput inside <field-ui label=\"...\"> for label association. ChatInput is a composite container, not a form field. For a labeled composer surface, use <chat-composer> + slot label markup."
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
"category": "agent",
|
|
62
|
+
"composes": [],
|
|
63
|
+
"events": {
|
|
64
|
+
"submit": {
|
|
65
|
+
"description": "Fires when the user presses Enter (without Shift) in the textarea OR clicks the built-in send button. The composer suppresses submission while `[loading]` is set.",
|
|
66
|
+
"detail": {
|
|
67
|
+
"model": {
|
|
68
|
+
"description": "Currently selected model value (empty if no model picker).",
|
|
69
|
+
"type": "string"
|
|
70
|
+
},
|
|
71
|
+
"text": {
|
|
72
|
+
"description": "Submitted message text from the inner textarea.",
|
|
73
|
+
"type": "string"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"examples": [
|
|
79
|
+
{
|
|
80
|
+
"description": "Minimal chat input — placeholder, no model picker. Sits inside a chat shell footer.",
|
|
81
|
+
"a2ui": "[\n {\"id\": \"root\", \"component\": \"ChatInput\", \"placeholder\": \"Ask me anything...\"}\n]",
|
|
82
|
+
"name": "basic-chat-input"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"description": "Chat input with model selection. The `models` prop drives the built-in model picker — DO NOT add a separate Select sibling.",
|
|
86
|
+
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"ChatInput\",\n \"placeholder\": \"Type a message...\",\n \"model\": \"claude-opus-4-7\",\n \"models\": [\n {\"value\": \"claude-opus-4-7\", \"label\": \"Claude Opus 4.7\"},\n {\"value\": \"claude-haiku-4-5\", \"label\": \"Claude Haiku 4.5\"},\n {\"value\": \"claude-sonnet-4-5\", \"label\": \"Claude Sonnet 4.5\"}\n ]\n }\n]",
|
|
87
|
+
"name": "chat-input-with-models"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"description": "Streaming response state. `[loading]` reflects on the host; send button disables; textarea stays editable so the user can draft a follow-up while the LLM is responding.",
|
|
91
|
+
"a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"ChatInput\",\n \"placeholder\": \"Drafting follow-up while streaming...\",\n \"loading\": true\n }\n]",
|
|
92
|
+
"name": "chat-input-loading-state"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"description": "Full chat shell — header + thread + ChatInput in the footer. Note: ChatInput is the sole footer child; no separate send button.",
|
|
96
|
+
"a2ui": "[\n {\"id\": \"root\", \"component\": \"ChatShell\", \"children\": [\"header\", \"thread\", \"input\"]},\n {\"id\": \"header\", \"component\": \"ChatHeader\", \"title\": \"Chat\"},\n {\"id\": \"thread\", \"component\": \"ChatThread\"},\n {\"id\": \"input\", \"component\": \"ChatInput\", \"placeholder\": \"Send a message...\"}\n]",
|
|
97
|
+
"name": "chat-shell-with-chat-input"
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"keywords": [
|
|
101
|
+
"chat-input",
|
|
102
|
+
"chat",
|
|
103
|
+
"message-input",
|
|
104
|
+
"composer",
|
|
105
|
+
"send-message",
|
|
106
|
+
"conversation",
|
|
107
|
+
"prompt",
|
|
108
|
+
"submit"
|
|
109
|
+
],
|
|
110
|
+
"name": "UIChatInput",
|
|
111
|
+
"related": [
|
|
112
|
+
"ChatShell",
|
|
113
|
+
"ChatThread",
|
|
114
|
+
"ChatComposer",
|
|
115
|
+
"ChatHeader",
|
|
116
|
+
"TextArea",
|
|
117
|
+
"Input"
|
|
118
|
+
],
|
|
119
|
+
"slots": {
|
|
120
|
+
"model": {
|
|
121
|
+
"description": "Override slot for the model picker. Most authors should NOT override this — set the `models` prop instead."
|
|
122
|
+
},
|
|
123
|
+
"send": {
|
|
124
|
+
"description": "Override slot for the send button only. The default stamped send button has `[icon=\"paper-plane-right\"] [variant=\"primary\"]`. Most authors should NOT override this — the built-in send button IS the send control. Adding a separate Button sibling for \"send\" duplicates this functionality."
|
|
125
|
+
},
|
|
126
|
+
"toolbar": {
|
|
127
|
+
"description": "Override slot for the entire toolbar row (model picker + send button). Most authors should NOT override this — the built-in toolbar handles model selection + send. Use this only when custom toolbar layout is required."
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"states": [
|
|
131
|
+
{
|
|
132
|
+
"description": "Default, accepting input. Send button enabled when textarea has content.",
|
|
133
|
+
"name": "idle"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"description": "Input fully disabled (typically during initial form setup).",
|
|
137
|
+
"attribute": "disabled",
|
|
138
|
+
"name": "disabled"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"description": "LLM is responding. Send button disabled + submit events suppressed, but textarea stays editable for follow-up drafts.",
|
|
142
|
+
"attribute": "loading",
|
|
143
|
+
"name": "loading"
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
"synonyms": {
|
|
147
|
+
"message-input": [
|
|
148
|
+
"conversation-input",
|
|
149
|
+
"prompt-input",
|
|
150
|
+
"send-bar"
|
|
151
|
+
]
|
|
152
|
+
},
|
|
153
|
+
"tag": "chat-input-ui",
|
|
154
|
+
"tokens": {},
|
|
155
|
+
"traits": [],
|
|
156
|
+
"version": 1
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -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 },
|
|
@@ -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
|
+
}
|
|
@@ -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 },
|
|
@@ -19,6 +19,7 @@ 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
|
|
22
23
|
// §154 (v0.5.3): Phosphor icons this primitive auto-stamps (without
|
|
23
24
|
// consumer markup). Aggregated by installIconLoadersForRegistered()
|
|
24
25
|
// across all defined elements. Audited by check-required-icons.mjs
|
|
@@ -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 },
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
import { UIFormElement } from '../../core/form.js';
|
|
21
21
|
|
|
22
22
|
export class UITextarea extends UIFormElement {
|
|
23
|
+
static labelDeprecated = false; // §170 (v0.5.4): label is first-class per textarea.yaml
|
|
23
24
|
static properties = {
|
|
24
25
|
...UIFormElement.properties,
|
|
25
26
|
placeholder: { type: String, default: '', reflect: true },
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
import { UIFormElement } from '../../core/form.js';
|
|
21
21
|
|
|
22
22
|
export class UIUpload extends UIFormElement {
|
|
23
|
+
static labelDeprecated = false; // §170 (v0.5.4): label is first-class per upload.yaml
|
|
23
24
|
static properties = {
|
|
24
25
|
...UIFormElement.properties,
|
|
25
26
|
label: { type: String, default: '', reflect: true },
|
package/core/icons.d.ts
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon registry — pluggable lookup map for `<icon-ui>` SVG resolution.
|
|
3
|
+
*
|
|
4
|
+
* Three consumer paths, picked by bundle-size budget:
|
|
5
|
+
*
|
|
6
|
+
* 1. **Zero-config** — import the main barrel; phosphor side-effect-loads
|
|
7
|
+
* via `core/icons-phosphor.js`. Largest bundle (~9 000 chunks under
|
|
8
|
+
* `vite build`). Best for prototypes.
|
|
9
|
+
*
|
|
10
|
+
* 2. **Opt-in phosphor with piecemeal component imports** — when you
|
|
11
|
+
* `import '@adia-ai/web-components/components/button'` etc. you skip
|
|
12
|
+
* the barrel's phosphor side-effect. Add it explicitly:
|
|
13
|
+
* import '@adia-ai/web-components/core/icons-phosphor';
|
|
14
|
+
*
|
|
15
|
+
* 3. **Scoped registration (smallest bundle)** — install only the icons
|
|
16
|
+
* you use via `installIconLoaders()` with a brace-list glob, OR
|
|
17
|
+
* `installIconLoadersForRegistered()` to auto-discover from defined
|
|
18
|
+
* primitives' `static requiredIcons`.
|
|
19
|
+
*
|
|
20
|
+
* Runtime exports mirror `core/icons.js`. `installIconLoadersForRegistered`
|
|
21
|
+
* shipped in v0.5.3 §154 (FEEDBACK-06 §4 + FEEDBACK-07 §4). `.d.ts`
|
|
22
|
+
* authored in v0.5.4 to close the missing-type-surface gap that blocked
|
|
23
|
+
* TypeScript consumers from importing the helper.
|
|
24
|
+
*
|
|
25
|
+
* @see ../USAGE.md (consumer guide)
|
|
26
|
+
* @see ./icons-phosphor.js (the zero-config side-effect path)
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Phosphor weight identifiers. `regular` is the default; the other five
|
|
31
|
+
* weights resolve to the corresponding `@phosphor-icons/core/assets/<weight>/`
|
|
32
|
+
* subtree when consumers install loaders for them.
|
|
33
|
+
*/
|
|
34
|
+
export const ICON_WEIGHTS: ReadonlyArray<'regular' | 'thin' | 'light' | 'bold' | 'fill' | 'duotone'>;
|
|
35
|
+
|
|
36
|
+
/** A single phosphor weight identifier. */
|
|
37
|
+
export type IconWeight = 'regular' | 'thin' | 'light' | 'bold' | 'fill' | 'duotone';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Loader value in an icon-loader map. Either the SVG string itself (eager
|
|
41
|
+
* `import.meta.glob({ eager: true })` output) or a thunk that resolves to
|
|
42
|
+
* the SVG string (lazy / dynamic import).
|
|
43
|
+
*/
|
|
44
|
+
export type IconLoader = string | (() => string | Promise<string>);
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Per-path loader map for a single weight. Keys are typically the
|
|
48
|
+
* `/node_modules/@phosphor-icons/core/assets/<weight>/<filename>.svg` paths
|
|
49
|
+
* `import.meta.glob` produces — but any keys work (§140's filename-suffix
|
|
50
|
+
* fallback handles pnpm / yarn-berry / custom-Vite-root prefixes).
|
|
51
|
+
*/
|
|
52
|
+
export type IconLoaderMap = Record<string, IconLoader>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Per-weight loader maps. Pass to `installIconLoaders()` /
|
|
56
|
+
* `installIconLoadersForRegistered()`. Most consumers pass only `regular`;
|
|
57
|
+
* weight-overloaded usage (e.g. `<icon-ui name="star" weight="fill">`)
|
|
58
|
+
* needs the corresponding weight populated.
|
|
59
|
+
*/
|
|
60
|
+
export interface WeightModules {
|
|
61
|
+
regular?: IconLoaderMap;
|
|
62
|
+
thin?: IconLoaderMap;
|
|
63
|
+
light?: IconLoaderMap;
|
|
64
|
+
bold?: IconLoaderMap;
|
|
65
|
+
fill?: IconLoaderMap;
|
|
66
|
+
duotone?: IconLoaderMap;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Register a single icon by name. Bypasses loader-map lookup entirely. */
|
|
70
|
+
export function registerIcon(name: string, svg: string, weight?: IconWeight): void;
|
|
71
|
+
|
|
72
|
+
/** Register multiple icons at a single weight. Bypasses loader-map lookup. */
|
|
73
|
+
export function registerIcons(icons: Record<string, string>, weight?: IconWeight): void;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get icon SVG by name + weight. Returns the cached SVG if present;
|
|
77
|
+
* otherwise triggers an async load (returning `''` immediately) + the
|
|
78
|
+
* registered `<icon-ui>` elements re-render once the load resolves.
|
|
79
|
+
*/
|
|
80
|
+
export function getIcon(name: string, weight?: IconWeight): string;
|
|
81
|
+
|
|
82
|
+
/** Sync check — is `name` cached in the registry at this weight? */
|
|
83
|
+
export function hasIcon(name: string, weight?: IconWeight): boolean;
|
|
84
|
+
|
|
85
|
+
/** List all cached `weight:name` keys in the registry. */
|
|
86
|
+
export function listIcons(): string[];
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Sync check — is `name` (or its `ICON_ALIASES` alias) a known icon at
|
|
90
|
+
* the given weight? Doesn't trigger loading. Used by primitives that
|
|
91
|
+
* accept either an icon name or a text label (`<input-ui prefix>`,
|
|
92
|
+
* `<input-ui suffix>`) to disambiguate.
|
|
93
|
+
*/
|
|
94
|
+
export function isIconName(name: string, weight?: IconWeight): boolean;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Resolves once the icon registry is sync-checkable — i.e., after the
|
|
98
|
+
* first `installIconLoaders()` call. Primitives that branch on
|
|
99
|
+
* `isIconName` at connect time should await this to avoid the static-
|
|
100
|
+
* deploy race (the registry starts empty, fills async via manifest fetch).
|
|
101
|
+
*/
|
|
102
|
+
export const whenIconRegistryReady: Promise<void>;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Install a per-weight loader map. Idempotent — subsequent calls replace
|
|
106
|
+
* the previous map. After install, re-stamps any existing
|
|
107
|
+
* `<icon-ui[name]>` elements so they re-render with the newly-loadable
|
|
108
|
+
* SVGs.
|
|
109
|
+
*
|
|
110
|
+
* @param modules per-weight maps; missing weights stay empty.
|
|
111
|
+
*/
|
|
112
|
+
export function installIconLoaders(modules: WeightModules): void;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Auto-discover the icon set from defined primitives' `static
|
|
116
|
+
* requiredIcons` declarations, then install loaders.
|
|
117
|
+
*
|
|
118
|
+
* Each AdiaUI primitive that auto-stamps icons declares them via:
|
|
119
|
+
*
|
|
120
|
+
* export class UISelect extends UIFormElement {
|
|
121
|
+
* static requiredIcons = ['caret-up-down'];
|
|
122
|
+
* // ...
|
|
123
|
+
* }
|
|
124
|
+
*
|
|
125
|
+
* This helper aggregates the union across all currently-defined
|
|
126
|
+
* primitives (post-side-effect imports) and installs `modules` as the
|
|
127
|
+
* loader source. The returned list is the discovered set — useful for
|
|
128
|
+
* trimming a wide glob to only what's needed.
|
|
129
|
+
*
|
|
130
|
+
* Shipped v0.5.3 §154 (FEEDBACK-06 §4 + FEEDBACK-07 §4).
|
|
131
|
+
*
|
|
132
|
+
* @param modules - per-weight loader maps (typically `import.meta.glob`
|
|
133
|
+
* output for `@phosphor-icons/core/assets/<weight>/*.svg`)
|
|
134
|
+
* @returns the union of `static requiredIcons` across all defined primitives
|
|
135
|
+
*/
|
|
136
|
+
export function installIconLoadersForRegistered(
|
|
137
|
+
modules: IconLoaderMap | WeightModules
|
|
138
|
+
): string[];
|
|
139
|
+
|
|
140
|
+
export namespace installIconLoadersForRegistered {
|
|
141
|
+
/**
|
|
142
|
+
* Same-shape companion to `installIconLoadersForRegistered` but
|
|
143
|
+
* doesn't install. Returns the union of `static requiredIcons` across
|
|
144
|
+
* all currently-defined primitives — useful when you want to build a
|
|
145
|
+
* narrower glob from the discovered list.
|
|
146
|
+
*/
|
|
147
|
+
function discover(): string[];
|
|
148
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adia-ai/web-components",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "AdiaUI web components — vanilla custom elements. A2UI runtime (renderer, registry, streams, wiring) lives in @adia-ai/a2ui-runtime.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./index.d.ts",
|