@loworbitstudio/visor-theme-engine 0.17.1 → 0.19.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/dist/adapters/index.d.ts +16 -2
- package/dist/adapters/index.js +85 -3
- package/dist/{chunk-BUWBBUFG.js → chunk-32DC5DAR.js} +490 -0
- package/dist/index.d.ts +141 -2
- package/dist/index.js +160 -3
- package/dist/{types-Cvm7vFwe.d.ts → types-DF5StphJ.d.ts} +164 -1
- package/package.json +1 -1
- package/src/visor-theme.schema.json +133 -0
package/dist/adapters/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { k as GeneratedPrimitives, s as SemanticTokens, R as ResolvedThemeConfig } from '../types-
|
|
1
|
+
import { k as GeneratedPrimitives, s as SemanticTokens, R as ResolvedThemeConfig } from '../types-DF5StphJ.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Adapter types for the Visor theme engine.
|
|
@@ -32,6 +32,13 @@ interface NextJSAdapterOptions extends AdapterOptions {
|
|
|
32
32
|
* (`:root`) for backward compatibility. See VI-368.
|
|
33
33
|
*/
|
|
34
34
|
scopePrefix?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Emit the `@import "@loworbitstudio/visor-core/reset";` line and the
|
|
37
|
+
* `@layer visor-base` origination block that binds theme tokens to the page
|
|
38
|
+
* root (default: true). Set false for consumers that ship Tailwind preflight
|
|
39
|
+
* or their own reset. See VI-616.
|
|
40
|
+
*/
|
|
41
|
+
includeBaseLayer?: boolean;
|
|
35
42
|
}
|
|
36
43
|
/** Options specific to the Deck adapter. */
|
|
37
44
|
interface DeckAdapterOptions extends AdapterOptions {
|
|
@@ -198,12 +205,19 @@ declare function flutterAdapter(input: AdapterInput, options?: FlutterAdapterOpt
|
|
|
198
205
|
/**
|
|
199
206
|
* Layer order declaration — must appear before any @layer blocks.
|
|
200
207
|
*
|
|
208
|
+
* `visor-base` (VI-616) is FIRST — i.e. lowest priority. It carries the
|
|
209
|
+
* element-level baseline (token-to-page binding + UA reset). Lowest placement
|
|
210
|
+
* means a consumer's own unlayered `body {}` always wins, and component
|
|
211
|
+
* `.module.css` (which uses no `@layer` at all) beats the base layer
|
|
212
|
+
* unconditionally. Author-origin still beats the UA stylesheet regardless of
|
|
213
|
+
* layer, so the reset does its job.
|
|
214
|
+
*
|
|
201
215
|
* `visor-brand` (VI-470) is ordered immediately after `visor-semantic`: brand
|
|
202
216
|
* asset vars (`--brand-*`) sit above semantic tokens so brand overrides stay
|
|
203
217
|
* cleanly separable, while still below `visor-adaptive` chrome and the
|
|
204
218
|
* `visor-bridge` framework layer.
|
|
205
219
|
*/
|
|
206
|
-
declare const LAYER_ORDER = "@layer visor-primitives, visor-semantic, visor-brand, visor-adaptive, visor-bridge;";
|
|
220
|
+
declare const LAYER_ORDER = "@layer visor-base, visor-primitives, visor-semantic, visor-brand, visor-adaptive, visor-bridge;";
|
|
207
221
|
/**
|
|
208
222
|
* Wrap CSS content in a named @layer block.
|
|
209
223
|
*/
|
package/dist/adapters/index.js
CHANGED
|
@@ -17,10 +17,11 @@ import {
|
|
|
17
17
|
generateTextScaleAliasDecls,
|
|
18
18
|
header,
|
|
19
19
|
parseColor,
|
|
20
|
+
resolveComponentBindings,
|
|
20
21
|
resolveThemeBrand,
|
|
21
22
|
resolveThemeFonts,
|
|
22
23
|
sectionComment
|
|
23
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-32DC5DAR.js";
|
|
24
25
|
|
|
25
26
|
// src/adapters/brand-passthrough.ts
|
|
26
27
|
var SENTINEL_COLOR = "#ff00ff";
|
|
@@ -82,8 +83,44 @@ ${prefersInner}
|
|
|
82
83
|
return blocks.filter(Boolean).join("\n\n");
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
// src/adapters/component-tokens-css.ts
|
|
87
|
+
function indentBlock2(selector, decls) {
|
|
88
|
+
if (decls.length === 0) return "";
|
|
89
|
+
return [selector + " {", ...decls.map((d) => ` ${d}`), "}"].join("\n");
|
|
90
|
+
}
|
|
91
|
+
function declsFor(values) {
|
|
92
|
+
return Object.keys(values).sort().map((name) => `--${name}: ${values[name]};`);
|
|
93
|
+
}
|
|
94
|
+
function generateComponentTokensCss(tokens, selectors, colorScheme = "adaptive") {
|
|
95
|
+
const lightDecls = declsFor(tokens.light);
|
|
96
|
+
const darkDecls = declsFor(tokens.dark);
|
|
97
|
+
if (lightDecls.length === 0 && darkDecls.length === 0) return "";
|
|
98
|
+
const blocks = [
|
|
99
|
+
"/* \u2500\u2500 Component tokens (VI-625) \u2014 theme bindings for the admin-UI families \u2500\u2500 */"
|
|
100
|
+
];
|
|
101
|
+
if (colorScheme === "dark-only") {
|
|
102
|
+
blocks.push(indentBlock2(selectors.light, darkDecls));
|
|
103
|
+
return blocks.filter(Boolean).join("\n\n");
|
|
104
|
+
}
|
|
105
|
+
if (colorScheme === "light-only") {
|
|
106
|
+
blocks.push(indentBlock2(selectors.light, lightDecls));
|
|
107
|
+
return blocks.filter(Boolean).join("\n\n");
|
|
108
|
+
}
|
|
109
|
+
if (lightDecls.length > 0) {
|
|
110
|
+
blocks.push(indentBlock2(selectors.light, lightDecls));
|
|
111
|
+
}
|
|
112
|
+
if (darkDecls.length > 0) {
|
|
113
|
+
blocks.push(indentBlock2(selectors.dark, darkDecls));
|
|
114
|
+
const prefersInner = indentBlock2(selectors.prefers, darkDecls).split("\n").map((l) => ` ${l}`).join("\n");
|
|
115
|
+
blocks.push(`@media (prefers-color-scheme: dark) {
|
|
116
|
+
${prefersInner}
|
|
117
|
+
}`);
|
|
118
|
+
}
|
|
119
|
+
return blocks.filter(Boolean).join("\n\n");
|
|
120
|
+
}
|
|
121
|
+
|
|
85
122
|
// src/adapters/layers.ts
|
|
86
|
-
var LAYER_ORDER = "@layer visor-primitives, visor-semantic, visor-brand, visor-adaptive, visor-bridge;";
|
|
123
|
+
var LAYER_ORDER = "@layer visor-base, visor-primitives, visor-semantic, visor-brand, visor-adaptive, visor-bridge;";
|
|
87
124
|
function wrapInLayer(layerName, css) {
|
|
88
125
|
const trimmed = css.trim();
|
|
89
126
|
if (!trimmed) return "";
|
|
@@ -99,12 +136,17 @@ function toKebabCase(name) {
|
|
|
99
136
|
function nextjsAdapter(input, options) {
|
|
100
137
|
const includeFontImports = options?.includeFontImports ?? true;
|
|
101
138
|
const includeFowt = options?.includeFowt ?? true;
|
|
139
|
+
const includeBaseLayer = options?.includeBaseLayer ?? true;
|
|
102
140
|
const scopePrefix = options?.scopePrefix;
|
|
103
141
|
const colorScheme = input.config["color-scheme"] ?? "adaptive";
|
|
104
142
|
const lines = [];
|
|
105
143
|
const slug = toKebabCase(input.config.name);
|
|
106
144
|
const aliasedFamilies = /* @__PURE__ */ new Map();
|
|
107
145
|
lines.push(header("Visor Theme \u2014 NextJS Adapter"));
|
|
146
|
+
if (includeBaseLayer) {
|
|
147
|
+
lines.push('@import "@loworbitstudio/visor-core/reset";');
|
|
148
|
+
lines.push("");
|
|
149
|
+
}
|
|
108
150
|
if (includeFontImports && input.config.typography) {
|
|
109
151
|
const fontResult = resolveThemeFonts(input.config.typography);
|
|
110
152
|
const fontSlots = [fontResult.heading, fontResult.display, fontResult.body, fontResult.mono];
|
|
@@ -157,6 +199,27 @@ function nextjsAdapter(input, options) {
|
|
|
157
199
|
}
|
|
158
200
|
lines.push(LAYER_ORDER);
|
|
159
201
|
lines.push("");
|
|
202
|
+
if (includeBaseLayer) {
|
|
203
|
+
const baseLines = [];
|
|
204
|
+
if (colorScheme === "dark-only" || colorScheme === "light-only") {
|
|
205
|
+
baseLines.push(sectionComment("Base: UA color-scheme"));
|
|
206
|
+
baseLines.push(
|
|
207
|
+
block("html", [`color-scheme: ${colorScheme === "dark-only" ? "dark" : "light"};`])
|
|
208
|
+
);
|
|
209
|
+
baseLines.push("");
|
|
210
|
+
}
|
|
211
|
+
baseLines.push(sectionComment("Base: token-to-page binding"));
|
|
212
|
+
baseLines.push(
|
|
213
|
+
block(scopePrefix ?? "body", [
|
|
214
|
+
"font-family: var(--font-body);",
|
|
215
|
+
"font-size: 1rem;",
|
|
216
|
+
"color: var(--text-primary);",
|
|
217
|
+
"background: var(--surface-page, var(--surface-background));"
|
|
218
|
+
])
|
|
219
|
+
);
|
|
220
|
+
lines.push(wrapInLayer("visor-base", baseLines.join("\n").trim()));
|
|
221
|
+
lines.push("");
|
|
222
|
+
}
|
|
160
223
|
const primitivesBody = stripHeader(
|
|
161
224
|
generatePrimitivesCss(input.primitives, input.config, {
|
|
162
225
|
aliasedFamilies,
|
|
@@ -243,6 +306,15 @@ ${inner.split("\n").map((l) => ` ${l}`).join("\n")}
|
|
|
243
306
|
lines.push(
|
|
244
307
|
wrapInLayer("visor-adaptive", adaptiveBody)
|
|
245
308
|
);
|
|
309
|
+
const componentTokensCss = generateComponentTokensCss(
|
|
310
|
+
resolveComponentBindings(input.config.components),
|
|
311
|
+
{ light: hostSelector, dark: darkSelectors.join(",\n"), prefers: prefersSelector },
|
|
312
|
+
colorScheme
|
|
313
|
+
);
|
|
314
|
+
if (componentTokensCss) {
|
|
315
|
+
lines.push("");
|
|
316
|
+
lines.push(wrapInLayer("visor-adaptive", componentTokensCss));
|
|
317
|
+
}
|
|
246
318
|
if (includeFowt) {
|
|
247
319
|
lines.push("");
|
|
248
320
|
lines.push(
|
|
@@ -811,7 +883,17 @@ ${inner.split("\n").map((l) => ` ${l}`).join("\n")}
|
|
|
811
883
|
},
|
|
812
884
|
colorScheme
|
|
813
885
|
);
|
|
814
|
-
const
|
|
886
|
+
const componentTokensCss = generateComponentTokensCss(
|
|
887
|
+
resolveComponentBindings(input.config.components),
|
|
888
|
+
{
|
|
889
|
+
light: lightSel,
|
|
890
|
+
dark: darkSel,
|
|
891
|
+
prefers: `${scopeClass}:not(.light):not(.theme-light):not([data-theme="light"])`
|
|
892
|
+
},
|
|
893
|
+
colorScheme
|
|
894
|
+
);
|
|
895
|
+
const adaptiveBody = [lines.join("\n").trim(), componentTokensCss].filter(Boolean).join("\n\n");
|
|
896
|
+
const adaptiveLayer = wrapInLayer("visor-adaptive", adaptiveBody);
|
|
815
897
|
const semanticLayer = wrapInLayer("visor-semantic", semanticLines.join("\n").trim());
|
|
816
898
|
const brandLayerBody = [brandResult.css, passthroughCss].filter(Boolean).join("\n\n");
|
|
817
899
|
const brandLayer = wrapInLayer("visor-brand", brandLayerBody);
|