@use 'sass:color'; @use 'sass:math'; @use 'sass:map'; @use 'sass:list'; @use 'sass:meta'; @use 'iro-sass/src/easing'; @use 'apca'; @function palette($base-color, $contrasts, $chroma-range: 1, $ref-color: $base-color, $chroma-easing: 'ease') { $base-lch: color.to-space($base-color, oklch); $ref-lch: color.to-space($ref-color, oklch); $ref-l: color.channel($ref-lch, 'lightness'); $ref-y: apca.sRGB_to_Y($ref-lch); $cmax: math.max(map.values($contrasts)...); $cmax: math.max($cmax, math.abs(math.min(map.values($contrasts)...))); $black-y: apca.sRGB_to_Y(#000); $white-y: apca.sRGB_to_Y(#fff); $chroma-inv: false; @if $chroma-range < 0 { $chroma-inv: true; $chroma-range: -1 * $chroma-range; } $chroma-easing: meta.get-function($chroma-easing, $module: easing); $palette: (); @each $key, $contrast in $contrasts { $y: apca.reverse($contrast, $ref-y); $l: color.channel($base-lch, 'lightness'); $c: 1; @if $y != false { $l: color.channel(apca.Y_to_sRGB($y), 'lightness', oklch); } @else { $y: $ref-y; } @if $chroma-range != 1 { $c: if($ref-l > 50%, math.clamp(0, math.div($contrast, $cmax), 1), -1 * math.clamp(-1, math.div($contrast, $cmax), 0)); @if $chroma-inv { $c: 1 - $c; } $c: meta.call($chroma-easing, $c); $c: $chroma-range + (1 - $chroma-range) * $c; } $color: oklch($l ($c * color.channel($base-lch, 'chroma')) color.channel($base-lch, 'hue')); $contrast-black: apca.contrast($black-y, $y); $contrast-white: apca.contrast($white-y, $y); $palette: map.set($palette, $key, $color); $palette: map.set($palette, #{$key}-text, if(math.abs($contrast-black) > math.abs($contrast-white), #000, #fff)); } @return $palette; } @function transparent-palette($color, $text, $alphas) { $palette: ( --text: $text, ); @each $key, $alpha in $alphas { $palette: map.set($palette, $key, rgba($color, $alpha)); } @return $palette; }