@adia-ai/web-components 0.8.43 → 0.8.45
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 +54 -0
- package/components/avatar/avatar.class.js +12 -1
- package/components/button/button.d.ts +4 -0
- package/components/chart/chart.a2ui.json +26 -0
- package/components/chart/chart.class.js +1304 -222
- package/components/chart/chart.css +151 -1
- package/components/chart/chart.d.ts +6 -0
- package/components/chart/chart.yaml +57 -0
- package/components/chart-legend/chart-legend.a2ui.json +17 -2
- package/components/chart-legend/chart-legend.class.js +69 -4
- package/components/chart-legend/chart-legend.css +65 -1
- package/components/chart-legend/chart-legend.d.ts +4 -2
- package/components/chart-legend/chart-legend.examples.md +4 -4
- package/components/chart-legend/chart-legend.yaml +43 -3
- package/components/combobox/combobox.a2ui.json +3 -0
- package/components/combobox/combobox.class.js +9 -8
- package/components/combobox/combobox.css +25 -4
- package/components/combobox/combobox.yaml +6 -0
- package/components/command/command.css +17 -1
- package/components/context-menu/context-menu.a2ui.json +8 -3
- package/components/context-menu/context-menu.class.js +46 -5
- package/components/context-menu/context-menu.d.ts +8 -3
- package/components/context-menu/context-menu.examples.md +2 -2
- package/components/context-menu/context-menu.yaml +22 -5
- package/components/heatmap/heatmap.a2ui.json +5 -0
- package/components/heatmap/heatmap.d.ts +2 -0
- package/components/heatmap/heatmap.yaml +8 -0
- package/components/input/input.a2ui.json +2 -2
- package/components/input/input.class.js +12 -7
- package/components/input/input.yaml +6 -5
- package/components/integration-card/integration-card.d.ts +2 -0
- package/components/nav/nav.a2ui.json +2 -2
- package/components/nav/nav.css +1 -1
- package/components/nav/nav.d.ts +1 -1
- package/components/nav/nav.yaml +14 -3
- package/components/nav-group/nav-group.css +37 -3
- package/components/noodles/noodles.a2ui.json +0 -15
- package/components/noodles/noodles.yaml +0 -12
- package/components/number-format/number-format.class.js +10 -0
- package/components/pagination/pagination.class.js +140 -26
- package/components/popover/popover.d.ts +2 -0
- package/components/progress/progress.class.js +11 -6
- package/components/range/range.class.js +9 -1
- package/components/search/search.class.js +39 -5
- package/components/select/select.a2ui.json +10 -1
- package/components/select/select.class.js +34 -14
- package/components/select/select.css +39 -1
- package/components/select/select.d.ts +2 -0
- package/components/select/select.yaml +19 -1
- package/components/stream/stream.d.ts +2 -0
- package/components/table/cell-types.js +9 -0
- package/components/table/table.a2ui.json +6 -1
- package/components/table/table.class.js +265 -34
- package/components/table/table.css +38 -10
- package/components/table/table.d.ts +3 -1
- package/components/table/table.examples.md +2 -2
- package/components/table/table.yaml +15 -2
- package/components/table-toolbar/table-toolbar.a2ui.json +43 -4
- package/components/table-toolbar/table-toolbar.class.js +407 -28
- package/components/table-toolbar/table-toolbar.css +299 -0
- package/components/table-toolbar/table-toolbar.d.ts +15 -1
- package/components/table-toolbar/table-toolbar.yaml +162 -15
- package/components/tag/tag.class.js +13 -1
- package/components/text/text.a2ui.json +3 -3
- package/components/text/text.d.ts +5 -3
- package/components/text/text.yaml +3 -3
- package/components/textarea/textarea.class.js +9 -1
- package/components/tour/tour.d.ts +10 -0
- package/core/a11y.d.ts +22 -0
- package/core/a11y.js +64 -0
- package/core/anchor.js +9 -5
- package/core/data-stream.js +37 -2
- package/core/element.js +1 -1
- package/core/index.d.ts +1 -0
- package/core/index.js +1 -0
- package/core/provider.d.ts +9 -13
- package/core/provider.js +9 -113
- package/core/store.d.ts +46 -0
- package/core/store.js +89 -0
- package/custom-elements.json +127 -33
- package/dist/host.min.css +1 -1
- package/dist/host.sheet.js +1 -1
- package/dist/theme-provider.min.js +1 -1
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +119 -119
- package/dist/web-components.sheet.js +1 -1
- package/package.json +1 -1
- package/patterns/access-requests/access-requests.examples.html +1 -1
- package/patterns/admin-keys-and-export/admin-keys-and-export.examples.html +7 -7
- package/patterns/agent-cost/agent-cost.examples.html +6 -6
- package/patterns/agent-memory/agent-memory.examples.html +3 -3
- package/patterns/agent-prompt-library/agent-prompt-library.examples.html +8 -8
- package/patterns/agent-tool-call/agent-tool-call.examples.html +1 -1
- package/patterns/approvals/approvals.examples.html +6 -6
- package/patterns/audit-log/audit-log.examples.html +1 -1
- package/patterns/bulk-action-toolbar/bulk-action-toolbar.examples.html +4 -4
- package/patterns/chart-in-card/chart-in-card.examples.html +114 -0
- package/patterns/chart-in-card/chart-in-card.examples.js +37 -0
- package/patterns/comments-and-collaboration/comments-and-collaboration.examples.html +5 -5
- package/patterns/data-tables-inline-edit-and-tree/data-tables-inline-edit-and-tree.examples.html +2 -2
- package/patterns/diff-review/diff-review.examples.html +6 -6
- package/patterns/export-flow/export-flow.examples.html +2 -2
- package/patterns/filter-bar/filter-bar.examples.html +2 -2
- package/patterns/forms-conditional-and-autocomplete/forms-conditional-and-autocomplete.examples.html +2 -2
- package/patterns/inline-dialog/inline-dialog.examples.html +2 -2
- package/patterns/marketing-engagement/marketing-engagement.examples.html +4 -4
- package/patterns/notifications-bell-and-digest/notifications-bell-and-digest.examples.html +1 -1
- package/patterns/permissions-matrix/permissions-matrix.examples.html +1 -1
- package/patterns/permissions-sharing/permissions-sharing.examples.html +2 -2
- package/patterns/profile-public-and-verification/profile-public-and-verification.examples.html +4 -4
- package/patterns/search-discovery/search-discovery.examples.html +2 -2
- package/styles/api/sizing.css +46 -0
- package/styles/type/roles.css +29 -9
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import { UIFormElement } from '../../core/form.js';
|
|
15
15
|
import { anchorPopover } from '../../core/anchor.js';
|
|
16
16
|
import { untracked } from '../../core/signals.js';
|
|
17
|
+
import { syncAutoAriaLabel } from '../../core/a11y.js';
|
|
17
18
|
|
|
18
19
|
function escapeHTML(s) {
|
|
19
20
|
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
@@ -46,6 +47,11 @@ export class UISelect extends UIFormElement {
|
|
|
46
47
|
size: { type: String, default: 'md', reflect: true },
|
|
47
48
|
open: { type: Boolean, default: false, reflect: true },
|
|
48
49
|
label: { type: String, default: '', reflect: true },
|
|
50
|
+
// gh#1748: keeps [label] as the accessible name (bridged to an explicit
|
|
51
|
+
// aria-label in #syncAccessibleName below) while suppressing the VISIBLE
|
|
52
|
+
// `::before` text (select.css) — for compositions that already show the
|
|
53
|
+
// name elsewhere. Mirrors check-ui's [label-hidden] (gh#1010).
|
|
54
|
+
labelHidden: { type: Boolean, default: false, reflect: true, attribute: 'label-hidden' },
|
|
49
55
|
icon: { type: String, default: '', reflect: true },
|
|
50
56
|
avatar: { type: String, default: '', reflect: true },
|
|
51
57
|
mark: { type: Boolean, default: false, reflect: true },
|
|
@@ -337,17 +343,22 @@ export class UISelect extends UIFormElement {
|
|
|
337
343
|
else this.selectAllOptions();
|
|
338
344
|
};
|
|
339
345
|
|
|
340
|
-
// FB-88: tracks
|
|
341
|
-
// `placeholder` (
|
|
342
|
-
// without ever clobbering
|
|
343
|
-
|
|
346
|
+
// FB-88: tracks the aria-label VALUE this element itself last derived from
|
|
347
|
+
// `placeholder` (undefined when none), so re-renders refresh/clear OUR name
|
|
348
|
+
// without ever clobbering a consumer's own aria-label (gh#1646: a boolean
|
|
349
|
+
// flag couldn't detect a consumer's setAttribute between batched renders).
|
|
350
|
+
// The compare-against-what-we-last-wrote guard lives in core/a11y.js's
|
|
351
|
+
// `syncAutoAriaLabel` (gh#1647 / gh#1651); this field is its state.
|
|
352
|
+
#lastAutoAriaLabel = undefined;
|
|
344
353
|
|
|
345
354
|
/**
|
|
346
355
|
* Derive an accessible name from `placeholder` when the select is otherwise
|
|
347
356
|
* unnamed — mirrors input-ui so a placeholder-only select (the idiomatic
|
|
348
357
|
* filter-bar shape) still has a name for assistive tech (WCAG 4.1.2, FB-88).
|
|
349
358
|
*
|
|
350
|
-
* Guards (a placeholder-only fix must NOT clobber a real label)
|
|
359
|
+
* Guards (a placeholder-only fix must NOT clobber a real label) — the
|
|
360
|
+
* per-component policy stays HERE, resolved into the source string
|
|
361
|
+
* (`''` = no auto name this render); the helper only reconciles it:
|
|
351
362
|
* • an author `aria-label`, a visible `label`, or an `aria-labelledby` wins;
|
|
352
363
|
* • the default 'Select...' prompt is NOT used as a name — otherwise every
|
|
353
364
|
* field-ui-wrapped select (named by a sibling `<label for>`, which aria-label
|
|
@@ -355,17 +366,26 @@ export class UISelect extends UIFormElement {
|
|
|
355
366
|
*/
|
|
356
367
|
#syncAccessibleName() {
|
|
357
368
|
const DEFAULT_PLACEHOLDER = 'Select...'; // matches static properties.placeholder.default
|
|
358
|
-
|
|
369
|
+
// gh#1748: [label-hidden] suppresses the visible `::before` text
|
|
370
|
+
// (select.css's `attr(label)` content) but [label] must still name the
|
|
371
|
+
// control — bridge it through the SAME tracked-ownership pipeline used
|
|
372
|
+
// below for the placeholder-only case, so a consumer's own directly-set
|
|
373
|
+
// aria-label is never clobbered (gh#1646 guarantee extends for free) and
|
|
374
|
+
// toggling [label-hidden] back off cleanly releases the bridged value
|
|
375
|
+
// (falls through to the visible-label path, which sets no aria-label —
|
|
376
|
+
// the generated `::before` content supplies the name instead, unchanged
|
|
377
|
+
// from today). Mirrors check-ui's [label-hidden] (gh#1010), which
|
|
378
|
+
// instead sets aria-label unconditionally since check-ui never relies
|
|
379
|
+
// on generated-content naming.
|
|
380
|
+
if (this.labelHidden && this.label) {
|
|
381
|
+
this.#lastAutoAriaLabel = syncAutoAriaLabel(this, this.#lastAutoAriaLabel, this.label);
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
359
384
|
const labeledElsewhere = !!this.label || this.hasAttribute('aria-labelledby');
|
|
360
|
-
const namable = !
|
|
385
|
+
const namable = !labeledElsewhere
|
|
361
386
|
&& this.placeholder && this.placeholder !== DEFAULT_PLACEHOLDER;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
this.#placeholderNamed = true;
|
|
365
|
-
} else if (this.#placeholderNamed) {
|
|
366
|
-
this.removeAttribute('aria-label');
|
|
367
|
-
this.#placeholderNamed = false;
|
|
368
|
-
}
|
|
387
|
+
const source = namable ? this.placeholder : '';
|
|
388
|
+
this.#lastAutoAriaLabel = syncAutoAriaLabel(this, this.#lastAutoAriaLabel, source);
|
|
369
389
|
}
|
|
370
390
|
|
|
371
391
|
connected() {
|
|
@@ -7,6 +7,15 @@
|
|
|
7
7
|
--select-px: var(--a-ui-px);
|
|
8
8
|
--select-radius: var(--a-radius);
|
|
9
9
|
--select-leading-radius: var(--a-radius-full);
|
|
10
|
+
/* gh#1633 / ADIA2-9136 (adiav2#12791) — the host's own `min-width: 0`
|
|
11
|
+
below (the ellipsis-reset trick, kept for the trigger/display text
|
|
12
|
+
inside this floor) had no intrinsic lower bound, so a select in a
|
|
13
|
+
shrinking flex/grid cell crushed to unusable width — the same gap
|
|
14
|
+
already fixed on --input-min-width (this family's reference; see
|
|
15
|
+
input.css, gh#781). Same ch-based UA-baseline derivation, applied
|
|
16
|
+
to select-ui's own trigger surface. Override to 0 to opt back into
|
|
17
|
+
full collapse. */
|
|
18
|
+
--select-min-width: 20ch;
|
|
10
19
|
|
|
11
20
|
/* ── Typography ── */
|
|
12
21
|
--select-font-size: var(--a-ui-size);
|
|
@@ -62,7 +71,11 @@
|
|
|
62
71
|
display: flex;
|
|
63
72
|
flex-direction: column;
|
|
64
73
|
gap: var(--select-gap);
|
|
65
|
-
min-width
|
|
74
|
+
/* Floored, not zeroed — see --select-min-width above (gh#1633). The
|
|
75
|
+
trigger's own `min-width: 0` further down stays 0: that one exists
|
|
76
|
+
so the display text can ellipsis-truncate INSIDE this floor, not to
|
|
77
|
+
guard the host's own collapse. */
|
|
78
|
+
min-width: var(--select-min-width);
|
|
66
79
|
/* font-family floor on the host — trigger/native-select/options inherit it. */
|
|
67
80
|
font-family: var(--select-font-family, var(--a-font-family-ui));
|
|
68
81
|
font-size: var(--select-font-size);
|
|
@@ -85,6 +98,31 @@
|
|
|
85
98
|
:scope:not([label])::before,
|
|
86
99
|
:scope[label=""]::before { display: none; }
|
|
87
100
|
|
|
101
|
+
/* Visually-hidden label (gh#1748) — [label-hidden] keeps the a11y name
|
|
102
|
+
(aria-label, bridged from [label] in select.class.js's
|
|
103
|
+
#syncAccessibleName()) but drops the visible text, for compositions
|
|
104
|
+
that already show the name elsewhere (e.g. a table-toolbar-ui
|
|
105
|
+
[slot="scope"] select whose scope/view name is redundant chrome next
|
|
106
|
+
to the toolbar's own title). Same canonical sr-only recipe as
|
|
107
|
+
<visually-hidden-ui> (visually-hidden.css) and check-ui's own
|
|
108
|
+
[label-hidden] (gh#1010) — clip-path does the real hiding, the rest is
|
|
109
|
+
belt-and-suspenders for cross-UA. More specific than the bare
|
|
110
|
+
`::before` rule above, so it wins whenever both [label] and
|
|
111
|
+
[label-hidden] are set. */
|
|
112
|
+
:scope[label][label-hidden]::before {
|
|
113
|
+
content: attr(label);
|
|
114
|
+
position: absolute !important;
|
|
115
|
+
width: 1px !important;
|
|
116
|
+
height: 1px !important;
|
|
117
|
+
padding: 0 !important;
|
|
118
|
+
margin: -1px !important;
|
|
119
|
+
overflow: hidden !important;
|
|
120
|
+
clip: rect(0, 0, 0, 0) !important;
|
|
121
|
+
clip-path: inset(100%) !important;
|
|
122
|
+
white-space: nowrap !important;
|
|
123
|
+
border: 0 !important;
|
|
124
|
+
}
|
|
125
|
+
|
|
88
126
|
/* Trigger */
|
|
89
127
|
[slot="trigger"] {
|
|
90
128
|
display: flex;
|
|
@@ -45,6 +45,8 @@ export class UISelect extends UIFormElement {
|
|
|
45
45
|
/** Open/closed reflected attribute — toggled by trigger click / keyboard. */
|
|
46
46
|
open: boolean;
|
|
47
47
|
label: string;
|
|
48
|
+
/** When true, [label] still sets the accessible name but the visible text is sr-only hidden (gh#1748, mirrors check-ui's [label-hidden], gh#1010). */
|
|
49
|
+
labelHidden: boolean;
|
|
48
50
|
/** Leading icon name (Phosphor registry). */
|
|
49
51
|
icon: string;
|
|
50
52
|
/** Leading avatar URL or name. */
|
|
@@ -104,6 +104,18 @@ props:
|
|
|
104
104
|
description: Label text above the trigger
|
|
105
105
|
type: string
|
|
106
106
|
default: ""
|
|
107
|
+
label-hidden:
|
|
108
|
+
description: >-
|
|
109
|
+
When true, [label] still sets the accessible name (aria-label) but the
|
|
110
|
+
visible `::before` text is suppressed via the canonical sr-only
|
|
111
|
+
technique (gh#1748, mirrors check-ui's [label-hidden], gh#1010). Use
|
|
112
|
+
when a sibling/ancestor composition already conveys the same name
|
|
113
|
+
visually (e.g. a scope/view-switcher select in a table-toolbar-ui
|
|
114
|
+
[slot="scope"], where the toolbar's own title already names the
|
|
115
|
+
view) and a second visible "Scope"-style label would paint it twice.
|
|
116
|
+
type: boolean
|
|
117
|
+
default: false
|
|
118
|
+
reflect: true
|
|
107
119
|
hint:
|
|
108
120
|
description: |-
|
|
109
121
|
§184 (v0.5.5, FEEDBACK-08 §7): small caption rendered beneath the select. Sets `aria-describedby` on the host so screen readers announce it as a description (distinct from `aria-label`, which comes from `label`). Does not conflict with the in-component `label`.
|
|
@@ -280,7 +292,13 @@ states:
|
|
|
280
292
|
description: Non-interactive; dimmed.
|
|
281
293
|
attribute: disabled
|
|
282
294
|
traits: []
|
|
283
|
-
tokens:
|
|
295
|
+
tokens:
|
|
296
|
+
--select-min-width:
|
|
297
|
+
description: >-
|
|
298
|
+
Intrinsic min-width floor on the host (default `20ch`, matching
|
|
299
|
+
input-ui's own `--input-min-width` UA-baseline derivation) so a
|
|
300
|
+
select in a shrinking flex/grid cell doesn't crush to unusable
|
|
301
|
+
width. Set to `0` to opt back into full collapse (gh#1633).
|
|
284
302
|
requiredIcons:
|
|
285
303
|
- caret-down
|
|
286
304
|
- check # checkbox indicator on each option in [multiple] mode
|
|
@@ -22,6 +22,8 @@ export type StreamErrorEvent = CustomEvent<StreamErrorEventDetail>;
|
|
|
22
22
|
export type StreamStartEvent = CustomEvent<unknown>;
|
|
23
23
|
|
|
24
24
|
export class UIStream extends UIElement {
|
|
25
|
+
/** When true, suppress the blinking cursor during active streaming */
|
|
26
|
+
hideCursor: boolean;
|
|
25
27
|
/** Milliseconds between character renders. 0 = real-time. */
|
|
26
28
|
pace: number;
|
|
27
29
|
/** Read-only reflected state, true while stream is active */
|
|
@@ -312,6 +312,15 @@ registerCellType('progress', {
|
|
|
312
312
|
|
|
313
313
|
// 13. actions
|
|
314
314
|
registerCellType('actions', {
|
|
315
|
+
// gh#1678 CodeRabbit follow-up: this render() calls addEventListener()
|
|
316
|
+
// directly on a plain node it creates — unlike every other cell type
|
|
317
|
+
// above (which only set attributes on custom elements, safe to adopt
|
|
318
|
+
// structurally), a discarded 'actions' cell loses a real listener with
|
|
319
|
+
// no way for isEqualNode() to see the loss. `attachesListeners: true`
|
|
320
|
+
// tells table.class.js's adoptOrDiffChildren() (via RENDERER_OWNED) to
|
|
321
|
+
// always replace this cell rather than ever adopt it on structural
|
|
322
|
+
// equality alone. See ssr-compatibility's references/guard-patterns.md §4.1.
|
|
323
|
+
attachesListeners: true,
|
|
315
324
|
render(value, row, cell, meta) {
|
|
316
325
|
const actions = meta?.actions || [];
|
|
317
326
|
let wrapper = cell.querySelector('row-ui');
|
|
@@ -13,8 +13,13 @@
|
|
|
13
13
|
}
|
|
14
14
|
],
|
|
15
15
|
"properties": {
|
|
16
|
+
"clickable-rows": {
|
|
17
|
+
"description": "Renders body rows with `cursor: pointer`. `row-click` fires unconditionally whether or not a listener is attached, so the cursor can't be inferred from listener presence — set this explicitly when row-click behavior is wired up (master-detail, open-flyout, navigation) so rows read as actionable.",
|
|
18
|
+
"type": "boolean",
|
|
19
|
+
"default": false
|
|
20
|
+
},
|
|
16
21
|
"columns": {
|
|
17
|
-
"description": "Column definitions. Array of {key, label, type?, width?, minWidth?, maxWidth?, flex?, sortable?, resizable?, filterable?, pinned?, hidden?, wrap?, valign?, accessor?, format?, render?, sortFn?, filterType?, meta?}. `valign` ('top'|'center') overrides the host [valign] for that column's body cells only — header cells always stay centered. Alternative to declarative <col-def> children (<col-def valign=\"top\">); col-def also accepts `meta` as a JSON attribute (gh#925) — e.g. <col-def type=\"badge\" meta='{\"variants\":{\"Online\":\"success\"}}'> — so cell-type meta (badge variant maps, currency codes) is expressible in static HTML.",
|
|
22
|
+
"description": "Column definitions. Array of {key, label, type?, width?, minWidth?, maxWidth?, flex?, sortable?, resizable?, filterable?, pinned?, hidden?, wrap?, valign?, accessor?, format?, render?, sortFn?, filterType?, meta?}. `valign` ('top'|'center') overrides the host [valign] for that column's body cells only — header cells always stay centered. Alternative to declarative <col-def> children (<col-def valign=\"top\">); col-def also accepts `meta` as a JSON attribute (gh#925) — e.g. <col-def type=\"badge\" meta='{\"variants\":{\"Online\":\"success\"}}'> — so cell-type meta (badge variant maps, currency codes) is expressible in static HTML. Truncation contract for `render` cells (gh#1681) — a `render(value, row, cell, dataIndex)` function's returned markup isn't guaranteed to be a bare <span>/<a> the way built-in cell types are, so single-line ellipsis truncation isn't automatic; set `data-truncate` on whichever rendered element (any tag, including a custom element) should single-line-ellipsis to opt it into the same contract built-in cells get for free. `[wrap]` (host) / `[data-wrap]` (per-column) override it back to multi-line, matching built-in cells.",
|
|
18
23
|
"$ref": "common_types.json#/$defs/DynamicStringList"
|
|
19
24
|
},
|
|
20
25
|
"component": {
|