@adia-ai/web-components 0.7.10 → 0.7.12
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 +34 -2
- package/README.md +2 -2
- package/USAGE.md +2 -2
- package/components/button/button.css +43 -16
- package/components/frame/frame.a2ui.json +1 -1
- package/components/frame/frame.css +9 -6
- package/components/frame/frame.d.ts +5 -3
- package/components/frame/frame.yaml +7 -5
- package/components/list/list.css +4 -0
- package/components/preview/preview.class.js +9 -0
- package/components/theme-provider/theme-provider.a2ui.json +88 -0
- package/components/theme-provider/theme-provider.class.js +134 -0
- package/components/theme-provider/theme-provider.css +18 -0
- package/components/theme-provider/theme-provider.d.ts +45 -0
- package/components/theme-provider/theme-provider.js +22 -0
- package/components/theme-provider/theme-provider.test.js +94 -0
- package/components/theme-provider/theme-provider.yaml +96 -0
- package/dist/host.min.css +1 -1
- package/dist/host.sheet.js +11 -0
- package/dist/prose.min.css +1 -0
- package/dist/prose.sheet.js +11 -0
- package/dist/themes.min.css +1 -0
- package/dist/themes.sheet.js +11 -0
- package/dist/verse.min.css +1 -0
- package/dist/verse.sheet.js +11 -0
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +1 -1
- package/dist/web-components.sheet.js +11 -0
- package/package.json +5 -1
- package/styles/README.md +1 -1
- package/styles/colors/parameters.css +1 -1
- package/styles/colors/primitives-accent.css +1 -1
- package/styles/colors/primitives-brand.css +1 -1
- package/styles/colors/primitives-danger.css +1 -1
- package/styles/colors/primitives-info.css +1 -1
- package/styles/colors/primitives-neutral.css +1 -1
- package/styles/colors/primitives-success.css +1 -1
- package/styles/colors/primitives-warning.css +1 -1
- package/styles/colors/scrims.css +1 -1
- package/styles/colors/semantics/aliases.css +1 -1
- package/styles/colors/semantics/buckets.css +1 -1
- package/styles/colors/semantics/core.css +1 -1
- package/styles/colors/semantics/data-viz.css +1 -1
- package/styles/colors/semantics/features.css +1 -1
- package/styles/colors/surfaces.css +1 -1
- package/styles/components.css +1 -0
- package/styles/design-tokens-export.js +1 -1
- package/styles/host.css +1 -1
- package/styles/prose.css +1 -1
- package/styles/themes.css +12 -12
- package/styles/verse.css +1 -1
- package/traits/resizable/resizable.js +49 -36
- package/traits/resizable/resizable.test.js +19 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
# Changelog — @adia-ai/web-components
|
|
2
2
|
|
|
3
|
-
## [
|
|
3
|
+
## [0.7.12] — 2026-06-04
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **New `<theme-provider>` element — adopt the AdiaUI foundation from anywhere, no `<head>` link.** A Light-DOM, `display: contents` infra wrapper (the 122nd primitive) that adopts the foundation — design tokens + resets + page-frame + every primitive's CSS, the constructable-stylesheet twin of `web-components.min.css` (byte-identical to the CDN bundle) — into `document.adoptedStyleSheets` once, deduped, at module-eval. So SPA roots / embedded apps / dynamic mounts render fully-styled **without** a hand-wired `<link rel="stylesheet">` in `<head>`. Opt-in `theme="ocean|forest|…"` (named preset) + `scale="verse|prose"` (typographic register) adopt their layer twin **on demand** (`theme=` matches the `[theme]` hook directly; `scale=` maps onto the existing `[verse]`/`[prose]` attribute). Coexists with the render-blocking `<link>` path (same bytes) — link for multi-page / top-level surfaces (cacheable, no flash), provider for no-`<head>` contexts. Deliberately **not** in the all-primitives barrel (it carries the whole foundation) — import `@adia-ai/web-components/components/theme-provider` explicitly. Files: `components/theme-provider/{theme-provider.js,.class.js,.css,.yaml,.html,.test.js}`.
|
|
8
|
+
- **CDN `.sheet.js` twins.** `bundle-css.mjs` co-emits a constructable-`CSSStyleSheet` twin beside each foundation `.min.css` — `web-components.sheet.js`, `host.sheet.js`, and the `themes` / `verse` / `prose` register twins — from the **same minified buffer** (byte-identical to the `.min.css`, verified by `check:css-bundles-fresh`, exposed as the `./css/sheet` export). A page that links `web-components.min.css` and one that adopts `web-components.sheet.js` render identically. Powers `<theme-provider>` and any runtime style injector that can't add a `<head>` link.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **BREAKING (pre-1.0 PATCH cadence) — the token-theme attribute `data-theme` is renamed `theme`.** `<html data-theme="ocean">` → `<html theme="ocean">`; `[data-theme="…"]` selectors → `[theme="…"]`; the token-root selector `:root, theme-ui, [data-theme]` → `:root, theme-ui, [theme], theme-provider` across the 14 foundation files (so `<theme-provider>` is itself a token-root). Cleaner, and it converges with `<canvas-ui theme="…">`, which already scoped AdiaUI themes the same way. Done as a repo-wide word-boundary sweep — compound attributes (`data-theme-slug`, `data-themes-grid`, `data-themed`, …) are preserved (the sweep also touched the styles/, traits/, and patterns/ trees). **Consumers using `data-theme="…"` must switch to `theme="…"`** — see `docs/MIGRATION GUIDE.md`.
|
|
13
|
+
- **CDN bundles rebuilt** — `dist/web-components.min.{css,js}` + `dist/host.min.css` regenerated so the `[theme]` rename, `<theme-provider>` registration, and the new register twins reach `@adia-ai/web-components@0.7` CDN consumers.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **`dts-codegen` reads the authoritative tag.** It reconstructed each demo's tag as `${name}-ui`, which mangles a no-`-ui` infra tag (`<theme-provider>` is the first) — it now reads `x-adiaui.tag` from the sidecar. Behavior-neutral for all 121 `-ui` components (their `name-ui` === `tag`); correct for infra tags. File: `scripts/build/dts-codegen.mjs`.
|
|
18
|
+
|
|
19
|
+
## [0.7.11] — 2026-06-04
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **`<frame-ui>` slot-override regions.** Beyond the native `<header>` / `<section>` / `<footer>` tags, any element can take a region role via `slot="header|body|footer"` (a CSS `[slot]` match — the same role-slot pattern as `<drawer-ui>`), so e.g. `<section slot="header">` is a pinned rail rather than the scroll body. The native tag stays the 90% sugar; reach for the slot when the element you want differs from the region role. Rail-slotted elements are `:not()`-excluded from the scroll-body selector, so a `[slot="header"]` section never doubles as the body. Files: `components/frame/{frame.css,frame.yaml,frame.html}`.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- **`button-ui` hover now intensifies to the family `-strong` step.** Filled buttons strengthen their fill on hover — neutral → `--a-bg-strong`, `variant="primary"` → `--a-accent-strong`, and `color="danger|success|info|warning"` → the matching `--a-{family}-strong`. Outline + ghost keep a transparent fill and instead move the **fg** from its rest color to `-strong` (per-color outline/ghost shift to `--a-{family}-strong` text). This corrects a latent bug where `variant="primary"` and `color="danger"` hovered to the neutral `--a-ui-bg-hover` scrim (dropping their color), while `success` / `info` / `warning` and the neutral/default button had no hover-bg feedback at all. Note `-strong` resolves to the same step as `-active`/pressed, so the `:active` scale transform is what distinguishes press from hover. Override surfaces preserved: ghost hover still reads `--button-fg-ghost-hover` (alert.css retints it) and `--button-bg/border-ghost-hover` (the `component-tokens` demo opts a fill back in); the orphaned `--button-bg-hover-danger` token was removed. Warning's mid-tone `-strong` under dark `--a-warning-fg` may read muddy — flagged to revisit the warning ramp upstream. Files: `components/button/{button.css,button.examples.html}`.
|
|
28
|
+
- **`resizable` trait — corner handles + symmetric-from-center resize.** The trait gained 4 corner hit-zones (drag a corner to resize BOTH axes at once) on top of the 4 edges; each handle carries its axis signs (`dw`/`dh`) + cursor, and corners are layered last so they win the hit-test where they overlap an edge. Adds symmetric resize-from-center. Powers `<embed-shell traits="resizable">` and any resizable surface. Files: `traits/resizable/{resizable.js,resizable.examples.html}`.
|
|
29
|
+
- **CDN bundles rebuilt** — `dist/web-components.min.css` + `dist/web-components.min.js` regenerated so the `<frame-ui>` slot-override, the `button-ui` hover `-strong` step, the `resizable` corner handles, and the `list-item-ui` / `<preview-ui>` fixes reach `@adia-ai/web-components@0.7` CDN consumers.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- **`list-item-ui` title vertical-centers with icon + action.** `[slot="text"]` lacked `align-self: center`, so when the action (e.g. a full-height `<button-ui>`) made row 1 taller than the title, the title top-aligned *above* the centered icon + action. All three row-1 cells now center together. Surfaced by `onboarding-checklist-ui` "Open" rows. File: `components/list/list.css`.
|
|
34
|
+
- **`<preview-ui>` code pane shows JSON attributes cleanly.** A JSON-bearing attribute (e.g. `items='[{"id":"a"}]'`) serializes via `outerHTML` as `items="[{"id"…}]"` — the `"` rendered literally in the code/copy pane, and `<code-ui>`’s Copy emitted entity-encoded source. `dedent()` now re-renders quote-bearing attribute values with single-quote delimiters (`items='[{"id":"a"}]'`) — the clean, valid, copy-paste-able form the author wrote (apostrophe-bearing values keep the escaped form, no safe single-char delimiter). File: `components/preview/preview.class.js`.
|
|
35
|
+
- **`[verse]` register radius comment corrected.** `styles/verse.css`'s `--a-radius-max: 0.75rem` carried a stale `/* 16px */` comment — `0.75rem` is 12px. Comment-only; no behavior change (the `0.75rem` max itself shipped in the 0.7.10 `[verse]` type bump). File: `styles/verse.css`.
|
|
4
36
|
|
|
5
37
|
## [0.7.10] — 2026-06-03
|
|
6
38
|
|
|
@@ -3026,7 +3058,7 @@ that don't surface in the export). Pure-JS OKLCH → OKLab → linear-sRGB
|
|
|
3026
3058
|
|
|
3027
3059
|
- **`styles/design-tokens-export.js`** (new ~430 lines) — extraction module:
|
|
3028
3060
|
CSSOM scanner with authoritative-selector filter (`:root, theme-ui,
|
|
3029
|
-
[
|
|
3061
|
+
[theme]` only — skipping attribute-scoped overrides that would
|
|
3030
3062
|
pollute the cssVar map under last-wins semantics), symbolic
|
|
3031
3063
|
`var()` / `light-dark()` chain walker, OKLCH color-math pipeline, four
|
|
3032
3064
|
output formatters (DTCG / hex / float-RGB / HSL-decimal). Public API:
|
package/README.md
CHANGED
|
@@ -336,12 +336,12 @@ generation engine consume.
|
|
|
336
336
|
## Themes, density, scale
|
|
337
337
|
|
|
338
338
|
```html
|
|
339
|
-
<div
|
|
339
|
+
<div theme="ocean" density="compact" size="sm">
|
|
340
340
|
…all descendants re-theme / re-densify / re-scale automatically…
|
|
341
341
|
</div>
|
|
342
342
|
```
|
|
343
343
|
|
|
344
|
-
- `[
|
|
344
|
+
- `[theme]` — 8 themes: `default`, `ocean`, `forest`, `sunset`,
|
|
345
345
|
`lavender`, `rose`, `slate`, `midnight`
|
|
346
346
|
- `[density]` — `compact` (0.85×) · `spacious` (1.15×)
|
|
347
347
|
- `[size]` — `sm`|`md`|`lg` shifts the entire typescale + component
|
package/USAGE.md
CHANGED
|
@@ -673,14 +673,14 @@ The same applies to `bind()` — call it once in the constructor or use a field,
|
|
|
673
673
|
AdiaUI is parametric. Three attributes drive global appearance:
|
|
674
674
|
|
|
675
675
|
```html
|
|
676
|
-
<div
|
|
676
|
+
<div theme="ocean" density="compact" size="sm">
|
|
677
677
|
<!-- all descendants re-theme / re-densify / re-scale -->
|
|
678
678
|
</div>
|
|
679
679
|
```
|
|
680
680
|
|
|
681
681
|
| Attribute | Values | Effect |
|
|
682
682
|
|---|---|---|
|
|
683
|
-
| `[
|
|
683
|
+
| `[theme]` | `default`, `ocean`, `forest`, `sunset`, `lavender`, `rose`, `slate`, `midnight` | Swaps the OKLCH color ramp |
|
|
684
684
|
| `[density]` | `compact` (0.85×), `spacious` (1.15×) | Multiplies `--a-density` token |
|
|
685
685
|
| `[size]` | `sm`, `md`, `lg` | Shifts typescale + component dimensions |
|
|
686
686
|
| `[radius]` | `sharp` (0), `rounded` (1), `round` (2) | Multiplies `--a-radius-k` token |
|
|
@@ -4,26 +4,54 @@
|
|
|
4
4
|
(0,1,1 / 0,2,1) is preserved. See docs/BROWSER-COMPAT.md §3a. */
|
|
5
5
|
button-ui:active { transform: scale(0.97); }
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
/* ── Hover (re-points the component tokens; lives outside @scope —
|
|
8
|
+
Safari 17.x ignores :scope:hover at the scope root, see note above) ──
|
|
9
|
+
Filled variants intensify the fill to the family `-strong` step (the
|
|
10
|
+
deeper, higher-contrast step — note it equals the `-active`/pressed
|
|
11
|
+
step, so the :active transform above is what distinguishes press from
|
|
12
|
+
hover). Outline + ghost keep a transparent fill and instead move the
|
|
13
|
+
FG from its rest color to the matching `-strong` color. */
|
|
14
|
+
|
|
15
|
+
/* Neutral / default — fill → neutral `-strong` surface. Only --button-bg
|
|
16
|
+
moves: the rest fg (--a-fg-strong) and border (transparent) are already
|
|
17
|
+
the hover targets. The filled accent/semantic rules below re-point
|
|
18
|
+
--button-bg at higher specificity and leave each variant's rest fg
|
|
19
|
+
untouched (primary/danger/etc. keep their light label). */
|
|
20
|
+
button-ui:not([disabled]):hover { --button-bg: var(--button-bg-hover); }
|
|
21
|
+
|
|
22
|
+
button-ui[variant="primary"]:not([disabled]):hover { --button-bg: var(--a-accent-strong); }
|
|
23
|
+
button-ui[color="danger"]:not([disabled]):hover { --button-bg: var(--a-danger-strong); }
|
|
24
|
+
button-ui[color="success"]:not([disabled]):hover { --button-bg: var(--a-success-strong); }
|
|
25
|
+
button-ui[color="info"]:not([disabled]):hover { --button-bg: var(--a-info-strong); }
|
|
26
|
+
/* warning fill → -strong like the rest; its mid-tone can read muddy under
|
|
27
|
+
the dark --a-warning-fg — revisit the warning ramp upstream if so. */
|
|
28
|
+
button-ui[color="warning"]:not([disabled]):hover { --button-bg: var(--a-warning-strong); }
|
|
29
|
+
|
|
30
|
+
/* Outline / ghost — no fill on hover; fg goes rest-color → `-strong`.
|
|
31
|
+
Ghost reads --button-fg-ghost-hover (default --a-fg-strong) so consumers
|
|
32
|
+
like alert.css can retint the ghost-hover label, and --button-bg/border-
|
|
33
|
+
ghost-hover (default transparent) so the component-tokens demo can opt a
|
|
34
|
+
fill back in. */
|
|
35
|
+
button-ui[variant="outline"]:not([disabled]):hover {
|
|
36
|
+
--button-bg: transparent;
|
|
10
37
|
--button-fg: var(--button-fg-hover);
|
|
11
|
-
--button-border: var(--button-border-hover);
|
|
12
38
|
}
|
|
13
39
|
button-ui[variant="ghost"]:not([disabled]):hover {
|
|
14
40
|
--button-bg: var(--button-bg-ghost-hover);
|
|
15
41
|
--button-fg: var(--button-fg-ghost-hover);
|
|
16
42
|
--button-border: var(--button-border-ghost-hover);
|
|
17
43
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
button-ui[color="danger"]:not([disabled]):hover
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
44
|
+
|
|
45
|
+
/* Per-color outline/ghost — fg → family `-strong` (specificity 0,4,1
|
|
46
|
+
clears the 0,3,0 [variant][color] rest combos inside @scope). */
|
|
47
|
+
button-ui[variant="outline"][color="danger"]:not([disabled]):hover,
|
|
48
|
+
button-ui[variant="ghost"][color="danger"]:not([disabled]):hover { --button-fg: var(--a-danger-strong); }
|
|
49
|
+
button-ui[variant="outline"][color="success"]:not([disabled]):hover,
|
|
50
|
+
button-ui[variant="ghost"][color="success"]:not([disabled]):hover { --button-fg: var(--a-success-strong); }
|
|
51
|
+
button-ui[variant="outline"][color="info"]:not([disabled]):hover,
|
|
52
|
+
button-ui[variant="ghost"][color="info"]:not([disabled]):hover { --button-fg: var(--a-info-strong); }
|
|
53
|
+
button-ui[variant="outline"][color="warning"]:not([disabled]):hover,
|
|
54
|
+
button-ui[variant="ghost"][color="warning"]:not([disabled]):hover { --button-fg: var(--a-warning-strong); }
|
|
27
55
|
|
|
28
56
|
@scope (button-ui) {
|
|
29
57
|
:where(:scope) {
|
|
@@ -41,7 +69,7 @@ button-ui[color="danger"]:not([disabled]):hover {
|
|
|
41
69
|
--button-font-weight: var(--a-ui-weight);
|
|
42
70
|
--button-font-family: var(--a-font-family-ui);
|
|
43
71
|
--button-gap: var(--a-space-1);
|
|
44
|
-
--button-bg-hover: var(--a-
|
|
72
|
+
--button-bg-hover: var(--a-bg-strong); /* neutral fill → neutral -strong surface on hover */
|
|
45
73
|
--button-fg-hover: var(--a-ui-text-hover);
|
|
46
74
|
--button-border-hover: transparent;
|
|
47
75
|
--button-bg-primary: var(--a-primary);
|
|
@@ -52,12 +80,11 @@ button-ui[color="danger"]:not([disabled]):hover {
|
|
|
52
80
|
--button-bg-ghost: transparent;
|
|
53
81
|
--button-fg-ghost: var(--a-fg-subtle);
|
|
54
82
|
--button-fg-ghost-hover: var(--a-fg-strong);
|
|
55
|
-
--button-bg-ghost-hover:
|
|
83
|
+
--button-bg-ghost-hover: transparent; /* ghost hover is fg-only; consumers/demo may override to add a fill */
|
|
56
84
|
--button-border-ghost: transparent;
|
|
57
85
|
--button-border-ghost-hover: transparent;
|
|
58
86
|
--button-bg-danger: var(--a-danger);
|
|
59
87
|
--button-fg-danger: var(--a-chrome-light); /* white on the saturated fill — see color rules */
|
|
60
|
-
--button-bg-hover-danger: var(--a-danger);
|
|
61
88
|
--button-bg-disabled: var(--a-ui-bg-disabled);
|
|
62
89
|
--button-fg-disabled: var(--a-ui-text-disabled);
|
|
63
90
|
--button-border-disabled: transparent;
|
|
@@ -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/Frame.json",
|
|
4
4
|
"title": "Frame",
|
|
5
|
-
"description": "Sticky-header / scrolling-body / sticky-footer layout frame — the\nchrome-less app-shell skeleton. A flex column that fills its parent's\nblock size: a native <header> child pins to the top, a <footer> child\npins to the bottom, and the <section> child scrolls between them (the\nonly region with overflow).
|
|
5
|
+
"description": "Sticky-header / scrolling-body / sticky-footer layout frame — the\nchrome-less app-shell skeleton. A flex column that fills its parent's\nblock size: a native <header> child pins to the top, a <footer> child\npins to the bottom, and the <section> child scrolls between them (the\nonly region with overflow). Regions are positioned by tag + DOM order, OR any\nelement can take a region role via slot=\"header|body|footer\" (a CSS [slot] match,\nnot native projection — ADR-0033) — e.g. <section slot=\"header\"> as a pinned rail.\nAll three are OPTIONAL, so the common shape is just <section> + <footer>. Use for\ntab / panel content\nwhere actions stay visible while the body scrolls. Distinct from <card-ui>\n(adds border + elevation + a rich header grid), <drawer-ui> / <modal-ui>\n(add a backdrop + dismiss), and the page shells (<admin-page> / <page-ui>) —\nthose layer chrome over this same region contract. Requires a definite-height\nparent (a flex/grid chain rooted at a viewport height) for the section to\nscroll; in a content-sized parent it collapses to its content (no scroll,\nnot broken).\n",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"allOf": [
|
|
8
8
|
{
|
|
@@ -22,16 +22,19 @@
|
|
|
22
22
|
min-block-size: 0;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
/* Pinned rails — <header
|
|
26
|
-
|
|
25
|
+
/* Pinned rails — native <header>/<footer>, OR any element that opts into the role
|
|
26
|
+
via slot="header"/"footer" (the drawer-ui pattern), so e.g. a <section slot="header">
|
|
27
|
+
becomes a pinned rail rather than the scroll body. Fixed height, never scroll. */
|
|
28
|
+
:scope > :is(header, footer, [slot="header"], [slot="footer"]) {
|
|
27
29
|
flex: 0 0 auto;
|
|
28
30
|
min-block-size: 0;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
/* The single scroll region
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
/* The single scroll region — native <section> OR slot="body", minus anything that
|
|
34
|
+
opted into a rail role above. `min-block-size: 0` lets the flex item shrink below
|
|
35
|
+
its content's intrinsic size — the flex-scroll gotcha that makes overflow:auto
|
|
36
|
+
actually scroll inside a column. */
|
|
37
|
+
:scope > :is(section, [slot="body"]):not([slot="header"]):not([slot="footer"]) {
|
|
35
38
|
flex: 1 1 auto;
|
|
36
39
|
min-block-size: 0;
|
|
37
40
|
overflow: auto;
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
chrome-less app-shell skeleton. A flex column that fills its parent's
|
|
4
4
|
block size: a native <header> child pins to the top, a <footer> child
|
|
5
5
|
pins to the bottom, and the <section> child scrolls between them (the
|
|
6
|
-
only region with overflow).
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
only region with overflow). Regions are positioned by tag + DOM order, OR any
|
|
7
|
+
element can take a region role via slot="header|body|footer" (a CSS [slot] match,
|
|
8
|
+
not native projection — ADR-0033) — e.g. <section slot="header"> as a pinned rail.
|
|
9
|
+
All three are OPTIONAL, so the common shape is just <section> + <footer>. Use for
|
|
10
|
+
tab / panel content
|
|
9
11
|
where actions stay visible while the body scrolls. Distinct from <card-ui>
|
|
10
12
|
(adds border + elevation + a rich header grid), <drawer-ui> / <modal-ui>
|
|
11
13
|
(add a backdrop + dismiss), and the page shells (<admin-page> / <page-ui>) —
|
|
@@ -11,9 +11,11 @@ description: |
|
|
|
11
11
|
chrome-less app-shell skeleton. A flex column that fills its parent's
|
|
12
12
|
block size: a native <header> child pins to the top, a <footer> child
|
|
13
13
|
pins to the bottom, and the <section> child scrolls between them (the
|
|
14
|
-
only region with overflow).
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
only region with overflow). Regions are positioned by tag + DOM order, OR any
|
|
15
|
+
element can take a region role via slot="header|body|footer" (a CSS [slot] match,
|
|
16
|
+
not native projection — ADR-0033) — e.g. <section slot="header"> as a pinned rail.
|
|
17
|
+
All three are OPTIONAL, so the common shape is just <section> + <footer>. Use for
|
|
18
|
+
tab / panel content
|
|
17
19
|
where actions stay visible while the body scrolls. Distinct from <card-ui>
|
|
18
20
|
(adds border + elevation + a rich header grid), <drawer-ui> / <modal-ui>
|
|
19
21
|
(add a backdrop + dismiss), and the page shells (<admin-page> / <page-ui>) —
|
|
@@ -33,8 +35,8 @@ a2ui:
|
|
|
33
35
|
rules:
|
|
34
36
|
- rule: 'Use <frame-ui> for a scroll-body-with-pinned-footer panel — the <section> scrolls; <header> / <footer> stay fixed.'
|
|
35
37
|
reason: 'The chrome-less app-shell frame.'
|
|
36
|
-
- rule: 'Regions are native <header> / <section> / <footer>
|
|
37
|
-
reason: 'Light
|
|
38
|
+
- rule: 'Regions are positioned by tag + DOM order (native <header> / <section> / <footer>) OR by a role slot: slot="header"/"footer" pins ANY element as a rail, slot="body" makes it the scroll region (e.g. <section slot="header"> is a pinned rail). The native tag is the 90% sugar; reach for the slot when the element you want differs from the region role.'
|
|
39
|
+
reason: 'CSS matches [slot=…] in Light DOM (ADR-0033, no native projection) — the same role-slot pattern as drawer-ui.'
|
|
38
40
|
- rule: 'Most panels need only <section> + <footer>; add <header> only when the panel has its own title or toolbar.'
|
|
39
41
|
reason: 'Header is optional.'
|
|
40
42
|
- rule: 'For a bordered/elevated surface use <card-ui>; for an overlay use <drawer-ui> / <modal-ui>; for routed page layout use <admin-page> / <page-ui>. frame-ui is the bare layout only.'
|
package/components/list/list.css
CHANGED
|
@@ -146,6 +146,10 @@
|
|
|
146
146
|
:scope [slot="text"] {
|
|
147
147
|
grid-column: 2;
|
|
148
148
|
grid-row: 1;
|
|
149
|
+
/* Center the title within row 1 so it aligns with the (also-centered) icon +
|
|
150
|
+
action. Without this, a full-height action button (e.g. onboarding's "Open")
|
|
151
|
+
makes row 1 taller than the title and the title top-aligns above the controls. */
|
|
152
|
+
align-self: center;
|
|
149
153
|
}
|
|
150
154
|
|
|
151
155
|
:scope [slot="description"] {
|
|
@@ -41,6 +41,15 @@ import { UIElement } from '../../core/element.js';
|
|
|
41
41
|
function dedent(src) {
|
|
42
42
|
let lines = src
|
|
43
43
|
.replace(/=""(?=[\s/>])/g, '') // boolean attr: truncate="" → truncate
|
|
44
|
+
// JSON / quote-bearing attribute values serialize as attr="…"…"…" —
|
|
45
|
+
// outerHTML escapes the inner " under the default double-quote delimiter. Re-render
|
|
46
|
+
// them single-quote-delimited (attr='…"…"…') — the clean, valid, copy-paste-able
|
|
47
|
+
// form the author actually wrote (e.g. items='[{"id":"a"}]'). Skipped when the value
|
|
48
|
+
// also contains a ' (no safe single-char delimiter — keep the escaped form).
|
|
49
|
+
.replace(/="([^"]*"[^"]*)"/g, (m, v) => {
|
|
50
|
+
const decoded = v.replace(/"/g, '"').replace(/&/g, '&');
|
|
51
|
+
return decoded.includes("'") ? m : `='${decoded}'`;
|
|
52
|
+
})
|
|
44
53
|
.replace(/\t/g, ' ')
|
|
45
54
|
.split('\n');
|
|
46
55
|
while (lines.length && lines[0].trim() === '') lines.shift();
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/ThemeProvider.json",
|
|
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=\"verse|prose\" sets the compact / long-form typographic register (adopts the\nmatching register layer; maps onto the [verse]/[prose] attribute). Each layer is\nfetched only when 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
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"theme": {
|
|
17
|
+
"description": "Named theme preset for the wrapped subtree (default, ocean, forest, sunset, lavender, rose, slate, midnight). Adopts the themes layer on demand + matches the [theme=\"…\"] hook.",
|
|
18
|
+
"type": "string",
|
|
19
|
+
"default": ""
|
|
20
|
+
},
|
|
21
|
+
"component": {
|
|
22
|
+
"const": "ThemeProvider"
|
|
23
|
+
},
|
|
24
|
+
"scale": {
|
|
25
|
+
"description": "Typographic / density register for the subtree — \"verse\" (compact) or \"prose\" (long-form). Adopts the matching register layer on demand; maps onto the [verse]/[prose] attribute (additive).",
|
|
26
|
+
"type": "string",
|
|
27
|
+
"default": ""
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"required": [
|
|
31
|
+
"component"
|
|
32
|
+
],
|
|
33
|
+
"unevaluatedProperties": false,
|
|
34
|
+
"x-adiaui": {
|
|
35
|
+
"anti_patterns": [],
|
|
36
|
+
"category": "layout",
|
|
37
|
+
"composes": [],
|
|
38
|
+
"events": {},
|
|
39
|
+
"examples": [
|
|
40
|
+
{
|
|
41
|
+
"description": "A client-mounted app root that self-provides the foundation (no head link).",
|
|
42
|
+
"a2ui": "[\n { \"id\": \"root\", \"component\": \"ThemeProvider\", \"children\": [\"panel\"] },\n { \"id\": \"panel\", \"component\": \"Frame\", \"children\": [\"body\", \"actions\"] },\n { \"id\": \"body\", \"component\": \"Section\", \"children\": [\"copy\"] },\n { \"id\": \"copy\", \"component\": \"Text\", \"variant\": \"body\", \"textContent\": \"Fully styled — no <head> stylesheet link.\" },\n { \"id\": \"actions\", \"component\": \"Footer\", \"children\": [\"go\"] },\n { \"id\": \"go\", \"component\": \"Button\", \"text\": \"Continue\", \"variant\": \"primary\" }\n]",
|
|
43
|
+
"name": "spa-root"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"keywords": [
|
|
47
|
+
"style",
|
|
48
|
+
"provider",
|
|
49
|
+
"foundation",
|
|
50
|
+
"tokens",
|
|
51
|
+
"reset",
|
|
52
|
+
"adopt",
|
|
53
|
+
"stylesheet",
|
|
54
|
+
"shell",
|
|
55
|
+
"embed",
|
|
56
|
+
"spa"
|
|
57
|
+
],
|
|
58
|
+
"name": "UIThemeProvider",
|
|
59
|
+
"related": [
|
|
60
|
+
"Frame",
|
|
61
|
+
"Card"
|
|
62
|
+
],
|
|
63
|
+
"slots": {},
|
|
64
|
+
"states": [
|
|
65
|
+
{
|
|
66
|
+
"description": "Default — foundation adopted into the document; children rendered.",
|
|
67
|
+
"name": "idle"
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"status": "experimental",
|
|
71
|
+
"synonyms": {
|
|
72
|
+
"foundation": [
|
|
73
|
+
"foundation",
|
|
74
|
+
"tokens",
|
|
75
|
+
"styles"
|
|
76
|
+
],
|
|
77
|
+
"provider": [
|
|
78
|
+
"provider",
|
|
79
|
+
"root",
|
|
80
|
+
"host"
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
"tag": "theme-provider",
|
|
84
|
+
"tokens": {},
|
|
85
|
+
"traits": [],
|
|
86
|
+
"version": 1
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Non-side-effect class export for `<theme-provider>`.
|
|
3
|
+
*
|
|
4
|
+
* Importing this file gives you the class (and adopts the foundation as a
|
|
5
|
+
* module-eval side effect) without auto-registering the tag. The auto-register
|
|
6
|
+
* path is `@adia-ai/web-components/components/theme-provider` (which imports this
|
|
7
|
+
* file + calls `defineIfFree()`).
|
|
8
|
+
*
|
|
9
|
+
* `<theme-provider>` — the foundation-providing wrapper. Adopt the AdiaUI
|
|
10
|
+
* foundation (design tokens + resets + page-frame + every primitive's CSS) into
|
|
11
|
+
* the document from anywhere in the DOM, so a surface renders fully-styled
|
|
12
|
+
* WITHOUT a hand-wired `<link rel="stylesheet">` in `<head>`. Layout-transparent
|
|
13
|
+
* (`display: contents`): the element owns no box; children lay out as if it
|
|
14
|
+
* weren't there.
|
|
15
|
+
*
|
|
16
|
+
* Mechanism: imports the constructable-stylesheet twin of `web-components.min.css`
|
|
17
|
+
* — byte-identical to the CDN bundle (emitted from the same buffer by
|
|
18
|
+
* `scripts/build/bundle-css.mjs`) — and adopts it once into
|
|
19
|
+
* `document.adoptedStyleSheets`, deduped by sheet identity. Adoption fires at
|
|
20
|
+
* module evaluation (the earliest point), so importing the element provides the
|
|
21
|
+
* foundation before the body paints in the common case.
|
|
22
|
+
*
|
|
23
|
+
* Coexists with the render-blocking `<link>` path — both deliver the same bytes.
|
|
24
|
+
* Use a `<link>` (→ the CDN `web-components.min.css`) for multi-page / top-level
|
|
25
|
+
* surfaces (cacheable across navigations, zero flash); use `<theme-provider>`
|
|
26
|
+
* for SPA roots, embedded apps, and dynamic mounts where you don't control
|
|
27
|
+
* `<head>` (e.g. `<embed-shell>`, an A2UI surface, a micro-frontend).
|
|
28
|
+
*
|
|
29
|
+
* Scope (v1): the provider supplies the FOUNDATION only — design tokens, resets,
|
|
30
|
+
* page-frame, and every primitive's CSS. OS light/dark resolves automatically
|
|
31
|
+
* (the tokens are `light-dark()`-based). Named themes (`[theme]`) and the
|
|
32
|
+
* `verse` / `prose` context registers live in OPT-IN layers (themes.css /
|
|
33
|
+
* verse.css / prose.css) that are NOT in the foundation bundle, so setting
|
|
34
|
+
* `theme` / `verse` on the wrapper does nothing until those layers are also
|
|
35
|
+
* adopted — a planned `theme=` / `verse` provider option (the token-root selector
|
|
36
|
+
* is pre-wired for it; see .brain/notes/theme-provider-design-2026-06-04.md).
|
|
37
|
+
*
|
|
38
|
+
* Deliberately NOT in the all-in-one `@adia-ai/web-components` barrel — it's
|
|
39
|
+
* opt-in infra (it carries the whole foundation). Import it explicitly:
|
|
40
|
+
* `import '@adia-ai/web-components/components/theme-provider';`
|
|
41
|
+
*
|
|
42
|
+
* @see ../../USAGE.md · .brain/notes/theme-provider-design-2026-06-04.md
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
import { UIElement } from '../../core/element.js';
|
|
46
|
+
import constructFoundationSheet from '../../dist/web-components.sheet.js';
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Adopt the foundation sheet into the document exactly once. Idempotent across
|
|
50
|
+
* any number of `<theme-provider>` instances (dedup by sheet identity). No-ops in
|
|
51
|
+
* a non-DOM context — `constructFoundationSheet()` returns `null` on SSR/Node.
|
|
52
|
+
*/
|
|
53
|
+
function provideFoundation() {
|
|
54
|
+
const sheet = constructFoundationSheet();
|
|
55
|
+
if (!sheet) return;
|
|
56
|
+
if (!document.adoptedStyleSheets.includes(sheet)) {
|
|
57
|
+
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Opt-in context registers — themes (named `[theme]` presets), and the `verse` /
|
|
62
|
+
// `prose` `scale` registers. Each is its own constructable-sheet twin (built by
|
|
63
|
+
// scripts/build/bundle-css.mjs, byte-identical to its .min.css). Adopted on demand
|
|
64
|
+
// the first time a provider needs one, deduped by sheet identity. Dynamic-imported
|
|
65
|
+
// (static paths, so bundlers can code-split) so the element stays lean — a provider
|
|
66
|
+
// that does no theming never pulls these in.
|
|
67
|
+
const TWIN_LOADED = { themes: false, verse: false, prose: false };
|
|
68
|
+
function loadTwin(name) {
|
|
69
|
+
switch (name) {
|
|
70
|
+
case 'themes': return import('../../dist/themes.sheet.js');
|
|
71
|
+
case 'verse': return import('../../dist/verse.sheet.js');
|
|
72
|
+
case 'prose': return import('../../dist/prose.sheet.js');
|
|
73
|
+
default: return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function ensureTwin(name) {
|
|
77
|
+
if (TWIN_LOADED[name]) return;
|
|
78
|
+
const p = loadTwin(name);
|
|
79
|
+
if (!p) return;
|
|
80
|
+
TWIN_LOADED[name] = true;
|
|
81
|
+
p.then((mod) => {
|
|
82
|
+
const sheet = mod?.default?.();
|
|
83
|
+
if (sheet && !document.adoptedStyleSheets.includes(sheet)) {
|
|
84
|
+
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
|
|
85
|
+
}
|
|
86
|
+
}).catch(() => { TWIN_LOADED[name] = false; }); // allow a later retry on failure
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Adopt the base foundation as early as this module evaluates — before any element
|
|
90
|
+
// connects, before the body paints when imported from <head>. Importing the
|
|
91
|
+
// provider IS the act of providing the foundation, wherever the element lands.
|
|
92
|
+
provideFoundation();
|
|
93
|
+
|
|
94
|
+
export class UIThemeProvider extends UIElement {
|
|
95
|
+
static properties = {
|
|
96
|
+
// Named theme preset (ocean / forest / slate / …). Reflected, so the attribute
|
|
97
|
+
// — which IS the `[theme="…"]` CSS hook in themes.css — tracks the property.
|
|
98
|
+
theme: { type: String, reflect: true },
|
|
99
|
+
// Typographic/density register: "verse" (compact) | "prose" (long-form).
|
|
100
|
+
// Mapped onto the existing `[verse]` / `[prose]` attribute below (additive —
|
|
101
|
+
// the register CSS is untouched), so every register rule incl. `[size]`
|
|
102
|
+
// sub-tiers applies for free.
|
|
103
|
+
scale: { type: String, reflect: true },
|
|
104
|
+
};
|
|
105
|
+
static template = () => null;
|
|
106
|
+
|
|
107
|
+
connected() {
|
|
108
|
+
// Layout-transparent + invisible to the a11y tree (the template-engine /
|
|
109
|
+
// traits-host convention). Set imperatively so it holds even in the frame
|
|
110
|
+
// before the adopted foundation's own `display: contents` rule applies.
|
|
111
|
+
this.style.display = 'contents';
|
|
112
|
+
if (!this.hasAttribute('role')) this.setAttribute('role', 'presentation');
|
|
113
|
+
provideFoundation(); // belt-and-suspenders for late registration
|
|
114
|
+
this.#applyContext();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
updated() {
|
|
118
|
+
this.#applyContext();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Adopt the opt-in twins for the current theme/scale, and map `scale` onto the
|
|
122
|
+
// existing register attribute. Idempotent (safe to call on every update).
|
|
123
|
+
#applyContext() {
|
|
124
|
+
// `theme="ocean"` already matches `[theme="ocean"]` (the attr is on the host);
|
|
125
|
+
// adopt themes.sheet.js so those preset rules exist in the document.
|
|
126
|
+
if (this.theme) ensureTwin('themes');
|
|
127
|
+
|
|
128
|
+
const scale = this.scale;
|
|
129
|
+
this.toggleAttribute('verse', scale === 'verse');
|
|
130
|
+
this.toggleAttribute('prose', scale === 'prose');
|
|
131
|
+
if (scale === 'verse') ensureTwin('verse');
|
|
132
|
+
else if (scale === 'prose') ensureTwin('prose');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<theme-provider>` — layout-transparent foundation host.
|
|
3
|
+
*
|
|
4
|
+
* The element exists to adopt the AdiaUI foundation into the document (see
|
|
5
|
+
* theme-provider.class.js); it owns no layout. `display: contents` removes its
|
|
6
|
+
* box so children lay out as if the wrapper weren't there. The class also sets
|
|
7
|
+
* this imperatively on connect — belt-and-suspenders for the frame before this
|
|
8
|
+
* adopted rule applies.
|
|
9
|
+
*
|
|
10
|
+
* NOTE: a `>` child combinator from an ancestor does NOT pierce a
|
|
11
|
+
* `display: contents` wrapper (FB-53) — keep `<theme-provider>` at/near the
|
|
12
|
+
* mount root, not spliced mid-layout-chain.
|
|
13
|
+
*/
|
|
14
|
+
@scope (theme-provider) {
|
|
15
|
+
:where(:scope) {
|
|
16
|
+
display: contents;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<theme-provider>` — Foundation-providing wrapper — adopts the AdiaUI foundation (design tokens +
|
|
3
|
+
resets + page-frame + every primitive's CSS) into the document from anywhere
|
|
4
|
+
in the DOM, so a surface renders fully-styled WITHOUT a hand-wired
|
|
5
|
+
<link rel="stylesheet"> in <head>. Layout-transparent (display: contents): the
|
|
6
|
+
element owns no box; children lay out as if it weren't there.
|
|
7
|
+
|
|
8
|
+
Mechanism: it imports the constructable-stylesheet twin of web-components.min.css
|
|
9
|
+
(byte-identical to the CDN bundle, emitted from the same build buffer) and
|
|
10
|
+
adopts it once into document.adoptedStyleSheets, deduped — adoption fires at
|
|
11
|
+
module load, before paint. Coexists with the render-blocking <link> path; both
|
|
12
|
+
deliver the same bytes. Use a <link> (-> the CDN web-components.min.css) for
|
|
13
|
+
multi-page / top-level surfaces (cacheable across navigations, zero flash); use
|
|
14
|
+
<theme-provider> for SPA roots, embedded apps, and dynamic mounts where you do
|
|
15
|
+
not control <head> (e.g. <embed-shell>, an A2UI surface, a micro-frontend).
|
|
16
|
+
|
|
17
|
+
Theming: the base foundation is OS light/dark via light-dark() tokens. Two opt-in
|
|
18
|
+
attributes adopt their layer on demand — theme="ocean|forest|slate|…" applies a
|
|
19
|
+
named preset (adopts the themes layer; matches the [theme] hook) and
|
|
20
|
+
scale="verse|prose" sets the compact / long-form typographic register (adopts the
|
|
21
|
+
matching register layer; maps onto the [verse]/[prose] attribute). Each layer is
|
|
22
|
+
fetched only when its attribute is set, so a bare provider stays lean.
|
|
23
|
+
Opt-in infra: NOT in the all-in-one @adia-ai/web-components barrel (it carries
|
|
24
|
+
the whole foundation); import @adia-ai/web-components/components/theme-provider
|
|
25
|
+
explicitly. Distinct from <frame-ui> (a layout skeleton, owns no CSS delivery)
|
|
26
|
+
and the page shells (chrome over the same foundation).
|
|
27
|
+
|
|
28
|
+
*
|
|
29
|
+
* @see https://ui-kit.exe.xyz/site/components/theme-provider
|
|
30
|
+
*
|
|
31
|
+
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
32
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
33
|
+
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
34
|
+
* regenerate; or hand-author this file fully if rich event types are
|
|
35
|
+
* needed beyond what the yaml `events:` block can express.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import { UIElement } from '../../core/element.js';
|
|
39
|
+
|
|
40
|
+
export class UIThemeProvider extends UIElement {
|
|
41
|
+
/** Named theme preset for the wrapped subtree (default, ocean, forest, sunset, lavender, rose, slate, midnight). Adopts the themes layer on demand + matches the [theme="…"] hook. */
|
|
42
|
+
theme: string;
|
|
43
|
+
/** Typographic / density register for the subtree — "verse" (compact) or "prose" (long-form). Adopts the matching register layer on demand; maps onto the [verse]/[prose] attribute (additive). */
|
|
44
|
+
scale: string;
|
|
45
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<theme-provider>` — auto-registers the tag on import, and adopts the AdiaUI
|
|
3
|
+
* foundation into the document (the side effect lives in the class module).
|
|
4
|
+
*
|
|
5
|
+
* import '@adia-ai/web-components/components/theme-provider';
|
|
6
|
+
* <theme-provider> … your app … </theme-provider>
|
|
7
|
+
*
|
|
8
|
+
* Opt-in infra: NOT pulled by the `@adia-ai/web-components` barrel (it carries
|
|
9
|
+
* the full foundation CSS as a constructable sheet). For the class without
|
|
10
|
+
* auto-registering the tag, import the `class` subpath:
|
|
11
|
+
*
|
|
12
|
+
* import { UIThemeProvider } from '@adia-ai/web-components/components/theme-provider/class';
|
|
13
|
+
*
|
|
14
|
+
* @see ../../USAGE.md#registration--auto-vs-explicit
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { defineIfFree } from '../../core/register.js';
|
|
18
|
+
import { UIThemeProvider } from './theme-provider.class.js';
|
|
19
|
+
|
|
20
|
+
defineIfFree('theme-provider', UIThemeProvider);
|
|
21
|
+
|
|
22
|
+
export { UIThemeProvider };
|