_keyframe.scss 4.31 KB
Newer Older
John Punzalan's avatar
John Punzalan committed
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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
// Internal counter for creating unique keyframe names
$-mui-custom: 0;

/// Creates a keyframe from one or more effect functions. Use this function instead of `mui-animation` if you want to create a keyframe animation *without* automatically assigning it to the element.
/// @param {String} $name - Name of the keyframe.
/// @param {Function} $effects... - One or more effect functions to build the keyframe with.
@mixin mui-keyframes($name, $effects...) {
  $obj: -mui-process-args($effects...);
  $obj: map-remove($obj, name);

  @keyframes #{$name} {
    // Now iterate through each keyframe percentage
    @each $pct, $props in $obj {
      #{-mui-keyframe-pct($pct)} {
        // Lastly, iterate through each CSS property within a percentage and print it out
        @each $prop, $value in $props {
          #{$prop}: #{$value};
        }
      }
    }
  }
}

/// Creates a string for a CSS keyframe, by converting a list of numbers to a comma-separated list of percentage values.
/// @param {Number|List} $input - List of numbers to use.
/// @return {String} A set of comma-separated percentage values.
/// @access private
@function -mui-keyframe-pct($input) {
  $output: ();

  @if type-of($input) == 'number' {
    $output: ($input * 1%);
  } @else if type-of($input) == 'list' {
    @each $i in $input {
      $output: append($output, ($i * 1%), comma);
    }
  }

  @return $output;
}

/// Prints the CSS properties from a specific key in a keyframes map. Used to borrow CSS from keyframe functions for use in transitions.
/// @param {Map} $kf - Keyframe map to extract from.
/// @param {Number} $key - Key in the map to print the CSS of.
/// @access private
@mixin -mui-keyframe-get($kf, $key) {
  $map: map-get($kf, $key);

  @each $prop, $value in $map or () {
    // Some keyframe maps store transforms as quoted strings
    @if type-of($value) == 'string' {
      $value: unquote($value);
    }
    #{$prop}: $value;
  }
}

/// Reformats a map containing keys with a list of values, so that each key is a single value.
/// @param {Map} $map - Map to split up.
/// @return {Map} A reformatted map.
/// @access private
@function -mui-keyframe-split($map) {
  $new-map: ();

  // Split keys with multiple values into individual keys
  @each $key, $item in $map {
    $key-type: type-of($key);

    @if $key-type == 'number' {
      $new-map: map-merge($new-map, ($key: $item));
    } @else if $key-type == 'list' {
      @each $k in $key {
        $new-map: map-merge($new-map, ($k: $item));
      }
    }
  }

  @return $new-map;
}

/// Combines a series of keyframe objects into one.
/// @param {Map} $maps... - A series of maps to merge, as individual parameters.
/// @return {Map} A combined keyframe object.
/// @access private
@function -mui-keyframe-combine($maps...) {
  $new-map: ();

  // Iterate through each map passed in
  @each $map in $maps {
    @if type-of($map) == 'string' {
      $map: call($map);
    }

    $map: -mui-keyframe-split($map);

    // Iterate through each keyframe in the map
    // $key is the keyframe percentage
    // $value is a map of CSS properties
    @each $key, $value in $map {
      $new-value: ();

      @if map-has-key($new-map, $key) {
        // If the map already has the keyframe %, append the new property
        $new-value: -mui-merge-properties(map-get($new-map, $key), $value);
      } @else {
        // Otherwise, create a new map with the new property
        $new-value: $value;
      }

      // Finally, merge the modified keyframe value into the output map
      $new-map: map-merge($new-map, ($key: $new-value));
    }
  }

  // Make a name for the keyframes
  $-mui-custom: $-mui-custom + 1 !global;
  $map-name: (name: 'custom-#{$-mui-custom}');
  $new-map: map-merge($new-map, $map-name);

  @return $new-map;
}

/// Combines two maps of CSS properties into one map. If both maps have a transform property, the values from each will be combined into one property.
/// @param {Map} $one - First map to merge.
/// @param {Map} $two - Second map to merge.
/// @return {Map} A combined map.
/// @access private
@function -mui-merge-properties($one, $two) {
  @if map-has-key($one, transform) and map-has-key($two, transform) {
    $transform: join(map-get($one, transform), map-get($two, transform));
    $one: map-merge($one, (transform: $transform));
    $two: map-remove($two, transform);
  }

  @return map-merge($one, $two);
}