@wix/himalaya-cli 0.1051.0 → 0.1052.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +238 -181
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -5603,7 +5603,6 @@ function walk(node, registry, path2, out) {
|
|
|
5603
5603
|
var SYSTEM_FONT_FAMILY, TONAL_ELEVATION_ALPHA;
|
|
5604
5604
|
var init_tokens = __esm({
|
|
5605
5605
|
"../../core/ts/src/tokens.ts"() {
|
|
5606
|
-
"use strict";
|
|
5607
5606
|
SYSTEM_FONT_FAMILY = "$system";
|
|
5608
5607
|
TONAL_ELEVATION_ALPHA = [0, 0.05, 0.08, 0.11, 0.12, 0.14];
|
|
5609
5608
|
}
|
|
@@ -5630,7 +5629,6 @@ function resolveTranslation(value, catalog, sourceCatalog) {
|
|
|
5630
5629
|
var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
|
|
5631
5630
|
var init_bindings = __esm({
|
|
5632
5631
|
"../../core/ts/src/bindings.ts"() {
|
|
5633
|
-
"use strict";
|
|
5634
5632
|
BINDING_SIGILS = ["service", "flag", "item", "t"];
|
|
5635
5633
|
BINDING_SIGIL_RE = new RegExp(
|
|
5636
5634
|
`^\\$(?:${BINDING_SIGILS.filter((s) => s !== "t").join("|")})\\b|^\\$t:`
|
|
@@ -11371,6 +11369,177 @@ var init_idiom = __esm({
|
|
|
11371
11369
|
}
|
|
11372
11370
|
});
|
|
11373
11371
|
|
|
11372
|
+
// ../../core/ts/src/brand-color-math.ts
|
|
11373
|
+
function channel2(hex2, offset) {
|
|
11374
|
+
return Number.parseInt(hex2.slice(offset, offset + 2), 16);
|
|
11375
|
+
}
|
|
11376
|
+
function toHex(r, g, b) {
|
|
11377
|
+
return `#${[r, g, b].map((value) => Math.round(value).toString(16).padStart(2, "0")).join("")}`.toUpperCase();
|
|
11378
|
+
}
|
|
11379
|
+
function mix(color, background, colorWeight) {
|
|
11380
|
+
const values = [1, 3, 5].map((offset) => channel2(color, offset) * colorWeight + channel2(background, offset) * (1 - colorWeight));
|
|
11381
|
+
return toHex(values[0], values[1], values[2]);
|
|
11382
|
+
}
|
|
11383
|
+
function relativeLuminance2(color) {
|
|
11384
|
+
const linear = [1, 3, 5].map((offset) => {
|
|
11385
|
+
const value = channel2(color, offset) / 255;
|
|
11386
|
+
return value <= 0.03928 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
|
|
11387
|
+
});
|
|
11388
|
+
return 0.2126 * linear[0] + 0.7152 * linear[1] + 0.0722 * linear[2];
|
|
11389
|
+
}
|
|
11390
|
+
function contrastRatio2(a, b) {
|
|
11391
|
+
const la = relativeLuminance2(a);
|
|
11392
|
+
const lb = relativeLuminance2(b);
|
|
11393
|
+
return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
|
|
11394
|
+
}
|
|
11395
|
+
function lstar(color) {
|
|
11396
|
+
const y = relativeLuminance2(color);
|
|
11397
|
+
return y <= 8856e-6 ? y * 903.3 : 116 * Math.cbrt(y) - 16;
|
|
11398
|
+
}
|
|
11399
|
+
function deriveAccentSurface(accent, surface, weight) {
|
|
11400
|
+
const tint = mix(accent, surface, weight);
|
|
11401
|
+
if (contrastRatio2(tint, surface) >= ACCENT_SURFACE_MIN_DELTA) return tint;
|
|
11402
|
+
const away = relativeLuminance2(surface) < 0.5 ? "#FFFFFF" : "#000000";
|
|
11403
|
+
for (let w = 0.02; w <= 0.5; w += 0.02) {
|
|
11404
|
+
const candidate = mix(away, surface, w);
|
|
11405
|
+
if (contrastRatio2(candidate, surface) >= ACCENT_SURFACE_MIN_DELTA) return candidate;
|
|
11406
|
+
}
|
|
11407
|
+
return tint;
|
|
11408
|
+
}
|
|
11409
|
+
function deriveSecondaryAccent(primary) {
|
|
11410
|
+
const shade2 = mix(primary, "#000000", SECONDARY_SHADE_WEIGHT);
|
|
11411
|
+
if (lstar(shade2) >= SECONDARY_MIN_LSTAR) return shade2;
|
|
11412
|
+
return mix(primary, "#FFFFFF", SECONDARY_SHADE_WEIGHT);
|
|
11413
|
+
}
|
|
11414
|
+
function textOn(color) {
|
|
11415
|
+
const luminance2 = relativeLuminance2(color);
|
|
11416
|
+
const whiteContrast = 1.05 / (luminance2 + 0.05);
|
|
11417
|
+
const blackContrast = (luminance2 + 0.05) / 0.05;
|
|
11418
|
+
return whiteContrast >= blackContrast ? "#FFFFFF" : "#000000";
|
|
11419
|
+
}
|
|
11420
|
+
function tuneDarkAccent(brand, darkSurface, lightSurface) {
|
|
11421
|
+
const kitInherentlyDark = lstar(lightSurface) < 50;
|
|
11422
|
+
if (kitInherentlyDark && contrastRatio2(brand, darkSurface) >= DARK_ARM_TARGET_CONTRAST && lstar(brand) <= DARK_ARM_LSTAR_CAP) {
|
|
11423
|
+
return brand;
|
|
11424
|
+
}
|
|
11425
|
+
let lift = DARK_ARM_MIN_LIFT;
|
|
11426
|
+
let candidate = mix(brand, "#FFFFFF", 1 - lift);
|
|
11427
|
+
while (contrastRatio2(candidate, darkSurface) < DARK_ARM_TARGET_CONTRAST && lift < 0.6) {
|
|
11428
|
+
lift += 0.04;
|
|
11429
|
+
candidate = mix(brand, "#FFFFFF", 1 - lift);
|
|
11430
|
+
}
|
|
11431
|
+
while (lstar(candidate) > DARK_ARM_LSTAR_CAP) {
|
|
11432
|
+
const darker = mix(candidate, "#000000", 0.94);
|
|
11433
|
+
if (contrastRatio2(darker, darkSurface) < DARK_ARM_FLOOR_CONTRAST) break;
|
|
11434
|
+
candidate = darker;
|
|
11435
|
+
}
|
|
11436
|
+
return candidate;
|
|
11437
|
+
}
|
|
11438
|
+
function textOnArm(accent) {
|
|
11439
|
+
return contrastRatio2("#FFFFFF", accent) >= 4.5 ? "#FFFFFF" : textOn(accent);
|
|
11440
|
+
}
|
|
11441
|
+
function tuneHighContrastAccent(brand, surface) {
|
|
11442
|
+
const towards = relativeLuminance2(surface) < 0.5 ? "#FFFFFF" : "#000000";
|
|
11443
|
+
let candidate = brand;
|
|
11444
|
+
for (let lift = 0; lift <= 0.9 && contrastRatio2(candidate, surface) < HIGH_CONTRAST_TARGET; lift += 0.04) {
|
|
11445
|
+
candidate = mix(brand, towards, 1 - lift);
|
|
11446
|
+
}
|
|
11447
|
+
return candidate;
|
|
11448
|
+
}
|
|
11449
|
+
function deriveAccentText(accent, surfaces) {
|
|
11450
|
+
const all = (typeof surfaces === "string" ? [surfaces] : [...surfaces]).map((s) => s.slice(0, 7));
|
|
11451
|
+
const page = all[0];
|
|
11452
|
+
const worst = (color) => Math.min(...all.map((s) => contrastRatio2(color, s)));
|
|
11453
|
+
const opaque = accent.length === 9 ? mix(accent.slice(0, 7), page, channel2(accent, 7) / 255) : accent;
|
|
11454
|
+
if (worst(opaque) >= ACCENT_TEXT_MIN_CONTRAST) return opaque;
|
|
11455
|
+
const pole = worst("#FFFFFF") >= worst("#000000") ? "#FFFFFF" : "#000000";
|
|
11456
|
+
for (let step = 1; step <= 100; step++) {
|
|
11457
|
+
const candidate = mix(pole, opaque, step / 100);
|
|
11458
|
+
if (worst(candidate) >= ACCENT_TEXT_MIN_CONTRAST) return candidate;
|
|
11459
|
+
}
|
|
11460
|
+
if (all.length > 1) {
|
|
11461
|
+
const side2 = (hex2) => relativeLuminance2(hex2) > MID_GREY_LUMINANCE;
|
|
11462
|
+
const sameSide = all.filter((s) => side2(s) === side2(page));
|
|
11463
|
+
return deriveAccentText(accent, sameSide.length < all.length ? sameSide : [page]);
|
|
11464
|
+
}
|
|
11465
|
+
return pole;
|
|
11466
|
+
}
|
|
11467
|
+
function textSurfacesOf(colors) {
|
|
11468
|
+
const out = { light: [], dark: [], highContrast: [] };
|
|
11469
|
+
for (const name of TEXT_BACKDROP_TOKENS) {
|
|
11470
|
+
const value = colors[name];
|
|
11471
|
+
for (const arm of ["light", "dark", "highContrast"]) {
|
|
11472
|
+
const hex2 = typeof value === "string" ? value : value && typeof value === "object" && !Array.isArray(value) ? value[arm] ?? value.light : void 0;
|
|
11473
|
+
if (typeof hex2 === "string" && hex2.startsWith("#") && hex2.length >= 7) out[arm].push(hex2);
|
|
11474
|
+
}
|
|
11475
|
+
}
|
|
11476
|
+
return out;
|
|
11477
|
+
}
|
|
11478
|
+
function stripBrandFromIdiom(tokens) {
|
|
11479
|
+
const idiom = tokens.idiom;
|
|
11480
|
+
if (!idiom || typeof idiom !== "object" || Array.isArray(idiom)) return;
|
|
11481
|
+
for (const overlay of Object.values(idiom)) {
|
|
11482
|
+
if (!overlay || typeof overlay !== "object" || Array.isArray(overlay)) continue;
|
|
11483
|
+
const o = overlay;
|
|
11484
|
+
const colors = o.colors;
|
|
11485
|
+
if (colors && typeof colors === "object" && !Array.isArray(colors)) {
|
|
11486
|
+
for (const key2 of BRAND_COLOR_TOKENS) delete colors[key2];
|
|
11487
|
+
if (Object.keys(colors).length === 0) delete o.colors;
|
|
11488
|
+
}
|
|
11489
|
+
const shadows = o.shadows;
|
|
11490
|
+
const glow = shadows && typeof shadows === "object" && !Array.isArray(shadows) ? shadows[BRAND_GLOW_SHADOW] : void 0;
|
|
11491
|
+
if (glow && typeof glow === "object" && !Array.isArray(glow) && "color" in glow) {
|
|
11492
|
+
delete glow.color;
|
|
11493
|
+
if (Object.keys(glow).length === 0) delete shadows[BRAND_GLOW_SHADOW];
|
|
11494
|
+
if (Object.keys(shadows).length === 0) delete o.shadows;
|
|
11495
|
+
}
|
|
11496
|
+
}
|
|
11497
|
+
}
|
|
11498
|
+
function deriveAccentFamily(primary, secondary, surfaces, textSurfaces = {}) {
|
|
11499
|
+
const primaryDark = tuneDarkAccent(primary, surfaces.dark, surfaces.light);
|
|
11500
|
+
const secondaryDark = tuneDarkAccent(secondary, surfaces.dark, surfaces.light);
|
|
11501
|
+
const primaryHigh = tuneHighContrastAccent(primary, surfaces.highContrast);
|
|
11502
|
+
const secondaryHigh = tuneHighContrastAccent(secondary, surfaces.highContrast);
|
|
11503
|
+
return {
|
|
11504
|
+
accentPrimary: { light: primary, dark: primaryDark, highContrast: primaryHigh },
|
|
11505
|
+
accentSecondary: { light: secondary, dark: secondaryDark, highContrast: secondaryHigh },
|
|
11506
|
+
accentSurface: {
|
|
11507
|
+
light: deriveAccentSurface(primary, surfaces.light, ACCENT_SURFACE_LIGHT_WEIGHT),
|
|
11508
|
+
dark: deriveAccentSurface(primaryDark, surfaces.dark, 0.24),
|
|
11509
|
+
highContrast: deriveAccentSurface(primaryHigh, surfaces.highContrast, 0.24)
|
|
11510
|
+
},
|
|
11511
|
+
textOnAccent: {
|
|
11512
|
+
light: textOnArm(primary),
|
|
11513
|
+
dark: textOnArm(primaryDark),
|
|
11514
|
+
highContrast: textOn(primaryHigh)
|
|
11515
|
+
},
|
|
11516
|
+
accentText: {
|
|
11517
|
+
light: deriveAccentText(primary, [surfaces.light, ...textSurfaces.light ?? []]),
|
|
11518
|
+
dark: deriveAccentText(primaryDark, [surfaces.dark, ...textSurfaces.dark ?? []]),
|
|
11519
|
+
highContrast: deriveAccentText(primaryHigh, [surfaces.highContrast, ...textSurfaces.highContrast ?? []])
|
|
11520
|
+
}
|
|
11521
|
+
};
|
|
11522
|
+
}
|
|
11523
|
+
var ACCENT_SURFACE_MIN_DELTA, ACCENT_SURFACE_LIGHT_WEIGHT, SECONDARY_SHADE_WEIGHT, SECONDARY_MIN_LSTAR, DARK_ARM_MIN_LIFT, DARK_ARM_TARGET_CONTRAST, DARK_ARM_FLOOR_CONTRAST, DARK_ARM_LSTAR_CAP, HIGH_CONTRAST_TARGET, ACCENT_TEXT_MIN_CONTRAST, MID_GREY_LUMINANCE, TEXT_BACKDROP_TOKENS, BRAND_COLOR_TOKENS, BRAND_GLOW_SHADOW;
|
|
11524
|
+
var init_brand_color_math = __esm({
|
|
11525
|
+
"../../core/ts/src/brand-color-math.ts"() {
|
|
11526
|
+
ACCENT_SURFACE_MIN_DELTA = 1.08;
|
|
11527
|
+
ACCENT_SURFACE_LIGHT_WEIGHT = 0.12;
|
|
11528
|
+
SECONDARY_SHADE_WEIGHT = 0.72;
|
|
11529
|
+
SECONDARY_MIN_LSTAR = 22;
|
|
11530
|
+
DARK_ARM_MIN_LIFT = 0.08;
|
|
11531
|
+
DARK_ARM_TARGET_CONTRAST = 3.4;
|
|
11532
|
+
DARK_ARM_FLOOR_CONTRAST = 3;
|
|
11533
|
+
DARK_ARM_LSTAR_CAP = 80;
|
|
11534
|
+
HIGH_CONTRAST_TARGET = 8.5;
|
|
11535
|
+
ACCENT_TEXT_MIN_CONTRAST = 4.5;
|
|
11536
|
+
MID_GREY_LUMINANCE = 0.179;
|
|
11537
|
+
TEXT_BACKDROP_TOKENS = ["surfaceSecondary", "surfaceElevated", "surfaceSubtle", "surfaceTertiary"];
|
|
11538
|
+
BRAND_COLOR_TOKENS = ["accentPrimary", "accentSecondary", "accentSurface", "textOnAccent", "accentText"];
|
|
11539
|
+
BRAND_GLOW_SHADOW = "glow";
|
|
11540
|
+
}
|
|
11541
|
+
});
|
|
11542
|
+
|
|
11374
11543
|
// src/token-lint.ts
|
|
11375
11544
|
import { existsSync as existsSync13, readFileSync as readFileSync14 } from "node:fs";
|
|
11376
11545
|
import { join as join16 } from "node:path";
|
|
@@ -11537,13 +11706,71 @@ function contrastFindings(colors) {
|
|
|
11537
11706
|
});
|
|
11538
11707
|
}
|
|
11539
11708
|
}
|
|
11709
|
+
accentOnSurfaces(colors, declared, findings);
|
|
11540
11710
|
return [...findings.values()];
|
|
11541
11711
|
}
|
|
11542
|
-
|
|
11712
|
+
function sameHueClearingAll(fg, bgs, target = AA_TEXT) {
|
|
11713
|
+
const base = fg.slice(0, 7);
|
|
11714
|
+
const poles = onLightSide(bgs[0]) ? ["#000000", "#FFFFFF"] : ["#FFFFFF", "#000000"];
|
|
11715
|
+
for (let step = 0; step <= 100; step++) {
|
|
11716
|
+
for (const pole of poles) {
|
|
11717
|
+
const candidate = mixHex(base, pole, 1 - step / 100);
|
|
11718
|
+
if (bgs.every((bg) => contrastRatio(candidate, bg) >= target)) return candidate;
|
|
11719
|
+
}
|
|
11720
|
+
}
|
|
11721
|
+
return void 0;
|
|
11722
|
+
}
|
|
11723
|
+
function accentOnSurfaces(colors, declared, findings) {
|
|
11724
|
+
const hasAccentText = colors.accentText !== void 0;
|
|
11725
|
+
for (const fgName of hasAccentText ? ["accentText", "accentPrimary"] : ["accentPrimary"]) {
|
|
11726
|
+
if (colors[fgName] === void 0) continue;
|
|
11727
|
+
const role = fgName === "accentText" ? "the colour of accent text" : hasAccentText ? "still the colour of some accent text (the selected Tabs label on web, rich-text links on Android)" : "the colour of accent text (no accentText is declared, so accent text is painted with accentPrimary)";
|
|
11728
|
+
accentOnSurfacesFor(fgName, role, colors, declared, findings);
|
|
11729
|
+
}
|
|
11730
|
+
}
|
|
11731
|
+
function accentOnSurfacesFor(fgName, role, colors, declared, findings) {
|
|
11732
|
+
for (const surface of TEXT_BACKDROP_TOKENS) {
|
|
11733
|
+
if (colors[surface] === void 0) continue;
|
|
11734
|
+
for (const scheme of SCHEMES) {
|
|
11735
|
+
if (!declared.has(scheme)) continue;
|
|
11736
|
+
const fg = schemeValue(colors[fgName], scheme);
|
|
11737
|
+
const bg = schemeValue(colors[surface], scheme);
|
|
11738
|
+
if (!fg || !bg) continue;
|
|
11739
|
+
const painted = paintedOver(fg, bg);
|
|
11740
|
+
if (!painted) continue;
|
|
11741
|
+
const pageRaw = schemeValue(colors.surfacePrimary, scheme);
|
|
11742
|
+
const page = pageRaw && paintedOver(fg, pageRaw) ? pageRaw.slice(0, 7) : void 0;
|
|
11743
|
+
const opaqueBg = bg.slice(0, 7);
|
|
11744
|
+
if (page === opaqueBg) continue;
|
|
11745
|
+
if (page && contrastRatio(paintedOver(fg, pageRaw), page) < AA_TEXT) continue;
|
|
11746
|
+
const ratio = contrastRatio(painted, opaqueBg);
|
|
11747
|
+
if (ratio >= AA_TEXT) continue;
|
|
11748
|
+
const key2 = `${fgName}|${surface}|${fg}|${bg}|${page ?? ""}`;
|
|
11749
|
+
const same2 = findings.get(key2);
|
|
11750
|
+
if (same2) {
|
|
11751
|
+
same2.schemes.push(scheme);
|
|
11752
|
+
continue;
|
|
11753
|
+
}
|
|
11754
|
+
const opposite = page !== void 0 && onLightSide(page) !== onLightSide(opaqueBg);
|
|
11755
|
+
const noSingle = page !== void 0 && opposite && contrastRatio(page, opaqueBg) < AA_TEXT * AA_TEXT;
|
|
11756
|
+
const suggestion = noSingle ? void 0 : sameHueClearingAll(painted, page ? [page, opaqueBg] : [opaqueBg]);
|
|
11757
|
+
const measured = (c) => page ? `${contrastRatio(c, opaqueBg).toFixed(2)}:1 on ${surface}, ${contrastRatio(c, page).toFixed(2)}:1 on surfacePrimary` : `${contrastRatio(c, opaqueBg).toFixed(2)}:1`;
|
|
11758
|
+
const restructure = ` Move ${surface} to the page's side of mid-grey (a ${page && onLightSide(page) ? "light" : "dark"} ${surface} on this page), or scope an explicit accent for that section with \`modifiers.theme\` (e.g. { "colors": { "accentText": "#RRGGBB" } } on the card).`;
|
|
11759
|
+
const fix = noSingle ? ` surfacePrimary (${page}) and ${surface} (${opaqueBg}) sit on opposite sides of mid-grey, so no single accent text colour can clear ${AA_TEXT}:1 on both.${restructure}` : suggestion ? ` A same-hue ${fgName} that clears it${page ? " and the page" : ""} is ${suggestion} (${measured(suggestion)}).` + (opposite ? ` The page and ${surface} sit on opposite sides of mid-grey, so only a narrow mid-tone clears both.${restructure}` : "") : ` No ${fgName} of this hue clears ${AA_TEXT}:1 on ${surface}${page ? " and the page" : ""}.` + (opposite ? restructure : "");
|
|
11760
|
+
findings.set(key2, {
|
|
11761
|
+
key: key2,
|
|
11762
|
+
schemes: [scheme],
|
|
11763
|
+
render: (schemes) => `colors.${fgName} (${fg}) on colors.${surface} (${bg}) is ${ratio.toFixed(2)}:1 in ${schemes.join(" / ")} \u2014 below the WCAG AA ${AA_TEXT}:1 for text. ${fgName} is ${role}, and a transparent label \u2014 a plain or link button, an inline action \u2014 has no background of its own, so inside a card or sheet it is read against ${surface}, not the page.${fix}`
|
|
11764
|
+
});
|
|
11765
|
+
}
|
|
11766
|
+
}
|
|
11767
|
+
}
|
|
11768
|
+
var AA_TEXT, CONTRAST_PAIRS, SCHEMES, channels, toHex2, mixHex, onLightSide;
|
|
11543
11769
|
var init_token_lint = __esm({
|
|
11544
11770
|
"src/token-lint.ts"() {
|
|
11545
11771
|
init_token_colors();
|
|
11546
11772
|
init_idiom();
|
|
11773
|
+
init_brand_color_math();
|
|
11547
11774
|
AA_TEXT = 4.5;
|
|
11548
11775
|
CONTRAST_PAIRS = [
|
|
11549
11776
|
{
|
|
@@ -11559,11 +11786,12 @@ var init_token_lint = __esm({
|
|
|
11559
11786
|
];
|
|
11560
11787
|
SCHEMES = ["light", "dark", "highContrast"];
|
|
11561
11788
|
channels = (hex2) => [1, 3, 5].map((i) => parseInt(hex2.slice(i, i + 2), 16));
|
|
11562
|
-
|
|
11789
|
+
toHex2 = (rgb) => `#${rgb.map((c) => Math.round(Math.min(255, Math.max(0, c))).toString(16).padStart(2, "0")).join("")}`.toUpperCase();
|
|
11563
11790
|
mixHex = (a, b, w) => {
|
|
11564
11791
|
const [ca, cb] = [channels(a), channels(b)];
|
|
11565
|
-
return
|
|
11792
|
+
return toHex2(ca.map((c, i) => c * w + cb[i] * (1 - w)));
|
|
11566
11793
|
};
|
|
11794
|
+
onLightSide = (hex2) => contrastRatio("#000000", hex2) >= contrastRatio("#FFFFFF", hex2);
|
|
11567
11795
|
}
|
|
11568
11796
|
});
|
|
11569
11797
|
|
|
@@ -12332,7 +12560,7 @@ function luminance([r, g, b]) {
|
|
|
12332
12560
|
});
|
|
12333
12561
|
return 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2];
|
|
12334
12562
|
}
|
|
12335
|
-
function
|
|
12563
|
+
function contrastRatio3(a, b) {
|
|
12336
12564
|
const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x);
|
|
12337
12565
|
return (hi + 0.05) / (lo + 0.05);
|
|
12338
12566
|
}
|
|
@@ -12341,11 +12569,11 @@ async function contrastingBackdrop(mark, requested) {
|
|
|
12341
12569
|
const { dominant } = await sharp(mark).stats();
|
|
12342
12570
|
const ink = [dominant.r, dominant.g, dominant.b];
|
|
12343
12571
|
const want = hexToRgb(requested);
|
|
12344
|
-
if (!want ||
|
|
12572
|
+
if (!want || contrastRatio3(ink, want) >= MIN_BACKDROP_CONTRAST) return requested;
|
|
12345
12573
|
const towardsWhite = luminance(ink) < 0.5;
|
|
12346
12574
|
for (const amount of [0.35, 0.55, 0.75, 0.9]) {
|
|
12347
|
-
const candidate =
|
|
12348
|
-
if (
|
|
12575
|
+
const candidate = mix2(want, towardsWhite ? [255, 255, 255] : [0, 0, 0], amount);
|
|
12576
|
+
if (contrastRatio3(ink, candidate) >= MIN_BACKDROP_CONTRAST) return rgbToHex(candidate);
|
|
12349
12577
|
}
|
|
12350
12578
|
return towardsWhite ? "#FFFFFF" : "#000000";
|
|
12351
12579
|
}
|
|
@@ -12355,7 +12583,7 @@ function hexToRgb(hex2) {
|
|
|
12355
12583
|
const n = parseInt(m[1], 16);
|
|
12356
12584
|
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
12357
12585
|
}
|
|
12358
|
-
function
|
|
12586
|
+
function mix2(a, b, t) {
|
|
12359
12587
|
return [0, 1, 2].map((i) => Math.round(a[i] + (b[i] - a[i]) * t));
|
|
12360
12588
|
}
|
|
12361
12589
|
function rgbToHex([r, g, b]) {
|
|
@@ -54671,177 +54899,6 @@ var init_tokens3 = __esm({
|
|
|
54671
54899
|
}
|
|
54672
54900
|
});
|
|
54673
54901
|
|
|
54674
|
-
// ../../core/ts/src/brand-color-math.ts
|
|
54675
|
-
function channel2(hex2, offset) {
|
|
54676
|
-
return Number.parseInt(hex2.slice(offset, offset + 2), 16);
|
|
54677
|
-
}
|
|
54678
|
-
function toHex2(r, g, b) {
|
|
54679
|
-
return `#${[r, g, b].map((value) => Math.round(value).toString(16).padStart(2, "0")).join("")}`.toUpperCase();
|
|
54680
|
-
}
|
|
54681
|
-
function mix2(color, background, colorWeight) {
|
|
54682
|
-
const values = [1, 3, 5].map((offset) => channel2(color, offset) * colorWeight + channel2(background, offset) * (1 - colorWeight));
|
|
54683
|
-
return toHex2(values[0], values[1], values[2]);
|
|
54684
|
-
}
|
|
54685
|
-
function relativeLuminance2(color) {
|
|
54686
|
-
const linear = [1, 3, 5].map((offset) => {
|
|
54687
|
-
const value = channel2(color, offset) / 255;
|
|
54688
|
-
return value <= 0.03928 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
|
|
54689
|
-
});
|
|
54690
|
-
return 0.2126 * linear[0] + 0.7152 * linear[1] + 0.0722 * linear[2];
|
|
54691
|
-
}
|
|
54692
|
-
function contrastRatio3(a, b) {
|
|
54693
|
-
const la = relativeLuminance2(a);
|
|
54694
|
-
const lb = relativeLuminance2(b);
|
|
54695
|
-
return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
|
|
54696
|
-
}
|
|
54697
|
-
function lstar(color) {
|
|
54698
|
-
const y = relativeLuminance2(color);
|
|
54699
|
-
return y <= 8856e-6 ? y * 903.3 : 116 * Math.cbrt(y) - 16;
|
|
54700
|
-
}
|
|
54701
|
-
function deriveAccentSurface(accent, surface, weight) {
|
|
54702
|
-
const tint = mix2(accent, surface, weight);
|
|
54703
|
-
if (contrastRatio3(tint, surface) >= ACCENT_SURFACE_MIN_DELTA) return tint;
|
|
54704
|
-
const away = relativeLuminance2(surface) < 0.5 ? "#FFFFFF" : "#000000";
|
|
54705
|
-
for (let w = 0.02; w <= 0.5; w += 0.02) {
|
|
54706
|
-
const candidate = mix2(away, surface, w);
|
|
54707
|
-
if (contrastRatio3(candidate, surface) >= ACCENT_SURFACE_MIN_DELTA) return candidate;
|
|
54708
|
-
}
|
|
54709
|
-
return tint;
|
|
54710
|
-
}
|
|
54711
|
-
function deriveSecondaryAccent(primary) {
|
|
54712
|
-
const shade2 = mix2(primary, "#000000", SECONDARY_SHADE_WEIGHT);
|
|
54713
|
-
if (lstar(shade2) >= SECONDARY_MIN_LSTAR) return shade2;
|
|
54714
|
-
return mix2(primary, "#FFFFFF", SECONDARY_SHADE_WEIGHT);
|
|
54715
|
-
}
|
|
54716
|
-
function textOn(color) {
|
|
54717
|
-
const luminance2 = relativeLuminance2(color);
|
|
54718
|
-
const whiteContrast = 1.05 / (luminance2 + 0.05);
|
|
54719
|
-
const blackContrast = (luminance2 + 0.05) / 0.05;
|
|
54720
|
-
return whiteContrast >= blackContrast ? "#FFFFFF" : "#000000";
|
|
54721
|
-
}
|
|
54722
|
-
function tuneDarkAccent(brand, darkSurface, lightSurface) {
|
|
54723
|
-
const kitInherentlyDark = lstar(lightSurface) < 50;
|
|
54724
|
-
if (kitInherentlyDark && contrastRatio3(brand, darkSurface) >= DARK_ARM_TARGET_CONTRAST && lstar(brand) <= DARK_ARM_LSTAR_CAP) {
|
|
54725
|
-
return brand;
|
|
54726
|
-
}
|
|
54727
|
-
let lift = DARK_ARM_MIN_LIFT;
|
|
54728
|
-
let candidate = mix2(brand, "#FFFFFF", 1 - lift);
|
|
54729
|
-
while (contrastRatio3(candidate, darkSurface) < DARK_ARM_TARGET_CONTRAST && lift < 0.6) {
|
|
54730
|
-
lift += 0.04;
|
|
54731
|
-
candidate = mix2(brand, "#FFFFFF", 1 - lift);
|
|
54732
|
-
}
|
|
54733
|
-
while (lstar(candidate) > DARK_ARM_LSTAR_CAP) {
|
|
54734
|
-
const darker = mix2(candidate, "#000000", 0.94);
|
|
54735
|
-
if (contrastRatio3(darker, darkSurface) < DARK_ARM_FLOOR_CONTRAST) break;
|
|
54736
|
-
candidate = darker;
|
|
54737
|
-
}
|
|
54738
|
-
return candidate;
|
|
54739
|
-
}
|
|
54740
|
-
function textOnArm(accent) {
|
|
54741
|
-
return contrastRatio3("#FFFFFF", accent) >= 4.5 ? "#FFFFFF" : textOn(accent);
|
|
54742
|
-
}
|
|
54743
|
-
function tuneHighContrastAccent(brand, surface) {
|
|
54744
|
-
const towards = relativeLuminance2(surface) < 0.5 ? "#FFFFFF" : "#000000";
|
|
54745
|
-
let candidate = brand;
|
|
54746
|
-
for (let lift = 0; lift <= 0.9 && contrastRatio3(candidate, surface) < HIGH_CONTRAST_TARGET; lift += 0.04) {
|
|
54747
|
-
candidate = mix2(brand, towards, 1 - lift);
|
|
54748
|
-
}
|
|
54749
|
-
return candidate;
|
|
54750
|
-
}
|
|
54751
|
-
function deriveAccentText(accent, surfaces) {
|
|
54752
|
-
const all = (typeof surfaces === "string" ? [surfaces] : [...surfaces]).map((s) => s.slice(0, 7));
|
|
54753
|
-
const page = all[0];
|
|
54754
|
-
const worst = (color) => Math.min(...all.map((s) => contrastRatio3(color, s)));
|
|
54755
|
-
const opaque = accent.length === 9 ? mix2(accent.slice(0, 7), page, channel2(accent, 7) / 255) : accent;
|
|
54756
|
-
if (worst(opaque) >= ACCENT_TEXT_MIN_CONTRAST) return opaque;
|
|
54757
|
-
const pole = worst("#FFFFFF") >= worst("#000000") ? "#FFFFFF" : "#000000";
|
|
54758
|
-
for (let step = 1; step <= 100; step++) {
|
|
54759
|
-
const candidate = mix2(pole, opaque, step / 100);
|
|
54760
|
-
if (worst(candidate) >= ACCENT_TEXT_MIN_CONTRAST) return candidate;
|
|
54761
|
-
}
|
|
54762
|
-
if (all.length > 1) {
|
|
54763
|
-
const side2 = (hex2) => relativeLuminance2(hex2) > MID_GREY_LUMINANCE;
|
|
54764
|
-
const sameSide = all.filter((s) => side2(s) === side2(page));
|
|
54765
|
-
return deriveAccentText(accent, sameSide.length < all.length ? sameSide : [page]);
|
|
54766
|
-
}
|
|
54767
|
-
return pole;
|
|
54768
|
-
}
|
|
54769
|
-
function textSurfacesOf(colors) {
|
|
54770
|
-
const out = { light: [], dark: [], highContrast: [] };
|
|
54771
|
-
for (const name of TEXT_BACKDROP_TOKENS) {
|
|
54772
|
-
const value = colors[name];
|
|
54773
|
-
for (const arm of ["light", "dark", "highContrast"]) {
|
|
54774
|
-
const hex2 = typeof value === "string" ? value : value && typeof value === "object" && !Array.isArray(value) ? value[arm] ?? value.light : void 0;
|
|
54775
|
-
if (typeof hex2 === "string" && hex2.startsWith("#") && hex2.length >= 7) out[arm].push(hex2);
|
|
54776
|
-
}
|
|
54777
|
-
}
|
|
54778
|
-
return out;
|
|
54779
|
-
}
|
|
54780
|
-
function stripBrandFromIdiom(tokens) {
|
|
54781
|
-
const idiom = tokens.idiom;
|
|
54782
|
-
if (!idiom || typeof idiom !== "object" || Array.isArray(idiom)) return;
|
|
54783
|
-
for (const overlay of Object.values(idiom)) {
|
|
54784
|
-
if (!overlay || typeof overlay !== "object" || Array.isArray(overlay)) continue;
|
|
54785
|
-
const o = overlay;
|
|
54786
|
-
const colors = o.colors;
|
|
54787
|
-
if (colors && typeof colors === "object" && !Array.isArray(colors)) {
|
|
54788
|
-
for (const key2 of BRAND_COLOR_TOKENS) delete colors[key2];
|
|
54789
|
-
if (Object.keys(colors).length === 0) delete o.colors;
|
|
54790
|
-
}
|
|
54791
|
-
const shadows = o.shadows;
|
|
54792
|
-
const glow = shadows && typeof shadows === "object" && !Array.isArray(shadows) ? shadows[BRAND_GLOW_SHADOW] : void 0;
|
|
54793
|
-
if (glow && typeof glow === "object" && !Array.isArray(glow) && "color" in glow) {
|
|
54794
|
-
delete glow.color;
|
|
54795
|
-
if (Object.keys(glow).length === 0) delete shadows[BRAND_GLOW_SHADOW];
|
|
54796
|
-
if (Object.keys(shadows).length === 0) delete o.shadows;
|
|
54797
|
-
}
|
|
54798
|
-
}
|
|
54799
|
-
}
|
|
54800
|
-
function deriveAccentFamily(primary, secondary, surfaces, textSurfaces = {}) {
|
|
54801
|
-
const primaryDark = tuneDarkAccent(primary, surfaces.dark, surfaces.light);
|
|
54802
|
-
const secondaryDark = tuneDarkAccent(secondary, surfaces.dark, surfaces.light);
|
|
54803
|
-
const primaryHigh = tuneHighContrastAccent(primary, surfaces.highContrast);
|
|
54804
|
-
const secondaryHigh = tuneHighContrastAccent(secondary, surfaces.highContrast);
|
|
54805
|
-
return {
|
|
54806
|
-
accentPrimary: { light: primary, dark: primaryDark, highContrast: primaryHigh },
|
|
54807
|
-
accentSecondary: { light: secondary, dark: secondaryDark, highContrast: secondaryHigh },
|
|
54808
|
-
accentSurface: {
|
|
54809
|
-
light: deriveAccentSurface(primary, surfaces.light, ACCENT_SURFACE_LIGHT_WEIGHT),
|
|
54810
|
-
dark: deriveAccentSurface(primaryDark, surfaces.dark, 0.24),
|
|
54811
|
-
highContrast: deriveAccentSurface(primaryHigh, surfaces.highContrast, 0.24)
|
|
54812
|
-
},
|
|
54813
|
-
textOnAccent: {
|
|
54814
|
-
light: textOnArm(primary),
|
|
54815
|
-
dark: textOnArm(primaryDark),
|
|
54816
|
-
highContrast: textOn(primaryHigh)
|
|
54817
|
-
},
|
|
54818
|
-
accentText: {
|
|
54819
|
-
light: deriveAccentText(primary, [surfaces.light, ...textSurfaces.light ?? []]),
|
|
54820
|
-
dark: deriveAccentText(primaryDark, [surfaces.dark, ...textSurfaces.dark ?? []]),
|
|
54821
|
-
highContrast: deriveAccentText(primaryHigh, [surfaces.highContrast, ...textSurfaces.highContrast ?? []])
|
|
54822
|
-
}
|
|
54823
|
-
};
|
|
54824
|
-
}
|
|
54825
|
-
var ACCENT_SURFACE_MIN_DELTA, ACCENT_SURFACE_LIGHT_WEIGHT, SECONDARY_SHADE_WEIGHT, SECONDARY_MIN_LSTAR, DARK_ARM_MIN_LIFT, DARK_ARM_TARGET_CONTRAST, DARK_ARM_FLOOR_CONTRAST, DARK_ARM_LSTAR_CAP, HIGH_CONTRAST_TARGET, ACCENT_TEXT_MIN_CONTRAST, MID_GREY_LUMINANCE, TEXT_BACKDROP_TOKENS, BRAND_COLOR_TOKENS, BRAND_GLOW_SHADOW;
|
|
54826
|
-
var init_brand_color_math = __esm({
|
|
54827
|
-
"../../core/ts/src/brand-color-math.ts"() {
|
|
54828
|
-
ACCENT_SURFACE_MIN_DELTA = 1.08;
|
|
54829
|
-
ACCENT_SURFACE_LIGHT_WEIGHT = 0.12;
|
|
54830
|
-
SECONDARY_SHADE_WEIGHT = 0.72;
|
|
54831
|
-
SECONDARY_MIN_LSTAR = 22;
|
|
54832
|
-
DARK_ARM_MIN_LIFT = 0.08;
|
|
54833
|
-
DARK_ARM_TARGET_CONTRAST = 3.4;
|
|
54834
|
-
DARK_ARM_FLOOR_CONTRAST = 3;
|
|
54835
|
-
DARK_ARM_LSTAR_CAP = 80;
|
|
54836
|
-
HIGH_CONTRAST_TARGET = 8.5;
|
|
54837
|
-
ACCENT_TEXT_MIN_CONTRAST = 4.5;
|
|
54838
|
-
MID_GREY_LUMINANCE = 0.179;
|
|
54839
|
-
TEXT_BACKDROP_TOKENS = ["surfaceSecondary", "surfaceElevated", "surfaceSubtle", "surfaceTertiary"];
|
|
54840
|
-
BRAND_COLOR_TOKENS = ["accentPrimary", "accentSecondary", "accentSurface", "textOnAccent", "accentText"];
|
|
54841
|
-
BRAND_GLOW_SHADOW = "glow";
|
|
54842
|
-
}
|
|
54843
|
-
});
|
|
54844
|
-
|
|
54845
54902
|
// src/site-analyze/branding-derive.ts
|
|
54846
54903
|
function secondBrandColour(wst) {
|
|
54847
54904
|
for (const name of ["--wst-color-fill-accent-2", "--wst-color-fill-accent-3"]) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1052.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
|
|
6
6
|
"keywords": [
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"artifactId": "himalaya-cli"
|
|
66
66
|
}
|
|
67
67
|
},
|
|
68
|
-
"falconPackageHash": "
|
|
68
|
+
"falconPackageHash": "418916efab2e1d4bc74db7d4eeb30ad2b9c0d20534c7d5757fcec730"
|
|
69
69
|
}
|