@adia-ai/web-components 0.8.3 → 0.8.5
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 +33 -0
- package/USAGE.md +60 -25
- package/components/accordion/accordion.css +5 -0
- package/components/adia-mark/adia-mark.a2ui.json +123 -0
- package/components/adia-mark/adia-mark.class.js +64 -0
- package/components/adia-mark/adia-mark.css +48 -0
- package/components/adia-mark/adia-mark.d.ts +20 -0
- package/components/adia-mark/adia-mark.examples.md +26 -0
- package/components/adia-mark/adia-mark.js +17 -0
- package/components/adia-mark/adia-mark.test.js +69 -0
- package/components/adia-mark/adia-mark.yaml +121 -0
- package/components/agent-artifact/agent-artifact.css +1 -0
- package/components/agent-questions/agent-questions.a2ui.json +2 -1
- package/components/agent-questions/agent-questions.class.js +96 -53
- package/components/agent-questions/agent-questions.css +27 -106
- package/components/agent-questions/agent-questions.yaml +1 -0
- package/components/agent-reasoning/agent-reasoning.css +9 -5
- package/components/button/button.class.js +9 -2
- package/components/button/button.css +1 -1
- package/components/calendar-grid/calendar-grid.a2ui.json +3 -1
- package/components/calendar-grid/calendar-grid.class.js +11 -6
- package/components/calendar-grid/calendar-grid.css +42 -20
- package/components/calendar-grid/calendar-grid.yaml +5 -0
- package/components/calendar-picker/calendar-picker.a2ui.json +3 -1
- package/components/calendar-picker/calendar-picker.class.js +11 -6
- package/components/calendar-picker/calendar-picker.css +41 -19
- package/components/calendar-picker/calendar-picker.yaml +5 -0
- package/components/chart/chart.class.js +17 -14
- package/components/chat-thread/chat-input.a2ui.json +3 -1
- package/components/chat-thread/chat-input.css +12 -13
- package/components/chat-thread/chat-input.js +6 -2
- package/components/chat-thread/chat-input.yaml +3 -0
- package/components/check/check.css +1 -1
- package/components/color-input/color-input.class.js +8 -5
- package/components/color-picker/color-picker.class.js +6 -3
- package/components/combobox/combobox.a2ui.json +3 -1
- package/components/combobox/combobox.class.js +1 -3
- package/components/combobox/combobox.css +9 -12
- package/components/combobox/combobox.yaml +2 -0
- package/components/date-range-picker/date-range-picker.css +1 -0
- package/components/field/field.class.js +10 -7
- package/components/fields/fields.class.js +15 -12
- package/components/icon/icon.class.js +9 -5
- package/components/index.js +1 -0
- package/components/input/input.css +6 -2
- package/components/nav/nav.class.js +2 -1
- package/components/nav-group/nav-group.css +5 -6
- package/components/noodles/noodles.class.js +14 -10
- package/components/option-card/option-card.css +1 -0
- package/components/page/page.class.js +3 -2
- package/components/radio/radio.css +1 -1
- package/components/range/range.css +2 -0
- package/components/select/select.a2ui.json +2 -1
- package/components/select/select.class.js +12 -11
- package/components/select/select.css +29 -40
- package/components/select/select.test.js +6 -2
- package/components/select/select.yaml +1 -0
- package/components/swatch/swatch.a2ui.json +3 -1
- package/components/swatch/swatch.class.js +41 -32
- package/components/swatch/swatch.css +13 -18
- package/components/swatch/swatch.yaml +2 -0
- package/components/swiper/swiper.class.js +4 -1
- package/components/swiper/swiper.css +13 -4
- package/components/switch/switch.css +1 -1
- package/components/tag/tag.a2ui.json +4 -1
- package/components/tag/tag.class.js +3 -1
- package/components/tag/tag.css +13 -15
- package/components/tag/tag.yaml +3 -0
- package/components/tags-input/tags-input.css +1 -0
- package/components/textarea/textarea.css +2 -0
- package/components/time-picker/time-picker.css +2 -0
- package/components/timeline/timeline.a2ui.json +2 -1
- package/components/timeline/timeline.class.js +7 -8
- package/components/timeline/timeline.css +14 -26
- package/components/timeline/timeline.yaml +1 -0
- package/components/toggle-group/toggle-group.css +1 -0
- package/components/toolbar/toolbar.class.js +11 -6
- package/components/tree/tree.class.js +5 -2
- package/components/tree/tree.css +5 -2
- package/components/upload/upload.css +1 -0
- package/core/data-stream.js +21 -15
- package/core/element.js +36 -1
- package/core/element.test.js +67 -0
- package/core/icons-phosphor.js +86 -22
- package/core/icons.js +22 -8
- package/dist/theme-provider.min.js +2 -2
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +109 -108
- package/dist/web-components.sheet.js +1 -1
- package/package.json +1 -5
- package/styles/colors/semantics/features.css +6 -1
- package/styles/components.css +1 -0
- package/traits/error-shake/error-shake.js +23 -17
- package/traits/fade-presence/fade-presence.js +19 -15
- package/traits/success-checkmark/success-checkmark.js +21 -16
|
@@ -115,14 +115,23 @@
|
|
|
115
115
|
color: var(--calendar-grid-title-fg);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
/* Stamped <button-ui variant="ghost" size="xs" icon="caret-…"> (gh issue
|
|
119
|
+
276 wave 4) — icon-only (no [text], no child text) so button-ui's own
|
|
120
|
+
[data-icon-only] rule already squares it to --button-height; pointing
|
|
121
|
+
--button-height at the nav size (not just literal width/height) avoids
|
|
122
|
+
the min-width/min-height floor trap. Literal background/color below
|
|
123
|
+
out-specify button.css's own (via the `button-ui` type-selector bump —
|
|
124
|
+
same technique as swiper's dots), so the button-ui type-selector prefix
|
|
125
|
+
is load-bearing, not decorative. */
|
|
126
|
+
button-ui[data-cal-prev],
|
|
127
|
+
button-ui[data-cal-next] {
|
|
128
|
+
--button-height: var(--calendar-grid-nav-size);
|
|
129
|
+
--a-icon-size: var(--calendar-grid-nav-icon-size);
|
|
130
|
+
|
|
120
131
|
display: inline-flex;
|
|
121
132
|
align-items: center;
|
|
122
133
|
justify-content: center;
|
|
123
|
-
width: var(--calendar-grid-nav-size);
|
|
124
134
|
height: var(--calendar-grid-nav-size);
|
|
125
|
-
padding: 0;
|
|
126
135
|
border: none;
|
|
127
136
|
border-radius: var(--calendar-grid-nav-radius);
|
|
128
137
|
background: var(--calendar-grid-nav-bg);
|
|
@@ -131,10 +140,9 @@
|
|
|
131
140
|
transition:
|
|
132
141
|
background var(--calendar-grid-duration) var(--calendar-grid-easing),
|
|
133
142
|
color var(--calendar-grid-duration) var(--calendar-grid-easing);
|
|
134
|
-
--a-icon-size: var(--calendar-grid-nav-icon-size);
|
|
135
143
|
}
|
|
136
|
-
[data-cal-prev]:hover,
|
|
137
|
-
[data-cal-next]:hover {
|
|
144
|
+
button-ui[data-cal-prev]:hover,
|
|
145
|
+
button-ui[data-cal-next]:hover {
|
|
138
146
|
background: var(--calendar-grid-nav-bg-hover);
|
|
139
147
|
color: var(--calendar-grid-nav-fg-hover);
|
|
140
148
|
}
|
|
@@ -164,7 +172,18 @@
|
|
|
164
172
|
gap: var(--calendar-grid-day-grid-gap);
|
|
165
173
|
}
|
|
166
174
|
|
|
167
|
-
|
|
175
|
+
/* Stamped <button-ui variant="ghost" text="…"> (gh issue 276 wave 4).
|
|
176
|
+
button-ui floors min-width/min-height at --button-height — point it at
|
|
177
|
+
the day-cell size (not just the literal width/height below) so the
|
|
178
|
+
floor never clamps a smaller [size] tier. The literal geometry/color
|
|
179
|
+
declarations below out-specify button-ui's own equivalents via the
|
|
180
|
+
`button-ui` type-selector bump (same technique as swiper's dots).
|
|
181
|
+
button-ui renders its label via `::after { content: attr(text) }` — the
|
|
182
|
+
today-indicator dot below therefore uses `::before` (kept free), not
|
|
183
|
+
`::after`, to avoid the two fighting over the same pseudo-element. */
|
|
184
|
+
button-ui[data-cal-day] {
|
|
185
|
+
--button-height: var(--calendar-grid-day-size);
|
|
186
|
+
|
|
168
187
|
display: flex;
|
|
169
188
|
align-items: center;
|
|
170
189
|
justify-content: center;
|
|
@@ -188,25 +207,25 @@
|
|
|
188
207
|
}
|
|
189
208
|
|
|
190
209
|
/* ── State: hover ── */
|
|
191
|
-
[data-cal-day]:not([disabled]):not([data-outside]):hover {
|
|
210
|
+
button-ui[data-cal-day]:not([disabled]):not([data-outside]):hover {
|
|
192
211
|
background: var(--calendar-grid-day-bg-hover);
|
|
193
212
|
color: var(--calendar-grid-day-fg-hover);
|
|
194
213
|
}
|
|
195
214
|
|
|
196
215
|
/* ── State: focus ── */
|
|
197
|
-
[data-cal-day]:not([disabled]):not([data-outside]):focus-visible,
|
|
198
|
-
[data-cal-day][data-focused] {
|
|
216
|
+
button-ui[data-cal-day]:not([disabled]):not([data-outside]):focus-visible,
|
|
217
|
+
button-ui[data-cal-day][data-focused] {
|
|
199
218
|
outline: none;
|
|
200
219
|
box-shadow: var(--calendar-grid-day-focus-ring);
|
|
201
220
|
}
|
|
202
221
|
|
|
203
222
|
/* ── State: selected ── */
|
|
204
|
-
[data-cal-day][data-selected] {
|
|
223
|
+
button-ui[data-cal-day][data-selected] {
|
|
205
224
|
background: var(--calendar-grid-day-bg-selected);
|
|
206
225
|
color: var(--calendar-grid-day-fg-selected);
|
|
207
226
|
font-weight: var(--calendar-grid-selected-weight);
|
|
208
227
|
}
|
|
209
|
-
[data-cal-day][data-selected]:not([disabled]):hover {
|
|
228
|
+
button-ui[data-cal-day][data-selected]:not([disabled]):hover {
|
|
210
229
|
background: var(--calendar-grid-day-bg-selected);
|
|
211
230
|
color: var(--calendar-grid-day-fg-selected);
|
|
212
231
|
}
|
|
@@ -217,21 +236,21 @@
|
|
|
217
236
|
fill); the in-range middle is visually subordinate. `:not([data-selected])`
|
|
218
237
|
guard prevents the muted fill from overriding the endpoint cells in
|
|
219
238
|
consumer code that sets both `value` AND `range-start`/`range-end`. */
|
|
220
|
-
[data-cal-day][data-in-range]:not([data-selected]) {
|
|
239
|
+
button-ui[data-cal-day][data-in-range]:not([data-selected]) {
|
|
221
240
|
background: var(--calendar-grid-day-bg-in-range);
|
|
222
241
|
color: var(--calendar-grid-day-fg-in-range);
|
|
223
242
|
}
|
|
224
|
-
[data-cal-day][data-in-range]:not([data-selected]):not([disabled]):hover {
|
|
243
|
+
button-ui[data-cal-day][data-in-range]:not([data-selected]):not([disabled]):hover {
|
|
225
244
|
background: var(--calendar-grid-day-bg-in-range);
|
|
226
245
|
}
|
|
227
246
|
|
|
228
247
|
/* ── State: today (unselected) ── */
|
|
229
|
-
[data-cal-day][data-today]:not([data-selected]) {
|
|
248
|
+
button-ui[data-cal-day][data-today]:not([data-selected]) {
|
|
230
249
|
position: relative;
|
|
231
250
|
color: var(--calendar-grid-day-today-color);
|
|
232
251
|
font-weight: var(--calendar-grid-today-weight);
|
|
233
252
|
}
|
|
234
|
-
[data-cal-day][data-today]:not([data-selected])::
|
|
253
|
+
button-ui[data-cal-day][data-today]:not([data-selected])::before {
|
|
235
254
|
content: "";
|
|
236
255
|
position: absolute;
|
|
237
256
|
left: 50%;
|
|
@@ -245,13 +264,16 @@
|
|
|
245
264
|
}
|
|
246
265
|
|
|
247
266
|
/* ── State: outside month ── */
|
|
248
|
-
[data-cal-day][data-outside] {
|
|
267
|
+
button-ui[data-cal-day][data-outside] {
|
|
249
268
|
color: var(--calendar-grid-day-fg-outside);
|
|
250
269
|
cursor: default;
|
|
251
270
|
}
|
|
252
271
|
|
|
253
|
-
/* ── State: disabled (excluding outside) ──
|
|
254
|
-
|
|
272
|
+
/* ── State: disabled (excluding outside) ──
|
|
273
|
+
`[disabled]` — NOT the `:disabled` pseudo-class, which only matches
|
|
274
|
+
native form controls; button-ui is a custom element, so `:disabled`
|
|
275
|
+
silently never matches it. */
|
|
276
|
+
button-ui[data-cal-day][disabled]:not([data-outside]) {
|
|
255
277
|
color: var(--calendar-grid-day-fg-disabled);
|
|
256
278
|
cursor: not-allowed;
|
|
257
279
|
}
|
|
@@ -16,6 +16,11 @@ description: >-
|
|
|
16
16
|
(two side-by-side grids), and datetime-picker-ui (one grid + time pane).
|
|
17
17
|
For a complete date-picker affordance (trigger + popover + form
|
|
18
18
|
participation), use calendar-picker-ui.
|
|
19
|
+
# Per ADR-0027 — primitives that programmatically create other primitives
|
|
20
|
+
# in their render() do NOT auto-import them. Consumer (or demo shell) must
|
|
21
|
+
# explicitly import each composed primitive.
|
|
22
|
+
composes:
|
|
23
|
+
- button-ui # day cells + month nav (gh issue 276 wave 4)
|
|
19
24
|
props:
|
|
20
25
|
value:
|
|
21
26
|
description: Selected date in ISO format (YYYY-MM-DD).
|
|
@@ -191,10 +191,14 @@ export class UICalendarPicker extends UIFormElement {
|
|
|
191
191
|
const maxDate = parseISO(this.max);
|
|
192
192
|
|
|
193
193
|
// Header
|
|
194
|
+
// <button-ui variant="ghost" icon="…"> (gh issue 276 wave 4) — no
|
|
195
|
+
// tabindex here, matching the native version: these nav buttons stay in
|
|
196
|
+
// the default tab order (unlike calendar-grid-ui's, which are pulled out
|
|
197
|
+
// via tabindex="-1" for its inline roving-tabindex day grid).
|
|
194
198
|
let h = `<div data-cal-header>
|
|
195
|
-
<button data-cal-prev
|
|
199
|
+
<button-ui variant="ghost" size="xs" icon="caret-left" data-cal-prev aria-label="Previous month"></button-ui>
|
|
196
200
|
<span data-cal-title>${MONTHS_LONG[month]} ${year}</span>
|
|
197
|
-
<button data-cal-next
|
|
201
|
+
<button-ui variant="ghost" size="xs" icon="caret-right" data-cal-next aria-label="Next month"></button-ui>
|
|
198
202
|
</div>`;
|
|
199
203
|
|
|
200
204
|
// Day-of-week header
|
|
@@ -210,7 +214,7 @@ export class UICalendarPicker extends UIFormElement {
|
|
|
210
214
|
// Previous month trailing days
|
|
211
215
|
for (let i = firstDay - 1; i >= 0; i--) {
|
|
212
216
|
const day = daysInPrev - i;
|
|
213
|
-
h += `<button
|
|
217
|
+
h += `<button-ui variant="ghost" data-cal-day data-outside disabled tabindex="-1" text="${day}"></button-ui>`;
|
|
214
218
|
}
|
|
215
219
|
|
|
216
220
|
// Current month days
|
|
@@ -223,7 +227,6 @@ export class UICalendarPicker extends UIFormElement {
|
|
|
223
227
|
const isFocused = this.#focusedDay === d;
|
|
224
228
|
|
|
225
229
|
const attrs = [
|
|
226
|
-
'type="button"',
|
|
227
230
|
'data-cal-day',
|
|
228
231
|
`data-date="${iso}"`,
|
|
229
232
|
isToday ? 'data-today' : '',
|
|
@@ -233,14 +236,16 @@ export class UICalendarPicker extends UIFormElement {
|
|
|
233
236
|
`tabindex="${isFocused ? '0' : '-1'}"`,
|
|
234
237
|
].filter(Boolean).join(' ');
|
|
235
238
|
|
|
236
|
-
|
|
239
|
+
// <button-ui variant="ghost" text="…"> (gh issue 276 wave 4) — the day
|
|
240
|
+
// number moves from element text content to the `text` attribute.
|
|
241
|
+
h += `<button-ui variant="ghost" ${attrs} text="${d}"></button-ui>`;
|
|
237
242
|
}
|
|
238
243
|
|
|
239
244
|
// Next month leading days
|
|
240
245
|
const totalCells = firstDay + daysInMonth;
|
|
241
246
|
const remaining = (7 - (totalCells % 7)) % 7;
|
|
242
247
|
for (let d = 1; d <= remaining; d++) {
|
|
243
|
-
h += `<button
|
|
248
|
+
h += `<button-ui variant="ghost" data-cal-day data-outside disabled tabindex="-1" text="${d}"></button-ui>`;
|
|
244
249
|
}
|
|
245
250
|
|
|
246
251
|
h += '</div>';
|
|
@@ -156,10 +156,12 @@
|
|
|
156
156
|
:scope:focus-visible [slot="trigger"] {
|
|
157
157
|
/* Canonical ring via L3 token (see semantics.css FOCUS block). */
|
|
158
158
|
box-shadow: var(--calendar-picker-trigger-focus-ring);
|
|
159
|
+
border-color: transparent;
|
|
159
160
|
}
|
|
160
161
|
:scope[aria-invalid="true"]:focus-visible [slot="trigger"],
|
|
161
162
|
:scope[error]:focus-visible [slot="trigger"] {
|
|
162
163
|
box-shadow: var(--calendar-picker-trigger-focus-ring-invalid);
|
|
164
|
+
border-color: transparent;
|
|
163
165
|
}
|
|
164
166
|
|
|
165
167
|
[slot="display"] {
|
|
@@ -230,14 +232,22 @@ calendar-picker-ui [data-cal-title] {
|
|
|
230
232
|
color: var(--calendar-picker-title-fg);
|
|
231
233
|
}
|
|
232
234
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
+
/* Stamped <button-ui variant="ghost" size="xs" icon="caret-…"> (gh issue 276
|
|
236
|
+
wave 4) — icon-only (no [text], no child text) so button-ui's own
|
|
237
|
+
[data-icon-only] rule already squares it to --button-height; pointing
|
|
238
|
+
--button-height at the nav size (not just literal height below) avoids
|
|
239
|
+
the min-width/min-height floor trap. Literal background/color below
|
|
240
|
+
out-specify button.css's own via the `button-ui` type-selector bump
|
|
241
|
+
(same technique as swiper's dots). */
|
|
242
|
+
calendar-picker-ui button-ui[data-cal-prev],
|
|
243
|
+
calendar-picker-ui button-ui[data-cal-next] {
|
|
244
|
+
--button-height: var(--calendar-picker-nav-size);
|
|
245
|
+
--a-icon-size: var(--calendar-picker-nav-icon-size);
|
|
246
|
+
|
|
235
247
|
display: inline-flex;
|
|
236
248
|
align-items: center;
|
|
237
249
|
justify-content: center;
|
|
238
|
-
width: var(--calendar-picker-nav-size);
|
|
239
250
|
height: var(--calendar-picker-nav-size);
|
|
240
|
-
padding: 0;
|
|
241
251
|
border: none;
|
|
242
252
|
border-radius: var(--calendar-picker-nav-radius);
|
|
243
253
|
background: var(--calendar-picker-nav-bg);
|
|
@@ -246,10 +256,9 @@ calendar-picker-ui [data-cal-next] {
|
|
|
246
256
|
transition:
|
|
247
257
|
background var(--calendar-picker-duration) var(--calendar-picker-easing),
|
|
248
258
|
color var(--calendar-picker-duration) var(--calendar-picker-easing);
|
|
249
|
-
--a-icon-size: var(--calendar-picker-nav-icon-size);
|
|
250
259
|
}
|
|
251
|
-
calendar-picker-ui [data-cal-prev]:hover,
|
|
252
|
-
calendar-picker-ui [data-cal-next]:hover {
|
|
260
|
+
calendar-picker-ui button-ui[data-cal-prev]:hover,
|
|
261
|
+
calendar-picker-ui button-ui[data-cal-next]:hover {
|
|
253
262
|
background: var(--calendar-picker-nav-bg-hover);
|
|
254
263
|
color: var(--calendar-picker-nav-fg-hover);
|
|
255
264
|
}
|
|
@@ -279,8 +288,18 @@ calendar-picker-ui [data-cal-grid] {
|
|
|
279
288
|
gap: var(--calendar-picker-day-grid-gap);
|
|
280
289
|
}
|
|
281
290
|
|
|
282
|
-
/* Day buttons
|
|
283
|
-
|
|
291
|
+
/* Day buttons — stamped <button-ui variant="ghost" text="…"> (gh issue 276
|
|
292
|
+
wave 4). button-ui floors min-width/min-height at --button-height — point
|
|
293
|
+
it at the day-cell size (not just the literal width/height below) so the
|
|
294
|
+
floor never clamps a smaller [size] tier. The literal geometry/color
|
|
295
|
+
declarations below out-specify button-ui's own equivalents via the
|
|
296
|
+
`button-ui` type-selector bump (same technique as swiper's dots).
|
|
297
|
+
button-ui renders its label via `::after { content: attr(text) }` — the
|
|
298
|
+
today-indicator dot below therefore uses `::before` (kept free), not
|
|
299
|
+
`::after`, to avoid the two fighting over the same pseudo-element. */
|
|
300
|
+
calendar-picker-ui button-ui[data-cal-day] {
|
|
301
|
+
--button-height: var(--calendar-picker-day-size);
|
|
302
|
+
|
|
284
303
|
display: flex;
|
|
285
304
|
align-items: center;
|
|
286
305
|
justify-content: center;
|
|
@@ -302,25 +321,25 @@ calendar-picker-ui [data-cal-day] {
|
|
|
302
321
|
}
|
|
303
322
|
|
|
304
323
|
/* ── State: hover ── */
|
|
305
|
-
calendar-picker-ui [data-cal-day]:not([disabled]):not([data-outside]):hover {
|
|
324
|
+
calendar-picker-ui button-ui[data-cal-day]:not([disabled]):not([data-outside]):hover {
|
|
306
325
|
background: var(--calendar-picker-day-bg-hover);
|
|
307
326
|
color: var(--calendar-picker-day-fg-hover);
|
|
308
327
|
}
|
|
309
328
|
|
|
310
329
|
/* ── State: focus ── */
|
|
311
|
-
calendar-picker-ui [data-cal-day]:not([disabled]):not([data-outside]):focus-visible,
|
|
312
|
-
calendar-picker-ui [data-cal-day][data-focused] {
|
|
330
|
+
calendar-picker-ui button-ui[data-cal-day]:not([disabled]):not([data-outside]):focus-visible,
|
|
331
|
+
calendar-picker-ui button-ui[data-cal-day][data-focused] {
|
|
313
332
|
outline: none;
|
|
314
333
|
box-shadow: var(--calendar-picker-day-focus-ring);
|
|
315
334
|
}
|
|
316
335
|
|
|
317
336
|
/* ── State: selected ── */
|
|
318
|
-
calendar-picker-ui [data-cal-day][data-selected] {
|
|
337
|
+
calendar-picker-ui button-ui[data-cal-day][data-selected] {
|
|
319
338
|
background: var(--calendar-picker-day-bg-selected);
|
|
320
339
|
color: var(--calendar-picker-day-fg-selected);
|
|
321
340
|
font-weight: var(--calendar-picker-selected-weight);
|
|
322
341
|
}
|
|
323
|
-
calendar-picker-ui [data-cal-day][data-selected]:not([disabled]):hover {
|
|
342
|
+
calendar-picker-ui button-ui[data-cal-day][data-selected]:not([disabled]):hover {
|
|
324
343
|
background: var(--calendar-picker-day-bg-selected-hover);
|
|
325
344
|
color: var(--calendar-picker-day-fg-selected);
|
|
326
345
|
}
|
|
@@ -328,12 +347,12 @@ calendar-picker-ui [data-cal-day][data-selected]:not([disabled]):hover {
|
|
|
328
347
|
/* ── State: today (unselected) ──
|
|
329
348
|
Use a small bottom dot so it does not compete with the rounded
|
|
330
349
|
focus-ring box-shadow (that looked like a double outline). */
|
|
331
|
-
calendar-picker-ui [data-cal-day][data-today]:not([data-selected]) {
|
|
350
|
+
calendar-picker-ui button-ui[data-cal-day][data-today]:not([data-selected]) {
|
|
332
351
|
position: relative;
|
|
333
352
|
color: var(--calendar-picker-day-today-border);
|
|
334
353
|
font-weight: var(--calendar-picker-today-weight);
|
|
335
354
|
}
|
|
336
|
-
calendar-picker-ui [data-cal-day][data-today]:not([data-selected])::
|
|
355
|
+
calendar-picker-ui button-ui[data-cal-day][data-today]:not([data-selected])::before {
|
|
337
356
|
content: "";
|
|
338
357
|
position: absolute;
|
|
339
358
|
left: 50%;
|
|
@@ -347,13 +366,16 @@ calendar-picker-ui [data-cal-day][data-today]:not([data-selected])::after {
|
|
|
347
366
|
}
|
|
348
367
|
|
|
349
368
|
/* ── State: outside month ── */
|
|
350
|
-
calendar-picker-ui [data-cal-day][data-outside] {
|
|
369
|
+
calendar-picker-ui button-ui[data-cal-day][data-outside] {
|
|
351
370
|
color: var(--calendar-picker-day-fg-outside);
|
|
352
371
|
cursor: default;
|
|
353
372
|
}
|
|
354
373
|
|
|
355
|
-
/* ── State: disabled ──
|
|
356
|
-
|
|
374
|
+
/* ── State: disabled ──
|
|
375
|
+
`[disabled]` — NOT the `:disabled` pseudo-class, which only matches
|
|
376
|
+
native form controls; button-ui is a custom element, so `:disabled`
|
|
377
|
+
silently never matches it. */
|
|
378
|
+
calendar-picker-ui button-ui[data-cal-day][disabled]:not([data-outside]) {
|
|
357
379
|
color: var(--calendar-picker-day-fg-disabled);
|
|
358
380
|
cursor: not-allowed;
|
|
359
381
|
}
|
|
@@ -11,6 +11,11 @@ description: >-
|
|
|
11
11
|
supports min/max and disabled-date masks. Use for single-date input in
|
|
12
12
|
forms; for date ranges compose two pickers or use a dedicated range
|
|
13
13
|
component.
|
|
14
|
+
# Per ADR-0027 — primitives that programmatically create other primitives
|
|
15
|
+
# in their render() do NOT auto-import them. Consumer (or demo shell) must
|
|
16
|
+
# explicitly import each composed primitive.
|
|
17
|
+
composes:
|
|
18
|
+
- button-ui # day cells + month nav (gh issue 276 wave 4)
|
|
14
19
|
props:
|
|
15
20
|
name:
|
|
16
21
|
description: Form field name
|
|
@@ -341,21 +341,24 @@ export class UIChart extends UIElement {
|
|
|
341
341
|
this.addEventListener('pointerdown', this.#onPointerDown);
|
|
342
342
|
this.addEventListener('click', this.#onClick);
|
|
343
343
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
this.#resizeRaf
|
|
355
|
-
this.#
|
|
344
|
+
// gh#285 — SSR DOM shims (linkedom) have no ResizeObserver global.
|
|
345
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
346
|
+
this.#resizeObs = new ResizeObserver((entries) => {
|
|
347
|
+
const { inlineSize: w, blockSize: h } = entries[0].contentBoxSize[0];
|
|
348
|
+
if (!this.#data.length) return;
|
|
349
|
+
const rw = Math.round(w);
|
|
350
|
+
const rh = Math.round(h);
|
|
351
|
+
if (rw === this.#lastW && (!this.hasAttribute('resize') || rh === this.#lastH)) return;
|
|
352
|
+
this.#lastW = rw;
|
|
353
|
+
this.#lastH = rh;
|
|
354
|
+
if (this.#resizeRaf) return;
|
|
355
|
+
this.#resizeRaf = requestAnimationFrame(() => {
|
|
356
|
+
this.#resizeRaf = null;
|
|
357
|
+
this.#renderChart();
|
|
358
|
+
});
|
|
356
359
|
});
|
|
357
|
-
|
|
358
|
-
|
|
360
|
+
this.#resizeObs.observe(this);
|
|
361
|
+
}
|
|
359
362
|
}
|
|
360
363
|
|
|
361
364
|
render() {
|
|
@@ -59,7 +59,9 @@
|
|
|
59
59
|
}
|
|
60
60
|
],
|
|
61
61
|
"category": "agent",
|
|
62
|
-
"composes": [
|
|
62
|
+
"composes": [
|
|
63
|
+
"button-ui"
|
|
64
|
+
],
|
|
63
65
|
"events": {
|
|
64
66
|
"submit": {
|
|
65
67
|
"description": "Fires when the user presses Enter (without Shift) in the textarea OR clicks the built-in send button. Unconditional — there is no [submit-on-enter] opt-in or opt-out attribute; Enter→submit is delegated from the inner <textarea-ui> which always emits a `submit` event on Enter without Shift. The composer suppresses submission while `[loading]` is set.",
|
|
@@ -122,10 +122,12 @@ chat-input-ui textarea-ui:not([disabled]) [slot="text"]:hover {
|
|
|
122
122
|
─────────────────────────────────────────────────────────────── */
|
|
123
123
|
:scope:focus-within {
|
|
124
124
|
box-shadow: var(--chat-input-focus-ring);
|
|
125
|
+
border-color: transparent;
|
|
125
126
|
}
|
|
126
127
|
:scope[aria-invalid="true"]:focus-within,
|
|
127
128
|
:scope[error]:focus-within {
|
|
128
129
|
box-shadow: var(--chat-input-focus-ring-invalid);
|
|
130
|
+
border-color: transparent;
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
/* ── Nested-control color isolation ─────────────────────────────────
|
|
@@ -239,23 +241,20 @@ chat-input-ui textarea-ui:not([disabled]) [slot="text"]:hover {
|
|
|
239
241
|
border: 1px solid var(--chat-input-image-border);
|
|
240
242
|
}
|
|
241
243
|
|
|
244
|
+
/* Attachment-remove — a stamped <button-ui variant="ghost" size="xs"
|
|
245
|
+
icon="x"> (gh issue 276: no native <button> in stamped DOM); the
|
|
246
|
+
floating filled-circle look rides button token re-points. */
|
|
242
247
|
[slot="preview"] [data-preview-remove] {
|
|
243
248
|
position: absolute;
|
|
244
249
|
top: calc(-1 * var(--chat-input-remove-offset));
|
|
245
250
|
right: calc(-1 * var(--chat-input-remove-offset));
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
line-height: 1;
|
|
254
|
-
cursor: pointer;
|
|
255
|
-
display: flex;
|
|
256
|
-
align-items: center;
|
|
257
|
-
justify-content: center;
|
|
258
|
-
padding: 0;
|
|
251
|
+
--button-height: var(--chat-input-remove-size);
|
|
252
|
+
--button-radius: var(--a-radius-full);
|
|
253
|
+
--button-bg: var(--chat-input-remove-bg);
|
|
254
|
+
--button-fg: var(--chat-input-remove-fg);
|
|
255
|
+
--button-bg-ghost-hover: var(--chat-input-remove-bg);
|
|
256
|
+
--button-fg-ghost-hover: var(--chat-input-remove-fg);
|
|
257
|
+
--a-icon-size: var(--chat-input-remove-font);
|
|
259
258
|
}
|
|
260
259
|
|
|
261
260
|
/* Disabled / streaming — host-level chrome. `color` cascades to the
|
|
@@ -228,8 +228,12 @@ class UIChatInput extends UIElement {
|
|
|
228
228
|
const img = document.createElement('img');
|
|
229
229
|
img.src = a.dataUrl;
|
|
230
230
|
img.alt = a.name || 'attachment';
|
|
231
|
-
|
|
232
|
-
btn
|
|
231
|
+
// button-ui, not a native <button> (gh issue 276).
|
|
232
|
+
const btn = document.createElement('button-ui');
|
|
233
|
+
btn.setAttribute('variant', 'ghost');
|
|
234
|
+
btn.setAttribute('size', 'xs');
|
|
235
|
+
btn.setAttribute('icon', 'x');
|
|
236
|
+
btn.setAttribute('aria-label', `Remove ${a.name || 'attachment'}`);
|
|
233
237
|
btn.setAttribute('data-preview-remove', '');
|
|
234
238
|
btn.addEventListener('click', () => this.#removeAttachment(i));
|
|
235
239
|
wrap.appendChild(img);
|
|
@@ -61,6 +61,9 @@ description: |
|
|
|
61
61
|
autocomplete, trailing/leading controls), wrap inside
|
|
62
62
|
`<chat-composer>` — see ChatComposer for the module-tier shape.
|
|
63
63
|
|
|
64
|
+
composes:
|
|
65
|
+
- button-ui # send button + attachment-remove (gh issue 276 — no native <button> in stamped DOM)
|
|
66
|
+
|
|
64
67
|
props:
|
|
65
68
|
disabled:
|
|
66
69
|
description: |
|
|
@@ -123,7 +123,7 @@ check-ui[indeterminate] {
|
|
|
123
123
|
:scope[label]::after { content: attr(label); }
|
|
124
124
|
|
|
125
125
|
/* Focus */
|
|
126
|
-
:scope:focus-visible [slot="box"] { box-shadow: var(--check-focus-ring); }
|
|
126
|
+
:scope:focus-visible [slot="box"] { box-shadow: var(--check-focus-ring); border-color: transparent; }
|
|
127
127
|
|
|
128
128
|
/* Size handled by universal [size] attribute system. */
|
|
129
129
|
}
|
|
@@ -169,11 +169,14 @@ export class UIColorInput extends UIFormElement {
|
|
|
169
169
|
// Store the observer in a #field so disconnected() can clean it up
|
|
170
170
|
// — without the explicit reference, the observer survives the host
|
|
171
171
|
// element across mount/unmount cycles (audit-lifecycle-leak).
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
172
|
+
// gh#285 — SSR DOM shims (linkedom) have no MutationObserver global.
|
|
173
|
+
if (typeof MutationObserver !== 'undefined') {
|
|
174
|
+
this.#popoverObserver = new MutationObserver(sync);
|
|
175
|
+
this.#popoverObserver.observe(this.#popover, {
|
|
176
|
+
attributes: true,
|
|
177
|
+
attributeFilter: ['open'],
|
|
178
|
+
});
|
|
179
|
+
}
|
|
177
180
|
}
|
|
178
181
|
|
|
179
182
|
#onPickerChange = (e) => {
|
|
@@ -362,9 +362,12 @@ export class UIColorPicker extends UIFormElement {
|
|
|
362
362
|
|
|
363
363
|
this.#hueTrack.addEventListener('keydown', this.#onHueKeydown);
|
|
364
364
|
|
|
365
|
-
// Observe area resize to redraw canvas
|
|
366
|
-
|
|
367
|
-
|
|
365
|
+
// Observe area resize to redraw canvas.
|
|
366
|
+
// gh#285 — SSR DOM shims (linkedom) have no ResizeObserver global.
|
|
367
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
368
|
+
this.#areaResizeObs = new ResizeObserver(() => this.#drawArea());
|
|
369
|
+
this.#areaResizeObs.observe(this.#areaEl);
|
|
370
|
+
}
|
|
368
371
|
}
|
|
369
372
|
|
|
370
373
|
disconnected() {
|
|
@@ -241,9 +241,7 @@ export class UICombobox extends UIFormElement {
|
|
|
241
241
|
aria-controls="${listboxId}"
|
|
242
242
|
aria-labelledby="${labelId}"
|
|
243
243
|
data-placeholder="${escapeHTML(this.placeholder || '')}"></span>
|
|
244
|
-
<button
|
|
245
|
-
<icon-ui name="x-circle"></icon-ui>
|
|
246
|
-
</button>
|
|
244
|
+
<button-ui variant="ghost" size="xs" data-clear aria-label="Clear" tabindex="-1" style="display:none"><icon-ui slot="icon" name="x-circle"></icon-ui></button-ui>
|
|
247
245
|
<span data-suffix>
|
|
248
246
|
<icon-ui name="caret-down"></icon-ui>
|
|
249
247
|
</span>
|
|
@@ -102,10 +102,12 @@
|
|
|
102
102
|
|
|
103
103
|
:scope:focus-within [data-field] {
|
|
104
104
|
box-shadow: var(--combobox-focus-ring);
|
|
105
|
+
border-color: transparent;
|
|
105
106
|
}
|
|
106
107
|
:scope[aria-invalid="true"]:focus-within [data-field],
|
|
107
108
|
:scope[error]:focus-within [data-field] {
|
|
108
109
|
box-shadow: var(--combobox-focus-ring-invalid);
|
|
110
|
+
border-color: transparent;
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
[data-prefix],
|
|
@@ -159,20 +161,15 @@
|
|
|
159
161
|
align-items: center;
|
|
160
162
|
}
|
|
161
163
|
|
|
164
|
+
/* Clear x — a stamped <button-ui variant="ghost" size="xs"> kept
|
|
165
|
+
mouse-only via tabindex="-1" (gh issue 276: no native <button> in
|
|
166
|
+
stamped DOM); colors/geometry ride button token re-points. */
|
|
162
167
|
[data-clear] {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
padding: 0;
|
|
167
|
-
margin: 0;
|
|
168
|
-
border: 0;
|
|
169
|
-
background: transparent;
|
|
170
|
-
color: var(--combobox-fg-muted);
|
|
171
|
-
cursor: pointer;
|
|
168
|
+
--button-fg: var(--combobox-fg-muted);
|
|
169
|
+
--button-fg-ghost-hover: var(--combobox-fg);
|
|
170
|
+
--button-height: calc(var(--combobox-font-size) + var(--a-space-1));
|
|
172
171
|
--a-icon-size: var(--combobox-font-size);
|
|
173
|
-
|
|
174
|
-
[data-clear]:hover {
|
|
175
|
-
color: var(--combobox-fg);
|
|
172
|
+
flex-shrink: 0;
|
|
176
173
|
}
|
|
177
174
|
}
|
|
178
175
|
|
|
@@ -20,6 +20,8 @@ description: |
|
|
|
20
20
|
# do NOT auto-import them. Consumer (or demo shell) must explicitly import.
|
|
21
21
|
composes:
|
|
22
22
|
- icon-ui # caret-down / x / magnifying-glass affixes (created in render)
|
|
23
|
+
- button-ui # clear-x affordance, mouse-only via tabindex=-1 (gh issue 276 — no native <button> in stamped DOM)
|
|
24
|
+
- spinner-ui # loading row in the stamped listbox
|
|
23
25
|
props:
|
|
24
26
|
name:
|
|
25
27
|
description: Form control name for form data submission
|
|
@@ -95,13 +95,16 @@ export class UIField extends UIElement {
|
|
|
95
95
|
this.#bindForToControl();
|
|
96
96
|
this.#bindErrorListener();
|
|
97
97
|
this.#labelEl?.addEventListener('click', this.#onLabelClick);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
this.#
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
98
|
+
// gh#285 — SSR DOM shims (linkedom) have no MutationObserver global.
|
|
99
|
+
if (typeof MutationObserver !== 'undefined') {
|
|
100
|
+
this.#mo = new MutationObserver(() => {
|
|
101
|
+
this.#bindForToControl();
|
|
102
|
+
this.#bindErrorListener();
|
|
103
|
+
this.#wireAriaDescribedBy();
|
|
104
|
+
this.#syncErrorMessage();
|
|
105
|
+
});
|
|
106
|
+
this.#mo.observe(this, { childList: true });
|
|
107
|
+
}
|
|
105
108
|
this.#syncErrorMessage();
|
|
106
109
|
}
|
|
107
110
|
|