@adia-ai/web-components 0.8.48 → 0.8.50
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 +16 -0
- package/MIGRATION.md +136 -0
- package/components/chart/chart.class.js +41 -10
- package/components/input/input.a2ui.json +2 -2
- package/components/input/input.css +45 -16
- package/components/input/input.yaml +11 -9
- package/components/search/search.a2ui.json +1 -1
- package/components/search/search.class.js +43 -0
- package/components/search/search.css +28 -0
- package/components/search/search.yaml +4 -1
- package/components/select/select.class.js +4 -1
- package/components/select/select.css +13 -0
- package/components/stat/stat.a2ui.json +30 -3
- package/components/stat/stat.css +88 -0
- package/components/stat/stat.d.ts +2 -2
- package/components/stat/stat.yaml +99 -6
- package/components/table/table.a2ui.json +1 -1
- package/components/table/table.class.js +9 -9
- package/components/table/table.d.ts +1 -1
- package/components/table/table.yaml +7 -7
- package/components/table-footer/table-footer.class.js +6 -6
- package/components/table-toolbar/table-toolbar.a2ui.json +3 -0
- package/components/table-toolbar/table-toolbar.class.js +28 -6
- package/components/table-toolbar/table-toolbar.css +30 -0
- package/components/table-toolbar/table-toolbar.yaml +57 -17
- package/components/theme-provider/theme-provider.a2ui.json +3 -5
- package/components/theme-provider/theme-provider.class.js +9 -30
- package/components/theme-provider/theme-provider.d.ts +3 -5
- package/components/theme-provider/theme-provider.yaml +4 -8
- package/core/element.js +16 -3
- package/custom-elements.json +10 -6
- package/dist/theme-provider.min.js +3 -3
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +58 -57
- package/dist/web-components.sheet.js +1 -1
- package/index.css +1 -2
- package/package.json +1 -1
- package/styles/README.md +1 -1
- package/styles/api/sizing.css +1 -1
- package/styles/host.css +1 -4
- package/styles/index.css +2 -2
- package/styles/scale.css +19 -26
- package/styles/themes.css +2 -2
- package/styles/type/roles.css +3 -3
- package/styles/typography.css +6 -5
- package/dist/prose.min.css +0 -1
- package/dist/prose.sheet.js +0 -11
- package/dist/verse.min.css +0 -1
- package/dist/verse.sheet.js +0 -11
- package/styles/prose.css +0 -211
- package/styles/verse.css +0 -151
package/components/stat/stat.css
CHANGED
|
@@ -19,6 +19,19 @@
|
|
|
19
19
|
|
|
20
20
|
/* ── Chart-band mode ── */
|
|
21
21
|
--stat-chart-band-height: 3rem;
|
|
22
|
+
|
|
23
|
+
/* ── Tile mode (band + bleed, ADR-0083) — change-chip overlay ──
|
|
24
|
+
Stat-scoped aliases falling back to the exact rung chart.css
|
|
25
|
+
resolves the corresponding --chart-chip-* token to, so an
|
|
26
|
+
ancestor override re-themes both chart axis chips and this delta
|
|
27
|
+
chip in one stroke (ADR-0083 decision 3). */
|
|
28
|
+
--stat-change-inset: var(--a-space-2);
|
|
29
|
+
--stat-change-chip-bg: var(--chart-chip-bg, var(--md-sys-color-neutral-container-high));
|
|
30
|
+
--stat-change-chip-fg: var(--chart-chip-fg, var(--md-sys-color-neutral-on-surface));
|
|
31
|
+
--stat-change-chip-radius: var(--chart-chip-radius, var(--a-radius-sm));
|
|
32
|
+
--stat-change-chip-pad-x: var(--chart-chip-pad-x, var(--a-space-1-5));
|
|
33
|
+
--stat-change-chip-pad-y: var(--chart-chip-pad-y, var(--a-space-1));
|
|
34
|
+
--stat-change-chip-font-size: var(--chart-chip-font-size, var(--a-ui-tiny));
|
|
22
35
|
}
|
|
23
36
|
|
|
24
37
|
:scope {
|
|
@@ -166,6 +179,81 @@
|
|
|
166
179
|
aspect-ratio: auto;
|
|
167
180
|
}
|
|
168
181
|
|
|
182
|
+
/* ── Tile layout: band + bleed together (ADR-0083) ──
|
|
183
|
+
The chart-band from `[band]` above, generalized to bleed three edges
|
|
184
|
+
(inline-start, inline-end, block-end) the way `[bleed]` already
|
|
185
|
+
bleeds horizontally, with the `change` delta overlaid as a chip
|
|
186
|
+
inside the band instead of stacking below it. Declared AFTER the
|
|
187
|
+
shipped `[band]` block above so it wins the equal-specificity tie
|
|
188
|
+
the undefined `band bleed` combination used to lose — `[band]`'s
|
|
189
|
+
grid-template-areas is replaced wholesale (the `change` row is
|
|
190
|
+
removed; the chip lives in the chart grid area instead). Host
|
|
191
|
+
precondition (author-controlled, undetected — the same posture
|
|
192
|
+
gh#1801 ratified for `section[bleed]`): this stat-ui must be the
|
|
193
|
+
last content before the card's block-end edge, no trailing
|
|
194
|
+
footer/section — a following region would collide with the
|
|
195
|
+
negative block-end margin below. Compose inside a card section:
|
|
196
|
+
<stat-ui band bleed value=… label=… change=… trend=…>
|
|
197
|
+
<chart-ui slot="chart" type="area" …></chart-ui>
|
|
198
|
+
</stat-ui> */
|
|
199
|
+
:scope[band][bleed]:has([slot="chart"]) {
|
|
200
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
201
|
+
grid-template-areas:
|
|
202
|
+
"label icon"
|
|
203
|
+
"value value"
|
|
204
|
+
"chart chart";
|
|
205
|
+
align-items: baseline;
|
|
206
|
+
}
|
|
207
|
+
:scope[band][bleed] [slot="chart"] {
|
|
208
|
+
grid-area: chart;
|
|
209
|
+
align-self: stretch;
|
|
210
|
+
height: var(--stat-chart-band-height);
|
|
211
|
+
aspect-ratio: auto;
|
|
212
|
+
/* Three-edge bleed via the --card-inset negative-extent technique
|
|
213
|
+
[bleed] already uses horizontally (see the horizontal-bleed block
|
|
214
|
+
above for the width/margin-block rationale — chart-ui pins its own
|
|
215
|
+
width:100%, so the box is explicitly sized rather than stretched). */
|
|
216
|
+
margin-inline: calc(-1 * var(--card-inset, 0px));
|
|
217
|
+
margin-block-end: calc(-1 * var(--card-inset, 0px));
|
|
218
|
+
width: calc(100% + 2 * var(--card-inset, 0px));
|
|
219
|
+
min-width: 0;
|
|
220
|
+
}
|
|
221
|
+
/* Change chip: overlaid in the chart's own grid area, above it in
|
|
222
|
+
paint order, anchored block-start / inline-end of the band (logical
|
|
223
|
+
properties — RTL mirrors for free). Corner clearance from the
|
|
224
|
+
card's rounded corners is structural: the band's rounded corners are
|
|
225
|
+
block-end only (its block-start edge is mid-card, square), so a
|
|
226
|
+
block-start-anchored chip can never meet one. pointer-events: none —
|
|
227
|
+
it's text, not a control, so it never blocks the chart's own
|
|
228
|
+
hover/tooltip hit-testing beneath it. */
|
|
229
|
+
:scope[band][bleed] [slot="change"] {
|
|
230
|
+
grid-area: chart;
|
|
231
|
+
justify-self: end;
|
|
232
|
+
align-self: start;
|
|
233
|
+
z-index: 1;
|
|
234
|
+
inset-block-start: var(--stat-change-inset);
|
|
235
|
+
inset-inline-end: var(--stat-change-inset);
|
|
236
|
+
position: relative;
|
|
237
|
+
pointer-events: none;
|
|
238
|
+
background: var(--stat-change-chip-bg);
|
|
239
|
+
border-radius: var(--stat-change-chip-radius);
|
|
240
|
+
padding: var(--stat-change-chip-pad-y) var(--stat-change-chip-pad-x);
|
|
241
|
+
font-size: var(--stat-change-chip-font-size);
|
|
242
|
+
}
|
|
243
|
+
/* Chip text fallback — deliberately LOW specificity via :where() (0,1,0,
|
|
244
|
+
same as the generic [slot="change"] rule below it) so the
|
|
245
|
+
[trend="up"/"down"] rules further down this file (0,2,0 — they win
|
|
246
|
+
regardless of source order) keep painting the chip's text + arrow
|
|
247
|
+
whenever a canonical trend is set. --stat-change-chip-fg applies only
|
|
248
|
+
when no trend is set — the fallback, not an override. Splitting this
|
|
249
|
+
one declaration out of the block above (which stays 0,3,0 for its
|
|
250
|
+
geometry/surface properties, none of which trend re-paints) is the
|
|
251
|
+
only way to give color a lower specificity than the rest of that
|
|
252
|
+
block while keeping this selector, not a shape-widening rewrite. */
|
|
253
|
+
:where(:scope[band][bleed]) [slot="change"] {
|
|
254
|
+
color: var(--stat-change-chip-fg);
|
|
255
|
+
}
|
|
256
|
+
|
|
169
257
|
/* ── Label (eyebrow) ── */
|
|
170
258
|
[slot="label"] {
|
|
171
259
|
grid-area: label;
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
import { UIElement } from '../../core/element.js';
|
|
14
14
|
|
|
15
15
|
export class UIStat extends UIElement {
|
|
16
|
-
/** Chart-band KPI layout. With a `slot="chart"` child, label / value / change stack full width top to bottom and the chart forms a short full-width band between the value and the change row (the Gmail/Vercel/shadcn stat-card shape). Composes with `icon` exactly as the base layout does. No effect without a chart slot. */
|
|
16
|
+
/** Chart-band KPI layout. With a `slot="chart"` child, label / value / change stack full width top to bottom and the chart forms a short full-width band between the value and the change row (the Gmail/Vercel/shadcn stat-card shape). Composes with `icon` exactly as the base layout does. Set together with `bleed` (`band bleed`) for the KPI tile: the band bleeds to the card's inline-start, inline-end, and block-end edges, and the `change` delta overlays it as a chip instead of stacking below it (ADR-0083) — the tile's `stat-ui` must be the card's last content (no trailing footer/section). No effect without a chart slot. */
|
|
17
17
|
band: boolean;
|
|
18
|
-
/**
|
|
18
|
+
/** The chart reaches the card's edges — which edges depends on `band`: a column bleeding top/right/bottom without it, a three-edge (inline-start, inline-end, block-end) bottom band with it. With `slot="chart"` alone (no `band`), the value / label / change stack on the left while the chart fills the right column at full height and bleeds to the card's top / right / bottom edges (the horizontal counterpart to a chart in a card `<section bleed>`). Set together with `band` for the full-bleed KPI tile — see `band`. No effect without a chart slot. */
|
|
19
19
|
bleed: boolean;
|
|
20
20
|
/** Change indicator text (e.g. '+12%', '-3%') */
|
|
21
21
|
change: string;
|
|
@@ -51,11 +51,14 @@ props:
|
|
|
51
51
|
default: ""
|
|
52
52
|
bleed:
|
|
53
53
|
description: >-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
The chart reaches the card's edges — which edges depends on `band`: a
|
|
55
|
+
column bleeding top/right/bottom without it, a three-edge (inline-start,
|
|
56
|
+
inline-end, block-end) bottom band with it. With `slot="chart"` alone
|
|
57
|
+
(no `band`), the value / label / change stack on the left while the
|
|
58
|
+
chart fills the right column at full height and bleeds to the card's
|
|
59
|
+
top / right / bottom edges (the horizontal counterpart to a chart in a
|
|
60
|
+
card `<section bleed>`). Set together with `band` for the full-bleed KPI
|
|
61
|
+
tile — see `band`. No effect without a chart slot.
|
|
59
62
|
type: boolean
|
|
60
63
|
default: false
|
|
61
64
|
band:
|
|
@@ -64,7 +67,12 @@ props:
|
|
|
64
67
|
change stack full width top to bottom and the chart forms a short
|
|
65
68
|
full-width band between the value and the change row (the
|
|
66
69
|
Gmail/Vercel/shadcn stat-card shape). Composes with `icon` exactly as
|
|
67
|
-
the base layout does.
|
|
70
|
+
the base layout does. Set together with `bleed` (`band bleed`) for the
|
|
71
|
+
KPI tile: the band bleeds to the card's inline-start, inline-end, and
|
|
72
|
+
block-end edges, and the `change` delta overlays it as a chip instead
|
|
73
|
+
of stacking below it (ADR-0083) — the tile's `stat-ui` must be the
|
|
74
|
+
card's last content (no trailing footer/section). No effect without a
|
|
75
|
+
chart slot.
|
|
68
76
|
type: boolean
|
|
69
77
|
default: false
|
|
70
78
|
events: {}
|
|
@@ -112,6 +120,37 @@ tokens:
|
|
|
112
120
|
description: Font size for the primary value
|
|
113
121
|
--stat-value-weight:
|
|
114
122
|
description: Font weight for the primary value
|
|
123
|
+
--stat-change-inset:
|
|
124
|
+
description: >-
|
|
125
|
+
Clearance of the `band bleed` tile's change chip from the chart band's
|
|
126
|
+
edges. Aliases the same ladder rung as `chart-ui`'s
|
|
127
|
+
`--chart-chrome-inset`.
|
|
128
|
+
--stat-change-chip-bg:
|
|
129
|
+
description: >-
|
|
130
|
+
Background of the `band bleed` tile's change chip. Falls back to
|
|
131
|
+
`chart-ui`'s `--chart-chip-bg`, so an ancestor override re-themes chart
|
|
132
|
+
axis chips and this delta chip together.
|
|
133
|
+
--stat-change-chip-fg:
|
|
134
|
+
description: >-
|
|
135
|
+
Text color of the `band bleed` tile's change chip when no canonical
|
|
136
|
+
`trend` is set (a set `trend` keeps painting via `--stat-up-fg` /
|
|
137
|
+
`--stat-down-fg`). Falls back to `chart-ui`'s `--chart-chip-fg`.
|
|
138
|
+
--stat-change-chip-radius:
|
|
139
|
+
description: >-
|
|
140
|
+
Corner radius of the `band bleed` tile's change chip. Falls back to
|
|
141
|
+
`chart-ui`'s `--chart-chip-radius`.
|
|
142
|
+
--stat-change-chip-pad-x:
|
|
143
|
+
description: >-
|
|
144
|
+
Inline padding of the `band bleed` tile's change chip. Falls back to
|
|
145
|
+
`chart-ui`'s `--chart-chip-pad-x`.
|
|
146
|
+
--stat-change-chip-pad-y:
|
|
147
|
+
description: >-
|
|
148
|
+
Block padding of the `band bleed` tile's change chip. Falls back to
|
|
149
|
+
`chart-ui`'s `--chart-chip-pad-y`.
|
|
150
|
+
--stat-change-chip-font-size:
|
|
151
|
+
description: >-
|
|
152
|
+
Font size of the `band bleed` tile's change chip. Falls back to
|
|
153
|
+
`chart-ui`'s `--chart-chip-font-size`.
|
|
115
154
|
requiredIcons:
|
|
116
155
|
- arrow-up
|
|
117
156
|
- arrow-down
|
|
@@ -123,6 +162,8 @@ a2ui:
|
|
|
123
162
|
reason: 'Different visual + semantic role.'
|
|
124
163
|
- rule: 'Delta indicator uses positive/negative semantic tokens; pass change= attribute with sign.'
|
|
125
164
|
reason: 'Built-in trend coloring; no manual styling needed.'
|
|
165
|
+
- rule: 'For the KPI tile — big value over a full-bleed sparkline/area band with the delta as a chip — set `band bleed` together on the stat-ui; the tile must be the card''s last content.'
|
|
166
|
+
reason: 'band bleed composes the shipped chart-band and horizontal-bleed layouts into the full-bleed tile with the change delta overlaid inside the band as a chip (ADR-0083); a trailing footer/section after it collides with the band''s negative block-end margin.'
|
|
126
167
|
anti_patterns: []
|
|
127
168
|
examples:
|
|
128
169
|
- name: basic-stat
|
|
@@ -150,6 +191,57 @@ examples:
|
|
|
150
191
|
"value": ""
|
|
151
192
|
}
|
|
152
193
|
]
|
|
194
|
+
- name: tile
|
|
195
|
+
description: KPI tile — band bleed with an overlaid delta chip (ADR-0083)
|
|
196
|
+
a2ui: >-
|
|
197
|
+
[
|
|
198
|
+
{
|
|
199
|
+
"id": "root",
|
|
200
|
+
"component": "Card",
|
|
201
|
+
"children": [
|
|
202
|
+
"sec"
|
|
203
|
+
]
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"id": "sec",
|
|
207
|
+
"component": "Section",
|
|
208
|
+
"children": [
|
|
209
|
+
"comp"
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"id": "comp",
|
|
214
|
+
"component": "Stat",
|
|
215
|
+
"band": true,
|
|
216
|
+
"bleed": true,
|
|
217
|
+
"label": "Sessions",
|
|
218
|
+
"value": "84,232",
|
|
219
|
+
"change": "+57%",
|
|
220
|
+
"trend": "up",
|
|
221
|
+
"children": [
|
|
222
|
+
"chart"
|
|
223
|
+
]
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"id": "chart",
|
|
227
|
+
"component": "Chart",
|
|
228
|
+
"slot": "chart",
|
|
229
|
+
"type": "area",
|
|
230
|
+
"x": "d",
|
|
231
|
+
"y": "v",
|
|
232
|
+
"noGrid": true,
|
|
233
|
+
"noValues": true,
|
|
234
|
+
"data": [
|
|
235
|
+
{ "d": "Mon", "v": 12 },
|
|
236
|
+
{ "d": "Tue", "v": 18 },
|
|
237
|
+
{ "d": "Wed", "v": 15 },
|
|
238
|
+
{ "d": "Thu", "v": 27 },
|
|
239
|
+
{ "d": "Fri", "v": 22 },
|
|
240
|
+
{ "d": "Sat", "v": 31 },
|
|
241
|
+
{ "d": "Sun", "v": 29 }
|
|
242
|
+
]
|
|
243
|
+
}
|
|
244
|
+
]
|
|
153
245
|
keywords:
|
|
154
246
|
- stat
|
|
155
247
|
- stats
|
|
@@ -169,6 +261,7 @@ keywords:
|
|
|
169
261
|
- observability
|
|
170
262
|
- performance
|
|
171
263
|
- scoreboard
|
|
264
|
+
- tile
|
|
172
265
|
synonyms:
|
|
173
266
|
analytics:
|
|
174
267
|
- chart
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"default": 0
|
|
61
61
|
},
|
|
62
62
|
"range-total": {
|
|
63
|
-
"description": "Total row count across ALL server pages (gh#1754, ADR-0082) — the table-authoritative server-mode data contract. Presence-gated: the attribute's PRESENCE, not its value, is the mode switch (checked via hasAttribute, never the coerced value alone — the same discipline table-footer-ui's own [range-total] ships). Absent (the default) means client mode: today's behavior exactly, [paginate] slices `.data` as always. Present with [paginate] > 0 means server mode: no local slicing (`.data` IS the current page and renders whole, after local search/sort/filter), the internal pager's page count becomes `max(1, ceil(range-total / paginate))` (one calc site, consolidated), and the internal page-reset sites (`data` set, `setFilter`, `clearFilters`) are suppressed so a fetch write-back never fights the pager back to page 0 — page state then moves only via pager interaction, the `footer-page` command, or `setState()`. The existing `page` event (0-based, unchanged) becomes the fetch trigger: the consumer listens for it, fetches that server page, and writes `.data` back. Explicit `range-total=\"0\"` is server-confirmed empty (pager hidden), never conflated with absent. With [paginate] absent/0, [range-total] is inert for this table's own rendering but stays readable by a bound table-footer-ui (REQ-W-006 branch 2) for its count-only label — see the footer-authoritative shape below, which remains lawful and is unaffected by this attribute. Named identically to table-toolbar-ui's and table-footer-ui's own [range-total] (rows, never `pagination-ui[total]`'s pages — the ADR-0063 B5 collision rule); a third instance of one name for one concept. Explicit `range-total=\"?\"` (gh#1877, ADR-0082 Amendment) is the OPEN/unproven-total state — cursor/hasMore server paging with no known row count yet: still server mode (still presence-gated), but the internal pager's page count stays exactly one page ahead of wherever the pager currently sits (never a fixed ceil(...) total), keeping `next` enabled indefinitely instead of hiding the pager the way a confirmed `range-total=\"0\"` would. Resolves to the normal finite server-mode behavior the instant a real number replaces the \"?\" — every reader downstream (table-toolbar-ui, table-footer-ui) shares this same distinction. Note:
|
|
63
|
+
"description": "Total row count across ALL server pages (gh#1754, ADR-0082) — the table-authoritative server-mode data contract. Presence-gated: the attribute's PRESENCE, not its value, is the mode switch (checked via hasAttribute, never the coerced value alone — the same discipline table-footer-ui's own [range-total] ships). Absent (the default) means client mode: today's behavior exactly, [paginate] slices `.data` as always. Present with [paginate] > 0 means server mode: no local slicing (`.data` IS the current page and renders whole, after local search/sort/filter), the internal pager's page count becomes `max(1, ceil(range-total / paginate))` (one calc site, consolidated), and the internal page-reset sites (`data` set, `setFilter`, `clearFilters`) are suppressed so a fetch write-back never fights the pager back to page 0 — page state then moves only via pager interaction, the `footer-page` command, or `setState()`. The existing `page` event (0-based, unchanged) becomes the fetch trigger: the consumer listens for it, fetches that server page, and writes `.data` back. Explicit `range-total=\"0\"` is server-confirmed empty (pager hidden), never conflated with absent. With [paginate] absent/0, [range-total] is inert for this table's own rendering but stays readable by a bound table-footer-ui (REQ-W-006 branch 2) for its count-only label — see the footer-authoritative shape below, which remains lawful and is unaffected by this attribute. Named identically to table-toolbar-ui's and table-footer-ui's own [range-total] (rows, never `pagination-ui[total]`'s pages — the ADR-0063 B5 collision rule); a third instance of one name for one concept. Explicit `range-total=\"?\"` (gh#1877, ADR-0082 Amendment) is the OPEN/unproven-total state — cursor/hasMore server paging with no known row count yet: still server mode (still presence-gated), but the internal pager's page count stays exactly one page ahead of wherever the pager currently sits (never a fixed ceil(...) total), keeping `next` enabled indefinitely instead of hiding the pager the way a confirmed `range-total=\"0\"` would. Resolves to the normal finite server-mode behavior the instant a real number replaces the \"?\" — every reader downstream (table-toolbar-ui, table-footer-ui) shares this same distinction. Note: this prop is Number-typed and reflected; \"?\" parses to NaN (`+\"?\"`), and the coerced numeric PROPERTY is what carries the open/unproven signal (non-finite) — every reader checks the property, never `getAttribute(...) === '?'`. The DOM attribute itself keeps the authored \"?\" (gh#1895 — the framework's attribute-reflection leaves a non-finite Number value unwritten rather than stringifying it back as the literal \"NaN\").",
|
|
64
64
|
"type": [
|
|
65
65
|
"number",
|
|
66
66
|
"string"
|
|
@@ -339,15 +339,15 @@ export class UITable extends UIElement {
|
|
|
339
339
|
// gh#1877/ADR-0082 Amendment — the open/unproven-total state. NOT keyed
|
|
340
340
|
// on the raw attribute string: `rangeTotal` is a Number-typed reflected
|
|
341
341
|
// prop (installProps in core/element.js), so setting range-total="?" is
|
|
342
|
-
// parsed via `+"?"` → NaN
|
|
343
|
-
//
|
|
344
|
-
//
|
|
345
|
-
//
|
|
346
|
-
//
|
|
347
|
-
//
|
|
348
|
-
//
|
|
349
|
-
//
|
|
350
|
-
//
|
|
342
|
+
// parsed via `+"?"` → NaN. gh#1895 — reflect() (core/element.js) leaves
|
|
343
|
+
// a non-finite Number value unwritten instead of stringifying it back
|
|
344
|
+
// onto the attribute, so by the time #draw()/render() runs,
|
|
345
|
+
// `getAttribute('range-total')` still reads the authored "?". The
|
|
346
|
+
// coerced PROPERTY still holds NaN stably, though (Object.is(NaN, NaN)
|
|
347
|
+
// is true, so re-parsing the unchanged attribute never re-triggers a
|
|
348
|
+
// write either) — that's what #pageCount/showPagination below need to
|
|
349
|
+
// tell "no total yet" apart from "confirmed empty" (range-total="0", a
|
|
350
|
+
// finite 0).
|
|
351
351
|
get #rangeOpen() { return this.#serverMode && !Number.isFinite(Number(this.rangeTotal)); }
|
|
352
352
|
|
|
353
353
|
// gh#1754/ADR-0082 REQ-D-003 (CodeRabbit, PR #1828) — a raw
|
|
@@ -104,7 +104,7 @@ export class UITable extends UIElement {
|
|
|
104
104
|
noPager: boolean;
|
|
105
105
|
/** Rows per page. 0 = show all rows without pagination. When > 0, renders the internal pagination bar below the table — UNLESS [no-pager] is also set (gh#1807, ADR-0080), which keeps [paginate]'s slicing/page-state/`page`-event/`footer-page`-listener behavior but suppresses only the bar itself (the anti-doubled-pager path for a table-footer-ui composition). When [range-total] is also set (gh#1754, ADR-0082), [paginate] becomes purely presentational — it supplies only the page-size for pager math; no local slicing runs. */
|
|
106
106
|
paginate: number;
|
|
107
|
-
/** Total row count across ALL server pages (gh#1754, ADR-0082) — the table-authoritative server-mode data contract. Presence-gated: the attribute's PRESENCE, not its value, is the mode switch (checked via hasAttribute, never the coerced value alone — the same discipline table-footer-ui's own [range-total] ships). Absent (the default) means client mode: today's behavior exactly, [paginate] slices `.data` as always. Present with [paginate] > 0 means server mode: no local slicing (`.data` IS the current page and renders whole, after local search/sort/filter), the internal pager's page count becomes `max(1, ceil(range-total / paginate))` (one calc site, consolidated), and the internal page-reset sites (`data` set, `setFilter`, `clearFilters`) are suppressed so a fetch write-back never fights the pager back to page 0 — page state then moves only via pager interaction, the `footer-page` command, or `setState()`. The existing `page` event (0-based, unchanged) becomes the fetch trigger: the consumer listens for it, fetches that server page, and writes `.data` back. Explicit `range-total="0"` is server-confirmed empty (pager hidden), never conflated with absent. With [paginate] absent/0, [range-total] is inert for this table's own rendering but stays readable by a bound table-footer-ui (REQ-W-006 branch 2) for its count-only label — see the footer-authoritative shape below, which remains lawful and is unaffected by this attribute. Named identically to table-toolbar-ui's and table-footer-ui's own [range-total] (rows, never `pagination-ui[total]`'s pages — the ADR-0063 B5 collision rule); a third instance of one name for one concept. Explicit `range-total="?"` (gh#1877, ADR-0082 Amendment) is the OPEN/unproven-total state — cursor/hasMore server paging with no known row count yet: still server mode (still presence-gated), but the internal pager's page count stays exactly one page ahead of wherever the pager currently sits (never a fixed ceil(...) total), keeping `next` enabled indefinitely instead of hiding the pager the way a confirmed `range-total="0"` would. Resolves to the normal finite server-mode behavior the instant a real number replaces the "?" — every reader downstream (table-toolbar-ui, table-footer-ui) shares this same distinction. Note:
|
|
107
|
+
/** Total row count across ALL server pages (gh#1754, ADR-0082) — the table-authoritative server-mode data contract. Presence-gated: the attribute's PRESENCE, not its value, is the mode switch (checked via hasAttribute, never the coerced value alone — the same discipline table-footer-ui's own [range-total] ships). Absent (the default) means client mode: today's behavior exactly, [paginate] slices `.data` as always. Present with [paginate] > 0 means server mode: no local slicing (`.data` IS the current page and renders whole, after local search/sort/filter), the internal pager's page count becomes `max(1, ceil(range-total / paginate))` (one calc site, consolidated), and the internal page-reset sites (`data` set, `setFilter`, `clearFilters`) are suppressed so a fetch write-back never fights the pager back to page 0 — page state then moves only via pager interaction, the `footer-page` command, or `setState()`. The existing `page` event (0-based, unchanged) becomes the fetch trigger: the consumer listens for it, fetches that server page, and writes `.data` back. Explicit `range-total="0"` is server-confirmed empty (pager hidden), never conflated with absent. With [paginate] absent/0, [range-total] is inert for this table's own rendering but stays readable by a bound table-footer-ui (REQ-W-006 branch 2) for its count-only label — see the footer-authoritative shape below, which remains lawful and is unaffected by this attribute. Named identically to table-toolbar-ui's and table-footer-ui's own [range-total] (rows, never `pagination-ui[total]`'s pages — the ADR-0063 B5 collision rule); a third instance of one name for one concept. Explicit `range-total="?"` (gh#1877, ADR-0082 Amendment) is the OPEN/unproven-total state — cursor/hasMore server paging with no known row count yet: still server mode (still presence-gated), but the internal pager's page count stays exactly one page ahead of wherever the pager currently sits (never a fixed ceil(...) total), keeping `next` enabled indefinitely instead of hiding the pager the way a confirmed `range-total="0"` would. Resolves to the normal finite server-mode behavior the instant a real number replaces the "?" — every reader downstream (table-toolbar-ui, table-footer-ui) shares this same distinction. Note: this prop is Number-typed and reflected; "?" parses to NaN (`+"?"`), and the coerced numeric PROPERTY is what carries the open/unproven signal (non-finite) — every reader checks the property, never `getAttribute(...) === '?'`. The DOM attribute itself keeps the authored "?" (gh#1895 — the framework's attribute-reflection leaves a non-finite Number value unwritten rather than stringifying it back as the literal "NaN"). */
|
|
108
108
|
rangeTotal: number | string;
|
|
109
109
|
/** Visual-only passthrough — applies `<table-ui>`'s chrome reset (background / border / border-radius all transparent) AND short-circuits the data lifecycle entirely. The consumer owns the body shape: no header injection, no row reconciliation from `.data`, no empty-state / loading overlays, no aggregation or pagination footers. Use raw when embedding `<table-ui>` inside surfaces that supply their own chrome (e.g. `<card-ui><section bleed>`), or when wrapping a consumer-authored native `<table>` for design-token styling without the framework's data semantics. Note: a `<table-ui>` placed directly inside `<card-ui><section bleed>` drops the table's visual chrome automatically (card.css, gh#796) even without `raw` — `raw` is still required to also short-circuit the data lifecycle. Pre-v0.6.33 (FB-53 §2) `raw` was visual-only and the data lifecycle still ran — wrapping a `.data`-unset native table produced a phantom "No data" overlay. v0.6.33+ matches the documented contract. */
|
|
110
110
|
raw: boolean;
|
|
@@ -107,13 +107,13 @@ props:
|
|
|
107
107
|
way a confirmed `range-total="0"` would. Resolves to the normal
|
|
108
108
|
finite server-mode behavior the instant a real number replaces the
|
|
109
109
|
"?" — every reader downstream (table-toolbar-ui, table-footer-ui)
|
|
110
|
-
shares this same distinction. Note:
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
shares this same distinction. Note: this prop is Number-typed and
|
|
111
|
+
reflected; "?" parses to NaN (`+"?"`), and the coerced numeric
|
|
112
|
+
PROPERTY is what carries the open/unproven signal (non-finite) —
|
|
113
|
+
every reader checks the property, never `getAttribute(...) === '?'`.
|
|
114
|
+
The DOM attribute itself keeps the authored "?" (gh#1895 — the
|
|
115
|
+
framework's attribute-reflection leaves a non-finite Number value
|
|
116
|
+
unwritten rather than stringifying it back as the literal "NaN").
|
|
117
117
|
type: [number, string]
|
|
118
118
|
default: 0
|
|
119
119
|
reflect: true
|
|
@@ -340,13 +340,13 @@ export class UITableFooter extends UIElement {
|
|
|
340
340
|
// resolved source of range-total (local attribute if set, else the
|
|
341
341
|
// server-mode target's own) coerces to a non-finite number. NOT keyed
|
|
342
342
|
// on the raw attribute string — rangeTotal is a Number-typed reflected
|
|
343
|
-
// prop, so range-total="?" parses via `+"?"` → NaN
|
|
344
|
-
//
|
|
345
|
-
// literal string "NaN"
|
|
346
|
-
// getAttribute('range-total')
|
|
343
|
+
// prop, so range-total="?" parses via `+"?"` → NaN. gh#1895 — reflect()
|
|
344
|
+
// (core/element.js) now leaves a non-finite Number value unwritten
|
|
345
|
+
// instead of stomping the sentinel with the literal string "NaN", so
|
|
346
|
+
// getAttribute('range-total') keeps reading "?" as authored. The
|
|
347
347
|
// coerced PROPERTY still holds NaN stably (Object.is(NaN, NaN) is
|
|
348
|
-
// true, so the
|
|
349
|
-
//
|
|
348
|
+
// true, so re-parsing the unchanged attribute never re-triggers a
|
|
349
|
+
// write either) — that's what tells "unknown yet" apart from
|
|
350
350
|
// "confirmed zero" (a finite 0) once safeRangeTotal has clamped both
|
|
351
351
|
// to 0.
|
|
352
352
|
const rangeOpen = hasRangeTotal
|
|
@@ -239,6 +239,9 @@
|
|
|
239
239
|
},
|
|
240
240
|
"scope": {
|
|
241
241
|
"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."
|
|
242
|
+
},
|
|
243
|
+
"summary": {
|
|
244
|
+
"description": "gh#1883 — trailing, text-tier cluster for an aggregate datum that belongs with the table but has no home in the range summary or the actions area (e.g. batch-detail's line-items Subtotal: `<span slot=\"summary\">Subtotal <strong>$1,240.00</strong></span>`). Rendered in the same flex row, after [slot=\"actions-leading\"] and before the page-size select / [slot=\"actions\"] — closer to the trailing edge than [slot=\"scope\"]/[range-*], since it reads as a result/total rather than pagination or view-switching context. Text sized via [--table-toolbar-summary-size] (shared with the \"Showing X–Y of N\" range summary — both are the same text tier). Plain author-supplied markup, same real-insertion-point pattern as every other table-toolbar slot — no forced typography beyond the font-size token. Stays visible at every ADR-0076 compaction stage: it is DATA (an aggregate figure the consumer chose to show), not chrome, so it is never dropped or compacted the way the range summary/ controls are — a consumer needing narrower-container behavior owns that via its own slotted content, not a component-side compaction rule. Empty (the default) has zero footprint on existing consumers."
|
|
242
245
|
}
|
|
243
246
|
},
|
|
244
247
|
"states": [
|
|
@@ -683,6 +683,26 @@ export class UITableToolbar extends UIElement {
|
|
|
683
683
|
}
|
|
684
684
|
}
|
|
685
685
|
|
|
686
|
+
// Summary slot passthrough (gh#1883) — a real insertion point (ADR-0067),
|
|
687
|
+
// same pattern as [slot="scope"]/[slot="actions-leading"]/[slot="actions"]
|
|
688
|
+
// above, for a trailing aggregate/total datum (e.g. line-items Subtotal)
|
|
689
|
+
// that belongs with the table but isn't pagination context. Rendered
|
|
690
|
+
// AFTER [slot="actions-leading"] and BEFORE the page-size select /
|
|
691
|
+
// [slot="actions"] — closer to the trailing edge than the range summary,
|
|
692
|
+
// controls, or search, since it reads as a result rather than view
|
|
693
|
+
// chrome. Deliberately NOT named [data-summary] — that marker already
|
|
694
|
+
// belongs to the "Showing X–Y of N" range-summary cluster stamped above;
|
|
695
|
+
// reusing it here would collide with every existing #updateSummary()/CSS
|
|
696
|
+
// selector keyed on that attribute.
|
|
697
|
+
const summarySlot = document.createElement('div');
|
|
698
|
+
summarySlot.setAttribute('data-summary-slot', '');
|
|
699
|
+
for (const node of [...this.children]) {
|
|
700
|
+
if (node === root) continue;
|
|
701
|
+
if (node.getAttribute?.('slot') === 'summary') {
|
|
702
|
+
summarySlot.appendChild(node);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
686
706
|
// Actions slot passthrough — we move any pre-existing [slot="actions"] children here
|
|
687
707
|
const actionsSlot = document.createElement('div');
|
|
688
708
|
actionsSlot.setAttribute('data-actions', '');
|
|
@@ -699,6 +719,7 @@ export class UITableToolbar extends UIElement {
|
|
|
699
719
|
root.appendChild(controls);
|
|
700
720
|
root.appendChild(search);
|
|
701
721
|
root.appendChild(actionsLeadingSlot);
|
|
722
|
+
root.appendChild(summarySlot);
|
|
702
723
|
root.appendChild(pageSize);
|
|
703
724
|
root.appendChild(actionsSlot);
|
|
704
725
|
|
|
@@ -865,12 +886,13 @@ export class UITableToolbar extends UIElement {
|
|
|
865
886
|
// gh#1877/ADR-0082 Amendment — same open/unproven-total discipline as
|
|
866
887
|
// table-footer-ui's own #draw(): NOT keyed on the raw attribute
|
|
867
888
|
// string. rangeTotal is a Number-typed reflected prop, so
|
|
868
|
-
// range-total="?" parses via `+"?"` → NaN
|
|
869
|
-
//
|
|
870
|
-
// string "NaN"
|
|
871
|
-
//
|
|
872
|
-
// (Object.is(NaN, NaN) is
|
|
873
|
-
//
|
|
889
|
+
// range-total="?" parses via `+"?"` → NaN. gh#1895 — reflect()
|
|
890
|
+
// (core/element.js) leaves a non-finite Number value unwritten instead
|
|
891
|
+
// of stomping the sentinel with the literal string "NaN", so
|
|
892
|
+
// getAttribute('range-total') keeps reading "?" as authored. The
|
|
893
|
+
// coerced PROPERTY still holds NaN stably (Object.is(NaN, NaN) is
|
|
894
|
+
// true, so re-parsing the unchanged attribute never re-triggers a
|
|
895
|
+
// write either), and that's what tells "unknown yet" apart from a
|
|
874
896
|
// confirmed range-total="0" (a finite 0).
|
|
875
897
|
const rangeOpen = !Number.isFinite(Number(this.rangeTotal));
|
|
876
898
|
// gh#1877/ADR-0082 Amendment — additive suffixes onto the normal
|
|
@@ -526,6 +526,36 @@
|
|
|
526
526
|
|
|
527
527
|
[data-actions-leading]:empty { display: none; }
|
|
528
528
|
|
|
529
|
+
/* ═══════ Summary slot ═══════ (gh#1883 — trailing aggregate/total datum,
|
|
530
|
+
e.g. line-items Subtotal, rendered AFTER [slot="actions-leading"] and
|
|
531
|
+
BEFORE the page-size select / [slot="actions"]. Text-tier sized via
|
|
532
|
+
--table-toolbar-summary-size — the SAME token the range summary
|
|
533
|
+
([data-summary-text]/[data-summary-compact]) already uses, since both
|
|
534
|
+
read as the same "small figure next to the toolbar chrome" tier;
|
|
535
|
+
color is NOT forced (unlike the range summary, which paints its own
|
|
536
|
+
generated text) — this slot holds plain author-supplied markup that
|
|
537
|
+
may want its own emphasis, e.g. a bold `<strong>` total.
|
|
538
|
+
Deliberately carries no margin-inline-start:auto of its own: it sits
|
|
539
|
+
between [data-actions-leading] and [data-page-size], both of which
|
|
540
|
+
already push the trailing group to the far edge, so a third auto
|
|
541
|
+
margin here would only ever be a no-op (the first unclaimed-space
|
|
542
|
+
sibling already claims it) — see [data-page-size]'s own comment below.
|
|
543
|
+
No compaction-stage hide/compact rule at any breakpoint or [stage]
|
|
544
|
+
pin, unlike [data-summary] above — this is DATA the consumer chose to
|
|
545
|
+
show, not chrome; a consumer needing narrower-container behavior owns
|
|
546
|
+
that via its own slotted content. */
|
|
547
|
+
|
|
548
|
+
[data-summary-slot] {
|
|
549
|
+
display: inline-flex;
|
|
550
|
+
align-items: center;
|
|
551
|
+
gap: var(--table-toolbar-cluster-gap);
|
|
552
|
+
flex: 0 0 auto;
|
|
553
|
+
font-size: var(--table-toolbar-summary-size);
|
|
554
|
+
line-height: var(--a-font-leading-snug);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
[data-summary-slot]:empty { display: none; }
|
|
558
|
+
|
|
529
559
|
/* ═══════ Page-size select ═══════ (gh#1615)
|
|
530
560
|
Carries the SAME margin-inline-start:auto as [data-search] so the
|
|
531
561
|
trailing group (controls/search/page-size/actions) still pushes to the
|
|
@@ -317,6 +317,26 @@ slots:
|
|
|
317
317
|
stamp. Empty (the default) has zero footprint on existing consumers.
|
|
318
318
|
actions:
|
|
319
319
|
description: Trailing action area — primary buttons (e.g. "New row") rendered after the search input, [slot="actions-leading"], and the page-size select.
|
|
320
|
+
summary:
|
|
321
|
+
description: >-
|
|
322
|
+
gh#1883 — trailing, text-tier cluster for an aggregate datum that
|
|
323
|
+
belongs with the table but has no home in the range summary or the
|
|
324
|
+
actions area (e.g. batch-detail's line-items Subtotal:
|
|
325
|
+
`<span slot="summary">Subtotal <strong>$1,240.00</strong></span>`).
|
|
326
|
+
Rendered in the same flex row, after [slot="actions-leading"] and
|
|
327
|
+
before the page-size select / [slot="actions"] — closer to the
|
|
328
|
+
trailing edge than [slot="scope"]/[range-*], since it reads as a
|
|
329
|
+
result/total rather than pagination or view-switching context. Text
|
|
330
|
+
sized via [--table-toolbar-summary-size] (shared with the
|
|
331
|
+
"Showing X–Y of N" range summary — both are the same text tier).
|
|
332
|
+
Plain author-supplied markup, same real-insertion-point pattern as
|
|
333
|
+
every other table-toolbar slot — no forced typography beyond the
|
|
334
|
+
font-size token. Stays visible at every ADR-0076 compaction stage: it
|
|
335
|
+
is DATA (an aggregate figure the consumer chose to show), not chrome,
|
|
336
|
+
so it is never dropped or compacted the way the range summary/
|
|
337
|
+
controls are — a consumer needing narrower-container behavior owns
|
|
338
|
+
that via its own slotted content, not a component-side compaction
|
|
339
|
+
rule. Empty (the default) has zero footprint on existing consumers.
|
|
320
340
|
states:
|
|
321
341
|
- name: idle
|
|
322
342
|
description: Default, ready for interaction.
|
|
@@ -354,29 +374,40 @@ a2ui:
|
|
|
354
374
|
- >-
|
|
355
375
|
Pair <table-toolbar-ui> with <table-ui> via [for="<table-id>"]
|
|
356
376
|
(or rely on first-sibling fallback when both are inside the
|
|
357
|
-
same parent). One toolbar per table.
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
chrome
|
|
365
|
-
|
|
377
|
+
same parent). One toolbar per table. <table-toolbar-ui> MAY sit
|
|
378
|
+
as <card-ui>'s <header>'s sole child — verified in a rendered
|
|
379
|
+
browser to lay out full-width identically to the
|
|
380
|
+
sibling-above-card pattern (gh#1807/#1884, ADR-0080) — but do
|
|
381
|
+
NOT also give that same <header> a slot="heading"/slot="action"
|
|
382
|
+
child: card.css's grid mode then shrinks the toolbar to its own
|
|
383
|
+
content width and collapses its flex-row layout. The
|
|
384
|
+
doubled-chrome hazard is a TITLE COLLISION, not a blanket
|
|
385
|
+
card-header ban (SPEC REQ-C-004): a toolbar carrying [text] must
|
|
386
|
+
not share a card with a separately heading-slotted <card-ui>
|
|
387
|
+
<header> — that pairing doubles the title row. As the header's
|
|
388
|
+
sole child, the toolbar's own [text]/[count] cluster IS the
|
|
389
|
+
card's title; there is no separate heading to collide with.
|
|
366
390
|
- >-
|
|
367
391
|
All four affordances (search, filter, sort, columns) default ON.
|
|
368
392
|
Opt out individually via [no-search] / [no-filter] / [no-sort]
|
|
369
393
|
/ [no-columns]. The previous [searchable] / [filterable]
|
|
370
394
|
attributes are deprecated — do NOT emit them.
|
|
371
395
|
- >-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
the
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
396
|
+
Two legitimate in-card placements, chosen by whether the card
|
|
397
|
+
header needs content beyond the toolbar: ABOVE the <card-ui>
|
|
398
|
+
(sibling, typically wrapped with the table in a <col-ui>) when
|
|
399
|
+
the header carries its own slot="heading"/slot="action" content
|
|
400
|
+
alongside the toolbar; or AS <card-ui>'s <header> sole child —
|
|
401
|
+
the canonical in-card shape (gh#1807/#1884, ADR-0080) — when the
|
|
402
|
+
toolbar IS the header and no separate title/action row is
|
|
403
|
+
needed. A toolbar can also stand alone outside any card-ui
|
|
404
|
+
parent with [variant="card"], which wraps it in card-style
|
|
405
|
+
chrome. The previous plain (non-bleed) <section> placement
|
|
406
|
+
between the card header and the bleed table section — a
|
|
407
|
+
title-less toolbar leaving the title to a separately-slotted
|
|
408
|
+
header — is retired: no live demo or pattern documents it, and
|
|
409
|
+
the header-child shape supersedes it as the canonical in-card
|
|
410
|
+
composition.
|
|
380
411
|
- >-
|
|
381
412
|
Use slot="action" (or [slot="actions"]) for trailing primary
|
|
382
413
|
buttons (Invite, Export, +New). Use [text] / [count] props for
|
|
@@ -433,6 +464,15 @@ a2ui:
|
|
|
433
464
|
and [range-noun] to stop hand-painting the per-slice noun ("of 80
|
|
434
465
|
users"). Same three attributes, same names, on table-footer-ui
|
|
435
466
|
(ADR-0082 §"same name on both companions").
|
|
467
|
+
- >-
|
|
468
|
+
Use [slot="summary"] (gh#1883) for a trailing aggregate/total datum
|
|
469
|
+
that belongs with the table but isn't pagination context — e.g.
|
|
470
|
+
batch-detail's line-items Subtotal:
|
|
471
|
+
`<span slot="summary">Subtotal <strong>$1,240.00</strong></span>`.
|
|
472
|
+
Renders after [slot="actions-leading"] and before the page-size
|
|
473
|
+
select / [slot="actions"]. Always visible — it is data, never
|
|
474
|
+
collapsed or hidden by the compaction stages that reduce
|
|
475
|
+
Filter/Sort/Columns/search or the range summary.
|
|
436
476
|
- >-
|
|
437
477
|
A plain <button-ui> slotted into [slot="actions-leading"] (e.g. the
|
|
438
478
|
app-owned Filter/Columns triggers above) already collapses to
|
|
@@ -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/ThemeProvider.json",
|
|
4
4
|
"title": "ThemeProvider",
|
|
5
|
-
"description": "Foundation-providing wrapper — adopts the AdiaUI foundation (design tokens +\nresets + page-frame + every primitive's CSS) into the document from anywhere\nin the DOM, so a surface renders fully-styled WITHOUT a hand-wired\n<link rel=\"stylesheet\"> in <head>. Layout-transparent (display: contents): the\nelement owns no box; children lay out as if it weren't there.\n\nMechanism: it imports the constructable-stylesheet twin of web-components.min.css\n(byte-identical to the CDN bundle, emitted from the same build buffer) and\nadopts it once into document.adoptedStyleSheets, deduped — adoption fires at\nmodule load, before paint. Coexists with the render-blocking <link> path; both\ndeliver the same bytes. Use a <link> (-> the CDN web-components.min.css) for\nmulti-page / top-level surfaces (cacheable across navigations, zero flash); use\n<theme-provider> for SPA roots, embedded apps, and dynamic mounts where you do\nnot control <head> (e.g. <embed-shell>, an A2UI surface, a micro-frontend).\n\nTheming: the base foundation is OS light/dark via light-dark() tokens. Two opt-in\nattributes adopt their layer on demand — theme=\"ocean|forest|slate|…\" applies a\nnamed preset (adopts the themes layer; matches the [theme] hook) and\nscale=\"ui-sm|ui-md|ui-lg|content-sm|content-md|content-lg\" sets the sizing\nregister (adopts the matching register layer).
|
|
5
|
+
"description": "Foundation-providing wrapper — adopts the AdiaUI foundation (design tokens +\nresets + page-frame + every primitive's CSS) into the document from anywhere\nin the DOM, so a surface renders fully-styled WITHOUT a hand-wired\n<link rel=\"stylesheet\"> in <head>. Layout-transparent (display: contents): the\nelement owns no box; children lay out as if it weren't there.\n\nMechanism: it imports the constructable-stylesheet twin of web-components.min.css\n(byte-identical to the CDN bundle, emitted from the same build buffer) and\nadopts it once into document.adoptedStyleSheets, deduped — adoption fires at\nmodule load, before paint. Coexists with the render-blocking <link> path; both\ndeliver the same bytes. Use a <link> (-> the CDN web-components.min.css) for\nmulti-page / top-level surfaces (cacheable across navigations, zero flash); use\n<theme-provider> for SPA roots, embedded apps, and dynamic mounts where you do\nnot control <head> (e.g. <embed-shell>, an A2UI surface, a micro-frontend).\n\nTheming: the base foundation is OS light/dark via light-dark() tokens. Two opt-in\nattributes adopt their layer on demand — theme=\"ocean|forest|slate|…\" applies a\nnamed preset (adopts the themes layer; matches the [theme] hook) and\nscale=\"ui-sm|ui-md|ui-lg|content-sm|content-md|content-lg\" sets the sizing\nregister (adopts the matching register layer). Each layer is fetched only\nwhen its attribute is set, so a bare provider stays lean.\nOpt-in infra: NOT in the all-in-one @adia-ai/web-components barrel (it carries\nthe whole foundation); import @adia-ai/web-components/components/theme-provider\nexplicitly. Distinct from <frame-ui> (a layout skeleton, owns no CSS delivery)\nand the page shells (chrome over the same foundation).\n",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"allOf": [
|
|
8
8
|
{
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"const": "ThemeProvider"
|
|
23
23
|
},
|
|
24
24
|
"scale": {
|
|
25
|
-
"description": "Sizing register for the subtree — one of the six [scale] tiers: ui-sm (dense product UI), ui-md (base), ui-lg (touch/presentation), content-sm (compact article), content-md (long-form), content-lg (hero/marketing). Adopts the scale layer on demand; the reflected attribute is the [scale=\"…\"] CSS hook.
|
|
25
|
+
"description": "Sizing register for the subtree — one of the six [scale] tiers: ui-sm (dense product UI), ui-md (base), ui-lg (touch/presentation), content-sm (compact article), content-md (long-form), content-lg (hero/marketing). Adopts the scale layer on demand; the reflected attribute is the [scale=\"…\"] CSS hook.",
|
|
26
26
|
"type": "string",
|
|
27
27
|
"enum": [
|
|
28
28
|
"ui-sm",
|
|
@@ -30,9 +30,7 @@
|
|
|
30
30
|
"ui-lg",
|
|
31
31
|
"content-sm",
|
|
32
32
|
"content-md",
|
|
33
|
-
"content-lg"
|
|
34
|
-
"verse",
|
|
35
|
-
"prose"
|
|
33
|
+
"content-lg"
|
|
36
34
|
],
|
|
37
35
|
"default": ""
|
|
38
36
|
}
|