# All files / color mix.js

100% Statements 12/12
71.43% Branches 5/7
100% Functions 1/1
100% Lines 12/12

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71

    7x
    5x

    5x
    5x

    5x
    5x
    5x
    5x
    5x
    5x

    5x

    5x

     // @flow

    import rgba from './rgba'
    import parseToRgb from './parseToRgb'
    import curry from '../internalHelpers/_curry'

    /**
     * Mixes two colors together by calculating the average of each of the RGB components.
     *
     * By default the weight is 0.5 meaning that half of the first color and half the second
     * color should be used. Optionally the weight can be modified by providing a number
     * as the first argument. 0.25 means that a quarter of the first color and three quarters
     * of the second color should be used.
     *
     * @example
     * // Styles as object usage
     * const styles = {
     *   background: mix(0.5, '#f00', '#00f')
     *   background: mix(0.25, '#f00', '#00f')
     *   background: mix(0.5, 'rgba(255, 0, 0, 0.5)', '#00f')
     * }
     *
     * // styled-components usage
     * const div = styled.div`
     *   background: ${mix(0.5, '#f00', '#00f')};
     *   background: ${mix(0.25, '#f00', '#00f')};
     *   background: ${mix(0.5, 'rgba(255, 0, 0, 0.5)', '#00f')};
     * `
     *
     * // CSS in JS Output
     *
     * element {
     *   background: "#7f007f";
     *   background: "#3f00bf";
     *   background: "rgba(63, 0, 191, 0.75)";
     * }
     */
    function mix(weight: number = 0.5, color: string, otherColor: string): string {
      const parsedColor1 = parseToRgb(color)
      const color1 = {
        ...parsedColor1,
        alpha: typeof parsedColor1.alpha === 'number' ? parsedColor1.alpha : 1,
      }

      const parsedColor2 = parseToRgb(otherColor)
      const color2 = {
        ...parsedColor2,
        alpha: typeof parsedColor2.alpha === 'number' ? parsedColor2.alpha : 1,
      }

      // The formular is copied from the original Sass implementation:
      // http://sass-lang.com/documentation/Sass/Script/Functions.html#mix-instance_method
      const alphaDelta = color1.alpha - color2.alpha
      const x = (weight * 2) - 1
      const y = x * alphaDelta === -1 ? x : (x + alphaDelta)
      const z = (1 + (x * alphaDelta))
      const weight1 = ((y / z) + 1) / 2.0
      const weight2 = 1 - weight1

      const mixedColor = {
        red: Math.floor((color1.red * weight1) + (color2.red * weight2)),
        green: Math.floor((color1.green * weight1) + (color2.green * weight2)),
        blue: Math.floor((color1.blue * weight1) + (color2.blue * weight2)),
        alpha: color1.alpha + ((color2.alpha - color1.alpha) * (weight / 1.0)),
      }

      return rgba(mixedColor)
    }

    export default curry(mix)