@loworbitstudio/visor-theme-engine 0.18.0 → 0.20.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 +5 -1
- package/dist/adapters/index.js +72 -25
- package/dist/{chunk-BUWBBUFG.js → chunk-JDYLDGUN.js} +610 -20
- package/dist/index.d.ts +272 -4
- package/dist/index.js +216 -4
- package/dist/{types-Cvm7vFwe.d.ts → types-BG-YT4JW.d.ts} +176 -1
- package/package.json +1 -1
- package/src/visor-theme.schema.json +134 -1
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-BG-YT4JW.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Adapter types for the Visor theme engine.
|
|
@@ -37,6 +37,10 @@ interface NextJSAdapterOptions extends AdapterOptions {
|
|
|
37
37
|
* `@layer visor-base` origination block that binds theme tokens to the page
|
|
38
38
|
* root (default: true). Set false for consumers that ship Tailwind preflight
|
|
39
39
|
* or their own reset. See VI-616.
|
|
40
|
+
*
|
|
41
|
+
* VI-638: the base block also carries `font-size: var(--font-size-base)`,
|
|
42
|
+
* which is how `typography.scale` reaches the page. A consumer that declines
|
|
43
|
+
* it must bind the base size itself — on `body`, not `:root`.
|
|
40
44
|
*/
|
|
41
45
|
includeBaseLayer?: boolean;
|
|
42
46
|
}
|
package/dist/adapters/index.js
CHANGED
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
collectBrandPassthrough,
|
|
9
9
|
fontStack,
|
|
10
10
|
generateDarkCss,
|
|
11
|
+
generateFontSizeDecls,
|
|
12
|
+
generateFontWeightDecls,
|
|
11
13
|
generateHairlineDecls,
|
|
12
14
|
generateIntentDecls,
|
|
13
15
|
generateLightCss,
|
|
@@ -17,10 +19,11 @@ import {
|
|
|
17
19
|
generateTextScaleAliasDecls,
|
|
18
20
|
header,
|
|
19
21
|
parseColor,
|
|
22
|
+
resolveComponentBindings,
|
|
20
23
|
resolveThemeBrand,
|
|
21
24
|
resolveThemeFonts,
|
|
22
25
|
sectionComment
|
|
23
|
-
} from "../chunk-
|
|
26
|
+
} from "../chunk-JDYLDGUN.js";
|
|
24
27
|
|
|
25
28
|
// src/adapters/brand-passthrough.ts
|
|
26
29
|
var SENTINEL_COLOR = "#ff00ff";
|
|
@@ -82,6 +85,42 @@ ${prefersInner}
|
|
|
82
85
|
return blocks.filter(Boolean).join("\n\n");
|
|
83
86
|
}
|
|
84
87
|
|
|
88
|
+
// src/adapters/component-tokens-css.ts
|
|
89
|
+
function indentBlock2(selector, decls) {
|
|
90
|
+
if (decls.length === 0) return "";
|
|
91
|
+
return [selector + " {", ...decls.map((d) => ` ${d}`), "}"].join("\n");
|
|
92
|
+
}
|
|
93
|
+
function declsFor(values) {
|
|
94
|
+
return Object.keys(values).sort().map((name) => `--${name}: ${values[name]};`);
|
|
95
|
+
}
|
|
96
|
+
function generateComponentTokensCss(tokens, selectors, colorScheme = "adaptive") {
|
|
97
|
+
const lightDecls = declsFor(tokens.light);
|
|
98
|
+
const darkDecls = declsFor(tokens.dark);
|
|
99
|
+
if (lightDecls.length === 0 && darkDecls.length === 0) return "";
|
|
100
|
+
const blocks = [
|
|
101
|
+
"/* \u2500\u2500 Component tokens (VI-625) \u2014 theme bindings for the admin-UI families \u2500\u2500 */"
|
|
102
|
+
];
|
|
103
|
+
if (colorScheme === "dark-only") {
|
|
104
|
+
blocks.push(indentBlock2(selectors.light, darkDecls));
|
|
105
|
+
return blocks.filter(Boolean).join("\n\n");
|
|
106
|
+
}
|
|
107
|
+
if (colorScheme === "light-only") {
|
|
108
|
+
blocks.push(indentBlock2(selectors.light, lightDecls));
|
|
109
|
+
return blocks.filter(Boolean).join("\n\n");
|
|
110
|
+
}
|
|
111
|
+
if (lightDecls.length > 0) {
|
|
112
|
+
blocks.push(indentBlock2(selectors.light, lightDecls));
|
|
113
|
+
}
|
|
114
|
+
if (darkDecls.length > 0) {
|
|
115
|
+
blocks.push(indentBlock2(selectors.dark, darkDecls));
|
|
116
|
+
const prefersInner = indentBlock2(selectors.prefers, darkDecls).split("\n").map((l) => ` ${l}`).join("\n");
|
|
117
|
+
blocks.push(`@media (prefers-color-scheme: dark) {
|
|
118
|
+
${prefersInner}
|
|
119
|
+
}`);
|
|
120
|
+
}
|
|
121
|
+
return blocks.filter(Boolean).join("\n\n");
|
|
122
|
+
}
|
|
123
|
+
|
|
85
124
|
// src/adapters/layers.ts
|
|
86
125
|
var LAYER_ORDER = "@layer visor-base, visor-primitives, visor-semantic, visor-brand, visor-adaptive, visor-bridge;";
|
|
87
126
|
function wrapInLayer(layerName, css) {
|
|
@@ -175,7 +214,11 @@ function nextjsAdapter(input, options) {
|
|
|
175
214
|
baseLines.push(
|
|
176
215
|
block(scopePrefix ?? "body", [
|
|
177
216
|
"font-family: var(--font-body);",
|
|
178
|
-
|
|
217
|
+
// VI-638: the scaled ramp is the single mechanism that sets type size,
|
|
218
|
+
// and the base step is what the page inherits. This binding lives on
|
|
219
|
+
// `body` (or the body-class scope), never `:root` — the ramp is
|
|
220
|
+
// expressed in `rem`, so a scaled root would multiply it a second time.
|
|
221
|
+
"font-size: var(--font-size-base, 1rem);",
|
|
179
222
|
"color: var(--text-primary);",
|
|
180
223
|
"background: var(--surface-page, var(--surface-background));"
|
|
181
224
|
])
|
|
@@ -269,6 +312,15 @@ ${inner.split("\n").map((l) => ` ${l}`).join("\n")}
|
|
|
269
312
|
lines.push(
|
|
270
313
|
wrapInLayer("visor-adaptive", adaptiveBody)
|
|
271
314
|
);
|
|
315
|
+
const componentTokensCss = generateComponentTokensCss(
|
|
316
|
+
resolveComponentBindings(input.config.components),
|
|
317
|
+
{ light: hostSelector, dark: darkSelectors.join(",\n"), prefers: prefersSelector },
|
|
318
|
+
colorScheme
|
|
319
|
+
);
|
|
320
|
+
if (componentTokensCss) {
|
|
321
|
+
lines.push("");
|
|
322
|
+
lines.push(wrapInLayer("visor-adaptive", componentTokensCss));
|
|
323
|
+
}
|
|
272
324
|
if (includeFowt) {
|
|
273
325
|
lines.push("");
|
|
274
326
|
lines.push(
|
|
@@ -491,23 +543,8 @@ function generateTypographyDecls(config, aliases) {
|
|
|
491
543
|
decls.push(`--font-heading: ${fontStack(headingFamily, aliases)};`);
|
|
492
544
|
decls.push(`--font-body: ${fontStack(config.typography.body.family, aliases)};`);
|
|
493
545
|
decls.push(`--font-mono: ${fontStack(config.typography.mono.family, aliases)};`);
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
sm: 14,
|
|
497
|
-
base: 16,
|
|
498
|
-
lg: 18,
|
|
499
|
-
xl: 20,
|
|
500
|
-
"2xl": 24,
|
|
501
|
-
"3xl": 30,
|
|
502
|
-
"4xl": 36
|
|
503
|
-
};
|
|
504
|
-
for (const [name, px] of Object.entries(fontSizes)) {
|
|
505
|
-
decls.push(`--font-size-${name}: ${px / 16}rem; /* ${px}px */`);
|
|
506
|
-
}
|
|
507
|
-
decls.push(`--font-weight-normal: ${config.typography.body.weight};`);
|
|
508
|
-
decls.push("--font-weight-medium: 500;");
|
|
509
|
-
decls.push(`--font-weight-semibold: ${config.typography.heading.weight};`);
|
|
510
|
-
decls.push("--font-weight-bold: 700;");
|
|
546
|
+
decls.push(...generateFontSizeDecls(config.typography.scale));
|
|
547
|
+
decls.push(...generateFontWeightDecls(config.typography));
|
|
511
548
|
const lineHeights = {
|
|
512
549
|
none: 1,
|
|
513
550
|
tight: 1.25,
|
|
@@ -640,7 +677,6 @@ function docsAdapter(input, options) {
|
|
|
640
677
|
fontLines.push("");
|
|
641
678
|
}
|
|
642
679
|
}
|
|
643
|
-
const scale = input.config.typography?.scale ?? 1;
|
|
644
680
|
const emittedFamilies = /* @__PURE__ */ new Set();
|
|
645
681
|
for (const font of fontSlots) {
|
|
646
682
|
if (font && font.source === "visor-fonts" && !emittedFamilies.has(font.family)) {
|
|
@@ -654,9 +690,6 @@ function docsAdapter(input, options) {
|
|
|
654
690
|
fontLines.push(` font-weight: ${weight};`);
|
|
655
691
|
fontLines.push(` font-style: ${font.italic ? "italic" : "normal"};`);
|
|
656
692
|
fontLines.push(` font-display: ${font.display};`);
|
|
657
|
-
if (scale !== 1) {
|
|
658
|
-
fontLines.push(` size-adjust: ${Math.round(scale * 100)}%;`);
|
|
659
|
-
}
|
|
660
693
|
fontLines.push("}");
|
|
661
694
|
fontLines.push("");
|
|
662
695
|
}
|
|
@@ -666,7 +699,11 @@ function docsAdapter(input, options) {
|
|
|
666
699
|
lines.push("\n/* \u2500\u2500 Section 1: Shared tokens (mode-independent) \u2500\u2500 */");
|
|
667
700
|
const sharedDecls = [
|
|
668
701
|
"min-height: 100vh;",
|
|
669
|
-
|
|
702
|
+
// VI-638: the scaled ramp is the single mechanism that sets type size, and
|
|
703
|
+
// the base step is what the page inherits. Safe here because the scope is a
|
|
704
|
+
// class on a wrapper, never `:root` — a scaled root would multiply the
|
|
705
|
+
// rem-expressed ramp a second time.
|
|
706
|
+
"font-size: var(--font-size-base, 1rem);",
|
|
670
707
|
// BO-56: pin UA chrome to the brand's single mode (adaptive emits nothing).
|
|
671
708
|
...singleMode ? [`color-scheme: ${singleMode};`] : [],
|
|
672
709
|
`background: var(--surface-page, var(--surface-background));`,
|
|
@@ -837,7 +874,17 @@ ${inner.split("\n").map((l) => ` ${l}`).join("\n")}
|
|
|
837
874
|
},
|
|
838
875
|
colorScheme
|
|
839
876
|
);
|
|
840
|
-
const
|
|
877
|
+
const componentTokensCss = generateComponentTokensCss(
|
|
878
|
+
resolveComponentBindings(input.config.components),
|
|
879
|
+
{
|
|
880
|
+
light: lightSel,
|
|
881
|
+
dark: darkSel,
|
|
882
|
+
prefers: `${scopeClass}:not(.light):not(.theme-light):not([data-theme="light"])`
|
|
883
|
+
},
|
|
884
|
+
colorScheme
|
|
885
|
+
);
|
|
886
|
+
const adaptiveBody = [lines.join("\n").trim(), componentTokensCss].filter(Boolean).join("\n\n");
|
|
887
|
+
const adaptiveLayer = wrapInLayer("visor-adaptive", adaptiveBody);
|
|
841
888
|
const semanticLayer = wrapInLayer("visor-semantic", semanticLines.join("\n").trim());
|
|
842
889
|
const brandLayerBody = [brandResult.css, passthroughCss].filter(Boolean).join("\n\n");
|
|
843
890
|
const brandLayer = wrapInLayer("visor-brand", brandLayerBody);
|