okchroma 0.8.2 → 0.9.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.
- package/README.md +136 -101
- package/dist-lib/index.cjs +107 -127
- package/dist-lib/index.mjs +107 -127
- package/dist-lib/types/engine/archetypes.d.ts +1 -1
- package/dist-lib/types/engine/dtcgRender.d.ts +2 -2
- package/dist-lib/types/engine/figmaRender.d.ts +0 -1
- package/dist-lib/types/engine/requirements/producers.d.ts +4 -0
- package/dist-lib/types/engine/tokenNames.d.ts +8 -12
- package/dist-lib/types/index.d.ts +1 -1
- package/package.json +1 -1
package/dist-lib/index.cjs
CHANGED
|
@@ -29,6 +29,7 @@ __export(index_exports, {
|
|
|
29
29
|
LINK_GROUP: () => LINK_GROUP,
|
|
30
30
|
LINK_POSTURES: () => LINK_POSTURES,
|
|
31
31
|
LINK_STATES: () => LINK_STATES,
|
|
32
|
+
LINK_STEP: () => LINK_STEP,
|
|
32
33
|
MODE_SPECS: () => MODE_SPECS,
|
|
33
34
|
OFFSET_ALPHAS: () => OFFSET_ALPHAS,
|
|
34
35
|
OUTLINE_HOVER_ALPHA: () => OUTLINE_HOVER_ALPHA,
|
|
@@ -43,9 +44,7 @@ __export(index_exports, {
|
|
|
43
44
|
STAMP_FILL: () => STAMP_FILL,
|
|
44
45
|
STAMP_FILL_HOVER: () => STAMP_FILL_HOVER,
|
|
45
46
|
STAMP_FILL_PRESSED: () => STAMP_FILL_PRESSED,
|
|
46
|
-
STAMP_LEAF: () => STAMP_LEAF,
|
|
47
47
|
STAMP_ON: () => STAMP_ON,
|
|
48
|
-
STAMP_STATE_LEAVES: () => STAMP_STATE_LEAVES,
|
|
49
48
|
SUBTLE_PASTEL_K: () => SUBTLE_PASTEL_K,
|
|
50
49
|
SUBTLE_TINT_MULT: () => SUBTLE_TINT_MULT,
|
|
51
50
|
absolutePath: () => absolutePath,
|
|
@@ -66,6 +65,7 @@ __export(index_exports, {
|
|
|
66
65
|
generateScale: () => generateScale,
|
|
67
66
|
generateSubtleSecondary: () => generateSubtleSecondary,
|
|
68
67
|
groupEntries: () => groupEntries,
|
|
68
|
+
linkLeaf: () => linkLeaf,
|
|
69
69
|
linkPath: () => linkPath,
|
|
70
70
|
neutralCss: () => neutralCss,
|
|
71
71
|
neutralTintHue: () => neutralTintHue,
|
|
@@ -114,13 +114,13 @@ function stateStepL(restL, _mode, k) {
|
|
|
114
114
|
}
|
|
115
115
|
var OVERRIDE_LIGHT_BELOW = ARCHETYPES.find((a) => a.name === "rich").min;
|
|
116
116
|
var OVERRIDE_DARK_ABOVE = ARCHETYPES.find((a) => a.name === "light").min;
|
|
117
|
-
function stateFillL(restL, mode, k) {
|
|
117
|
+
function stateFillL(restL, mode, k, keepsPole) {
|
|
118
118
|
const natural = mode === "dark" ? 1 : -1;
|
|
119
119
|
const overridden = mode === "light" ? restL < OVERRIDE_LIGHT_BELOW : restL > OVERRIDE_DARK_ABOVE;
|
|
120
120
|
const preferred = overridden ? -natural : natural;
|
|
121
121
|
const fits = (d) => {
|
|
122
122
|
const p = restL + d * stateStepL(restL, mode, 2);
|
|
123
|
-
return p >= STATE_L_MIN && p <= STATE_L_MAX;
|
|
123
|
+
return p >= STATE_L_MIN && p <= STATE_L_MAX && (keepsPole?.(p) ?? true);
|
|
124
124
|
};
|
|
125
125
|
const dir = fits(preferred) ? preferred : fits(-preferred) ? -preferred : preferred;
|
|
126
126
|
const L = restL + dir * stateStepL(restL, mode, k);
|
|
@@ -838,32 +838,20 @@ function stopTokenName(stop) {
|
|
|
838
838
|
}
|
|
839
839
|
var PAPER_0 = "paper-0";
|
|
840
840
|
var PEN_100 = "pen-100";
|
|
841
|
-
var STAMP_FILL = "stamp-
|
|
842
|
-
var STAMP_FILL_HOVER = "stamp-
|
|
843
|
-
var STAMP_FILL_PRESSED = "stamp-
|
|
841
|
+
var STAMP_FILL = "stamp-0";
|
|
842
|
+
var STAMP_FILL_HOVER = "stamp-1";
|
|
843
|
+
var STAMP_FILL_PRESSED = "stamp-2";
|
|
844
844
|
var STAMP_EDGE = "stamp-edge";
|
|
845
845
|
var STAMP_ON = "stamp-on";
|
|
846
|
-
var STAMP_STATE_LEAVES = {
|
|
847
|
-
[STAMP_FILL]: "stamp/fill",
|
|
848
|
-
[STAMP_FILL_HOVER]: "stamp/fill-hover",
|
|
849
|
-
[STAMP_FILL_PRESSED]: "stamp/fill-pressed",
|
|
850
|
-
[STAMP_EDGE]: "stamp/edge",
|
|
851
|
-
[STAMP_ON]: "stamp/on"
|
|
852
|
-
};
|
|
853
|
-
var STAMP_LEAF = {
|
|
854
|
-
FILL: STAMP_STATE_LEAVES[STAMP_FILL],
|
|
855
|
-
FILL_HOVER: STAMP_STATE_LEAVES[STAMP_FILL_HOVER],
|
|
856
|
-
FILL_PRESSED: STAMP_STATE_LEAVES[STAMP_FILL_PRESSED],
|
|
857
|
-
EDGE: STAMP_STATE_LEAVES[STAMP_EDGE],
|
|
858
|
-
ON: STAMP_STATE_LEAVES[STAMP_ON]
|
|
859
|
-
};
|
|
860
846
|
var cssVarName = (path) => `--${path.join("-")}`;
|
|
861
847
|
var figmaPathOf = (path) => path.join("/");
|
|
862
|
-
var familyPath = (family, leaf) => [family,
|
|
848
|
+
var familyPath = (family, leaf) => [family, leaf];
|
|
863
849
|
var LINK_GROUP = "link";
|
|
864
850
|
var LINK_POSTURES = ["default", "inverse"];
|
|
865
851
|
var LINK_STATES = ["enabled", "hover", "pressed"];
|
|
866
|
-
var
|
|
852
|
+
var LINK_STEP = { enabled: 0, hover: 1, pressed: 2 };
|
|
853
|
+
var linkLeaf = (posture, state) => `${posture}-${LINK_STEP[state]}`;
|
|
854
|
+
var linkPath = (posture, state) => [LINK_GROUP, linkLeaf(posture, state)];
|
|
867
855
|
var ABSOLUTE_GROUP = "absolute";
|
|
868
856
|
var absolutePath = (family) => [ABSOLUTE_GROUP, family];
|
|
869
857
|
var COLOR_GROUP = "color";
|
|
@@ -2236,6 +2224,20 @@ function ctaDarkDualGateL(base, darkH, onFillTextIsWhite, enforce, coLc, capLoL,
|
|
|
2236
2224
|
const lLc = findLForBlackTextLc(startL, C2, darkH, coLc + APCA_SOLVE_MARGIN_LC, capHiL);
|
|
2237
2225
|
return Math.max(l45, Math.min(lLc, capHiL));
|
|
2238
2226
|
}
|
|
2227
|
+
function stepKeepsPole(mode, white, chromaAt, H2, law) {
|
|
2228
|
+
if (mode === "light") return void 0;
|
|
2229
|
+
if (law.enforceLc !== void 0) {
|
|
2230
|
+
const bar = law.enforceLc;
|
|
2231
|
+
const lcAt = white ? whiteTextLcAt : blackTextLcAt;
|
|
2232
|
+
return (L) => lcAt(L, chromaAt(L), H2) >= bar;
|
|
2233
|
+
}
|
|
2234
|
+
if (law.ratioFloor === void 0) return void 0;
|
|
2235
|
+
const floor = law.ratioFloor, poleY = white ? 1 : 0;
|
|
2236
|
+
return (L) => {
|
|
2237
|
+
const C2 = clampChromaToGamut(L, chromaAt(L), H2);
|
|
2238
|
+
return Math.min(legalRatio(L, C2, H2, poleY), contrastRatio(shippedY(L, C2, H2), poleY)) >= floor;
|
|
2239
|
+
};
|
|
2240
|
+
}
|
|
2239
2241
|
function onFillIsWhiteDarkAt(L, C2, H2, enforce, ratioFloor) {
|
|
2240
2242
|
return onTextIsWhite(apcaYAt(L, C2, H2), L, C2, H2, enforce, ratioFloor);
|
|
2241
2243
|
}
|
|
@@ -2518,7 +2520,8 @@ function resolveRamp(hex, mode, spec, opts) {
|
|
|
2518
2520
|
const enforceLc = spec.ons.onFill.enforceLc;
|
|
2519
2521
|
const coLc = ctx.opts?.apcaClearance && enforceLc === void 0 ? ctx.opts.apcaClearanceLc ?? spec.ons.onFill.coEnforceLc : void 0;
|
|
2520
2522
|
const onFloor = enforceLc !== void 0 ? void 0 : spec.ons.onFill.ratioFloor;
|
|
2521
|
-
let cta,
|
|
2523
|
+
let cta, onFillIsWhite;
|
|
2524
|
+
let stateC, stateH;
|
|
2522
2525
|
if (mode === "light") {
|
|
2523
2526
|
onFillIsWhite = onFillIsWhiteLight(ctx, enforceLc !== void 0 ? false : onFillEnforce);
|
|
2524
2527
|
let light9L = enforceLc !== void 0 ? ctaLightLApca(ctx, onFillIsWhite, onFillEnforce, enforceLc) : ctaLightL(ctx, onFillIsWhite, onFillEnforce);
|
|
@@ -2550,21 +2553,14 @@ function resolveRamp(hex, mode, spec, opts) {
|
|
|
2550
2553
|
}
|
|
2551
2554
|
}
|
|
2552
2555
|
cta = emitRole(STAMP_FILL, light9L, ctaCFor(light9L) * ctaCMul, ctaH);
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
if (light9L !== ctx.scaleL) {
|
|
2560
|
-
cta.enforced = true;
|
|
2561
|
-
ctaHover.enforced = true;
|
|
2562
|
-
ctaPressed.enforced = true;
|
|
2563
|
-
}
|
|
2556
|
+
stateC = {
|
|
2557
|
+
hover: (L) => ctx.cAt("light", L, (hoverReq?.chromaMult ?? 1) * ctx.brandC) * ctaCMul,
|
|
2558
|
+
pressed: (L) => ctx.cAt("light", L, (pressedReq?.chromaMult ?? 1) * ctx.brandC) * ctaCMul
|
|
2559
|
+
};
|
|
2560
|
+
stateH = ctaH;
|
|
2561
|
+
if (light9L !== ctx.scaleL) cta.enforced = true;
|
|
2564
2562
|
if (repelled) {
|
|
2565
2563
|
cta.repelled = true;
|
|
2566
|
-
ctaHover.repelled = true;
|
|
2567
|
-
ctaPressed.repelled = true;
|
|
2568
2564
|
onFillIsWhite = onFillIsWhiteDarkAt(
|
|
2569
2565
|
cta.L,
|
|
2570
2566
|
cta.C,
|
|
@@ -2577,50 +2573,29 @@ function resolveRamp(hex, mode, spec, opts) {
|
|
|
2577
2573
|
const d = dctx;
|
|
2578
2574
|
const cta9L = ctx.opts?.darkCtaFlatApp !== void 0 ? flatDarkCtaL(d, (L) => ctx.cAt("dark", L, d.darkC9), ctx.darkCtaH, ctx.opts.darkCtaFlatApp) : d.dark9L;
|
|
2579
2575
|
const dCFor = (L) => ctx.cAt("dark", L, d.darkC9);
|
|
2580
|
-
|
|
2576
|
+
stateC = { hover: dCFor, pressed: dCFor };
|
|
2577
|
+
stateH = ctx.darkCtaH;
|
|
2581
2578
|
cta = emitRole(STAMP_FILL, cta9L, dCFor(cta9L), ctx.darkCtaH);
|
|
2582
|
-
{
|
|
2583
|
-
const [hL, pL] = dTrio(cta9L);
|
|
2584
|
-
ctaHover = emitRole(STAMP_FILL_HOVER, hL, dCFor(hL), ctx.darkCtaH);
|
|
2585
|
-
ctaPressed = emitRole(STAMP_FILL_PRESSED, pL, dCFor(pL), ctx.darkCtaH);
|
|
2586
|
-
}
|
|
2587
2579
|
onFillIsWhite = onFillIsWhiteDarkAt(cta.L, cta.C, cta.H, enforceLc !== void 0 ? false : onFillEnforce);
|
|
2588
2580
|
const enforcedL = enforceLc !== void 0 ? ctaDarkEnforcedLApca(ctx, cta, onFillIsWhite, onFillEnforce, enforceLc) : ctaDarkEnforcedL(ctx, cta, onFillIsWhite, onFillEnforce);
|
|
2589
2581
|
if (enforcedL !== null) {
|
|
2590
2582
|
cta = emitRole(STAMP_FILL, enforcedL, dCFor(enforcedL), ctx.darkCtaH);
|
|
2591
|
-
const [hL, pL] = dTrio(enforcedL);
|
|
2592
|
-
ctaHover = emitRole(STAMP_FILL_HOVER, hL, dCFor(hL), ctx.darkCtaH);
|
|
2593
|
-
ctaPressed = emitRole(STAMP_FILL_PRESSED, pL, dCFor(pL), ctx.darkCtaH);
|
|
2594
2583
|
cta.enforced = true;
|
|
2595
|
-
ctaHover.enforced = true;
|
|
2596
|
-
ctaPressed.enforced = true;
|
|
2597
2584
|
}
|
|
2598
2585
|
if (coLc !== void 0) {
|
|
2599
2586
|
const [capLoL, capHiL] = CTA_CLEARANCE_CAPS;
|
|
2600
2587
|
const clearedL = ctaDarkDualGateL(cta, ctx.darkCtaH, onFillIsWhite, onFillEnforce, coLc + APCA_ENFORCE_MARGIN_LC, capLoL, capHiL);
|
|
2601
2588
|
if (Math.abs(clearedL - cta.L) > 1e-9) {
|
|
2602
2589
|
cta = emitRole(STAMP_FILL, clearedL, dCFor(clearedL), ctx.darkCtaH);
|
|
2603
|
-
const [hL, pL] = dTrio(clearedL);
|
|
2604
|
-
ctaHover = emitRole(STAMP_FILL_HOVER, hL, dCFor(hL), ctx.darkCtaH);
|
|
2605
|
-
ctaPressed = emitRole(STAMP_FILL_PRESSED, pL, dCFor(pL), ctx.darkCtaH);
|
|
2606
2590
|
cta.enforced = true;
|
|
2607
|
-
ctaHover.enforced = true;
|
|
2608
|
-
ctaPressed.enforced = true;
|
|
2609
2591
|
}
|
|
2610
2592
|
}
|
|
2611
2593
|
if (ctx.opts?.ctaSolve) {
|
|
2612
2594
|
const exitL = solveDarkCtaExit(cta, dCFor, ctx.darkCtaH, ctx.opts.ctaSolve.redDark, enforceLc, coLc);
|
|
2613
2595
|
if (exitL !== null) {
|
|
2614
2596
|
cta = emitRole(STAMP_FILL, exitL, dCFor(exitL), ctx.darkCtaH);
|
|
2615
|
-
const [hL, pL] = dTrio(exitL);
|
|
2616
|
-
ctaHover = emitRole(STAMP_FILL_HOVER, hL, dCFor(hL), ctx.darkCtaH);
|
|
2617
|
-
ctaPressed = emitRole(STAMP_FILL_PRESSED, pL, dCFor(pL), ctx.darkCtaH);
|
|
2618
2597
|
cta.enforced = true;
|
|
2619
|
-
ctaHover.enforced = true;
|
|
2620
|
-
ctaPressed.enforced = true;
|
|
2621
2598
|
cta.repelled = true;
|
|
2622
|
-
ctaHover.repelled = true;
|
|
2623
|
-
ctaPressed.repelled = true;
|
|
2624
2599
|
onFillIsWhite = onFillIsWhiteDarkAt(
|
|
2625
2600
|
cta.L,
|
|
2626
2601
|
cta.C,
|
|
@@ -2636,6 +2611,19 @@ function resolveRamp(hex, mode, spec, opts) {
|
|
|
2636
2611
|
const other = legalRatio(cta.L, cta.C, cta.H, onFillIsWhite ? 0 : 1);
|
|
2637
2612
|
if (chosen < onFloor && other >= onFloor) onFillIsWhite = !onFillIsWhite;
|
|
2638
2613
|
}
|
|
2614
|
+
const keepsPole = stepKeepsPole(mode, onFillIsWhite, stateC.pressed, stateH, { ratioFloor: onFloor, enforceLc });
|
|
2615
|
+
const hL = stateFillL(cta.L, mode, 1, keepsPole);
|
|
2616
|
+
const pL = stateFillL(cta.L, mode, 2, keepsPole);
|
|
2617
|
+
const ctaHover = emitRole(STAMP_FILL_HOVER, hL, stateC.hover(hL), stateH);
|
|
2618
|
+
const ctaPressed = emitRole(STAMP_FILL_PRESSED, pL, stateC.pressed(pL), stateH);
|
|
2619
|
+
if (cta.enforced) {
|
|
2620
|
+
ctaHover.enforced = true;
|
|
2621
|
+
ctaPressed.enforced = true;
|
|
2622
|
+
}
|
|
2623
|
+
if (cta.repelled) {
|
|
2624
|
+
ctaHover.repelled = true;
|
|
2625
|
+
ctaPressed.repelled = true;
|
|
2626
|
+
}
|
|
2639
2627
|
return { mode, seed, stops, roles: { cta, ctaHover, ctaPressed }, ons: { onFillIsWhite } };
|
|
2640
2628
|
}
|
|
2641
2629
|
|
|
@@ -2718,18 +2706,18 @@ function generateNeutralScale(brandH, level = "default", contrastProfile) {
|
|
|
2718
2706
|
if (popLift > 1e-6) {
|
|
2719
2707
|
scale.ctaDark = makeStop(9, scale.dark[3].L + popLift, scale.dark[3].C, scale.dark[3].H);
|
|
2720
2708
|
}
|
|
2721
|
-
const nState = (stop, mode, rest, k) => {
|
|
2722
|
-
const L = stateFillL(rest.L, mode, k);
|
|
2723
|
-
return makeStop(stop, L, curve(L, mode), rest.H);
|
|
2724
|
-
};
|
|
2725
|
-
scale.ctaHover = nState(10, "light", scale.cta, 1);
|
|
2726
|
-
scale.ctaPressed = nState(11, "light", scale.cta, 2);
|
|
2727
|
-
scale.ctaHoverDark = nState(10, "dark", scale.ctaDark, 1);
|
|
2728
|
-
scale.ctaPressedDark = nState(11, "dark", scale.ctaDark, 2);
|
|
2729
2709
|
const onEnforce = contrastProfile !== "apca";
|
|
2730
2710
|
const onFloor = 4.5;
|
|
2731
2711
|
scale.onFillTextIsWhite = onTextIsWhite(apcaY(scale.cta.r, scale.cta.g, scale.cta.b), scale.cta.L, scale.cta.C, scale.cta.H, onEnforce, onFloor);
|
|
2732
2712
|
scale.onFillTextIsWhiteDark = onTextIsWhite(apcaY(scale.ctaDark.r, scale.ctaDark.g, scale.ctaDark.b), scale.ctaDark.L, scale.ctaDark.C, scale.ctaDark.H, onEnforce, onFloor);
|
|
2713
|
+
const nState = (stop, mode, rest, k, white) => {
|
|
2714
|
+
const L = stateFillL(rest.L, mode, k, stepKeepsPole(mode, white, (l) => curve(l, mode), rest.H, { ratioFloor: onFloor }));
|
|
2715
|
+
return makeStop(stop, L, curve(L, mode), rest.H);
|
|
2716
|
+
};
|
|
2717
|
+
scale.ctaHover = nState(10, "light", scale.cta, 1, scale.onFillTextIsWhite);
|
|
2718
|
+
scale.ctaPressed = nState(11, "light", scale.cta, 2, scale.onFillTextIsWhite);
|
|
2719
|
+
scale.ctaHoverDark = nState(10, "dark", scale.ctaDark, 1, scale.onFillTextIsWhiteDark);
|
|
2720
|
+
scale.ctaPressedDark = nState(11, "dark", scale.ctaDark, 2, scale.onFillTextIsWhiteDark);
|
|
2733
2721
|
return scale;
|
|
2734
2722
|
}
|
|
2735
2723
|
function generateSubtleSecondary(hex, opts) {
|
|
@@ -2742,10 +2730,6 @@ function generateSubtleSecondary(hex, opts) {
|
|
|
2742
2730
|
});
|
|
2743
2731
|
const asCta = (stop, src) => makeStop(stop, src.L, src.C, src.H);
|
|
2744
2732
|
const mk = (stop, L, mode) => makeStop(stop, L, curve(L, mode), scale.brandH);
|
|
2745
|
-
const st = (stop, mode, rest, k) => {
|
|
2746
|
-
const L = stateFillL(rest.L, mode, k);
|
|
2747
|
-
return makeStop(stop, L, curve(L, mode), rest.H);
|
|
2748
|
-
};
|
|
2749
2733
|
if (opts?.ctaL) {
|
|
2750
2734
|
scale.cta = mk(9, opts.ctaL.light, "light");
|
|
2751
2735
|
scale.ctaDark = mk(9, opts.ctaL.dark, "dark");
|
|
@@ -2753,14 +2737,18 @@ function generateSubtleSecondary(hex, opts) {
|
|
|
2753
2737
|
scale.cta = asCta(9, scale.light[3]);
|
|
2754
2738
|
scale.ctaDark = asCta(9, scale.dark[3]);
|
|
2755
2739
|
}
|
|
2756
|
-
scale.ctaHover = st(10, "light", scale.cta, 1);
|
|
2757
|
-
scale.ctaPressed = st(11, "light", scale.cta, 2);
|
|
2758
|
-
scale.ctaHoverDark = st(10, "dark", scale.ctaDark, 1);
|
|
2759
|
-
scale.ctaPressedDark = st(11, "dark", scale.ctaDark, 2);
|
|
2760
2740
|
const onEnforce = opts?.contrastProfile !== "apca";
|
|
2761
2741
|
const onFloor = 4.5;
|
|
2762
2742
|
scale.onFillTextIsWhite = onTextIsWhite(apcaY(scale.cta.r, scale.cta.g, scale.cta.b), scale.cta.L, scale.cta.C, scale.cta.H, onEnforce, onFloor);
|
|
2763
2743
|
scale.onFillTextIsWhiteDark = onTextIsWhite(apcaY(scale.ctaDark.r, scale.ctaDark.g, scale.ctaDark.b), scale.ctaDark.L, scale.ctaDark.C, scale.ctaDark.H, onEnforce, onFloor);
|
|
2744
|
+
const st = (stop, mode, rest, k, white) => {
|
|
2745
|
+
const L = stateFillL(rest.L, mode, k, stepKeepsPole(mode, white, (l) => curve(l, mode), rest.H, { ratioFloor: onFloor }));
|
|
2746
|
+
return makeStop(stop, L, curve(L, mode), rest.H);
|
|
2747
|
+
};
|
|
2748
|
+
scale.ctaHover = st(10, "light", scale.cta, 1, scale.onFillTextIsWhite);
|
|
2749
|
+
scale.ctaPressed = st(11, "light", scale.cta, 2, scale.onFillTextIsWhite);
|
|
2750
|
+
scale.ctaHoverDark = st(10, "dark", scale.ctaDark, 1, scale.onFillTextIsWhiteDark);
|
|
2751
|
+
scale.ctaPressedDark = st(11, "dark", scale.ctaDark, 2, scale.onFillTextIsWhiteDark);
|
|
2764
2752
|
return scale;
|
|
2765
2753
|
}
|
|
2766
2754
|
|
|
@@ -2854,20 +2842,21 @@ var SCALE = {
|
|
|
2854
2842
|
// ("heavy-emphasis": "high" and "low" are plane words in the community plugin and
|
|
2855
2843
|
// "strong" carries "on")
|
|
2856
2844
|
"pen-70": { req: "heavy-emphasis text, inverted backgrounds", contrast: AA_BODY, claim: claimOf("pen"), theming: solved, collides: true },
|
|
2857
|
-
// the stamp
|
|
2845
|
+
// the stamp rows, each a position: the fill at rest and at one and two steps, the edge,
|
|
2846
|
+
// the on-text. No body names a state; a consumer's semantic layer names the states and
|
|
2847
|
+
// aliases the steps. "CTA" stays in these bodies on purpose: it is not a token label, so
|
|
2858
2848
|
// it floods nothing, and a designer's "cta" query lands on these rows.
|
|
2859
2849
|
// the usage lines are the owner's guidance, for the document rendering: the fill is
|
|
2860
2850
|
// misused as a standalone color in the wild
|
|
2861
|
-
"stamp
|
|
2862
|
-
req: "CTAs",
|
|
2851
|
+
"stamp-0": {
|
|
2852
|
+
req: "CTAs, the fill at rest",
|
|
2863
2853
|
theming: (f) => `fully re-solved per theme and family${COLOR_WORD[f]}`,
|
|
2864
|
-
use: "primary button fills; optional for avatars, badges and other elements that carry text. Not a standalone color: it has no contrast guarantee of its own, only its on-text has one. Use it alone or with
|
|
2854
|
+
use: "primary button fills; optional for avatars, badges and other elements that carry text. Not a standalone color: it has no contrast guarantee of its own, only its on-text has one. Use it alone or with the two steps above it. Always bordered with its edge"
|
|
2865
2855
|
},
|
|
2866
|
-
"stamp
|
|
2867
|
-
"stamp
|
|
2868
|
-
"stamp
|
|
2869
|
-
|
|
2870
|
-
"stamp/on": { req: "text over the CTA color", contrast: `${AA_BODY} over its CTA`, theming: (f) => `whichever pole passes; quiet CTAs take the soft pole${COLOR_WORD[f]}`, use: "the only text color over the fill; never elsewhere" }
|
|
2856
|
+
"stamp-1": { req: "CTAs, the fill one step from rest", theming: (f) => `follows the fill at rest${COLOR_WORD[f]}`, use: "the fill one step from rest, with the fill at rest; for nothing else. Always bordered with the edge" },
|
|
2857
|
+
"stamp-2": { req: "CTAs, the fill two steps from rest", theming: (f) => `follows the fill at rest${COLOR_WORD[f]}`, use: "the fill two steps from rest, with the fill at rest; for nothing else. Always bordered with the edge" },
|
|
2858
|
+
"stamp-edge": { req: "min APCA visibility", theming: (f) => `draws for CTAs that sit close to the page; strength per family tier${COLOR_WORD[f]}`, use: "the border of the fill at every step, always rendered with it and never without it (it resolves to transparent unless the fill sits close to the page); for nothing else" },
|
|
2859
|
+
"stamp-on": { req: "text over the CTA color", contrast: `${AA_BODY} over its CTA`, theming: (f) => `whichever pole passes; quiet CTAs take the soft pole${COLOR_WORD[f]}`, use: "the only text color over the fill at every step; never elsewhere" }
|
|
2871
2860
|
};
|
|
2872
2861
|
var NEUTRAL_ONLY = {
|
|
2873
2862
|
// the pole is measured against the neutral's own stops only; as text, it is the on-color
|
|
@@ -2876,15 +2865,15 @@ var NEUTRAL_ONLY = {
|
|
|
2876
2865
|
// the literal pole carries no tint, so no theming line
|
|
2877
2866
|
"pen-100": { req: "max-emphasis text", contrast: AA_BODY, claim: () => `${AA_BODY} on every paper and chalk of every family` }
|
|
2878
2867
|
};
|
|
2879
|
-
var LINK = (
|
|
2880
|
-
req: "links" +
|
|
2868
|
+
var LINK = (step, contrast) => ({
|
|
2869
|
+
req: "links" + step,
|
|
2881
2870
|
contrast,
|
|
2882
2871
|
claim: () => `${contrast} on every paper of the neutral`,
|
|
2883
2872
|
theming: "rides the theme\u2019s link color; custom seed re-solves; overridable per theme",
|
|
2884
2873
|
use: "hyperlinks; not a text-style CTA, which is the text stops read as states"
|
|
2885
2874
|
});
|
|
2886
|
-
var LINK_INVERSE = (
|
|
2887
|
-
req: "links over inverted backgrounds" +
|
|
2875
|
+
var LINK_INVERSE = (step, contrast) => ({
|
|
2876
|
+
req: "links over inverted backgrounds" + step,
|
|
2888
2877
|
contrast,
|
|
2889
2878
|
claim: () => `${contrast} on any family's pen-70`,
|
|
2890
2879
|
theming: "same seed as the link, re-solved for inverted backgrounds; overridable per theme",
|
|
@@ -2893,12 +2882,12 @@ var LINK_INVERSE = (state, contrast) => ({
|
|
|
2893
2882
|
var SYSTEM = {
|
|
2894
2883
|
"absolute/brand": { req: "identity seed reference", theming: "the theme\u2019s own input, as given", use: "a reference value (logos, swatches of the input); never a UI color, it carries no contrast guarantee" },
|
|
2895
2884
|
"absolute/brand-alt": { req: "identity seed reference", theming: "the theme\u2019s paired input, as given", use: "a reference value (logos, swatches of the input); never a UI color, it carries no contrast guarantee" },
|
|
2896
|
-
"link/default
|
|
2897
|
-
"link/default
|
|
2898
|
-
"link/default
|
|
2899
|
-
"link/inverse
|
|
2900
|
-
"link/inverse
|
|
2901
|
-
"link/inverse
|
|
2885
|
+
"link/default-0": LINK("", AA_BODY),
|
|
2886
|
+
"link/default-1": LINK(", one step from rest", AA_BODY),
|
|
2887
|
+
"link/default-2": LINK(", two steps from rest", AA_BODY),
|
|
2888
|
+
"link/inverse-0": LINK_INVERSE("", AA_BODY),
|
|
2889
|
+
"link/inverse-1": LINK_INVERSE(", one step from rest", AA_BODY),
|
|
2890
|
+
"link/inverse-2": LINK_INVERSE(", two steps from rest", AA_BODY)
|
|
2902
2891
|
};
|
|
2903
2892
|
var PREFIXES = [
|
|
2904
2893
|
// community spellings first: the family word is a prefix of the community shapes
|
|
@@ -3335,11 +3324,12 @@ function escapeCtaFamily(nScale, mode, contrastProfile) {
|
|
|
3335
3324
|
if (!strongText) throw new Error("escapeCtaFamily: the neutral scale has no ink-11 stop");
|
|
3336
3325
|
const mk = (stop, L) => makeStop(stop, L, strongText.C, strongText.H);
|
|
3337
3326
|
const cta = mk(9, strongText.L);
|
|
3338
|
-
const ctaHover = mk(10, stateFillL(strongText.L, mode, 1));
|
|
3339
|
-
const ctaPressed = mk(11, stateFillL(strongText.L, mode, 2));
|
|
3340
3327
|
const onEnforce = contrastProfile !== "apca";
|
|
3341
3328
|
const onFloor = contrastProfile === "apca" ? void 0 : 4.5;
|
|
3342
3329
|
const onFillIsWhite = onTextIsWhite(apcaY(cta.r, cta.g, cta.b), cta.L, cta.C, cta.H, onEnforce, onFloor);
|
|
3330
|
+
const keepsPole = stepKeepsPole(mode, onFillIsWhite, () => strongText.C, strongText.H, { ratioFloor: onFloor });
|
|
3331
|
+
const ctaHover = mk(10, stateFillL(strongText.L, mode, 1, keepsPole));
|
|
3332
|
+
const ctaPressed = mk(11, stateFillL(strongText.L, mode, 2, keepsPole));
|
|
3343
3333
|
return { cta, ctaHover, ctaPressed, onFillIsWhite };
|
|
3344
3334
|
}
|
|
3345
3335
|
var SECONDARY_DISTINCT_DELTA_E = 0.12;
|
|
@@ -3889,9 +3879,6 @@ function colorFromHexString(hex) {
|
|
|
3889
3879
|
const h = hex.replace("#", "");
|
|
3890
3880
|
return color(parseInt(h.slice(0, 2), 16) / 255, parseInt(h.slice(2, 4), 16) / 255, parseInt(h.slice(4, 6), 16) / 255);
|
|
3891
3881
|
}
|
|
3892
|
-
function bandedLeaf(flat) {
|
|
3893
|
-
return STAMP_STATE_LEAVES[flat] ?? flat;
|
|
3894
|
-
}
|
|
3895
3882
|
function groupEntries(g2) {
|
|
3896
3883
|
const entries = Object.entries(g2);
|
|
3897
3884
|
const digitLeading = (k) => /^\d/.test(k);
|
|
@@ -3899,24 +3886,15 @@ function groupEntries(g2) {
|
|
|
3899
3886
|
return entries.sort((a, b) => parseInt(b[0], 10) - parseInt(a[0], 10));
|
|
3900
3887
|
return entries;
|
|
3901
3888
|
}
|
|
3902
|
-
function putLeaf(g2, flat, tok) {
|
|
3903
|
-
const path = bandedLeaf(flat).split("/");
|
|
3904
|
-
let cur = g2;
|
|
3905
|
-
for (const seg of path.slice(0, -1)) {
|
|
3906
|
-
if (!(seg in cur) || "$type" in cur[seg]) cur[seg] = {};
|
|
3907
|
-
cur = cur[seg];
|
|
3908
|
-
}
|
|
3909
|
-
cur[path[path.length - 1]] = tok;
|
|
3910
|
-
}
|
|
3911
3889
|
function rampGroup(stops, onFillWhite, extra) {
|
|
3912
3890
|
const g2 = {};
|
|
3913
3891
|
const leaves = stops.map((s) => ({ name: stopTokenName(s.stop), tok: colorFromStop(s) })).sort((a, b) => tokenOrder(a.name) - tokenOrder(b.name));
|
|
3914
|
-
for (const l of leaves)
|
|
3915
|
-
if (extra?.cta)
|
|
3916
|
-
if (extra?.ctaHover)
|
|
3917
|
-
if (extra?.ctaPressed)
|
|
3918
|
-
if (extra?.cta)
|
|
3919
|
-
|
|
3892
|
+
for (const l of leaves) g2[l.name] = l.tok;
|
|
3893
|
+
if (extra?.cta) g2[STAMP_FILL] = colorFromStop(extra.cta);
|
|
3894
|
+
if (extra?.ctaHover) g2[STAMP_FILL_HOVER] = colorFromStop(extra.ctaHover);
|
|
3895
|
+
if (extra?.ctaPressed) g2[STAMP_FILL_PRESSED] = colorFromStop(extra.ctaPressed);
|
|
3896
|
+
if (extra?.cta) g2[STAMP_EDGE] = extra.ctaBorder ?? TRANSPARENT_TOKEN;
|
|
3897
|
+
g2[STAMP_ON] = pole(onFillWhite);
|
|
3920
3898
|
return g2;
|
|
3921
3899
|
}
|
|
3922
3900
|
function themeToFigma(r, input) {
|
|
@@ -3955,16 +3933,18 @@ function themeToFigma(r, input) {
|
|
|
3955
3933
|
if (input.secondaryStyle === "outline" && input.secondary) {
|
|
3956
3934
|
const s8 = secondary[mode].find((s) => s.stop === 8);
|
|
3957
3935
|
const s9 = secondary[mode].find((s) => s.stop === 9);
|
|
3958
|
-
|
|
3936
|
+
secondaryGroup[STAMP_FILL] = TRANSPARENT_TOKEN;
|
|
3959
3937
|
if (s8) {
|
|
3960
3938
|
const e = srgbEmitChannels(s8);
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3939
|
+
secondaryGroup[STAMP_FILL_HOVER] = color(e.r, e.g, e.b, OUTLINE_HOVER_ALPHA);
|
|
3940
|
+
secondaryGroup[STAMP_FILL_PRESSED] = color(e.r, e.g, e.b, OUTLINE_PRESSED_ALPHA);
|
|
3941
|
+
secondaryGroup[STAMP_EDGE] = colorFromStop(s8);
|
|
3964
3942
|
}
|
|
3965
|
-
if (s9)
|
|
3943
|
+
if (s9) secondaryGroup[STAMP_ON] = colorFromStop(s9);
|
|
3966
3944
|
}
|
|
3967
|
-
const softOnCta = (g3, white) =>
|
|
3945
|
+
const softOnCta = (g3, white) => {
|
|
3946
|
+
g3[STAMP_ON] = pole(white, SOFT_ON_CTA_ALPHA[mode]);
|
|
3947
|
+
};
|
|
3968
3948
|
softOnCta(neutralGroup, mode === "light" ? nScale.onFillTextIsWhite : nScale.onFillTextIsWhiteDark);
|
|
3969
3949
|
if (input.secondary && input.secondaryStyle !== "outline" && softOnCtaPasses(input.secondary, mode))
|
|
3970
3950
|
softOnCta(secondaryGroup, mode === "light" ? secondaryOnFillLight : secondaryOnFillDark);
|
|
@@ -3972,10 +3952,10 @@ function themeToFigma(r, input) {
|
|
|
3972
3952
|
const esc = input.ctaEscape ? escapeCtaFamily(nScale, mode, input.contrastProfile) : null;
|
|
3973
3953
|
if (esc) {
|
|
3974
3954
|
for (const g3 of input.secondary ? [brandGroup] : [brandGroup, secondaryGroup]) {
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3955
|
+
g3[STAMP_FILL] = colorFromStop(esc.cta);
|
|
3956
|
+
g3[STAMP_FILL_HOVER] = colorFromStop(esc.ctaHover);
|
|
3957
|
+
g3[STAMP_FILL_PRESSED] = colorFromStop(esc.ctaPressed);
|
|
3958
|
+
g3[STAMP_ON] = pole(esc.onFillIsWhite);
|
|
3979
3959
|
}
|
|
3980
3960
|
}
|
|
3981
3961
|
const scaleTextAt = (n) => {
|
|
@@ -3985,7 +3965,7 @@ function themeToFigma(r, input) {
|
|
|
3985
3965
|
};
|
|
3986
3966
|
const trio = (posture) => {
|
|
3987
3967
|
const t = posture === "default" ? lt ? mode === "light" ? [lt.link, lt.linkHover, lt.linkPressed] : [lt.linkDark, lt.linkHoverDark, lt.linkPressedDark] : [scaleTextAt(9), scaleTextAt(10), scaleTextAt(11)] : mode === "light" ? [invLt.link, invLt.linkHover, invLt.linkPressed] : [invLt.linkDark, invLt.linkHoverDark, invLt.linkPressedDark];
|
|
3988
|
-
return Object.fromEntries(LINK_STATES.map((state, i) => [state, colorFromStop(t[i])]));
|
|
3968
|
+
return Object.fromEntries(LINK_STATES.map((state, i) => [linkLeaf(posture, state), colorFromStop(t[i])]));
|
|
3989
3969
|
};
|
|
3990
3970
|
const g2 = {
|
|
3991
3971
|
[CSS_FAMILY.neutral]: neutralGroup,
|
|
@@ -4000,7 +3980,7 @@ function themeToFigma(r, input) {
|
|
|
4000
3980
|
ctaFamily(sig.scale, mode, role)
|
|
4001
3981
|
);
|
|
4002
3982
|
}
|
|
4003
|
-
g2[LINK_GROUP] = {
|
|
3983
|
+
g2[LINK_GROUP] = { ...trio("default"), ...trio("inverse") };
|
|
4004
3984
|
g2[ABSOLUTE_GROUP] = {
|
|
4005
3985
|
[CSS_FAMILY.brandPrimary]: colorFromHexString(scale.identityHex ?? invSeed),
|
|
4006
3986
|
[CSS_FAMILY.brandSecondary]: colorFromHexString((input.secondary ?? scale).identityHex ?? invSeed)
|