@adia-ai/web-components 0.8.43 → 0.8.44
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 +30 -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.d.ts +2 -0
- 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/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 +88 -4
- 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/select/select.a2ui.json +5 -1
- package/components/select/select.class.js +14 -14
- package/components/select/select.css +14 -1
- package/components/select/select.yaml +7 -1
- package/components/stream/stream.d.ts +2 -0
- package/components/table/table.a2ui.json +6 -1
- package/components/table/table.class.js +18 -1
- package/components/table/table.css +31 -6
- package/components/table/table.d.ts +3 -1
- package/components/table/table.examples.md +2 -2
- package/components/table/table.yaml +9 -1
- package/components/table-toolbar/table-toolbar.a2ui.json +28 -4
- package/components/table-toolbar/table-toolbar.class.js +346 -11
- package/components/table-toolbar/table-toolbar.css +265 -0
- package/components/table-toolbar/table-toolbar.d.ts +5 -1
- package/components/table-toolbar/table-toolbar.yaml +130 -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/element.js +1 -1
- package/custom-elements.json +73 -29
- 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/type/roles.css +29 -9
|
@@ -301,7 +301,11 @@
|
|
|
301
301
|
]
|
|
302
302
|
},
|
|
303
303
|
"tag": "select-ui",
|
|
304
|
-
"tokens": {
|
|
304
|
+
"tokens": {
|
|
305
|
+
"--select-min-width": {
|
|
306
|
+
"description": "Intrinsic min-width floor on the host (default `20ch`, matching input-ui's own `--input-min-width` UA-baseline derivation) so a select in a shrinking flex/grid cell doesn't crush to unusable width. Set to `0` to opt back into full collapse (gh#1633)."
|
|
307
|
+
}
|
|
308
|
+
},
|
|
305
309
|
"traits": [],
|
|
306
310
|
"version": 1
|
|
307
311
|
}
|
|
@@ -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, '>');
|
|
@@ -337,17 +338,22 @@ export class UISelect extends UIFormElement {
|
|
|
337
338
|
else this.selectAllOptions();
|
|
338
339
|
};
|
|
339
340
|
|
|
340
|
-
// FB-88: tracks
|
|
341
|
-
// `placeholder` (
|
|
342
|
-
// without ever clobbering
|
|
343
|
-
|
|
341
|
+
// FB-88: tracks the aria-label VALUE this element itself last derived from
|
|
342
|
+
// `placeholder` (undefined when none), so re-renders refresh/clear OUR name
|
|
343
|
+
// without ever clobbering a consumer's own aria-label (gh#1646: a boolean
|
|
344
|
+
// flag couldn't detect a consumer's setAttribute between batched renders).
|
|
345
|
+
// The compare-against-what-we-last-wrote guard lives in core/a11y.js's
|
|
346
|
+
// `syncAutoAriaLabel` (gh#1647 / gh#1651); this field is its state.
|
|
347
|
+
#lastAutoAriaLabel = undefined;
|
|
344
348
|
|
|
345
349
|
/**
|
|
346
350
|
* Derive an accessible name from `placeholder` when the select is otherwise
|
|
347
351
|
* unnamed — mirrors input-ui so a placeholder-only select (the idiomatic
|
|
348
352
|
* filter-bar shape) still has a name for assistive tech (WCAG 4.1.2, FB-88).
|
|
349
353
|
*
|
|
350
|
-
* Guards (a placeholder-only fix must NOT clobber a real label)
|
|
354
|
+
* Guards (a placeholder-only fix must NOT clobber a real label) — the
|
|
355
|
+
* per-component policy stays HERE, resolved into the source string
|
|
356
|
+
* (`''` = no auto name this render); the helper only reconciles it:
|
|
351
357
|
* • an author `aria-label`, a visible `label`, or an `aria-labelledby` wins;
|
|
352
358
|
* • the default 'Select...' prompt is NOT used as a name — otherwise every
|
|
353
359
|
* field-ui-wrapped select (named by a sibling `<label for>`, which aria-label
|
|
@@ -355,17 +361,11 @@ export class UISelect extends UIFormElement {
|
|
|
355
361
|
*/
|
|
356
362
|
#syncAccessibleName() {
|
|
357
363
|
const DEFAULT_PLACEHOLDER = 'Select...'; // matches static properties.placeholder.default
|
|
358
|
-
const authoredAria = this.hasAttribute('aria-label') && !this.#placeholderNamed;
|
|
359
364
|
const labeledElsewhere = !!this.label || this.hasAttribute('aria-labelledby');
|
|
360
|
-
const namable = !
|
|
365
|
+
const namable = !labeledElsewhere
|
|
361
366
|
&& 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
|
-
}
|
|
367
|
+
const source = namable ? this.placeholder : '';
|
|
368
|
+
this.#lastAutoAriaLabel = syncAutoAriaLabel(this, this.#lastAutoAriaLabel, source);
|
|
369
369
|
}
|
|
370
370
|
|
|
371
371
|
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);
|
|
@@ -280,7 +280,13 @@ states:
|
|
|
280
280
|
description: Non-interactive; dimmed.
|
|
281
281
|
attribute: disabled
|
|
282
282
|
traits: []
|
|
283
|
-
tokens:
|
|
283
|
+
tokens:
|
|
284
|
+
--select-min-width:
|
|
285
|
+
description: >-
|
|
286
|
+
Intrinsic min-width floor on the host (default `20ch`, matching
|
|
287
|
+
input-ui's own `--input-min-width` UA-baseline derivation) so a
|
|
288
|
+
select in a shrinking flex/grid cell doesn't crush to unusable
|
|
289
|
+
width. Set to `0` to opt back into full collapse (gh#1633).
|
|
284
290
|
requiredIcons:
|
|
285
291
|
- caret-down
|
|
286
292
|
- 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 */
|
|
@@ -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": {
|
|
@@ -125,6 +125,11 @@ export class UITable extends UIElement {
|
|
|
125
125
|
paginate: { type: Number, default: 0, reflect: true },
|
|
126
126
|
loading: { type: Boolean, default: false, reflect: true },
|
|
127
127
|
search: { type: String, default: '', reflect: true },
|
|
128
|
+
// adiav2 zero-overrides purge (gh#1680) deleted an app-side [data-clickable]
|
|
129
|
+
// cursor rule with no kit-side replacement — row-click is always-emitted
|
|
130
|
+
// (fires whether or not a listener cares), so cursor can't be inferred
|
|
131
|
+
// from listener presence; this is an explicit opt-in affordance instead.
|
|
132
|
+
clickableRows: { type: Boolean, default: false, reflect: true, attribute: 'clickable-rows' },
|
|
128
133
|
};
|
|
129
134
|
|
|
130
135
|
static template = () => null;
|
|
@@ -735,6 +740,18 @@ export class UITable extends UIElement {
|
|
|
735
740
|
const allSelected = this.#data.length > 0 && this.#selected.size === this.#data.length;
|
|
736
741
|
const cells = [];
|
|
737
742
|
|
|
743
|
+
// Expand column header — an empty placeholder for the reserved
|
|
744
|
+
// expand-toggle track. Must precede the checkbox header, matching the
|
|
745
|
+
// grid template and body-row cell order (gh#1654: with no placeholder,
|
|
746
|
+
// every header label sat one column left of its data).
|
|
747
|
+
if (this.expandable) {
|
|
748
|
+
const cell = document.createElement('div');
|
|
749
|
+
cell.setAttribute('role', 'columnheader');
|
|
750
|
+
cell.setAttribute('data-expand-col', '');
|
|
751
|
+
cell.setAttribute('aria-label', 'Expand');
|
|
752
|
+
cells.push(cell);
|
|
753
|
+
}
|
|
754
|
+
|
|
738
755
|
// Checkbox column header
|
|
739
756
|
if (this.selectable) {
|
|
740
757
|
const cell = document.createElement('div');
|
|
@@ -1505,7 +1522,7 @@ export class UITable extends UIElement {
|
|
|
1505
1522
|
|
|
1506
1523
|
#onKeydown = (e) => {
|
|
1507
1524
|
const visCols = this.#visibleColumns;
|
|
1508
|
-
const totalCols = visCols.length + (this.selectable ? 1 : 0);
|
|
1525
|
+
const totalCols = visCols.length + (this.expandable ? 1 : 0) + (this.selectable ? 1 : 0);
|
|
1509
1526
|
const body = this.querySelector(':scope > [data-body]');
|
|
1510
1527
|
const totalRows = body ? body.children.length : 0;
|
|
1511
1528
|
|
|
@@ -303,9 +303,18 @@
|
|
|
303
303
|
|
|
304
304
|
/* text-overflow on a flex container doesn't reach text nodes (anonymous
|
|
305
305
|
flex items). Built-in cell types now wrap text in <span>; link type
|
|
306
|
-
creates <a>; avatar/progress composite types use row-ui > span.
|
|
306
|
+
creates <a>; avatar/progress composite types use row-ui > span.
|
|
307
|
+
|
|
308
|
+
`[data-truncate]` (gh#1681) extends the identical contract to
|
|
309
|
+
consumer-rendered `column.render` cells, whose output shape isn't
|
|
310
|
+
guaranteed to be a bare <span>/<a> — a render() function sets it on
|
|
311
|
+
whichever element (any tag, including a custom element) should
|
|
312
|
+
single-line-ellipsis, the same way a column author sets [data-wrap] to
|
|
313
|
+
opt a built-in cell INTO wrapping. Undocumented before this: `render`
|
|
314
|
+
cells clipped with no ellipsis and no opt-in path. */
|
|
307
315
|
[data-body] [role="gridcell"] > span,
|
|
308
|
-
[data-body] [role="gridcell"] > a
|
|
316
|
+
[data-body] [role="gridcell"] > a,
|
|
317
|
+
[data-body] [role="gridcell"] > [data-truncate] {
|
|
309
318
|
min-width: 0;
|
|
310
319
|
flex: 1;
|
|
311
320
|
overflow: hidden;
|
|
@@ -351,8 +360,10 @@
|
|
|
351
360
|
|
|
352
361
|
:scope[wrap] [data-body] [role="gridcell"] > span,
|
|
353
362
|
:scope[wrap] [data-body] [role="gridcell"] > a,
|
|
363
|
+
:scope[wrap] [data-body] [role="gridcell"] > [data-truncate],
|
|
354
364
|
[data-body] [role="gridcell"][data-wrap] > span,
|
|
355
|
-
[data-body] [role="gridcell"][data-wrap] > a
|
|
365
|
+
[data-body] [role="gridcell"][data-wrap] > a,
|
|
366
|
+
[data-body] [role="gridcell"][data-wrap] > [data-truncate] {
|
|
356
367
|
white-space: normal;
|
|
357
368
|
overflow: visible;
|
|
358
369
|
text-overflow: clip;
|
|
@@ -417,6 +428,15 @@
|
|
|
417
428
|
color: var(--table-fg-hover);
|
|
418
429
|
}
|
|
419
430
|
|
|
431
|
+
/* Clickable-row affordance (gh#1680) — adiav2's zero-overrides purge
|
|
432
|
+
deleted an app-side [data-clickable] cursor rule with no kit-side
|
|
433
|
+
replacement. `row-click` fires unconditionally regardless of whether a
|
|
434
|
+
listener cares, so cursor can't be inferred from listener presence;
|
|
435
|
+
`clickable-rows` is an explicit opt-in instead. */
|
|
436
|
+
:scope[clickable-rows] [data-body] > [role="row"] {
|
|
437
|
+
cursor: pointer;
|
|
438
|
+
}
|
|
439
|
+
|
|
420
440
|
/* Selected row — must out-specify the base row rule `[data-body] >
|
|
421
441
|
[role="row"]` (0,2,0) and the hover rule (0,2,1), or the highlight never
|
|
422
442
|
paints. Scoping to `[data-body] > [role="row"][aria-selected="true"]` lifts
|
|
@@ -534,9 +554,14 @@
|
|
|
534
554
|
|
|
535
555
|
/* ═══════ Overlays (empty / loading / error) ═══════ */
|
|
536
556
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
557
|
+
/* Scoped to the host's direct children — gh#1700, hygiene pass matching
|
|
558
|
+
the command-ui (gh#1697/#1698) and combobox-ui (gh#1700) fix shape.
|
|
559
|
+
Single-consumer today (only table.class.js's own `:scope >
|
|
560
|
+
[data-empty]` / `:scope > [data-loading]` overlay markers), but a bare
|
|
561
|
+
selector here is one nested consumer away from the same leak. */
|
|
562
|
+
:scope > [data-overlay],
|
|
563
|
+
:scope > [data-empty],
|
|
564
|
+
:scope > [data-loading] {
|
|
540
565
|
grid-column: 1 / -1;
|
|
541
566
|
display: flex;
|
|
542
567
|
flex-direction: column;
|
|
@@ -86,7 +86,9 @@ export interface TableSortEventDetail {
|
|
|
86
86
|
export type TableSortEvent = CustomEvent<TableSortEventDetail>;
|
|
87
87
|
|
|
88
88
|
export class UITable extends UIElement {
|
|
89
|
-
/**
|
|
89
|
+
/** 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. */
|
|
90
|
+
clickableRows: boolean;
|
|
91
|
+
/** 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. */
|
|
90
92
|
columns: string;
|
|
91
93
|
/** JS property (set programmatically — `el.data = [...]`) — row records, an array of plain objects keyed to columns[].key. May also be supplied declaratively as a JSON-array `data="[…]"` attribute, hydrated once at connect (gh#288) — the same pattern chart-ui's `data` attribute uses. Custom accessor on the element class, not a reflected attribute. */
|
|
92
94
|
data: string;
|
|
@@ -20,7 +20,7 @@ composes:
|
|
|
20
20
|
- badge-ui
|
|
21
21
|
props:
|
|
22
22
|
columns:
|
|
23
|
-
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.
|
|
23
|
+
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.
|
|
24
24
|
type: array
|
|
25
25
|
default: []
|
|
26
26
|
dynamic: true # JS-set collection prop with a custom setter — deliberately not in static properties
|
|
@@ -85,6 +85,14 @@ props:
|
|
|
85
85
|
range select.
|
|
86
86
|
type: boolean
|
|
87
87
|
default: false
|
|
88
|
+
clickable-rows:
|
|
89
|
+
description: >-
|
|
90
|
+
Renders body rows with `cursor: pointer`. `row-click` fires unconditionally
|
|
91
|
+
whether or not a listener is attached, so the cursor can't be inferred from
|
|
92
|
+
listener presence — set this explicitly when row-click behavior is wired up
|
|
93
|
+
(master-detail, open-flyout, navigation) so rows read as actionable.
|
|
94
|
+
type: boolean
|
|
95
|
+
default: false
|
|
88
96
|
sortable:
|
|
89
97
|
description: Enable click-to-sort on column headers. Supports multi-sort via Shift+click.
|
|
90
98
|
type: boolean
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://adiaui.dev/a2ui/v0_9/components/TableToolbar.json",
|
|
4
4
|
"title": "TableToolbar",
|
|
5
|
-
"description": "Header / companion bar for a sibling table-ui. Renders an optional leading [slot=\"scope\"] region, title + count badge, an optional \"Showing X–Y of N\" range summary, filter / sort / columns popovers, a search input, an optional page-size select, and a trailing [slot=\"actions\"] region — all wired to the target table via an [for] id-ref. Modeled on chart-legend-ui's [for] binding pattern. Drop next to (or above) any table-ui to add the standard data-grid toolbar without re-implementing search, filter, sort, column visibility, or pagination summary/page-size. Filter rows auto-pick a primitive per column: ≤ 50 distinct values → multi-select (searchable when ≥ 12 options), id-like keys → free-text contains. The column descriptor's `filter` field overrides the auto-detect: `'select'` forces multi-select even on high-cardinality columns; `'text'` forces a contains input even on small enums.",
|
|
5
|
+
"description": "Header / companion bar for a sibling table-ui. Renders an optional leading [slot=\"scope\"] region, title + count badge, an optional \"Showing X–Y of N\" range summary, filter / sort / columns popovers, a search input, an optional [slot=\"actions-leading\"] region, an optional page-size select, and a trailing [slot=\"actions\"] region — all wired to the target table via an [for] id-ref. Modeled on chart-legend-ui's [for] binding pattern. Drop next to (or above) any table-ui to add the standard data-grid toolbar without re-implementing search, filter, sort, column visibility, or pagination summary/page-size. Filter rows auto-pick a primitive per column: ≤ 50 distinct values → multi-select (searchable when ≥ 12 options), id-like keys → free-text contains. The column descriptor's `filter` field overrides the auto-detect: `'select'` forces multi-select even on high-cardinality columns; `'text'` forces a contains input even on small enums.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"allOf": [
|
|
8
8
|
{
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
}
|
|
14
14
|
],
|
|
15
15
|
"properties": {
|
|
16
|
+
"chromeOnly": {
|
|
17
|
+
"description": "Suppress all four native controls/search at once (filter, sort, columns, search) as additive sugar over noFilter/noSort/noColumns/ noSearch (ADR-0076, ADIA2-9123). Precedence is pure, absolute OR — while set, all four stay off regardless of any individual no-* attribute's own value, with no partial re-enable path; to re-enable one control, remove chrome-only entirely and set the other three no-* attributes explicitly instead. The four granular attributes are not deprecated or removed — they remain the independently-addressable shipped API; chrome-only never replaces them, it's a convenience preset on top.",
|
|
18
|
+
"type": "boolean",
|
|
19
|
+
"default": false
|
|
20
|
+
},
|
|
16
21
|
"component": {
|
|
17
22
|
"const": "TableToolbar"
|
|
18
23
|
},
|
|
@@ -75,6 +80,18 @@
|
|
|
75
80
|
"type": "number",
|
|
76
81
|
"default": 0
|
|
77
82
|
},
|
|
83
|
+
"stage": {
|
|
84
|
+
"description": "Explicit compaction-stage override (ADR-0076). Unset (the default, empty string) means auto-snap: the toolbar's own inline-size container query picks the nearest stage from its live width against the three --table-toolbar-bp-* breakpoints, snapping discretely, never interpolating. Setting stage explicitly pins that stage's rendering regardless of the container's actual width — overriding the container query, mirroring chart-ui's ratio override shape. Primary use: visual-eval fixtures that need a deterministic stage without resizing a real container, and a consumer embedding the toolbar inside a known-narrow panel who wants to skip auto-detection entirely. All four stages' CSS is now live (ADR-0076): search-tight steps the search field down (step 2); icon-only drops control labels and compacts/hides the range summary (steps 3+4); overflow collapses Filter/Sort/Columns into one \"More\" trigger routed through the same menu-ui/menu-item-ui pattern used elsewhere in the corpus (step 5). The resolved stage — the pin if set, otherwise the live width classification — also reflects onto the host as `data-stage-resolved` (step 7, informational only, mirrors chart-ui's `data-ratio-resolved` convention — never drives table-toolbar's own rendering, which stays 100% CSS-driven).",
|
|
85
|
+
"type": "string",
|
|
86
|
+
"enum": [
|
|
87
|
+
"",
|
|
88
|
+
"full",
|
|
89
|
+
"search-tight",
|
|
90
|
+
"icon-only",
|
|
91
|
+
"overflow"
|
|
92
|
+
],
|
|
93
|
+
"default": ""
|
|
94
|
+
},
|
|
78
95
|
"text": {
|
|
79
96
|
"description": "Title text shown on the left.",
|
|
80
97
|
"type": "string",
|
|
@@ -105,6 +122,7 @@
|
|
|
105
122
|
"field-ui",
|
|
106
123
|
"select-ui",
|
|
107
124
|
"input-ui",
|
|
125
|
+
"menu-ui",
|
|
108
126
|
"menu-item-ui",
|
|
109
127
|
"icon-ui",
|
|
110
128
|
"check-ui"
|
|
@@ -133,8 +151,8 @@
|
|
|
133
151
|
"name": "members-toolbar"
|
|
134
152
|
},
|
|
135
153
|
{
|
|
136
|
-
"description": "The ratified adiav2 list-page toolbar row (ADIA2-9123): scope menu, range summary, filter/columns
|
|
137
|
-
"a2ui": "[\n {\"id\": \"root\", \"component\": \"Column\", \"gap\": \"3\", \"children\": [\"bar\", \"card\"]},\n {\"id\": \"bar\", \"component\": \"TableToolbar\", \"for\": \"accounts\", \"no-sort\": true, \"no-search\": true, \"range-start\": 1, \"range-end\": 25, \"range-total\": 320, \"page-size\": 25, \"page-size-options\": [10, 25, 50, 100]},\n {\"id\": \"card\", \"component\": \"Card\", \"children\": [\"sec\"]},\n {\"id\": \"sec\", \"component\": \"Section\", \"bleed\": true, \"children\": [\"tbl\"]},\n {\"id\": \"tbl\", \"component\": \"Table\", \"id\": \"accounts\", \"sortable\": true, \"raw\": true}\n]",
|
|
154
|
+
"description": "The ratified adiav2 list-page toolbar row (ADIA2-9123, gh#1649): scope menu, range summary, app-owned Filter/Columns triggers (their own filter drawer, not the native popovers — [no-filter]/[no-columns]/ [no-sort]/[no-search] drop the native affordances), page-size select, and a primary CTA — [slot=\"actions-leading\"] carries the Filter/Columns triggers so they land BEFORE the page-size select, while [slot=\"actions\"] carries the CTA so it lands after.",
|
|
155
|
+
"a2ui": "[\n {\"id\": \"root\", \"component\": \"Column\", \"gap\": \"3\", \"children\": [\"bar\", \"card\"]},\n {\"id\": \"bar\", \"component\": \"TableToolbar\", \"for\": \"accounts\", \"no-filter\": true, \"no-sort\": true, \"no-columns\": true, \"no-search\": true, \"range-start\": 1, \"range-end\": 25, \"range-total\": 320, \"page-size\": 25, \"page-size-options\": [10, 25, 50, 100], \"children\": [\"btn-filter\", \"btn-columns\", \"btn-new\"]},\n {\"id\": \"btn-filter\", \"component\": \"Button\", \"text\": \"Filter\", \"variant\": \"ghost\", \"slot\": \"actions-leading\"},\n {\"id\": \"btn-columns\", \"component\": \"Button\", \"text\": \"Columns\", \"variant\": \"ghost\", \"slot\": \"actions-leading\"},\n {\"id\": \"btn-new\", \"component\": \"Button\", \"text\": \"New account\", \"variant\": \"primary\", \"slot\": \"actions\"},\n {\"id\": \"card\", \"component\": \"Card\", \"children\": [\"sec\"]},\n {\"id\": \"sec\", \"component\": \"Section\", \"bleed\": true, \"children\": [\"tbl\"]},\n {\"id\": \"tbl\", \"component\": \"Table\", \"id\": \"accounts\", \"sortable\": true, \"raw\": true}\n]",
|
|
138
156
|
"name": "adiav2-list-page-toolbar-row"
|
|
139
157
|
}
|
|
140
158
|
],
|
|
@@ -163,7 +181,13 @@
|
|
|
163
181
|
],
|
|
164
182
|
"slots": {
|
|
165
183
|
"actions": {
|
|
166
|
-
"description": "Trailing action area — primary buttons (e.g. \"New row\") rendered after the search input."
|
|
184
|
+
"description": "Trailing action area — primary buttons (e.g. \"New row\") rendered after the search input, [slot=\"actions-leading\"], and the page-size select."
|
|
185
|
+
},
|
|
186
|
+
"actions-leading": {
|
|
187
|
+
"description": "Region rendered AFTER the search input and BEFORE the native page-size select (gh#1649) — for app-owned trigger buttons (e.g. custom Filter / Columns triggers that open the consumer's own drawer instead of the native filter/columns popovers) that must land ahead of the page-size select rather than after it, unlike [slot=\"actions\"]. Same real-insertion-point pattern as [slot=\"scope\"] / [slot=\"actions\"] — positioning is CSS by DOM order, not a template stamp. Empty (the default) has zero footprint on existing consumers."
|
|
188
|
+
},
|
|
189
|
+
"empty": {
|
|
190
|
+
"description": "Renders in place of the range-summary text — the same [data-summary] region — when [range-total] is EXPLICITLY present and equal to \"0\" (checked via hasAttribute, never the computed value alone, so an unset range-total during loading never flashes this content; ADR-0076, REQ-E-001). Mutually exclusive with a positive [range-total]: the normal \"Showing X-Y of N\" text always wins whenever range-total is a positive number. Empty (the default) preserves today's exact behavior — [data-summary] hides on a confirmed range-total=\"0\" exactly as before this slot existed. Plain author-supplied markup (text, an empty-state-ui composite, an icon+text pair) — table-toolbar does not template or constrain its shape. Naming matches chart-ui's own existing `empty` slot convention."
|
|
167
191
|
},
|
|
168
192
|
"scope": {
|
|
169
193
|
"description": "Leading region rendered BEFORE the [text]/[count] title cluster — e.g. a scope/view-switcher menu (an org's teams, a saved view). Positioning is CSS by DOM order, mirroring how [slot=\"actions\"] is a real, author-fillable insertion point rather than template-stamped content."
|