@angular/core 20.3.2 → 20.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/api.d.d.ts +2 -2
  2. package/chrome_dev_tools_performance.d.d.ts +3 -3
  3. package/discovery.d.d.ts +12 -5
  4. package/effect.d.d.ts +3 -3
  5. package/event_dispatcher.d.d.ts +2 -2
  6. package/fesm2022/attribute.mjs +2 -2
  7. package/fesm2022/attribute.mjs.map +1 -1
  8. package/fesm2022/core.mjs +2 -2
  9. package/fesm2022/core.mjs.map +1 -1
  10. package/fesm2022/debug_node.mjs +209 -113
  11. package/fesm2022/debug_node.mjs.map +1 -1
  12. package/fesm2022/effect.mjs +2 -2
  13. package/fesm2022/effect.mjs.map +1 -1
  14. package/fesm2022/not_found.mjs +2 -2
  15. package/fesm2022/not_found.mjs.map +1 -1
  16. package/fesm2022/primitives/di.mjs +2 -2
  17. package/fesm2022/primitives/di.mjs.map +1 -1
  18. package/fesm2022/primitives/event-dispatch.mjs +2 -2
  19. package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
  20. package/fesm2022/primitives/signals.mjs +137 -4
  21. package/fesm2022/primitives/signals.mjs.map +1 -1
  22. package/fesm2022/resource.mjs +2 -2
  23. package/fesm2022/resource.mjs.map +1 -1
  24. package/fesm2022/root_effect_scheduler.mjs +3 -3
  25. package/fesm2022/root_effect_scheduler.mjs.map +1 -1
  26. package/fesm2022/rxjs-interop.mjs +2 -2
  27. package/fesm2022/rxjs-interop.mjs.map +1 -1
  28. package/fesm2022/signal.mjs +9 -9
  29. package/fesm2022/signal.mjs.map +1 -1
  30. package/fesm2022/testing.mjs +2 -2
  31. package/fesm2022/testing.mjs.map +1 -1
  32. package/fesm2022/weak_ref.mjs +2 -2
  33. package/fesm2022/weak_ref.mjs.map +1 -1
  34. package/{graph.d.d.ts → formatter.d.d.ts} +15 -3
  35. package/index.d.ts +8 -7
  36. package/package.json +2 -2
  37. package/primitives/di/index.d.ts +2 -2
  38. package/primitives/event-dispatch/index.d.ts +2 -2
  39. package/primitives/signals/index.d.ts +4 -4
  40. package/rxjs-interop/index.d.ts +3 -3
  41. package/schematics/bundles/add-bootstrap-context-to-server-main.cjs +5 -5
  42. package/schematics/bundles/{apply_import_manager-Ch2ALAC9.cjs → apply_import_manager-CUBvPp_2.cjs} +3 -3
  43. package/schematics/bundles/cleanup-unused-imports.cjs +5 -5
  44. package/schematics/bundles/{compiler_host-Jw4hNUf8.cjs → compiler_host-DJHZ7M9N.cjs} +2 -2
  45. package/schematics/bundles/control-flow-migration.cjs +3 -3
  46. package/schematics/bundles/document-core.cjs +5 -5
  47. package/schematics/bundles/imports-CIX-JgAN.cjs +1 -1
  48. package/schematics/bundles/{index-Gg0PI_fh.cjs → index-BZJ8bv9v.cjs} +27 -17
  49. package/schematics/bundles/{index-DWTTHy-7.cjs → index-DU_evmAi.cjs} +4 -4
  50. package/schematics/bundles/inject-flags.cjs +5 -5
  51. package/schematics/bundles/inject-migration.cjs +3 -3
  52. package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
  53. package/schematics/bundles/{migrate_ts_type_references-D_xIwAQ5.cjs → migrate_ts_type_references-58gA72Ti.cjs} +5 -5
  54. package/schematics/bundles/ng_decorators-B5HCqr20.cjs +1 -1
  55. package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
  56. package/schematics/bundles/output-migration.cjs +6 -6
  57. package/schematics/bundles/{project_paths-CfXVBYVk.cjs → project_paths-DcM18127.cjs} +3 -3
  58. package/schematics/bundles/{project_tsconfig_paths-C11WBTJF.cjs → project_tsconfig_paths-Dqd0J7st.cjs} +34 -40
  59. package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
  60. package/schematics/bundles/route-lazy-loading.cjs +3 -3
  61. package/schematics/bundles/router-current-navigation.cjs +4 -4
  62. package/schematics/bundles/self-closing-tags-migration.cjs +4 -4
  63. package/schematics/bundles/signal-input-migration.cjs +67 -8
  64. package/schematics/bundles/signal-queries-migration.cjs +7 -7
  65. package/schematics/bundles/signals.cjs +7 -7
  66. package/schematics/bundles/standalone-migration.cjs +106 -46
  67. package/schematics/bundles/symbol-VPWguRxr.cjs +1 -1
  68. package/schematics/bundles/test-bed-get.cjs +4 -4
  69. package/testing/index.d.ts +3 -3
  70. package/weak_ref.d.d.ts +2 -2
@@ -1,10 +1,10 @@
1
1
  /**
2
- * @license Angular v20.3.2
3
- * (c) 2010-2025 Google LLC. https://angular.io/
2
+ * @license Angular v20.3.4
3
+ * (c) 2010-2025 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
6
6
 
7
- import { attachInjectFlag, _global, ɵɵdefineInjectable as __defineInjectable, ɵɵdefineInjector as __defineInjector, ɵɵinject as __inject, ɵɵinvalidFactoryDep as __invalidFactoryDep, resolveForwardRef, newArray, EMPTY_OBJ, assertString, assertNotEqual, FLAGS, assertEqual, isInCheckNoChangesMode, PREORDER_HOOK_FLAGS, assertFirstCreatePass, assertDefined, throwError, assertNumber, assertGreaterThan, HEADER_OFFSET, DECLARATION_VIEW, NG_FACTORY_DEF, isForwardRef, getFactoryDef, assertIndexInRange, assertTNodeForLView, enterDI, runInInjectorProfilerContext, getCurrentTNode, getLView, emitInjectorToCreateInstanceEvent, emitInstanceCreatedByInjectorEvent, throwProviderNotFoundError, leaveDI, assertNodeInjector, stringifyForError, cyclicDependencyErrorWithDetails, cyclicDependencyError, setInjectorProfilerContext, setInjectImplementation, assertDirectiveDef, NG_ELEMENT_ID, convertToBitFlags, isRootView, T_HOST, TVIEW, injectRootLimpMode, isComponentDef, EMBEDDED_VIEW_INJECTOR, INJECTOR$1 as INJECTOR, DECLARATION_COMPONENT_VIEW, isComponentHost, RuntimeError, NG_PROV_DEF, getClosureSafeProperty, getNativeByTNode, flatten, arrayEquals, ID, isLView, assertDomNode, unwrapRNode, getComponentLViewByIndex, CONTEXT, EMPTY_ARRAY, assertLView, HOST, CHILD_HEAD, NEXT, isLContainer, getLViewParent, Injector, CLEANUP, getComponentDef, getDirectiveDef, InjectionToken, inject, isInSkipHydrationBlock as isInSkipHydrationBlock$1, HYDRATION, isContentQueryHost, setCurrentQueryIndex, XSS_SECURITY_URL, renderStringify, ENVIRONMENT, makeEnvironmentProviders, isDirectiveHost, formatRuntimeError, resetPreOrderHookFlags, PARENT, RENDERER, CHILD_TAIL, assertSame, assertFirstUpdatePass, getSelectedIndex, getTView, assertIndexInDeclRange, setSelectedIndex, assertLContainer, MOVED_VIEWS, isDestroyed, REACTIVE_TEMPLATE_CONSUMER, DECLARATION_LCONTAINER, QUERIES, assertNotReactive, ON_DESTROY_HOOKS, assertFunction, EFFECTS, assertProjectionSlots, NATIVE, ANIMATIONS, assertParentView, CONTAINER_HEADER_OFFSET, assertNotSame, setCurrentDirectiveIndex, setCurrentTNode, getElementDepthCount, increaseElementDepthCount, wasLastNodeCreated, isCurrentTNodeParent, setCurrentTNodeAsNotParent, assertHasParent, INTERNAL_APPLICATION_ERROR_HANDLER, stringify, getCurrentDirectiveIndex, unwrapLView, isCreationMode, enterView, leaveView, AFTER_RENDER_SEQUENCES_TO_ADD, markAncestorsForTraversal, markViewForRefresh, setIsRefreshingViews, isExhaustiveCheckNoChanges, requiresRefreshOrTraversal, setIsInCheckNoChangesMode, CheckNoChangesMode, setBindingIndex, EFFECTS_TO_SCHEDULE, viewAttachedToChangeDetector, setBindingRootForHostBindings, isRefreshingViews, removeFromArray, addToArray, updateAncestorTraversalFlagsOnAttach, storeLViewOnDestroy, VIEW_REFS, assertGreaterThanOrEqual, isInI18nBlock, assertTNodeForTView, getCurrentParentTNode, getCurrentTNodePlaceholderOk, assertTNode, assertTIcu, assertNumberInRange, DEHYDRATED_VIEWS, getNgModuleDef, getPipeDef as getPipeDef$1, getNgModuleDefOrThrow, isStandalone, concatStringsWithSpace, assertInjectImplementationNotEqual, emitInjectEvent, getConstant, assertLessThan, getOrCreateTViewCleanup, getOrCreateLViewCleanup, assertNotDefined, nextBindingIndex, getSelectedTNode, getDirectiveDefOrThrow, getTNode, assertComponentType, debugStringifyTypeForError, ChangeDetectionScheduler, EnvironmentInjector, SVG_NAMESPACE, MATH_ML_NAMESPACE, viewAttachedToContainer, storeCleanupWithContext, signal, createInjectorWithoutInjectorInstances, R3Injector, getNullInjector, internalImportProvidersFrom, initNgDevMode, fillProperties, getBindingsEnabled, lastNodeWasCreated, isInInjectionContext, DestroyRef, PendingTasksInternal, noop, ErrorHandler, assertNotInReactiveContext, assertInInjectionContext, ViewContext, removeLViewOnDestroy, walkUpViews, getNativeByIndex, assertElement, arrayInsert2, arraySplice, setInjectorProfiler, NullInjector, ENVIRONMENT_INITIALIZER, INJECTOR_DEF_TYPES, walkProviderTree, getInjectorDef, deepForEach, isTypeProvider, isSignal, runInInjectionContext, ZONELESS_ENABLED, EffectScheduler, PendingTasks, assertTNodeCreationIndex, isSkipHydrationRootTNode, leaveSkipHydrationBlock, decreaseElementDepthCount, getNamespace, enterSkipHydrationBlock, getCurrentDirectiveDef, assertIndexInExpandoRange, getBindingIndex, assertOneOf, setInI18nBlock, nextContextImpl, getCurrentQueryIndex, getContextLView, load, keyValueArrayIndexOf, keyValueArraySet, keyValueArrayGet, incrementBindingIndex, isWritableSignal, store, providerToFactory, emitProviderConfiguredEvent, isClassProvider, getBindingRoot, NG_COMP_DEF, ɵɵresetView as __resetView, ɵɵnamespaceHTML as __namespaceHTML, ɵɵnamespaceMathML as __namespaceMathML, ɵɵnamespaceSVG as __namespaceSVG, ɵɵenableBindings as __enableBindings, ɵɵdisableBindings as __disableBindings, ɵɵrestoreView as __restoreView, forwardRef, NG_MOD_DEF, NG_INJ_DEF, NG_DIR_DEF, NG_PIPE_DEF, ZONELESS_SCHEDULER_DISABLED, SCHEDULE_IN_ROOT_ZONE, PROVIDED_ZONELESS, getNativeByTNodeOrNull } from './root_effect_scheduler.mjs';
7
+ import { attachInjectFlag, _global, ɵɵdefineInjectable as __defineInjectable, ɵɵdefineInjector as __defineInjector, ɵɵinject as __inject, ɵɵinvalidFactoryDep as __invalidFactoryDep, resolveForwardRef, newArray, EMPTY_OBJ, assertString, assertNotEqual, FLAGS, assertEqual, isInCheckNoChangesMode, PREORDER_HOOK_FLAGS, assertFirstCreatePass, assertDefined, throwError, assertNumber, assertGreaterThan, HEADER_OFFSET, DECLARATION_VIEW, NG_FACTORY_DEF, isForwardRef, getFactoryDef, assertIndexInRange, assertTNodeForLView, enterDI, runInInjectorProfilerContext, getCurrentTNode, getLView, emitInjectorToCreateInstanceEvent, emitInstanceCreatedByInjectorEvent, throwProviderNotFoundError, leaveDI, assertNodeInjector, stringifyForError, cyclicDependencyErrorWithDetails, cyclicDependencyError, setInjectorProfilerContext, setInjectImplementation, assertDirectiveDef, NG_ELEMENT_ID, convertToBitFlags, isRootView, T_HOST, TVIEW, injectRootLimpMode, isComponentDef, EMBEDDED_VIEW_INJECTOR, INJECTOR$1 as INJECTOR, DECLARATION_COMPONENT_VIEW, isComponentHost, RuntimeError, NG_PROV_DEF, getClosureSafeProperty, getNativeByTNode, flatten, arrayEquals, ID, isLView, assertDomNode, unwrapRNode, getComponentLViewByIndex, CONTEXT, EMPTY_ARRAY, assertLView, HOST, CHILD_HEAD, NEXT, isLContainer, getLViewParent, Injector, CLEANUP, getComponentDef, getDirectiveDef, InjectionToken, inject, isInSkipHydrationBlock as isInSkipHydrationBlock$1, HYDRATION, isContentQueryHost, setCurrentQueryIndex, XSS_SECURITY_URL, renderStringify, ENVIRONMENT, makeEnvironmentProviders, isDirectiveHost, formatRuntimeError, resetPreOrderHookFlags, PARENT, RENDERER, CHILD_TAIL, assertSame, assertFirstUpdatePass, getSelectedIndex, getTView, assertIndexInDeclRange, setSelectedIndex, assertLContainer, MOVED_VIEWS, isDestroyed, REACTIVE_TEMPLATE_CONSUMER, DECLARATION_LCONTAINER, QUERIES, assertNotReactive, ON_DESTROY_HOOKS, assertFunction, EFFECTS, assertProjectionSlots, NATIVE, assertParentView, CONTAINER_HEADER_OFFSET, ANIMATIONS, assertNotSame, setCurrentDirectiveIndex, setCurrentTNode, getElementDepthCount, increaseElementDepthCount, wasLastNodeCreated, isCurrentTNodeParent, setCurrentTNodeAsNotParent, assertHasParent, INTERNAL_APPLICATION_ERROR_HANDLER, stringify, getCurrentDirectiveIndex, unwrapLView, isCreationMode, enterView, leaveView, AFTER_RENDER_SEQUENCES_TO_ADD, markAncestorsForTraversal, markViewForRefresh, setIsRefreshingViews, isExhaustiveCheckNoChanges, requiresRefreshOrTraversal, setIsInCheckNoChangesMode, CheckNoChangesMode, setBindingIndex, EFFECTS_TO_SCHEDULE, viewAttachedToChangeDetector, setBindingRootForHostBindings, isRefreshingViews, removeFromArray, addToArray, updateAncestorTraversalFlagsOnAttach, storeLViewOnDestroy, VIEW_REFS, assertGreaterThanOrEqual, isInI18nBlock, assertTNodeForTView, getCurrentParentTNode, getCurrentTNodePlaceholderOk, assertTNode, assertTIcu, assertNumberInRange, DEHYDRATED_VIEWS, getNgModuleDef, getPipeDef as getPipeDef$1, getNgModuleDefOrThrow, isStandalone, concatStringsWithSpace, assertInjectImplementationNotEqual, emitInjectEvent, getConstant, assertLessThan, getOrCreateTViewCleanup, getOrCreateLViewCleanup, assertNotDefined, nextBindingIndex, getSelectedTNode, getDirectiveDefOrThrow, getTNode, assertComponentType, debugStringifyTypeForError, ChangeDetectionScheduler, EnvironmentInjector, SVG_NAMESPACE, MATH_ML_NAMESPACE, viewAttachedToContainer, storeCleanupWithContext, signal, createInjectorWithoutInjectorInstances, R3Injector, getNullInjector, internalImportProvidersFrom, initNgDevMode, fillProperties, getBindingsEnabled, lastNodeWasCreated, isInInjectionContext, DestroyRef, PendingTasksInternal, noop, ErrorHandler, assertNotInReactiveContext, assertInInjectionContext, ViewContext, removeLViewOnDestroy, walkUpViews, getNativeByIndex, assertElement, arrayInsert2, arraySplice, setInjectorProfiler, NullInjector, ENVIRONMENT_INITIALIZER, INJECTOR_DEF_TYPES, walkProviderTree, getInjectorDef, deepForEach, isTypeProvider, isSignal, runInInjectionContext, ZONELESS_ENABLED, EffectScheduler, PendingTasks, assertTNodeCreationIndex, isSkipHydrationRootTNode, leaveSkipHydrationBlock, decreaseElementDepthCount, getNamespace, enterSkipHydrationBlock, getCurrentDirectiveDef, assertIndexInExpandoRange, getBindingIndex, assertOneOf, setInI18nBlock, nextContextImpl, getCurrentQueryIndex, getContextLView, load, keyValueArrayIndexOf, keyValueArraySet, keyValueArrayGet, incrementBindingIndex, isWritableSignal, store, providerToFactory, emitProviderConfiguredEvent, isClassProvider, getBindingRoot, NG_COMP_DEF, ɵɵresetView as __resetView, ɵɵnamespaceHTML as __namespaceHTML, ɵɵnamespaceMathML as __namespaceMathML, ɵɵnamespaceSVG as __namespaceSVG, ɵɵenableBindings as __enableBindings, ɵɵdisableBindings as __disableBindings, ɵɵrestoreView as __restoreView, forwardRef, NG_MOD_DEF, NG_INJ_DEF, NG_DIR_DEF, NG_PIPE_DEF, ZONELESS_SCHEDULER_DISABLED, SCHEDULE_IN_ROOT_ZONE, PROVIDED_ZONELESS, getNativeByTNodeOrNull } from './root_effect_scheduler.mjs';
8
8
  import { setActiveConsumer, SIGNAL, consumerDestroy, REACTIVE_NODE, consumerPollProducersForChange, consumerBeforeComputation, getActiveConsumer, consumerAfterComputation, createComputed, setThrowInvalidWriteToSignalError } from './signal.mjs';
9
9
  import { Subject, Subscription } from 'rxjs';
10
10
  import { setActiveConsumer as setActiveConsumer$1 } from '@angular/core/primitives/signals';
@@ -7213,6 +7213,8 @@ function ensureIcuContainerVisitorLoaded(loader) {
7213
7213
 
7214
7214
  /** Parses a CSS time value to milliseconds. */
7215
7215
  function parseCssTimeUnitsToMs(value) {
7216
+ if (!value)
7217
+ return 0;
7216
7218
  // Some browsers will return it in seconds, whereas others will return milliseconds.
7217
7219
  const multiplier = value.toLowerCase().indexOf('ms') > -1 ? 1 : 1000;
7218
7220
  return parseFloat(value) * multiplier;
@@ -7323,11 +7325,54 @@ function determineLongestAnimationFromElementAnimations(el, animationsMap, anima
7323
7325
  }
7324
7326
  const allLeavingAnimations = new Set();
7325
7327
 
7328
+ /**
7329
+ * A [DI token](api/core/InjectionToken) that enables or disables all enter and leave animations.
7330
+ */
7331
+ const ANIMATIONS_DISABLED = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'AnimationsDisabled' : '', {
7332
+ providedIn: 'root',
7333
+ factory: () => false,
7334
+ });
7335
+ /**
7336
+ * A [DI token](api/core/InjectionToken) for the queue of all animations.
7337
+ */
7338
+ const ANIMATION_QUEUE = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'AnimationQueue' : '', {
7339
+ providedIn: 'root',
7340
+ factory: () => {
7341
+ return {
7342
+ queue: new Set(),
7343
+ isScheduled: false,
7344
+ };
7345
+ },
7346
+ });
7347
+ /**
7348
+ * A [DI token](api/core/InjectionToken) that configures the maximum animation timeout
7349
+ * before element removal. The default value mirrors from Chrome's cross document
7350
+ * navigation view transition timeout. It's intended to prevent people from accidentally
7351
+ * forgetting to call the removal function in their callback. Also serves as a delay
7352
+ * for when stylesheets are pruned.
7353
+ *
7354
+ * @publicApi 20.2
7355
+ */
7356
+ const MAX_ANIMATION_TIMEOUT = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'MaxAnimationTimeout' : '', {
7357
+ providedIn: 'root',
7358
+ factory: () => MAX_ANIMATION_TIMEOUT_DEFAULT,
7359
+ });
7360
+ const MAX_ANIMATION_TIMEOUT_DEFAULT = 4000;
7361
+
7362
+ function maybeQueueEnterAnimation(parentLView, parent, tNode, injector) {
7363
+ const enterAnimations = parentLView?.[ANIMATIONS]?.enter;
7364
+ if (parent !== null && enterAnimations && enterAnimations.has(tNode.index)) {
7365
+ const animationQueue = injector.get(ANIMATION_QUEUE);
7366
+ for (const animateFn of enterAnimations.get(tNode.index).animateFns) {
7367
+ animationQueue.queue.add(animateFn);
7368
+ }
7369
+ }
7370
+ }
7326
7371
  /**
7327
7372
  * NOTE: for performance reasons, the possible actions are inlined within the function instead of
7328
7373
  * being passed as an argument.
7329
7374
  */
7330
- function applyToElementOrContainer(action, renderer, parent, lNodeToHandle, beforeNode, parentLView) {
7375
+ function applyToElementOrContainer(action, renderer, injector, parent, lNodeToHandle, tNode, beforeNode, parentLView) {
7331
7376
  // If this slot was allocated for a text node dynamically created by i18n, the text node itself
7332
7377
  // won't be created until i18nApply() in the update block, so this node should be skipped.
7333
7378
  // For more info, see "ICU expressions should work inside an ngTemplateOutlet inside an ngFor"
@@ -7348,6 +7393,7 @@ function applyToElementOrContainer(action, renderer, parent, lNodeToHandle, befo
7348
7393
  }
7349
7394
  const rNode = unwrapRNode(lNodeToHandle);
7350
7395
  if (action === 0 /* WalkTNodeTreeAction.Create */ && parent !== null) {
7396
+ maybeQueueEnterAnimation(parentLView, parent, tNode, injector);
7351
7397
  if (beforeNode == null) {
7352
7398
  nativeAppendChild(renderer, parent, rNode);
7353
7399
  }
@@ -7356,10 +7402,11 @@ function applyToElementOrContainer(action, renderer, parent, lNodeToHandle, befo
7356
7402
  }
7357
7403
  }
7358
7404
  else if (action === 1 /* WalkTNodeTreeAction.Insert */ && parent !== null) {
7405
+ maybeQueueEnterAnimation(parentLView, parent, tNode, injector);
7359
7406
  nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);
7360
7407
  }
7361
7408
  else if (action === 2 /* WalkTNodeTreeAction.Detach */) {
7362
- runLeaveAnimationsWithCallback(parentLView, (nodeHasLeaveAnimations) => {
7409
+ runLeaveAnimationsWithCallback(parentLView, tNode, injector, (nodeHasLeaveAnimations) => {
7363
7410
  // the nodeHasLeaveAnimations indicates to the renderer that the element needs to
7364
7411
  // be removed synchronously and sets the requireSynchronousElementRemoval flag in
7365
7412
  // the renderer.
@@ -7367,15 +7414,26 @@ function applyToElementOrContainer(action, renderer, parent, lNodeToHandle, befo
7367
7414
  });
7368
7415
  }
7369
7416
  else if (action === 3 /* WalkTNodeTreeAction.Destroy */) {
7370
- runLeaveAnimationsWithCallback(parentLView, () => {
7417
+ runLeaveAnimationsWithCallback(parentLView, tNode, injector, () => {
7371
7418
  renderer.destroyNode(rNode);
7372
7419
  });
7373
7420
  }
7374
7421
  if (lContainer != null) {
7375
- applyContainer(renderer, action, lContainer, parent, beforeNode);
7422
+ applyContainer(renderer, action, injector, lContainer, tNode, parent, beforeNode);
7376
7423
  }
7377
7424
  }
7378
7425
  }
7426
+ function addToAnimationQueue(injector, animationFns) {
7427
+ const animationQueue = injector.get(ANIMATION_QUEUE);
7428
+ if (Array.isArray(animationFns)) {
7429
+ for (const animateFn of animationFns) {
7430
+ animationQueue.queue.add(animateFn);
7431
+ }
7432
+ }
7433
+ else {
7434
+ animationQueue.queue.add(animationFns);
7435
+ }
7436
+ }
7379
7437
  /**
7380
7438
  * Removes all DOM elements associated with a view.
7381
7439
  *
@@ -7549,30 +7607,46 @@ function cleanUpView(tView, lView) {
7549
7607
  setActiveConsumer(prevConsumer);
7550
7608
  }
7551
7609
  }
7552
- function runLeaveAnimationsWithCallback(lView, callback) {
7553
- if (lView && lView[ANIMATIONS] && lView[ANIMATIONS].leave) {
7554
- if (lView[ANIMATIONS].skipLeaveAnimations) {
7555
- lView[ANIMATIONS].skipLeaveAnimations = false;
7556
- }
7557
- else {
7558
- const leaveAnimations = lView[ANIMATIONS].leave;
7610
+ function runLeaveAnimationsWithCallback(lView, tNode, injector, callback) {
7611
+ const animations = lView?.[ANIMATIONS];
7612
+ if (animations == null || animations.leave == undefined || !animations.leave.has(tNode.index))
7613
+ return callback(false);
7614
+ // this is solely for move operations to prevent leave animations from running
7615
+ // on the moved nodes, which would have deleted the node.
7616
+ if (animations.skipLeaveAnimations) {
7617
+ animations.skipLeaveAnimations = false;
7618
+ return callback(false);
7619
+ }
7620
+ addToAnimationQueue(injector, () => {
7621
+ // it's possible that in the time between when the leave animation was
7622
+ // and the time it was executed, the data structure changed. So we need
7623
+ // to be safe here.
7624
+ if (animations.leave && animations.leave.has(tNode.index)) {
7625
+ const leaveAnimationMap = animations.leave;
7626
+ const leaveAnimations = leaveAnimationMap.get(tNode.index);
7559
7627
  const runningAnimations = [];
7560
- for (let index = 0; index < leaveAnimations.length; index++) {
7561
- const animateFn = leaveAnimations[index];
7562
- runningAnimations.push(animateFn());
7628
+ if (leaveAnimations) {
7629
+ for (let index = 0; index < leaveAnimations.animateFns.length; index++) {
7630
+ const animationFn = leaveAnimations.animateFns[index];
7631
+ const { promise } = animationFn();
7632
+ runningAnimations.push(promise);
7633
+ }
7563
7634
  }
7564
- lView[ANIMATIONS].running = Promise.allSettled(runningAnimations);
7565
- lView[ANIMATIONS].leave = undefined;
7635
+ animations.running = Promise.allSettled(runningAnimations);
7636
+ runAfterLeaveAnimations(lView, callback);
7566
7637
  }
7567
- }
7568
- runAfterLeaveAnimations(lView, callback);
7638
+ else {
7639
+ if (lView)
7640
+ allLeavingAnimations.delete(lView);
7641
+ callback(false);
7642
+ }
7643
+ });
7569
7644
  }
7570
7645
  function runAfterLeaveAnimations(lView, callback) {
7571
- if (lView && lView[ANIMATIONS] && lView[ANIMATIONS].running) {
7572
- lView[ANIMATIONS].running.then(() => {
7573
- if (lView[ANIMATIONS] && lView[ANIMATIONS].running) {
7574
- lView[ANIMATIONS].running = undefined;
7575
- }
7646
+ const runningAnimations = lView[ANIMATIONS]?.running;
7647
+ if (runningAnimations) {
7648
+ runningAnimations.then(() => {
7649
+ lView[ANIMATIONS].running = undefined;
7576
7650
  allLeavingAnimations.delete(lView);
7577
7651
  callback(true);
7578
7652
  });
@@ -7899,6 +7973,7 @@ function getBeforeNodeForView(viewIndexInContainer, lContainer) {
7899
7973
  function applyNodes(renderer, action, tNode, lView, parentRElement, beforeNode, isProjection) {
7900
7974
  while (tNode != null) {
7901
7975
  ngDevMode && assertTNodeForLView(tNode, lView);
7976
+ const injector = lView[INJECTOR];
7902
7977
  // Let declarations don't have corresponding DOM nodes so we skip over them.
7903
7978
  if (tNode.type === 128 /* TNodeType.LetDeclaration */) {
7904
7979
  tNode = tNode.next;
@@ -7917,22 +7992,22 @@ function applyNodes(renderer, action, tNode, lView, parentRElement, beforeNode,
7917
7992
  if (!isDetachedByI18n(tNode)) {
7918
7993
  if (tNodeType & 8 /* TNodeType.ElementContainer */) {
7919
7994
  applyNodes(renderer, action, tNode.child, lView, parentRElement, beforeNode, false);
7920
- applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode, lView);
7995
+ applyToElementOrContainer(action, renderer, injector, parentRElement, rawSlotValue, tNode, beforeNode, lView);
7921
7996
  }
7922
7997
  else if (tNodeType & 32 /* TNodeType.Icu */) {
7923
7998
  const nextRNode = icuContainerIterate(tNode, lView);
7924
7999
  let rNode;
7925
8000
  while ((rNode = nextRNode())) {
7926
- applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode, lView);
8001
+ applyToElementOrContainer(action, renderer, injector, parentRElement, rNode, tNode, beforeNode, lView);
7927
8002
  }
7928
- applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode, lView);
8003
+ applyToElementOrContainer(action, renderer, injector, parentRElement, rawSlotValue, tNode, beforeNode, lView);
7929
8004
  }
7930
8005
  else if (tNodeType & 16 /* TNodeType.Projection */) {
7931
8006
  applyProjectionRecursive(renderer, action, lView, tNode, parentRElement, beforeNode);
7932
8007
  }
7933
8008
  else {
7934
8009
  ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 4 /* TNodeType.Container */);
7935
- applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode, lView);
8010
+ applyToElementOrContainer(action, renderer, injector, parentRElement, rawSlotValue, tNode, beforeNode, lView);
7936
8011
  }
7937
8012
  }
7938
8013
  tNode = isProjection ? tNode.projectionNext : tNode.next;
@@ -7986,7 +8061,7 @@ function applyProjectionRecursive(renderer, action, lView, tProjectionNode, pare
7986
8061
  // This should be refactored and cleaned up.
7987
8062
  for (let i = 0; i < nodeToProjectOrRNodes.length; i++) {
7988
8063
  const rNode = nodeToProjectOrRNodes[i];
7989
- applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode, lView);
8064
+ applyToElementOrContainer(action, renderer, lView[INJECTOR], parentRElement, rNode, tProjectionNode, beforeNode, lView);
7990
8065
  }
7991
8066
  }
7992
8067
  else {
@@ -8013,7 +8088,7 @@ function applyProjectionRecursive(renderer, action, lView, tProjectionNode, pare
8013
8088
  * @param parentRElement parent DOM element for insertion/removal.
8014
8089
  * @param beforeNode Before which node the insertions should happen.
8015
8090
  */
8016
- function applyContainer(renderer, action, lContainer, parentRElement, beforeNode) {
8091
+ function applyContainer(renderer, action, injector, lContainer, tNode, parentRElement, beforeNode) {
8017
8092
  ngDevMode && assertLContainer(lContainer);
8018
8093
  const anchor = lContainer[NATIVE]; // LContainer has its own before node.
8019
8094
  const native = unwrapRNode(lContainer);
@@ -8028,7 +8103,7 @@ function applyContainer(renderer, action, lContainer, parentRElement, beforeNode
8028
8103
  // don't see a reason why they should be different, but they are.
8029
8104
  //
8030
8105
  // If they are we need to process the second anchor as well.
8031
- applyToElementOrContainer(action, renderer, parentRElement, anchor, beforeNode);
8106
+ applyToElementOrContainer(action, renderer, injector, parentRElement, anchor, tNode, beforeNode);
8032
8107
  }
8033
8108
  for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
8034
8109
  const lView = lContainer[i];
@@ -9126,7 +9201,6 @@ function refreshView(tView, lView, templateFn, context) {
9126
9201
  if (templateFn !== null) {
9127
9202
  executeTemplate(tView, lView, templateFn, 2 /* RenderFlags.Update */, context);
9128
9203
  }
9129
- runEnterAnimations(lView);
9130
9204
  const hooksInitPhaseCompleted = (flags & 3 /* LViewFlags.InitPhaseStateMask */) === 3 /* InitPhaseState.InitPhaseCompleted */;
9131
9205
  // execute pre-order hooks (OnInit, OnChanges, DoCheck)
9132
9206
  // PERF WARNING: do NOT extract this to a separate function without running benchmarks
@@ -9254,15 +9328,6 @@ function refreshView(tView, lView, templateFn, context) {
9254
9328
  leaveView();
9255
9329
  }
9256
9330
  }
9257
- function runEnterAnimations(lView) {
9258
- const animationData = lView[ANIMATIONS];
9259
- if (animationData?.enter) {
9260
- for (const animateFn of animationData.enter) {
9261
- animateFn();
9262
- }
9263
- animationData.enter = undefined;
9264
- }
9265
- }
9266
9331
  /**
9267
9332
  * Goes over embedded views (ones created through ViewContainerRef APIs) and refreshes
9268
9333
  * them by executing an associated template function.
@@ -13691,7 +13756,7 @@ class ComponentFactory extends ComponentFactory$1 {
13691
13756
  }
13692
13757
  function createRootTView(rootSelectorOrNode, componentDef, componentBindings, directives) {
13693
13758
  const tAttributes = rootSelectorOrNode
13694
- ? ['ng-version', '20.3.2']
13759
+ ? ['ng-version', '20.3.4']
13695
13760
  : // Extract attributes and classes from the first selector only to match VE behavior.
13696
13761
  extractAttrsAndClassesFromSelector(componentDef.selectors[0]);
13697
13762
  let creationBindings = null;
@@ -21830,14 +21895,13 @@ function ɵɵdeferHydrateOnViewport() {
21830
21895
  // since these instructions won't exist for dehydrated content.
21831
21896
  }
21832
21897
 
21833
- const ARIA_PREFIX = 'aria';
21834
21898
  /**
21835
- * Update an ARIA attribute by either its attribute or property name on a selected element.
21899
+ * Update an ARIA attribute on a selected element.
21836
21900
  *
21837
- * If the property name also exists as an input property on any of the element's directives, those
21838
- * inputs will be set instead of the element property.
21901
+ * If the attribute name also exists as an input property on any of the element's directives, those
21902
+ * inputs will be set instead of the element attribute.
21839
21903
  *
21840
- * @param name Name of the ARIA attribute or property (beginning with `aria`).
21904
+ * @param name Name of the ARIA attribute (beginning with `aria-`).
21841
21905
  * @param value New value to write.
21842
21906
  * @returns This function returns itself so that it may be chained.
21843
21907
  *
@@ -21857,31 +21921,12 @@ function ɵɵariaProperty(name, value) {
21857
21921
  else {
21858
21922
  ngDevMode && assertTNodeType(tNode, 2 /* TNodeType.Element */);
21859
21923
  const element = getNativeByTNode(tNode, lView);
21860
- const attributeName = ariaAttrName(name);
21861
- setElementAttribute(lView[RENDERER], element, null, tNode.value, attributeName, value, null);
21924
+ setElementAttribute(lView[RENDERER], element, null, tNode.value, name, value, null);
21862
21925
  }
21863
21926
  ngDevMode && storePropertyBindingMetadata(tView.data, tNode, name, bindingIndex);
21864
21927
  }
21865
21928
  return ɵɵariaProperty;
21866
21929
  }
21867
- /**
21868
- * Converts an ARIA property name to its corresponding attribute name, if necessary.
21869
- *
21870
- * For example, converts `ariaLabel` to `aria-label`.
21871
- *
21872
- * https://www.w3.org/TR/wai-aria-1.2/#accessibilityroleandproperties-correspondence
21873
- *
21874
- * This must be kept in sync with the the function of the same name in
21875
- * packages/compiler/src/template/pipeline/src/phases/reify.ts
21876
- *
21877
- * @param name A property name that starts with `aria`.
21878
- * @returns The corresponding attribute name.
21879
- */
21880
- function ariaAttrName(name) {
21881
- return name.charAt(ARIA_PREFIX.length) !== '-'
21882
- ? ARIA_PREFIX + '-' + name.slice(ARIA_PREFIX.length).toLowerCase()
21883
- : name; // Property already has attribute name.
21884
- }
21885
21930
 
21886
21931
  /**
21887
21932
  * Updates the value of or removes a bound attribute on an Element.
@@ -21908,28 +21953,6 @@ function ɵɵattribute(name, value, sanitizer, namespace) {
21908
21953
  return ɵɵattribute;
21909
21954
  }
21910
21955
 
21911
- /**
21912
- * A [DI token](api/core/InjectionToken) that enables or disables all enter and leave animations.
21913
- */
21914
- const ANIMATIONS_DISABLED = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'AnimationsDisabled' : '', {
21915
- providedIn: 'root',
21916
- factory: () => false,
21917
- });
21918
- /**
21919
- * A [DI token](api/core/InjectionToken) that configures the maximum animation timeout
21920
- * before element removal. The default value mirrors from Chrome's cross document
21921
- * navigation view transition timeout. It's intended to prevent people from accidentally
21922
- * forgetting to call the removal function in their callback. Also serves as a delay
21923
- * for when stylesheets are pruned.
21924
- *
21925
- * @publicApi 20.2
21926
- */
21927
- const MAX_ANIMATION_TIMEOUT = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'MaxAnimationTimeout' : '', {
21928
- providedIn: 'root',
21929
- factory: () => MAX_ANIMATION_TIMEOUT_DEFAULT,
21930
- });
21931
- const MAX_ANIMATION_TIMEOUT_DEFAULT = 4000;
21932
-
21933
21956
  const DEFAULT_ANIMATIONS_DISABLED = false;
21934
21957
  const areAnimationSupported = (typeof ngServerMode === 'undefined' || !ngServerMode) &&
21935
21958
  typeof document !== 'undefined' &&
@@ -22059,14 +22082,14 @@ function trackLeavingNodes(tNode, el) {
22059
22082
  */
22060
22083
  function getLViewEnterAnimations(lView) {
22061
22084
  const animationData = (lView[ANIMATIONS] ??= {});
22062
- return (animationData.enter ??= []);
22085
+ return (animationData.enter ??= new Map());
22063
22086
  }
22064
22087
  /**
22065
22088
  * Retrieves the list of specified leave animations from the lView
22066
22089
  */
22067
22090
  function getLViewLeaveAnimations(lView) {
22068
22091
  const animationData = (lView[ANIMATIONS] ??= {});
22069
- return (animationData.leave ??= []);
22092
+ return (animationData.leave ??= new Map());
22070
22093
  }
22071
22094
  /**
22072
22095
  * Gets the list of classes from a passed in value
@@ -22120,13 +22143,43 @@ function elementHasClassList(element, classList) {
22120
22143
  */
22121
22144
  function isLongestAnimation(event, nativeElement) {
22122
22145
  const longestAnimation = longestAnimations.get(nativeElement);
22146
+ // If we don't have any record of a longest animation, then we shouldn't
22147
+ // block the animationend/transitionend event from doing its work.
22148
+ if (longestAnimation === undefined)
22149
+ return true;
22123
22150
  return (nativeElement === event.target &&
22124
- longestAnimation !== undefined &&
22125
22151
  ((longestAnimation.animationName !== undefined &&
22126
22152
  event.animationName === longestAnimation.animationName) ||
22127
22153
  (longestAnimation.propertyName !== undefined &&
22128
22154
  event.propertyName === longestAnimation.propertyName)));
22129
22155
  }
22156
+ /**
22157
+ * Stores a given animation function in the LView's animation map for later execution
22158
+ *
22159
+ * @param animations Either the enter or leave animation map from the LView
22160
+ * @param tNode The TNode the animation is associated with
22161
+ * @param fn The animation function to be called later
22162
+ */
22163
+ function addAnimationToLView(animations, tNode, fn) {
22164
+ const nodeAnimations = animations.get(tNode.index) ?? { animateFns: [] };
22165
+ nodeAnimations.animateFns.push(fn);
22166
+ animations.set(tNode.index, nodeAnimations);
22167
+ }
22168
+ function cleanupAfterLeaveAnimations(resolvers, cleanupFns) {
22169
+ if (resolvers) {
22170
+ for (const fn of resolvers) {
22171
+ fn();
22172
+ }
22173
+ }
22174
+ for (const fn of cleanupFns) {
22175
+ fn();
22176
+ }
22177
+ }
22178
+ function clearLViewNodeAnimationResolvers(lView, tNode) {
22179
+ const nodeAnimations = getLViewLeaveAnimations(lView).get(tNode.index);
22180
+ if (nodeAnimations)
22181
+ nodeAnimations.resolvers = undefined;
22182
+ }
22130
22183
 
22131
22184
  /**
22132
22185
  * Instruction to handle the `animate.enter` behavior for class bindings.
@@ -22148,7 +22201,8 @@ function ɵɵanimateEnter(value) {
22148
22201
  }
22149
22202
  const tNode = getCurrentTNode();
22150
22203
  cancelLeavingNodes(tNode, lView);
22151
- getLViewEnterAnimations(lView).push(() => runEnterAnimation(lView, tNode, value));
22204
+ addAnimationToLView(getLViewEnterAnimations(lView), tNode, () => runEnterAnimation(lView, tNode, value));
22205
+ queueEnterAnimations(lView);
22152
22206
  return ɵɵanimateEnter; // For chaining
22153
22207
  }
22154
22208
  function runEnterAnimation(lView, tNode, value) {
@@ -22165,13 +22219,19 @@ function runEnterAnimation(lView, tNode, value) {
22165
22219
  // This also allows us to setup cancellation of animations in progress if the
22166
22220
  // gets removed early.
22167
22221
  const handleEnterAnimationStart = (event) => {
22222
+ // this early exit case is to prevent issues with bubbling events that are from child element animations
22223
+ if (event.target !== nativeElement)
22224
+ return;
22168
22225
  const eventName = event instanceof AnimationEvent ? 'animationend' : 'transitionend';
22169
22226
  ngZone.runOutsideAngular(() => {
22170
- cleanupFns.push(renderer.listen(nativeElement, eventName, handleEnterAnimationEnd));
22227
+ renderer.listen(nativeElement, eventName, handleEnterAnimationEnd);
22171
22228
  });
22172
22229
  };
22173
22230
  // When the longest animation ends, we can remove all the classes
22174
22231
  const handleEnterAnimationEnd = (event) => {
22232
+ // this early exit case is to prevent issues with bubbling events that are from child element animations
22233
+ if (event.target !== nativeElement)
22234
+ return;
22175
22235
  enterAnimationEnd(event, nativeElement, renderer);
22176
22236
  };
22177
22237
  // We only need to add these event listeners if there are actual classes to apply
@@ -22202,7 +22262,8 @@ function runEnterAnimation(lView, tNode, value) {
22202
22262
  }
22203
22263
  function enterAnimationEnd(event, nativeElement, renderer) {
22204
22264
  const elementData = enterClassMap.get(nativeElement);
22205
- if (!elementData)
22265
+ // this event.target check is to prevent issues with bubbling events that are from child element animations
22266
+ if (event.target !== nativeElement || !elementData)
22206
22267
  return;
22207
22268
  if (isLongestAnimation(event, nativeElement)) {
22208
22269
  // Now that we've found the longest animation, there's no need
@@ -22237,7 +22298,8 @@ function ɵɵanimateEnterListener(value) {
22237
22298
  }
22238
22299
  const tNode = getCurrentTNode();
22239
22300
  cancelLeavingNodes(tNode, lView);
22240
- getLViewEnterAnimations(lView).push(() => runEnterAnimationFunction(lView, tNode, value));
22301
+ addAnimationToLView(getLViewEnterAnimations(lView), tNode, () => runEnterAnimationFunction(lView, tNode, value));
22302
+ queueEnterAnimations(lView);
22241
22303
  return ɵɵanimateEnterListener;
22242
22304
  }
22243
22305
  /**
@@ -22270,37 +22332,39 @@ function ɵɵanimateLeave(value) {
22270
22332
  return ɵɵanimateLeave;
22271
22333
  }
22272
22334
  const tNode = getCurrentTNode();
22273
- getLViewLeaveAnimations(lView).push(() => runLeaveAnimations(lView, tNode, value, animationsDisabled));
22335
+ addAnimationToLView(getLViewLeaveAnimations(lView), tNode, () => runLeaveAnimations(lView, tNode, value));
22336
+ enableAnimationQueueScheduler(lView[INJECTOR]);
22274
22337
  return ɵɵanimateLeave; // For chaining
22275
22338
  }
22276
- function runLeaveAnimations(lView, tNode, value, animationsDisabled) {
22339
+ function runLeaveAnimations(lView, tNode, value) {
22277
22340
  const { promise, resolve } = promiseWithResolvers();
22278
22341
  const nativeElement = getNativeByTNode(tNode, lView);
22279
22342
  ngDevMode && assertElementNodes(nativeElement, 'animate.leave');
22280
22343
  const renderer = lView[RENDERER];
22281
22344
  const ngZone = lView[INJECTOR].get(NgZone);
22282
22345
  allLeavingAnimations.add(lView);
22346
+ (getLViewLeaveAnimations(lView).get(tNode.index).resolvers ??= []).push(resolve);
22283
22347
  const activeClasses = getClassListFromValue(value);
22284
22348
  if (activeClasses && activeClasses.length > 0) {
22285
- animateLeaveClassRunner(nativeElement, tNode, activeClasses, renderer, animationsDisabled, ngZone, resolve);
22349
+ animateLeaveClassRunner(nativeElement, tNode, lView, activeClasses, renderer, ngZone);
22286
22350
  }
22287
22351
  else {
22288
22352
  resolve();
22289
22353
  }
22290
- return promise;
22354
+ return { promise, resolve };
22291
22355
  }
22292
22356
  /**
22293
22357
  * This function actually adds the classes that animate element that's leaving the DOM.
22294
22358
  * Once it finishes, it calls the remove function that was provided by the DOM renderer.
22295
22359
  */
22296
- function animateLeaveClassRunner(el, tNode, classList, renderer, animationsDisabled, ngZone, resolver) {
22297
- if (animationsDisabled) {
22298
- longestAnimations.delete(el);
22299
- resolver();
22300
- return;
22301
- }
22360
+ function animateLeaveClassRunner(el, tNode, lView, classList, renderer, ngZone) {
22302
22361
  cancelAnimationsIfRunning(el, renderer);
22362
+ const cleanupFns = [];
22363
+ const resolvers = getLViewLeaveAnimations(lView).get(tNode.index)?.resolvers;
22303
22364
  const handleOutAnimationEnd = (event) => {
22365
+ // this early exit case is to prevent issues with bubbling events that are from child element animations
22366
+ if (event.target !== el)
22367
+ return;
22304
22368
  if (event instanceof CustomEvent || isLongestAnimation(event, el)) {
22305
22369
  // Now that we've found the longest animation, there's no need
22306
22370
  // to keep bubbling up this event as it's not going to apply to
@@ -22317,12 +22381,13 @@ function animateLeaveClassRunner(el, tNode, classList, renderer, animationsDisab
22317
22381
  renderer.removeClass(el, item);
22318
22382
  }
22319
22383
  }
22384
+ cleanupAfterLeaveAnimations(resolvers, cleanupFns);
22385
+ clearLViewNodeAnimationResolvers(lView, tNode);
22320
22386
  }
22321
- resolver();
22322
22387
  };
22323
22388
  ngZone.runOutsideAngular(() => {
22324
- renderer.listen(el, 'animationend', handleOutAnimationEnd);
22325
- renderer.listen(el, 'transitionend', handleOutAnimationEnd);
22389
+ cleanupFns.push(renderer.listen(el, 'animationend', handleOutAnimationEnd));
22390
+ cleanupFns.push(renderer.listen(el, 'transitionend', handleOutAnimationEnd));
22326
22391
  });
22327
22392
  trackLeavingNodes(tNode, el);
22328
22393
  for (const item of classList) {
@@ -22336,7 +22401,8 @@ function animateLeaveClassRunner(el, tNode, classList, renderer, animationsDisab
22336
22401
  determineLongestAnimation(el, longestAnimations, areAnimationSupported);
22337
22402
  if (!longestAnimations.has(el)) {
22338
22403
  clearLeavingNodes(tNode, el);
22339
- resolver();
22404
+ cleanupAfterLeaveAnimations(resolvers, cleanupFns);
22405
+ clearLViewNodeAnimationResolvers(lView, tNode);
22340
22406
  }
22341
22407
  });
22342
22408
  });
@@ -22364,7 +22430,8 @@ function ɵɵanimateLeaveListener(value) {
22364
22430
  const lView = getLView();
22365
22431
  const tNode = getCurrentTNode();
22366
22432
  allLeavingAnimations.add(lView);
22367
- getLViewLeaveAnimations(lView).push(() => runLeaveAnimationFunction(lView, tNode, value));
22433
+ addAnimationToLView(getLViewLeaveAnimations(lView), tNode, () => runLeaveAnimationFunction(lView, tNode, value));
22434
+ enableAnimationQueueScheduler(lView[INJECTOR]);
22368
22435
  return ɵɵanimateLeaveListener; // For chaining
22369
22436
  }
22370
22437
  /**
@@ -22405,6 +22472,35 @@ function runLeaveAnimationFunction(lView, tNode, value) {
22405
22472
  // Ensure cleanup if the LView is destroyed before the animation runs.
22406
22473
  return promise;
22407
22474
  }
22475
+ function queueEnterAnimations(lView) {
22476
+ enableAnimationQueueScheduler(lView[INJECTOR]);
22477
+ const enterAnimations = lView[ANIMATIONS]?.enter;
22478
+ if (enterAnimations) {
22479
+ const animationQueue = lView[INJECTOR].get(ANIMATION_QUEUE);
22480
+ for (const [_, nodeAnimations] of enterAnimations) {
22481
+ for (const animateFn of nodeAnimations.animateFns) {
22482
+ animationQueue.queue.add(animateFn);
22483
+ }
22484
+ }
22485
+ }
22486
+ }
22487
+ function enableAnimationQueueScheduler(injector) {
22488
+ const animationQueue = injector.get(ANIMATION_QUEUE);
22489
+ // We only need to schedule the animation queue runner once per application.
22490
+ if (!animationQueue.isScheduled) {
22491
+ afterEveryRender(() => {
22492
+ runQueuedAnimations(injector);
22493
+ }, { injector });
22494
+ animationQueue.isScheduled = true;
22495
+ }
22496
+ }
22497
+ function runQueuedAnimations(injector) {
22498
+ const animationQueue = injector.get(ANIMATION_QUEUE);
22499
+ for (let animateFn of animationQueue.queue) {
22500
+ animateFn();
22501
+ }
22502
+ animationQueue.queue.clear();
22503
+ }
22408
22504
 
22409
22505
  /*!
22410
22506
  * @license