@ttoss/fsl-theme 2.0.0 → 2.1.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 +41 -30
- package/dist/{Types-BkaxtsMv.d.cts → Types-a_sfpbha.d.cts} +23 -11
- package/dist/{Types-BkaxtsMv.d.mts → Types-a_sfpbha.d.mts} +23 -11
- package/dist/{baseBundle-R7WyjyTw.mjs → baseBundle-CXdxj_re.mjs} +1 -1
- package/dist/{baseBundle-DdRSa5mf.cjs → baseBundle-a9LDsqYy.cjs} +1 -1
- package/dist/{createTheme--UFgVlEn.cjs → createTheme-B7H0xSVp.cjs} +95 -17
- package/dist/{createTheme-B6tVIikC.mjs → createTheme-Bm9LVQ4w.mjs} +96 -18
- package/dist/css.cjs +4 -3
- package/dist/css.d.cts +21 -2
- package/dist/css.d.mts +21 -2
- package/dist/css.mjs +4 -3
- package/dist/dataviz/index.cjs +2 -2
- package/dist/dataviz/index.d.cts +1 -1
- package/dist/dataviz/index.d.mts +1 -1
- package/dist/dataviz/index.mjs +1 -1
- package/dist/dtcg.d.cts +1 -1
- package/dist/dtcg.d.mts +1 -1
- package/dist/{index-7YL90Xqs.d.cts → index-BmZQVd3G.d.cts} +1 -1
- package/dist/{index-BmCTIOzh.d.mts → index-XZsRrMTF.d.mts} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +1 -1
- package/dist/{react-C8JrZf-b.d.mts → react-BwsjWKmo.d.mts} +46 -15
- package/dist/{react-DLB8nrXQ.cjs → react-DQErMGJz.cjs} +90 -18
- package/dist/{react-Dt7vGAVG.d.cts → react-Drr-QSuX.d.cts} +46 -15
- package/dist/react.cjs +3 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.mts +1 -1
- package/dist/react.mjs +92 -18
- package/dist/runtime-entry.cjs +1 -1
- package/dist/runtime-entry.mjs +1 -1
- package/dist/{ssrScript-MF5SIONH.cjs → ssrScript-D73WcrCM.cjs} +51 -3
- package/dist/{ssrScript-DNLlLDps.mjs → ssrScript-zDK1dqXr.mjs} +51 -3
- package/dist/themes/bruttal.cjs +2 -2
- package/dist/themes/bruttal.d.cts +1 -1
- package/dist/themes/bruttal.d.mts +1 -1
- package/dist/themes/bruttal.mjs +2 -2
- package/dist/{toCssVars-C-9yIZDR.mjs → toCssVars-CWTlp9St.mjs} +38 -3
- package/dist/{toCssVars-BseqmMcT.cjs → toCssVars-D0BR23cP.cjs} +38 -3
- package/dist/vars.cjs +7 -7
- package/dist/vars.d.cts +6 -6
- package/dist/vars.d.mts +6 -6
- package/dist/vars.mjs +7 -7
- package/dist/{withDataviz-CYRf4exT.cjs → withDataviz-DrUtw8cc.cjs} +1 -1
- package/dist/{withDataviz-BvpZJnFx.mjs → withDataviz-Ln3sEwb7.mjs} +1 -1
- package/llms.txt +6 -4
- package/package.json +1 -1
|
@@ -18,7 +18,7 @@ var resolveTheme = cfg => {
|
|
|
18
18
|
const mode = stored != null && stored.mode != null && cfg.validModes.indexOf(stored.mode) !== -1 ? stored.mode : cfg.defaultMode;
|
|
19
19
|
return {
|
|
20
20
|
mode,
|
|
21
|
-
resolvedMode: mode === "system" ? typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : mode
|
|
21
|
+
resolvedMode: mode === "system" ? typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : mode
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
24
|
|
|
@@ -34,6 +34,20 @@ var writeStorage = (key, data) => {
|
|
|
34
34
|
localStorage.setItem(key, JSON.stringify(data));
|
|
35
35
|
} catch {}
|
|
36
36
|
};
|
|
37
|
+
var createMediaQuery = () => {
|
|
38
|
+
if (typeof window.matchMedia === "function") return window.matchMedia("(prefers-color-scheme: dark)");
|
|
39
|
+
return {
|
|
40
|
+
matches: false,
|
|
41
|
+
addEventListener: () => {},
|
|
42
|
+
removeEventListener: () => {}
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* DEV-only registry of live runtimes per root element. Two runtimes writing
|
|
47
|
+
* `data-tt-*` to the same root overwrite each other (last writer wins), so
|
|
48
|
+
* the second attach warns. Entries are decremented on `destroy()`.
|
|
49
|
+
*/
|
|
50
|
+
var activeRuntimesPerRoot = /* @__PURE__ */new WeakMap();
|
|
37
51
|
/**
|
|
38
52
|
* Creates a framework-agnostic runtime that manages theme switching.
|
|
39
53
|
*
|
|
@@ -60,6 +74,11 @@ var createThemeRuntime = (config = {}) => {
|
|
|
60
74
|
} = config;
|
|
61
75
|
const listeners = /* @__PURE__ */new Set();
|
|
62
76
|
let destroyed = false;
|
|
77
|
+
if (process.env.NODE_ENV !== "production") {
|
|
78
|
+
const count = (activeRuntimesPerRoot.get(root) ?? 0) + 1;
|
|
79
|
+
activeRuntimesPerRoot.set(root, count);
|
|
80
|
+
if (count > 1) console.warn("[fsl-theme] Multiple theme runtimes are attached to the same root element. They overwrite each other's data-tt-* attributes (last writer wins) and their mode states do not sync. Render a single <ThemeProvider> per root, or pass a distinct `root` to each.");
|
|
81
|
+
}
|
|
63
82
|
const init = resolveTheme({
|
|
64
83
|
storageKey,
|
|
65
84
|
defaultMode,
|
|
@@ -94,7 +113,7 @@ var createThemeRuntime = (config = {}) => {
|
|
|
94
113
|
const state = getState();
|
|
95
114
|
for (const listener of listeners) listener(state);
|
|
96
115
|
};
|
|
97
|
-
const mediaQuery =
|
|
116
|
+
const mediaQuery = createMediaQuery();
|
|
98
117
|
const onSystemChange = () => {
|
|
99
118
|
if (destroyed) return;
|
|
100
119
|
resolvedMode = mediaQuery.matches ? "dark" : "light";
|
|
@@ -107,6 +126,30 @@ var createThemeRuntime = (config = {}) => {
|
|
|
107
126
|
if (active) mediaQuery.addEventListener("change", onSystemChange);
|
|
108
127
|
};
|
|
109
128
|
syncMediaListener(mode === "system");
|
|
129
|
+
/** Parse + validate a persisted `{ mode }` payload; null when unusable. */
|
|
130
|
+
const parseStoredMode = raw => {
|
|
131
|
+
let stored = null;
|
|
132
|
+
try {
|
|
133
|
+
stored = JSON.parse(raw);
|
|
134
|
+
} catch {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
const nextMode = stored?.mode;
|
|
138
|
+
return nextMode && VALID_MODES.includes(nextMode) ? nextMode : null;
|
|
139
|
+
};
|
|
140
|
+
const onStorage = event => {
|
|
141
|
+
if (destroyed || event.key !== storageKey || event.newValue === null) return;
|
|
142
|
+
if (event.storageArea != null && event.storageArea !== localStorage) return;
|
|
143
|
+
const nextMode = parseStoredMode(event.newValue);
|
|
144
|
+
if (!nextMode) return;
|
|
145
|
+
mode = nextMode;
|
|
146
|
+
resolvedMode = mode === "system" ? mediaQuery.matches ? "dark" : "light" : mode;
|
|
147
|
+
syncMediaListener(mode === "system");
|
|
148
|
+
applyState({
|
|
149
|
+
persist: false
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
window.addEventListener("storage", onStorage);
|
|
110
153
|
const setMode = newMode => {
|
|
111
154
|
if (destroyed || !VALID_MODES.includes(newMode)) return;
|
|
112
155
|
mode = newMode;
|
|
@@ -126,7 +169,12 @@ var createThemeRuntime = (config = {}) => {
|
|
|
126
169
|
const destroy = () => {
|
|
127
170
|
destroyed = true;
|
|
128
171
|
syncMediaListener(false);
|
|
172
|
+
window.removeEventListener("storage", onStorage);
|
|
129
173
|
listeners.clear();
|
|
174
|
+
if (process.env.NODE_ENV !== "production") {
|
|
175
|
+
const count = activeRuntimesPerRoot.get(root) ?? 0;
|
|
176
|
+
activeRuntimesPerRoot.set(root, Math.max(0, count - 1));
|
|
177
|
+
}
|
|
130
178
|
};
|
|
131
179
|
return {
|
|
132
180
|
getState,
|
|
@@ -173,7 +221,7 @@ var getThemeScriptContent = (config = {}) => {
|
|
|
173
221
|
defaultTheme,
|
|
174
222
|
defaultMode,
|
|
175
223
|
validModes: [...VALID_MODES]
|
|
176
|
-
})};var d=document.documentElement;var s=null;try{var r=localStorage.getItem(cfg.storageKey);if(r)s=JSON.parse(r);}catch(e){}var m=(s!=null&&s.mode!=null&&cfg.validModes.indexOf(s.mode)!==-1)?s.mode:cfg.defaultMode;var rm=m==="system"?(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"):m;if(cfg.defaultTheme){d.setAttribute("data-tt-theme",cfg.defaultTheme);}else{d.removeAttribute("data-tt-theme");}d.setAttribute("data-tt-mode",rm);d.style.colorScheme=rm;})()`;
|
|
224
|
+
}).replace(/</g, "\\u003C")};var d=document.documentElement;var s=null;try{var r=localStorage.getItem(cfg.storageKey);if(r)s=JSON.parse(r);}catch(e){}var m=(s!=null&&s.mode!=null&&cfg.validModes.indexOf(s.mode)!==-1)?s.mode:cfg.defaultMode;var rm=m==="system"?(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"):m;if(cfg.defaultTheme){d.setAttribute("data-tt-theme",cfg.defaultTheme);}else{d.removeAttribute("data-tt-theme");}d.setAttribute("data-tt-mode",rm);d.style.colorScheme=rm;})()`;
|
|
177
225
|
};
|
|
178
226
|
|
|
179
227
|
//#endregion
|
|
@@ -18,7 +18,7 @@ var resolveTheme = cfg => {
|
|
|
18
18
|
const mode = stored != null && stored.mode != null && cfg.validModes.indexOf(stored.mode) !== -1 ? stored.mode : cfg.defaultMode;
|
|
19
19
|
return {
|
|
20
20
|
mode,
|
|
21
|
-
resolvedMode: mode === "system" ? typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : mode
|
|
21
|
+
resolvedMode: mode === "system" ? typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : mode
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
24
|
|
|
@@ -34,6 +34,20 @@ var writeStorage = (key, data) => {
|
|
|
34
34
|
localStorage.setItem(key, JSON.stringify(data));
|
|
35
35
|
} catch {}
|
|
36
36
|
};
|
|
37
|
+
var createMediaQuery = () => {
|
|
38
|
+
if (typeof window.matchMedia === "function") return window.matchMedia("(prefers-color-scheme: dark)");
|
|
39
|
+
return {
|
|
40
|
+
matches: false,
|
|
41
|
+
addEventListener: () => {},
|
|
42
|
+
removeEventListener: () => {}
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* DEV-only registry of live runtimes per root element. Two runtimes writing
|
|
47
|
+
* `data-tt-*` to the same root overwrite each other (last writer wins), so
|
|
48
|
+
* the second attach warns. Entries are decremented on `destroy()`.
|
|
49
|
+
*/
|
|
50
|
+
var activeRuntimesPerRoot = /* @__PURE__ */new WeakMap();
|
|
37
51
|
/**
|
|
38
52
|
* Creates a framework-agnostic runtime that manages theme switching.
|
|
39
53
|
*
|
|
@@ -60,6 +74,11 @@ var createThemeRuntime = (config = {}) => {
|
|
|
60
74
|
} = config;
|
|
61
75
|
const listeners = /* @__PURE__ */new Set();
|
|
62
76
|
let destroyed = false;
|
|
77
|
+
if (process.env.NODE_ENV !== "production") {
|
|
78
|
+
const count = (activeRuntimesPerRoot.get(root) ?? 0) + 1;
|
|
79
|
+
activeRuntimesPerRoot.set(root, count);
|
|
80
|
+
if (count > 1) console.warn("[fsl-theme] Multiple theme runtimes are attached to the same root element. They overwrite each other's data-tt-* attributes (last writer wins) and their mode states do not sync. Render a single <ThemeProvider> per root, or pass a distinct `root` to each.");
|
|
81
|
+
}
|
|
63
82
|
const init = resolveTheme({
|
|
64
83
|
storageKey,
|
|
65
84
|
defaultMode,
|
|
@@ -94,7 +113,7 @@ var createThemeRuntime = (config = {}) => {
|
|
|
94
113
|
const state = getState();
|
|
95
114
|
for (const listener of listeners) listener(state);
|
|
96
115
|
};
|
|
97
|
-
const mediaQuery =
|
|
116
|
+
const mediaQuery = createMediaQuery();
|
|
98
117
|
const onSystemChange = () => {
|
|
99
118
|
if (destroyed) return;
|
|
100
119
|
resolvedMode = mediaQuery.matches ? "dark" : "light";
|
|
@@ -107,6 +126,30 @@ var createThemeRuntime = (config = {}) => {
|
|
|
107
126
|
if (active) mediaQuery.addEventListener("change", onSystemChange);
|
|
108
127
|
};
|
|
109
128
|
syncMediaListener(mode === "system");
|
|
129
|
+
/** Parse + validate a persisted `{ mode }` payload; null when unusable. */
|
|
130
|
+
const parseStoredMode = raw => {
|
|
131
|
+
let stored = null;
|
|
132
|
+
try {
|
|
133
|
+
stored = JSON.parse(raw);
|
|
134
|
+
} catch {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
const nextMode = stored?.mode;
|
|
138
|
+
return nextMode && VALID_MODES.includes(nextMode) ? nextMode : null;
|
|
139
|
+
};
|
|
140
|
+
const onStorage = event => {
|
|
141
|
+
if (destroyed || event.key !== storageKey || event.newValue === null) return;
|
|
142
|
+
if (event.storageArea != null && event.storageArea !== localStorage) return;
|
|
143
|
+
const nextMode = parseStoredMode(event.newValue);
|
|
144
|
+
if (!nextMode) return;
|
|
145
|
+
mode = nextMode;
|
|
146
|
+
resolvedMode = mode === "system" ? mediaQuery.matches ? "dark" : "light" : mode;
|
|
147
|
+
syncMediaListener(mode === "system");
|
|
148
|
+
applyState({
|
|
149
|
+
persist: false
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
window.addEventListener("storage", onStorage);
|
|
110
153
|
const setMode = newMode => {
|
|
111
154
|
if (destroyed || !VALID_MODES.includes(newMode)) return;
|
|
112
155
|
mode = newMode;
|
|
@@ -126,7 +169,12 @@ var createThemeRuntime = (config = {}) => {
|
|
|
126
169
|
const destroy = () => {
|
|
127
170
|
destroyed = true;
|
|
128
171
|
syncMediaListener(false);
|
|
172
|
+
window.removeEventListener("storage", onStorage);
|
|
129
173
|
listeners.clear();
|
|
174
|
+
if (process.env.NODE_ENV !== "production") {
|
|
175
|
+
const count = activeRuntimesPerRoot.get(root) ?? 0;
|
|
176
|
+
activeRuntimesPerRoot.set(root, Math.max(0, count - 1));
|
|
177
|
+
}
|
|
130
178
|
};
|
|
131
179
|
return {
|
|
132
180
|
getState,
|
|
@@ -173,7 +221,7 @@ var getThemeScriptContent = (config = {}) => {
|
|
|
173
221
|
defaultTheme,
|
|
174
222
|
defaultMode,
|
|
175
223
|
validModes: [...VALID_MODES]
|
|
176
|
-
})};var d=document.documentElement;var s=null;try{var r=localStorage.getItem(cfg.storageKey);if(r)s=JSON.parse(r);}catch(e){}var m=(s!=null&&s.mode!=null&&cfg.validModes.indexOf(s.mode)!==-1)?s.mode:cfg.defaultMode;var rm=m==="system"?(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"):m;if(cfg.defaultTheme){d.setAttribute("data-tt-theme",cfg.defaultTheme);}else{d.removeAttribute("data-tt-theme");}d.setAttribute("data-tt-mode",rm);d.style.colorScheme=rm;})()`;
|
|
224
|
+
}).replace(/</g, "\\u003C")};var d=document.documentElement;var s=null;try{var r=localStorage.getItem(cfg.storageKey);if(r)s=JSON.parse(r);}catch(e){}var m=(s!=null&&s.mode!=null&&cfg.validModes.indexOf(s.mode)!==-1)?s.mode:cfg.defaultMode;var rm=m==="system"?(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"):m;if(cfg.defaultTheme){d.setAttribute("data-tt-theme",cfg.defaultTheme);}else{d.removeAttribute("data-tt-theme");}d.setAttribute("data-tt-mode",rm);d.style.colorScheme=rm;})()`;
|
|
177
225
|
};
|
|
178
226
|
|
|
179
227
|
//#endregion
|
package/dist/themes/bruttal.cjs
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, {
|
|
3
3
|
value: 'Module'
|
|
4
4
|
});
|
|
5
|
-
const require_createTheme = require('../createTheme
|
|
5
|
+
const require_createTheme = require('../createTheme-B7H0xSVp.cjs');
|
|
6
6
|
const require_helpers = require('../helpers-BU40JvFA.cjs');
|
|
7
|
-
const require_withDataviz = require('../withDataviz-
|
|
7
|
+
const require_withDataviz = require('../withDataviz-DrUtw8cc.cjs');
|
|
8
8
|
|
|
9
9
|
//#region src/themes/bruttal.ts
|
|
10
10
|
/**
|
package/dist/themes/bruttal.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
-
import { a as darkAlternate, n as createTheme } from "../createTheme-
|
|
2
|
+
import { a as darkAlternate, n as createTheme } from "../createTheme-Bm9LVQ4w.mjs";
|
|
3
3
|
import { r as deepMerge } from "../helpers-BXaKe2s3.mjs";
|
|
4
|
-
import { t as withDataviz } from "../withDataviz-
|
|
4
|
+
import { t as withDataviz } from "../withDataviz-Ln3sEwb7.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/themes/bruttal.ts
|
|
7
7
|
/**
|
|
@@ -11,7 +11,7 @@ import { t as CSS_PATH_PREFIXES } from "./tokenRegistry-DviyqDeE.mjs";
|
|
|
11
11
|
*/
|
|
12
12
|
var toCssVarName = tokenPath => {
|
|
13
13
|
for (const [prefix, cssPrefix] of CSS_PATH_PREFIXES) if (tokenPath.startsWith(prefix)) return `${cssPrefix}${tokenPath.slice(prefix.length).replace(/\./g, "-")}`;
|
|
14
|
-
return `--tt-${tokenPath.replace(/\./g, "-")}`;
|
|
14
|
+
return `--tt-${(tokenPath.startsWith("semantic.") ? tokenPath.slice(9) : tokenPath).replace(/\./g, "-")}`;
|
|
15
15
|
};
|
|
16
16
|
/**
|
|
17
17
|
* Replace all embedded `{token.path}` refs inside a raw string with `var(--tt-...)` references.
|
|
@@ -212,6 +212,34 @@ var isThemeBundle = input => {
|
|
|
212
212
|
return "baseMode" in input && "base" in input;
|
|
213
213
|
};
|
|
214
214
|
/**
|
|
215
|
+
* Build the no-JS / pre-hydration system-mode fallback block.
|
|
216
|
+
*
|
|
217
|
+
* Canonical 1-theme model only (no `themeId`): before the runtime (or the SSR
|
|
218
|
+
* bootstrap script) stamps `data-tt-mode`, and for users with JavaScript
|
|
219
|
+
* disabled, the alternate mode would otherwise never apply. This block scopes
|
|
220
|
+
* the alternate diff vars to `@media (prefers-color-scheme: <mode>)` behind
|
|
221
|
+
* `:root:not([data-tt-mode])`, so it applies exactly while no explicit mode
|
|
222
|
+
* attribute exists and gets out of the way the moment the runtime writes one
|
|
223
|
+
* (persisted user choice always wins over the OS preference).
|
|
224
|
+
*/
|
|
225
|
+
var buildSystemModeFallbackBlock = ({
|
|
226
|
+
mode,
|
|
227
|
+
vars
|
|
228
|
+
}) => {
|
|
229
|
+
const entries = Object.entries(vars);
|
|
230
|
+
const selector = ":root:not([data-tt-mode])";
|
|
231
|
+
const lines = entries.map(([name, value]) => {
|
|
232
|
+
return ` ${name}: ${hasCqUnits(value) ? toViewportFallback(String(value)) : value};`;
|
|
233
|
+
});
|
|
234
|
+
const cqEntries = entries.filter(([, value]) => {
|
|
235
|
+
return hasCqUnits(value);
|
|
236
|
+
});
|
|
237
|
+
const cqBlock = cqEntries.length > 0 ? `\n\n @supports (width: 1cqi) {\n ${selector} {\n${cqEntries.map(([name, value]) => {
|
|
238
|
+
return ` ${name}: ${value};`;
|
|
239
|
+
}).join("\n")}\n }\n }` : "";
|
|
240
|
+
return `@media (prefers-color-scheme: ${mode}) {\n ${selector} {\n color-scheme: ${mode};\n${lines.join("\n")}\n }${cqBlock}\n}`;
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
215
243
|
* Compute a diff record: only entries in `full` whose values differ from `base`.
|
|
216
244
|
*/
|
|
217
245
|
var diffCssVars = ({
|
|
@@ -238,7 +266,8 @@ var diffCssVars = ({
|
|
|
238
266
|
*/
|
|
239
267
|
var bundleToCssVars = (bundle, options) => {
|
|
240
268
|
const {
|
|
241
|
-
themeId
|
|
269
|
+
themeId,
|
|
270
|
+
systemModeFallback = true
|
|
242
271
|
} = options;
|
|
243
272
|
const {
|
|
244
273
|
baseMode,
|
|
@@ -297,7 +326,13 @@ var bundleToCssVars = (bundle, options) => {
|
|
|
297
326
|
alternate: alternateResult,
|
|
298
327
|
toCssString: () => {
|
|
299
328
|
const parts = [baseResult.toCssString()];
|
|
300
|
-
if (Object.keys(diffVars).length > 0)
|
|
329
|
+
if (Object.keys(diffVars).length > 0) {
|
|
330
|
+
parts.push(alternateResult.toCssString());
|
|
331
|
+
if (!themeId && systemModeFallback) parts.push(buildSystemModeFallbackBlock({
|
|
332
|
+
mode: alternateMode,
|
|
333
|
+
vars: diffVars
|
|
334
|
+
}));
|
|
335
|
+
}
|
|
301
336
|
return parts.join("\n\n");
|
|
302
337
|
}
|
|
303
338
|
};
|
|
@@ -11,7 +11,7 @@ const require_tokenRegistry = require('./tokenRegistry-f_Bx_BAN.cjs');
|
|
|
11
11
|
*/
|
|
12
12
|
var toCssVarName = tokenPath => {
|
|
13
13
|
for (const [prefix, cssPrefix] of require_tokenRegistry.CSS_PATH_PREFIXES) if (tokenPath.startsWith(prefix)) return `${cssPrefix}${tokenPath.slice(prefix.length).replace(/\./g, "-")}`;
|
|
14
|
-
return `--tt-${tokenPath.replace(/\./g, "-")}`;
|
|
14
|
+
return `--tt-${(tokenPath.startsWith("semantic.") ? tokenPath.slice(9) : tokenPath).replace(/\./g, "-")}`;
|
|
15
15
|
};
|
|
16
16
|
/**
|
|
17
17
|
* Replace all embedded `{token.path}` refs inside a raw string with `var(--tt-...)` references.
|
|
@@ -212,6 +212,34 @@ var isThemeBundle = input => {
|
|
|
212
212
|
return "baseMode" in input && "base" in input;
|
|
213
213
|
};
|
|
214
214
|
/**
|
|
215
|
+
* Build the no-JS / pre-hydration system-mode fallback block.
|
|
216
|
+
*
|
|
217
|
+
* Canonical 1-theme model only (no `themeId`): before the runtime (or the SSR
|
|
218
|
+
* bootstrap script) stamps `data-tt-mode`, and for users with JavaScript
|
|
219
|
+
* disabled, the alternate mode would otherwise never apply. This block scopes
|
|
220
|
+
* the alternate diff vars to `@media (prefers-color-scheme: <mode>)` behind
|
|
221
|
+
* `:root:not([data-tt-mode])`, so it applies exactly while no explicit mode
|
|
222
|
+
* attribute exists and gets out of the way the moment the runtime writes one
|
|
223
|
+
* (persisted user choice always wins over the OS preference).
|
|
224
|
+
*/
|
|
225
|
+
var buildSystemModeFallbackBlock = ({
|
|
226
|
+
mode,
|
|
227
|
+
vars
|
|
228
|
+
}) => {
|
|
229
|
+
const entries = Object.entries(vars);
|
|
230
|
+
const selector = ":root:not([data-tt-mode])";
|
|
231
|
+
const lines = entries.map(([name, value]) => {
|
|
232
|
+
return ` ${name}: ${hasCqUnits(value) ? toViewportFallback(String(value)) : value};`;
|
|
233
|
+
});
|
|
234
|
+
const cqEntries = entries.filter(([, value]) => {
|
|
235
|
+
return hasCqUnits(value);
|
|
236
|
+
});
|
|
237
|
+
const cqBlock = cqEntries.length > 0 ? `\n\n @supports (width: 1cqi) {\n ${selector} {\n${cqEntries.map(([name, value]) => {
|
|
238
|
+
return ` ${name}: ${value};`;
|
|
239
|
+
}).join("\n")}\n }\n }` : "";
|
|
240
|
+
return `@media (prefers-color-scheme: ${mode}) {\n ${selector} {\n color-scheme: ${mode};\n${lines.join("\n")}\n }${cqBlock}\n}`;
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
215
243
|
* Compute a diff record: only entries in `full` whose values differ from `base`.
|
|
216
244
|
*/
|
|
217
245
|
var diffCssVars = ({
|
|
@@ -238,7 +266,8 @@ var diffCssVars = ({
|
|
|
238
266
|
*/
|
|
239
267
|
var bundleToCssVars = (bundle, options) => {
|
|
240
268
|
const {
|
|
241
|
-
themeId
|
|
269
|
+
themeId,
|
|
270
|
+
systemModeFallback = true
|
|
242
271
|
} = options;
|
|
243
272
|
const {
|
|
244
273
|
baseMode,
|
|
@@ -297,7 +326,13 @@ var bundleToCssVars = (bundle, options) => {
|
|
|
297
326
|
alternate: alternateResult,
|
|
298
327
|
toCssString: () => {
|
|
299
328
|
const parts = [baseResult.toCssString()];
|
|
300
|
-
if (Object.keys(diffVars).length > 0)
|
|
329
|
+
if (Object.keys(diffVars).length > 0) {
|
|
330
|
+
parts.push(alternateResult.toCssString());
|
|
331
|
+
if (!themeId && systemModeFallback) parts.push(buildSystemModeFallbackBlock({
|
|
332
|
+
mode: alternateMode,
|
|
333
|
+
vars: diffVars
|
|
334
|
+
}));
|
|
335
|
+
}
|
|
301
336
|
return parts.join("\n\n");
|
|
302
337
|
}
|
|
303
338
|
};
|
package/dist/vars.cjs
CHANGED
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, Symbol.toStringTag, {
|
|
|
3
3
|
value: 'Module'
|
|
4
4
|
});
|
|
5
5
|
const require_helpers = require('./helpers-BU40JvFA.cjs');
|
|
6
|
-
const require_baseBundle = require('./baseBundle-
|
|
7
|
-
const require_toCssVars = require('./toCssVars-
|
|
6
|
+
const require_baseBundle = require('./baseBundle-a9LDsqYy.cjs');
|
|
7
|
+
const require_toCssVars = require('./toCssVars-D0BR23cP.cjs');
|
|
8
8
|
|
|
9
9
|
//#region src/roots/toVars.ts
|
|
10
10
|
/**
|
|
@@ -23,7 +23,7 @@ const require_toCssVars = require('./toCssVars-BseqmMcT.cjs');
|
|
|
23
23
|
*
|
|
24
24
|
* const vars = buildVarsMap(baseTheme);
|
|
25
25
|
* vars.colors.action.primary.background.default
|
|
26
|
-
* // → 'var(--tt-action-primary-background-default)'
|
|
26
|
+
* // → 'var(--tt-colors-action-primary-background-default)'
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
29
|
var buildVarsMap = theme => {
|
|
@@ -57,15 +57,15 @@ var buildVarsMap = theme => {
|
|
|
57
57
|
* import { vars } from '@ttoss/fsl-theme/vars';
|
|
58
58
|
*
|
|
59
59
|
* <Button style={{ background: vars.colors.action.primary.background.default }} />
|
|
60
|
-
* // → background: 'var(--tt-action-primary-background-default)'
|
|
60
|
+
* // → background: 'var(--tt-colors-action-primary-background-default)'
|
|
61
61
|
* ```
|
|
62
62
|
*
|
|
63
63
|
* ## Usage in CSS / CSS Modules
|
|
64
64
|
*
|
|
65
65
|
* ```css
|
|
66
66
|
* .button {
|
|
67
|
-
* background: var(--tt-action-primary-background-default);
|
|
68
|
-
* color: var(--tt-action-primary-text-default);
|
|
67
|
+
* background: var(--tt-colors-action-primary-background-default);
|
|
68
|
+
* color: var(--tt-colors-action-primary-text-default);
|
|
69
69
|
* }
|
|
70
70
|
* ```
|
|
71
71
|
*
|
|
@@ -110,7 +110,7 @@ var buildVarsMap = theme => {
|
|
|
110
110
|
* buildVarsMap(myTheme.base) as CssVarsMap<MySemanticTokens>;
|
|
111
111
|
*
|
|
112
112
|
* myVars.colors.brandX.primary.default;
|
|
113
|
-
* // → 'var(--tt-colors-
|
|
113
|
+
* // → 'var(--tt-colors-brandX-primary-default)' (camelCase is preserved)
|
|
114
114
|
* ```
|
|
115
115
|
*
|
|
116
116
|
* For one-off custom keys where the extra structure is trivial, use
|
package/dist/vars.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { a as ThemeTokens, n as SemanticTokens } from "./Types-
|
|
2
|
+
import { a as ThemeTokens, n as SemanticTokens } from "./Types-a_sfpbha.cjs";
|
|
3
3
|
|
|
4
4
|
//#region src/roots/toVars.d.ts
|
|
5
5
|
/**
|
|
@@ -38,7 +38,7 @@ type CssVarsMap<T> = { [K in keyof T as K extends `$${string}` ? never : K]: Non
|
|
|
38
38
|
*
|
|
39
39
|
* const vars = buildVarsMap(baseTheme);
|
|
40
40
|
* vars.colors.action.primary.background.default
|
|
41
|
-
* // → 'var(--tt-action-primary-background-default)'
|
|
41
|
+
* // → 'var(--tt-colors-action-primary-background-default)'
|
|
42
42
|
* ```
|
|
43
43
|
*/
|
|
44
44
|
declare const buildVarsMap: (theme: ThemeTokens) => CssVarsMap<ThemeTokens["semantic"]>;
|
|
@@ -60,15 +60,15 @@ declare const buildVarsMap: (theme: ThemeTokens) => CssVarsMap<ThemeTokens["sema
|
|
|
60
60
|
* import { vars } from '@ttoss/fsl-theme/vars';
|
|
61
61
|
*
|
|
62
62
|
* <Button style={{ background: vars.colors.action.primary.background.default }} />
|
|
63
|
-
* // → background: 'var(--tt-action-primary-background-default)'
|
|
63
|
+
* // → background: 'var(--tt-colors-action-primary-background-default)'
|
|
64
64
|
* ```
|
|
65
65
|
*
|
|
66
66
|
* ## Usage in CSS / CSS Modules
|
|
67
67
|
*
|
|
68
68
|
* ```css
|
|
69
69
|
* .button {
|
|
70
|
-
* background: var(--tt-action-primary-background-default);
|
|
71
|
-
* color: var(--tt-action-primary-text-default);
|
|
70
|
+
* background: var(--tt-colors-action-primary-background-default);
|
|
71
|
+
* color: var(--tt-colors-action-primary-text-default);
|
|
72
72
|
* }
|
|
73
73
|
* ```
|
|
74
74
|
*
|
|
@@ -113,7 +113,7 @@ declare const buildVarsMap: (theme: ThemeTokens) => CssVarsMap<ThemeTokens["sema
|
|
|
113
113
|
* buildVarsMap(myTheme.base) as CssVarsMap<MySemanticTokens>;
|
|
114
114
|
*
|
|
115
115
|
* myVars.colors.brandX.primary.default;
|
|
116
|
-
* // → 'var(--tt-colors-
|
|
116
|
+
* // → 'var(--tt-colors-brandX-primary-default)' (camelCase is preserved)
|
|
117
117
|
* ```
|
|
118
118
|
*
|
|
119
119
|
* For one-off custom keys where the extra structure is trivial, use
|
package/dist/vars.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { a as ThemeTokens, n as SemanticTokens } from "./Types-
|
|
2
|
+
import { a as ThemeTokens, n as SemanticTokens } from "./Types-a_sfpbha.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/roots/toVars.d.ts
|
|
5
5
|
/**
|
|
@@ -38,7 +38,7 @@ type CssVarsMap<T> = { [K in keyof T as K extends `$${string}` ? never : K]: Non
|
|
|
38
38
|
*
|
|
39
39
|
* const vars = buildVarsMap(baseTheme);
|
|
40
40
|
* vars.colors.action.primary.background.default
|
|
41
|
-
* // → 'var(--tt-action-primary-background-default)'
|
|
41
|
+
* // → 'var(--tt-colors-action-primary-background-default)'
|
|
42
42
|
* ```
|
|
43
43
|
*/
|
|
44
44
|
declare const buildVarsMap: (theme: ThemeTokens) => CssVarsMap<ThemeTokens["semantic"]>;
|
|
@@ -60,15 +60,15 @@ declare const buildVarsMap: (theme: ThemeTokens) => CssVarsMap<ThemeTokens["sema
|
|
|
60
60
|
* import { vars } from '@ttoss/fsl-theme/vars';
|
|
61
61
|
*
|
|
62
62
|
* <Button style={{ background: vars.colors.action.primary.background.default }} />
|
|
63
|
-
* // → background: 'var(--tt-action-primary-background-default)'
|
|
63
|
+
* // → background: 'var(--tt-colors-action-primary-background-default)'
|
|
64
64
|
* ```
|
|
65
65
|
*
|
|
66
66
|
* ## Usage in CSS / CSS Modules
|
|
67
67
|
*
|
|
68
68
|
* ```css
|
|
69
69
|
* .button {
|
|
70
|
-
* background: var(--tt-action-primary-background-default);
|
|
71
|
-
* color: var(--tt-action-primary-text-default);
|
|
70
|
+
* background: var(--tt-colors-action-primary-background-default);
|
|
71
|
+
* color: var(--tt-colors-action-primary-text-default);
|
|
72
72
|
* }
|
|
73
73
|
* ```
|
|
74
74
|
*
|
|
@@ -113,7 +113,7 @@ declare const buildVarsMap: (theme: ThemeTokens) => CssVarsMap<ThemeTokens["sema
|
|
|
113
113
|
* buildVarsMap(myTheme.base) as CssVarsMap<MySemanticTokens>;
|
|
114
114
|
*
|
|
115
115
|
* myVars.colors.brandX.primary.default;
|
|
116
|
-
* // → 'var(--tt-colors-
|
|
116
|
+
* // → 'var(--tt-colors-brandX-primary-default)' (camelCase is preserved)
|
|
117
117
|
* ```
|
|
118
118
|
*
|
|
119
119
|
* For one-off custom keys where the extra structure is trivial, use
|
package/dist/vars.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
2
|
import { o as isPlainObject } from "./helpers-BXaKe2s3.mjs";
|
|
3
|
-
import { t as baseBundle } from "./baseBundle-
|
|
4
|
-
import { t as toCssVarName } from "./toCssVars-
|
|
3
|
+
import { t as baseBundle } from "./baseBundle-CXdxj_re.mjs";
|
|
4
|
+
import { t as toCssVarName } from "./toCssVars-CWTlp9St.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/roots/toVars.ts
|
|
7
7
|
/**
|
|
@@ -20,7 +20,7 @@ import { t as toCssVarName } from "./toCssVars-C-9yIZDR.mjs";
|
|
|
20
20
|
*
|
|
21
21
|
* const vars = buildVarsMap(baseTheme);
|
|
22
22
|
* vars.colors.action.primary.background.default
|
|
23
|
-
* // → 'var(--tt-action-primary-background-default)'
|
|
23
|
+
* // → 'var(--tt-colors-action-primary-background-default)'
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
26
|
var buildVarsMap = theme => {
|
|
@@ -54,15 +54,15 @@ var buildVarsMap = theme => {
|
|
|
54
54
|
* import { vars } from '@ttoss/fsl-theme/vars';
|
|
55
55
|
*
|
|
56
56
|
* <Button style={{ background: vars.colors.action.primary.background.default }} />
|
|
57
|
-
* // → background: 'var(--tt-action-primary-background-default)'
|
|
57
|
+
* // → background: 'var(--tt-colors-action-primary-background-default)'
|
|
58
58
|
* ```
|
|
59
59
|
*
|
|
60
60
|
* ## Usage in CSS / CSS Modules
|
|
61
61
|
*
|
|
62
62
|
* ```css
|
|
63
63
|
* .button {
|
|
64
|
-
* background: var(--tt-action-primary-background-default);
|
|
65
|
-
* color: var(--tt-action-primary-text-default);
|
|
64
|
+
* background: var(--tt-colors-action-primary-background-default);
|
|
65
|
+
* color: var(--tt-colors-action-primary-text-default);
|
|
66
66
|
* }
|
|
67
67
|
* ```
|
|
68
68
|
*
|
|
@@ -107,7 +107,7 @@ var buildVarsMap = theme => {
|
|
|
107
107
|
* buildVarsMap(myTheme.base) as CssVarsMap<MySemanticTokens>;
|
|
108
108
|
*
|
|
109
109
|
* myVars.colors.brandX.primary.default;
|
|
110
|
-
* // → 'var(--tt-colors-
|
|
110
|
+
* // → 'var(--tt-colors-brandX-primary-default)' (camelCase is preserved)
|
|
111
111
|
* ```
|
|
112
112
|
*
|
|
113
113
|
* For one-off custom keys where the extra structure is trivial, use
|
package/llms.txt
CHANGED
|
@@ -289,7 +289,8 @@ Not every state is legal in every `ux` context. Illegal combinations are TypeScr
|
|
|
289
289
|
| `indeterminate` | — | ✅ | — | — | — |
|
|
290
290
|
| `current` | — | — | ✅ (active route) | — | — |
|
|
291
291
|
| `visited` | — | — | ✅ | — | ✅ (link in content) |
|
|
292
|
-
| `droptarget` |
|
|
292
|
+
| `droptarget` | ✅ | ✅ (file input) | ✅ | — | ✅ |
|
|
293
|
+
| `invalid` | — | ✅ (runtime validation outcome — `isInvalid`, never authorial; pairs with `input.negative.*` on the validationMessage) | — | — | — |
|
|
293
294
|
|
|
294
295
|
State disambiguation rules:
|
|
295
296
|
- **`active` vs `pressed`**: `active` = the brief moment of clicking (transient). `pressed` = persistent toggle engaged ("Bold" button). Never use `active` for toggle state.
|
|
@@ -575,7 +576,7 @@ const DarkModeToggle = () => {
|
|
|
575
576
|
```tsx
|
|
576
577
|
import { useResolvedTokens } from '@ttoss/fsl-theme/react';
|
|
577
578
|
|
|
578
|
-
// Keys are full semantic dot-paths; values are resolved raw CSS values (hex,
|
|
579
|
+
// Keys are full semantic dot-paths; values are resolved raw CSS values (hex, numbers, etc.)
|
|
579
580
|
const NativeButton = ({ disabled }: { disabled?: boolean }) => {
|
|
580
581
|
const resolved = useResolvedTokens();
|
|
581
582
|
return (
|
|
@@ -584,8 +585,7 @@ const NativeButton = ({ disabled }: { disabled?: boolean }) => {
|
|
|
584
585
|
backgroundColor: disabled
|
|
585
586
|
? resolved['semantic.colors.action.primary.background.disabled']
|
|
586
587
|
: resolved['semantic.colors.action.primary.background.default'],
|
|
587
|
-
|
|
588
|
-
paddingHorizontal: resolved['semantic.spacing.inset.control.md'],
|
|
588
|
+
opacity: disabled ? Number(resolved['semantic.opacity.disabled']) : 1,
|
|
589
589
|
}}
|
|
590
590
|
/>
|
|
591
591
|
);
|
|
@@ -594,6 +594,8 @@ const NativeButton = ({ disabled }: { disabled?: boolean }) => {
|
|
|
594
594
|
|
|
595
595
|
`useResolvedTokens()` automatically applies coarse-pointer hit target overrides — mirrors the `@media (any-pointer: coarse)` block that `toCssVars` injects for CSS consumers.
|
|
596
596
|
|
|
597
|
+
⚠ **CSS-coupled tokens stay unresolved** (model.md §8): spacing steps (`calc(N * var(--tt-core-spacing-engine-unit))`), fluid `text.*.fontSize` / `sizing.hit.*` (`clamp()` + `cqi`), `sizing.viewport.*` (`dvh`/`dvw`), `sizing.measure.reading` (`ch`), and `spacing.gutter.*` are CSS expressions and are **not usable** outside a CSS engine. In non-CSS environments, consume colors, opacity, z-index, font weights/leading, and other scalar tokens — derive dimensional values from your platform's layout system.
|
|
598
|
+
|
|
597
599
|
---
|
|
598
600
|
|
|
599
601
|
# JOB 2 — Customizing a theme
|