src/lib/styles/animation.scss
@mixin pulse($scaleX: var(--neo-pulse-scale-x, 2), $scaleY: var(--neo-pulse-scale-y, 2), $opacity-start: 1, $opacity-end: 0) {
  @keyframes pulse {
    0% {
      transform: scaleX(1) scaleY(1);
      opacity: 0;
    }

    25% {
      opacity: $opacity-start;
    }

    100% {
      transform: scaleX($scaleX) scaleY($scaleY);
      opacity: $opacity-end;
    }
  }
}

@mixin coalesce($scaleX: var(--neo-coalesce-scale-x, 2), $scaleY: var(--neo-coalesce-scale-y, 2), $opacity-start: 1, $opacity-end: 0) {
  @keyframes coalesce {
    0% {
      transform: scaleX($scaleX) scaleY($scaleY);
      opacity: 0;
    }

    75% {
      opacity: $opacity-start;
    }

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

@mixin rotate {
  @keyframes rotate {
    from {
      --neo-angle: 0deg;
    }

    to {
      --neo-angle: 360deg;
    }
  }
}

@mixin skeleton($start: var(--neo-skeleton-start), $end: var(--neo-skeleton-end)) {
  @keyframes skeleton {
    0%,
    80%,
    100% {
      opacity: $start;
    }

    40% {
      opacity: $end;
    }
  }
}

@mixin indeterminate-slow($name: right, $axis: X, $polarity: positive) {
  @keyframes indeterminate-slow-#{$name} {
    0% {
      transform: translate#{$axis }(0) scale#{$axis }(0);
    }

    10% {
      transform: translate#{$axis }(0) scale#{$axis }(0.4);
    }

    60%,
    100% {
      transform: translate#{$axis }(#{if($polarity == positive, 110%, -110%)}) scale#{$axis }(0.6);
    }
  }
}

@mixin indeterminate-fast($name: right, $axis: X, $polarity: positive, $size: grow) {
  @keyframes indeterminate-fast-#{$name} {
    0%,
    40% {
      transform: translate#{$axis }(0) scale#{$axis }(0);
    }

    60% {
      transform: translate#{$axis }(0) scale#{$axis }(0.6);
    }

    90%,
    100% {
      transform: translate#{$axis }(#{if($polarity == positive, 110%, -110%)}) scale#{$axis }(0.1);
    }
  }
}

@mixin spin-in($scale: var(--neo-scale-target, 0.9)) {
  @keyframes neo-spin-in {
    0% {
      --neo-rotation: -90deg;

      animation-timing-function: ease-in-out;
    }

    20% {
      --neo-scale: #{$scale};
      --neo-rotation: -90deg;
    }

    85% {
      --neo-scale: #{$scale};
      --neo-rotation: 0deg;

      animation-timing-function: ease-in-out;
    }

    100% {
      --neo-rotation: 0deg;
    }
  }
}

@mixin spin-out($scale: var(--neo-scale-target, 0.9)) {
  @keyframes neo-spin-out {
    0% {
      --neo-rotation: 0deg;

      animation-timing-function: ease-in-out;
    }

    20% {
      --neo-scale: #{$scale};
      --neo-rotation: 0deg;
    }

    85% {
      --neo-scale: #{$scale};
      --neo-rotation: 90deg;

      animation-timing-function: ease-in-out;
    }

    100% {
      --neo-rotation: 90deg;
    }
  }
}

@mixin time-in($start: -0.1, $end: 1.1) {
  @keyframes neo-time-in {
    0% {
      --neo-time: #{$start};
    }

    100% {
      --neo-time: #{$end};
    }
  }
}

@mixin circle-in($circle-x: 50%, $circle-y: 0%, $size: 120%) {
  @keyframes circle-in {
    from {
      clip-path: circle(0% at #{$circle-x} #{$circle-y});
    }

    to {
      clip-path: circle(#{$size} at #{$circle-x} #{$circle-y});
    }
  }
}
