graycoreio/daffodil

View on GitHub
libs/design/scss/theming/illuminate/illuminate.scss

Summary

Maintainability
Test Coverage
@use 'sass:map';
@use '../contrast/luminance/luminance';

// @docs
// Take a numeric map and sort it.
//
// https://gist.github.com/Jakobud/a0ac11e80a1de453cd86f0d3fc0a1410
// Credit to: https://gist.github.com/iamandrewluca
//
@function _daff-illuminate-sort($map) {
    // Transform map to zipped list
    $keys: ();
    $values: ();

    @each $key, $val in $map {
        $keys: append($keys, $key);
        $values: append($values, $val);
    }

    $list: zip($keys, $values);

    $sorted-map: ();

    @while length($list) > 0 {
        // Find smallest pair
        $smallest-pair: nth($list, 1);

        @each $pair in $list {
            $value: nth($pair, 2);
            $smallest-value: nth($smallest-pair, 2);

            @if $value < $smallest-value {
                $smallest-pair: $pair;
            }
        }

        // Add smallest pair to sorted map
        $key: nth($smallest-pair, 1);
        $value: nth($smallest-pair, 2);
        $sorted-map: map.merge(
            $sorted-map,
            (
                $key: $value
            )
        );

        // Remove from list smallest pair
        $smallest-pair-index: index($list, $smallest-pair);
        $new-list: ();

        @for $i from 1 through length($list) {
            @if $i != $smallest-pair-index {
                $new-list: append($new-list, nth($list, $i), 'space');
            }
        }

        $list: $new-list;
    }

    @return $sorted-map;
}

// Given a map of key, luminance pairs, find the key
// of the value that is "nth" away from zero.
//
// @param $map: a map of key, luminance pairs,
// @param $nth: nth steps away from zero
@function _daff-illuminate-get-key($map, $nth: 1) {
    //Cap off "nth" to prevent going out-of-bounds.
    @if ($nth > length($map)) {
        $nth: length(map);
    }

    $map: _daff-illuminate-sort($map);
    @return nth(nth($map, $nth), 1);
}

// Takes a $color and palette and returns the color in
// the palette which would "illuminate" against that color.
//
// @usage
// ```
// daff-illuminate($palette);
// ```
//
@function daff-illuminate($color, $palette, $nth: 1) {
    $luminance-map: ();

    //Validate
    @each $key, $palette-color in $palette {
        @if (type-of($key) == 'string') {
            $palette: map.remove($palette, $key);
        }
    }

    //Transform into usable values
    @each $key, $palette-color in $palette {
        $luminance-map: map.merge(
            $luminance-map,
            (
                $key: (
                    luminance.daff-luminance($palette-color) - luminance.daff-luminance($color)
                )
            )
        );
    }


    //Calculate which color to get
    $brighter-colors: ();
    $darker-colors: ();

    @each $key, $luminance in $luminance-map {
        @if ($luminance > 0) {
            $brighter-colors: map.merge(
                $brighter-colors,
                (
                    $key: $luminance
                )
            );
        }

        @if ($luminance < 0) {
            $darker-colors: map.merge(
                $darker-colors,
                (
                    $key: abs($luminance)
                )
            );
        }
    }

    $key: null;

    @if (luminance.daff-luminance($color) >= 0.5) {
        //If the color is bright
        $key: _daff-illuminate-get-key($darker-colors, $nth);
    }
    @else {
        //If the color is dark
        $key: _daff-illuminate-get-key($brighter-colors, $nth);
    }

    @return map.get($palette, $key);
}