@loworbitstudio/visor-theme-engine 0.17.1 → 0.18.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.
@@ -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
  */
@@ -83,7 +83,7 @@ ${prefersInner}
83
83
  }
84
84
 
85
85
  // src/adapters/layers.ts
86
- var LAYER_ORDER = "@layer visor-primitives, visor-semantic, visor-brand, visor-adaptive, visor-bridge;";
86
+ var LAYER_ORDER = "@layer visor-base, visor-primitives, visor-semantic, visor-brand, visor-adaptive, visor-bridge;";
87
87
  function wrapInLayer(layerName, css) {
88
88
  const trimmed = css.trim();
89
89
  if (!trimmed) return "";
@@ -99,12 +99,17 @@ function toKebabCase(name) {
99
99
  function nextjsAdapter(input, options) {
100
100
  const includeFontImports = options?.includeFontImports ?? true;
101
101
  const includeFowt = options?.includeFowt ?? true;
102
+ const includeBaseLayer = options?.includeBaseLayer ?? true;
102
103
  const scopePrefix = options?.scopePrefix;
103
104
  const colorScheme = input.config["color-scheme"] ?? "adaptive";
104
105
  const lines = [];
105
106
  const slug = toKebabCase(input.config.name);
106
107
  const aliasedFamilies = /* @__PURE__ */ new Map();
107
108
  lines.push(header("Visor Theme \u2014 NextJS Adapter"));
109
+ if (includeBaseLayer) {
110
+ lines.push('@import "@loworbitstudio/visor-core/reset";');
111
+ lines.push("");
112
+ }
108
113
  if (includeFontImports && input.config.typography) {
109
114
  const fontResult = resolveThemeFonts(input.config.typography);
110
115
  const fontSlots = [fontResult.heading, fontResult.display, fontResult.body, fontResult.mono];
@@ -157,6 +162,27 @@ function nextjsAdapter(input, options) {
157
162
  }
158
163
  lines.push(LAYER_ORDER);
159
164
  lines.push("");
165
+ if (includeBaseLayer) {
166
+ const baseLines = [];
167
+ if (colorScheme === "dark-only" || colorScheme === "light-only") {
168
+ baseLines.push(sectionComment("Base: UA color-scheme"));
169
+ baseLines.push(
170
+ block("html", [`color-scheme: ${colorScheme === "dark-only" ? "dark" : "light"};`])
171
+ );
172
+ baseLines.push("");
173
+ }
174
+ baseLines.push(sectionComment("Base: token-to-page binding"));
175
+ baseLines.push(
176
+ block(scopePrefix ?? "body", [
177
+ "font-family: var(--font-body);",
178
+ "font-size: 1rem;",
179
+ "color: var(--text-primary);",
180
+ "background: var(--surface-page, var(--surface-background));"
181
+ ])
182
+ );
183
+ lines.push(wrapInLayer("visor-base", baseLines.join("\n").trim()));
184
+ lines.push("");
185
+ }
160
186
  const primitivesBody = stripHeader(
161
187
  generatePrimitivesCss(input.primitives, input.config, {
162
188
  aliasedFamilies,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loworbitstudio/visor-theme-engine",
3
- "version": "0.17.1",
3
+ "version": "0.18.0",
4
4
  "description": "Theme engine for the Visor design system — shade generation, token mapping, font resolution, and import/export for .visor.yaml themes.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",