@asteby/metacore-theme 2.21.0 → 2.25.0

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/README.md CHANGED
@@ -66,6 +66,37 @@ the brand painted by `applyBranding`. Import it after your tokens:
66
66
  It includes a near-opaque fallback for browsers without `backdrop-filter`
67
67
  and for `prefers-reduced-transparency`.
68
68
 
69
+ #### Host chrome and mobile floating panel (optional variables)
70
+
71
+ A host with fixed chrome around the shell publishes its sizes on `:root`. All
72
+ variables are optional and default to `0`/flat: without them the compiled CSS
73
+ behaves exactly as before.
74
+
75
+ | Variable | Default | Effect |
76
+ |---|---|---|
77
+ | `--app-topbar-h` | `0px` | Fixed top bar: pushes the inset (and `@asteby/metacore-ui` `Sidebar`) down |
78
+ | `--app-notice-h` | `0px` | Notice strip under the top bar (0 when hidden) |
79
+ | `--app-bottombar-h` | `0px` | Bottom dock on mobile: bottom margin of the inset and the mobile sidebar sheet |
80
+ | `--glass-inset-max-height` | `none` | Cap for the inset when the wrapper is not height-bound, e.g. `calc(100svh - var(--app-topbar-h) - var(--app-notice-h) - 1rem)` |
81
+ | `--glass-mobile-gutter` | `0px` | Margin around the inset on phones (e.g. `0.5rem`) |
82
+ | `--glass-mobile-radius` | `0px` | Corner radius of the inset on phones (e.g. `var(--glass-radius)`) |
83
+ | `--glass-mobile-border-width` | `0px` | Rim width on phones (e.g. `1px`) |
84
+ | `--glass-mobile-shadow` | `none` | Shadow on phones (e.g. `var(--glass-highlight), var(--glass-shadow)`) |
85
+
86
+ ```css
87
+ :root {
88
+ --app-topbar-h: 3rem;
89
+ --app-bottombar-h: 4rem; /* 0 from sm up if the dock is mobile-only */
90
+ --glass-mobile-gutter: 0.5rem;
91
+ --glass-mobile-radius: var(--glass-radius);
92
+ --glass-mobile-border-width: 1px;
93
+ --glass-mobile-shadow: var(--glass-highlight), var(--glass-shadow);
94
+ }
95
+ ```
96
+
97
+ An inset with no sidebar sibling (chat-like screens) floats on desktop with
98
+ `<SidebarInset data-glass-float>`.
99
+
69
100
  ## Usage from JS/TS
70
101
 
71
102
  For programmatic access (Storybook, charts, PDF):
@@ -93,6 +124,33 @@ The bundled `<ThemeProvider>` (light/dark/system, cookie-persisted) is the
93
124
  recommended entry; consumer apps can drop their local copies and use
94
125
  `useTheme()` for the toggle UI.
95
126
 
127
+ ## No flash on reload
128
+
129
+ `<ThemeProvider>` stores what `<html>` ends up painting — light/dark, the
130
+ `data-ui-*` attributes (theme pack, font, density), `font-*` classes, inline
131
+ custom properties (brand color) and the branding surfaces stylesheet. An inline
132
+ script restores it before the first frame, so a returning visitor never sees
133
+ the defaults first. First visits follow `prefers-color-scheme`. Transitions stay
134
+ off until the providers have mounted (`data-boot-transition` opts an element
135
+ out, e.g. a splash that fades).
136
+
137
+ ```ts
138
+ // vite.config.ts
139
+ import { themeBootScript } from '@asteby/metacore-theme/boot'
140
+
141
+ plugins: [
142
+ {
143
+ name: 'metacore-theme-boot',
144
+ transformIndexHtml: () => [
145
+ { tag: 'script', children: themeBootScript(), injectTo: 'head-prepend' },
146
+ ],
147
+ },
148
+ ]
149
+ ```
150
+
151
+ `@asteby/metacore-theme/boot` has no React import, so it loads in a Node
152
+ config. Pass `persistBoot={false}` to the provider to opt out.
153
+
96
154
  ## License
97
155
 
98
156
  Apache-2.0
package/dist/boot.d.ts ADDED
@@ -0,0 +1,75 @@
1
+ export type ThemeMode = 'light' | 'dark';
2
+ /** localStorage entry holding the last resolved theme of this origin. */
3
+ export declare const THEME_BOOT_STORAGE_KEY = "mc:theme-boot:v1";
4
+ /** Cookie the ThemeProvider stores the user's light/dark/system choice in. */
5
+ export declare const THEME_MODE_COOKIE = "metacore-ui-theme";
6
+ /**
7
+ * Class on <html> while the boot theme settles. Transitions are off under
8
+ * it, so the providers re-applying the same theme can't animate anything.
9
+ */
10
+ export declare const THEME_BOOTING_CLASS = "mc-theme-booting";
11
+ /** Elements (and their subtree) that keep their transitions during boot. */
12
+ export declare const THEME_BOOT_TRANSITION_ATTRIBUTE = "data-boot-transition";
13
+ /** What one mode paints: inline custom properties and generated stylesheets. */
14
+ export interface ThemeBootModeSnapshot {
15
+ vars: Record<string, string>;
16
+ styles: Record<string, string>;
17
+ /** attrs + classes it was captured under; another value makes it stale. */
18
+ base: string;
19
+ }
20
+ export interface ThemeBootSnapshot {
21
+ v: 1;
22
+ attrs: Record<string, string>;
23
+ classes: string[];
24
+ modes: Partial<Record<ThemeMode, ThemeBootModeSnapshot>>;
25
+ }
26
+ export interface ThemeBootScriptOptions {
27
+ storageKey?: string;
28
+ modeCookie?: string;
29
+ /** Mode for a first visit with no cookie. `system` follows the OS. */
30
+ defaultMode?: ThemeMode | 'system';
31
+ /** Longest the transition lock may last if the app never releases it. */
32
+ maxLockMs?: number;
33
+ }
34
+ export interface ThemeBootWatchOptions {
35
+ storageKey?: string;
36
+ /** <html> attributes to keep. Default: every `data-ui-*`. */
37
+ attributePattern?: RegExp;
38
+ /** <html> classes to keep, besides light/dark. Default: `font-*`. */
39
+ classPattern?: RegExp;
40
+ /** <style id> elements whose text is kept per mode. */
41
+ styleIds?: string[];
42
+ }
43
+ /** The stylesheet the metacore branding provider generates. */
44
+ export declare const BRANDING_STYLE_ID = "metacore-branding-surfaces";
45
+ /**
46
+ * Inline script (no <script> tag) that restores the stored theme. Put it
47
+ * first in <head>, before the stylesheets, as a classic (not module) script.
48
+ */
49
+ export declare function themeBootScript(options?: ThemeBootScriptOptions): string;
50
+ /**
51
+ * Turns transitions back on once the app painted with its theme. Waits two
52
+ * frames so the providers' first effects commit without animating.
53
+ */
54
+ export declare function releaseThemeBoot(): void;
55
+ /** Reads what <html> paints right now. */
56
+ export declare function captureThemeBoot(options?: ThemeBootWatchOptions): {
57
+ mode: ThemeMode;
58
+ attrs: Record<string, string>;
59
+ classes: string[];
60
+ vars: Record<string, string>;
61
+ styles: Record<string, string>;
62
+ };
63
+ /**
64
+ * Stores the current theme for the next load. The other mode's entry is
65
+ * kept only while the pack/font/density it was taken under still holds.
66
+ * Returns false when nothing changed.
67
+ */
68
+ export declare function persistThemeBoot(options?: ThemeBootWatchOptions): boolean;
69
+ /**
70
+ * Keeps the stored theme in sync with <html>: any provider that changes a
71
+ * class, a data-ui-* attribute, an inline custom property or a watched
72
+ * stylesheet triggers one write per task. Returns the unsubscribe.
73
+ */
74
+ export declare function watchThemeBoot(options?: ThemeBootWatchOptions): () => void;
75
+ //# sourceMappingURL=boot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boot.d.ts","sourceRoot":"","sources":["../src/boot.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAA;AAExC,yEAAyE;AACzE,eAAO,MAAM,sBAAsB,qBAAqB,CAAA;AACxD,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,sBAAsB,CAAA;AACpD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,qBAAqB,CAAA;AACrD,4EAA4E;AAC5E,eAAO,MAAM,+BAA+B,yBAAyB,CAAA;AAErE,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,iBAAiB;IAChC,CAAC,EAAE,CAAC,CAAA;IACJ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC,CAAA;CACzD;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sEAAsE;IACtE,WAAW,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;IAClC,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,+DAA+D;AAC/D,eAAO,MAAM,iBAAiB,+BAA+B,CAAA;AA0D7D;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,MAAM,CAU5E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAKvC;AAMD,0CAA0C;AAC1C,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,qBAA0B,GAAG;IACrE,IAAI,EAAE,SAAS,CAAA;IACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC/B,CAoBA;AAYD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAoB7E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,MAAM,IAAI,CAiC9E"}
package/dist/boot.js ADDED
@@ -0,0 +1,218 @@
1
+ // Paints the theme a returning visitor last saw before the first frame.
2
+ //
3
+ // Every theme provider (dark/light, theme pack, font, density, brand color)
4
+ // resolves after the bundle runs, some after a fetch. Until then the page
5
+ // painted the defaults and then switched: a visible flash on every reload.
6
+ // The providers keep writing <html> as they do today; `watchThemeBoot`
7
+ // stores the result, and `themeBootScript()` is a small inline script for
8
+ // the top of <head> that puts it back synchronously, before any CSS or paint.
9
+ //
10
+ // This module has no React import so a Vite config can build the snippet.
11
+ /** localStorage entry holding the last resolved theme of this origin. */
12
+ export const THEME_BOOT_STORAGE_KEY = 'mc:theme-boot:v1';
13
+ /** Cookie the ThemeProvider stores the user's light/dark/system choice in. */
14
+ export const THEME_MODE_COOKIE = 'metacore-ui-theme';
15
+ /**
16
+ * Class on <html> while the boot theme settles. Transitions are off under
17
+ * it, so the providers re-applying the same theme can't animate anything.
18
+ */
19
+ export const THEME_BOOTING_CLASS = 'mc-theme-booting';
20
+ /** Elements (and their subtree) that keep their transitions during boot. */
21
+ export const THEME_BOOT_TRANSITION_ATTRIBUTE = 'data-boot-transition';
22
+ /** The stylesheet the metacore branding provider generates. */
23
+ export const BRANDING_STYLE_ID = 'metacore-branding-surfaces';
24
+ const DEFAULT_ATTRIBUTES = /^data-ui-/;
25
+ const DEFAULT_CLASSES = /^font-/;
26
+ // Serialized into the inline script: no reference to anything outside it,
27
+ // and ES5 syntax only, since it runs before any polyfill.
28
+ function bootTheme(o) {
29
+ var d = document;
30
+ var root = d.documentElement;
31
+ var release = function () {
32
+ root.classList.remove(o.lockClass);
33
+ };
34
+ try {
35
+ var lock = d.createElement('style');
36
+ lock.textContent =
37
+ 'html.' + o.lockClass + ' *:not([' + o.allowAttr + ']):not([' + o.allowAttr + '] *),' +
38
+ 'html.' + o.lockClass + ' *::before,html.' + o.lockClass + ' *::after' +
39
+ '{transition:none!important}';
40
+ d.head.appendChild(lock);
41
+ root.classList.add(o.lockClass);
42
+ setTimeout(release, o.maxLockMs);
43
+ var m = d.cookie.match(new RegExp('(?:^|; )' + encodeURIComponent(o.modeCookie) + '=([^;]*)'));
44
+ var pref = m ? decodeURIComponent(m[1]) : o.defaultMode;
45
+ var dark = pref === 'dark' ||
46
+ (pref !== 'light' && !!window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
47
+ var mode = dark ? 'dark' : 'light';
48
+ root.classList.remove(dark ? 'light' : 'dark');
49
+ root.classList.add(mode);
50
+ var raw = localStorage.getItem(o.storageKey);
51
+ var s = raw ? JSON.parse(raw) : null;
52
+ if (!s || s.v !== 1)
53
+ return;
54
+ var k;
55
+ for (k in s.attrs) {
56
+ // Only data-* from storage: never an event-handler attribute.
57
+ if (/^data-[\w-]+$/.test(k) && typeof s.attrs[k] === 'string')
58
+ root.setAttribute(k, s.attrs[k]);
59
+ }
60
+ for (var i = 0; i < (s.classes || []).length; i++) {
61
+ if (typeof s.classes[i] === 'string')
62
+ root.classList.add(s.classes[i]);
63
+ }
64
+ var ms = s.modes && s.modes[mode];
65
+ if (!ms)
66
+ return;
67
+ for (k in ms.vars) {
68
+ if (/^--[\w-]+$/.test(k))
69
+ root.style.setProperty(k, String(ms.vars[k]));
70
+ }
71
+ for (k in ms.styles) {
72
+ var el = d.getElementById(k) || d.head.appendChild(d.createElement('style'));
73
+ el.id = k;
74
+ el.textContent = String(ms.styles[k]);
75
+ }
76
+ }
77
+ catch (e) {
78
+ // Storage blocked or corrupt entry: the providers paint as before.
79
+ }
80
+ }
81
+ /**
82
+ * Inline script (no <script> tag) that restores the stored theme. Put it
83
+ * first in <head>, before the stylesheets, as a classic (not module) script.
84
+ */
85
+ export function themeBootScript(options = {}) {
86
+ const config = {
87
+ storageKey: options.storageKey ?? THEME_BOOT_STORAGE_KEY,
88
+ modeCookie: options.modeCookie ?? THEME_MODE_COOKIE,
89
+ defaultMode: options.defaultMode ?? 'system',
90
+ maxLockMs: options.maxLockMs ?? 8000,
91
+ lockClass: THEME_BOOTING_CLASS,
92
+ allowAttr: THEME_BOOT_TRANSITION_ATTRIBUTE,
93
+ };
94
+ return `(${bootTheme.toString().replace(/\n\s+/g, '\n')})(${JSON.stringify(config)});`;
95
+ }
96
+ /**
97
+ * Turns transitions back on once the app painted with its theme. Waits two
98
+ * frames so the providers' first effects commit without animating.
99
+ */
100
+ export function releaseThemeBoot() {
101
+ if (typeof document === 'undefined')
102
+ return;
103
+ const done = () => document.documentElement.classList.remove(THEME_BOOTING_CLASS);
104
+ if (typeof requestAnimationFrame !== 'function')
105
+ return done();
106
+ requestAnimationFrame(() => requestAnimationFrame(done));
107
+ }
108
+ function currentMode(root) {
109
+ return root.classList.contains('dark') ? 'dark' : 'light';
110
+ }
111
+ /** Reads what <html> paints right now. */
112
+ export function captureThemeBoot(options = {}) {
113
+ const root = document.documentElement;
114
+ const attrPattern = options.attributePattern ?? DEFAULT_ATTRIBUTES;
115
+ const classPattern = options.classPattern ?? DEFAULT_CLASSES;
116
+ const attrs = {};
117
+ for (const attr of Array.from(root.attributes)) {
118
+ if (attrPattern.test(attr.name))
119
+ attrs[attr.name] = attr.value;
120
+ }
121
+ const classes = Array.from(root.classList).filter((c) => classPattern.test(c)).sort();
122
+ const vars = {};
123
+ for (let i = 0; i < root.style.length; i++) {
124
+ const prop = root.style.item(i);
125
+ if (prop.startsWith('--'))
126
+ vars[prop] = root.style.getPropertyValue(prop).trim();
127
+ }
128
+ const styles = {};
129
+ for (const id of options.styleIds ?? [BRANDING_STYLE_ID]) {
130
+ const el = document.getElementById(id);
131
+ if (el instanceof HTMLStyleElement && el.textContent)
132
+ styles[id] = el.textContent;
133
+ }
134
+ return { mode: currentMode(root), attrs, classes, vars, styles };
135
+ }
136
+ function readSnapshot(key) {
137
+ try {
138
+ const raw = localStorage.getItem(key);
139
+ const parsed = raw ? JSON.parse(raw) : null;
140
+ return parsed && parsed.v === 1 ? parsed : null;
141
+ }
142
+ catch {
143
+ return null;
144
+ }
145
+ }
146
+ /**
147
+ * Stores the current theme for the next load. The other mode's entry is
148
+ * kept only while the pack/font/density it was taken under still holds.
149
+ * Returns false when nothing changed.
150
+ */
151
+ export function persistThemeBoot(options = {}) {
152
+ if (typeof document === 'undefined')
153
+ return false;
154
+ const key = options.storageKey ?? THEME_BOOT_STORAGE_KEY;
155
+ const now = captureThemeBoot(options);
156
+ const base = JSON.stringify([now.attrs, now.classes]);
157
+ const prev = readSnapshot(key);
158
+ const modes = {};
159
+ const other = now.mode === 'dark' ? 'light' : 'dark';
160
+ const kept = prev?.modes[other];
161
+ if (kept && kept.base === base)
162
+ modes[other] = kept;
163
+ modes[now.mode] = { vars: now.vars, styles: now.styles, base };
164
+ const next = { v: 1, attrs: now.attrs, classes: now.classes, modes };
165
+ const serialized = JSON.stringify(next);
166
+ try {
167
+ if (localStorage.getItem(key) === serialized)
168
+ return false;
169
+ localStorage.setItem(key, serialized);
170
+ return true;
171
+ }
172
+ catch {
173
+ return false;
174
+ }
175
+ }
176
+ /**
177
+ * Keeps the stored theme in sync with <html>: any provider that changes a
178
+ * class, a data-ui-* attribute, an inline custom property or a watched
179
+ * stylesheet triggers one write per task. Returns the unsubscribe.
180
+ */
181
+ export function watchThemeBoot(options = {}) {
182
+ if (typeof document === 'undefined' || typeof MutationObserver === 'undefined') {
183
+ return () => { };
184
+ }
185
+ const styleIds = new Set(options.styleIds ?? [BRANDING_STYLE_ID]);
186
+ let scheduled = false;
187
+ const schedule = () => {
188
+ if (scheduled)
189
+ return;
190
+ scheduled = true;
191
+ setTimeout(() => {
192
+ scheduled = false;
193
+ persistThemeBoot(options);
194
+ }, 0);
195
+ };
196
+ const inWatchedStyle = (node) => {
197
+ const el = node instanceof Element ? node : node?.parentElement;
198
+ return !!el && el.tagName === 'STYLE' && styleIds.has(el.id);
199
+ };
200
+ const observer = new MutationObserver((records) => {
201
+ for (const record of records) {
202
+ if (record.target === document.documentElement && record.type === 'attributes') {
203
+ return schedule();
204
+ }
205
+ if (inWatchedStyle(record.target))
206
+ return schedule();
207
+ for (const node of Array.from(record.addedNodes)) {
208
+ if (inWatchedStyle(node))
209
+ return schedule();
210
+ }
211
+ }
212
+ });
213
+ observer.observe(document.documentElement, { attributes: true });
214
+ observer.observe(document.head, { childList: true, subtree: true, characterData: true });
215
+ schedule();
216
+ return () => observer.disconnect();
217
+ }
218
+ //# sourceMappingURL=boot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boot.js","sourceRoot":"","sources":["../src/boot.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -4,4 +4,6 @@ export { colorTokens, chartTokens, radiusTokens, shadowTokens, fontTokens, track
4
4
  export type { ThemeConfig } from './preset.js';
5
5
  export { ThemeProvider, useTheme } from './provider.js';
6
6
  export type { ThemeProviderProps, ThemeProviderState } from './provider.js';
7
+ export { themeBootScript, watchThemeBoot, persistThemeBoot, captureThemeBoot, releaseThemeBoot, THEME_BOOT_STORAGE_KEY, THEME_MODE_COOKIE, THEME_BOOTING_CLASS, THEME_BOOT_TRANSITION_ATTRIBUTE, BRANDING_STYLE_ID, } from './boot.js';
8
+ export type { ThemeMode, ThemeBootSnapshot, ThemeBootModeSnapshot, ThemeBootScriptOptions, ThemeBootWatchOptions, } from './boot.js';
7
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAChD,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,OAAO,EACL,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,EACZ,WAAW,GACZ,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACvD,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAChD,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,OAAO,EACL,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,EACZ,WAAW,GACZ,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACvD,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAE3E,OAAO,EACL,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,+BAA+B,EAC/B,iBAAiB,GAClB,MAAM,WAAW,CAAA;AAClB,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,WAAW,CAAA"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { fonts, fontFamilies } from './fonts.js';
2
2
  export { colorTokens, chartTokens, radiusTokens, shadowTokens, fontTokens, trackingTokens, motionTokens, themeConfig, } from './preset.js';
3
3
  export { ThemeProvider, useTheme } from './provider.js';
4
+ export { themeBootScript, watchThemeBoot, persistThemeBoot, captureThemeBoot, releaseThemeBoot, THEME_BOOT_STORAGE_KEY, THEME_MODE_COOKIE, THEME_BOOTING_CLASS, THEME_BOOT_TRANSITION_ATTRIBUTE, BRANDING_STYLE_ID, } from './boot.js';
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAGhD,OAAO,EACL,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,EACZ,WAAW,GACZ,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAGhD,OAAO,EACL,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,EACZ,WAAW,GACZ,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAGvD,OAAO,EACL,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,+BAA+B,EAC/B,iBAAiB,GAClB,MAAM,WAAW,CAAA"}
@@ -1,9 +1,17 @@
1
+ import { type ThemeBootWatchOptions } from './boot.js';
1
2
  type Theme = 'dark' | 'light' | 'system';
2
3
  type ResolvedTheme = Exclude<Theme, 'system'>;
3
4
  export type ThemeProviderProps = {
4
5
  children: React.ReactNode;
5
6
  defaultTheme?: Theme;
6
7
  storageKey?: string;
8
+ /**
9
+ * Stores the resolved theme of <html> for `themeBootScript()`, so the next
10
+ * load paints it before the first frame. On by default; pass options to
11
+ * change what is kept. A custom `storageKey` must also be given to the
12
+ * script as `modeCookie`.
13
+ */
14
+ persistBoot?: boolean | ThemeBootWatchOptions;
7
15
  };
8
16
  export type ThemeProviderState = {
9
17
  defaultTheme: Theme;
@@ -12,7 +20,7 @@ export type ThemeProviderState = {
12
20
  setTheme: (theme: Theme) => void;
13
21
  resetTheme: () => void;
14
22
  };
15
- export declare function ThemeProvider({ children, defaultTheme, storageKey, }: ThemeProviderProps): import("react").JSX.Element;
23
+ export declare function ThemeProvider({ children, defaultTheme, storageKey, persistBoot, }: ThemeProviderProps): import("react").JSX.Element;
16
24
  export declare function useTheme(): ThemeProviderState;
17
25
  export {};
18
26
  //# sourceMappingURL=provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAEA,KAAK,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;AACxC,KAAK,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AAM7C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,KAAK,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,EAAE,KAAK,CAAA;IACnB,aAAa,EAAE,aAAa,CAAA;IAC5B,KAAK,EAAE,KAAK,CAAA;IACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,UAAU,EAAE,MAAM,IAAI,CAAA;CACvB,CAAA;AAgCD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,YAA4B,EAC5B,UAAgC,GACjC,EAAE,kBAAkB,+BAuDpB;AAGD,wBAAgB,QAAQ,IAAI,kBAAkB,CAI7C"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,qBAAqB,EAC3B,MAAM,WAAW,CAAA;AAElB,KAAK,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;AACxC,KAAK,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AAM7C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,KAAK,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,qBAAqB,CAAA;CAC9C,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,EAAE,KAAK,CAAA;IACnB,aAAa,EAAE,aAAa,CAAA;IAC5B,KAAK,EAAE,KAAK,CAAA;IACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,UAAU,EAAE,MAAM,IAAI,CAAA;CACvB,CAAA;AAgCD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,YAA4B,EAC5B,UAAgC,EAChC,WAAkB,GACnB,EAAE,kBAAkB,+BAoEpB;AAGD,wBAAgB,QAAQ,IAAI,kBAAkB,CAI7C"}
package/dist/provider.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createContext, useContext, useEffect, useMemo, useState } from 'react';
3
+ import { THEME_MODE_COOKIE, releaseThemeBoot, watchThemeBoot, } from './boot.js';
3
4
  const DEFAULT_THEME = 'system';
4
- const DEFAULT_STORAGE_KEY = 'metacore-ui-theme';
5
+ const DEFAULT_STORAGE_KEY = THEME_MODE_COOKIE;
5
6
  const THEME_COOKIE_MAX_AGE = 60 * 60 * 24 * 365;
6
7
  const initialState = {
7
8
  defaultTheme: DEFAULT_THEME,
@@ -32,7 +33,7 @@ function clearCookie(name) {
32
33
  return;
33
34
  document.cookie = `${encodeURIComponent(name)}=; path=/; max-age=0; SameSite=Lax`;
34
35
  }
35
- export function ThemeProvider({ children, defaultTheme = DEFAULT_THEME, storageKey = DEFAULT_STORAGE_KEY, }) {
36
+ export function ThemeProvider({ children, defaultTheme = DEFAULT_THEME, storageKey = DEFAULT_STORAGE_KEY, persistBoot = true, }) {
36
37
  const [theme, _setTheme] = useState(() => readCookie(storageKey) || defaultTheme);
37
38
  const resolvedTheme = useMemo(() => {
38
39
  if (theme === 'system') {
@@ -49,8 +50,13 @@ export function ThemeProvider({ children, defaultTheme = DEFAULT_THEME, storageK
49
50
  return;
50
51
  const root = window.document.documentElement;
51
52
  const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
53
+ // Unchanged classes are left alone: every class mutation makes the
54
+ // branding provider repaint its tokens.
52
55
  const applyTheme = (current) => {
53
- root.classList.remove('light', 'dark');
56
+ const other = current === 'dark' ? 'light' : 'dark';
57
+ if (root.classList.contains(current) && !root.classList.contains(other))
58
+ return;
59
+ root.classList.remove(other);
54
60
  root.classList.add(current);
55
61
  };
56
62
  const handleChange = () => {
@@ -62,6 +68,14 @@ export function ThemeProvider({ children, defaultTheme = DEFAULT_THEME, storageK
62
68
  mediaQuery.addEventListener('change', handleChange);
63
69
  return () => mediaQuery.removeEventListener('change', handleChange);
64
70
  }, [theme, resolvedTheme]);
71
+ const bootOptions = typeof persistBoot === 'object' ? persistBoot : undefined;
72
+ useEffect(() => {
73
+ const stop = persistBoot === false ? () => { } : watchThemeBoot(bootOptions);
74
+ releaseThemeBoot();
75
+ return stop;
76
+ // Options are read once: the watcher lives as long as the app.
77
+ // eslint-disable-next-line react-hooks/exhaustive-deps
78
+ }, [persistBoot === false]);
65
79
  const setTheme = (next) => {
66
80
  writeCookie(storageKey, next, THEME_COOKIE_MAX_AGE);
67
81
  _setTheme(next);
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-theme",
3
- "version": "2.21.0",
3
+ "version": "2.25.0",
4
4
  "description": "Metacore design tokens + Tailwind 4 preset (oklch, shadows, fonts, dark mode)",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -28,6 +28,10 @@
28
28
  "types": "./dist/fonts.d.ts",
29
29
  "import": "./dist/fonts.js"
30
30
  },
31
+ "./boot": {
32
+ "types": "./dist/boot.d.ts",
33
+ "import": "./dist/boot.js"
34
+ },
31
35
  "./preset": {
32
36
  "types": "./dist/preset.d.ts",
33
37
  "import": "./dist/preset.js"
@@ -44,9 +48,11 @@
44
48
  "devDependencies": {
45
49
  "@types/react": "^19.0.0",
46
50
  "@types/react-dom": "^19.0.0",
51
+ "happy-dom": "^20.11.2",
47
52
  "react": "^19.2.4",
48
53
  "react-dom": "^19.2.4",
49
- "typescript": "^6.0.0"
54
+ "typescript": "^6.0.0",
55
+ "vitest": "^4.0.0"
50
56
  },
51
57
  "publishConfig": {
52
58
  "access": "public"
@@ -55,6 +61,7 @@
55
61
  "build": "tsc -p tsconfig.json",
56
62
  "dev": "tsc -w -p tsconfig.json",
57
63
  "typecheck": "tsc -p tsconfig.json --noEmit",
58
- "clean": "rm -rf dist"
64
+ "clean": "rm -rf dist",
65
+ "test": "vitest run"
59
66
  }
60
67
  }
package/styles/glass.css CHANGED
@@ -134,7 +134,14 @@
134
134
  background-attachment: fixed;
135
135
  }
136
136
 
137
- /* ─── Blur behind every translucent surface ─── */
137
+ /* ─── Blur behind every translucent surface ───
138
+ * A backdrop-filter makes its element the containing block of every
139
+ * position:fixed descendant, the main inset included. A fixed layer rendered
140
+ * inline inside the page (a drag overlay, a full-screen editor, a loading
141
+ * veil) is then placed and clipped by the panel, not the viewport. Render such
142
+ * layers through a portal to <body>: Radix primitives already do, and
143
+ * @asteby/metacore-runtime-react ships PortalDragOverlay for dnd-kit.
144
+ */
138
145
  [data-ui-theme='glass'] .bg-background,
139
146
  [data-ui-theme='glass'] .bg-card,
140
147
  [data-ui-theme='glass'] .bg-popover,
@@ -190,19 +197,53 @@
190
197
  width: calc(var(--sidebar-width-icon) + 1rem);
191
198
  }
192
199
 
200
+ /*
201
+ * Host chrome awareness. A host with fixed chrome around the app shell
202
+ * publishes its sizes as CSS variables on :root (all default to 0, so without
203
+ * them nothing changes):
204
+ *
205
+ * --app-topbar-h height of a fixed top bar
206
+ * --app-notice-h height of a notice strip under it (0 when hidden)
207
+ * --app-bottombar-h height of a bottom dock (mobile)
208
+ *
209
+ * The floating inset leaves them free: top margin = topbar + notice + gutter,
210
+ * bottom margin (mobile) = bottombar + gutter. Optionally cap the panel with
211
+ * --glass-inset-max-height: calc(100svh - var(--app-topbar-h) - var(--app-notice-h) - 1rem);
212
+ * when the shell wrapper is not height-bound (min-h-svh) — the SDK
213
+ * SidebarProvider is h-svh, where the panel already stretches to fit.
214
+ */
193
215
  @media (min-width: 768px) {
194
216
  [data-ui-theme='glass'] [data-slot='sidebar'][data-variant='sidebar'] ~ [data-slot='sidebar-inset'] {
195
- margin: 0.5rem;
217
+ margin: calc(var(--app-topbar-h, 0px) + var(--app-notice-h, 0px) + 0.5rem) 0.5rem 0.5rem;
196
218
  margin-inline-start: 0;
219
+ max-height: var(--glass-inset-max-height, none);
220
+ }
221
+
222
+ /*
223
+ * Opt-in: an inset with no sidebar sibling (chat-like screens) floats the
224
+ * same way with <SidebarInset data-glass-float>.
225
+ */
226
+ [data-ui-theme='glass'] [data-slot='sidebar-inset'][data-glass-float] {
227
+ margin: calc(var(--app-topbar-h, 0px) + var(--app-notice-h, 0px) + 0.5rem) 0.5rem 0.5rem;
228
+ max-height: var(--glass-inset-max-height, none);
197
229
  }
198
230
  }
199
231
 
200
232
  @media (max-width: 767px) {
201
- /* No sidebar panel beside it on phones: the inset is the whole screen. */
233
+ /*
234
+ * No sidebar panel beside it on phones: by default the inset is the whole
235
+ * screen, flat. Opt in to a floating panel with --glass-mobile-gutter
236
+ * (e.g. 0.5rem), --glass-mobile-radius (e.g. var(--glass-radius)),
237
+ * --glass-mobile-border-width (e.g. 1px) and --glass-mobile-shadow
238
+ * (e.g. var(--glass-highlight), var(--glass-shadow)).
239
+ */
202
240
  [data-ui-theme='glass'] [data-slot='sidebar-inset'] {
203
- border: 0;
204
- border-radius: 0;
205
- box-shadow: none;
241
+ margin: calc(var(--app-topbar-h, 0px) + var(--app-notice-h, 0px) + var(--glass-mobile-gutter, 0px))
242
+ var(--glass-mobile-gutter, 0px) calc(var(--app-bottombar-h, 0px) + var(--glass-mobile-gutter, 0px));
243
+ max-height: var(--glass-inset-max-height, none);
244
+ border-width: var(--glass-mobile-border-width, 0px);
245
+ border-radius: var(--glass-mobile-radius, 0px);
246
+ box-shadow: var(--glass-mobile-shadow, none);
206
247
  }
207
248
  }
208
249
 
@@ -212,7 +253,8 @@
212
253
  * gutter, over the dimmed overlay, so it takes the denser popover glass.
213
254
  */
214
255
  [data-ui-theme='glass'] [data-mobile='true'][data-slot='sidebar'] {
215
- inset-block: 0.5rem;
256
+ inset-block-start: calc(var(--app-topbar-h, 0px) + var(--app-notice-h, 0px) + 0.5rem);
257
+ inset-block-end: calc(var(--app-bottombar-h, 0px) + 0.5rem);
216
258
  inset-inline-start: 0.5rem;
217
259
  height: auto;
218
260
  background-color: var(--popover);