@loworbitstudio/visor-theme-engine 0.1.0 → 0.4.1

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.
@@ -467,8 +467,7 @@ function resolveThemeFonts(typography, options) {
467
467
  const warnings = [];
468
468
  let headingResolution = null;
469
469
  if (typography.heading?.family) {
470
- const weights = [];
471
- if (typography.heading.weight) weights.push(typography.heading.weight);
470
+ const weights = typography.heading.weights ? [...typography.heading.weights] : typography.heading.weight ? [typography.heading.weight] : [];
472
471
  headingResolution = resolveFont(typography.heading.family, {
473
472
  weights: weights.length > 0 ? weights : void 0,
474
473
  display,
@@ -481,10 +480,15 @@ function resolveThemeFonts(typography, options) {
481
480
  }
482
481
  let bodyResolution = null;
483
482
  if (typography.body?.family) {
484
- const bodyWeights = [];
485
- if (typography.body.weight) bodyWeights.push(typography.body.weight);
486
- if (!bodyWeights.includes(400)) bodyWeights.push(400);
487
- if (!bodyWeights.includes(700)) bodyWeights.push(700);
483
+ let bodyWeights;
484
+ if (typography.body.weights) {
485
+ bodyWeights = [...typography.body.weights];
486
+ } else {
487
+ bodyWeights = [];
488
+ if (typography.body.weight) bodyWeights.push(typography.body.weight);
489
+ if (!bodyWeights.includes(400)) bodyWeights.push(400);
490
+ if (!bodyWeights.includes(700)) bodyWeights.push(700);
491
+ }
488
492
  if (headingResolution && typography.body.family.toLowerCase() === headingResolution.family.toLowerCase()) {
489
493
  const mergedWeights = Array.from(
490
494
  /* @__PURE__ */ new Set([...headingResolution.weights, ...bodyWeights])
@@ -510,19 +514,22 @@ function resolveThemeFonts(typography, options) {
510
514
  }
511
515
  let displayResolution = null;
512
516
  if (typography.display?.family) {
513
- const displayWeights = [];
514
- if (typography.display.weight) displayWeights.push(typography.display.weight);
517
+ const displayWeights = typography.display.weights ? [...typography.display.weights] : typography.display.weight ? [typography.display.weight] : [];
515
518
  if (headingResolution && typography.display.family.toLowerCase() === headingResolution.family.toLowerCase()) {
516
- const mergedWeights = Array.from(
517
- /* @__PURE__ */ new Set([...headingResolution.weights, ...displayWeights])
518
- ).sort((a, b) => a - b);
519
- headingResolution = resolveFont(typography.heading.family, {
520
- weights: mergedWeights,
521
- display,
522
- source: typography.heading.source,
523
- org: typography.heading.org
524
- });
525
- displayResolution = headingResolution;
519
+ if (typography.heading?.weights) {
520
+ displayResolution = headingResolution;
521
+ } else {
522
+ const mergedWeights = Array.from(
523
+ /* @__PURE__ */ new Set([...headingResolution.weights, ...displayWeights])
524
+ ).sort((a, b) => a - b);
525
+ headingResolution = resolveFont(typography.heading.family, {
526
+ weights: mergedWeights,
527
+ display,
528
+ source: typography.heading.source,
529
+ org: typography.heading.org
530
+ });
531
+ displayResolution = headingResolution;
532
+ }
526
533
  } else if (bodyResolution && typography.display.family.toLowerCase() === bodyResolution.family.toLowerCase()) {
527
534
  const mergedWeights = Array.from(
528
535
  /* @__PURE__ */ new Set([...bodyResolution.weights, ...displayWeights])
@@ -957,9 +964,9 @@ var LIGHTNESS_TARGETS = {
957
964
  200: 0.87,
958
965
  300: 0.78,
959
966
  400: 0.65,
960
- 500: 0.55,
961
- 600: -1,
962
- // placeholder — replaced by input L at anchor
967
+ 500: -1,
968
+ // placeholder — replaced by input L at anchor (brand color lives at 500)
969
+ 600: 0.45,
963
970
  700: 0.38,
964
971
  800: 0.3,
965
972
  900: 0.22,
@@ -979,8 +986,8 @@ var CHROMA_MULTIPLIERS = {
979
986
  950: 0.5
980
987
  };
981
988
  var ANCHOR_SHADE = {
982
- primary: 600,
983
- accent: 600,
989
+ primary: 500,
990
+ accent: 500,
984
991
  neutral: 500,
985
992
  success: 500,
986
993
  warning: 500,
@@ -1359,6 +1366,26 @@ function generateFullBundleCss(primitives, tokens, config) {
1359
1366
  return lines.join("\n");
1360
1367
  }
1361
1368
 
1369
+ // src/types.ts
1370
+ var MATERIAL_TEXT_SLOTS = [
1371
+ "displayLarge",
1372
+ "displayMedium",
1373
+ "displaySmall",
1374
+ "headlineLarge",
1375
+ "headlineMedium",
1376
+ "headlineSmall",
1377
+ "titleLarge",
1378
+ "titleMedium",
1379
+ "titleSmall",
1380
+ "bodyLarge",
1381
+ "bodyMedium",
1382
+ "bodySmall",
1383
+ "labelLarge",
1384
+ "labelMedium",
1385
+ "labelSmall",
1386
+ "labelXSmall"
1387
+ ];
1388
+
1362
1389
  export {
1363
1390
  googleFontsCatalog,
1364
1391
  lookupGoogleFont,
@@ -1385,6 +1412,7 @@ export {
1385
1412
  isValidColor,
1386
1413
  compositeOverBackground,
1387
1414
  serializeColor,
1415
+ MATERIAL_TEXT_SLOTS,
1388
1416
  FULL_SHADE_STEPS,
1389
1417
  SELECTIVE_SHADE_STEPS,
1390
1418
  TAILWIND_GRAY,
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, R as ResolvedThemeConfig, c as GeneratedPrimitives, d as ThemeOutput, e as ThemeData, f as VisorThemeConfig, g as FullShadeScale, C as ColorRole, S as SelectiveShadeScale, h as RGB, P as ParsedColor, O as OKLCH, i as SemanticTokens, j as ShadeStep } from './types-r7ae3WP2.js';
2
- export { k as ColorFormat, l as FontSource, m as RGBA, n as SemanticTokenValue } from './types-r7ae3WP2.js';
1
+ import { F as FontResolveOptions, a as FontResolution, V as VisorTypography, b as FontDisplayStrategy, T as ThemeFontResult, G as GoogleFontEntry, R as ResolvedThemeConfig, c as GeneratedPrimitives, d as ThemeOutput, e as ThemeData, f as VisorThemeConfig, g as FullShadeScale, C as ColorRole, S as SelectiveShadeScale, h as RGB, P as ParsedColor, O as OKLCH, i as SemanticTokens, j as ShadeStep } from './types-gAlkt__C.js';
2
+ export { k as ColorFormat, l as FontSource, m as RGBA, n as SemanticTokenValue } from './types-gAlkt__C.js';
3
3
 
4
4
  /**
5
5
  * Font resolver — maps font family names to loadable font resources.
@@ -97,7 +97,7 @@ declare function lookupGoogleFont(family: string): GoogleFontEntry | undefined;
97
97
  */
98
98
 
99
99
  /**
100
- * Generate all shade scales from a resolved config.
100
+ * Generate all shade scales from a resolved config (light-mode colors).
101
101
  * If neutral is null, uses Tailwind Gray verbatim.
102
102
  */
103
103
  declare function generatePrimitives(config: ResolvedThemeConfig): GeneratedPrimitives;
@@ -367,6 +367,61 @@ var properties = {
367
367
  type: "string"
368
368
  }
369
369
  }
370
+ },
371
+ slots: {
372
+ type: "object",
373
+ description: "Per-slot overrides for the generated Flutter Material TextTheme. Any subset of the 16 slots may be specified; omitted slots fall through to the Material 3 2024 defaults shipped in visor_core.",
374
+ additionalProperties: false,
375
+ properties: {
376
+ displayLarge: {
377
+ $ref: "#/$defs/textSlotOverride"
378
+ },
379
+ displayMedium: {
380
+ $ref: "#/$defs/textSlotOverride"
381
+ },
382
+ displaySmall: {
383
+ $ref: "#/$defs/textSlotOverride"
384
+ },
385
+ headlineLarge: {
386
+ $ref: "#/$defs/textSlotOverride"
387
+ },
388
+ headlineMedium: {
389
+ $ref: "#/$defs/textSlotOverride"
390
+ },
391
+ headlineSmall: {
392
+ $ref: "#/$defs/textSlotOverride"
393
+ },
394
+ titleLarge: {
395
+ $ref: "#/$defs/textSlotOverride"
396
+ },
397
+ titleMedium: {
398
+ $ref: "#/$defs/textSlotOverride"
399
+ },
400
+ titleSmall: {
401
+ $ref: "#/$defs/textSlotOverride"
402
+ },
403
+ bodyLarge: {
404
+ $ref: "#/$defs/textSlotOverride"
405
+ },
406
+ bodyMedium: {
407
+ $ref: "#/$defs/textSlotOverride"
408
+ },
409
+ bodySmall: {
410
+ $ref: "#/$defs/textSlotOverride"
411
+ },
412
+ labelLarge: {
413
+ $ref: "#/$defs/textSlotOverride"
414
+ },
415
+ labelMedium: {
416
+ $ref: "#/$defs/textSlotOverride"
417
+ },
418
+ labelSmall: {
419
+ $ref: "#/$defs/textSlotOverride"
420
+ },
421
+ labelXSmall: {
422
+ $ref: "#/$defs/textSlotOverride"
423
+ }
424
+ }
370
425
  }
371
426
  }
372
427
  },
@@ -432,6 +487,29 @@ var properties = {
432
487
  }
433
488
  }
434
489
  },
490
+ strokeWidths: {
491
+ type: "object",
492
+ description: "Stroke-width scale in pixels — used for borders, outlines, dividers, progress-indicator strokes. Defaults: thin=1, regular=1.5, medium=2, thick=2.5.",
493
+ additionalProperties: false,
494
+ properties: {
495
+ thin: {
496
+ type: "number",
497
+ minimum: 0
498
+ },
499
+ regular: {
500
+ type: "number",
501
+ minimum: 0
502
+ },
503
+ medium: {
504
+ type: "number",
505
+ minimum: 0
506
+ },
507
+ thick: {
508
+ type: "number",
509
+ minimum: 0
510
+ }
511
+ }
512
+ },
435
513
  motion: {
436
514
  type: "object",
437
515
  description: "Motion/animation configuration.",
@@ -498,6 +576,28 @@ var $defs = {
498
576
  pattern: "^oklch\\("
499
577
  }
500
578
  ]
579
+ },
580
+ textSlotOverride: {
581
+ type: "object",
582
+ description: "Per-slot override for one Material TextTheme entry.",
583
+ additionalProperties: false,
584
+ properties: {
585
+ size: {
586
+ type: "number",
587
+ exclusiveMinimum: 0,
588
+ description: "Font size in logical pixels (Flutter TextStyle.fontSize)."
589
+ },
590
+ weight: {
591
+ type: "integer",
592
+ minimum: 100,
593
+ maximum: 900,
594
+ description: "Font weight."
595
+ },
596
+ "letter-spacing": {
597
+ type: "number",
598
+ description: "Letter spacing in logical pixels (Flutter TextStyle.letterSpacing). Material defaults include negative values, e.g. -0.25 for displayLarge."
599
+ }
600
+ }
501
601
  }
502
602
  };
503
603
  var visorTheme_schema = {
@@ -658,10 +758,12 @@ declare function resolveConfig(config: VisorThemeConfig): ResolvedThemeConfig;
658
758
  */
659
759
 
660
760
  /**
661
- * Assign semantic tokens from generated shade scales and resolved config.
662
- * Returns concrete hex values for all ~55 tokens in both light and dark modes.
761
+ * Assign semantic tokens from mode-specific shade scales and resolved config.
762
+ * lightPrimitives drives light-mode token values; darkPrimitives drives dark-mode
763
+ * values — allowing themes with colors-dark overrides to produce correct dark
764
+ * semantic tokens (e.g. surface-accent-default uses the dark brand color).
663
765
  */
664
- declare function assignSemanticTokens(primitives: GeneratedPrimitives, config: ResolvedThemeConfig): SemanticTokens;
766
+ declare function assignSemanticTokens(lightPrimitives: GeneratedPrimitives, darkPrimitives: GeneratedPrimitives, config: ResolvedThemeConfig): SemanticTokens;
665
767
 
666
768
  /**
667
769
  * Override Application (Stage 4)