| @@ -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 | }, |