@loworbitstudio/visor-theme-engine 0.9.0 → 0.10.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
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as GeneratedPrimitives, i as SemanticTokens, R as ResolvedThemeConfig } from '../types-
|
|
1
|
+
import { c as GeneratedPrimitives, i as SemanticTokens, R as ResolvedThemeConfig } from '../types-Dwc1V0Nc.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Adapter types for the Visor theme engine.
|
package/dist/adapters/index.js
CHANGED
|
@@ -6,14 +6,18 @@ import {
|
|
|
6
6
|
buildVisorFontUrl,
|
|
7
7
|
fontStack,
|
|
8
8
|
generateDarkCss,
|
|
9
|
+
generateHairlineDecls,
|
|
10
|
+
generateIntentDecls,
|
|
9
11
|
generateLightCss,
|
|
10
12
|
generatePrimitivesCss,
|
|
11
13
|
generateShadeScale,
|
|
14
|
+
generateSpaceAliasDecls,
|
|
15
|
+
generateTextScaleAliasDecls,
|
|
12
16
|
header,
|
|
13
17
|
parseColor,
|
|
14
18
|
resolveThemeFonts,
|
|
15
19
|
sectionComment
|
|
16
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-43TVIXUS.js";
|
|
17
21
|
|
|
18
22
|
// src/adapters/layers.ts
|
|
19
23
|
var LAYER_ORDER = "@layer visor-primitives, visor-semantic, visor-adaptive, visor-bridge;";
|
|
@@ -589,9 +593,46 @@ ${inner.split("\n").map((l) => ` ${l}`).join("\n")}
|
|
|
589
593
|
lines.push(sectionComment2("Fumadocs bridge: light"));
|
|
590
594
|
lines.push(block(`html:not(.dark) ${scopeClass}`, generateFumadocsBridgeDecls(input.tokens, "light")));
|
|
591
595
|
lines.push("");
|
|
592
|
-
const
|
|
596
|
+
const semanticLines = [];
|
|
597
|
+
semanticLines.push("\n/* \u2500\u2500 Layer: Semantic aliases (VI-451) \u2500\u2500 */");
|
|
598
|
+
semanticLines.push(sectionComment2("Discrete: Text size aliases (--text-N)"));
|
|
599
|
+
semanticLines.push(block(scopeClass, generateTextScaleAliasDecls()));
|
|
600
|
+
semanticLines.push("");
|
|
601
|
+
semanticLines.push(sectionComment2("Discrete: Space aliases (--space-N)"));
|
|
602
|
+
semanticLines.push(block(scopeClass, generateSpaceAliasDecls(input.config)));
|
|
603
|
+
semanticLines.push("");
|
|
604
|
+
semanticLines.push(sectionComment2("Intent aliases (light)"));
|
|
605
|
+
semanticLines.push(block(`html:not(.dark) ${scopeClass}`, generateIntentDecls(input.tokens, "light")));
|
|
606
|
+
semanticLines.push("");
|
|
607
|
+
semanticLines.push(sectionComment2("Hairline aliases (light)"));
|
|
608
|
+
semanticLines.push(block(`html:not(.dark) ${scopeClass}`, generateHairlineDecls(input.tokens, "light")));
|
|
609
|
+
semanticLines.push("");
|
|
610
|
+
semanticLines.push(sectionComment2("Intent aliases (dark) \u2014 manual toggle"));
|
|
611
|
+
semanticLines.push(block(`.dark ${scopeClass}`, generateIntentDecls(input.tokens, "dark")));
|
|
612
|
+
semanticLines.push("");
|
|
613
|
+
semanticLines.push(sectionComment2("Hairline aliases (dark) \u2014 manual toggle"));
|
|
614
|
+
semanticLines.push(block(`.dark ${scopeClass}`, generateHairlineDecls(input.tokens, "dark")));
|
|
615
|
+
semanticLines.push("");
|
|
616
|
+
semanticLines.push(sectionComment2("Intent aliases (dark) \u2014 prefers-color-scheme"));
|
|
617
|
+
{
|
|
618
|
+
const inner = block(`${scopeClass}:not(.light)`, generateIntentDecls(input.tokens, "dark"));
|
|
619
|
+
semanticLines.push(`@media (prefers-color-scheme: dark) {
|
|
620
|
+
${inner.split("\n").map((l) => ` ${l}`).join("\n")}
|
|
621
|
+
}`);
|
|
622
|
+
}
|
|
623
|
+
semanticLines.push("");
|
|
624
|
+
semanticLines.push(sectionComment2("Hairline aliases (dark) \u2014 prefers-color-scheme"));
|
|
625
|
+
{
|
|
626
|
+
const inner = block(`${scopeClass}:not(.light)`, generateHairlineDecls(input.tokens, "dark"));
|
|
627
|
+
semanticLines.push(`@media (prefers-color-scheme: dark) {
|
|
628
|
+
${inner.split("\n").map((l) => ` ${l}`).join("\n")}
|
|
629
|
+
}`);
|
|
630
|
+
}
|
|
631
|
+
semanticLines.push("");
|
|
632
|
+
const adaptiveLayer = wrapInLayer("visor-adaptive", lines.join("\n").trim());
|
|
633
|
+
const semanticLayer = wrapInLayer("visor-semantic", semanticLines.join("\n").trim());
|
|
593
634
|
const head = fontLines.length > 0 ? fontLines.join("\n") + "\n" : "";
|
|
594
|
-
return head + LAYER_ORDER + "\n\n" +
|
|
635
|
+
return head + LAYER_ORDER + "\n\n" + semanticLayer + "\n\n" + adaptiveLayer + "\n";
|
|
595
636
|
}
|
|
596
637
|
|
|
597
638
|
// src/flutter/color-to-dart.ts
|
|
@@ -1324,6 +1324,9 @@ function generateMotionPrimitives(config) {
|
|
|
1324
1324
|
decls.push(
|
|
1325
1325
|
"--motion-easing-spring: cubic-bezier(0.34, 1.56, 0.64, 1);"
|
|
1326
1326
|
);
|
|
1327
|
+
if (config.motion["easing-overshoot"]) {
|
|
1328
|
+
decls.push(`--motion-easing-overshoot: ${config.motion["easing-overshoot"]};`);
|
|
1329
|
+
}
|
|
1327
1330
|
return decls;
|
|
1328
1331
|
}
|
|
1329
1332
|
function generateMiscPrimitives() {
|
|
@@ -1369,6 +1372,9 @@ function generatePrimitivesCss(primitives, config, options) {
|
|
|
1369
1372
|
lines.push(block(host, generateMiscPrimitives()));
|
|
1370
1373
|
return header("Visor Theme \u2014 Primitives") + lines.join("\n");
|
|
1371
1374
|
}
|
|
1375
|
+
function hairlineDeclName(name) {
|
|
1376
|
+
return name === "default" ? "--hairline" : `--hairline-${name}`;
|
|
1377
|
+
}
|
|
1372
1378
|
function generateSemanticCss(tokens) {
|
|
1373
1379
|
const lines = [];
|
|
1374
1380
|
lines.push(sectionComment("Semantic: Text"));
|
|
@@ -1391,8 +1397,61 @@ function generateSemanticCss(tokens) {
|
|
|
1391
1397
|
([name, { light }]) => `--interactive-${name}: ${light};`
|
|
1392
1398
|
);
|
|
1393
1399
|
lines.push(block(":root", interactiveDecls));
|
|
1400
|
+
lines.push(sectionComment("Semantic: Intent (aliases)"));
|
|
1401
|
+
const intentDecls = Object.entries(tokens.intent).map(
|
|
1402
|
+
([name, { light }]) => `--${name}: ${light};`
|
|
1403
|
+
);
|
|
1404
|
+
lines.push(block(":root", intentDecls));
|
|
1405
|
+
lines.push(sectionComment("Semantic: Hairline (aliases)"));
|
|
1406
|
+
const hairlineDecls = Object.entries(tokens.hairline).map(
|
|
1407
|
+
([name, { light }]) => `${hairlineDeclName(name)}: ${light};`
|
|
1408
|
+
);
|
|
1409
|
+
lines.push(block(":root", hairlineDecls));
|
|
1394
1410
|
return header("Visor Theme \u2014 Semantic") + lines.join("\n");
|
|
1395
1411
|
}
|
|
1412
|
+
var TEXT_SCALE_ALIASES = [
|
|
1413
|
+
11,
|
|
1414
|
+
13,
|
|
1415
|
+
14,
|
|
1416
|
+
16,
|
|
1417
|
+
20,
|
|
1418
|
+
24,
|
|
1419
|
+
32,
|
|
1420
|
+
40,
|
|
1421
|
+
48
|
|
1422
|
+
];
|
|
1423
|
+
function generateTextScaleAliasDecls() {
|
|
1424
|
+
return TEXT_SCALE_ALIASES.map((px) => `--text-${px}: ${px}px;`);
|
|
1425
|
+
}
|
|
1426
|
+
var SPACE_ALIAS_MULTIPLIERS = [
|
|
1427
|
+
1,
|
|
1428
|
+
2,
|
|
1429
|
+
3,
|
|
1430
|
+
4,
|
|
1431
|
+
5,
|
|
1432
|
+
6,
|
|
1433
|
+
8,
|
|
1434
|
+
10,
|
|
1435
|
+
12,
|
|
1436
|
+
16
|
|
1437
|
+
];
|
|
1438
|
+
function generateSpaceAliasDecls(config) {
|
|
1439
|
+
const base = config.spacing.base;
|
|
1440
|
+
return SPACE_ALIAS_MULTIPLIERS.map((m) => {
|
|
1441
|
+
const px = base * m;
|
|
1442
|
+
return `--space-${m}: ${px}px;`;
|
|
1443
|
+
});
|
|
1444
|
+
}
|
|
1445
|
+
function generateIntentDecls(tokens, mode) {
|
|
1446
|
+
return Object.entries(tokens.intent).map(
|
|
1447
|
+
([name, value]) => `--${name}: ${value[mode]};`
|
|
1448
|
+
);
|
|
1449
|
+
}
|
|
1450
|
+
function generateHairlineDecls(tokens, mode) {
|
|
1451
|
+
return Object.entries(tokens.hairline).map(
|
|
1452
|
+
([name, value]) => `${hairlineDeclName(name)}: ${value[mode]};`
|
|
1453
|
+
);
|
|
1454
|
+
}
|
|
1396
1455
|
function buildAdaptiveDecls(tokens, theme) {
|
|
1397
1456
|
const textDecls = Object.entries(tokens.text).map(
|
|
1398
1457
|
([name, values]) => `--text-${name}: ${values[theme]};`
|
|
@@ -1406,11 +1465,13 @@ function buildAdaptiveDecls(tokens, theme) {
|
|
|
1406
1465
|
const interactiveDecls = Object.entries(tokens.interactive).map(
|
|
1407
1466
|
([name, values]) => `--interactive-${name}: ${values[theme]};`
|
|
1408
1467
|
);
|
|
1409
|
-
|
|
1468
|
+
const intentDecls = generateIntentDecls(tokens, theme);
|
|
1469
|
+
const hairlineDecls = generateHairlineDecls(tokens, theme);
|
|
1470
|
+
return { textDecls, surfaceDecls, borderDecls, interactiveDecls, intentDecls, hairlineDecls };
|
|
1410
1471
|
}
|
|
1411
1472
|
function generateLightCss(tokens, options) {
|
|
1412
1473
|
const lines = [];
|
|
1413
|
-
const { textDecls, surfaceDecls, borderDecls, interactiveDecls } = buildAdaptiveDecls(tokens, "light");
|
|
1474
|
+
const { textDecls, surfaceDecls, borderDecls, interactiveDecls, intentDecls, hairlineDecls } = buildAdaptiveDecls(tokens, "light");
|
|
1414
1475
|
const host = options?.scopePrefix ?? ":root";
|
|
1415
1476
|
lines.push(sectionComment("Adaptive: Text (light)"));
|
|
1416
1477
|
lines.push(block(host, textDecls));
|
|
@@ -1420,11 +1481,15 @@ function generateLightCss(tokens, options) {
|
|
|
1420
1481
|
lines.push(block(host, borderDecls));
|
|
1421
1482
|
lines.push(sectionComment("Adaptive: Interactive (light)"));
|
|
1422
1483
|
lines.push(block(host, interactiveDecls));
|
|
1484
|
+
lines.push(sectionComment("Adaptive: Intent aliases (light)"));
|
|
1485
|
+
lines.push(block(host, intentDecls));
|
|
1486
|
+
lines.push(sectionComment("Adaptive: Hairline aliases (light)"));
|
|
1487
|
+
lines.push(block(host, hairlineDecls));
|
|
1423
1488
|
return header("Visor Theme \u2014 Light") + lines.join("\n");
|
|
1424
1489
|
}
|
|
1425
1490
|
function generateDarkCss(tokens, options) {
|
|
1426
1491
|
const lines = [];
|
|
1427
|
-
const { textDecls, surfaceDecls, borderDecls, interactiveDecls } = buildAdaptiveDecls(tokens, "dark");
|
|
1492
|
+
const { textDecls, surfaceDecls, borderDecls, interactiveDecls, intentDecls, hairlineDecls } = buildAdaptiveDecls(tokens, "dark");
|
|
1428
1493
|
const prefix = options?.scopePrefix;
|
|
1429
1494
|
const darkSelectors = prefix ? [`${prefix}.dark`, `${prefix}.theme-dark`, `${prefix}[data-theme="dark"]`] : [".dark", ".theme-dark", '[data-theme="dark"]'];
|
|
1430
1495
|
const darkSelector = darkSelectors.join(",\n");
|
|
@@ -1437,6 +1502,10 @@ function generateDarkCss(tokens, options) {
|
|
|
1437
1502
|
lines.push(block(darkSelector, borderDecls));
|
|
1438
1503
|
lines.push(sectionComment("Adaptive: Interactive (dark) \u2014 manual toggle"));
|
|
1439
1504
|
lines.push(block(darkSelector, interactiveDecls));
|
|
1505
|
+
lines.push(sectionComment("Adaptive: Intent aliases (dark) \u2014 manual toggle"));
|
|
1506
|
+
lines.push(block(darkSelector, intentDecls));
|
|
1507
|
+
lines.push(sectionComment("Adaptive: Hairline aliases (dark) \u2014 manual toggle"));
|
|
1508
|
+
lines.push(block(darkSelector, hairlineDecls));
|
|
1440
1509
|
lines.push(
|
|
1441
1510
|
sectionComment("Adaptive: Text (dark) \u2014 prefers-color-scheme")
|
|
1442
1511
|
);
|
|
@@ -1467,6 +1536,22 @@ ${block(prefersSelector, borderDecls)}}`
|
|
|
1467
1536
|
lines.push(
|
|
1468
1537
|
`@media (prefers-color-scheme: dark) {
|
|
1469
1538
|
${block(prefersSelector, interactiveDecls)}}`
|
|
1539
|
+
);
|
|
1540
|
+
lines.push("");
|
|
1541
|
+
lines.push(
|
|
1542
|
+
sectionComment("Adaptive: Intent aliases (dark) \u2014 prefers-color-scheme")
|
|
1543
|
+
);
|
|
1544
|
+
lines.push(
|
|
1545
|
+
`@media (prefers-color-scheme: dark) {
|
|
1546
|
+
${block(prefersSelector, intentDecls)}}`
|
|
1547
|
+
);
|
|
1548
|
+
lines.push("");
|
|
1549
|
+
lines.push(
|
|
1550
|
+
sectionComment("Adaptive: Hairline aliases (dark) \u2014 prefers-color-scheme")
|
|
1551
|
+
);
|
|
1552
|
+
lines.push(
|
|
1553
|
+
`@media (prefers-color-scheme: dark) {
|
|
1554
|
+
${block(prefersSelector, hairlineDecls)}}`
|
|
1470
1555
|
);
|
|
1471
1556
|
lines.push("");
|
|
1472
1557
|
return header("Visor Theme \u2014 Dark") + lines.join("\n");
|
|
@@ -1561,6 +1646,10 @@ export {
|
|
|
1561
1646
|
sectionComment,
|
|
1562
1647
|
generatePrimitivesCss,
|
|
1563
1648
|
generateSemanticCss,
|
|
1649
|
+
generateTextScaleAliasDecls,
|
|
1650
|
+
generateSpaceAliasDecls,
|
|
1651
|
+
generateIntentDecls,
|
|
1652
|
+
generateHairlineDecls,
|
|
1564
1653
|
generateLightCss,
|
|
1565
1654
|
generateDarkCss,
|
|
1566
1655
|
generateFullBundleCss
|
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-
|
|
2
|
-
export { k as ColorFormat, l as FontSource, m as RGBA, n as SemanticTokenValue } from './types-
|
|
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-Dwc1V0Nc.js';
|
|
2
|
+
export { k as ColorFormat, l as FontSource, m as RGBA, n as SemanticTokenValue } from './types-Dwc1V0Nc.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Font resolver — maps font family names to loadable font resources.
|
|
@@ -898,6 +898,8 @@ declare const SEMANTIC_MAP: {
|
|
|
898
898
|
surface: Record<string, SemanticMapping>;
|
|
899
899
|
border: Record<string, SemanticMapping>;
|
|
900
900
|
interactive: Record<string, SemanticMapping>;
|
|
901
|
+
intent: Record<string, SemanticMapping>;
|
|
902
|
+
hairline: Record<string, SemanticMapping>;
|
|
901
903
|
};
|
|
902
904
|
|
|
903
905
|
/**
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
rgbToHex,
|
|
35
35
|
rgbToOklch,
|
|
36
36
|
serializeColor
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-43TVIXUS.js";
|
|
38
38
|
|
|
39
39
|
// src/fonts/validate-coverage.ts
|
|
40
40
|
var FONT_VAR_RE = /--font-(heading|display|body|sans|mono)\s*:\s*([^;]+);/g;
|
|
@@ -605,7 +605,7 @@ var KNOWN_SPACING_KEYS = /* @__PURE__ */ new Set(["base"]);
|
|
|
605
605
|
var KNOWN_RADIUS_KEYS = /* @__PURE__ */ new Set(["sm", "md", "lg", "xl", "pill"]);
|
|
606
606
|
var KNOWN_SHADOW_KEYS = /* @__PURE__ */ new Set(["xs", "sm", "md", "lg", "xl"]);
|
|
607
607
|
var KNOWN_STROKE_WIDTH_KEYS = /* @__PURE__ */ new Set(["thin", "regular", "medium", "thick"]);
|
|
608
|
-
var KNOWN_MOTION_KEYS = /* @__PURE__ */ new Set(["duration-fast", "duration-normal", "duration-slow", "easing"]);
|
|
608
|
+
var KNOWN_MOTION_KEYS = /* @__PURE__ */ new Set(["duration-fast", "duration-normal", "duration-slow", "easing", "easing-overshoot"]);
|
|
609
609
|
var KNOWN_OVERRIDES_KEYS = /* @__PURE__ */ new Set(["light", "dark"]);
|
|
610
610
|
function checkUnknownKeys(obj, errors) {
|
|
611
611
|
for (const key of Object.keys(obj)) {
|
|
@@ -1024,7 +1024,10 @@ function resolveConfig(config) {
|
|
|
1024
1024
|
"duration-fast": config.motion?.["duration-fast"] ?? DEFAULTS.motion["duration-fast"],
|
|
1025
1025
|
"duration-normal": config.motion?.["duration-normal"] ?? DEFAULTS.motion["duration-normal"],
|
|
1026
1026
|
"duration-slow": config.motion?.["duration-slow"] ?? DEFAULTS.motion["duration-slow"],
|
|
1027
|
-
easing: config.motion?.easing ?? DEFAULTS.motion.easing
|
|
1027
|
+
easing: config.motion?.easing ?? DEFAULTS.motion.easing,
|
|
1028
|
+
// VI-451 (drive-by): pass through opt-in bouncy easing when set; absent
|
|
1029
|
+
// themes leave this undefined and fall through to --motion-easing-spring.
|
|
1030
|
+
...config.motion?.["easing-overshoot"] !== void 0 ? { "easing-overshoot": config.motion["easing-overshoot"] } : {}
|
|
1028
1031
|
},
|
|
1029
1032
|
overrides: config.overrides,
|
|
1030
1033
|
originalColors,
|
|
@@ -1057,6 +1060,11 @@ var SEMANTIC_TEXT_MAP = {
|
|
|
1057
1060
|
light: { role: "neutral", shade: 600 },
|
|
1058
1061
|
dark: { role: "neutral", shade: 400 }
|
|
1059
1062
|
},
|
|
1063
|
+
// VI-451: deemphasized but readable — slots between tertiary and disabled.
|
|
1064
|
+
muted: {
|
|
1065
|
+
light: { role: "neutral", shade: 500 },
|
|
1066
|
+
dark: { role: "neutral", shade: 500 }
|
|
1067
|
+
},
|
|
1060
1068
|
disabled: {
|
|
1061
1069
|
light: { role: "neutral", shade: 300 },
|
|
1062
1070
|
dark: { role: "neutral", shade: 600 }
|
|
@@ -1117,6 +1125,16 @@ var SEMANTIC_SURFACE_MAP = {
|
|
|
1117
1125
|
light: { role: "neutral", shade: 100 },
|
|
1118
1126
|
dark: { role: "neutral", shade: 700 }
|
|
1119
1127
|
},
|
|
1128
|
+
// VI-451: deeper than page — used by admin-ui chrome (deepest backdrop).
|
|
1129
|
+
screen: {
|
|
1130
|
+
light: { role: "neutral", shade: 50 },
|
|
1131
|
+
dark: { role: "neutral", shade: 950 }
|
|
1132
|
+
},
|
|
1133
|
+
// VI-451: singular elevation alias, distinct from elev-0..4. Defaults to mid (elev-2).
|
|
1134
|
+
elev: {
|
|
1135
|
+
light: { role: "neutral", shade: 100 },
|
|
1136
|
+
dark: { role: "neutral", shade: 800 }
|
|
1137
|
+
},
|
|
1120
1138
|
overlay: {
|
|
1121
1139
|
light: { role: "neutral", shade: 900 },
|
|
1122
1140
|
dark: { role: "neutral", shade: 950 }
|
|
@@ -1311,11 +1329,56 @@ var SEMANTIC_INTERACTIVE_MAP = {
|
|
|
1311
1329
|
dark: { role: "neutral", shade: 700 }
|
|
1312
1330
|
}
|
|
1313
1331
|
};
|
|
1332
|
+
var SEMANTIC_INTENT_MAP = {
|
|
1333
|
+
primary: {
|
|
1334
|
+
light: { role: "primary", shade: 500 },
|
|
1335
|
+
dark: { role: "primary", shade: 500 }
|
|
1336
|
+
},
|
|
1337
|
+
// Text color paired with --primary backgrounds. Default white; themes whose
|
|
1338
|
+
// primary fails AA on white pin to a graphite via overrides (entr does this).
|
|
1339
|
+
"primary-text": {
|
|
1340
|
+
light: { constant: "#ffffff" },
|
|
1341
|
+
dark: { constant: "#ffffff" }
|
|
1342
|
+
},
|
|
1343
|
+
accent: {
|
|
1344
|
+
light: { role: "accent", shade: 500 },
|
|
1345
|
+
dark: { role: "accent", shade: 500 }
|
|
1346
|
+
},
|
|
1347
|
+
success: {
|
|
1348
|
+
light: { role: "success", shade: 500 },
|
|
1349
|
+
dark: { role: "success", shade: 500 }
|
|
1350
|
+
},
|
|
1351
|
+
warning: {
|
|
1352
|
+
light: { role: "warning", shade: 500 },
|
|
1353
|
+
dark: { role: "warning", shade: 500 }
|
|
1354
|
+
},
|
|
1355
|
+
// shadcn naming — aliases the `error` role.
|
|
1356
|
+
destructive: {
|
|
1357
|
+
light: { role: "error", shade: 500 },
|
|
1358
|
+
dark: { role: "error", shade: 500 }
|
|
1359
|
+
},
|
|
1360
|
+
info: {
|
|
1361
|
+
light: { role: "info", shade: 500 },
|
|
1362
|
+
dark: { role: "info", shade: 500 }
|
|
1363
|
+
}
|
|
1364
|
+
};
|
|
1365
|
+
var SEMANTIC_HAIRLINE_MAP = {
|
|
1366
|
+
default: {
|
|
1367
|
+
light: { constant: "rgba(0, 0, 0, 0.06)" },
|
|
1368
|
+
dark: { constant: "rgba(255, 255, 255, 0.06)" }
|
|
1369
|
+
},
|
|
1370
|
+
strong: {
|
|
1371
|
+
light: { constant: "rgba(0, 0, 0, 0.10)" },
|
|
1372
|
+
dark: { constant: "rgba(255, 255, 255, 0.10)" }
|
|
1373
|
+
}
|
|
1374
|
+
};
|
|
1314
1375
|
var SEMANTIC_MAP = {
|
|
1315
1376
|
text: SEMANTIC_TEXT_MAP,
|
|
1316
1377
|
surface: SEMANTIC_SURFACE_MAP,
|
|
1317
1378
|
border: SEMANTIC_BORDER_MAP,
|
|
1318
|
-
interactive: SEMANTIC_INTERACTIVE_MAP
|
|
1379
|
+
interactive: SEMANTIC_INTERACTIVE_MAP,
|
|
1380
|
+
intent: SEMANTIC_INTENT_MAP,
|
|
1381
|
+
hairline: SEMANTIC_HAIRLINE_MAP
|
|
1319
1382
|
};
|
|
1320
1383
|
|
|
1321
1384
|
// src/assign.ts
|
|
@@ -1357,6 +1420,8 @@ function assignSemanticTokens(lightPrimitives, darkPrimitives, config) {
|
|
|
1357
1420
|
const surface = {};
|
|
1358
1421
|
const border = {};
|
|
1359
1422
|
const interactive = {};
|
|
1423
|
+
const intent = {};
|
|
1424
|
+
const hairline = {};
|
|
1360
1425
|
for (const [name, mapping] of Object.entries(SEMANTIC_MAP.text)) {
|
|
1361
1426
|
text[name] = resolveMapping(mapping, lightPrimitives, darkPrimitives, config);
|
|
1362
1427
|
}
|
|
@@ -1369,7 +1434,13 @@ function assignSemanticTokens(lightPrimitives, darkPrimitives, config) {
|
|
|
1369
1434
|
for (const [name, mapping] of Object.entries(SEMANTIC_MAP.interactive)) {
|
|
1370
1435
|
interactive[name] = resolveMapping(mapping, lightPrimitives, darkPrimitives, config);
|
|
1371
1436
|
}
|
|
1372
|
-
|
|
1437
|
+
for (const [name, mapping] of Object.entries(SEMANTIC_MAP.intent)) {
|
|
1438
|
+
intent[name] = resolveMapping(mapping, lightPrimitives, darkPrimitives, config);
|
|
1439
|
+
}
|
|
1440
|
+
for (const [name, mapping] of Object.entries(SEMANTIC_MAP.hairline)) {
|
|
1441
|
+
hairline[name] = resolveMapping(mapping, lightPrimitives, darkPrimitives, config);
|
|
1442
|
+
}
|
|
1443
|
+
return { text, surface, border, interactive, intent, hairline };
|
|
1373
1444
|
}
|
|
1374
1445
|
|
|
1375
1446
|
// src/overrides.ts
|
|
@@ -1377,9 +1448,13 @@ var TOKEN_CATEGORIES = [
|
|
|
1377
1448
|
{ prefix: "text-", key: "text" },
|
|
1378
1449
|
{ prefix: "surface-", key: "surface" },
|
|
1379
1450
|
{ prefix: "border-", key: "border" },
|
|
1380
|
-
{ prefix: "interactive-", key: "interactive" }
|
|
1451
|
+
{ prefix: "interactive-", key: "interactive" },
|
|
1452
|
+
{ prefix: "hairline-", key: "hairline" }
|
|
1381
1453
|
];
|
|
1382
1454
|
function findToken(key, tokens) {
|
|
1455
|
+
if (key === "hairline" && "default" in tokens.hairline) {
|
|
1456
|
+
return { group: tokens.hairline, name: "default" };
|
|
1457
|
+
}
|
|
1383
1458
|
for (const { prefix, key: groupKey } of TOKEN_CATEGORIES) {
|
|
1384
1459
|
if (key.startsWith(prefix)) {
|
|
1385
1460
|
const name = key.slice(prefix.length);
|
|
@@ -1388,6 +1463,9 @@ function findToken(key, tokens) {
|
|
|
1388
1463
|
}
|
|
1389
1464
|
}
|
|
1390
1465
|
}
|
|
1466
|
+
if (key in tokens.intent) {
|
|
1467
|
+
return { group: tokens.intent, name: key };
|
|
1468
|
+
}
|
|
1391
1469
|
return null;
|
|
1392
1470
|
}
|
|
1393
1471
|
function applyOverrides(tokens, overrides) {
|
|
@@ -1396,9 +1474,11 @@ function applyOverrides(tokens, overrides) {
|
|
|
1396
1474
|
text: { ...tokens.text },
|
|
1397
1475
|
surface: { ...tokens.surface },
|
|
1398
1476
|
border: { ...tokens.border },
|
|
1399
|
-
interactive: { ...tokens.interactive }
|
|
1477
|
+
interactive: { ...tokens.interactive },
|
|
1478
|
+
intent: { ...tokens.intent },
|
|
1479
|
+
hairline: { ...tokens.hairline }
|
|
1400
1480
|
};
|
|
1401
|
-
for (const group of ["text", "surface", "border", "interactive"]) {
|
|
1481
|
+
for (const group of ["text", "surface", "border", "interactive", "intent", "hairline"]) {
|
|
1402
1482
|
for (const [name, value] of Object.entries(result[group])) {
|
|
1403
1483
|
result[group][name] = { ...value };
|
|
1404
1484
|
}
|
|
@@ -1615,10 +1695,13 @@ function exportTheme(primitives, config) {
|
|
|
1615
1695
|
const motion = {};
|
|
1616
1696
|
for (const [key, defaultVal] of Object.entries(DEFAULT_MOTION)) {
|
|
1617
1697
|
const val = config.motion[key];
|
|
1618
|
-
if (val !== defaultVal) {
|
|
1698
|
+
if (val !== void 0 && val !== defaultVal) {
|
|
1619
1699
|
motion[key] = val;
|
|
1620
1700
|
}
|
|
1621
1701
|
}
|
|
1702
|
+
if (config.motion["easing-overshoot"] !== void 0) {
|
|
1703
|
+
motion["easing-overshoot"] = config.motion["easing-overshoot"];
|
|
1704
|
+
}
|
|
1622
1705
|
if (Object.keys(motion).length > 0) {
|
|
1623
1706
|
output.motion = motion;
|
|
1624
1707
|
}
|
|
@@ -268,6 +268,12 @@ interface VisorThemeConfig {
|
|
|
268
268
|
"duration-normal"?: string;
|
|
269
269
|
"duration-slow"?: string;
|
|
270
270
|
easing?: string;
|
|
271
|
+
/**
|
|
272
|
+
* VI-451 (drive-by): opt-in tier-2 easing for bouncy entrances
|
|
273
|
+
* (marker pops, scale-in entrances). Emitted as `--motion-easing-overshoot`
|
|
274
|
+
* when set; absent themes fall through to the default `--motion-easing-spring`.
|
|
275
|
+
*/
|
|
276
|
+
"easing-overshoot"?: string;
|
|
271
277
|
};
|
|
272
278
|
overrides?: {
|
|
273
279
|
light?: Record<string, string>;
|
|
@@ -380,6 +386,8 @@ interface ResolvedThemeConfig {
|
|
|
380
386
|
"duration-normal": string;
|
|
381
387
|
"duration-slow": string;
|
|
382
388
|
easing: string;
|
|
389
|
+
/** VI-451 (drive-by): opt-in bouncy easing for marker pops / scale-in entrances. */
|
|
390
|
+
"easing-overshoot"?: string;
|
|
383
391
|
};
|
|
384
392
|
overrides?: {
|
|
385
393
|
light?: Record<string, string>;
|
|
@@ -408,6 +416,8 @@ interface SemanticTokens {
|
|
|
408
416
|
surface: Record<string, SemanticTokenValue>;
|
|
409
417
|
border: Record<string, SemanticTokenValue>;
|
|
410
418
|
interactive: Record<string, SemanticTokenValue>;
|
|
419
|
+
intent: Record<string, SemanticTokenValue>;
|
|
420
|
+
hairline: Record<string, SemanticTokenValue>;
|
|
411
421
|
}
|
|
412
422
|
interface ThemeOutput {
|
|
413
423
|
primitivesCss: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loworbitstudio/visor-theme-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.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",
|