# All files / mixins radialGradient.js

100% Statements 15/15
100% Branches 22/22
100% Functions 3/3
100% Lines 14/14

    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82

    4x

    5x
    5x
    25x

    25x
    4x
    4x

    21x
    1x

    20x
    7x

    5x

    6x
    5x

     // @flow

    /** */
    type RadialGradientConfiguration = {
      colorStops: Array<string>;
      extent?: string;
      fallback?: string;
      position?: string;
      shape?: string;
    };

    function parseFallback(colorStops: Array<string>) {
      return colorStops[0].split(' ')[0]
    }

    function constructGradientValue(literals: Array<string>, ...substitutions: Array<string>) {
      let template = ''
      for (let i = 0; i < literals.length; i += 1) {
        template += literals[i]
        // Adds leading coma if properties preceed color-stops
        if ((i === 3 && substitutions[i]) && (substitutions[0] || substitutions[1] || substitutions[2])) {
          template = template.slice(0, -1)
          template += `, ${substitutions[i]}`
        // No trailing space if color-stops is the only param provided
        } else if ((i === 3 && substitutions[i]) && (!substitutions[0] && !substitutions[1] && !substitutions[2])) {
          template += `${substitutions[i]}`
        // Only adds substitution if it is defined
        } else if (substitutions[i]) {
          template += `${substitutions[i]} `
        }
      }
      return template.trim()
    }

    /**
     * CSS for declaring a radial gradient, including a fallback background-color. The fallback is either the first color-stop or an explicitly passed fallback color.
     *
     * @example
     * // Styles as object usage
     * const styles = {
     *   ...radialGradient({
     *     colorStops: ['#00FFFF 0%', 'rgba(0, 0, 255, 0) 50%', '#0000FF 95%'],
     *     extent: 'farthest-corner at 45px 45px',
     *     position: 'center',
     *     shape: 'ellipse',
     *   })
     * }
     *
     * // styled-components usage
     * const div = styled.div`
     *   ${radialGradient({
     *     colorStops: ['#00FFFF 0%', 'rgba(0, 0, 255, 0) 50%', '#0000FF 95%'],
     *     extent: 'farthest-corner at 45px 45px',
     *     position: 'center',
     *     shape: 'ellipse',
     *   })}
     *`
     *
     * // CSS as JS Output
     *
     * div: {
     *   'background-color': '#00FFFF',
     *   'background-image': 'radial-gradient(center ellipse farthest-corner at 45px 45px, #00FFFF 0%, rgba(0, 0, 255, 0) 50%, #0000FF 95%)',
     * }
     */

    function radialGradient({
      colorStops,
      extent,
      fallback,
      position,
      shape,
    }: RadialGradientConfiguration) {
      if (!colorStops || colorStops.length < 2) throw new Error('radialGradient requries at least 2 color-stops to properly render.')
      return {
        'background-color': fallback || parseFallback(colorStops),
        'background-image': constructGradientValue`radial-gradient(${position}${shape}${extent}${colorStops.join(', ')})`,
      }
    }

    export default radialGradient