PluginProbe
Gutenberg / 24.1.0
Gutenberg v24.1.0
24.1.0 24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 All 404 releases
← All changes | build/scripts/theme/index.js +141 -95 23.9.0 → 24.1.0 View file →
@@ -3344,25 +3344,20 @@
3344 3344 }
3345 3345 }
3346 3346 });
3347 3347
3348 + // packages/theme/node_modules/colorjs.io/src/equals.js
3349 + function equals(color1, color2) {
3350 + color1 = getColor(color1);
3351 + color2 = getColor(color2);
3352 + return color1.space === color2.space && color1.alpha === color2.alpha && color1.coords.every((c, i) => c === color2.coords[i]);
3353 + }
3354 +
3348 3355 // packages/theme/node_modules/colorjs.io/src/luminance.js
3349 3356 function getLuminance(color) {
3350 3357 return get(color, [xyz_d65_default, "y"]);
3351 3358 }
3352 3359
3353 - // packages/theme/node_modules/colorjs.io/src/contrast/WCAG21.js
3354 - function contrastWCAG21(color1, color2) {
3355 - color1 = getColor(color1);
3356 - color2 = getColor(color2);
3357 - let Y1 = Math.max(getLuminance(color1), 0);
3358 - let Y2 = Math.max(getLuminance(color2), 0);
3359 - if (Y2 > Y1) {
3360 - [Y1, Y2] = [Y2, Y1];
3361 - }
3362 - return (Y1 + 0.05) / (Y2 + 0.05);
3363 - }
3364 -
3365 3360 // packages/theme/node_modules/colorjs.io/src/spaces/hsl.js
3366 3361 var hsl_default = new ColorSpace({
3367 3362 id: "hsl",
3368 3363 name: "HSL",
@@ -3524,13 +3519,13 @@
3524 3519 "background-interactive-neutral-weak",
3525 3520 "background-interactive-neutral-weak-disabled"
3526 3521 ],
3527 3522 "primary-bgFill1": ["background-interactive-brand-strong"],
3523 + "primary-bgFill2": ["background-interactive-brand-strong-active"],
3528 3524 "primary-fgFill": [
3529 3525 "foreground-interactive-brand-strong",
3530 3526 "foreground-interactive-brand-strong-active"
3531 3527 ],
3532 - "primary-bgFill2": ["background-interactive-brand-strong-active"],
3533 3528 "primary-surface4": ["background-interactive-brand-weak-active"],
3534 3529 "primary-fgSurface4": ["foreground-interactive-brand-active"],
3535 3530 "primary-fgSurface3": ["foreground-interactive-brand"],
3536 3531 "primary-stroke3": [
@@ -3561,13 +3556,13 @@
3561 3556 "warning-fgSurface3": ["foreground-content-warning-weak"],
3562 3557 "warning-stroke3": ["stroke-surface-warning-strong"],
3563 3558 "warning-stroke1": ["stroke-surface-warning"],
3564 3559 "error-bgFill1": ["background-interactive-error-strong"],
3560 + "error-bgFill2": ["background-interactive-error-strong-active"],
3565 3561 "error-fgFill": [
3566 3562 "foreground-interactive-error-strong",
3567 3563 "foreground-interactive-error-strong-active"
3568 3564 ],
3569 - "error-bgFill2": ["background-interactive-error-strong-active"],
3570 3565 "error-surface2": [
3571 3566 "background-interactive-error-active",
3572 3567 "background-surface-error-weak"
3573 3568 ],
@@ -3596,9 +3591,14 @@
3596 3591 "background-interactive-error-strong-disabled",
3597 3592 "background-interactive-neutral-strong-disabled"
3598 3593 ],
3599 3594 "bg-surface4": ["background-interactive-neutral-weak-active"],
3600 - "bg-surface3": ["background-surface-neutral-strong"],
3595 + "bg-surface3": [
3596 + "background-interactive-neutral",
3597 + "background-interactive-neutral-active",
3598 + "background-interactive-neutral-disabled",
3599 + "background-surface-neutral-strong"
3600 + ],
3601 3601 "bg-fgSurface4": [
3602 3602 "foreground-content-neutral",
3603 3603 "foreground-interactive-neutral",
3604 3604 "foreground-interactive-neutral-active",
@@ -3656,8 +3656,9 @@
3656 3656 };
3657 3657
3658 3658 // packages/theme/build-module/color-ramps/lib/color-utils.mjs
3659 3659 var ALLOWED_SEED_COLOR_SPACES = [srgb_default];
3660 + var objectLuminanceCache = /* @__PURE__ */ new WeakMap();
3660 3661 function getColorString(color) {
3661 3662 ColorSpace.register(srgb_default);
3662 3663 const rgbRounded = serialize(to(color, srgb_default));
3663 3664 return serialize(rgbRounded, { format: "hex" });
@@ -3662,12 +3663,33 @@
3662 3663 const rgbRounded = serialize(to(color, srgb_default));
3663 3664 return serialize(rgbRounded, { format: "hex" });
3664 3665 }
3665 3666 function getContrast(colorA, colorB) {
3666 - ColorSpace.register(srgb_default);
3667 - return contrastWCAG21(colorA, colorB);
3667 + return getContrastFromLuminances(
3668 + getRelativeLuminance(colorA),
3669 + getRelativeLuminance(colorB)
3670 + );
3668 3671 }
3669 - function assertValidSeedColor(seed) {
3672 + function getRelativeLuminance(color) {
3673 + if (typeof color === "string") {
3674 + ColorSpace.register(srgb_default);
3675 + return Math.max(getLuminance(color), 0);
3676 + }
3677 + const cachedLuminance = objectLuminanceCache.get(color);
3678 + if (cachedLuminance && equals(cachedLuminance.color, color)) {
3679 + return cachedLuminance.luminance;
3680 + }
3681 + const luminance = Math.max(getLuminance(color), 0);
3682 + objectLuminanceCache.set(color, {
3683 + color: clone(color),
3684 + luminance
3685 + });
3686 + return luminance;
3687 + }
3688 + function getContrastFromLuminances(first, second) {
3689 + return first > second ? (first + 0.05) / (second + 0.05) : (second + 0.05) / (first + 0.05);
3690 + }
3691 + function parseSeedColor(seed) {
3670 3692 ALLOWED_SEED_COLOR_SPACES.forEach(
3671 3693 (space) => ColorSpace.register(space)
3672 3694 );
3673 3695 let parsedColor;
@@ -3688,11 +3710,11 @@
3688 3710 throw new Error(
3689 3711 `Unsupported seed color "${seed}": expected a fully opaque color.`
3690 3712 );
3691 3713 }
3714 + return parsedColor;
3692 3715 }
3693 3716 function clampToGamut(c) {
3694 - ColorSpace.register(srgb_default);
3695 3717 return to(toGamut(c, { space: srgb_default, method: "css" }), oklch_default);
3696 3718 }
3697 3719
3698 3720 // packages/theme/build-module/color-ramps/lib/constants.mjs
@@ -3736,11 +3758,16 @@
3736 3758 dependents.set(step, []);
3737 3759 });
3738 3760 Object.entries(config).forEach(([stepName, stepConfig]) => {
3739 3761 const step = stepName;
3740 - const reference = stepConfig.contrast.reference;
3741 - dependencies.get(step).push(reference);
3742 - dependents.get(reference).push(step);
3762 + const references = [
3763 + stepConfig.contrast.reference,
3764 + ...stepConfig.contrast.additionalReferences ?? []
3765 + ];
3766 + for (const reference of references) {
3767 + dependencies.get(step).push(reference);
3768 + dependents.get(reference).push(step);
3769 + }
3743 3770 if (stepConfig.sameAsIfPossible) {
3744 3771 dependencies.get(step).push(stepConfig.sameAsIfPossible);
3745 3772 dependents.get(stepConfig.sameAsIfPossible).push(step);
3746 3773 }
@@ -3787,8 +3814,9 @@
3787 3814 if (!stepConfig) {
3788 3815 return;
3789 3816 }
3790 3817 visit(stepConfig.contrast.reference);
3818 + stepConfig.contrast.additionalReferences?.forEach(visit);
3791 3819 if (stepConfig.sameAsIfPossible) {
3792 3820 visit(stepConfig.sameAsIfPossible);
3793 3821 }
3794 3822 result.add(step);
@@ -3795,11 +3823,20 @@
3795 3823 }
3796 3824 visit(stepName);
3797 3825 return Array.from(result);
3798 3826 }
3799 - function computeBetterFgColorDirection(seed, preferLighter) {
3800 - const contrastAgainstBlack = getContrast(seed, BLACK);
3801 - const contrastAgainstWhite = getContrast(seed, WHITE);
3827 + function computeBetterFgColorDirection(references, preferLighter) {
3828 + const referenceColors = Array.isArray(references) ? references : [references];
3829 + const contrastAgainstBlack = Math.min(
3830 + ...referenceColors.map(
3831 + (reference) => getContrast(reference, BLACK)
3832 + )
3833 + );
3834 + const contrastAgainstWhite = Math.min(
3835 + ...referenceColors.map(
3836 + (reference) => getContrast(reference, WHITE)
3837 + )
3838 + );
3802 3839 return contrastAgainstBlack > contrastAgainstWhite + (preferLighter ? WHITE_TEXT_CONTRAST_MARGIN : 0) ? { better: "darker", worse: "lighter" } : { better: "lighter", worse: "darker" };
3803 3840 }
3804 3841 function adjustContrastTarget(target) {
3805 3842 if (target === 1) {
@@ -3850,13 +3887,12 @@
3850 3887 return bestC;
3851 3888 }
3852 3889
3853 3890 // packages/theme/build-module/color-ramps/lib/taper-chroma.mjs
3854 - function taperChroma(seed, lTarget, options = {}) {
3891 + function createChromaTaper(seed, options = {}) {
3855 3892 const gamut = options.gamut ?? srgb_default;
3856 3893 const alpha = options.alpha ?? 0.65;
3857 3894 const carry = options.carry ?? 0.5;
3858 - const cUpperBound = options.cUpperBound ?? 0.45;
3859 3895 const radiusLight = options.radiusLight ?? 0.2;
3860 3896 const radiusDark = options.radiusDark ?? 0.2;
3861 3897 const kLight = options.kLight ?? 0.85;
3862 3898 const kDark = options.kDark ?? 0.85;
@@ -3868,37 +3904,34 @@
3868 3904 if (chromaIsTiny || hueIsInvalid) {
3869 3905 if (typeof options.hueFallback === "number") {
3870 3906 hSeed = normalizeHue(options.hueFallback);
3871 3907 } else {
3872 - return {
3908 + return (lTarget) => ({
3873 3909 space: oklch_default,
3874 3910 coords: [clamp01(lTarget), 0, 0],
3875 3911 alpha: 1
3876 - };
3912 + });
3877 3913 }
3878 3914 }
3879 3915 const lSeed = clamp01(get(seed, [oklch_default, "l"]));
3880 - const cmaxSeed = getCachedMaxChromaAtLH(lSeed, hSeed, gamut, cUpperBound);
3881 - const cmaxTarget = getCachedMaxChromaAtLH(
3882 - clamp01(lTarget),
3883 - hSeed,
3884 - gamut,
3885 - cUpperBound
3886 - );
3887 - let seedRelative = 0;
3916 + const cmaxSeed = getMaxChromaAtLH(lSeed, hSeed, gamut);
3888 3917 const denom = cmaxSeed > 0 ? cmaxSeed : 1e-6;
3889 - seedRelative = clamp01(cSeed / denom);
3890 - const cIntendedBase = alpha * cmaxTarget;
3891 - const cWithCarry = cIntendedBase * Math.pow(seedRelative, clamp01(carry));
3892 - const t = continuousTaper(lSeed, lTarget, {
3893 - radiusLight,
3894 - radiusDark,
3895 - kLight,
3896 - kDark
3897 - });
3898 - const cPlanned = cWithCarry * t;
3899 - const lOut = clamp01(lTarget);
3900 - return { l: lOut, c: cPlanned };
3918 + const seedRelative = clamp01(cSeed / denom);
3919 + const seedCarry = Math.pow(seedRelative, clamp01(carry));
3920 + return (lTarget) => {
3921 + const cmaxTarget = getMaxChromaAtLH(clamp01(lTarget), hSeed, gamut);
3922 + const cIntendedBase = alpha * cmaxTarget;
3923 + const cWithCarry = cIntendedBase * seedCarry;
3924 + const t = continuousTaper(lSeed, lTarget, {
3925 + radiusLight,
3926 + radiusDark,
3927 + kLight,
3928 + kDark
3929 + });
3930 + const cPlanned = cWithCarry * t;
3931 + const lOut = clamp01(lTarget);
3932 + return { l: lOut, c: cPlanned };
3933 + };
3901 3934 }
3902 3935 function clamp01(x) {
3903 3936 if (x < 0) {
3904 3937 return 0;
@@ -3929,34 +3962,13 @@
3929 3962 const u = opts.radiusDark > 0 ? Math.abs(d2) / opts.radiusDark : 1;
3930 3963 const w = raisedCosine(u > 1 ? 1 : u);
3931 3964 return 1 - (1 - opts.kDark) * w;
3932 3965 }
3933 - var maxChromaCache = /* @__PURE__ */ new Map();
3934 - function keyMax(l, h, gamut, cap) {
3935 - const lq = quantize(l, 0.05);
3936 - const hq = quantize(normalizeHue(h), 10);
3937 - const cq = quantize(cap, 0.05);
3938 - return `${gamut}|L:${lq}|H:${hq}|cap:${cq}`;
3939 - }
3940 - function quantize(x, step) {
3941 - const k = Math.round(x / step);
3942 - return k * step;
3943 - }
3944 - function getCachedMaxChromaAtLH(l, h, gamutSpace, cap) {
3945 - const gamut = gamutSpace.id;
3946 - const key = keyMax(l, h, gamut, cap);
3947 - const hit = maxChromaCache.get(key);
3948 - if (typeof hit === "number") {
3949 - return hit;
3950 - }
3951 - const computed = maxInGamutChromaAtLH(l, h, gamutSpace, cap);
3952 - maxChromaCache.set(key, computed);
3953 - return computed;
3954 - }
3955 - function maxInGamutChromaAtLH(l, h, gamutSpace, cap) {
3966 + var MAX_CHROMA = 0.45;
3967 + function getMaxChromaAtLH(l, h, gamutSpace) {
3956 3968 const probe = {
3957 3969 space: oklch_default,
3958 - coords: [l, cap, h],
3970 + coords: [clamp01(l), MAX_CHROMA, normalizeHue(h)],
3959 3971 alpha: 1
3960 3972 };
3961 3973 const clamped = toGamutCSS(probe, { space: gamutSpace });
3962 3974 return get(clamped, [oklch_default, "c"]);
@@ -3976,13 +3988,16 @@
3976 3988 reached: true,
3977 3989 achieved: 1
3978 3990 };
3979 3991 }
3992 + const seedChroma = get(seed, [oklch_default, "c"]);
3993 + const seedHue = get(seed, [oklch_default, "h"]);
3994 + const taperChromaAtLightness = taperChromaOptions ? createChromaTaper(seed, taperChromaOptions) : void 0;
3980 3995 function getColorForL(l) {
3981 3996 let newL = l;
3982 - let newC = get(seed, [oklch_default, "c"]);
3983 - if (taperChromaOptions) {
3984 - const tapered = taperChroma(seed, newL, taperChromaOptions);
3997 + let newC = seedChroma;
3998 + if (taperChromaAtLightness) {
3999 + const tapered = taperChromaAtLightness(newL);
3985 4000 if ("l" in tapered && "c" in tapered) {
3986 4001 newL = tapered.l;
3987 4002 newC = tapered.c;
3988 4003 } else {
@@ -3990,9 +4005,9 @@
3990 4005 }
3991 4006 }
3992 4007 return clampToGamut({
3993 4008 space: oklch_default,
3994 - coords: [newL, newC, get(seed, [oklch_default, "h"])],
4009 + coords: [newL, newC, seedHue],
3995 4010 alpha: seed.alpha
3996 4011 });
3997 4012 }
3998 4013 const mostContrastingL = direction === "lighter" ? 1 : 0;
@@ -4056,9 +4071,9 @@
4056 4071 let maxDeficitStep;
4057 4072 const calculatedColors = /* @__PURE__ */ new Map();
4058 4073 calculatedColors.set("seed", seed);
4059 4074 for (const stepName of sortedSteps) {
4060 - let computeDirection2 = function(color, followDirection) {
4075 + let computeDirection2 = function(colors, followDirection) {
4061 4076 if (followDirection === "main") {
4062 4077 return mainDir;
4063 4078 }
4064 4079 if (followDirection === "opposite") {
@@ -4065,9 +4080,9 @@
4065 4080 return oppDir;
4066 4081 }
4067 4082 if (followDirection === "best") {
4068 4083 return computeBetterFgColorDirection(
4069 - color,
4084 + colors,
4070 4085 contrast.preferLighter
4071 4086 ).better;
4072 4087 }
4073 4088 return followDirection;
@@ -4078,14 +4093,21 @@
4078 4093 lightness: stepLightnessConstraint,
4079 4094 taperChromaOptions,
4080 4095 sameAsIfPossible
4081 4096 } = config[stepName];
4082 - const referenceColor = calculatedColors.get(contrast.reference);
4083 - if (!referenceColor) {
4084 - throw new Error(
4085 - `Reference color for step ${stepName} not found: ${contrast.reference}`
4086 - );
4087 - }
4097 + const referenceNames = [
4098 + contrast.reference,
4099 + ...contrast.additionalReferences ?? []
4100 + ];
4101 + const referenceColors = referenceNames.map((referenceName) => {
4102 + const referenceColor2 = calculatedColors.get(referenceName);
4103 + if (!referenceColor2) {
4104 + throw new Error(
4105 + `Reference color for step ${stepName} not found: ${referenceName}`
4106 + );
4107 + }
4108 + return referenceColor2;
4109 + });
4088 4110 if (sameAsIfPossible) {
4089 4111 const candidateColor = calculatedColors.get(sameAsIfPossible);
4090 4112 if (!candidateColor) {
4091 4113 throw new Error(
@@ -4091,14 +4113,13 @@
4091 4113 throw new Error(
4092 4114 `Same-as color for step ${stepName} not found: ${sameAsIfPossible}`
4093 4115 );
4094 4116 }
4095 - const candidateContrast = getContrast(
4096 - referenceColor,
4097 - candidateColor
4117 + const adjustedTarget2 = adjustContrastTarget(contrast.target);
4118 + const candidateMeetsTarget = referenceColors.every(
4119 + (referenceColor2) => getContrast(referenceColor2, candidateColor) >= adjustedTarget2
4098 4120 );
4099 - const adjustedTarget2 = adjustContrastTarget(contrast.target);
4100 - if (candidateContrast >= adjustedTarget2) {
4121 + if (candidateMeetsTarget) {
4101 4122 calculatedColors.set(stepName, candidateColor);
4102 4123 rampResults[stepName] = getColorString(candidateColor);
4103 4124 continue;
4104 4125 }
@@ -4103,11 +4124,15 @@
4103 4124 continue;
4104 4125 }
4105 4126 }
4106 4127 const computedDir = computeDirection2(
4107 - referenceColor,
4128 + referenceColors,
4108 4129 contrast.followDirection
4109 4130 );
4131 + const endpoint = computedDir === "lighter" ? WHITE : BLACK;
4132 + const referenceColor = referenceColors.reduce(
4133 + (tightest, current) => getContrast(current, endpoint) < getContrast(tightest, endpoint) ? current : tightest
4134 + );
4110 4135 const adjustedTarget = adjustContrastTarget(contrast.target);
4111 4136 let lightnessConstraint;
4112 4137 if (pinLightness?.stepName === stepName) {
4113 4138 lightnessConstraint = {
@@ -4154,12 +4179,12 @@
4154 4179 mainDirection,
4155 4180 pinLightness,
4156 4181 rescaleToFitContrastTargets = true
4157 4182 } = {}) {
4158 - assertValidSeedColor(seedArg);
4183 + const parsedSeed = parseSeedColor(seedArg);
4159 4184 let seed;
4160 4185 try {
4161 - seed = clampToGamut(seedArg);
4186 + seed = clampToGamut(parsedSeed);
4162 4187 } catch (error) {
4163 4188 throw new Error(
4164 4189 `Invalid seed color "${seedArg}": ${error instanceof Error ? error.message : "Unknown error"}`
4165 4190 );
@@ -4427,11 +4452,12 @@
4427 4452 // fgFill
4428 4453 fgFill: {
4429 4454 contrast: {
4430 4455 reference: "bgFill1",
4456 + additionalReferences: ["bgFill2"],
4431 4457 followDirection: "best",
4432 - target: 4.5,
4433 - preferLighter: true
4458 + // Preserve the 4.5:1 WCAG floor after 8-bit sRGB serialization.
4459 + target: 4.55
4434 4460 },
4435 4461 lightness: lightnessConstraintForegroundHighContrast,
4436 4462 taperChromaOptions: FG_TAPER_CHROMA
4437 4463 },
@@ -4559,8 +4585,28 @@
4559 4585
4560 4586 // packages/theme/build-module/semantic-color-contrast-pairs.mjs
4561 4587 var MINIMUM_TEXT_CONTRAST = 4.5;
4562 4588 var SEMANTIC_COLOR_CONTRAST_PAIRS = [
4589 + {
4590 + background: "background.interactive.neutral",
4591 + foreground: "foreground.interactive.neutral"
4592 + },
4593 + {
4594 + background: "background.interactive.neutral",
4595 + foreground: "foreground.interactive.neutral-weak"
4596 + },
4597 + {
4598 + background: "background.interactive.neutral-active",
4599 + foreground: "foreground.interactive.neutral"
4600 + },
4601 + {
4602 + background: "background.interactive.neutral-active",
4603 + foreground: "foreground.interactive.neutral-weak"
4604 + },
4605 + {
4606 + background: "background.interactive.neutral-weak-active",
4607 + foreground: "foreground.interactive.neutral-active"
4608 + },
4563 4609 {
4564 4610 background: "background.surface.neutral",
4565 4611 foreground: "foreground.content.neutral"
4566 4612 },