Repository: angular/angular
File: packages/core/src/render3/instructions/animation.ts (TypeScript)

Code before:
    return ɵɵanimateEnter;
  }

  const tNode = getCurrentTNode()!;
  cancelLeavingNodes(tNode, lView);

  addAnimationToLView(getLViewEnterAnimations(lView), tNode, () =>
    runEnterAnimation(lView, tNode, value),
  );

  initializeAnimationQueueScheduler(lView[INJECTOR]);

  // We have to queue here due to the animation instruction being invoked after the element
  // instruction. The DOM node has to exist before we can queue an animation. Any node that
  // is not inside of control flow needs to get queued here. For nodes inside of control
  // flow, those are queued in node_manipulation.ts and are deduped by a Set in the animation
  // queue.
  queueEnterAnimations(lView[INJECTOR], getLViewEnterAnimations(lView));

  return ɵɵanimateEnter; // For chaining
}

export function runEnterAnimation(
  lView: LView,
  tNode: TNode,
  value: string | (() => string | string[]),
): void {
  const nativeElement = getNativeByTNode(tNode, lView) as HTMLElement;

  ngDevMode && assertElementNodes(nativeElement, 'animate.enter');

  const renderer = lView[RENDERER];
  const ngZone = lView[INJECTOR]!.get(NgZone);

  // Retrieve the actual class list from the value. This will resolve any resolver functions from
  // bindings.
  const activeClasses = getClassListFromValue(value);
  const cleanupFns: VoidFunction[] = [];

  // In the case where multiple animations are happening on the element, we need
  // to get the longest animation to ensure we don't complete animations early.
  // This also allows us to setup cancellation of animations in progress if the
  // gets removed early.
  const handleEnterAnimationStart = (event: AnimationEvent | TransitionEvent) => {
    // this early exit case is to prevent issues with bubbling events that are from child element animations
    if (event.target !== nativeElement) return;

    const eventName = event instanceof AnimationEvent ? 'animationend' : 'transitionend';
    ngZone.runOutsideAngular(() => {
      renderer.listen(nativeElement, eventName, handleEnterAnimationEnd);
    });

Review comment (suggestion):
```suggestion
  value: string | AnimationClassBindingFn,
```

Code after:
    return ɵɵanimateEnter;
  }

  const tNode = getCurrentTNode()!;
  cancelLeavingNodes(tNode, lView);

  addAnimationToLView(getLViewEnterAnimations(lView), tNode, () =>
    runEnterAnimation(lView, tNode, value),
  );

  initializeAnimationQueueScheduler(lView[INJECTOR]);

  // We have to queue here due to the animation instruction being invoked after the element
  // instruction. The DOM node has to exist before we can queue an animation. Any node that
  // is not inside of control flow needs to get queued here. For nodes inside of control
  // flow, those are queued in node_manipulation.ts and are deduped by a Set in the animation
  // queue.
  queueEnterAnimations(lView[INJECTOR], getLViewEnterAnimations(lView));

  return ɵɵanimateEnter; // For chaining
}

export function runEnterAnimation(
  lView: LView,
  tNode: TNode,
  value: string | AnimationClassBindingFn,
): void {
  const nativeElement = getNativeByTNode(tNode, lView) as HTMLElement;

  ngDevMode && assertElementNodes(nativeElement, 'animate.enter');

  const renderer = lView[RENDERER];
  const ngZone = lView[INJECTOR]!.get(NgZone);

  // Retrieve the actual class list from the value. This will resolve any resolver functions from
  // bindings.
  const activeClasses = getClassListFromValue(value);
  const cleanupFns: VoidFunction[] = [];

  // In the case where multiple animations are happening on the element, we need
  // to get the longest animation to ensure we don't complete animations early.
  // This also allows us to setup cancellation of animations in progress if the
  // gets removed early.
  const handleEnterAnimationStart = (event: AnimationEvent | TransitionEvent) => {
    // this early exit case is to prevent issues with bubbling events that are from child element animations
    if (event.target !== nativeElement) return;

    const eventName = event instanceof AnimationEvent ? 'animationend' : 'transitionend';
    ngZone.runOutsideAngular(() => {
      renderer.listen(nativeElement, eventName, handleEnterAnimationEnd);
    });