PluginProbe
Gutenberg / trunk
Gutenberg vtrunk
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 +365 -138 23.8.0 → trunk View file →
@@ -1,5 +1,6 @@
1 1 (function() {
2 +"use strict";
2 3 var wp;
3 4 (wp ||= {}).theme = (() => {
4 5 var __create = Object.create;
5 6 var __defProp = Object.defineProperty;
@@ -3343,25 +3344,20 @@
3343 3344 }
3344 3345 }
3345 3346 });
3346 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 +
3347 3355 // packages/theme/node_modules/colorjs.io/src/luminance.js
3348 3356 function getLuminance(color) {
3349 3357 return get(color, [xyz_d65_default, "y"]);
3350 3358 }
3351 3359
3352 - // packages/theme/node_modules/colorjs.io/src/contrast/WCAG21.js
3353 - function contrastWCAG21(color1, color2) {
3354 - color1 = getColor(color1);
3355 - color2 = getColor(color2);
3356 - let Y1 = Math.max(getLuminance(color1), 0);
3357 - let Y2 = Math.max(getLuminance(color2), 0);
3358 - if (Y2 > Y1) {
3359 - [Y1, Y2] = [Y2, Y1];
3360 - }
3361 - return (Y1 + 0.05) / (Y2 + 0.05);
3362 - }
3363 -
3364 3360 // packages/theme/node_modules/colorjs.io/src/spaces/hsl.js
3365 3361 var hsl_default = new ColorSpace({
3366 3362 id: "hsl",
3367 3363 name: "HSL",
@@ -3523,13 +3519,13 @@
3523 3519 "background-interactive-neutral-weak",
3524 3520 "background-interactive-neutral-weak-disabled"
3525 3521 ],
3526 3522 "primary-bgFill1": ["background-interactive-brand-strong"],
3523 + "primary-bgFill2": ["background-interactive-brand-strong-active"],
3527 3524 "primary-fgFill": [
3528 3525 "foreground-interactive-brand-strong",
3529 3526 "foreground-interactive-brand-strong-active"
3530 3527 ],
3531 - "primary-bgFill2": ["background-interactive-brand-strong-active"],
3532 3528 "primary-surface4": ["background-interactive-brand-weak-active"],
3533 3529 "primary-fgSurface4": ["foreground-interactive-brand-active"],
3534 3530 "primary-fgSurface3": ["foreground-interactive-brand"],
3535 3531 "primary-stroke3": [
@@ -3560,13 +3556,13 @@
3560 3556 "warning-fgSurface3": ["foreground-content-warning-weak"],
3561 3557 "warning-stroke3": ["stroke-surface-warning-strong"],
3562 3558 "warning-stroke1": ["stroke-surface-warning"],
3563 3559 "error-bgFill1": ["background-interactive-error-strong"],
3560 + "error-bgFill2": ["background-interactive-error-strong-active"],
3564 3561 "error-fgFill": [
3565 3562 "foreground-interactive-error-strong",
3566 3563 "foreground-interactive-error-strong-active"
3567 3564 ],
3568 - "error-bgFill2": ["background-interactive-error-strong-active"],
3569 3565 "error-surface2": [
3570 3566 "background-interactive-error-active",
3571 3567 "background-surface-error-weak"
3572 3568 ],
@@ -3595,9 +3591,14 @@
3595 3591 "background-interactive-error-strong-disabled",
3596 3592 "background-interactive-neutral-strong-disabled"
3597 3593 ],
3598 3594 "bg-surface4": ["background-interactive-neutral-weak-active"],
3599 - "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 + ],
3600 3601 "bg-fgSurface4": [
3601 3602 "foreground-content-neutral",
3602 3603 "foreground-interactive-neutral",
3603 3604 "foreground-interactive-neutral-active",
@@ -3655,8 +3656,9 @@
3655 3656 };
3656 3657
3657 3658 // packages/theme/build-module/color-ramps/lib/color-utils.mjs
3658 3659 var ALLOWED_SEED_COLOR_SPACES = [srgb_default];
3660 + var objectLuminanceCache = /* @__PURE__ */ new WeakMap();
3659 3661 function getColorString(color) {
3660 3662 ColorSpace.register(srgb_default);
3661 3663 const rgbRounded = serialize(to(color, srgb_default));
3662 3664 return serialize(rgbRounded, { format: "hex" });
@@ -3661,12 +3663,33 @@
3661 3663 const rgbRounded = serialize(to(color, srgb_default));
3662 3664 return serialize(rgbRounded, { format: "hex" });
3663 3665 }
3664 3666 function getContrast(colorA, colorB) {
3665 - ColorSpace.register(srgb_default);
3666 - return contrastWCAG21(colorA, colorB);
3667 + return getContrastFromLuminances(
3668 + getRelativeLuminance(colorA),
3669 + getRelativeLuminance(colorB)
3670 + );
3667 3671 }
3668 - 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) {
3669 3692 ALLOWED_SEED_COLOR_SPACES.forEach(
3670 3693 (space) => ColorSpace.register(space)
3671 3694 );
3672 3695 let parsedColor;
@@ -3687,11 +3710,11 @@
3687 3710 throw new Error(
3688 3711 `Unsupported seed color "${seed}": expected a fully opaque color.`
3689 3712 );
3690 3713 }
3714 + return parsedColor;
3691 3715 }
3692 3716 function clampToGamut(c) {
3693 - ColorSpace.register(srgb_default);
3694 3717 return to(toGamut(c, { space: srgb_default, method: "css" }), oklch_default);
3695 3718 }
3696 3719
3697 3720 // packages/theme/build-module/color-ramps/lib/constants.mjs
@@ -3735,11 +3758,16 @@
3735 3758 dependents.set(step, []);
3736 3759 });
3737 3760 Object.entries(config).forEach(([stepName, stepConfig]) => {
3738 3761 const step = stepName;
3739 - const reference = stepConfig.contrast.reference;
3740 - dependencies.get(step).push(reference);
3741 - 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 + }
3742 3770 if (stepConfig.sameAsIfPossible) {
3743 3771 dependencies.get(step).push(stepConfig.sameAsIfPossible);
3744 3772 dependents.get(stepConfig.sameAsIfPossible).push(step);
3745 3773 }
@@ -3786,8 +3814,9 @@
3786 3814 if (!stepConfig) {
3787 3815 return;
3788 3816 }
3789 3817 visit(stepConfig.contrast.reference);
3818 + stepConfig.contrast.additionalReferences?.forEach(visit);
3790 3819 if (stepConfig.sameAsIfPossible) {
3791 3820 visit(stepConfig.sameAsIfPossible);
3792 3821 }
3793 3822 result.add(step);
@@ -3794,11 +3823,20 @@
3794 3823 }
3795 3824 visit(stepName);
3796 3825 return Array.from(result);
3797 3826 }
3798 - function computeBetterFgColorDirection(seed, preferLighter) {
3799 - const contrastAgainstBlack = getContrast(seed, BLACK);
3800 - 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 + );
3801 3839 return contrastAgainstBlack > contrastAgainstWhite + (preferLighter ? WHITE_TEXT_CONTRAST_MARGIN : 0) ? { better: "darker", worse: "lighter" } : { better: "lighter", worse: "darker" };
3802 3840 }
3803 3841 function adjustContrastTarget(target) {
3804 3842 if (target === 1) {
@@ -3849,13 +3887,12 @@
3849 3887 return bestC;
3850 3888 }
3851 3889
3852 3890 // packages/theme/build-module/color-ramps/lib/taper-chroma.mjs
3853 - function taperChroma(seed, lTarget, options = {}) {
3891 + function createChromaTaper(seed, options = {}) {
3854 3892 const gamut = options.gamut ?? srgb_default;
3855 3893 const alpha = options.alpha ?? 0.65;
3856 3894 const carry = options.carry ?? 0.5;
3857 - const cUpperBound = options.cUpperBound ?? 0.45;
3858 3895 const radiusLight = options.radiusLight ?? 0.2;
3859 3896 const radiusDark = options.radiusDark ?? 0.2;
3860 3897 const kLight = options.kLight ?? 0.85;
3861 3898 const kDark = options.kDark ?? 0.85;
@@ -3867,37 +3904,34 @@
3867 3904 if (chromaIsTiny || hueIsInvalid) {
3868 3905 if (typeof options.hueFallback === "number") {
3869 3906 hSeed = normalizeHue(options.hueFallback);
3870 3907 } else {
3871 - return {
3908 + return (lTarget) => ({
3872 3909 space: oklch_default,
3873 3910 coords: [clamp01(lTarget), 0, 0],
3874 3911 alpha: 1
3875 - };
3912 + });
3876 3913 }
3877 3914 }
3878 3915 const lSeed = clamp01(get(seed, [oklch_default, "l"]));
3879 - const cmaxSeed = getCachedMaxChromaAtLH(lSeed, hSeed, gamut, cUpperBound);
3880 - const cmaxTarget = getCachedMaxChromaAtLH(
3881 - clamp01(lTarget),
3882 - hSeed,
3883 - gamut,
3884 - cUpperBound
3885 - );
3886 - let seedRelative = 0;
3916 + const cmaxSeed = getMaxChromaAtLH(lSeed, hSeed, gamut);
3887 3917 const denom = cmaxSeed > 0 ? cmaxSeed : 1e-6;
3888 - seedRelative = clamp01(cSeed / denom);
3889 - const cIntendedBase = alpha * cmaxTarget;
3890 - const cWithCarry = cIntendedBase * Math.pow(seedRelative, clamp01(carry));
3891 - const t = continuousTaper(lSeed, lTarget, {
3892 - radiusLight,
3893 - radiusDark,
3894 - kLight,
3895 - kDark
3896 - });
3897 - const cPlanned = cWithCarry * t;
3898 - const lOut = clamp01(lTarget);
3899 - 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 + };
3900 3934 }
3901 3935 function clamp01(x) {
3902 3936 if (x < 0) {
3903 3937 return 0;
@@ -3928,34 +3962,13 @@
3928 3962 const u = opts.radiusDark > 0 ? Math.abs(d2) / opts.radiusDark : 1;
3929 3963 const w = raisedCosine(u > 1 ? 1 : u);
3930 3964 return 1 - (1 - opts.kDark) * w;
3931 3965 }
3932 - var maxChromaCache = /* @__PURE__ */ new Map();
3933 - function keyMax(l, h, gamut, cap) {
3934 - const lq = quantize(l, 0.05);
3935 - const hq = quantize(normalizeHue(h), 10);
3936 - const cq = quantize(cap, 0.05);
3937 - return `${gamut}|L:${lq}|H:${hq}|cap:${cq}`;
3938 - }
3939 - function quantize(x, step) {
3940 - const k = Math.round(x / step);
3941 - return k * step;
3942 - }
3943 - function getCachedMaxChromaAtLH(l, h, gamutSpace, cap) {
3944 - const gamut = gamutSpace.id;
3945 - const key = keyMax(l, h, gamut, cap);
3946 - const hit = maxChromaCache.get(key);
3947 - if (typeof hit === "number") {
3948 - return hit;
3949 - }
3950 - const computed = maxInGamutChromaAtLH(l, h, gamutSpace, cap);
3951 - maxChromaCache.set(key, computed);
3952 - return computed;
3953 - }
3954 - function maxInGamutChromaAtLH(l, h, gamutSpace, cap) {
3966 + var MAX_CHROMA = 0.45;
3967 + function getMaxChromaAtLH(l, h, gamutSpace) {
3955 3968 const probe = {
3956 3969 space: oklch_default,
3957 - coords: [l, cap, h],
3970 + coords: [clamp01(l), MAX_CHROMA, normalizeHue(h)],
3958 3971 alpha: 1
3959 3972 };
3960 3973 const clamped = toGamutCSS(probe, { space: gamutSpace });
3961 3974 return get(clamped, [oklch_default, "c"]);
@@ -3975,13 +3988,16 @@
3975 3988 reached: true,
3976 3989 achieved: 1
3977 3990 };
3978 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;
3979 3995 function getColorForL(l) {
3980 3996 let newL = l;
3981 - let newC = get(seed, [oklch_default, "c"]);
3982 - if (taperChromaOptions) {
3983 - const tapered = taperChroma(seed, newL, taperChromaOptions);
3997 + let newC = seedChroma;
3998 + if (taperChromaAtLightness) {
3999 + const tapered = taperChromaAtLightness(newL);
3984 4000 if ("l" in tapered && "c" in tapered) {
3985 4001 newL = tapered.l;
3986 4002 newC = tapered.c;
3987 4003 } else {
@@ -3989,9 +4005,9 @@
3989 4005 }
3990 4006 }
3991 4007 return clampToGamut({
3992 4008 space: oklch_default,
3993 - coords: [newL, newC, get(seed, [oklch_default, "h"])],
4009 + coords: [newL, newC, seedHue],
3994 4010 alpha: seed.alpha
3995 4011 });
3996 4012 }
3997 4013 const mostContrastingL = direction === "lighter" ? 1 : 0;
@@ -4055,9 +4071,9 @@
4055 4071 let maxDeficitStep;
4056 4072 const calculatedColors = /* @__PURE__ */ new Map();
4057 4073 calculatedColors.set("seed", seed);
4058 4074 for (const stepName of sortedSteps) {
4059 - let computeDirection = function(color, followDirection) {
4075 + let computeDirection2 = function(colors, followDirection) {
4060 4076 if (followDirection === "main") {
4061 4077 return mainDir;
4062 4078 }
4063 4079 if (followDirection === "opposite") {
@@ -4064,14 +4080,15 @@
4064 4080 return oppDir;
4065 4081 }
4066 4082 if (followDirection === "best") {
4067 4083 return computeBetterFgColorDirection(
4068 - color,
4084 + colors,
4069 4085 contrast.preferLighter
4070 4086 ).better;
4071 4087 }
4072 4088 return followDirection;
4073 4089 };
4090 + var computeDirection = computeDirection2;
4074 4091 const {
4075 4092 contrast,
4076 4093 lightness: stepLightnessConstraint,
4077 4094 taperChromaOptions,
@@ -4076,14 +4093,21 @@
4076 4093 lightness: stepLightnessConstraint,
4077 4094 taperChromaOptions,
4078 4095 sameAsIfPossible
4079 4096 } = config[stepName];
4080 - const referenceColor = calculatedColors.get(contrast.reference);
4081 - if (!referenceColor) {
4082 - throw new Error(
4083 - `Reference color for step ${stepName} not found: ${contrast.reference}`
4084 - );
4085 - }
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 + });
4086 4110 if (sameAsIfPossible) {
4087 4111 const candidateColor = calculatedColors.get(sameAsIfPossible);
4088 4112 if (!candidateColor) {
4089 4113 throw new Error(
@@ -4089,23 +4113,26 @@
4089 4113 throw new Error(
4090 4114 `Same-as color for step ${stepName} not found: ${sameAsIfPossible}`
4091 4115 );
4092 4116 }
4093 - const candidateContrast = getContrast(
4094 - referenceColor,
4095 - candidateColor
4117 + const adjustedTarget2 = adjustContrastTarget(contrast.target);
4118 + const candidateMeetsTarget = referenceColors.every(
4119 + (referenceColor2) => getContrast(referenceColor2, candidateColor) >= adjustedTarget2
4096 4120 );
4097 - const adjustedTarget2 = adjustContrastTarget(contrast.target);
4098 - if (candidateContrast >= adjustedTarget2) {
4121 + if (candidateMeetsTarget) {
4099 4122 calculatedColors.set(stepName, candidateColor);
4100 4123 rampResults[stepName] = getColorString(candidateColor);
4101 4124 continue;
4102 4125 }
4103 4126 }
4104 - const computedDir = computeDirection(
4105 - referenceColor,
4127 + const computedDir = computeDirection2(
4128 + referenceColors,
4106 4129 contrast.followDirection
4107 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 + );
4108 4135 const adjustedTarget = adjustContrastTarget(contrast.target);
4109 4136 let lightnessConstraint;
4110 4137 if (pinLightness?.stepName === stepName) {
4111 4138 lightnessConstraint = {
@@ -4152,12 +4179,12 @@
4152 4179 mainDirection,
4153 4180 pinLightness,
4154 4181 rescaleToFitContrastTargets = true
4155 4182 } = {}) {
4156 - assertValidSeedColor(seedArg);
4183 + const parsedSeed = parseSeedColor(seedArg);
4157 4184 let seed;
4158 4185 try {
4159 - seed = clampToGamut(seedArg);
4186 + seed = clampToGamut(parsedSeed);
4160 4187 } catch (error) {
4161 4188 throw new Error(
4162 4189 `Invalid seed color "${seedArg}": ${error instanceof Error ? error.message : "Unknown error"}`
4163 4190 );
@@ -4187,12 +4214,13 @@
4187 4214 oppDir,
4188 4215 pinLightness
4189 4216 });
4190 4217 let bestRamp = rampResults;
4218 + let bestWarnings = warnings;
4191 4219 if (maxDeficit > CONTRAST_EPSILON && rescaleToFitContrastTargets) {
4192 - let getSeedForL = function(l) {
4220 + let getSeedForL2 = function(l) {
4193 4221 return clampToGamut(set(clone(seed), [oklch_default, "l"], l));
4194 - }, getDeficitForSeed = function(s) {
4222 + }, getDeficitForSeed2 = function(s) {
4195 4223 const iterationResults = calculateRamp({
4196 4224 seed: s,
4197 4225 sortedSteps: iterSteps,
4198 4226 config,
@@ -4201,8 +4229,9 @@
4201 4229 pinLightness
4202 4230 });
4203 4231 return iterationResults.maxDeficitDirection === maxDeficitDirection ? iterationResults.maxDeficit : -maxDeficit;
4204 4232 };
4233 + var getSeedForL = getSeedForL2, getDeficitForSeed = getDeficitForSeed2;
4205 4234 const iterSteps = stepsForStep(maxDeficitStep, config);
4206 4235 const lowerSeedL = maxDeficitDirection === "lighter" ? 0 : 1;
4207 4236 const lowerDeficit = -maxDeficit;
4208 4237 const upperSeedL = get(seed, [oklch_default, "l"]);
@@ -4207,16 +4236,16 @@
4207 4236 const lowerDeficit = -maxDeficit;
4208 4237 const upperSeedL = get(seed, [oklch_default, "l"]);
4209 4238 const upperDeficit = maxDeficit;
4210 4239 const bestSeed = solveWithBisect(
4211 - getSeedForL,
4212 - getDeficitForSeed,
4240 + getSeedForL2,
4241 + getDeficitForSeed2,
4213 4242 lowerSeedL,
4214 4243 lowerDeficit,
4215 4244 upperSeedL,
4216 4245 upperDeficit
4217 4246 );
4218 - bestRamp = calculateRamp({
4247 + const finalResult = calculateRamp({
4219 4248 seed: bestSeed,
4220 4249 sortedSteps,
4221 4250 config,
4222 4251 mainDir,
@@ -4221,9 +4250,11 @@
4221 4250 config,
4222 4251 mainDir,
4223 4252 oppDir,
4224 4253 pinLightness
4225 - }).rampResults;
4254 + });
4255 + bestRamp = finalResult.rampResults;
4256 + bestWarnings = finalResult.warnings;
4226 4257 }
4227 4258 if (mainDir === "darker") {
4228 4259 const tmpSurface1 = bestRamp.surface1;
4229 4260 bestRamp.surface1 = bestRamp.surface3;
@@ -4230,9 +4261,9 @@
4230 4261 bestRamp.surface3 = tmpSurface1;
4231 4262 }
4232 4263 return {
4233 4264 ramp: bestRamp,
4234 - warnings,
4265 + warnings: bestWarnings,
4235 4266 direction: mainDir
4236 4267 };
4237 4268 }
4238 4269
@@ -4421,11 +4452,12 @@
4421 4452 // fgFill
4422 4453 fgFill: {
4423 4454 contrast: {
4424 4455 reference: "bgFill1",
4456 + additionalReferences: ["bgFill2"],
4425 4457 followDirection: "best",
4426 - target: 4.5,
4427 - preferLighter: true
4458 + // Preserve the 4.5:1 WCAG floor after 8-bit sRGB serialization.
4459 + target: 4.55
4428 4460 },
4429 4461 lightness: lightnessConstraintForegroundHighContrast,
4430 4462 taperChromaOptions: FG_TAPER_CHROMA
4431 4463 },
@@ -4550,8 +4582,160 @@
4550 4582 const bgRampInfo = bgRamp ? getBgRampInfo(bgRamp) : void 0;
4551 4583 return buildRamp(seed, ACCENT_RAMP_CONFIG, bgRampInfo);
4552 4584 }
4553 4585
4586 + // packages/theme/build-module/semantic-color-contrast-pairs.mjs
4587 + var MINIMUM_TEXT_CONTRAST = 4.5;
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 + },
4609 + {
4610 + background: "background.surface.neutral",
4611 + foreground: "foreground.content.neutral"
4612 + },
4613 + {
4614 + background: "background.surface.neutral-strong",
4615 + foreground: "foreground.content.neutral"
4616 + },
4617 + {
4618 + background: "background.surface.neutral-weak",
4619 + foreground: "foreground.content.neutral"
4620 + },
4621 + {
4622 + background: "background.surface.neutral",
4623 + foreground: "foreground.content.neutral-weak"
4624 + },
4625 + {
4626 + background: "background.surface.info",
4627 + foreground: "foreground.content.info"
4628 + },
4629 + {
4630 + background: "background.surface.info-weak",
4631 + foreground: "foreground.content.info-weak"
4632 + },
4633 + {
4634 + background: "background.surface.success",
4635 + foreground: "foreground.content.success"
4636 + },
4637 + {
4638 + background: "background.surface.success-weak",
4639 + foreground: "foreground.content.success-weak"
4640 + },
4641 + {
4642 + background: "background.surface.warning",
4643 + foreground: "foreground.content.warning"
4644 + },
4645 + {
4646 + background: "background.surface.warning-weak",
4647 + foreground: "foreground.content.warning-weak"
4648 + },
4649 + {
4650 + background: "background.surface.caution",
4651 + foreground: "foreground.content.caution"
4652 + },
4653 + {
4654 + background: "background.surface.caution-weak",
4655 + foreground: "foreground.content.caution-weak"
4656 + },
4657 + {
4658 + background: "background.surface.error",
4659 + foreground: "foreground.content.error"
4660 + },
4661 + {
4662 + background: "background.surface.error-weak",
4663 + foreground: "foreground.content.error-weak"
4664 + },
4665 + {
4666 + background: "background.interactive.brand-strong",
4667 + foreground: "foreground.interactive.brand-strong"
4668 + },
4669 + {
4670 + background: "background.interactive.brand-strong-active",
4671 + foreground: "foreground.interactive.brand-strong-active"
4672 + },
4673 + {
4674 + background: "background.interactive.error-strong",
4675 + foreground: "foreground.interactive.error-strong"
4676 + },
4677 + {
4678 + background: "background.interactive.error-strong-active",
4679 + foreground: "foreground.interactive.error-strong-active"
4680 + },
4681 + {
4682 + background: "background.interactive.neutral-strong",
4683 + foreground: "foreground.interactive.neutral-strong"
4684 + },
4685 + {
4686 + background: "background.interactive.neutral-strong-active",
4687 + foreground: "foreground.interactive.neutral-strong-active"
4688 + }
4689 + ];
4690 + function getSemanticColorCustomProperty(token) {
4691 + return `--wpds-color-${token.replaceAll(".", "-")}`;
4692 + }
4693 +
4694 + // packages/theme/build-module/theme-provider-color-warnings.mjs
4695 + function collectThemeProviderColorWarnings(ramps, colorValues) {
4696 + const warnings = [];
4697 + for (const [rampName, result] of ramps) {
4698 + for (const step of result.warnings ?? []) {
4699 + warnings.push({
4700 + type: "ramp",
4701 + ramp: rampName,
4702 + step
4703 + });
4704 + }
4705 + }
4706 + for (const {
4707 + background: backgroundToken,
4708 + foreground: foregroundToken
4709 + } of SEMANTIC_COLOR_CONTRAST_PAIRS) {
4710 + const backgroundColor = colorValues.get(
4711 + getSemanticColorCustomProperty(backgroundToken)
4712 + );
4713 + const foregroundColor = colorValues.get(
4714 + getSemanticColorCustomProperty(foregroundToken)
4715 + );
4716 + if (backgroundColor === void 0 || foregroundColor === void 0) {
4717 + continue;
4718 + }
4719 + const achievedContrast = getContrast(
4720 + backgroundColor,
4721 + foregroundColor
4722 + );
4723 + if (achievedContrast < MINIMUM_TEXT_CONTRAST) {
4724 + warnings.push({
4725 + type: "contrast",
4726 + backgroundToken,
4727 + backgroundColor,
4728 + foregroundToken,
4729 + foregroundColor,
4730 + requiredContrast: MINIMUM_TEXT_CONTRAST,
4731 + achievedContrast
4732 + });
4733 + }
4734 + }
4735 + return warnings;
4736 + }
4737 +
4554 4738 // packages/theme/build-module/use-theme-provider-styles.mjs
4555 4739 var getCachedBgRamp = memize(buildBgRamp, { maxSize: 10 });
4556 4740 var getCachedAccentRamp = memize(buildAccentRamp, { maxSize: 10 });
4557 4741 var legacyWpComponentsOverridesCSS = [
@@ -4647,9 +4831,10 @@
4647 4831 function colorTokensCSS(computedColorRamps) {
4648 4832 const entries = [];
4649 4833 for (const [rampName, { ramp }] of computedColorRamps) {
4650 4834 for (const [tokenName, tokenValue] of Object.entries(ramp)) {
4651 - const key = `${rampName}-${tokenName}`;
4835 + const primitiveRampName = rampName === "background" ? "bg" : rampName;
4836 + const key = `${primitiveRampName}-${tokenName}`;
4652 4837 const aliasedBy = color_tokens_default[key] ?? [];
4653 4838 for (const aliasedId of aliasedBy) {
4654 4839 entries.push([`--wpds-color-${aliasedId}`, tokenValue]);
4655 4840 }
@@ -4658,14 +4843,14 @@
4658 4843 return entries;
4659 4844 }
4660 4845 function generateStyles({
4661 4846 primary,
4662 - computedColorRamps
4847 + colorEntries
4663 4848 }) {
4664 4849 return Object.fromEntries(
4665 4850 [
4666 4851 // Semantic color tokens
4667 - colorTokensCSS(computedColorRamps),
4852 + colorEntries,
4668 4853 // Legacy overrides
4669 4854 legacyWpAdminThemeOverridesCSS(primary),
4670 4855 legacyWpComponentsOverridesCSS
4671 4856 ].flat()
@@ -4670,8 +4855,35 @@
4670 4855 legacyWpComponentsOverridesCSS
4671 4856 ].flat()
4672 4857 );
4673 4858 }
4859 + function generateThemeProviderColors(primary, background) {
4860 + const seeds = {
4861 + ...DEFAULT_SEED_COLORS,
4862 + background,
4863 + primary
4864 + };
4865 + const computedColorRamps = /* @__PURE__ */ new Map();
4866 + const bgRamp = getCachedBgRamp(seeds.background);
4867 + for (const [rawRampName, seed] of Object.entries(seeds)) {
4868 + const rampName = rawRampName;
4869 + computedColorRamps.set(
4870 + rampName,
4871 + rampName === "background" ? bgRamp : getCachedAccentRamp(seed, bgRamp)
4872 + );
4873 + }
4874 + const colorEntries = colorTokensCSS(computedColorRamps);
4875 + return {
4876 + styles: generateStyles({
4877 + primary: seeds.primary,
4878 + colorEntries
4879 + }),
4880 + warnings: collectThemeProviderColorWarnings(
4881 + computedColorRamps,
4882 + new Map(colorEntries)
4883 + )
4884 + };
4885 + }
4674 4886 function useThemeProviderStyles({
4675 4887 color = {},
4676 4888 cursor,
4677 4889 cornerRadius
@@ -4692,46 +4904,30 @@
4692 4904 cornerRadius: cornerRadiusPreset
4693 4905 }),
4694 4906 [primary, background, cursorControl, cornerRadiusPreset]
4695 4907 );
4696 - const colorStyles = (0, import_element2.useMemo)(() => {
4908 + const generatedColors = (0, import_element2.useMemo)(() => {
4697 4909 if (primary === void 0 || background === void 0) {
4698 - return {};
4910 + return {
4911 + styles: {},
4912 + warnings: void 0
4913 + };
4699 4914 }
4700 - const seeds = {
4701 - ...DEFAULT_SEED_COLORS,
4702 - background,
4703 - primary
4704 - };
4705 - const computedColorRamps = /* @__PURE__ */ new Map();
4706 - const bgRamp = getCachedBgRamp(seeds.background);
4707 - Object.entries(seeds).forEach(([rampName, seed]) => {
4708 - if (rampName === "background") {
4709 - computedColorRamps.set("bg", bgRamp);
4710 - } else {
4711 - computedColorRamps.set(
4712 - rampName,
4713 - getCachedAccentRamp(seed, bgRamp)
4714 - );
4715 - }
4716 - });
4717 - return generateStyles({
4718 - primary: seeds.primary,
4719 - computedColorRamps
4720 - });
4915 + return generateThemeProviderColors(primary, background);
4721 4916 }, [primary, background]);
4722 4917 const themeProviderStyles = (0, import_element2.useMemo)(
4723 4918 () => ({
4724 - ...colorStyles,
4919 + ...generatedColors.styles,
4725 4920 ...cursorControl && {
4726 4921 "--wpds-cursor-control": cursorControl
4727 4922 }
4728 4923 }),
4729 - [colorStyles, cursorControl]
4924 + [generatedColors.styles, cursorControl]
4730 4925 );
4731 4926 return {
4732 4927 resolvedSettings,
4733 - themeProviderStyles
4928 + themeProviderStyles,
4929 + colorWarnings: generatedColors.warnings
4734 4930 };
4735 4931 }
4736 4932
4737 4933 // packages/theme/build-module/theme-provider.mjs
@@ -4816,11 +5012,11 @@
4816 5012 injectStyle(targetDocument, hash, css);
4817 5013 }
4818 5014 }
4819 5015 if (typeof process === "undefined" || true) {
4820 - registerStyle("f4e6e06c6a", ".dba930ea7a9438fd__root{display:contents}");
5016 + registerStyle("8d074a190c", "._0ebd6d9bf8b95794__wrapper{display:contents}");
4821 5017 }
4822 - var style_default = { "root": "dba930ea7a9438fd__root" };
5018 + var style_default = { "wrapper": "_0ebd6d9bf8b95794__wrapper" };
4823 5019 var rootProviderCountByDocument = /* @__PURE__ */ new WeakMap();
4824 5020 var ThemeProvider = ({
4825 5021 children,
4826 5022 color = {},
@@ -4825,16 +5021,18 @@
4825 5021 children,
4826 5022 color = {},
4827 5023 cursor,
4828 5024 cornerRadius,
4829 - isRoot = false
5025 + isRoot = false,
5026 + onColorWarnings
4830 5027 }) => {
4831 - const { themeProviderStyles, resolvedSettings } = useThemeProviderStyles({
5028 + const { themeProviderStyles, resolvedSettings, colorWarnings } = useThemeProviderStyles({
4832 5029 color,
4833 5030 cursor,
4834 5031 cornerRadius
4835 5032 });
4836 5033 const cornerRadiusPreset = resolvedSettings.cornerRadius ?? "subtle";
5034 + const onColorWarningsEvent = (0, import_compose.useEvent)(onColorWarnings);
4837 5035 const contextValue = (0, import_element3.useMemo)(
4838 5036 () => ({
4839 5037 resolvedSettings
4840 5038 }),
@@ -4840,8 +5038,13 @@
4840 5038 }),
4841 5039 [resolvedSettings]
4842 5040 );
4843 5041 const wrapperRef = (0, import_element3.useRef)(null);
5042 + (0, import_element3.useEffect)(() => {
5043 + if (colorWarnings !== void 0) {
5044 + onColorWarningsEvent(colorWarnings);
5045 + }
5046 + }, [colorWarnings, onColorWarningsEvent]);
4844 5047 (0, import_compose.useIsomorphicLayoutEffect)(() => {
4845 5048 if (!isRoot) {
4846 5049 return;
4847 5050 }
@@ -4860,8 +5063,16 @@
4860 5063 rootProviderCountByDocument.set(doc, active + 1);
4861 5064 }
4862 5065 const previous = /* @__PURE__ */ new Map();
4863 5066 const applied = [];
5067 + const previousRootProvider = root.getAttribute(
5068 + "data-wpds-root-provider"
5069 + );
5070 + const previousCornerRadius = root.getAttribute(
5071 + "data-wpds-corner-radius"
5072 + );
5073 + root.setAttribute("data-wpds-root-provider", "true");
5074 + root.setAttribute("data-wpds-corner-radius", cornerRadiusPreset);
4864 5075 for (const [rawKey, rawValue] of Object.entries(
4865 5076 themeProviderStyles
4866 5077 )) {
4867 5078 if (!rawKey.startsWith("--") || rawValue === null || rawValue === void 0) {
@@ -4887,10 +5098,26 @@
4887 5098 } else {
4888 5099 root.style.removeProperty(key);
4889 5100 }
4890 5101 }
5102 + if (previousRootProvider === null) {
5103 + root.removeAttribute("data-wpds-root-provider");
5104 + } else {
5105 + root.setAttribute(
5106 + "data-wpds-root-provider",
5107 + previousRootProvider
5108 + );
5109 + }
5110 + if (previousCornerRadius === null) {
5111 + root.removeAttribute("data-wpds-corner-radius");
5112 + } else {
5113 + root.setAttribute(
5114 + "data-wpds-corner-radius",
5115 + previousCornerRadius
5116 + );
5117 + }
4891 5118 };
4892 - }, [isRoot, themeProviderStyles]);
5119 + }, [cornerRadiusPreset, isRoot, themeProviderStyles]);
4893 5120 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4894 5121 "div",
4895 5122 {
4896 5123 ref: wrapperRef,
@@ -4895,9 +5122,9 @@
4895 5122 {
4896 5123 ref: wrapperRef,
4897 5124 "data-wpds-root-provider": isRoot || void 0,
4898 5125 "data-wpds-corner-radius": cornerRadiusPreset,
4899 - className: style_default.root,
5126 + className: style_default.wrapper,
4900 5127 style: themeProviderStyles,
4901 5128 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value: contextValue, children })
4902 5129 }
4903 5130 );