
$animation-default-scale-factor: 1;
$animation-default-scale-factor-ms: 1000;
$animation-easing-ios: cubic-bezier(0.23, 1, 0.32, 1);
$animation-easing-android: cubic-bezier(0.4, 0, 0.2, 1);

:root {
  --animation-scale-factor: #{$animation-default-scale-factor};
  --animation-duration-very-fast: #{$animation-default-scale-factor * 0.18s};
  --animation-duration-very-fast-ms: #{$animation-default-scale-factor-ms * 0.18};
  --animation-duration-fast: #{$animation-default-scale-factor * 0.25s};
  --animation-duration-fast-ms: #{$animation-default-scale-factor-ms * 0.25};
  --animation-duration-standard: #{$animation-default-scale-factor * 0.35s};
  --animation-duration-standard-ms: #{$animation-default-scale-factor-ms * 0.35};
  --animation-duration-slow: #{$animation-default-scale-factor * 0.55s};
  --animation-duration-slow-ms: #{$animation-default-scale-factor-ms * 0.5};
  --animation-easing: #{$animation-easing-android};

  // Values provided to JS must be valid JSON
  --animation-easing-json: [0.4, 0, 0.2, 1];
  --animation-easing-js: var(--animation-easing-json);
}

// Preset animations **********************************************************/
@keyframes zoom {
  0% {
    transform: scale(0, 0);
    opacity: 0;
  }

  100% {
    transform: scale(1, 1);
    opacity: 1;
  }
}

@keyframes bounce {
  0% {
    transform: scale(0);
    opacity: 0;
  }

  50% {
    transform: scale(1.1);
    opacity: 0.4;
  }

  75% {
    transform: scale(0.9);
    opacity: 0.7;
  }

  100% {
    transform: scale(1);
    opacity: 1;
  }
}

@mixin animation($animation-name) {
  animation-name: $animation-name;
  animation-duration: var(--animation-duration-standard);
  animation-timing-function: var(--animation-easing);
  animation-delay: 0ms;
  animation-iteration-count: 1;
}

$transition-presets: (
  zoom: (
    start: (transform: scale(0, 0), opacity: 0),
    end: (transform: scale(1, 1), opacity: 1)
  ),
  fade: (
    start: (opacity: 0),
    end: (opacity: 1)
  ),
  flex: (
    start: (flex-grow: 0),
    end: (flex-grow: 1)
  )
);

// Animation helpers **********************************************************/
@mixin transition-properties($properties, $easing, $duration) {
  $transitions: ();
  @each $value in $properties {
    $transitions: append($transitions, $value $duration $easing, comma);
  }
  transition: $transitions;
}

@mixin transition-properties-with-delay($properties, $easing, $duration, $delay: 0s) {
  $transitions: ();
  @each $value in $properties {
    $transitions: append($transitions, $value $duration $easing $delay, comma);
  }
  transition: $transitions;
}

@mixin group-transition-enter {
  &-enter {
    @content;
  }
}

@mixin group-transition-appear {
  &-appear {
    @content;
  }
}

@mixin group-transition-leave {
  &-leave {
    @content;
  }
}

@mixin group-transition($transition-name, $duration: var(--animation-duration-standard)) {
  $transition: map-get($transition-presets, $transition-name);
  $properties: map-keys(map-get($transition, 'start'));

  &-appear,
  &-enter {
    @each $key, $value in map-get($transition, 'start') {
      #{$key}: $value;
    }


    &-active {

      @include transition-properties($properties, var(--animation-easing), $duration);
      @each $key, $value in map-get($transition, 'end') {
        #{$key}: $value;
      }
    }
  }

  &-leave {
    @each $key, $value in map-get($transition, 'end') {
      #{$key}: $value;
    }


    &-active {
      @include transition-properties($properties, var(--animation-easing), $duration);
      @each $key, $value in map-get($transition, 'start') {
        #{$key}: $value;
      }
    }
  }
}

@mixin group-transition-with-delay($transition-name, $duration, $delay) {
  $transition: map-get($transition-presets, $transition-name);
  $properties: map-keys(map-get($transition, 'start'));

  &-appear {
    @each $key, $value in map-get($transition, 'start') {
      #{$key}: $value;
    }

    &-active {
      @include transition-properties-with-delay($properties, var(--animation-easing), $duration, $delay);
      @each $key, $value in map-get($transition, 'end') {
        #{$key}: $value;
      }
    }
  }

  &-enter {
    @each $key, $value in map-get($transition, 'start') {
      #{$key}: $value;
    }

    &-active {
      @include transition-properties-with-delay($properties, var(--animation-easing), $duration, $delay);
      @each $key, $value in map-get($transition, 'end') {
        #{$key}: $value;
      }
    }
  }

  &-leave {
    @each $key, $value in map-get($transition, 'end') {
      #{$key}: $value;
    }

    &-active {
      @include transition-properties($properties, var(--animation-easing), $duration);
      @each $key, $value in map-get($transition, 'start') {
        #{$key}: $value;
      }
    }
  }
}
