okchroma 0.6.1 → 0.8.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/README.md +82 -17
- package/dist-lib/index.cjs +331 -558
- package/dist-lib/index.mjs +331 -558
- package/dist-lib/types/engine/cssRender.d.ts +0 -37
- package/dist-lib/types/engine/dtcgRender.d.ts +47 -0
- package/dist-lib/types/engine/figmaRender.d.ts +1 -5
- package/dist-lib/types/engine/tokenDescriptions.d.ts +20 -0
- package/dist-lib/types/engine/tokenNames.d.ts +14 -30
- package/dist-lib/types/engine/tokensRender.d.ts +2 -4
- package/dist-lib/types/index.d.ts +6 -7
- package/package.json +6 -5
- package/tokens/semantic.css +0 -202
package/dist-lib/index.mjs
CHANGED
|
@@ -725,29 +725,14 @@ function perceptualDarkC(L, H2, nativeC, keep = KEEP_DARK, gamut = MASTER_GAMUT)
|
|
|
725
725
|
var SHARED_NAMES = {
|
|
726
726
|
1: "paper-1",
|
|
727
727
|
2: "paper-3",
|
|
728
|
-
// stop 3 renamed wash-3 → paper-3 (owner 2026-07-24, elevation round): it is a
|
|
729
|
-
// PLANE in both themes (light sink / dark pop), so it belongs to the surface band.
|
|
730
|
-
// NAME ONLY — generation is index-keyed and unchanged; the chalk-collision machinery
|
|
731
|
-
// (collision.ts CHALK_STOPS) deliberately still spans stops 3–7. (The requirement
|
|
732
|
-
// spec's `group` label followed the band to 'paper' on 2026-08-31 — labels only,
|
|
733
|
-
// the spans never moved; see spec.ts groupOf.)
|
|
734
|
-
// Stage B (owner 2026-08-07, names only): relabeled to the ROOT_L-derived digit,
|
|
735
|
-
// paper-5 — same band, same index.
|
|
736
728
|
3: "paper-5",
|
|
737
729
|
4: "chalk-8",
|
|
738
730
|
5: "chalk-11",
|
|
739
731
|
6: "chalk-15",
|
|
740
732
|
7: "chalk-20",
|
|
741
733
|
8: "highlighter-26",
|
|
742
|
-
//
|
|
743
|
-
//
|
|
744
|
-
// deleted; this stop carries both jobs, its on-color a paper token), the between
|
|
745
|
-
// text stop (a value the retired text-cta hover state used to generate bespokely,
|
|
746
|
-
// promoted to a normal stop), and the strong text stop. The three read as states
|
|
747
|
-
// ARE the text-style cta (owner 2026-08-12). C49 restored the top
|
|
748
|
-
// two pre-collapse stop INDICES (11, and the off-scale anchor's 12 — emitted as a
|
|
749
|
-
// literal in cssRender, not through this table) with the between stop taking the
|
|
750
|
-
// vacated index 10; the indices (9/10/11) are unchanged since.
|
|
734
|
+
// the pen band: the first text stop doubles as the emphasis fill, the between stop and
|
|
735
|
+
// the strong stop follow; the three read as states are the text-style CTA (C49)
|
|
751
736
|
9: "pencil-47",
|
|
752
737
|
10: "pen-58",
|
|
753
738
|
11: "pen-70"
|
|
@@ -779,63 +764,22 @@ var STAMP_LEAF = {
|
|
|
779
764
|
EDGE: STAMP_STATE_LEAVES[STAMP_EDGE],
|
|
780
765
|
ON: STAMP_STATE_LEAVES[STAMP_ON]
|
|
781
766
|
};
|
|
782
|
-
var
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
TRANSPARENT: "system/alpha/transparent",
|
|
793
|
-
INK: "system/alpha/ink",
|
|
794
|
-
// the DIRECTIONAL ladders (owner 2026-08-31, renaming the 2026-08-18 bare rungs
|
|
795
|
-
// and the 2026-08-29 inverse ladder): away-from-bg is the page-polarity pole
|
|
796
|
-
// (black in light, white in dark), toward-bg the flipped pole — STATE LAYERS for
|
|
797
|
-
// INVERTED grounds, whose polarity is opposite the page's. (Never call toward-bg
|
|
798
|
-
// a "chalk": that word belongs to the tinted band stops.) The reversal lives in
|
|
799
|
-
// the engine: a consumer on an inverted ground names one token and never picks a
|
|
800
|
-
// pole. Colored fills never ride these; their states stay engine-solved stops.
|
|
801
|
-
// Rungs are two-digit percent, harmonizing with shadow-04/08/12.
|
|
802
|
-
AWAY_FROM_BG_06: "system/alpha/away-from-bg/06",
|
|
803
|
-
AWAY_FROM_BG_08: "system/alpha/away-from-bg/08",
|
|
804
|
-
AWAY_FROM_BG_16: "system/alpha/away-from-bg/16",
|
|
805
|
-
TOWARD_BG_06: "system/alpha/toward-bg/06",
|
|
806
|
-
TOWARD_BG_08: "system/alpha/toward-bg/08",
|
|
807
|
-
TOWARD_BG_16: "system/alpha/toward-bg/16",
|
|
808
|
-
SHADOW_04: "system/alpha/shadow-04",
|
|
809
|
-
SHADOW_08: "system/alpha/shadow-08",
|
|
810
|
-
SHADOW_12: "system/alpha/shadow-12"
|
|
811
|
-
},
|
|
812
|
-
// the OPACITY LADDER's rows: bare numbers, never colors. `alpha` above is the group
|
|
813
|
-
// of colors that carry transparency; `opacity` is the numbers they compose with
|
|
814
|
-
// (values in cssRender OPACITY_RUNGS; the ext plugin zones these under utility/).
|
|
815
|
-
OPACITY: {
|
|
816
|
-
"004": "system/opacity/004",
|
|
817
|
-
"008": "system/opacity/008",
|
|
818
|
-
"012": "system/opacity/012",
|
|
819
|
-
"016": "system/opacity/016",
|
|
820
|
-
"024": "system/opacity/024",
|
|
821
|
-
"032": "system/opacity/032",
|
|
822
|
-
"048": "system/opacity/048",
|
|
823
|
-
"064": "system/opacity/064"
|
|
824
|
-
}
|
|
825
|
-
};
|
|
826
|
-
var SURFACE_PLANE_LAW = {
|
|
827
|
-
[SYSTEM_LEAF.SURFACE.DIM]: { light: SHARED_NAMES[3], dark: PAPER_0 },
|
|
828
|
-
[SYSTEM_LEAF.SURFACE.LOW]: { light: SHARED_NAMES[2], dark: SHARED_NAMES[1] },
|
|
829
|
-
[SYSTEM_LEAF.SURFACE.MID]: { light: SHARED_NAMES[1], dark: SHARED_NAMES[2] },
|
|
830
|
-
[SYSTEM_LEAF.SURFACE.HIGH]: { light: PAPER_0, dark: SHARED_NAMES[3] }
|
|
831
|
-
};
|
|
767
|
+
var cssVarName = (path) => `--${path.join("-")}`;
|
|
768
|
+
var figmaPathOf = (path) => path.join("/");
|
|
769
|
+
var familyPath = (family, leaf) => [family, ...(STAMP_STATE_LEAVES[leaf] ?? leaf).split("/")];
|
|
770
|
+
var LINK_GROUP = "link";
|
|
771
|
+
var LINK_POSTURES = ["default", "inverse"];
|
|
772
|
+
var LINK_STATES = ["enabled", "hover", "pressed"];
|
|
773
|
+
var linkPath = (posture, state) => [LINK_GROUP, posture, state];
|
|
774
|
+
var ABSOLUTE_GROUP = "absolute";
|
|
775
|
+
var absolutePath = (family) => [ABSOLUTE_GROUP, family];
|
|
776
|
+
var COLOR_GROUP = "color";
|
|
832
777
|
var TOKEN_ORDER = [
|
|
833
778
|
...Object.values(SHARED_NAMES),
|
|
834
779
|
STAMP_FILL,
|
|
835
780
|
STAMP_FILL_HOVER,
|
|
836
781
|
STAMP_FILL_PRESSED,
|
|
837
|
-
STAMP_ON
|
|
838
|
-
"identity"
|
|
782
|
+
STAMP_ON
|
|
839
783
|
];
|
|
840
784
|
function tokenOrder(name) {
|
|
841
785
|
const i = TOKEN_ORDER.indexOf(name);
|
|
@@ -2764,8 +2708,34 @@ var COLOR_WORD = {
|
|
|
2764
2708
|
[FAMILY.positive]: " (green)",
|
|
2765
2709
|
[FAMILY.info]: " (blue)"
|
|
2766
2710
|
};
|
|
2767
|
-
var
|
|
2768
|
-
var
|
|
2711
|
+
var COLLIDES = "shifts to avoid similar colors";
|
|
2712
|
+
var GUARANTEE_SCOPE = {
|
|
2713
|
+
highlighter: { level: AA_LARGE, grounds: ["paper"] },
|
|
2714
|
+
pencil: { level: AA_BODY, grounds: ["paper"] },
|
|
2715
|
+
pen: { level: AA_BODY, grounds: ["paper", "chalk"] }
|
|
2716
|
+
};
|
|
2717
|
+
var BAND_STOPS = {
|
|
2718
|
+
highlighter: ["highlighter-26"],
|
|
2719
|
+
pencil: ["pencil-47"],
|
|
2720
|
+
pen: ["pen-58", "pen-70"]
|
|
2721
|
+
};
|
|
2722
|
+
var list = (words) => words.length > 1 ? `${words.slice(0, -1).join(", ")} and ${words[words.length - 1]}` : words[0];
|
|
2723
|
+
var ofFamilies = (fam) => fam === FAMILY.neutral ? "of every family" : "of this family and of the neutral";
|
|
2724
|
+
var fromFamilies = (fam) => fam === FAMILY.neutral ? "from every family" : "from this family and from the neutral";
|
|
2725
|
+
var claimOf = (band) => (fam) => `${GUARANTEE_SCOPE[band].level} on every ${GUARANTEE_SCOPE[band].grounds.join(" and ")} ${ofFamilies(fam)}`;
|
|
2726
|
+
var groundLine = (ground) => (fam) => {
|
|
2727
|
+
const bands = Object.keys(GUARANTEE_SCOPE).filter((b) => GUARANTEE_SCOPE[b].grounds.includes(ground));
|
|
2728
|
+
const byLevel = /* @__PURE__ */ new Map();
|
|
2729
|
+
for (const b of bands) {
|
|
2730
|
+
const stops = [...BAND_STOPS[b], ...b === "pen" && fam === FAMILY.neutral ? ["pen-100"] : []];
|
|
2731
|
+
byLevel.set(GUARANTEE_SCOPE[b].level, [...byLevel.get(GUARANTEE_SCOPE[b].level) ?? [], ...stops]);
|
|
2732
|
+
}
|
|
2733
|
+
const clears = [...byLevel.entries()].map(([level, stops]) => `${list(stops)} clear${stops.length === 1 ? "s" : ""} it as ${level}`).join("; ");
|
|
2734
|
+
const notHeld = Object.keys(GUARANTEE_SCOPE).filter((b) => !bands.includes(b));
|
|
2735
|
+
return `${clears}, ${fromFamilies(fam)}${notHeld.length ? `; ${list(notHeld.map((b) => `the ${b}`))} ${notHeld.length === 1 ? "is" : "are"} not held against it` : ""}`;
|
|
2736
|
+
};
|
|
2737
|
+
var PAPER = { req: "backgrounds, inverted text", theming: (f) => TINT[f], collides: true, ground: groundLine("paper") };
|
|
2738
|
+
var CHALK = { req: "decorative borders, inverted text, illos, signal hierarchy", theming: (f) => TINT[f], collides: true, ground: groundLine("chalk") };
|
|
2769
2739
|
var solved = (f) => `${TINT[f]}; re-solved to clear its floor`;
|
|
2770
2740
|
var OVERLAY = {
|
|
2771
2741
|
req: "translucent backgrounds that hold their reading on any paper",
|
|
@@ -2777,106 +2747,123 @@ var SCALE = {
|
|
|
2777
2747
|
"paper-99-overlay": OVERLAY,
|
|
2778
2748
|
"paper-3": PAPER,
|
|
2779
2749
|
"paper-97-overlay": OVERLAY,
|
|
2780
|
-
"paper-5": { req: "backgrounds, inverted text", theming: (f) => `${TINT[f]}. Worst background text stops must clear.`, collides: true },
|
|
2750
|
+
"paper-5": { req: "backgrounds, inverted text", theming: (f) => `${TINT[f]}. Worst background text stops must clear.`, collides: true, ground: (f) => `${groundLine("paper")(f)}; the ground the text stops are solved against` },
|
|
2781
2751
|
"paper-95-overlay": OVERLAY,
|
|
2782
2752
|
"chalk-8": CHALK,
|
|
2783
2753
|
"chalk-11": CHALK,
|
|
2784
2754
|
"chalk-15": CHALK,
|
|
2785
2755
|
"chalk-20": CHALK,
|
|
2786
|
-
// ("icons"
|
|
2787
|
-
//
|
|
2788
|
-
"highlighter-26": { req: "focus rings, icons, large text, translucent state layers over any ground", contrast: AA_LARGE, theming: solved, collides: true },
|
|
2789
|
-
"pencil-47": { req: "regular text, inverted backgrounds", contrast: AA_BODY, theming: solved, collides: true },
|
|
2790
|
-
"pen-58": { req: "regular text, inverted backgrounds", contrast: AA_BODY, theming: solved, collides: true },
|
|
2791
|
-
// ("
|
|
2792
|
-
//
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
//
|
|
2796
|
-
//
|
|
2797
|
-
//
|
|
2798
|
-
"stamp/fill": {
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
"stamp/
|
|
2756
|
+
// ("icons" stays although it carries "on": an "icon" query landing on the highlighter
|
|
2757
|
+
// rows is worth that noise)
|
|
2758
|
+
"highlighter-26": { req: "focus rings, icons, large text, translucent state layers over any ground", contrast: AA_LARGE, claim: claimOf("highlighter"), theming: solved, collides: true },
|
|
2759
|
+
"pencil-47": { req: "regular text, inverted backgrounds", contrast: AA_BODY, claim: claimOf("pencil"), theming: solved, collides: true },
|
|
2760
|
+
"pen-58": { req: "regular text, inverted backgrounds", contrast: AA_BODY, claim: claimOf("pen"), theming: solved, collides: true },
|
|
2761
|
+
// ("heavy-emphasis": "high" and "low" are plane words in the community plugin and
|
|
2762
|
+
// "strong" carries "on")
|
|
2763
|
+
"pen-70": { req: "heavy-emphasis text, inverted backgrounds", contrast: AA_BODY, claim: claimOf("pen"), theming: solved, collides: true },
|
|
2764
|
+
// the stamp family. "CTA" stays in these bodies on purpose: it is not a token label, so
|
|
2765
|
+
// it floods nothing, and a designer's "cta" query lands on these rows.
|
|
2766
|
+
// the usage lines are the owner's guidance, for the document rendering: the fill is
|
|
2767
|
+
// misused as a standalone color in the wild
|
|
2768
|
+
"stamp/fill": {
|
|
2769
|
+
req: "CTAs",
|
|
2770
|
+
theming: (f) => `fully re-solved per theme and family${COLOR_WORD[f]}`,
|
|
2771
|
+
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 its hover and pressed states. Always bordered with its edge"
|
|
2772
|
+
},
|
|
2773
|
+
"stamp/fill-hover": { req: "CTA pointer-over state", theming: (f) => `follows its rest fill${COLOR_WORD[f]}`, use: "the pointer-over state of the fill, with the fill; for nothing else. Always bordered with the edge" },
|
|
2774
|
+
"stamp/fill-pressed": { req: "CTA pressed state", theming: (f) => `follows its rest fill${COLOR_WORD[f]}`, use: "the pressed state of the fill, with the fill; for nothing else. Always bordered with the edge" },
|
|
2775
|
+
"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 and its states, always rendered with them and never without them (it resolves to transparent unless the fill sits close to the page); for nothing else" },
|
|
2776
|
+
// ("fill" is a label word and foreign here)
|
|
2777
|
+
"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" }
|
|
2778
|
+
};
|
|
2779
|
+
var NEUTRAL_ONLY = {
|
|
2780
|
+
// the pole is measured against the neutral's own stops only; as text, it is the on-color
|
|
2781
|
+
// of every family's emphasis fill (the band audit holds that)
|
|
2782
|
+
"paper-0": { req: "backgrounds, inverted text", theming: (f) => TINT[f], ground: () => `the neutral's highlighter-26 clears it as ${AA_LARGE}; its pencil-47, pen-58, pen-70 and pen-100 clear it as ${AA_BODY}; as text, ${AA_BODY} on every family's pencil-47` },
|
|
2783
|
+
// the literal pole carries no tint, so no theming line
|
|
2784
|
+
"pen-100": { req: "max-emphasis text", contrast: AA_BODY, claim: () => `${AA_BODY} on every paper and chalk of every family` }
|
|
2804
2785
|
};
|
|
2805
|
-
var ABS = { req: "extreme poles for CTAs, aliased global endpoints" };
|
|
2806
|
-
var OFFSET = { req: "min APCA visibility", theming: "offsets CTAs in themes where they sit close to the page" };
|
|
2807
|
-
var OFFSET_INVERSE = { req: "state layers over inverted backgrounds", theming: "the offset ladder with its pole flipped, so inverted grounds keep the same rungs" };
|
|
2808
|
-
var SHADOW = { req: "drop shadows" };
|
|
2809
|
-
var OPACITY_RUNG = { req: "translucency weight for any color", theming: "a bare number; a translucent row composes its color with one rung" };
|
|
2810
|
-
var OPACITY_STATE = { req: "translucency weight for any color; the state layer weight of the non-text stop over any ground", theming: "a bare number; a translucent row composes its color with one rung" };
|
|
2811
|
-
var PLANE = (req) => ({ req, theming: "aliased to the gray ramp" });
|
|
2812
2786
|
var LINK = (state, contrast) => ({
|
|
2813
2787
|
req: "links" + state,
|
|
2814
2788
|
contrast,
|
|
2815
|
-
|
|
2789
|
+
claim: () => `${contrast} on every paper of the neutral`,
|
|
2790
|
+
theming: "rides the theme\u2019s link color; custom seed re-solves; overridable per theme",
|
|
2791
|
+
use: "hyperlinks; not a text-style CTA, which is the text stops read as states"
|
|
2816
2792
|
});
|
|
2817
2793
|
var LINK_INVERSE = (state, contrast) => ({
|
|
2818
2794
|
req: "links over inverted backgrounds" + state,
|
|
2819
2795
|
contrast,
|
|
2820
|
-
|
|
2796
|
+
claim: () => `${contrast} on any family's pen-70`,
|
|
2797
|
+
theming: "same seed as the link, re-solved for inverted backgrounds; overridable per theme",
|
|
2798
|
+
use: "hyperlinks on a pen-70 ground; not a text-style CTA"
|
|
2821
2799
|
});
|
|
2822
2800
|
var SYSTEM = {
|
|
2823
|
-
"
|
|
2824
|
-
"
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
"
|
|
2829
|
-
|
|
2830
|
-
"
|
|
2831
|
-
"system/alpha/transparent": { req: "aliased off-states" },
|
|
2832
|
-
// the OPACITY LADDER: bare numbers a translucent color row composes with (the
|
|
2833
|
-
// scrim is the absolute black at the top rung). No conformance line of its own:
|
|
2834
|
-
// the state-layer claim rides the non-text stop these weights apply to
|
|
2835
|
-
"system/opacity/004": OPACITY_RUNG,
|
|
2836
|
-
"system/opacity/008": OPACITY_STATE,
|
|
2837
|
-
"system/opacity/012": OPACITY_STATE,
|
|
2838
|
-
"system/opacity/016": OPACITY_STATE,
|
|
2839
|
-
"system/opacity/024": OPACITY_STATE,
|
|
2840
|
-
"system/opacity/032": OPACITY_STATE,
|
|
2841
|
-
"system/opacity/048": OPACITY_RUNG,
|
|
2842
|
-
"system/opacity/064": OPACITY_RUNG,
|
|
2843
|
-
// ("fills" reworded 2026-08-18: fill became a label word and is foreign here;
|
|
2844
|
-
// "on-color" reworded 2026-08-28: the bare on fed the "on" flood)
|
|
2845
|
-
"system/alpha/ink": { req: "soft text pole for quiet CTAs" },
|
|
2846
|
-
"system/alpha/away-from-bg/06": OFFSET,
|
|
2847
|
-
"system/alpha/away-from-bg/08": OFFSET,
|
|
2848
|
-
"system/alpha/away-from-bg/16": OFFSET,
|
|
2849
|
-
// the inverse ladder: the offset rungs with the pole flipped per mode, for
|
|
2850
|
-
// chalks and edges over inverted backgrounds ("interaction" avoided in the
|
|
2851
|
-
// bodies: acti-ON would feed the "on" flood)
|
|
2852
|
-
"system/alpha/toward-bg/06": OFFSET_INVERSE,
|
|
2853
|
-
"system/alpha/toward-bg/08": OFFSET_INVERSE,
|
|
2854
|
-
"system/alpha/toward-bg/16": OFFSET_INVERSE,
|
|
2855
|
-
"system/alpha/shadow-04": SHADOW,
|
|
2856
|
-
"system/alpha/shadow-08": SHADOW,
|
|
2857
|
-
"system/alpha/shadow-12": SHADOW,
|
|
2858
|
-
// ("elevation" dropped 2026-08-28: elevati-ON fed the "on" flood; the sibling
|
|
2859
|
-
// planes never carried the word)
|
|
2860
|
-
"system/surface/dim": PLANE("recessed plane"),
|
|
2861
|
-
"system/surface/low": PLANE("resting page plane"),
|
|
2862
|
-
"system/surface/mid": PLANE("raised plane \u2014 cards, menus"),
|
|
2863
|
-
// ("overlays" reworded 2026-08-13: paper-overlay took the word as a label — the C50 law)
|
|
2864
|
-
"system/surface/high": PLANE("topmost plane \u2014 modals, dialogs"),
|
|
2865
|
-
"system/link/default/enabled": LINK("", AA_BODY),
|
|
2866
|
-
"system/link/default/hover": LINK(" pointer-over", AA_BODY),
|
|
2867
|
-
"system/link/default/pressed": LINK(" pressed", AA_BODY),
|
|
2868
|
-
"system/link/inverse/enabled": LINK_INVERSE("", AA_BODY),
|
|
2869
|
-
"system/link/inverse/hover": LINK_INVERSE(" pointer-over", AA_BODY),
|
|
2870
|
-
"system/link/inverse/pressed": LINK_INVERSE(" pressed", AA_BODY)
|
|
2801
|
+
"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" },
|
|
2802
|
+
"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" },
|
|
2803
|
+
"link/default/enabled": LINK("", AA_BODY),
|
|
2804
|
+
"link/default/hover": LINK(" pointer-over", AA_BODY),
|
|
2805
|
+
"link/default/pressed": LINK(" pressed", AA_BODY),
|
|
2806
|
+
"link/inverse/enabled": LINK_INVERSE("", AA_BODY),
|
|
2807
|
+
"link/inverse/hover": LINK_INVERSE(" pointer-over", AA_BODY),
|
|
2808
|
+
"link/inverse/pressed": LINK_INVERSE(" pressed", AA_BODY)
|
|
2871
2809
|
};
|
|
2872
2810
|
var PREFIXES = [
|
|
2873
|
-
// community spellings
|
|
2874
|
-
//
|
|
2875
|
-
// 'brand/alt/'), so most-specific must be tried before the family words
|
|
2811
|
+
// community spellings first: the family word is a prefix of the community shapes
|
|
2812
|
+
// ('brand/' would shadow 'brand/primary/' and 'brand/alt/'), so most-specific wins
|
|
2876
2813
|
["brand/primary/", FAMILY.brandPrimary],
|
|
2877
2814
|
["brand/alt/", FAMILY.brandSecondary],
|
|
2878
2815
|
...FAMILIES.map((f) => [f + "/", f])
|
|
2879
2816
|
];
|
|
2817
|
+
var ZONE_MAP = [
|
|
2818
|
+
// brand-alt before brand: canonicalize is first-match startsWith, and brand is a prefix
|
|
2819
|
+
// of brand-alt
|
|
2820
|
+
["system/abs-alt", "absolute/brand-alt"],
|
|
2821
|
+
["system/abs-primary", "absolute/brand"],
|
|
2822
|
+
["system/link/", "link/"],
|
|
2823
|
+
["color/", ""],
|
|
2824
|
+
["base/", ""],
|
|
2825
|
+
["primitive/", ""]
|
|
2826
|
+
];
|
|
2827
|
+
function canonicalize(path) {
|
|
2828
|
+
for (const [prefix, home] of ZONE_MAP)
|
|
2829
|
+
if (path.startsWith(prefix)) return home + path.slice(prefix.length);
|
|
2830
|
+
return path;
|
|
2831
|
+
}
|
|
2832
|
+
function bodyFor(path) {
|
|
2833
|
+
const canonical = canonicalize(path);
|
|
2834
|
+
if (SYSTEM[canonical]) return { body: SYSTEM[canonical], fam: FAMILY.neutral };
|
|
2835
|
+
const hit = PREFIXES.find(([p]) => canonical.startsWith(p));
|
|
2836
|
+
if (!hit) return void 0;
|
|
2837
|
+
const [prefix, fam] = hit;
|
|
2838
|
+
const leaf = canonical.slice(prefix.length);
|
|
2839
|
+
const body = fam === FAMILY.neutral && NEUTRAL_ONLY[leaf] || SCALE[leaf];
|
|
2840
|
+
return body ? { body, fam } : void 0;
|
|
2841
|
+
}
|
|
2842
|
+
function describeToken(path) {
|
|
2843
|
+
const canonical = canonicalize(path);
|
|
2844
|
+
const title = canonical.replace(/[/-]/g, " ");
|
|
2845
|
+
const hit = bodyFor(canonical);
|
|
2846
|
+
if (!hit) return title;
|
|
2847
|
+
const { body, fam } = hit;
|
|
2848
|
+
const lines = [title, `Req for: ${body.req}`];
|
|
2849
|
+
if (body.contrast) lines.push(body.contrast);
|
|
2850
|
+
if (body.theming) lines.push(`Theming: ${typeof body.theming === "function" ? body.theming(fam) : body.theming}`);
|
|
2851
|
+
if (body.collides && SIGNALS.includes(fam)) lines.push(COLLIDES);
|
|
2852
|
+
return lines.join("\n");
|
|
2853
|
+
}
|
|
2854
|
+
function describeDocument(path) {
|
|
2855
|
+
const hit = bodyFor(canonicalize(path));
|
|
2856
|
+
if (!hit) return "";
|
|
2857
|
+
const { body, fam } = hit;
|
|
2858
|
+
const lines = [`Req for: ${body.req}`];
|
|
2859
|
+
if (body.claim) lines.push(body.claim(fam));
|
|
2860
|
+
else if (body.contrast) lines.push(body.contrast);
|
|
2861
|
+
if (body.ground) lines.push(`Ground: ${body.ground(fam)}`);
|
|
2862
|
+
if (body.use) lines.push(`Use: ${body.use}`);
|
|
2863
|
+
if (body.theming) lines.push(`Theming: ${typeof body.theming === "function" ? body.theming(fam) : body.theming}`);
|
|
2864
|
+
if (body.collides && SIGNALS.includes(fam)) lines.push(COLLIDES);
|
|
2865
|
+
return lines.join("\n");
|
|
2866
|
+
}
|
|
2880
2867
|
|
|
2881
2868
|
// src/engine/signals.ts
|
|
2882
2869
|
var SIGNALS2 = [
|
|
@@ -3195,7 +3182,7 @@ var OUTLINE_PRESSED_ALPHA = 0.18;
|
|
|
3195
3182
|
var SOFT_ON_CTA_ALPHA = { light: 0.75, dark: 0.8 };
|
|
3196
3183
|
function softOnCtaPasses(s, mode) {
|
|
3197
3184
|
const white = mode === "light" ? s.onFillTextIsWhite : s.onFillTextIsWhiteDark;
|
|
3198
|
-
const
|
|
3185
|
+
const pole2 = white ? 1 : 0;
|
|
3199
3186
|
const a = SOFT_ON_CTA_ALPHA[mode];
|
|
3200
3187
|
const states = mode === "light" ? [s.cta, s.ctaHover, s.ctaPressed] : [s.ctaDark, s.ctaHoverDark, s.ctaPressedDark];
|
|
3201
3188
|
const lin = (v2) => v2 <= 0.04045 ? v2 / 12.92 : ((v2 + 0.055) / 1.055) ** 2.4;
|
|
@@ -3205,7 +3192,7 @@ function softOnCtaPasses(s, mode) {
|
|
|
3205
3192
|
const e = srgbEmitChannels(st);
|
|
3206
3193
|
const fr = q2(e.r), fg = q2(e.g), fb = q2(e.b);
|
|
3207
3194
|
const fillY = relY(fr, fg, fb);
|
|
3208
|
-
const textY = relY(
|
|
3195
|
+
const textY = relY(pole2 * a + fr * (1 - a), pole2 * a + fg * (1 - a), pole2 * a + fb * (1 - a));
|
|
3209
3196
|
if (contrastRatio(textY, fillY) < 4.5) return false;
|
|
3210
3197
|
}
|
|
3211
3198
|
return true;
|
|
@@ -3451,7 +3438,7 @@ var p3Differs = (s) => s.C > clampChromaToGamut(s.L, s.C, s.H, "srgb") + 1e-4;
|
|
|
3451
3438
|
var P3_SUPPORTS = "@supports (color: color(display-p3 1 1 1))";
|
|
3452
3439
|
var P3_MEDIA = "@media (color-gamut: p3)";
|
|
3453
3440
|
function stopsToVars(stops, prefix) {
|
|
3454
|
-
return [...stops].sort((a, b) => tokenOrder(stopTokenName(a.stop)) - tokenOrder(stopTokenName(b.stop))).map((s) => `
|
|
3441
|
+
return [...stops].sort((a, b) => tokenOrder(stopTokenName(a.stop)) - tokenOrder(stopTokenName(b.stop))).map((s) => ` ${cssVarName(familyPath(prefix, stopTokenName(s.stop)))}: ${stopHex(s)};`).join("\n");
|
|
3455
3442
|
}
|
|
3456
3443
|
var onColor = (white) => white ? "#ffffff" : "#000000";
|
|
3457
3444
|
var CTA_BORDER_LC_FLOOR = 15;
|
|
@@ -3462,34 +3449,7 @@ function pageStopFor(neutral, mode) {
|
|
|
3462
3449
|
}
|
|
3463
3450
|
var OFFSET_ALPHAS = { 6: 0.06, 8: 0.08, 16: 0.16 };
|
|
3464
3451
|
var ctaBorderRung = (prefix) => prefix === CSS_NEUTRAL ? 8 : prefix === CSS_SECONDARY ? 6 : 16;
|
|
3465
|
-
var offsetLeafName = (rung) => String(rung).padStart(2, "0");
|
|
3466
|
-
var offsetVarName = (rung) => `--alpha-away-from-bg-${offsetLeafName(rung)}`;
|
|
3467
|
-
var OPACITY_RUNGS = { 4: 0.04, 8: 0.08, 12: 0.12, 16: 0.16, 24: 0.24, 32: 0.32, 48: 0.48, 64: 0.64 };
|
|
3468
|
-
var INTERACTION_RUNGS = [8, 12, 16, 24, 32];
|
|
3469
|
-
var opacityLeafName = (rung) => String(rung).padStart(3, "0");
|
|
3470
|
-
var opacityVarName = (rung) => `--opacity-${opacityLeafName(rung)}`;
|
|
3471
|
-
var opacityTokenPath = (rung) => SYSTEM_LEAF.OPACITY[opacityLeafName(rung)];
|
|
3472
|
-
var SHADOW_ALPHAS = {
|
|
3473
|
-
4: { light: OPACITY_RUNGS[4], dark: OPACITY_RUNGS[32] },
|
|
3474
|
-
8: { light: OPACITY_RUNGS[8], dark: OPACITY_RUNGS[48] },
|
|
3475
|
-
12: { light: OPACITY_RUNGS[12], dark: OPACITY_RUNGS[64] }
|
|
3476
|
-
};
|
|
3477
|
-
var SCRIM_ALPHA = OPACITY_RUNGS[64];
|
|
3478
|
-
var DISABLED_OPACITY = 0.38;
|
|
3479
|
-
var TRANSPARENT_VAR = "--alpha-transparent";
|
|
3480
3452
|
var offsetRgba = (rung, mode) => mode === "light" ? `rgba(0, 0, 0, ${OFFSET_ALPHAS[rung]})` : `rgba(255, 255, 255, ${OFFSET_ALPHAS[rung]})`;
|
|
3481
|
-
var alphaRootVars = (mode) => [
|
|
3482
|
-
` ${TRANSPARENT_VAR}: transparent;`,
|
|
3483
|
-
// the opacity ladder, mode-invariant like transparent; repeated in the dark block to
|
|
3484
|
-
// keep the set together
|
|
3485
|
-
...Object.keys(OPACITY_RUNGS).map(Number).map((r) => ` ${opacityVarName(r)}: ${OPACITY_RUNGS[r]};`),
|
|
3486
|
-
...Object.keys(OFFSET_ALPHAS).map(Number).sort((a, b) => a - b).map((r) => ` ${offsetVarName(r)}: ${offsetRgba(r, mode)};`),
|
|
3487
|
-
// the toward-bg ladder (the 2026-08-29 inverse ladder, renamed 2026-08-31): the
|
|
3488
|
-
// same rungs, pole flipped per mode — state layers for INVERTED grounds (never
|
|
3489
|
-
// called a "chalk" — that word is the tinted band's). One spelling with the Figma
|
|
3490
|
-
// row: --alpha-toward-bg-06 ↔ system/alpha/toward-bg/06.
|
|
3491
|
-
...Object.keys(OFFSET_ALPHAS).map(Number).sort((a, b) => a - b).map((r) => ` --alpha-toward-bg-${offsetLeafName(r)}: ${offsetRgba(r, mode === "light" ? "dark" : "light")};`)
|
|
3492
|
-
];
|
|
3493
3453
|
function ctaPageLc(s, mode, page) {
|
|
3494
3454
|
const cta = mode === "light" ? s.cta : s.ctaDark;
|
|
3495
3455
|
return Math.abs(apcaLc(apcaY(cta.r, cta.g, cta.b), apcaY(page.r, page.g, page.b)));
|
|
@@ -3504,23 +3464,20 @@ function brandKindBody(prefix, s, mode, page, on = prefix === CSS_NEUTRAL ? "sof
|
|
|
3504
3464
|
const onCta = mode === "light" ? s.onFillTextIsWhite : s.onFillTextIsWhiteDark;
|
|
3505
3465
|
const border = ctaNeedsBorder(s, mode, page);
|
|
3506
3466
|
const scaleBlock = [
|
|
3507
|
-
...stops.map((x2) => ({ name: stopTokenName(x2.stop), line: `
|
|
3467
|
+
...stops.map((x2) => ({ name: stopTokenName(x2.stop), line: ` ${cssVarName(familyPath(prefix, stopTokenName(x2.stop)))}: ${stopHex(x2)};` }))
|
|
3508
3468
|
].sort((a, b) => tokenOrder(a.name) - tokenOrder(b.name)).map((v2) => v2.line).join("\n");
|
|
3509
3469
|
return [
|
|
3510
3470
|
scaleBlock,
|
|
3511
|
-
`
|
|
3512
|
-
`
|
|
3513
|
-
`
|
|
3514
|
-
`
|
|
3515
|
-
// the
|
|
3516
|
-
//
|
|
3517
|
-
//
|
|
3518
|
-
//
|
|
3519
|
-
//
|
|
3520
|
-
|
|
3521
|
-
// the caller's per-mode verdict. Loud fills (brand, signals, the cta escape) keep the
|
|
3522
|
-
// solid pole.
|
|
3523
|
-
on === "soft" ? ` --${prefix}-stamp-on: rgba(${onCta ? "255, 255, 255" : "0, 0, 0"}, ${SOFT_ON_CTA_ALPHA[mode]});` : ` --${prefix}-stamp-on: ${onColor(onCta)};`
|
|
3471
|
+
` ${cssVarName(familyPath(prefix, STAMP_FILL))}: ${stopHex(f.cta)};`,
|
|
3472
|
+
` ${cssVarName(familyPath(prefix, STAMP_FILL_HOVER))}: ${stopHex(f.ctaHover)};`,
|
|
3473
|
+
` ${cssVarName(familyPath(prefix, STAMP_FILL_PRESSED))}: ${stopHex(f.ctaPressed)};`,
|
|
3474
|
+
` ${cssVarName(familyPath(prefix, STAMP_EDGE))}: ${border ? offsetRgba(ctaBorderRung(prefix), mode) : "transparent"};`,
|
|
3475
|
+
// the soft on-text: a quiet fill's button text is the pole at alpha, composited over
|
|
3476
|
+
// whatever state the fill is in so hover and pressed carry their own legibility (C47).
|
|
3477
|
+
// The neutral's is unconditional (the parameter default); the secondary's is the
|
|
3478
|
+
// caller's per-mode verdict. Loud fills (the brand, the signals, the cta escape) keep
|
|
3479
|
+
// the solid pole.
|
|
3480
|
+
on === "soft" ? ` ${cssVarName(familyPath(prefix, STAMP_ON))}: rgba(${onCta ? "255, 255, 255" : "0, 0, 0"}, ${SOFT_ON_CTA_ALPHA[mode]});` : ` ${cssVarName(familyPath(prefix, STAMP_ON))}: ${onColor(onCta)};`
|
|
3524
3481
|
];
|
|
3525
3482
|
}
|
|
3526
3483
|
function ctaFamilyOf(s, mode) {
|
|
@@ -3530,9 +3487,9 @@ function brandKindP3Body(prefix, s, mode) {
|
|
|
3530
3487
|
const stops = mode === "light" ? s.light : s.dark;
|
|
3531
3488
|
const f = ctaFamilyOf(s, mode);
|
|
3532
3489
|
const out = [];
|
|
3533
|
-
for (const st of stops) if (p3Differs(st)) out.push(`
|
|
3534
|
-
for (const [name, st] of [[
|
|
3535
|
-
if (p3Differs(st)) out.push(`
|
|
3490
|
+
for (const st of stops) if (p3Differs(st)) out.push(` ${cssVarName(familyPath(prefix, stopTokenName(st.stop)))}: ${p3Value(st)};`);
|
|
3491
|
+
for (const [name, st] of [[STAMP_FILL, f.cta], [STAMP_FILL_HOVER, f.ctaHover], [STAMP_FILL_PRESSED, f.ctaPressed]])
|
|
3492
|
+
if (p3Differs(st)) out.push(` ${cssVarName(familyPath(prefix, name))}: ${p3Value(st)};`);
|
|
3536
3493
|
return out;
|
|
3537
3494
|
}
|
|
3538
3495
|
function neutralCss(selector, brandH, level = "default", contrastProfile, ctaBorder = true) {
|
|
@@ -3543,16 +3500,14 @@ function neutralCss(selector, brandH, level = "default", contrastProfile, ctaBor
|
|
|
3543
3500
|
const p3Dark = brandKindP3Body(CSS_NEUTRAL, s, "dark");
|
|
3544
3501
|
return [
|
|
3545
3502
|
`${selector} {`,
|
|
3546
|
-
`
|
|
3547
|
-
`
|
|
3548
|
-
// the neutral
|
|
3549
|
-
// the neutral's overlays never read the visibility bar (the exempt family), so
|
|
3550
|
-
// the brandless chrome context passes 0
|
|
3503
|
+
` ${cssVarName(familyPath(CSS_NEUTRAL, PAPER_0))}: ${p02(s.paper0, "#ffffff")};`,
|
|
3504
|
+
` ${cssVarName(familyPath(CSS_NEUTRAL, PEN_100))}: ${p02(s.pen100, "#000000")};`,
|
|
3505
|
+
// the neutral is the page, so it is judged against its own paper stop
|
|
3551
3506
|
...brandKindBody(CSS_NEUTRAL, s, "light", nPage("light")),
|
|
3552
3507
|
`}`,
|
|
3553
3508
|
`${selector}[data-theme="dark"] {`,
|
|
3554
|
-
`
|
|
3555
|
-
`
|
|
3509
|
+
` ${cssVarName(familyPath(CSS_NEUTRAL, PAPER_0))}: ${p02(s.paper0Dark, "#000000")};`,
|
|
3510
|
+
` ${cssVarName(familyPath(CSS_NEUTRAL, PEN_100))}: ${p02(s.pen100Dark, "#ffffff")};`,
|
|
3556
3511
|
...brandKindBody(CSS_NEUTRAL, s, "dark", nPage("dark")),
|
|
3557
3512
|
`}`,
|
|
3558
3513
|
...p3Light.length || p3Dark.length ? [
|
|
@@ -3584,16 +3539,9 @@ function signalsCss(contrastProfile) {
|
|
|
3584
3539
|
return [
|
|
3585
3540
|
`/* Signal scales \u2014 engine-generated from canonical hexes, shared across brands */`,
|
|
3586
3541
|
`:root {`,
|
|
3587
|
-
// the system alpha variables every family's cta-border aliases (owner 2026-07-29) — this is
|
|
3588
|
-
// the engine's one global :root, the CSS counterpart of the Figma side's system/alpha/* rows.
|
|
3589
|
-
// Emitted in BOTH blocks because the offset rungs are scheme-DIVERGENT (black in light,
|
|
3590
|
-
// white in dark); --alpha-transparent and the opacity ladder (mode-invariant) repeat
|
|
3591
|
-
// harmlessly and keep the set together.
|
|
3592
|
-
...alphaRootVars("light"),
|
|
3593
3542
|
...lightBlocks,
|
|
3594
3543
|
`}`,
|
|
3595
3544
|
`${SIGNALS_DARK_SELECTOR} {`,
|
|
3596
|
-
...alphaRootVars("dark"),
|
|
3597
3545
|
...darkBlocks,
|
|
3598
3546
|
`}`,
|
|
3599
3547
|
...p3LightBlocks.length || p3DarkBlocks.length ? [
|
|
@@ -3627,69 +3575,72 @@ function brandCss(slug, displayName, r, secondary, noteSuffix = "", neutralLevel
|
|
|
3627
3575
|
const page = ctaBorder ? { light: pageStopFor(nScale, "light"), dark: pageStopFor(nScale, "dark") } : { light: void 0, dark: void 0 };
|
|
3628
3576
|
const mirrorBody = (prefix, mode) => {
|
|
3629
3577
|
const stops = mode === "light" ? scale.light : scale.dark;
|
|
3630
|
-
const alias = (name) => `
|
|
3578
|
+
const alias = (name) => ` ${cssVarName(familyPath(prefix, name))}: var(${cssVarName(familyPath(CSS_BRAND, name))});`;
|
|
3631
3579
|
return [
|
|
3632
3580
|
...stops.map((x2) => alias(stopTokenName(x2.stop))),
|
|
3633
|
-
alias(
|
|
3634
|
-
alias(
|
|
3635
|
-
alias(
|
|
3636
|
-
alias(
|
|
3637
|
-
alias(
|
|
3581
|
+
alias(STAMP_FILL),
|
|
3582
|
+
alias(STAMP_FILL_HOVER),
|
|
3583
|
+
alias(STAMP_FILL_PRESSED),
|
|
3584
|
+
alias(STAMP_EDGE),
|
|
3585
|
+
alias(STAMP_ON)
|
|
3638
3586
|
];
|
|
3639
3587
|
};
|
|
3640
3588
|
const secondaryOn = (mode) => secondary && secondaryStyle !== "outline" && softOnCtaPasses(secondary, mode) ? "soft" : "solid";
|
|
3641
3589
|
const secondaryLight = secondary ? brandKindBody(CSS_SECONDARY, secondary, "light", page.light, secondaryOn("light")) : mirrorBody(CSS_SECONDARY, "light");
|
|
3642
3590
|
const secondaryDark = secondary ? brandKindBody(CSS_SECONDARY, secondary, "dark", page.dark, secondaryOn("dark")) : mirrorBody(CSS_SECONDARY, "dark");
|
|
3643
|
-
const brandIdentity = `
|
|
3644
|
-
const secondaryIdentity = secondary ? `
|
|
3591
|
+
const brandIdentity = ` ${cssVarName(absolutePath(CSS_BRAND))}: ${scale.identityHex};`;
|
|
3592
|
+
const secondaryIdentity = secondary ? ` ${cssVarName(absolutePath(CSS_SECONDARY))}: ${secondary.identityHex};` : ` ${cssVarName(absolutePath(CSS_SECONDARY))}: var(${cssVarName(absolutePath(CSS_BRAND))});`;
|
|
3645
3593
|
const p0hex = (s, fallback) => s ? stopHex(s) : fallback;
|
|
3646
|
-
const lightAnchors = [`
|
|
3647
|
-
const darkAnchors = [`
|
|
3594
|
+
const lightAnchors = [` ${cssVarName(familyPath(CSS_NEUTRAL, PAPER_0))}: ${p0hex(nScale.paper0, "#ffffff")};`, ` ${cssVarName(familyPath(CSS_NEUTRAL, PEN_100))}: ${p0hex(nScale.pen100, "#000000")};`];
|
|
3595
|
+
const darkAnchors = [` ${cssVarName(familyPath(CSS_NEUTRAL, PAPER_0))}: ${p0hex(nScale.paper0Dark, "#000000")};`, ` ${cssVarName(familyPath(CSS_NEUTRAL, PEN_100))}: ${p0hex(nScale.pen100Dark, "#ffffff")};`];
|
|
3648
3596
|
const linkTrio = linkHex ? resolveLinkTrio(linkHex, contrastProfile) : null;
|
|
3649
|
-
const
|
|
3650
|
-
|
|
3651
|
-
`
|
|
3652
|
-
`
|
|
3597
|
+
const linkVar = (state) => cssVarName(linkPath("default", state));
|
|
3598
|
+
const link = (mode) => linkTrio ? mode === "light" ? [` ${linkVar("enabled")}: ${stopHex(linkTrio.link)};`, ` ${linkVar("hover")}: ${stopHex(linkTrio.linkHover)};`, ` ${linkVar("pressed")}: ${stopHex(linkTrio.linkPressed)};`] : [` ${linkVar("enabled")}: ${stopHex(linkTrio.linkDark)};`, ` ${linkVar("hover")}: ${stopHex(linkTrio.linkHoverDark)};`, ` ${linkVar("pressed")}: ${stopHex(linkTrio.linkPressedDark)};`] : [
|
|
3599
|
+
` ${linkVar("enabled")}: var(${cssVarName(familyPath(CSS_BRAND, stopTokenName(9)))});`,
|
|
3600
|
+
` ${linkVar("hover")}: var(${cssVarName(familyPath(CSS_BRAND, stopTokenName(10)))});`,
|
|
3601
|
+
` ${linkVar("pressed")}: var(${cssVarName(familyPath(CSS_BRAND, stopTokenName(11)))});`
|
|
3653
3602
|
];
|
|
3654
3603
|
const linkP3 = (mode) => {
|
|
3655
3604
|
if (!linkTrio) return [];
|
|
3656
|
-
const trio = mode === "light" ? [["
|
|
3657
|
-
return trio.filter(([, s]) => p3Differs(s)).map(([n, s]) => `
|
|
3605
|
+
const trio = mode === "light" ? [["enabled", linkTrio.link], ["hover", linkTrio.linkHover], ["pressed", linkTrio.linkPressed]] : [["enabled", linkTrio.linkDark], ["hover", linkTrio.linkHoverDark], ["pressed", linkTrio.linkPressedDark]];
|
|
3606
|
+
return trio.filter(([, s]) => p3Differs(s)).map(([n, s]) => ` ${linkVar(n)}: ${p3Value(s)};`);
|
|
3658
3607
|
};
|
|
3659
3608
|
const inverseSeed = linkHex ?? scale.identityHex ?? stopHex(scale.light.find((x2) => x2.stop === 9));
|
|
3660
3609
|
const linkInverseTrio = resolveLinkInverseTrio(inverseSeed, contrastProfile);
|
|
3661
|
-
const
|
|
3610
|
+
const inverseVar = (state) => cssVarName(linkPath("inverse", state));
|
|
3611
|
+
const linkInverse = (mode) => mode === "light" ? [` ${inverseVar("enabled")}: ${stopHex(linkInverseTrio.link)};`, ` ${inverseVar("hover")}: ${stopHex(linkInverseTrio.linkHover)};`, ` ${inverseVar("pressed")}: ${stopHex(linkInverseTrio.linkPressed)};`] : [` ${inverseVar("enabled")}: ${stopHex(linkInverseTrio.linkDark)};`, ` ${inverseVar("hover")}: ${stopHex(linkInverseTrio.linkHoverDark)};`, ` ${inverseVar("pressed")}: ${stopHex(linkInverseTrio.linkPressedDark)};`];
|
|
3662
3612
|
const linkInverseP3 = (mode) => {
|
|
3663
|
-
const trio = mode === "light" ? [["
|
|
3664
|
-
return trio.filter(([, s]) => p3Differs(s)).map(([n, s]) => `
|
|
3613
|
+
const trio = mode === "light" ? [["enabled", linkInverseTrio.link], ["hover", linkInverseTrio.linkHover], ["pressed", linkInverseTrio.linkPressed]] : [["enabled", linkInverseTrio.linkDark], ["hover", linkInverseTrio.linkHoverDark], ["pressed", linkInverseTrio.linkPressedDark]];
|
|
3614
|
+
return trio.filter(([, s]) => p3Differs(s)).map(([n, s]) => ` ${inverseVar(n)}: ${p3Value(s)};`);
|
|
3665
3615
|
};
|
|
3666
3616
|
const escape = (mode) => {
|
|
3667
3617
|
if (!ctaEscape) return [];
|
|
3668
3618
|
const esc = escapeCtaFamily(nScale, mode, contrastProfile);
|
|
3669
3619
|
return [
|
|
3670
|
-
`
|
|
3671
|
-
`
|
|
3672
|
-
`
|
|
3673
|
-
`
|
|
3620
|
+
` ${cssVarName(familyPath(CSS_BRAND, STAMP_FILL))}: ${stopHex(esc.cta)};`,
|
|
3621
|
+
` ${cssVarName(familyPath(CSS_BRAND, STAMP_FILL_HOVER))}: ${stopHex(esc.ctaHover)};`,
|
|
3622
|
+
` ${cssVarName(familyPath(CSS_BRAND, STAMP_FILL_PRESSED))}: ${stopHex(esc.ctaPressed)};`,
|
|
3623
|
+
` ${cssVarName(familyPath(CSS_BRAND, STAMP_ON))}: ${onColor(esc.onFillIsWhite)};`
|
|
3674
3624
|
];
|
|
3675
3625
|
};
|
|
3676
3626
|
const outline = (mode) => {
|
|
3677
3627
|
if (secondaryStyle !== "outline" || !secondary) return [];
|
|
3678
3628
|
const s8 = (mode === "light" ? secondary.light : secondary.dark).find((s) => s.stop === 8);
|
|
3679
|
-
const c = (
|
|
3629
|
+
const c = (v3) => Math.round(Math.min(1, Math.max(0, v3)) * 255);
|
|
3680
3630
|
const s8e = s8 ? srgbEmitChannels(s8) : null;
|
|
3631
|
+
const v2 = (leaf) => cssVarName(familyPath(CSS_SECONDARY, leaf));
|
|
3681
3632
|
return [
|
|
3682
|
-
`
|
|
3633
|
+
` ${v2(STAMP_FILL)}: transparent;`,
|
|
3683
3634
|
...s8e ? [
|
|
3684
|
-
`
|
|
3685
|
-
`
|
|
3635
|
+
` ${v2(STAMP_FILL_HOVER)}: rgba(${c(s8e.r)}, ${c(s8e.g)}, ${c(s8e.b)}, ${OUTLINE_HOVER_ALPHA});`,
|
|
3636
|
+
` ${v2(STAMP_FILL_PRESSED)}: rgba(${c(s8e.r)}, ${c(s8e.g)}, ${c(s8e.b)}, ${OUTLINE_PRESSED_ALPHA});`
|
|
3686
3637
|
] : [],
|
|
3687
|
-
`
|
|
3688
|
-
`
|
|
3638
|
+
` ${v2(STAMP_EDGE)}: var(${v2(stopTokenName(8))});`,
|
|
3639
|
+
` ${v2(STAMP_ON)}: var(${v2(stopTokenName(9))});`
|
|
3689
3640
|
];
|
|
3690
3641
|
};
|
|
3691
|
-
const dropOutlineCta = (lines) => secondaryStyle === "outline" ? lines.filter((l) => !
|
|
3692
|
-
const dropEscapeCta = (lines) => ctaEscape ? lines.filter((l) => !
|
|
3642
|
+
const dropOutlineCta = (lines) => secondaryStyle === "outline" ? lines.filter((l) => ![STAMP_FILL, STAMP_FILL_HOVER, STAMP_FILL_PRESSED].some((leaf) => l.startsWith(` ${cssVarName(familyPath(CSS_SECONDARY, leaf))}:`))) : lines;
|
|
3643
|
+
const dropEscapeCta = (lines) => ctaEscape ? lines.filter((l) => ![STAMP_FILL, STAMP_FILL_HOVER, STAMP_FILL_PRESSED].some((leaf) => l.startsWith(` ${cssVarName(familyPath(CSS_BRAND, leaf))}:`))) : lines;
|
|
3693
3644
|
const p3Light = [
|
|
3694
3645
|
...dropEscapeCta(brandKindP3Body(CSS_BRAND, scale, "light")),
|
|
3695
3646
|
...secondary ? dropOutlineCta(brandKindP3Body(CSS_SECONDARY, secondary, "light")) : [],
|
|
@@ -3797,17 +3748,6 @@ function resolveReferences(own, shared) {
|
|
|
3797
3748
|
for (const name of /* @__PURE__ */ new Set([...own.keys(), ...shared.keys()])) out[name] = resolve(lookup(name), 0);
|
|
3798
3749
|
return out;
|
|
3799
3750
|
}
|
|
3800
|
-
function systemCss() {
|
|
3801
|
-
const planeRef = (stop) => stop === PAPER_0 ? `var(--${PAPER_0})` : `var(--${CSS_FAMILY.neutral}-${stop})`;
|
|
3802
|
-
const pad = (r) => String(r).padStart(2, "0");
|
|
3803
|
-
const lines = (mode) => [
|
|
3804
|
-
...Object.entries(SURFACE_PLANE_LAW).map(([leaf, stops]) => ` --surface-${leaf.split("/").pop()}: ${planeRef(stops[mode])};`),
|
|
3805
|
-
...Object.keys(SHADOW_ALPHAS).map(Number).map((r) => ` --shadow-${pad(r)}: rgba(0, 0, 0, ${SHADOW_ALPHAS[r][mode]});`),
|
|
3806
|
-
` --scrim: rgba(0, 0, 0, ${SCRIM_ALPHA});`,
|
|
3807
|
-
` --disabled-opacity: ${DISABLED_OPACITY};`
|
|
3808
|
-
];
|
|
3809
|
-
return [":root {", ...lines("light"), "}", `:root${DARK_MARK}, ${DARK_MARK} {`, ...lines("dark"), "}"].join("\n");
|
|
3810
|
-
}
|
|
3811
3751
|
function tokensFromEmission(slug, css) {
|
|
3812
3752
|
const { light, dark, order } = readEmission(css);
|
|
3813
3753
|
const resolvedLight = resolveReferences(light, /* @__PURE__ */ new Map());
|
|
@@ -3819,7 +3759,6 @@ function tokensFromEmission(slug, css) {
|
|
|
3819
3759
|
function themeTokens(input) {
|
|
3820
3760
|
const css = [
|
|
3821
3761
|
signalsCss(input.contrastProfile),
|
|
3822
|
-
systemCss(),
|
|
3823
3762
|
brandCss(
|
|
3824
3763
|
input.slug,
|
|
3825
3764
|
input.displayName ?? input.slug,
|
|
@@ -3838,168 +3777,35 @@ function themeTokens(input) {
|
|
|
3838
3777
|
return tokensFromEmission(input.slug, css);
|
|
3839
3778
|
}
|
|
3840
3779
|
|
|
3841
|
-
// src/engine/interaction.ts
|
|
3842
|
-
var INTERACTION_POLE_FAMILY = { strong: "neutral-strong", inverse: "neutral-inverse" };
|
|
3843
|
-
var INTERACTION_FAMILIES = [
|
|
3844
|
-
CSS_FAMILY.neutral,
|
|
3845
|
-
CSS_FAMILY.brandPrimary,
|
|
3846
|
-
CSS_FAMILY.brandSecondary,
|
|
3847
|
-
...SIGNALS2.map((s) => s.emitName),
|
|
3848
|
-
INTERACTION_POLE_FAMILY.strong,
|
|
3849
|
-
INTERACTION_POLE_FAMILY.inverse
|
|
3850
|
-
];
|
|
3851
|
-
var INTERACTION_STATES = ["enabled", "hover", "pressed", "selected"];
|
|
3852
|
-
var INTERACTION_LADDER = {
|
|
3853
|
-
subtle: { enabled: 12, hover: 16, pressed: 24, selected: 32 },
|
|
3854
|
-
hint: { enabled: null, hover: 8, pressed: 12, selected: 16 }
|
|
3855
|
-
};
|
|
3856
|
-
var INTERACTION_ROWS = [
|
|
3857
|
-
"fg",
|
|
3858
|
-
"fg-strong",
|
|
3859
|
-
"fg-on-hint",
|
|
3860
|
-
"solid-bg-enabled",
|
|
3861
|
-
"solid-bg-hover",
|
|
3862
|
-
"solid-bg-pressed",
|
|
3863
|
-
"solid-border",
|
|
3864
|
-
"solid-fg",
|
|
3865
|
-
"subtle-bg-enabled",
|
|
3866
|
-
"subtle-bg-hover",
|
|
3867
|
-
"subtle-bg-pressed",
|
|
3868
|
-
"subtle-bg-selected",
|
|
3869
|
-
"hint-bg-enabled",
|
|
3870
|
-
"hint-bg-hover",
|
|
3871
|
-
"hint-bg-pressed",
|
|
3872
|
-
"hint-bg-selected"
|
|
3873
|
-
];
|
|
3874
|
-
var interactionVarName = (family, row) => `--${family}-${row}`;
|
|
3875
|
-
var isPole = (family) => family === INTERACTION_POLE_FAMILY.strong || family === INTERACTION_POLE_FAMILY.inverse;
|
|
3876
|
-
var hexChannels = (hex) => {
|
|
3877
|
-
const m = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(hex.trim());
|
|
3878
|
-
return m ? [parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16)] : null;
|
|
3879
|
-
};
|
|
3880
|
-
function interactionTintName(family) {
|
|
3881
|
-
if (family === INTERACTION_POLE_FAMILY.strong) return PEN_100;
|
|
3882
|
-
if (family === INTERACTION_POLE_FAMILY.inverse) return PAPER_0;
|
|
3883
|
-
return `${family}-${stopTokenName(8)}`;
|
|
3884
|
-
}
|
|
3885
|
-
function interactionRows(family, mode, tokens) {
|
|
3886
|
-
const neutral = CSS_FAMILY.neutral;
|
|
3887
|
-
const v2 = (name) => `var(--${name})`;
|
|
3888
|
-
const pen = (stop) => `${family}-${stopTokenName(stop)}`;
|
|
3889
|
-
const tintHex = tokens[mode][interactionTintName(family)];
|
|
3890
|
-
const ch = tintHex ? hexChannels(tintHex) : null;
|
|
3891
|
-
if (!ch) throw new Error(`interactionRows: no sRGB hex for ${interactionTintName(family)} in ${mode}`);
|
|
3892
|
-
const at = (rung) => rung === null ? v2(TRANSPARENT_VAR.slice(2)) : `rgba(${ch[0]}, ${ch[1]}, ${ch[2]}, ${OPACITY_RUNGS[rung]})`;
|
|
3893
|
-
const text = isPole(family) ? [["fg", v2(interactionTintName(family))], ["fg-strong", v2(interactionTintName(family))], ["fg-on-hint", v2(interactionTintName(family))]] : [["fg", v2(pen(10))], ["fg-strong", v2(pen(11))], ["fg-on-hint", v2(pen(9))]];
|
|
3894
|
-
const solid = family === INTERACTION_POLE_FAMILY.strong ? [
|
|
3895
|
-
["solid-bg-enabled", v2(PEN_100)],
|
|
3896
|
-
["solid-bg-hover", v2(`${neutral}-${stopTokenName(11)}`)],
|
|
3897
|
-
["solid-bg-pressed", v2(`${neutral}-${stopTokenName(10)}`)],
|
|
3898
|
-
["solid-border", v2(TRANSPARENT_VAR.slice(2))],
|
|
3899
|
-
["solid-fg", v2(PAPER_0)]
|
|
3900
|
-
] : family === INTERACTION_POLE_FAMILY.inverse ? [
|
|
3901
|
-
["solid-bg-enabled", v2(PAPER_0)],
|
|
3902
|
-
["solid-bg-hover", v2(`${neutral}-${stopTokenName(2)}`)],
|
|
3903
|
-
["solid-bg-pressed", v2(`${neutral}-${stopTokenName(3)}`)],
|
|
3904
|
-
["solid-border", v2(TRANSPARENT_VAR.slice(2))],
|
|
3905
|
-
["solid-fg", v2(PEN_100)]
|
|
3906
|
-
] : [
|
|
3907
|
-
["solid-bg-enabled", v2(`${family}-${STAMP_FILL}`)],
|
|
3908
|
-
["solid-bg-hover", v2(`${family}-${STAMP_FILL_HOVER}`)],
|
|
3909
|
-
["solid-bg-pressed", v2(`${family}-${STAMP_FILL_PRESSED}`)],
|
|
3910
|
-
["solid-border", v2(`${family}-${STAMP_EDGE}`)],
|
|
3911
|
-
["solid-fg", v2(`${family}-${STAMP_ON}`)]
|
|
3912
|
-
];
|
|
3913
|
-
const ladder = (tier) => INTERACTION_STATES.map((state) => [`${tier}-bg-${state}`, at(INTERACTION_LADDER[tier][state])]);
|
|
3914
|
-
return [...text, ...solid, ...ladder("subtle"), ...ladder("hint")];
|
|
3915
|
-
}
|
|
3916
|
-
var rowVariesByMode = (row) => /^(subtle|hint)-bg-/.test(row) && row !== "hint-bg-enabled";
|
|
3917
|
-
function interactionCss(slug, tokens) {
|
|
3918
|
-
const scope = `[data-brand="${slug}"]`;
|
|
3919
|
-
const light = [];
|
|
3920
|
-
const dark = [];
|
|
3921
|
-
for (const family of INTERACTION_FAMILIES) {
|
|
3922
|
-
for (const [row, value] of interactionRows(family, "light", tokens)) light.push(` ${interactionVarName(family, row)}: ${value};`);
|
|
3923
|
-
for (const [row, value] of interactionRows(family, "dark", tokens)) if (rowVariesByMode(row)) dark.push(` ${interactionVarName(family, row)}: ${value};`);
|
|
3924
|
-
}
|
|
3925
|
-
const scoped = INTERACTION_FAMILIES.flatMap((family) => [
|
|
3926
|
-
`${scope} [data-family="${family}"], ${scope}[data-family="${family}"] {`,
|
|
3927
|
-
...INTERACTION_ROWS.map((row) => ` --${row}: var(${interactionVarName(family, row)});`),
|
|
3928
|
-
`}`
|
|
3929
|
-
]);
|
|
3930
|
-
return [
|
|
3931
|
-
`/* Interaction register: solid, subtle and hint tiers per family, the translucent rows at the engine's opacity rungs */`,
|
|
3932
|
-
`${scope} {`,
|
|
3933
|
-
...light,
|
|
3934
|
-
`}`,
|
|
3935
|
-
`${scope}[data-theme="dark"] {`,
|
|
3936
|
-
...dark,
|
|
3937
|
-
`}`,
|
|
3938
|
-
...scoped
|
|
3939
|
-
].join("\n");
|
|
3940
|
-
}
|
|
3941
|
-
function interactionTokens(tokens) {
|
|
3942
|
-
const add = (mode) => {
|
|
3943
|
-
const m = /* @__PURE__ */ new Map();
|
|
3944
|
-
for (const family of INTERACTION_FAMILIES)
|
|
3945
|
-
for (const [row, value] of interactionRows(family, mode, tokens)) m.set(interactionVarName(family, row).slice(2), value);
|
|
3946
|
-
return m;
|
|
3947
|
-
};
|
|
3948
|
-
const rawLight = add("light");
|
|
3949
|
-
const rawDark = add("dark");
|
|
3950
|
-
const baseLight = new Map(Object.entries(tokens.light));
|
|
3951
|
-
const baseDark = new Map(Object.entries(tokens.dark));
|
|
3952
|
-
const light = resolveReferences(rawLight, baseLight);
|
|
3953
|
-
const dark = resolveReferences(rawDark, baseDark);
|
|
3954
|
-
const names = [...tokens.names, ...rawLight.keys()];
|
|
3955
|
-
const invariant = [...tokens.invariant, ...[...rawLight.keys()].filter((n) => rawLight.get(n) === rawDark.get(n))];
|
|
3956
|
-
return {
|
|
3957
|
-
slug: tokens.slug,
|
|
3958
|
-
names,
|
|
3959
|
-
light: { ...tokens.light, ...Object.fromEntries([...rawLight.keys()].map((n) => [n, light[n]])) },
|
|
3960
|
-
dark: { ...tokens.dark, ...Object.fromEntries([...rawDark.keys()].map((n) => [n, dark[n]])) },
|
|
3961
|
-
invariant,
|
|
3962
|
-
raw: {
|
|
3963
|
-
light: { ...tokens.raw.light, ...Object.fromEntries(rawLight) },
|
|
3964
|
-
dark: { ...tokens.raw.dark, ...Object.fromEntries(rawDark) }
|
|
3965
|
-
}
|
|
3966
|
-
};
|
|
3967
|
-
}
|
|
3968
|
-
|
|
3969
3780
|
// src/engine/figmaRender.ts
|
|
3970
|
-
var
|
|
3971
|
-
|
|
3972
|
-
$type: "color",
|
|
3973
|
-
|
|
3974
|
-
|
|
3781
|
+
var channel = (v2) => Math.round(Math.round(Math.min(1, Math.max(0, v2)) * 255) / 255 * 1e4) / 1e4;
|
|
3782
|
+
function color(r, g2, b, alpha = 1) {
|
|
3783
|
+
return { $type: "color", $value: { colorSpace: "srgb", components: [channel(r), channel(g2), channel(b)], alpha, hex: toHex2(r, g2, b) } };
|
|
3784
|
+
}
|
|
3785
|
+
var TRANSPARENT_TOKEN = color(0, 0, 0, 0);
|
|
3975
3786
|
var OFFSET_TOKEN = (rung, mode) => {
|
|
3976
3787
|
const c = mode === "light" ? 0 : 1;
|
|
3977
|
-
return
|
|
3978
|
-
$type: "color",
|
|
3979
|
-
$value: { colorSpace: "srgb", components: [c, c, c], alpha: OFFSET_ALPHAS[rung], hex: mode === "light" ? "#000000" : "#ffffff" }
|
|
3980
|
-
};
|
|
3788
|
+
return color(c, c, c, OFFSET_ALPHAS[rung]);
|
|
3981
3789
|
};
|
|
3982
3790
|
function colorFromStop(s) {
|
|
3983
3791
|
const { r, g: g2, b } = srgbEmitChannels(s);
|
|
3984
|
-
return
|
|
3985
|
-
$type: "color",
|
|
3986
|
-
$value: { colorSpace: "srgb", components: [clamp01(r), clamp01(g2), clamp01(b)], alpha: 1, hex: toHex2(r, g2, b) }
|
|
3987
|
-
};
|
|
3988
|
-
}
|
|
3989
|
-
function colorFromHex(white) {
|
|
3990
|
-
const v2 = white ? 1 : 0;
|
|
3991
|
-
return { $type: "color", $value: { colorSpace: "srgb", components: [v2, v2, v2], alpha: 1, hex: white ? "#ffffff" : "#000000" } };
|
|
3792
|
+
return color(r, g2, b);
|
|
3992
3793
|
}
|
|
3794
|
+
var pole = (white, alpha = 1) => white ? color(1, 1, 1, alpha) : color(0, 0, 0, alpha);
|
|
3993
3795
|
function colorFromHexString(hex) {
|
|
3994
3796
|
const h = hex.replace("#", "");
|
|
3995
|
-
|
|
3996
|
-
const g2 = parseInt(h.slice(2, 4), 16) / 255;
|
|
3997
|
-
const b = parseInt(h.slice(4, 6), 16) / 255;
|
|
3998
|
-
return { $type: "color", $value: { colorSpace: "srgb", components: [r, g2, b], alpha: 1, hex: hex.toLowerCase() } };
|
|
3797
|
+
return color(parseInt(h.slice(0, 2), 16) / 255, parseInt(h.slice(2, 4), 16) / 255, parseInt(h.slice(4, 6), 16) / 255);
|
|
3999
3798
|
}
|
|
4000
3799
|
function bandedLeaf(flat) {
|
|
4001
3800
|
return STAMP_STATE_LEAVES[flat] ?? flat;
|
|
4002
3801
|
}
|
|
3802
|
+
function groupEntries(g2) {
|
|
3803
|
+
const entries = Object.entries(g2);
|
|
3804
|
+
const digitLeading = (k) => /^\d/.test(k);
|
|
3805
|
+
if (entries.length > 1 && entries.every(([k]) => digitLeading(k)))
|
|
3806
|
+
return entries.sort((a, b) => parseInt(b[0], 10) - parseInt(a[0], 10));
|
|
3807
|
+
return entries;
|
|
3808
|
+
}
|
|
4003
3809
|
function putLeaf(g2, flat, tok) {
|
|
4004
3810
|
const path = bandedLeaf(flat).split("/");
|
|
4005
3811
|
let cur = g2;
|
|
@@ -4017,8 +3823,7 @@ function rampGroup(stops, onFillWhite, extra) {
|
|
|
4017
3823
|
if (extra?.ctaHover) putLeaf(g2, STAMP_FILL_HOVER, colorFromStop(extra.ctaHover));
|
|
4018
3824
|
if (extra?.ctaPressed) putLeaf(g2, STAMP_FILL_PRESSED, colorFromStop(extra.ctaPressed));
|
|
4019
3825
|
if (extra?.cta) putLeaf(g2, STAMP_EDGE, extra.ctaBorder ?? TRANSPARENT_TOKEN);
|
|
4020
|
-
putLeaf(g2, STAMP_ON,
|
|
4021
|
-
if (extra?.identityHex) g2["identity"] = colorFromHexString(extra.identityHex);
|
|
3826
|
+
putLeaf(g2, STAMP_ON, pole(onFillWhite));
|
|
4022
3827
|
return g2;
|
|
4023
3828
|
}
|
|
4024
3829
|
function themeToFigma(r, input) {
|
|
@@ -4031,10 +3836,6 @@ function themeToFigma(r, input) {
|
|
|
4031
3836
|
ctaBorder: ctaNeedsBorder(s, mode, borderPage(mode)) ? OFFSET_TOKEN(ctaBorderRung(prefix), mode) : TRANSPARENT_TOKEN,
|
|
4032
3837
|
...mode === "light" ? { cta: s.cta, ctaHover: s.ctaHover, ctaPressed: s.ctaPressed } : { cta: s.ctaDark, ctaHover: s.ctaHoverDark, ctaPressed: s.ctaPressedDark }
|
|
4033
3838
|
});
|
|
4034
|
-
const brandExtra = (s, mode, prefix) => ({
|
|
4035
|
-
identityHex: s.identityHex,
|
|
4036
|
-
...ctaFamily(s, mode, prefix)
|
|
4037
|
-
});
|
|
4038
3839
|
const nScale = generateNeutralScale(input.neutralH ?? scale.brandH, input.neutralLevel ?? "default", input.contrastProfile);
|
|
4039
3840
|
const lt = input.linkHex ? resolveLinkTrio(input.linkHex, input.contrastProfile) : null;
|
|
4040
3841
|
const invSeed = input.linkHex ?? scale.identityHex ?? (() => {
|
|
@@ -4043,10 +3844,9 @@ function themeToFigma(r, input) {
|
|
|
4043
3844
|
return toHex2(e.r, e.g, e.b);
|
|
4044
3845
|
})();
|
|
4045
3846
|
const invLt = resolveLinkInverseTrio(invSeed, input.contrastProfile);
|
|
4046
|
-
const neutralExtra = (mode) => ctaFamily(nScale, mode, CSS_FAMILY.neutral);
|
|
4047
3847
|
const build = (mode) => {
|
|
4048
3848
|
const p02 = mode === "light" ? nScale.paper0 : nScale.paper0Dark;
|
|
4049
|
-
const ramp = rampGroup(nScale[mode], mode === "light" ? nScale.onFillTextIsWhite : nScale.onFillTextIsWhiteDark,
|
|
3849
|
+
const ramp = rampGroup(nScale[mode], mode === "light" ? nScale.onFillTextIsWhite : nScale.onFillTextIsWhiteDark, ctaFamily(nScale, mode, CSS_FAMILY.neutral));
|
|
4050
3850
|
const i02 = mode === "light" ? nScale.pen100 : nScale.pen100Dark;
|
|
4051
3851
|
const splicePen100 = (g3) => {
|
|
4052
3852
|
if (!i02) return g3;
|
|
@@ -4058,41 +3858,31 @@ function themeToFigma(r, input) {
|
|
|
4058
3858
|
return out;
|
|
4059
3859
|
};
|
|
4060
3860
|
const neutralGroup = splicePen100(p02 ? { [PAPER_0]: colorFromStop(p02), ...ramp } : ramp);
|
|
4061
|
-
const secondaryGroup = rampGroup(secondary[mode], mode === "light" ? secondaryOnFillLight : secondaryOnFillDark,
|
|
3861
|
+
const secondaryGroup = rampGroup(secondary[mode], mode === "light" ? secondaryOnFillLight : secondaryOnFillDark, ctaFamily(secondary, mode, CSS_FAMILY.brandSecondary));
|
|
4062
3862
|
if (input.secondaryStyle === "outline" && input.secondary) {
|
|
4063
3863
|
const s8 = secondary[mode].find((s) => s.stop === 8);
|
|
4064
3864
|
const s9 = secondary[mode].find((s) => s.stop === 9);
|
|
4065
3865
|
putLeaf(secondaryGroup, STAMP_FILL, TRANSPARENT_TOKEN);
|
|
4066
3866
|
if (s8) {
|
|
4067
3867
|
const e = srgbEmitChannels(s8);
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
});
|
|
4072
|
-
putLeaf(secondaryGroup, STAMP_FILL_HOVER, alphaTint(OUTLINE_HOVER_ALPHA));
|
|
4073
|
-
putLeaf(secondaryGroup, STAMP_FILL_PRESSED, alphaTint(OUTLINE_PRESSED_ALPHA));
|
|
3868
|
+
putLeaf(secondaryGroup, STAMP_FILL_HOVER, color(e.r, e.g, e.b, OUTLINE_HOVER_ALPHA));
|
|
3869
|
+
putLeaf(secondaryGroup, STAMP_FILL_PRESSED, color(e.r, e.g, e.b, OUTLINE_PRESSED_ALPHA));
|
|
3870
|
+
putLeaf(secondaryGroup, STAMP_EDGE, colorFromStop(s8));
|
|
4074
3871
|
}
|
|
4075
|
-
if (s8) putLeaf(secondaryGroup, STAMP_EDGE, colorFromStop(s8));
|
|
4076
3872
|
if (s9) putLeaf(secondaryGroup, STAMP_ON, colorFromStop(s9));
|
|
4077
3873
|
}
|
|
4078
|
-
const softOnCta = (g3, white) =>
|
|
4079
|
-
const p = white ? 1 : 0;
|
|
4080
|
-
putLeaf(g3, STAMP_ON, {
|
|
4081
|
-
$type: "color",
|
|
4082
|
-
$value: { colorSpace: "srgb", components: [p, p, p], alpha: SOFT_ON_CTA_ALPHA[mode], hex: white ? "#ffffff" : "#000000" }
|
|
4083
|
-
});
|
|
4084
|
-
};
|
|
3874
|
+
const softOnCta = (g3, white) => putLeaf(g3, STAMP_ON, pole(white, SOFT_ON_CTA_ALPHA[mode]));
|
|
4085
3875
|
softOnCta(neutralGroup, mode === "light" ? nScale.onFillTextIsWhite : nScale.onFillTextIsWhiteDark);
|
|
4086
3876
|
if (input.secondary && input.secondaryStyle !== "outline" && softOnCtaPasses(input.secondary, mode))
|
|
4087
3877
|
softOnCta(secondaryGroup, mode === "light" ? secondaryOnFillLight : secondaryOnFillDark);
|
|
4088
|
-
const brandGroup = rampGroup(scale[mode], mode === "light" ? scale.onFillTextIsWhite : scale.onFillTextIsWhiteDark,
|
|
3878
|
+
const brandGroup = rampGroup(scale[mode], mode === "light" ? scale.onFillTextIsWhite : scale.onFillTextIsWhiteDark, ctaFamily(scale, mode, CSS_FAMILY.brandPrimary));
|
|
4089
3879
|
const esc = input.ctaEscape ? escapeCtaFamily(nScale, mode, input.contrastProfile) : null;
|
|
4090
3880
|
if (esc) {
|
|
4091
3881
|
for (const g3 of input.secondary ? [brandGroup] : [brandGroup, secondaryGroup]) {
|
|
4092
3882
|
putLeaf(g3, STAMP_FILL, colorFromStop(esc.cta));
|
|
4093
3883
|
putLeaf(g3, STAMP_FILL_HOVER, colorFromStop(esc.ctaHover));
|
|
4094
3884
|
putLeaf(g3, STAMP_FILL_PRESSED, colorFromStop(esc.ctaPressed));
|
|
4095
|
-
putLeaf(g3, STAMP_ON,
|
|
3885
|
+
putLeaf(g3, STAMP_ON, pole(esc.onFillIsWhite));
|
|
4096
3886
|
}
|
|
4097
3887
|
}
|
|
4098
3888
|
const scaleTextAt = (n) => {
|
|
@@ -4100,146 +3890,131 @@ function themeToFigma(r, input) {
|
|
|
4100
3890
|
if (!s) throw new Error(`themeToFigma link: the brand scale has no pen stop ${n}`);
|
|
4101
3891
|
return s;
|
|
4102
3892
|
};
|
|
4103
|
-
const
|
|
4104
|
-
|
|
3893
|
+
const trio = (posture) => {
|
|
3894
|
+
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];
|
|
3895
|
+
return Object.fromEntries(LINK_STATES.map((state, i) => [state, colorFromStop(t[i])]));
|
|
3896
|
+
};
|
|
4105
3897
|
const g2 = {
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
link: linkGroup,
|
|
4110
|
-
"link-inverse": linkInverseGroup
|
|
3898
|
+
[CSS_FAMILY.neutral]: neutralGroup,
|
|
3899
|
+
[CSS_FAMILY.brandPrimary]: brandGroup,
|
|
3900
|
+
[CSS_FAMILY.brandSecondary]: secondaryGroup
|
|
4111
3901
|
};
|
|
4112
3902
|
for (const sig of input.signals) {
|
|
4113
|
-
|
|
3903
|
+
const role = SIGNAL_EMIT_NAME[sig.name] ?? sig.name;
|
|
3904
|
+
g2[role] = rampGroup(
|
|
4114
3905
|
sig.scale[mode],
|
|
4115
3906
|
mode === "light" ? sig.scale.onFillTextIsWhite : sig.scale.onFillTextIsWhiteDark,
|
|
4116
|
-
|
|
4117
|
-
// Unreachable at the Lc 15 gate — no signal gets within 4 Lc of it — but defined, not accidental.
|
|
4118
|
-
ctaFamily(sig.scale, mode, sig.name)
|
|
3907
|
+
ctaFamily(sig.scale, mode, role)
|
|
4119
3908
|
);
|
|
4120
3909
|
}
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
$value: { colorSpace: "srgb", components: [c, c, c], alpha, hex: white ? "#ffffff" : "#000000" }
|
|
4126
|
-
};
|
|
3910
|
+
g2[LINK_GROUP] = { default: trio("default"), inverse: trio("inverse") };
|
|
3911
|
+
g2[ABSOLUTE_GROUP] = {
|
|
3912
|
+
[CSS_FAMILY.brandPrimary]: colorFromHexString(scale.identityHex ?? invSeed),
|
|
3913
|
+
[CSS_FAMILY.brandSecondary]: colorFromHexString((input.secondary ?? scale).identityHex ?? invSeed)
|
|
4127
3914
|
};
|
|
4128
|
-
putLeaf(g2, SYSTEM_LEAF.ABS_BLACK, colorFromHex(false));
|
|
4129
|
-
putLeaf(g2, SYSTEM_LEAF.ABS_WHITE, colorFromHex(true));
|
|
4130
|
-
for (const [path, law] of Object.entries(SURFACE_PLANE_LAW)) {
|
|
4131
|
-
const tok = neutralGroup[law[mode]];
|
|
4132
|
-
if (tok && "$type" in tok) putLeaf(g2, path, tok);
|
|
4133
|
-
}
|
|
4134
|
-
putLeaf(g2, SYSTEM_LEAF.ALPHA.TRANSPARENT, pole(true, 0));
|
|
4135
|
-
for (const rung of Object.keys(OPACITY_RUNGS).map(Number))
|
|
4136
|
-
putLeaf(g2, opacityTokenPath(rung), { $type: "number", $value: rung });
|
|
4137
|
-
putLeaf(g2, SYSTEM_LEAF.ALPHA.INK, pole(mode === "dark", SOFT_ON_CTA_ALPHA[mode]));
|
|
4138
|
-
putLeaf(g2, SYSTEM_LEAF.ALPHA.AWAY_FROM_BG_06, OFFSET_TOKEN(6, mode));
|
|
4139
|
-
putLeaf(g2, SYSTEM_LEAF.ALPHA.AWAY_FROM_BG_08, OFFSET_TOKEN(8, mode));
|
|
4140
|
-
putLeaf(g2, SYSTEM_LEAF.ALPHA.AWAY_FROM_BG_16, OFFSET_TOKEN(16, mode));
|
|
4141
|
-
const inv = mode === "light" ? "dark" : "light";
|
|
4142
|
-
putLeaf(g2, SYSTEM_LEAF.ALPHA.TOWARD_BG_06, OFFSET_TOKEN(6, inv));
|
|
4143
|
-
putLeaf(g2, SYSTEM_LEAF.ALPHA.TOWARD_BG_08, OFFSET_TOKEN(8, inv));
|
|
4144
|
-
putLeaf(g2, SYSTEM_LEAF.ALPHA.TOWARD_BG_16, OFFSET_TOKEN(16, inv));
|
|
4145
|
-
putLeaf(g2, SYSTEM_LEAF.ALPHA.SHADOW_04, pole(false, SHADOW_ALPHAS[4][mode]));
|
|
4146
|
-
putLeaf(g2, SYSTEM_LEAF.ALPHA.SHADOW_08, pole(false, SHADOW_ALPHAS[8][mode]));
|
|
4147
|
-
putLeaf(g2, SYSTEM_LEAF.ALPHA.SHADOW_12, pole(false, SHADOW_ALPHAS[12][mode]));
|
|
4148
3915
|
return g2;
|
|
4149
3916
|
};
|
|
4150
3917
|
return { light: build("light"), dark: build("dark") };
|
|
4151
3918
|
}
|
|
4152
3919
|
|
|
4153
|
-
// src/engine/
|
|
4154
|
-
var
|
|
4155
|
-
var
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
const
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
3920
|
+
// src/engine/dtcgRender.ts
|
|
3921
|
+
var STAMP = [STAMP_FILL, STAMP_FILL_HOVER, STAMP_FILL_PRESSED, STAMP_EDGE, STAMP_ON];
|
|
3922
|
+
var STOPS = Array.from({ length: SCALE_STOP_COUNT }, (_, i) => stopTokenName(i + 1));
|
|
3923
|
+
function tokenPaths() {
|
|
3924
|
+
const family = (word, poles) => [
|
|
3925
|
+
...poles ? [familyPath(word, PAPER_0)] : [],
|
|
3926
|
+
...STOPS.map((leaf) => familyPath(word, leaf)),
|
|
3927
|
+
...poles ? [familyPath(word, PEN_100)] : [],
|
|
3928
|
+
...STAMP.map((leaf) => familyPath(word, leaf))
|
|
3929
|
+
];
|
|
3930
|
+
return [
|
|
3931
|
+
...family(CSS_FAMILY.neutral, true),
|
|
3932
|
+
...family(CSS_FAMILY.brandPrimary, false),
|
|
3933
|
+
...family(CSS_FAMILY.brandSecondary, false),
|
|
3934
|
+
...SIGNALS2.flatMap((s) => family(s.emitName, false)),
|
|
3935
|
+
...LINK_POSTURES.flatMap((posture) => LINK_STATES.map((state) => linkPath(posture, state))),
|
|
3936
|
+
absolutePath(CSS_FAMILY.brandPrimary),
|
|
3937
|
+
absolutePath(CSS_FAMILY.brandSecondary)
|
|
3938
|
+
];
|
|
3939
|
+
}
|
|
3940
|
+
var byName = () => new Map(tokenPaths().map((p) => [cssVarName(p).slice(2), p]));
|
|
3941
|
+
function tokenPathOf(name) {
|
|
3942
|
+
return byName().get(name);
|
|
3943
|
+
}
|
|
3944
|
+
function descriptionPathOf(name) {
|
|
3945
|
+
const p = tokenPathOf(name);
|
|
3946
|
+
return p && figmaPathOf(p);
|
|
3947
|
+
}
|
|
3948
|
+
var component = (c8) => Math.round(c8 / 255 * 1e4) / 1e4;
|
|
3949
|
+
var colorValue = (r, g2, b, alpha) => ({
|
|
3950
|
+
colorSpace: "srgb",
|
|
3951
|
+
components: [component(r), component(g2), component(b)],
|
|
3952
|
+
alpha,
|
|
3953
|
+
hex: "#" + [r, g2, b].map((c) => c.toString(16).padStart(2, "0")).join("")
|
|
3954
|
+
});
|
|
3955
|
+
function dtcgColor(value) {
|
|
3956
|
+
let m;
|
|
3957
|
+
if (m = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(value)) return colorValue(parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16), 1);
|
|
3958
|
+
if (m = /^rgba\((\d+), (\d+), (\d+), ([0-9.]+)\)$/.exec(value)) return colorValue(+m[1], +m[2], +m[3], +m[4]);
|
|
3959
|
+
if (value === "transparent") return colorValue(0, 0, 0, 0);
|
|
3960
|
+
throw new Error(`dtcgColor: not a color the emitters write: ${value}`);
|
|
3961
|
+
}
|
|
3962
|
+
var ALIAS = /^var\(--([a-z0-9-]+)\)$/;
|
|
3963
|
+
var SEGMENT = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
3964
|
+
function tokensToDtcg(tokens, options = {}) {
|
|
3965
|
+
const { rootGroup } = options;
|
|
3966
|
+
if (rootGroup !== void 0 && !SEGMENT.test(rootGroup)) throw new Error(`tokensToDtcg: rootGroup must be lower-case words and digits joined by hyphens: ${JSON.stringify(rootGroup)}`);
|
|
3967
|
+
const rooted = (path) => rootGroup === void 0 ? path : [rootGroup, ...path];
|
|
3968
|
+
const paths = byName();
|
|
3969
|
+
const roster = new Set(paths.keys());
|
|
3970
|
+
for (const name of tokens.names) if (!roster.has(name)) throw new Error(`tokensToDtcg: the emit carries a name the roster does not know: ${name}`);
|
|
3971
|
+
for (const name of roster) if (!(name in tokens.light)) throw new Error(`tokensToDtcg: the emit lacks ${name}`);
|
|
3972
|
+
const build = (mode) => {
|
|
3973
|
+
const doc = {};
|
|
3974
|
+
for (const [name, path] of paths) {
|
|
3975
|
+
const raw = tokens.raw[mode][name] ?? tokens.raw.light[name];
|
|
3976
|
+
const alias = ALIAS.exec(raw);
|
|
3977
|
+
let token;
|
|
3978
|
+
if (alias) {
|
|
3979
|
+
const target = paths.get(alias[1]);
|
|
3980
|
+
if (!target) throw new Error(`tokensToDtcg: ${name} references a name outside the roster: ${alias[1]}`);
|
|
3981
|
+
token = { $type: "color", $value: `{${rooted(target).join(".")}}` };
|
|
3982
|
+
} else {
|
|
3983
|
+
token = { $type: "color", $value: dtcgColor(tokens[mode][name]) };
|
|
3984
|
+
}
|
|
3985
|
+
const body = describeDocument(figmaPathOf(path));
|
|
3986
|
+
if (body) token.$description = body;
|
|
3987
|
+
let cur = doc;
|
|
3988
|
+
for (const seg of rooted(path).slice(0, -1)) {
|
|
3989
|
+
const next = cur[seg];
|
|
3990
|
+
if (next && "$type" in next) throw new Error(`tokensToDtcg: ${seg} is both a token and a group on the way to ${path.join("/")}`);
|
|
3991
|
+
cur = cur[seg] ?? (cur[seg] = {});
|
|
3992
|
+
}
|
|
3993
|
+
const leaf = path[path.length - 1];
|
|
3994
|
+
if (leaf in cur) throw new Error(`tokensToDtcg: duplicate path ${path.join("/")}`);
|
|
3995
|
+
cur[leaf] = token;
|
|
3996
|
+
}
|
|
3997
|
+
return doc;
|
|
4182
3998
|
};
|
|
4183
|
-
|
|
4184
|
-
const rv = roleVal[rr.role];
|
|
4185
|
-
group[rr.role] = { $type: "color", $value: hexToValue(rv.hex), $extensions: { [EXT_KEY]: { resolver: RESOLVER_ID, seed: seedRef, mode, ...rr } } };
|
|
4186
|
-
}
|
|
4187
|
-
return group;
|
|
4188
|
-
}
|
|
4189
|
-
function parseToken(token) {
|
|
4190
|
-
const ext = token.$extensions?.[EXT_KEY];
|
|
4191
|
-
if (!ext) throw new Error("missing $extensions." + EXT_KEY);
|
|
4192
|
-
if (ext.resolver !== RESOLVER_ID) throw new Error(`unknown resolver "${ext.resolver}" (this resolver is ${RESOLVER_ID})`);
|
|
4193
|
-
const { resolver, seed, mode, ...req } = ext;
|
|
4194
|
-
const isRole = "role" in req;
|
|
4195
|
-
if (!isRole) {
|
|
4196
|
-
for (const k of ["stop", "rootL", "group", "produce"]) if (req[k] === void 0) throw new Error(`stop requirement missing "${k}"`);
|
|
4197
|
-
}
|
|
4198
|
-
if (isRole) {
|
|
4199
|
-
for (const k of ["role", "produce", "floorL", "chromaMult"]) if (req[k] === void 0) throw new Error(`role requirement missing "${k}"`);
|
|
4200
|
-
}
|
|
4201
|
-
if (isRole && LEGACY_ROLE_NAMES[req.role]) req.role = LEGACY_ROLE_NAMES[req.role];
|
|
4202
|
-
return { req, seedRef: seed, mode };
|
|
4203
|
-
}
|
|
4204
|
-
function resolveDtcgRamp(group) {
|
|
4205
|
-
const seedHex = group.seed.$value.hex;
|
|
4206
|
-
const ons = group.$extensions?.[EXT_KEY]?.ons;
|
|
4207
|
-
if (!ons) throw new Error("missing group-level ons declaration");
|
|
4208
|
-
const stops = [];
|
|
4209
|
-
const roles = [];
|
|
4210
|
-
let mode;
|
|
4211
|
-
for (const [k, t] of Object.entries(group)) {
|
|
4212
|
-
if (k === "seed" || k === "$extensions") continue;
|
|
4213
|
-
const { req, mode: m } = parseToken(t);
|
|
4214
|
-
mode ?? (mode = m);
|
|
4215
|
-
"role" in req ? roles.push(req) : stops.push(req);
|
|
4216
|
-
}
|
|
4217
|
-
if (!mode) throw new Error("empty ramp group");
|
|
4218
|
-
stops.sort((a, b) => a.stop - b.stop);
|
|
4219
|
-
return resolveRamp(seedHex, mode, { stops, roles, ons });
|
|
3999
|
+
return { light: build("light"), dark: build("dark") };
|
|
4220
4000
|
}
|
|
4221
4001
|
export {
|
|
4002
|
+
ABSOLUTE_GROUP,
|
|
4003
|
+
BAND_STOPS,
|
|
4004
|
+
COLOR_GROUP,
|
|
4222
4005
|
CSS_FAMILY,
|
|
4223
4006
|
DEFAULT_LINK_HEX,
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
INTERACTION_POLE_FAMILY,
|
|
4229
|
-
INTERACTION_ROWS,
|
|
4230
|
-
INTERACTION_RUNGS,
|
|
4231
|
-
INTERACTION_STATES,
|
|
4007
|
+
GUARANTEE_SCOPE,
|
|
4008
|
+
LINK_GROUP,
|
|
4009
|
+
LINK_POSTURES,
|
|
4010
|
+
LINK_STATES,
|
|
4232
4011
|
MODE_SPECS,
|
|
4233
4012
|
OFFSET_ALPHAS,
|
|
4234
|
-
OPACITY_RUNGS,
|
|
4235
4013
|
OUTLINE_HOVER_ALPHA,
|
|
4236
4014
|
PAPER_0,
|
|
4237
4015
|
PEN_100,
|
|
4238
|
-
RESOLVER_ID,
|
|
4239
4016
|
SCALE_STOP_COUNT,
|
|
4240
|
-
SCRIM_ALPHA,
|
|
4241
4017
|
SECONDARY_DISTINCT_DELTA_E,
|
|
4242
|
-
SHADOW_ALPHAS,
|
|
4243
4018
|
SIGNALS2 as SIGNALS,
|
|
4244
4019
|
SIGNAL_EMIT_NAME,
|
|
4245
4020
|
SIGNAL_SCALES,
|
|
@@ -4247,38 +4022,35 @@ export {
|
|
|
4247
4022
|
STAMP_FILL,
|
|
4248
4023
|
STAMP_FILL_HOVER,
|
|
4249
4024
|
STAMP_FILL_PRESSED,
|
|
4025
|
+
STAMP_LEAF,
|
|
4250
4026
|
STAMP_ON,
|
|
4251
4027
|
STAMP_STATE_LEAVES,
|
|
4252
4028
|
SUBTLE_PASTEL_K,
|
|
4253
4029
|
SUBTLE_TINT_MULT,
|
|
4254
|
-
|
|
4255
|
-
SYSTEM_LEAF,
|
|
4030
|
+
absolutePath,
|
|
4256
4031
|
brandCss,
|
|
4257
4032
|
checkAllCollisions,
|
|
4258
4033
|
checkCollision,
|
|
4259
4034
|
checkHueCollision,
|
|
4260
4035
|
classifyArchetype,
|
|
4036
|
+
cssVarName,
|
|
4261
4037
|
ctaBorderRung,
|
|
4262
4038
|
ctaNeedsBorder,
|
|
4263
|
-
|
|
4039
|
+
describeDocument,
|
|
4040
|
+
describeToken,
|
|
4041
|
+
descriptionPathOf,
|
|
4042
|
+
familyPath,
|
|
4043
|
+
figmaPathOf,
|
|
4264
4044
|
generateNeutralScale,
|
|
4265
4045
|
generateScale,
|
|
4266
4046
|
generateSubtleSecondary,
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
interactionTintName,
|
|
4270
|
-
interactionTokens,
|
|
4271
|
-
interactionVarName,
|
|
4047
|
+
groupEntries,
|
|
4048
|
+
linkPath,
|
|
4272
4049
|
neutralCss,
|
|
4273
4050
|
neutralTintHue,
|
|
4274
|
-
opacityLeafName,
|
|
4275
|
-
opacityTokenPath,
|
|
4276
|
-
opacityVarName,
|
|
4277
4051
|
pageStopFor,
|
|
4278
|
-
parseToken,
|
|
4279
4052
|
readEmission,
|
|
4280
4053
|
resolveBrand,
|
|
4281
|
-
resolveDtcgRamp,
|
|
4282
4054
|
resolveLinkInverseTrio,
|
|
4283
4055
|
resolveLinkTrio,
|
|
4284
4056
|
resolveReferences,
|
|
@@ -4288,10 +4060,11 @@ export {
|
|
|
4288
4060
|
stopHex,
|
|
4289
4061
|
stopTokenName,
|
|
4290
4062
|
stopsToVars,
|
|
4291
|
-
systemCss,
|
|
4292
4063
|
themeToFigma,
|
|
4293
4064
|
themeTokens,
|
|
4294
4065
|
toHex2 as toHex,
|
|
4295
4066
|
tokenOrder,
|
|
4296
|
-
|
|
4067
|
+
tokenPathOf,
|
|
4068
|
+
tokensFromEmission,
|
|
4069
|
+
tokensToDtcg
|
|
4297
4070
|
};
|