@loworbitstudio/visor-theme-engine 0.25.0 → 0.29.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/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FontResolveOptions, a as FontResolution, V as VisorTypography, b as FontDisplayStrategy, T as ThemeFontResult, G as GoogleFontEntry, c as VisorBrand, B as BrandSlot, d as BrandSource, e as BrandResolution, C as ColorScheme, f as ThemeBrandResult, g as BrandStrategy, h as BrandStrategyContext, i as BrandStrategyIssue, j as BrandStrategyValidationResult, S as SerializedBrandStrategy, R as ResolvedThemeConfig, k as GeneratedPrimitives, l as ThemeOutput, m as ThemeData, n as VisorThemeConfig, o as FullShadeScale, p as ColorRole, q as SelectiveShadeScale, r as RGB, P as ParsedColor, O as OKLCH, s as SemanticTokens, t as ShadeStep } from './types-ZPTjTL_-.js';
2
- export { u as BRAND_VARIANTS, v as BRAND_VISIBILITIES, w as BrandAccessibility, x as BrandArchetype, y as BrandBoilerplate, z as BrandColorPairing, A as BrandColorUsage, D as BrandContrastTarget, E as BrandGoverns, H as BrandLexiconEntry, I as BrandMessaging, J as BrandPersonalityTrait, K as BrandPillar, L as BrandPositioning, M as BrandStrategyIssueSeverity, N as BrandToneEntry, Q as BrandVariant, U as BrandVisibility, W as BrandVoice, X as BrandVoiceTrait, Y as COMPONENT_TOKEN_FAMILIES, Z as COMPONENT_TOKEN_FAMILY_BY_NAME, _ as ColorFormat, $ as ComponentTokenBinding, a0 as ComponentTokenBindings, a1 as ComponentTokenConsumer, a2 as ComponentTokenFamily, a3 as ComponentTokenSpec, a4 as DEFAULT_BRAND_STRATEGY_SURFACES, a5 as DEFAULT_BRAND_STRATEGY_TONE_STATES, a6 as FontSource, a7 as GOVERNS_WILDCARD, a8 as RGBA, a9 as ResolvedComponentTokens, aa as SemanticTokenValue, ab as allComponentTokenNames, ac as componentTokenName, ad as hasComponentBindings, ae as resolveComponentBindings, af as validateComponentBindings } from './types-ZPTjTL_-.js';
1
+ import { F as FontResolveOptions, a as FontResolution, V as VisorTypography, b as FontDisplayStrategy, T as ThemeFontResult, G as GoogleFontEntry, c as VisorBrand, B as BrandSlot, d as BrandSource, e as BrandResolution, C as ColorScheme, f as ThemeBrandResult, g as BrandStrategy, h as BrandStrategyContext, i as BrandStrategyIssue, j as BrandStrategyValidationResult, S as SerializedBrandStrategy, R as ResolvedThemeConfig, k as GeneratedPrimitives, l as ThemeOutput, m as ThemeData, n as VisorThemeConfig, o as FullShadeScale, p as ColorRole, q as SelectiveShadeScale, r as RGB, P as ParsedColor, O as OKLCH, s as SemanticTokens, t as ShadeStep } from './types-C7nWZ5fB.js';
2
+ export { u as BRAND_VARIANTS, v as BRAND_VISIBILITIES, w as BrandAccessibility, x as BrandArchetype, y as BrandBoilerplate, z as BrandColorPairing, A as BrandColorUsage, D as BrandContrastTarget, E as BrandGoverns, H as BrandLexiconEntry, I as BrandMessaging, J as BrandPersonalityTrait, K as BrandPillar, L as BrandPositioning, M as BrandStrategyIssueSeverity, N as BrandToneEntry, Q as BrandVariant, U as BrandVisibility, W as BrandVoice, X as BrandVoiceTrait, Y as COMPONENT_TOKEN_FAMILIES, Z as COMPONENT_TOKEN_FAMILY_BY_NAME, _ as ColorFormat, $ as ComponentTokenBinding, a0 as ComponentTokenBindings, a1 as ComponentTokenConsumer, a2 as ComponentTokenFamily, a3 as ComponentTokenSpec, a4 as DEFAULT_BRAND_STRATEGY_SURFACES, a5 as DEFAULT_BRAND_STRATEGY_TONE_STATES, a6 as FontSource, a7 as GOVERNS_WILDCARD, a8 as RGBA, a9 as ResolvedComponentTokens, aa as SemanticTokenValue, ab as allComponentTokenNames, ac as componentTokenName, ad as hasComponentBindings, ae as resolveComponentBindings, af as validateComponentBindings } from './types-C7nWZ5fB.js';
3
3
 
4
4
  /**
5
5
  * Font resolver — maps font family names to loadable font resources.
@@ -527,6 +527,16 @@ var properties = {
527
527
  org: {
528
528
  type: "string",
529
529
  description: "Organization namespace for visor-fonts CDN (required when source is visor-fonts)."
530
+ },
531
+ "text-transform": {
532
+ type: "string",
533
+ "enum": [
534
+ "none",
535
+ "uppercase",
536
+ "lowercase",
537
+ "capitalize"
538
+ ],
539
+ description: "Casing applied to this slot's text via --font-heading-text-transform. Emitted only when set."
530
540
  }
531
541
  }
532
542
  },
@@ -557,6 +567,16 @@ var properties = {
557
567
  org: {
558
568
  type: "string",
559
569
  description: "Organization namespace for visor-fonts CDN (required when source is visor-fonts)."
570
+ },
571
+ "text-transform": {
572
+ type: "string",
573
+ "enum": [
574
+ "none",
575
+ "uppercase",
576
+ "lowercase",
577
+ "capitalize"
578
+ ],
579
+ description: "Casing applied to this slot's text via --font-display-text-transform. Emitted only when set."
560
580
  }
561
581
  }
562
582
  },
@@ -586,6 +606,16 @@ var properties = {
586
606
  org: {
587
607
  type: "string",
588
608
  description: "Organization namespace for visor-fonts CDN (required when source is visor-fonts)."
609
+ },
610
+ "text-transform": {
611
+ type: "string",
612
+ "enum": [
613
+ "none",
614
+ "uppercase",
615
+ "lowercase",
616
+ "capitalize"
617
+ ],
618
+ description: "Casing applied to this slot's text via --font-body-text-transform. Emitted only when set."
589
619
  }
590
620
  }
591
621
  },
@@ -596,6 +626,16 @@ var properties = {
596
626
  family: {
597
627
  type: "string",
598
628
  description: "Google Fonts family name or CSS font stack for monospace."
629
+ },
630
+ "text-transform": {
631
+ type: "string",
632
+ "enum": [
633
+ "none",
634
+ "uppercase",
635
+ "lowercase",
636
+ "capitalize"
637
+ ],
638
+ description: "Casing applied to this slot's text via --font-mono-text-transform. Emitted only when set."
599
639
  }
600
640
  }
601
641
  },
@@ -1144,6 +1184,34 @@ var properties = {
1144
1184
  $ref: "#/$defs/componentTokenBinding"
1145
1185
  }
1146
1186
  },
1187
+ input: {
1188
+ type: "object",
1189
+ description: "Input shape at the default `md` size. Each key falls back to the matching `--input-*-md` variable, so a scope that sets one still applies while the key is unbound; a bound key wins. Keys: md-height, md-padding, md-radius.",
1190
+ additionalProperties: {
1191
+ $ref: "#/$defs/componentTokenBinding"
1192
+ }
1193
+ },
1194
+ textarea: {
1195
+ type: "object",
1196
+ description: "Textarea shape at the default `md` size. Keys: padding, radius.",
1197
+ additionalProperties: {
1198
+ $ref: "#/$defs/componentTokenBinding"
1199
+ }
1200
+ },
1201
+ select: {
1202
+ type: "object",
1203
+ description: "Select trigger shape at the default `md` size. Keys: height, padding, radius.",
1204
+ additionalProperties: {
1205
+ $ref: "#/$defs/componentTokenBinding"
1206
+ }
1207
+ },
1208
+ "tag-input": {
1209
+ type: "object",
1210
+ description: "TagInput — the field around the tags, each held tag, and the opt-in typing slot (`entryAs=\"slot\"`). The slot follows the tag's shape unless its own keys are set. Keys: min-height, padding, radius, tag-height, tag-padding-x, tag-font-size, tag-font-weight, tag-radius, slot-height, slot-padding-x, slot-radius, slot-min-width.",
1211
+ additionalProperties: {
1212
+ $ref: "#/$defs/componentTokenBinding"
1213
+ }
1214
+ },
1147
1215
  hairline: {
1148
1216
  type: "object",
1149
1217
  description: "The one switch for hairlines (VI-680). Every hairline rule, divider and ring reads its weight from `--hairline-width`, so `width: 0` removes them all at once. Independent of the `control` edge switch. Keys: width.",
@@ -1153,7 +1221,7 @@ var properties = {
1153
1221
  },
1154
1222
  control: {
1155
1223
  type: "object",
1156
- description: "The one switch for form-control edges (VI-655). Every form control draws its resting edge from these, so `edge-width: 0` removes every resting edge at once, dashed edges included, with no layout shift. Keys: edge-width, edge-color, edge-style, drop-edge-width, drop-edge-style, state-edge-width.",
1224
+ description: "The one switch for form-control edges (VI-655). Every form control draws its resting edge from these, so `edge-width: 0` removes every resting edge at once, dashed edges included, with no layout shift. Keys: edge-width, edge-color, edge-style, drop-edge-width, drop-edge-style, state-edge-width, invalid-ring-width, invalid-halo-width.",
1157
1225
  additionalProperties: {
1158
1226
  $ref: "#/$defs/componentTokenBinding"
1159
1227
  }
@@ -1174,7 +1242,7 @@ var properties = {
1174
1242
  },
1175
1243
  button: {
1176
1244
  type: "object",
1177
- description: "Button type treatment and rounding. The unprefixed keys set every size at once; a size key (`dlg-radius`) overrides one size. Keys: text-transform, letter-spacing, radius, sm-font-size, sm-text-transform, sm-letter-spacing, sm-radius, md-font-size, md-text-transform, md-letter-spacing, md-radius, lg-font-size, lg-text-transform, lg-letter-spacing, lg-radius, dlg-font-size, dlg-text-transform, dlg-letter-spacing, dlg-radius, icon-size, icon-pad, icon-radius, icon-ghost-color.",
1245
+ description: "Button type treatment and rounding. The unprefixed keys set every size at once; a size key (`dlg-radius`) overrides one size. Keys: text-transform, letter-spacing, font-weight, radius, sm-font-size, sm-font-weight, sm-text-transform, sm-letter-spacing, sm-radius, md-font-size, md-font-weight, md-text-transform, md-letter-spacing, md-radius, lg-font-size, lg-font-weight, lg-text-transform, lg-letter-spacing, lg-radius, dlg-font-size, dlg-font-weight, dlg-text-transform, dlg-letter-spacing, dlg-radius, icon-size, icon-pad, icon-radius, icon-ghost-color.",
1178
1246
  additionalProperties: {
1179
1247
  $ref: "#/$defs/componentTokenBinding"
1180
1248
  }
@@ -1188,14 +1256,21 @@ var properties = {
1188
1256
  },
1189
1257
  "switch": {
1190
1258
  type: "object",
1191
- description: "Switch track and knob dimensions (default size; `size=\"sm\"` keeps its own). Set `knob-inset` to size the knob from the track: it sits that far from the track's outer edge on every side. Keys: track-width, track-height, knob-inset, track-bg, edge-color.",
1259
+ description: "Switch track and knob dimensions (default size; `size=\"sm\"` keeps its own) and colours. Set `knob-inset` to size the knob from the track: it sits that far from the track's outer edge on every side. Keys: track-width, track-height, knob-inset, track-bg, edge-color, track-hover-bg, track-hover-bg-checked, knob-bg, knob-bg-checked.",
1192
1260
  additionalProperties: {
1193
1261
  $ref: "#/$defs/componentTokenBinding"
1194
1262
  }
1195
1263
  },
1196
1264
  "save-status": {
1197
1265
  type: "object",
1198
- description: "SaveStatus readout — the fixed-width slot, its type, the Syncing ink and the Unsaved dot, so the readout never reflows its row. Keys: width, syncing-color, dot-size, font-family, text-transform, letter-spacing.",
1266
+ description: "SaveStatus readout — the fixed-width slot, its type, the Syncing ink and the Unsaved dot, so the readout never reflows its row. Keys: width, syncing-color, font-size, dot-size, unsaved-dot-size, font-family, text-transform, letter-spacing.",
1267
+ additionalProperties: {
1268
+ $ref: "#/$defs/componentTokenBinding"
1269
+ }
1270
+ },
1271
+ "segmented-control": {
1272
+ type: "object",
1273
+ description: "SegmentedControl — the well, its corner radius, the sliding pill, the ink and the state edge on it. The resting edge is the shared `control` edge. Keys: track-bg, radius, indicator-bg, indicator-text, indicator-edge, inactive-text, active-weight.",
1199
1274
  additionalProperties: {
1200
1275
  $ref: "#/$defs/componentTokenBinding"
1201
1276
  }
@@ -1214,6 +1289,20 @@ var properties = {
1214
1289
  $ref: "#/$defs/componentTokenBinding"
1215
1290
  }
1216
1291
  },
1292
+ "input-affix": {
1293
+ type: "object",
1294
+ description: "Input and NumberInput prefix and suffix: the gap between a fixed affix and the value, and the affix's ink. Keys: gap, color.",
1295
+ additionalProperties: {
1296
+ $ref: "#/$defs/componentTokenBinding"
1297
+ }
1298
+ },
1299
+ separator: {
1300
+ type: "object",
1301
+ description: "Separator rule colour, bare or either side of a label. Keys: color.",
1302
+ additionalProperties: {
1303
+ $ref: "#/$defs/componentTokenBinding"
1304
+ }
1305
+ },
1217
1306
  "admin-ui": {
1218
1307
  type: "object",
1219
1308
  description: "Structural roles the admin-ui pattern owns. `marquee-family` is the display face for KPI hero figures and marquee page titles — the role the admin-ui portability audit named as the one piece of ENTR brand coupling a new theme must rebind. Keys: marquee-family.",
@@ -2005,6 +2094,25 @@ declare function getKnownTokenRefs(): Set<string>;
2005
2094
  * a diff against that file readable.
2006
2095
  */
2007
2096
  declare const VISOR_CORE_SEMANTIC_ALIASES: Readonly<Record<string, string>>;
2097
+ /**
2098
+ * Aliases visor-core declares with a **different referent in dark mode**, mapped
2099
+ * to that dark referent. `--sidebar-bg` is `var(--color-neutral-50)` on `:root`
2100
+ * but `var(--color-neutral-900)` under `[data-theme="dark"]` and the
2101
+ * prefers-color-scheme block.
2102
+ *
2103
+ * `VISOR_CORE_SEMANTIC_ALIASES` records the light referent. A theme scope
2104
+ * re-declares these with the light referent on the host and with the dark one
2105
+ * on its dark selectors (VI-696), so a scoped dark sidebar resolves to the
2106
+ * theme's own `neutral-900`, not its near-white `neutral-50` (the VI-648 flat
2107
+ * emission) nor visor-core's untuned default (the VI-695 skip).
2108
+ *
2109
+ * Pinned against the dark rules of the emitted `tokens.css` by
2110
+ * `semantic-alias-coverage`: both the key set and every referent. A new
2111
+ * mode-dependent alias, or a changed dark referent, fails there by name.
2112
+ */
2113
+ declare const VISOR_CORE_DARK_SEMANTIC_ALIASES: Readonly<Record<string, string>>;
2114
+ /** The aliases in `VISOR_CORE_DARK_SEMANTIC_ALIASES`: the ones whose referent changes with the mode. */
2115
+ declare const MODE_DEPENDENT_SEMANTIC_ALIASES: ReadonlySet<string>;
2008
2116
  /**
2009
2117
  * Every custom property declared anywhere in `css`, without the leading `--`.
2010
2118
  *
@@ -2012,8 +2120,13 @@ declare const VISOR_CORE_SEMANTIC_ALIASES: Readonly<Record<string, string>>;
2012
2120
  * `generateSemanticAliasDecls` reflects what this theme *actually* emits —
2013
2121
  * including conditional output such as the `--font-weight-<n>` ladder, which
2014
2122
  * only appears when a theme declares an explicit `weights` array.
2123
+ *
2124
+ * `options.exclude` drops the rules whose selector is listed, for a caller that
2125
+ * needs only what one mode's selector can see (VI-696).
2015
2126
  */
2016
- declare function collectDeclaredProperties(css: string): Set<string>;
2127
+ declare function collectDeclaredProperties(css: string, options?: {
2128
+ exclude?: readonly string[];
2129
+ }): Set<string>;
2017
2130
  /**
2018
2131
  * The `--alias: var(--referent);` declarations to re-emit on a theme's scope
2019
2132
  * selector, given everything the theme has emitted so far.
@@ -2030,11 +2143,20 @@ declare function collectDeclaredProperties(css: string): Set<string>;
2030
2143
  * the correct outcome — re-emitting would replace a working value with an
2031
2144
  * invalid one.
2032
2145
  *
2146
+ * `options.skip` names aliases to leave inheriting visor-core's value.
2147
+ *
2148
+ * `options.table` swaps the alias → referent table. A dark selector passes
2149
+ * `VISOR_CORE_DARK_SEMANTIC_ALIASES`, with `declared` read off only what that
2150
+ * selector sees; a dark-only host passes `VISOR_CORE_SEMANTIC_ALIASES_DARK_HOST`.
2151
+ *
2033
2152
  * Returns `[]` for a `:root`-scoped theme's caller, which does not need this at
2034
2153
  * all: there, visor-core's aliases and the theme's primitives are declared on
2035
2154
  * the same element, so substitution already sees the theme's values.
2036
2155
  */
2037
- declare function generateSemanticAliasDecls(declared: ReadonlySet<string>): string[];
2156
+ declare function generateSemanticAliasDecls(declared: ReadonlySet<string>, options?: {
2157
+ skip?: ReadonlySet<string>;
2158
+ table?: Readonly<Record<string, string>>;
2159
+ }): string[];
2038
2160
 
2039
2161
  /**
2040
2162
  * Per-theme font-family aliasing — substrate fix for VI-354.
@@ -2286,4 +2408,36 @@ declare function cleanFontValue(val: string): string;
2286
2408
  */
2287
2409
  declare function extractFromCSS(files: CSSFile[], name?: string): ExtractionResult;
2288
2410
 
2289
- export { type BrandPassthrough, BrandResolution, BrandSlot, BrandSource, BrandStrategy, BrandStrategyContext, BrandStrategyIssue, BrandStrategyValidationResult, type CSSFile, ColorRole, type Confidence, DEFAULT_VISOR_BRAND, type ExtractedToken, type ExtractionResult, FONT_WEIGHT_ALIASES, type FontCoverageError, type FontCoverageResult, FontDisplayStrategy, type FontFaceDeclaration, FontResolution, FontResolveOptions, FullShadeScale, GeneratedPrimitives, GoogleFontEntry, OKLCH, ParsedColor, RGB, ResolvedThemeConfig, type ResolvedWeightRamp, SEMANTIC_MAP, SelectiveShadeScale, SemanticTokens, SerializedBrandStrategy, ShadeStep, TAILWIND_GRAY, ThemeBrandResult, ThemeData, ThemeFontResult, ThemeOutput, type ThemeValidationResult, VISOR_BRANDS_CDN, VISOR_CORE_SEMANTIC_ALIASES, VISOR_DEFAULT_BRAND_PATH, VISOR_FONTS_CDN, type ValidateOptions, type ValidationIssue, type ValidationSeverity, VisorBrand, VisorThemeConfig, VisorTypography, WEIGHT_RAMP_TARGETS, applyOverrides, assignSemanticTokens, buildVisorBrandUrl, buildVisorFontUrl, checkBrandStrategyCoherence, checkBrandStrategyStructure, clampToSrgb, cleanFontValue, collectBrandPassthrough, collectDeclaredProperties, compositeOverBackground, declaresWeights, exportTheme, extractFromCSS, formatFontCoverageError, generateDarkCss, generateFontWeightDecls, generateFullBundleCss, generateLightCss, generatePreloadLinks, generatePrimitives, generatePrimitivesCss, generateSemanticAliasDecls, generateSemanticCss, generateShadeScale, generateStylesheetLinks, generateTheme, generateThemeData, generateThemeDataFromConfig, generateThemeFromConfig, getContrastRatio, getKnownTokenRefs, getLuminance, googleFontsCatalog, hasBrandPassthrough, hexToOklch, hexToRgb, isValidColor, isValidHex, isVisorThemeConfig, loadedWeights, lookupFontWeightAlias, lookupGoogleFont, matchLoadedWeight, normalizeHex, oklchToHex, parseCSSDeclarations, parseColor, parseConfig, parseFontFaceDeclarations, parseHex, parseHsla, parseOklch, parseRgba, resolveBrandSlot, resolveBrandSource, resolveConfig, resolveFont, resolveRoleWeight, resolveThemeBrand, resolveThemeFonts, resolveWeightRamp, rgbToHex, serializeBrandStrategy, serializeColor, validate, validateBrandStrategy, validateConfig, validateFontCoverage, visorTheme_schema as visorThemeSchema };
2411
+ /**
2412
+ * Vertical font metrics for centring a native <input>'s text (VI-684).
2413
+ *
2414
+ * A native input cannot be trimmed to its capital band without clipping
2415
+ * descenders and accents, so its capitals sit wherever the font's line box puts
2416
+ * them: half a line above the box centre plus (ascent - descent) / 2, each
2417
+ * rounded to a whole px. That depends on the face, so input.module.css reads
2418
+ * `--font-ascent` / `--font-descent` (unitless em ratios) to work out the
2419
+ * padding that lands the baseline on the right pixel.
2420
+ *
2421
+ * The ratios are Chromium's own `fontBoundingBoxAscent` / `Descent` at 1000px
2422
+ * (what its line layout rounds), measured once from the real faces by
2423
+ * scripts/measure-font-metrics.mjs and committed here. Measuring at build time
2424
+ * would put a network fetch and a font parser on every theme build.
2425
+ *
2426
+ * A face with no entry emits no tokens, and the input takes no nudge: it renders
2427
+ * as it did before VI-684 (within about 1px of centre), never worse.
2428
+ *
2429
+ * `system-ui` is platform-dependent. The entry is what Chromium resolves on
2430
+ * macOS (San Francisco). Windows and Linux resolve another face, so the nudge
2431
+ * there is a best effort; override it with --font-ascent / --font-descent.
2432
+ */
2433
+ interface FontVerticalMetrics {
2434
+ /** Ascent as a fraction of the font size. */
2435
+ ascent: number;
2436
+ /** Descent as a fraction of the font size. */
2437
+ descent: number;
2438
+ }
2439
+ declare const FONT_VERTICAL_METRICS: Record<string, FontVerticalMetrics>;
2440
+ /** The `--font-ascent` / `--font-descent` declarations for a body family, or none when the face is unmeasured. */
2441
+ declare function generateFontMetricDecls(family: string): string[];
2442
+
2443
+ export { type BrandPassthrough, BrandResolution, BrandSlot, BrandSource, BrandStrategy, BrandStrategyContext, BrandStrategyIssue, BrandStrategyValidationResult, type CSSFile, ColorRole, type Confidence, DEFAULT_VISOR_BRAND, type ExtractedToken, type ExtractionResult, FONT_VERTICAL_METRICS, FONT_WEIGHT_ALIASES, type FontCoverageError, type FontCoverageResult, FontDisplayStrategy, type FontFaceDeclaration, FontResolution, FontResolveOptions, type FontVerticalMetrics, FullShadeScale, GeneratedPrimitives, GoogleFontEntry, MODE_DEPENDENT_SEMANTIC_ALIASES, OKLCH, ParsedColor, RGB, ResolvedThemeConfig, type ResolvedWeightRamp, SEMANTIC_MAP, SelectiveShadeScale, SemanticTokens, SerializedBrandStrategy, ShadeStep, TAILWIND_GRAY, ThemeBrandResult, ThemeData, ThemeFontResult, ThemeOutput, type ThemeValidationResult, VISOR_BRANDS_CDN, VISOR_CORE_DARK_SEMANTIC_ALIASES, VISOR_CORE_SEMANTIC_ALIASES, VISOR_DEFAULT_BRAND_PATH, VISOR_FONTS_CDN, type ValidateOptions, type ValidationIssue, type ValidationSeverity, VisorBrand, VisorThemeConfig, VisorTypography, WEIGHT_RAMP_TARGETS, applyOverrides, assignSemanticTokens, buildVisorBrandUrl, buildVisorFontUrl, checkBrandStrategyCoherence, checkBrandStrategyStructure, clampToSrgb, cleanFontValue, collectBrandPassthrough, collectDeclaredProperties, compositeOverBackground, declaresWeights, exportTheme, extractFromCSS, formatFontCoverageError, generateDarkCss, generateFontMetricDecls, generateFontWeightDecls, generateFullBundleCss, generateLightCss, generatePreloadLinks, generatePrimitives, generatePrimitivesCss, generateSemanticAliasDecls, generateSemanticCss, generateShadeScale, generateStylesheetLinks, generateTheme, generateThemeData, generateThemeDataFromConfig, generateThemeFromConfig, getContrastRatio, getKnownTokenRefs, getLuminance, googleFontsCatalog, hasBrandPassthrough, hexToOklch, hexToRgb, isValidColor, isValidHex, isVisorThemeConfig, loadedWeights, lookupFontWeightAlias, lookupGoogleFont, matchLoadedWeight, normalizeHex, oklchToHex, parseCSSDeclarations, parseColor, parseConfig, parseFontFaceDeclarations, parseHex, parseHsla, parseOklch, parseRgba, resolveBrandSlot, resolveBrandSource, resolveConfig, resolveFont, resolveRoleWeight, resolveThemeBrand, resolveThemeFonts, resolveWeightRamp, rgbToHex, serializeBrandStrategy, serializeColor, validate, validateBrandStrategy, validateConfig, validateFontCoverage, visorTheme_schema as visorThemeSchema };
package/dist/index.js CHANGED
@@ -3,10 +3,14 @@ import {
3
3
  COMPONENT_TOKEN_FAMILIES,
4
4
  COMPONENT_TOKEN_FAMILY_BY_NAME,
5
5
  DEFAULT_VISOR_BRAND,
6
+ FONT_VERTICAL_METRICS,
6
7
  FONT_WEIGHT_ALIASES,
7
8
  MATERIAL_TEXT_SLOTS,
9
+ MODE_DEPENDENT_SEMANTIC_ALIASES,
8
10
  TAILWIND_GRAY,
11
+ TEXT_TRANSFORMS,
9
12
  VISOR_BRANDS_CDN,
13
+ VISOR_CORE_DARK_SEMANTIC_ALIASES,
10
14
  VISOR_CORE_SEMANTIC_ALIASES,
11
15
  VISOR_DEFAULT_BRAND_PATH,
12
16
  VISOR_FONTS_CDN,
@@ -22,6 +26,7 @@ import {
22
26
  compositeOverBackground,
23
27
  declaresWeights,
24
28
  generateDarkCss,
29
+ generateFontMetricDecls,
25
30
  generateFontWeightDecls,
26
31
  generateFullBundleCss,
27
32
  generateLightCss,
@@ -63,7 +68,7 @@ import {
63
68
  rgbToOklch,
64
69
  serializeColor,
65
70
  validateComponentBindings
66
- } from "./chunk-C2DUPZVY.js";
71
+ } from "./chunk-YMCDUC7N.js";
67
72
 
68
73
  // src/fonts/validate-coverage.ts
69
74
  var FONT_VAR_RE = /--font-(heading|display|body|sans|mono)\s*:\s*([^;]+);/g;
@@ -747,6 +752,11 @@ var visor_theme_schema_default = {
747
752
  org: {
748
753
  type: "string",
749
754
  description: "Organization namespace for visor-fonts CDN (required when source is visor-fonts)."
755
+ },
756
+ "text-transform": {
757
+ type: "string",
758
+ enum: ["none", "uppercase", "lowercase", "capitalize"],
759
+ description: "Casing applied to this slot's text via --font-heading-text-transform. Emitted only when set."
750
760
  }
751
761
  }
752
762
  },
@@ -773,6 +783,11 @@ var visor_theme_schema_default = {
773
783
  org: {
774
784
  type: "string",
775
785
  description: "Organization namespace for visor-fonts CDN (required when source is visor-fonts)."
786
+ },
787
+ "text-transform": {
788
+ type: "string",
789
+ enum: ["none", "uppercase", "lowercase", "capitalize"],
790
+ description: "Casing applied to this slot's text via --font-display-text-transform. Emitted only when set."
776
791
  }
777
792
  }
778
793
  },
@@ -798,6 +813,11 @@ var visor_theme_schema_default = {
798
813
  org: {
799
814
  type: "string",
800
815
  description: "Organization namespace for visor-fonts CDN (required when source is visor-fonts)."
816
+ },
817
+ "text-transform": {
818
+ type: "string",
819
+ enum: ["none", "uppercase", "lowercase", "capitalize"],
820
+ description: "Casing applied to this slot's text via --font-body-text-transform. Emitted only when set."
801
821
  }
802
822
  }
803
823
  },
@@ -808,6 +828,11 @@ var visor_theme_schema_default = {
808
828
  family: {
809
829
  type: "string",
810
830
  description: "Google Fonts family name or CSS font stack for monospace."
831
+ },
832
+ "text-transform": {
833
+ type: "string",
834
+ enum: ["none", "uppercase", "lowercase", "capitalize"],
835
+ description: "Casing applied to this slot's text via --font-mono-text-transform. Emitted only when set."
811
836
  }
812
837
  }
813
838
  },
@@ -1180,6 +1205,34 @@ var visor_theme_schema_default = {
1180
1205
  $ref: "#/$defs/componentTokenBinding"
1181
1206
  }
1182
1207
  },
1208
+ input: {
1209
+ type: "object",
1210
+ description: "Input shape at the default `md` size. Each key falls back to the matching `--input-*-md` variable, so a scope that sets one still applies while the key is unbound; a bound key wins. Keys: md-height, md-padding, md-radius.",
1211
+ additionalProperties: {
1212
+ $ref: "#/$defs/componentTokenBinding"
1213
+ }
1214
+ },
1215
+ textarea: {
1216
+ type: "object",
1217
+ description: "Textarea shape at the default `md` size. Keys: padding, radius.",
1218
+ additionalProperties: {
1219
+ $ref: "#/$defs/componentTokenBinding"
1220
+ }
1221
+ },
1222
+ select: {
1223
+ type: "object",
1224
+ description: "Select trigger shape at the default `md` size. Keys: height, padding, radius.",
1225
+ additionalProperties: {
1226
+ $ref: "#/$defs/componentTokenBinding"
1227
+ }
1228
+ },
1229
+ "tag-input": {
1230
+ type: "object",
1231
+ description: 'TagInput \u2014 the field around the tags, each held tag, and the opt-in typing slot (`entryAs="slot"`). The slot follows the tag\'s shape unless its own keys are set. Keys: min-height, padding, radius, tag-height, tag-padding-x, tag-font-size, tag-font-weight, tag-radius, slot-height, slot-padding-x, slot-radius, slot-min-width.',
1232
+ additionalProperties: {
1233
+ $ref: "#/$defs/componentTokenBinding"
1234
+ }
1235
+ },
1183
1236
  hairline: {
1184
1237
  type: "object",
1185
1238
  description: "The one switch for hairlines (VI-680). Every hairline rule, divider and ring reads its weight from `--hairline-width`, so `width: 0` removes them all at once. Independent of the `control` edge switch. Keys: width.",
@@ -1189,7 +1242,7 @@ var visor_theme_schema_default = {
1189
1242
  },
1190
1243
  control: {
1191
1244
  type: "object",
1192
- description: "The one switch for form-control edges (VI-655). Every form control draws its resting edge from these, so `edge-width: 0` removes every resting edge at once, dashed edges included, with no layout shift. Keys: edge-width, edge-color, edge-style, drop-edge-width, drop-edge-style, state-edge-width.",
1245
+ description: "The one switch for form-control edges (VI-655). Every form control draws its resting edge from these, so `edge-width: 0` removes every resting edge at once, dashed edges included, with no layout shift. Keys: edge-width, edge-color, edge-style, drop-edge-width, drop-edge-style, state-edge-width, invalid-ring-width, invalid-halo-width.",
1193
1246
  additionalProperties: {
1194
1247
  $ref: "#/$defs/componentTokenBinding"
1195
1248
  }
@@ -1210,7 +1263,7 @@ var visor_theme_schema_default = {
1210
1263
  },
1211
1264
  button: {
1212
1265
  type: "object",
1213
- description: "Button type treatment and rounding. The unprefixed keys set every size at once; a size key (`dlg-radius`) overrides one size. Keys: text-transform, letter-spacing, radius, sm-font-size, sm-text-transform, sm-letter-spacing, sm-radius, md-font-size, md-text-transform, md-letter-spacing, md-radius, lg-font-size, lg-text-transform, lg-letter-spacing, lg-radius, dlg-font-size, dlg-text-transform, dlg-letter-spacing, dlg-radius, icon-size, icon-pad, icon-radius, icon-ghost-color.",
1266
+ description: "Button type treatment and rounding. The unprefixed keys set every size at once; a size key (`dlg-radius`) overrides one size. Keys: text-transform, letter-spacing, font-weight, radius, sm-font-size, sm-font-weight, sm-text-transform, sm-letter-spacing, sm-radius, md-font-size, md-font-weight, md-text-transform, md-letter-spacing, md-radius, lg-font-size, lg-font-weight, lg-text-transform, lg-letter-spacing, lg-radius, dlg-font-size, dlg-font-weight, dlg-text-transform, dlg-letter-spacing, dlg-radius, icon-size, icon-pad, icon-radius, icon-ghost-color.",
1214
1267
  additionalProperties: {
1215
1268
  $ref: "#/$defs/componentTokenBinding"
1216
1269
  }
@@ -1224,14 +1277,21 @@ var visor_theme_schema_default = {
1224
1277
  },
1225
1278
  switch: {
1226
1279
  type: "object",
1227
- description: 'Switch track and knob dimensions (default size; `size="sm"` keeps its own). Set `knob-inset` to size the knob from the track: it sits that far from the track\'s outer edge on every side. Keys: track-width, track-height, knob-inset, track-bg, edge-color.',
1280
+ description: 'Switch track and knob dimensions (default size; `size="sm"` keeps its own) and colours. Set `knob-inset` to size the knob from the track: it sits that far from the track\'s outer edge on every side. Keys: track-width, track-height, knob-inset, track-bg, edge-color, track-hover-bg, track-hover-bg-checked, knob-bg, knob-bg-checked.',
1228
1281
  additionalProperties: {
1229
1282
  $ref: "#/$defs/componentTokenBinding"
1230
1283
  }
1231
1284
  },
1232
1285
  "save-status": {
1233
1286
  type: "object",
1234
- description: "SaveStatus readout \u2014 the fixed-width slot, its type, the Syncing ink and the Unsaved dot, so the readout never reflows its row. Keys: width, syncing-color, dot-size, font-family, text-transform, letter-spacing.",
1287
+ description: "SaveStatus readout \u2014 the fixed-width slot, its type, the Syncing ink and the Unsaved dot, so the readout never reflows its row. Keys: width, syncing-color, font-size, dot-size, unsaved-dot-size, font-family, text-transform, letter-spacing.",
1288
+ additionalProperties: {
1289
+ $ref: "#/$defs/componentTokenBinding"
1290
+ }
1291
+ },
1292
+ "segmented-control": {
1293
+ type: "object",
1294
+ description: "SegmentedControl \u2014 the well, its corner radius, the sliding pill, the ink and the state edge on it. The resting edge is the shared `control` edge. Keys: track-bg, radius, indicator-bg, indicator-text, indicator-edge, inactive-text, active-weight.",
1235
1295
  additionalProperties: {
1236
1296
  $ref: "#/$defs/componentTokenBinding"
1237
1297
  }
@@ -1250,6 +1310,20 @@ var visor_theme_schema_default = {
1250
1310
  $ref: "#/$defs/componentTokenBinding"
1251
1311
  }
1252
1312
  },
1313
+ "input-affix": {
1314
+ type: "object",
1315
+ description: "Input and NumberInput prefix and suffix: the gap between a fixed affix and the value, and the affix's ink. Keys: gap, color.",
1316
+ additionalProperties: {
1317
+ $ref: "#/$defs/componentTokenBinding"
1318
+ }
1319
+ },
1320
+ separator: {
1321
+ type: "object",
1322
+ description: "Separator rule colour, bare or either side of a label. Keys: color.",
1323
+ additionalProperties: {
1324
+ $ref: "#/$defs/componentTokenBinding"
1325
+ }
1326
+ },
1253
1327
  "admin-ui": {
1254
1328
  type: "object",
1255
1329
  description: "Structural roles the admin-ui pattern owns. `marquee-family` is the display face for KPI hero figures and marquee page titles \u2014 the role the admin-ui portability audit named as the one piece of ENTR brand coupling a new theme must rebind. Keys: marquee-family.",
@@ -1564,8 +1638,8 @@ var KNOWN_TYPOGRAPHY_KEYS = /* @__PURE__ */ new Set([
1564
1638
  "text-on-dark"
1565
1639
  ]);
1566
1640
  var KNOWN_CDN_OVERRIDE_KEYS = /* @__PURE__ */ new Set(["visor-fonts"]);
1567
- var KNOWN_TYPOGRAPHY_FONT_KEYS = /* @__PURE__ */ new Set(["family", "weight", "weights", "source", "org"]);
1568
- var KNOWN_TYPOGRAPHY_MONO_KEYS = /* @__PURE__ */ new Set(["family", "weight", "weights", "source", "org"]);
1641
+ var KNOWN_TYPOGRAPHY_FONT_KEYS = /* @__PURE__ */ new Set(["family", "weight", "weights", "source", "org", "text-transform"]);
1642
+ var KNOWN_TYPOGRAPHY_MONO_KEYS = /* @__PURE__ */ new Set(["family", "weight", "weights", "source", "org", "text-transform"]);
1569
1643
  var KNOWN_LETTER_SPACING_KEYS = /* @__PURE__ */ new Set([
1570
1644
  "xl",
1571
1645
  "lg",
@@ -1882,6 +1956,12 @@ function validateConfig(config) {
1882
1956
  errors.push(`'typography.cdn-overrides.visor-fonts' must not be empty`);
1883
1957
  }
1884
1958
  const orgOptional = typeof visorFontsOverride === "string" && visorFontsOverride.length > 0;
1959
+ for (const slot of ["heading", "display", "body", "mono"]) {
1960
+ const tt = typo[slot]?.["text-transform"];
1961
+ if (tt !== void 0 && !TEXT_TRANSFORMS.includes(tt)) {
1962
+ errors.push(`'typography.${slot}.text-transform' must be one of: ${TEXT_TRANSFORMS.join(", ")}`);
1963
+ }
1964
+ }
1885
1965
  for (const slot of ["heading", "display", "body"]) {
1886
1966
  const font = typo[slot];
1887
1967
  if (font && font.source === "visor-fonts" && !orgOptional && !font.org) {
@@ -2136,6 +2216,7 @@ function resolveConfig(config) {
2136
2216
  weight: config.typography?.heading?.weight ?? DEFAULTS.typography.heading.weight,
2137
2217
  ...config.typography?.heading?.source && { source: config.typography.heading.source },
2138
2218
  ...config.typography?.heading?.org && { org: config.typography.heading.org },
2219
+ ...config.typography?.heading?.["text-transform"] && { "text-transform": config.typography.heading["text-transform"] },
2139
2220
  ...config.typography?.heading?.weights && { weights: config.typography.heading.weights }
2140
2221
  },
2141
2222
  display: {
@@ -2143,6 +2224,7 @@ function resolveConfig(config) {
2143
2224
  weight: config.typography?.display?.weight ?? 400,
2144
2225
  ...config.typography?.display?.source && { source: config.typography.display.source },
2145
2226
  ...config.typography?.display?.org && { org: config.typography.display.org },
2227
+ ...config.typography?.display?.["text-transform"] && { "text-transform": config.typography.display["text-transform"] },
2146
2228
  ...config.typography?.display?.weights && { weights: config.typography.display.weights }
2147
2229
  },
2148
2230
  body: {
@@ -2150,6 +2232,7 @@ function resolveConfig(config) {
2150
2232
  weight: config.typography?.body?.weight ?? DEFAULTS.typography.body.weight,
2151
2233
  ...config.typography?.body?.source && { source: config.typography.body.source },
2152
2234
  ...config.typography?.body?.org && { org: config.typography.body.org },
2235
+ ...config.typography?.body?.["text-transform"] && { "text-transform": config.typography.body["text-transform"] },
2153
2236
  ...config.typography?.body?.weights && { weights: config.typography.body.weights }
2154
2237
  },
2155
2238
  mono: {
@@ -2157,7 +2240,8 @@ function resolveConfig(config) {
2157
2240
  ...config.typography?.mono?.weight && { weight: config.typography.mono.weight },
2158
2241
  ...config.typography?.mono?.weights && { weights: config.typography.mono.weights },
2159
2242
  ...config.typography?.mono?.source && { source: config.typography.mono.source },
2160
- ...config.typography?.mono?.org && { org: config.typography.mono.org }
2243
+ ...config.typography?.mono?.org && { org: config.typography.mono.org },
2244
+ ...config.typography?.mono?.["text-transform"] && { "text-transform": config.typography.mono["text-transform"] }
2161
2245
  },
2162
2246
  ...config.typography?.["cdn-overrides"] && {
2163
2247
  "cdn-overrides": config.typography["cdn-overrides"]
@@ -4353,11 +4437,14 @@ export {
4353
4437
  DEFAULT_BRAND_STRATEGY_SURFACES,
4354
4438
  DEFAULT_BRAND_STRATEGY_TONE_STATES,
4355
4439
  DEFAULT_VISOR_BRAND,
4440
+ FONT_VERTICAL_METRICS,
4356
4441
  FONT_WEIGHT_ALIASES,
4357
4442
  GOVERNS_WILDCARD,
4443
+ MODE_DEPENDENT_SEMANTIC_ALIASES,
4358
4444
  SEMANTIC_MAP,
4359
4445
  TAILWIND_GRAY,
4360
4446
  VISOR_BRANDS_CDN,
4447
+ VISOR_CORE_DARK_SEMANTIC_ALIASES,
4361
4448
  VISOR_CORE_SEMANTIC_ALIASES,
4362
4449
  VISOR_DEFAULT_BRAND_PATH,
4363
4450
  VISOR_FONTS_CDN,
@@ -4380,6 +4467,7 @@ export {
4380
4467
  extractFromCSS,
4381
4468
  formatFontCoverageError,
4382
4469
  generateDarkCss,
4470
+ generateFontMetricDecls,
4383
4471
  generateFontWeightDecls,
4384
4472
  generateFullBundleCss,
4385
4473
  generateLightCss,
@@ -603,6 +603,8 @@ declare function validateComponentBindings(bindings: unknown): string[];
603
603
  * Covers the full pipeline: .visor.yaml config → shade scales → semantic tokens → CSS output.
604
604
  */
605
605
 
606
+ /** VI-687: casing a typography slot applies to its text. */
607
+ type TextTransform = "none" | "uppercase" | "lowercase" | "capitalize";
606
608
  type ShadeStep = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950;
607
609
  type ColorRole = "primary" | "accent" | "neutral" | "success" | "warning" | "error" | "info";
608
610
  type FullShadeScale = Record<ShadeStep, string>;
@@ -707,6 +709,7 @@ interface VisorThemeConfig {
707
709
  weights?: number[];
708
710
  source?: FontSource;
709
711
  org?: string;
712
+ "text-transform"?: TextTransform;
710
713
  };
711
714
  display?: {
712
715
  family?: string;
@@ -714,6 +717,7 @@ interface VisorThemeConfig {
714
717
  weights?: number[];
715
718
  source?: FontSource;
716
719
  org?: string;
720
+ "text-transform"?: TextTransform;
717
721
  };
718
722
  body?: {
719
723
  family?: string;
@@ -721,6 +725,7 @@ interface VisorThemeConfig {
721
725
  weights?: number[];
722
726
  source?: FontSource;
723
727
  org?: string;
728
+ "text-transform"?: TextTransform;
724
729
  };
725
730
  mono?: {
726
731
  family?: string;
@@ -728,6 +733,7 @@ interface VisorThemeConfig {
728
733
  weights?: number[];
729
734
  source?: FontSource;
730
735
  org?: string;
736
+ "text-transform"?: TextTransform;
731
737
  };
732
738
  /**
733
739
  * VI-447: 6-tier letter-spacing ramp (`xl | lg | md | sm | xs | tight`).
@@ -912,6 +918,7 @@ interface ResolvedThemeConfig {
912
918
  weights?: number[];
913
919
  source?: FontSource;
914
920
  org?: string;
921
+ "text-transform"?: TextTransform;
915
922
  };
916
923
  display: {
917
924
  family: string;
@@ -919,6 +926,7 @@ interface ResolvedThemeConfig {
919
926
  weights?: number[];
920
927
  source?: FontSource;
921
928
  org?: string;
929
+ "text-transform"?: TextTransform;
922
930
  };
923
931
  body: {
924
932
  family: string;
@@ -926,6 +934,7 @@ interface ResolvedThemeConfig {
926
934
  weights?: number[];
927
935
  source?: FontSource;
928
936
  org?: string;
937
+ "text-transform"?: TextTransform;
929
938
  };
930
939
  mono: {
931
940
  family: string;
@@ -933,6 +942,7 @@ interface ResolvedThemeConfig {
933
942
  weights?: number[];
934
943
  source?: FontSource;
935
944
  org?: string;
945
+ "text-transform"?: TextTransform;
936
946
  };
937
947
  /**
938
948
  * Per-source CDN base URL overrides (e.g., `visor-fonts:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loworbitstudio/visor-theme-engine",
3
- "version": "0.25.0",
3
+ "version": "0.29.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",