@angular/core 20.2.0-next.1 → 20.2.0-next.2

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 (69) hide show
  1. package/api.d.d.ts +1 -1
  2. package/chrome_dev_tools_performance.d.d.ts +1 -1
  3. package/discovery.d.d.ts +1 -1
  4. package/event_dispatcher.d.d.ts +1 -1
  5. package/fesm2022/attribute.mjs +1 -1
  6. package/fesm2022/attribute.mjs.map +1 -1
  7. package/fesm2022/core.mjs +29 -32
  8. package/fesm2022/core.mjs.map +1 -1
  9. package/fesm2022/debug_node.mjs +599 -7
  10. package/fesm2022/debug_node.mjs.map +1 -1
  11. package/fesm2022/not_found.mjs +1 -1
  12. package/fesm2022/not_found.mjs.map +1 -1
  13. package/fesm2022/primitives/di.mjs +1 -1
  14. package/fesm2022/primitives/di.mjs.map +1 -1
  15. package/fesm2022/primitives/event-dispatch.mjs +1 -1
  16. package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
  17. package/fesm2022/primitives/signals.mjs +1 -1
  18. package/fesm2022/primitives/signals.mjs.map +1 -1
  19. package/fesm2022/resource.mjs +8 -5
  20. package/fesm2022/resource.mjs.map +1 -1
  21. package/fesm2022/root_effect_scheduler.mjs +16 -2
  22. package/fesm2022/root_effect_scheduler.mjs.map +1 -1
  23. package/fesm2022/rxjs-interop.mjs +1 -1
  24. package/fesm2022/rxjs-interop.mjs.map +1 -1
  25. package/fesm2022/signal.mjs +1 -1
  26. package/fesm2022/signal.mjs.map +1 -1
  27. package/fesm2022/testing.mjs +16 -8
  28. package/fesm2022/testing.mjs.map +1 -1
  29. package/fesm2022/untracked.mjs +1 -1
  30. package/fesm2022/untracked.mjs.map +1 -1
  31. package/fesm2022/weak_ref.mjs +1 -1
  32. package/fesm2022/weak_ref.mjs.map +1 -1
  33. package/graph.d.d.ts +1 -1
  34. package/index.d.ts +149 -3
  35. package/package.json +2 -2
  36. package/primitives/di/index.d.ts +1 -1
  37. package/primitives/event-dispatch/index.d.ts +1 -1
  38. package/primitives/signals/index.d.ts +1 -1
  39. package/rxjs-interop/index.d.ts +1 -1
  40. package/schematics/bundles/{apply_import_manager-ceekZYTK.cjs → apply_import_manager-Bkosyy2x.cjs} +3 -3
  41. package/schematics/bundles/{checker-BVY3FNBy.cjs → checker-Cfq29XaS.cjs} +693 -189
  42. package/schematics/bundles/cleanup-unused-imports.cjs +5 -5
  43. package/schematics/bundles/{compiler_host-DRAgYPzr.cjs → compiler_host-CSrf1kFh.cjs} +2 -2
  44. package/schematics/bundles/control-flow-migration.cjs +3 -3
  45. package/schematics/bundles/document-core.cjs +5 -5
  46. package/schematics/bundles/imports-CIX-JgAN.cjs +1 -1
  47. package/schematics/bundles/{index-B7rvD9dh.cjs → index-DYbdsCUu.cjs} +79 -42
  48. package/schematics/bundles/{index-DkKydW5H.cjs → index-DwmX8Ifa.cjs} +4 -4
  49. package/schematics/bundles/inject-flags.cjs +5 -5
  50. package/schematics/bundles/inject-migration.cjs +3 -3
  51. package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
  52. package/schematics/bundles/{migrate_ts_type_references-BRFh6uWT.cjs → migrate_ts_type_references-C7NB9fZH.cjs} +5 -5
  53. package/schematics/bundles/ng_decorators-B5HCqr20.cjs +1 -1
  54. package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
  55. package/schematics/bundles/output-migration.cjs +6 -6
  56. package/schematics/bundles/{project_paths-zgvnBQD8.cjs → project_paths-5CoqAjNK.cjs} +3 -3
  57. package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +1 -1
  58. package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
  59. package/schematics/bundles/route-lazy-loading.cjs +3 -3
  60. package/schematics/bundles/self-closing-tags-migration.cjs +4 -4
  61. package/schematics/bundles/signal-input-migration.cjs +7 -7
  62. package/schematics/bundles/signal-queries-migration.cjs +7 -7
  63. package/schematics/bundles/signals.cjs +7 -7
  64. package/schematics/bundles/standalone-migration.cjs +4 -4
  65. package/schematics/bundles/symbol-VPWguRxr.cjs +1 -1
  66. package/schematics/bundles/test-bed-get.cjs +4 -4
  67. package/signal.d.d.ts +1 -1
  68. package/testing/index.d.ts +12 -2
  69. package/weak_ref.d.d.ts +1 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v20.2.0-next.1
3
+ * @license Angular v20.2.0-next.2
4
4
  * (c) 2010-2025 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -2693,7 +2693,18 @@ class Identifiers {
2693
2693
  static pipeBind4 = { name: 'ɵɵpipeBind4', moduleName: CORE };
2694
2694
  static pipeBindV = { name: 'ɵɵpipeBindV', moduleName: CORE };
2695
2695
  static domProperty = { name: 'ɵɵdomProperty', moduleName: CORE };
2696
+ static ariaProperty = { name: 'ɵɵariaProperty', moduleName: CORE };
2696
2697
  static property = { name: 'ɵɵproperty', moduleName: CORE };
2698
+ static animationEnterListener = {
2699
+ name: 'ɵɵanimateEnterListener',
2700
+ moduleName: CORE,
2701
+ };
2702
+ static animationLeaveListener = {
2703
+ name: 'ɵɵanimateLeaveListener',
2704
+ moduleName: CORE,
2705
+ };
2706
+ static animationEnter = { name: 'ɵɵanimateEnter', moduleName: CORE };
2707
+ static animationLeave = { name: 'ɵɵanimateLeave', moduleName: CORE };
2697
2708
  static i18n = { name: 'ɵɵi18n', moduleName: CORE };
2698
2709
  static i18nAttributes = { name: 'ɵɵi18nAttributes', moduleName: CORE };
2699
2710
  static i18nExp = { name: 'ɵɵi18nExp', moduleName: CORE };
@@ -2837,6 +2848,10 @@ class Identifiers {
2837
2848
  name: 'ɵɵExternalStylesFeature',
2838
2849
  moduleName: CORE,
2839
2850
  };
2851
+ static AnimationsFeature = {
2852
+ name: 'ɵɵAnimationsFeature',
2853
+ moduleName: CORE,
2854
+ };
2840
2855
  static listener = { name: 'ɵɵlistener', moduleName: CORE };
2841
2856
  static getInheritedFactory = {
2842
2857
  name: 'ɵɵgetInheritedFactory',
@@ -4412,6 +4427,7 @@ class ParsedProperty {
4412
4427
  valueSpan;
4413
4428
  isLiteral;
4414
4429
  isLegacyAnimation;
4430
+ isAnimation;
4415
4431
  constructor(name, expression, type, sourceSpan, keySpan, valueSpan) {
4416
4432
  this.name = name;
4417
4433
  this.expression = expression;
@@ -4421,6 +4437,7 @@ class ParsedProperty {
4421
4437
  this.valueSpan = valueSpan;
4422
4438
  this.isLiteral = this.type === ParsedPropertyType.LITERAL_ATTR;
4423
4439
  this.isLegacyAnimation = this.type === ParsedPropertyType.LEGACY_ANIMATION;
4440
+ this.isAnimation = this.type === ParsedPropertyType.ANIMATION;
4424
4441
  }
4425
4442
  }
4426
4443
  var ParsedPropertyType;
@@ -4429,6 +4446,7 @@ var ParsedPropertyType;
4429
4446
  ParsedPropertyType[ParsedPropertyType["LITERAL_ATTR"] = 1] = "LITERAL_ATTR";
4430
4447
  ParsedPropertyType[ParsedPropertyType["LEGACY_ANIMATION"] = 2] = "LEGACY_ANIMATION";
4431
4448
  ParsedPropertyType[ParsedPropertyType["TWO_WAY"] = 3] = "TWO_WAY";
4449
+ ParsedPropertyType[ParsedPropertyType["ANIMATION"] = 4] = "ANIMATION";
4432
4450
  })(ParsedPropertyType || (ParsedPropertyType = {}));
4433
4451
  exports.ParsedEventType = void 0;
4434
4452
  (function (ParsedEventType) {
@@ -4438,6 +4456,8 @@ exports.ParsedEventType = void 0;
4438
4456
  ParsedEventType[ParsedEventType["LegacyAnimation"] = 1] = "LegacyAnimation";
4439
4457
  // Event side of a two-way binding (e.g. `[(property)]="expression"`).
4440
4458
  ParsedEventType[ParsedEventType["TwoWay"] = 2] = "TwoWay";
4459
+ // Animation specific event
4460
+ ParsedEventType[ParsedEventType["Animation"] = 3] = "Animation";
4441
4461
  })(exports.ParsedEventType || (exports.ParsedEventType = {}));
4442
4462
  class ParsedEvent {
4443
4463
  name;
@@ -4488,6 +4508,8 @@ exports.BindingType = void 0;
4488
4508
  BindingType[BindingType["LegacyAnimation"] = 4] = "LegacyAnimation";
4489
4509
  // Property side of a two-way binding (e.g. `[(property)]="expression"`).
4490
4510
  BindingType[BindingType["TwoWay"] = 5] = "TwoWay";
4511
+ // A binding to an animation CSS class or function (e.g. `[animate.leave]="expression"`).
4512
+ BindingType[BindingType["Animation"] = 6] = "Animation";
4491
4513
  })(exports.BindingType || (exports.BindingType = {}));
4492
4514
  class BoundElementProperty {
4493
4515
  name;
@@ -8618,6 +8640,22 @@ var OpKind;
8618
8640
  * Creation op that attaches the location at which an element was defined in a template to it.
8619
8641
  */
8620
8642
  OpKind[OpKind["SourceLocation"] = 52] = "SourceLocation";
8643
+ /**
8644
+ * An operation to bind animation css classes to an element.
8645
+ */
8646
+ OpKind[OpKind["Animation"] = 53] = "Animation";
8647
+ /**
8648
+ * An operation to bind animation css classes to an element.
8649
+ */
8650
+ OpKind[OpKind["AnimationString"] = 54] = "AnimationString";
8651
+ /**
8652
+ * An operation to bind animation css classes to an element.
8653
+ */
8654
+ OpKind[OpKind["AnimationBinding"] = 55] = "AnimationBinding";
8655
+ /**
8656
+ * An operation to bind animation events to an element.
8657
+ */
8658
+ OpKind[OpKind["AnimationListener"] = 56] = "AnimationListener";
8621
8659
  })(OpKind || (OpKind = {}));
8622
8660
  /**
8623
8661
  * Distinguishes different kinds of IR expressions.
@@ -8808,6 +8846,10 @@ var BindingKind;
8808
8846
  * Property side of a two-way binding.
8809
8847
  */
8810
8848
  BindingKind[BindingKind["TwoWayProperty"] = 7] = "TwoWayProperty";
8849
+ /**
8850
+ * Property side of an animation binding.
8851
+ */
8852
+ BindingKind[BindingKind["Animation"] = 8] = "Animation";
8811
8853
  })(BindingKind || (BindingKind = {}));
8812
8854
  /**
8813
8855
  * Enumeration of possible times i18n params can be resolved.
@@ -9048,13 +9090,13 @@ function createBindingOp(target, kind, name, expression, unit, securityContext,
9048
9090
  /**
9049
9091
  * Create a `PropertyOp`.
9050
9092
  */
9051
- function createPropertyOp(target, name, expression, isLegacyAnimationTrigger, securityContext, isStructuralTemplateAttribute, templateKind, i18nContext, i18nMessage, sourceSpan) {
9093
+ function createPropertyOp(target, name, expression, bindingKind, securityContext, isStructuralTemplateAttribute, templateKind, i18nContext, i18nMessage, sourceSpan) {
9052
9094
  return {
9053
9095
  kind: OpKind.Property,
9054
9096
  target,
9055
9097
  name,
9056
9098
  expression,
9057
- isLegacyAnimationTrigger,
9099
+ bindingKind,
9058
9100
  securityContext,
9059
9101
  sanitizer: null,
9060
9102
  isStructuralTemplateAttribute,
@@ -9205,6 +9247,24 @@ function createRepeaterOp(repeaterCreate, targetSlot, collection, sourceSpan) {
9205
9247
  ...TRAIT_DEPENDS_ON_SLOT_CONTEXT,
9206
9248
  };
9207
9249
  }
9250
+ /**
9251
+ * Create an `AnimationBindingOp`.
9252
+ */
9253
+ function createAnimationBindingOp(name, target, animationKind, expression, securityContext, sourceSpan, animationBindingKind) {
9254
+ return {
9255
+ kind: OpKind.AnimationBinding,
9256
+ name,
9257
+ target,
9258
+ animationKind,
9259
+ expression,
9260
+ i18nMessage: null,
9261
+ securityContext,
9262
+ sanitizer: null,
9263
+ sourceSpan,
9264
+ animationBindingKind,
9265
+ ...NEW_OP,
9266
+ };
9267
+ }
9208
9268
  function createDeferWhenOp(target, expr, modifier, sourceSpan) {
9209
9269
  return {
9210
9270
  kind: OpKind.DeferWhen,
@@ -10035,6 +10095,8 @@ function transformExpressionsInOp(op, transform, flags) {
10035
10095
  case OpKind.StyleMap:
10036
10096
  case OpKind.ClassProp:
10037
10097
  case OpKind.ClassMap:
10098
+ case OpKind.AnimationString:
10099
+ case OpKind.AnimationBinding:
10038
10100
  case OpKind.Binding:
10039
10101
  if (op.expression instanceof Interpolation) {
10040
10102
  transformExpressionsInInterpolation(op.expression, transform, flags);
@@ -10087,6 +10149,8 @@ function transformExpressionsInOp(op, transform, flags) {
10087
10149
  op.contextValue = transformExpressionsInExpression(op.contextValue, transform, flags);
10088
10150
  }
10089
10151
  break;
10152
+ case OpKind.Animation:
10153
+ case OpKind.AnimationListener:
10090
10154
  case OpKind.Listener:
10091
10155
  case OpKind.TwoWayListener:
10092
10156
  for (const innerOp of op.handlerOps) {
@@ -10738,6 +10802,43 @@ function createTextOp(xref, initialValue, icuPlaceholder, sourceSpan) {
10738
10802
  ...NEW_OP,
10739
10803
  };
10740
10804
  }
10805
+ /**
10806
+ * Create an `AnimationOp`.
10807
+ */
10808
+ function createAnimationStringOp(name, target, animationKind, expression, securityContext, sourceSpan) {
10809
+ return {
10810
+ kind: OpKind.AnimationString,
10811
+ name,
10812
+ target,
10813
+ animationKind,
10814
+ expression,
10815
+ i18nMessage: null,
10816
+ securityContext,
10817
+ sanitizer: null,
10818
+ sourceSpan,
10819
+ ...NEW_OP,
10820
+ };
10821
+ }
10822
+ /**
10823
+ * Create an `AnimationOp`.
10824
+ */
10825
+ function createAnimationOp(name, target, animationKind, callbackOps, securityContext, sourceSpan) {
10826
+ const handlerOps = new OpList();
10827
+ handlerOps.push(callbackOps);
10828
+ return {
10829
+ kind: OpKind.Animation,
10830
+ name,
10831
+ target,
10832
+ animationKind,
10833
+ handlerOps,
10834
+ handlerFnName: null,
10835
+ i18nMessage: null,
10836
+ securityContext,
10837
+ sanitizer: null,
10838
+ sourceSpan,
10839
+ ...NEW_OP,
10840
+ };
10841
+ }
10741
10842
  /**
10742
10843
  * Create a `ListenerOp`. Host bindings reuse all the listener logic.
10743
10844
  */
@@ -10761,6 +10862,28 @@ function createListenerOp(target, targetSlot, name, tag, handlerOps, legacyAnima
10761
10862
  ...NEW_OP,
10762
10863
  };
10763
10864
  }
10865
+ /**
10866
+ * Create a `ListenerOp`. Host bindings reuse all the listener logic.
10867
+ */
10868
+ function createAnimationListenerOp(target, targetSlot, name, tag, handlerOps, animationKind, eventTarget, hostListener, sourceSpan) {
10869
+ const handlerList = new OpList();
10870
+ handlerList.push(handlerOps);
10871
+ return {
10872
+ kind: OpKind.AnimationListener,
10873
+ target,
10874
+ targetSlot,
10875
+ tag,
10876
+ hostListener,
10877
+ name,
10878
+ animationKind,
10879
+ handlerOps: handlerList,
10880
+ handlerFnName: null,
10881
+ consumesDollarEvent: false,
10882
+ eventTarget,
10883
+ sourceSpan,
10884
+ ...NEW_OP,
10885
+ };
10886
+ }
10764
10887
  /**
10765
10888
  * Create a `TwoWayListenerOp`.
10766
10889
  */
@@ -11010,12 +11133,12 @@ function createSourceLocationOp(templatePath, locations) {
11010
11133
  };
11011
11134
  }
11012
11135
 
11013
- function createDomPropertyOp(name, expression, isLegacyAnimationTrigger, i18nContext, securityContext, sourceSpan) {
11136
+ function createDomPropertyOp(name, expression, bindingKind, i18nContext, securityContext, sourceSpan) {
11014
11137
  return {
11015
11138
  kind: OpKind.DomProperty,
11016
11139
  name,
11017
11140
  expression,
11018
- isLegacyAnimationTrigger,
11141
+ bindingKind,
11019
11142
  i18nContext,
11020
11143
  securityContext,
11021
11144
  sanitizer: null,
@@ -11182,7 +11305,10 @@ class CompilationUnit {
11182
11305
  *ops() {
11183
11306
  for (const op of this.create) {
11184
11307
  yield op;
11185
- if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
11308
+ if (op.kind === OpKind.Listener ||
11309
+ op.kind === OpKind.Animation ||
11310
+ op.kind === OpKind.AnimationListener ||
11311
+ op.kind === OpKind.TwoWayListener) {
11186
11312
  for (const listenerOp of op.handlerOps) {
11187
11313
  yield listenerOp;
11188
11314
  }
@@ -11462,7 +11588,8 @@ function extractAttributes(job) {
11462
11588
  extractAttributeOp(unit, op, elements);
11463
11589
  break;
11464
11590
  case OpKind.Property:
11465
- if (!op.isLegacyAnimationTrigger) {
11591
+ if (op.bindingKind !== BindingKind.LegacyAnimation &&
11592
+ op.bindingKind !== BindingKind.Animation) {
11466
11593
  let bindingKind;
11467
11594
  if (op.i18nMessage !== null && op.templateKind === null) {
11468
11595
  // If the binding has an i18n context, it is an i18n attribute, and should have that
@@ -11480,14 +11607,14 @@ function extractAttributes(job) {
11480
11607
  createExtractedAttributeOp(op.target, bindingKind, null, op.name,
11481
11608
  /* expression */ null,
11482
11609
  /* i18nContext */ null,
11483
- /* i18nMessage */ null, op.securityContext), lookupElement$2(elements, op.target));
11610
+ /* i18nMessage */ null, op.securityContext), lookupElement$3(elements, op.target));
11484
11611
  }
11485
11612
  break;
11486
11613
  case OpKind.TwoWayProperty:
11487
11614
  OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.TwoWayProperty, null, op.name,
11488
11615
  /* expression */ null,
11489
11616
  /* i18nContext */ null,
11490
- /* i18nMessage */ null, op.securityContext), lookupElement$2(elements, op.target));
11617
+ /* i18nMessage */ null, op.securityContext), lookupElement$3(elements, op.target));
11491
11618
  break;
11492
11619
  case OpKind.StyleProp:
11493
11620
  case OpKind.ClassProp:
@@ -11500,7 +11627,7 @@ function extractAttributes(job) {
11500
11627
  OpList.insertBefore(createExtractedAttributeOp(op.target, BindingKind.Property, null, op.name,
11501
11628
  /* expression */ null,
11502
11629
  /* i18nContext */ null,
11503
- /* i18nMessage */ null, SecurityContext.STYLE), lookupElement$2(elements, op.target));
11630
+ /* i18nMessage */ null, SecurityContext.STYLE), lookupElement$3(elements, op.target));
11504
11631
  }
11505
11632
  break;
11506
11633
  case OpKind.Listener:
@@ -11520,7 +11647,7 @@ function extractAttributes(job) {
11520
11647
  unit.create.push(extractedAttributeOp);
11521
11648
  }
11522
11649
  else {
11523
- OpList.insertBefore(extractedAttributeOp, lookupElement$2(elements, op.target));
11650
+ OpList.insertBefore(extractedAttributeOp, lookupElement$3(elements, op.target));
11524
11651
  }
11525
11652
  }
11526
11653
  break;
@@ -11531,7 +11658,7 @@ function extractAttributes(job) {
11531
11658
  /* expression */ null,
11532
11659
  /* i18nContext */ null,
11533
11660
  /* i18nMessage */ null, SecurityContext.NONE);
11534
- OpList.insertBefore(extractedAttributeOp, lookupElement$2(elements, op.target));
11661
+ OpList.insertBefore(extractedAttributeOp, lookupElement$3(elements, op.target));
11535
11662
  }
11536
11663
  break;
11537
11664
  }
@@ -11541,7 +11668,7 @@ function extractAttributes(job) {
11541
11668
  /**
11542
11669
  * Looks up an element in the given map by xref ID.
11543
11670
  */
11544
- function lookupElement$2(elements, xref) {
11671
+ function lookupElement$3(elements, xref) {
11545
11672
  const el = elements.get(xref);
11546
11673
  if (el === undefined) {
11547
11674
  throw new Error('All attributes should have an element-like target.');
@@ -11569,7 +11696,7 @@ function extractAttributeOp(unit, op, elements) {
11569
11696
  unit.create.push(extractedAttributeOp);
11570
11697
  }
11571
11698
  else {
11572
- const ownerOp = lookupElement$2(elements, op.target);
11699
+ const ownerOp = lookupElement$3(elements, op.target);
11573
11700
  OpList.insertBefore(extractedAttributeOp, ownerOp);
11574
11701
  }
11575
11702
  OpList.remove(op);
@@ -11579,7 +11706,7 @@ function extractAttributeOp(unit, op, elements) {
11579
11706
  /**
11580
11707
  * Looks up an element in the given map by xref ID.
11581
11708
  */
11582
- function lookupElement$1(elements, xref) {
11709
+ function lookupElement$2(elements, xref) {
11583
11710
  const el = elements.get(xref);
11584
11711
  if (el === undefined) {
11585
11712
  throw new Error('All attributes should have an element-like target.');
@@ -11605,21 +11732,27 @@ function specializeBindings(job) {
11605
11732
  case BindingKind.Attribute:
11606
11733
  if (op.name === 'ngNonBindable') {
11607
11734
  OpList.remove(op);
11608
- const target = lookupElement$1(elements, op.target);
11735
+ const target = lookupElement$2(elements, op.target);
11609
11736
  target.nonBindable = true;
11610
11737
  }
11738
+ else if (op.name.startsWith('animate.')) {
11739
+ OpList.replace(op, createAnimationBindingOp(op.name, op.target, op.name === 'animate.enter' ? "enter" /* ir.AnimationKind.ENTER */ : "leave" /* ir.AnimationKind.LEAVE */, op.expression, op.securityContext, op.sourceSpan, 0 /* ir.AnimationBindingKind.STRING */));
11740
+ }
11611
11741
  else {
11612
11742
  const [namespace, name] = splitNsName(op.name);
11613
11743
  OpList.replace(op, createAttributeOp(op.target, namespace, name, op.expression, op.securityContext, op.isTextAttribute, op.isStructuralTemplateAttribute, op.templateKind, op.i18nMessage, op.sourceSpan));
11614
11744
  }
11615
11745
  break;
11746
+ case BindingKind.Animation:
11747
+ OpList.replace(op, createAnimationBindingOp(op.name, op.target, op.name === 'animate.enter' ? "enter" /* ir.AnimationKind.ENTER */ : "leave" /* ir.AnimationKind.LEAVE */, op.expression, op.securityContext, op.sourceSpan, 1 /* ir.AnimationBindingKind.VALUE */));
11748
+ break;
11616
11749
  case BindingKind.Property:
11617
11750
  case BindingKind.LegacyAnimation:
11618
11751
  if (job.kind === CompilationJobKind.Host) {
11619
- OpList.replace(op, createDomPropertyOp(op.name, op.expression, op.bindingKind === BindingKind.LegacyAnimation, op.i18nContext, op.securityContext, op.sourceSpan));
11752
+ OpList.replace(op, createDomPropertyOp(op.name, op.expression, op.bindingKind, op.i18nContext, op.securityContext, op.sourceSpan));
11620
11753
  }
11621
11754
  else {
11622
- OpList.replace(op, createPropertyOp(op.target, op.name, op.expression, op.bindingKind === BindingKind.LegacyAnimation, op.securityContext, op.isStructuralTemplateAttribute, op.templateKind, op.i18nContext, op.i18nMessage, op.sourceSpan));
11755
+ OpList.replace(op, createPropertyOp(op.target, op.name, op.expression, op.bindingKind, op.securityContext, op.isStructuralTemplateAttribute, op.templateKind, op.i18nContext, op.i18nMessage, op.sourceSpan));
11623
11756
  }
11624
11757
  break;
11625
11758
  case BindingKind.TwoWayProperty:
@@ -11641,6 +11774,7 @@ function specializeBindings(job) {
11641
11774
  }
11642
11775
 
11643
11776
  const CHAIN_COMPATIBILITY = new Map([
11777
+ [Identifiers.ariaProperty, Identifiers.ariaProperty],
11644
11778
  [Identifiers.attribute, Identifiers.attribute],
11645
11779
  [Identifiers.classProp, Identifiers.classProp],
11646
11780
  [Identifiers.element, Identifiers.element],
@@ -11671,6 +11805,10 @@ const CHAIN_COMPATIBILITY = new Map([
11671
11805
  [Identifiers.domElementContainerEnd, Identifiers.domElementContainerEnd],
11672
11806
  [Identifiers.domListener, Identifiers.domListener],
11673
11807
  [Identifiers.domTemplate, Identifiers.domTemplate],
11808
+ [Identifiers.animationEnter, Identifiers.animationEnter],
11809
+ [Identifiers.animationLeave, Identifiers.animationLeave],
11810
+ [Identifiers.animationEnterListener, Identifiers.animationEnterListener],
11811
+ [Identifiers.animationLeaveListener, Identifiers.animationLeaveListener],
11674
11812
  ]);
11675
11813
  /**
11676
11814
  * Chaining results in repeated call expressions, causing a deep AST of receiver expressions. To prevent running out of
@@ -12091,6 +12229,52 @@ function serializeAttributes({ attributes, bindings, classes, i18n, projectAs, s
12091
12229
  return literalArr(attrArray);
12092
12230
  }
12093
12231
 
12232
+ /**
12233
+ * Looks up an element in the given map by xref ID.
12234
+ */
12235
+ function lookupElement$1(elements, xref) {
12236
+ const el = elements.get(xref);
12237
+ if (el === undefined) {
12238
+ throw new Error('All attributes should have an element-like target.');
12239
+ }
12240
+ return el;
12241
+ }
12242
+ function convertAnimations(job) {
12243
+ const elements = new Map();
12244
+ for (const unit of job.units) {
12245
+ for (const op of unit.create) {
12246
+ if (!isElementOrContainerOp(op)) {
12247
+ continue;
12248
+ }
12249
+ elements.set(op.xref, op);
12250
+ }
12251
+ }
12252
+ for (const unit of job.units) {
12253
+ for (const op of unit.ops()) {
12254
+ if (op.kind === OpKind.AnimationBinding) {
12255
+ const createAnimationOp = getAnimationOp(op);
12256
+ if (job.kind === CompilationJobKind.Host) {
12257
+ unit.create.push(createAnimationOp);
12258
+ }
12259
+ else {
12260
+ OpList.insertAfter(createAnimationOp, lookupElement$1(elements, op.target));
12261
+ }
12262
+ OpList.remove(op);
12263
+ }
12264
+ }
12265
+ }
12266
+ }
12267
+ function getAnimationOp(op) {
12268
+ if (op.animationBindingKind === 0 /* ir.AnimationBindingKind.STRING */) {
12269
+ // this is a simple string case
12270
+ return createAnimationStringOp(op.name, op.target, op.name === 'animate.enter' ? "enter" /* ir.AnimationKind.ENTER */ : "leave" /* ir.AnimationKind.LEAVE */, op.expression, op.securityContext, op.sourceSpan);
12271
+ }
12272
+ else {
12273
+ const expression = op.expression;
12274
+ return createAnimationOp(op.name, op.target, op.name === 'animate.enter' ? "enter" /* ir.AnimationKind.ENTER */ : "leave" /* ir.AnimationKind.LEAVE */, [createStatementOp(new ReturnStatement(expression, expression.sourceSpan))], op.securityContext, op.sourceSpan);
12275
+ }
12276
+ }
12277
+
12094
12278
  /**
12095
12279
  * Some binding instructions in the update block may actually correspond to i18n bindings. In that
12096
12280
  * case, they should be replaced with i18nExp instructions for the dynamic portions.
@@ -12988,6 +13172,8 @@ function recursivelyProcessView(view, parentScope) {
12988
13172
  op.trackByOps.prepend(generateVariablesInScopeForView(view, scope, false));
12989
13173
  }
12990
13174
  break;
13175
+ case OpKind.Animation:
13176
+ case OpKind.AnimationListener:
12991
13177
  case OpKind.Listener:
12992
13178
  case OpKind.TwoWayListener:
12993
13179
  // Prepend variables to listener handler functions.
@@ -13070,7 +13256,7 @@ function getScopeForView(view, parent) {
13070
13256
  * This is a recursive process, as views inherit variables available from their parent view, which
13071
13257
  * itself may have inherited variables, etc.
13072
13258
  */
13073
- function generateVariablesInScopeForView(view, scope, isListener) {
13259
+ function generateVariablesInScopeForView(view, scope, isCallback) {
13074
13260
  const newOps = [];
13075
13261
  if (scope.view !== view.xref) {
13076
13262
  // Before generating variables for a parent view, we need to switch to the context of the parent
@@ -13094,7 +13280,7 @@ function generateVariablesInScopeForView(view, scope, isListener) {
13094
13280
  for (const ref of scope.references) {
13095
13281
  newOps.push(createVariableOp(view.job.allocateXrefId(), ref.variable, new ReferenceExpr(ref.targetId, ref.targetSlot, ref.offset), VariableFlags.None));
13096
13282
  }
13097
- if (scope.view !== view.xref || isListener) {
13283
+ if (scope.view !== view.xref || isCallback) {
13098
13284
  for (const decl of scope.letDeclarations) {
13099
13285
  newOps.push(createVariableOp(view.job.allocateXrefId(), decl.variable, new ContextLetReferenceExpr(decl.targetId, decl.targetSlot), VariableFlags.None));
13100
13286
  }
@@ -16393,6 +16579,23 @@ class _Tokenizer {
16393
16579
  return isNameEnd(code);
16394
16580
  };
16395
16581
  }
16582
+ else if (attrNameStart === $LBRACKET) {
16583
+ let openBrackets = 0;
16584
+ // Be more permissive for which characters are allowed inside square-bracketed attributes,
16585
+ // because they usually end up being bound as attribute values. Some third-party packages
16586
+ // like Tailwind take advantage of this.
16587
+ nameEndPredicate = (code) => {
16588
+ if (code === $LBRACKET) {
16589
+ openBrackets++;
16590
+ }
16591
+ else if (code === $RBRACKET) {
16592
+ openBrackets--;
16593
+ }
16594
+ // Only check for name-ending characters if the brackets are balanced or mismatched.
16595
+ // Also interrupt the matching on new lines.
16596
+ return openBrackets <= 0 ? isNameEnd(code) : isNewLine(code);
16597
+ };
16598
+ }
16396
16599
  else {
16397
16600
  nameEndPredicate = isNameEnd;
16398
16601
  }
@@ -20316,6 +20519,44 @@ const _ATTR_TO_PROP = new Map(Object.entries({
20316
20519
  'innerHtml': 'innerHTML',
20317
20520
  'readonly': 'readOnly',
20318
20521
  'tabindex': 'tabIndex',
20522
+ // https://www.w3.org/TR/wai-aria-1.2/#accessibilityroleandproperties-correspondence
20523
+ 'aria-atomic': 'ariaAtomic',
20524
+ 'aria-autocomplete': 'ariaAutoComplete',
20525
+ 'aria-busy': 'ariaBusy',
20526
+ 'aria-checked': 'ariaChecked',
20527
+ 'aria-colcount': 'ariaColCount',
20528
+ 'aria-colindex': 'ariaColIndex',
20529
+ 'aria-colspan': 'ariaColSpan',
20530
+ 'aria-current': 'ariaCurrent',
20531
+ 'aria-disabled': 'ariaDisabled',
20532
+ 'aria-expanded': 'ariaExpanded',
20533
+ 'aria-haspopup': 'ariaHasPopup',
20534
+ 'aria-hidden': 'ariaHidden',
20535
+ 'aria-invalid': 'ariaInvalid',
20536
+ 'aria-keyshortcuts': 'ariaKeyShortcuts',
20537
+ 'aria-label': 'ariaLabel',
20538
+ 'aria-level': 'ariaLevel',
20539
+ 'aria-live': 'ariaLive',
20540
+ 'aria-modal': 'ariaModal',
20541
+ 'aria-multiline': 'ariaMultiLine',
20542
+ 'aria-multiselectable': 'ariaMultiSelectable',
20543
+ 'aria-orientation': 'ariaOrientation',
20544
+ 'aria-placeholder': 'ariaPlaceholder',
20545
+ 'aria-posinset': 'ariaPosInSet',
20546
+ 'aria-pressed': 'ariaPressed',
20547
+ 'aria-readonly': 'ariaReadOnly',
20548
+ 'aria-required': 'ariaRequired',
20549
+ 'aria-roledescription': 'ariaRoleDescription',
20550
+ 'aria-rowcount': 'ariaRowCount',
20551
+ 'aria-rowindex': 'ariaRowIndex',
20552
+ 'aria-rowspan': 'ariaRowSpan',
20553
+ 'aria-selected': 'ariaSelected',
20554
+ 'aria-setsize': 'ariaSetSize',
20555
+ 'aria-sort': 'ariaSort',
20556
+ 'aria-valuemax': 'ariaValueMax',
20557
+ 'aria-valuemin': 'ariaValueMin',
20558
+ 'aria-valuenow': 'ariaValueNow',
20559
+ 'aria-valuetext': 'ariaValueText',
20319
20560
  }));
20320
20561
  // Invert _ATTR_TO_PROP.
20321
20562
  const _PROP_TO_ATTR = Array.from(_ATTR_TO_PROP).reduce((inverted, [propertyName, attributeName]) => {
@@ -22262,10 +22503,33 @@ function addNamesToView(unit, baseName, state, compatibility) {
22262
22503
  switch (op.kind) {
22263
22504
  case OpKind.Property:
22264
22505
  case OpKind.DomProperty:
22265
- if (op.isLegacyAnimationTrigger) {
22506
+ if (op.bindingKind === BindingKind.LegacyAnimation) {
22266
22507
  op.name = '@' + op.name;
22267
22508
  }
22268
22509
  break;
22510
+ case OpKind.Animation:
22511
+ if (op.handlerFnName === null) {
22512
+ const animationKind = op.name.replace('.', '');
22513
+ op.handlerFnName = `${unit.fnName}_${animationKind}_cb`;
22514
+ op.handlerFnName = sanitizeIdentifier(op.handlerFnName);
22515
+ }
22516
+ break;
22517
+ case OpKind.AnimationListener:
22518
+ if (op.handlerFnName !== null) {
22519
+ break;
22520
+ }
22521
+ if (!op.hostListener && op.targetSlot.slot === null) {
22522
+ throw new Error(`Expected a slot to be assigned`);
22523
+ }
22524
+ const animationKind = op.name.replace('.', '');
22525
+ if (op.hostListener) {
22526
+ op.handlerFnName = `${baseName}_${animationKind}_HostBindingHandler`;
22527
+ }
22528
+ else {
22529
+ op.handlerFnName = `${unit.fnName}_${op.tag.replace('-', '_')}_${animationKind}_${op.targetSlot.slot}_listener`;
22530
+ }
22531
+ op.handlerFnName = sanitizeIdentifier(op.handlerFnName);
22532
+ break;
22269
22533
  case OpKind.Listener:
22270
22534
  if (op.handlerFnName !== null) {
22271
22535
  break;
@@ -22423,7 +22687,10 @@ function stripImportant(name) {
22423
22687
  function mergeNextContextExpressions(job) {
22424
22688
  for (const unit of job.units) {
22425
22689
  for (const op of unit.create) {
22426
- if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
22690
+ if (op.kind === OpKind.Listener ||
22691
+ op.kind === OpKind.Animation ||
22692
+ op.kind === OpKind.AnimationListener ||
22693
+ op.kind === OpKind.TwoWayListener) {
22427
22694
  mergeNextContextsInOps(op.handlerOps);
22428
22695
  }
22429
22696
  }
@@ -22544,7 +22811,9 @@ function kindWithInterpolationTest(kind, interpolation) {
22544
22811
  }
22545
22812
  function basicListenerKindTest(op) {
22546
22813
  return ((op.kind === OpKind.Listener && !(op.hostListener && op.isLegacyAnimationListener)) ||
22547
- op.kind === OpKind.TwoWayListener);
22814
+ op.kind === OpKind.TwoWayListener ||
22815
+ op.kind === OpKind.Animation ||
22816
+ op.kind === OpKind.AnimationListener);
22548
22817
  }
22549
22818
  function nonInterpolationPropertyKindTest(op) {
22550
22819
  return ((op.kind === OpKind.Property || op.kind === OpKind.TwoWayProperty) &&
@@ -22591,6 +22860,7 @@ const UPDATE_HOST_ORDERING = [
22591
22860
  const handledOpKinds = new Set([
22592
22861
  OpKind.Listener,
22593
22862
  OpKind.TwoWayListener,
22863
+ OpKind.AnimationListener,
22594
22864
  OpKind.StyleMap,
22595
22865
  OpKind.ClassMap,
22596
22866
  OpKind.StyleProp,
@@ -22599,6 +22869,7 @@ const handledOpKinds = new Set([
22599
22869
  OpKind.TwoWayProperty,
22600
22870
  OpKind.DomProperty,
22601
22871
  OpKind.Attribute,
22872
+ OpKind.Animation,
22602
22873
  ]);
22603
22874
  /**
22604
22875
  * Many type of operations have ordering constraints that must be respected. For example, a
@@ -23289,6 +23560,9 @@ function i18nAttributes(slot, i18nAttributesConfig) {
23289
23560
  const args = [literal(slot), literal(i18nAttributesConfig)];
23290
23561
  return call(Identifiers.i18nAttributes, args, null);
23291
23562
  }
23563
+ function ariaProperty(name, expression, sourceSpan) {
23564
+ return propertyBase(Identifiers.ariaProperty, name, expression, null, sourceSpan);
23565
+ }
23292
23566
  function property(name, expression, sanitizer, sourceSpan) {
23293
23567
  return propertyBase(Identifiers.property, name, expression, sanitizer, sourceSpan);
23294
23568
  }
@@ -23402,6 +23676,36 @@ function i18nApply(slot, sourceSpan) {
23402
23676
  function domProperty(name, expression, sanitizer, sourceSpan) {
23403
23677
  return propertyBase(Identifiers.domProperty, name, expression, sanitizer, sourceSpan);
23404
23678
  }
23679
+ function animation(animationKind, handlerFn, sanitizer, sourceSpan) {
23680
+ const args = [handlerFn];
23681
+ if (sanitizer !== null) {
23682
+ args.push(sanitizer);
23683
+ }
23684
+ const identifier = animationKind === "enter" /* ir.AnimationKind.ENTER */
23685
+ ? Identifiers.animationEnter
23686
+ : Identifiers.animationLeave;
23687
+ return call(identifier, args, sourceSpan);
23688
+ }
23689
+ function animationString(animationKind, expression, sanitizer, sourceSpan) {
23690
+ const value = expression instanceof Interpolation
23691
+ ? interpolationToExpression(expression, sourceSpan)
23692
+ : expression;
23693
+ const args = [value];
23694
+ if (sanitizer !== null) {
23695
+ args.push(sanitizer);
23696
+ }
23697
+ const identifier = animationKind === "enter" /* ir.AnimationKind.ENTER */
23698
+ ? Identifiers.animationEnter
23699
+ : Identifiers.animationLeave;
23700
+ return call(identifier, args, sourceSpan);
23701
+ }
23702
+ function animationListener(animationKind, handlerFn, eventTargetResolver, sourceSpan) {
23703
+ const args = [handlerFn];
23704
+ const identifier = animationKind === "enter" /* ir.AnimationKind.ENTER */
23705
+ ? Identifiers.animationEnterListener
23706
+ : Identifiers.animationLeaveListener;
23707
+ return call(identifier, args, sourceSpan);
23708
+ }
23405
23709
  function syntheticHostProperty(name, expression, sourceSpan) {
23406
23710
  return call(Identifiers.syntheticHostProperty, [literal(name), expression], sourceSpan);
23407
23711
  }
@@ -23535,6 +23839,7 @@ function callVariadicInstruction(config, baseArgs, interpolationArgs, extraArgs,
23535
23839
  return createStatementOp(callVariadicInstructionExpr(config, baseArgs, interpolationArgs, extraArgs, sourceSpan).toStmt());
23536
23840
  }
23537
23841
 
23842
+ const ARIA_PREFIX = 'aria';
23538
23843
  /**
23539
23844
  * Map of target resolvers for event listeners.
23540
23845
  */
@@ -23648,6 +23953,18 @@ function reifyCreateOperations(unit, ops) {
23648
23953
  case OpKind.DeclareLet:
23649
23954
  OpList.replace(op, declareLet(op.handle.slot, op.sourceSpan));
23650
23955
  break;
23956
+ case OpKind.AnimationString:
23957
+ OpList.replace(op, animationString(op.animationKind, op.expression, op.sanitizer, op.sourceSpan));
23958
+ break;
23959
+ case OpKind.Animation:
23960
+ const animationCallbackFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps,
23961
+ /* consumesDollarEvent */ false);
23962
+ OpList.replace(op, animation(op.animationKind, animationCallbackFn, op.sanitizer, op.sourceSpan));
23963
+ break;
23964
+ case OpKind.AnimationListener:
23965
+ const animationListenerFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, op.consumesDollarEvent);
23966
+ OpList.replace(op, animationListener(op.animationKind, animationListenerFn, null, op.sourceSpan));
23967
+ break;
23651
23968
  case OpKind.Listener:
23652
23969
  const listenerFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, op.consumesDollarEvent);
23653
23970
  const eventTargetResolver = op.eventTarget
@@ -23826,9 +24143,11 @@ function reifyUpdateOperations(unit, ops) {
23826
24143
  OpList.replace(op, advance(op.delta, op.sourceSpan));
23827
24144
  break;
23828
24145
  case OpKind.Property:
23829
- OpList.replace(op, unit.job.mode === TemplateCompilationMode.DomOnly && !op.isLegacyAnimationTrigger
23830
- ? domProperty(DOM_PROPERTY_REMAPPING.get(op.name) ?? op.name, op.expression, op.sanitizer, op.sourceSpan)
23831
- : property(op.name, op.expression, op.sanitizer, op.sourceSpan));
24146
+ OpList.replace(op, unit.job.mode === TemplateCompilationMode.DomOnly &&
24147
+ op.bindingKind !== BindingKind.LegacyAnimation &&
24148
+ op.bindingKind !== BindingKind.Animation
24149
+ ? reifyDomProperty(op)
24150
+ : reifyProperty(op));
23832
24151
  break;
23833
24152
  case OpKind.TwoWayProperty:
23834
24153
  OpList.replace(op, twoWayProperty(op.name, op.expression, op.sanitizer, op.sourceSpan));
@@ -23862,11 +24181,12 @@ function reifyUpdateOperations(unit, ops) {
23862
24181
  throw new Error('not yet handled');
23863
24182
  }
23864
24183
  else {
23865
- if (op.isLegacyAnimationTrigger) {
24184
+ if (op.bindingKind === BindingKind.LegacyAnimation ||
24185
+ op.bindingKind === BindingKind.Animation) {
23866
24186
  OpList.replace(op, syntheticHostProperty(op.name, op.expression, op.sourceSpan));
23867
24187
  }
23868
24188
  else {
23869
- OpList.replace(op, domProperty(DOM_PROPERTY_REMAPPING.get(op.name) ?? op.name, op.expression, op.sanitizer, op.sourceSpan));
24189
+ OpList.replace(op, reifyDomProperty(op));
23870
24190
  }
23871
24191
  }
23872
24192
  break;
@@ -23898,6 +24218,61 @@ function reifyUpdateOperations(unit, ops) {
23898
24218
  }
23899
24219
  }
23900
24220
  }
24221
+ /**
24222
+ * Converts an ARIA property name to its corresponding attribute name, if necessary.
24223
+ *
24224
+ * For example, converts `ariaLabel` to `aria-label`.
24225
+ *
24226
+ * https://www.w3.org/TR/wai-aria-1.2/#accessibilityroleandproperties-correspondence
24227
+ *
24228
+ * This must be kept in sync with the the function of the same name in
24229
+ * packages/core/src/render3/instructions/aria_property.ts.
24230
+ *
24231
+ * @param name A property name that starts with `aria`.
24232
+ * @returns The corresponding attribute name.
24233
+ */
24234
+ function ariaAttrName(name) {
24235
+ return name.charAt(ARIA_PREFIX.length) !== '-'
24236
+ ? ARIA_PREFIX + '-' + name.slice(ARIA_PREFIX.length).toLowerCase()
24237
+ : name; // Property already has attribute name.
24238
+ }
24239
+ /**
24240
+ * Returns whether `name` is an ARIA property (or attribute) name.
24241
+ *
24242
+ * This is a heuristic based on whether name begins with and is longer than `aria`. For example,
24243
+ * this returns true for both `ariaLabel` and `aria-label`.
24244
+ */
24245
+ function isAriaProperty(name) {
24246
+ return name.startsWith(ARIA_PREFIX) && name.length > ARIA_PREFIX.length;
24247
+ }
24248
+ /**
24249
+ * Reifies a DOM property binding operation.
24250
+ *
24251
+ * This is an optimized version of {@link reifyProperty} that avoids unnecessarily trying to bind
24252
+ * to directive inputs at runtime for views that don't import any directives.
24253
+ *
24254
+ * @param op A property binding operation.
24255
+ * @returns A statement to update the property at runtime.
24256
+ */
24257
+ function reifyDomProperty(op) {
24258
+ return isAriaProperty(op.name)
24259
+ ? attribute(ariaAttrName(op.name), op.expression, null, null, op.sourceSpan)
24260
+ : domProperty(DOM_PROPERTY_REMAPPING.get(op.name) ?? op.name, op.expression, op.sanitizer, op.sourceSpan);
24261
+ }
24262
+ /**
24263
+ * Reifies a property binding operation.
24264
+ *
24265
+ * The returned statement attempts to bind to directive inputs before falling back to a DOM
24266
+ * property.
24267
+ *
24268
+ * @param op A property binding operation.
24269
+ * @returns A statement to update the property at runtime.
24270
+ */
24271
+ function reifyProperty(op) {
24272
+ return isAriaProperty(op.name)
24273
+ ? ariaProperty(op.name, op.expression, op.sourceSpan)
24274
+ : property(op.name, op.expression, op.sanitizer, op.sourceSpan);
24275
+ }
23901
24276
  function reifyIrExpression(expr) {
23902
24277
  if (!isIrExpression(expr)) {
23903
24278
  return expr;
@@ -24139,6 +24514,8 @@ function processLexicalScope$1(view, ops) {
24139
24514
  break;
24140
24515
  }
24141
24516
  break;
24517
+ case OpKind.Animation:
24518
+ case OpKind.AnimationListener:
24142
24519
  case OpKind.Listener:
24143
24520
  case OpKind.TwoWayListener:
24144
24521
  processLexicalScope$1(view, op.handlerOps);
@@ -24204,11 +24581,13 @@ function resolveDollarEvent(job) {
24204
24581
  }
24205
24582
  function transformDollarEvent(ops) {
24206
24583
  for (const op of ops) {
24207
- if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
24584
+ if (op.kind === OpKind.Listener ||
24585
+ op.kind === OpKind.TwoWayListener ||
24586
+ op.kind === OpKind.AnimationListener) {
24208
24587
  transformExpressionsInOp(op, (expr) => {
24209
24588
  if (expr instanceof LexicalReadExpr && expr.name === '$event') {
24210
24589
  // Two-way listeners always consume `$event` so they omit this field.
24211
- if (op.kind === OpKind.Listener) {
24590
+ if (op.kind === OpKind.Listener || op.kind === OpKind.AnimationListener) {
24212
24591
  op.consumesDollarEvent = true;
24213
24592
  }
24214
24593
  return new ReadVarExpr(expr.name);
@@ -24599,6 +24978,8 @@ function processLexicalScope(unit, ops, savedView) {
24599
24978
  break;
24600
24979
  }
24601
24980
  break;
24981
+ case OpKind.Animation:
24982
+ case OpKind.AnimationListener:
24602
24983
  case OpKind.Listener:
24603
24984
  case OpKind.TwoWayListener:
24604
24985
  // Listener functions have separate variable declarations, so process them as a separate
@@ -24616,7 +24997,10 @@ function processLexicalScope(unit, ops, savedView) {
24616
24997
  // scope. Also, look for `ir.RestoreViewExpr`s and match them with the snapshotted view context
24617
24998
  // variable.
24618
24999
  for (const op of ops) {
24619
- if (op.kind == OpKind.Listener || op.kind === OpKind.TwoWayListener) {
25000
+ if (op.kind == OpKind.Listener ||
25001
+ op.kind === OpKind.TwoWayListener ||
25002
+ op.kind === OpKind.Animation ||
25003
+ op.kind === OpKind.AnimationListener) {
24620
25004
  // Listeners were already processed above with their own scopes.
24621
25005
  continue;
24622
25006
  }
@@ -24785,7 +25169,10 @@ function saveAndRestoreView(job) {
24785
25169
  }, new GetCurrentViewExpr(), VariableFlags.None),
24786
25170
  ]);
24787
25171
  for (const op of unit.create) {
24788
- if (op.kind !== OpKind.Listener && op.kind !== OpKind.TwoWayListener) {
25172
+ if (op.kind !== OpKind.Listener &&
25173
+ op.kind !== OpKind.TwoWayListener &&
25174
+ op.kind !== OpKind.Animation &&
25175
+ op.kind !== OpKind.AnimationListener) {
24789
25176
  continue;
24790
25177
  }
24791
25178
  // Embedded views always need the save/restore view operation.
@@ -25105,7 +25492,10 @@ function generateTemporaries(ops) {
25105
25492
  // Add declarations for the temp vars.
25106
25493
  generatedStatements.push(...Array.from(new Set(defs.values())).map((name) => createStatementOp(new DeclareVarStmt(name))));
25107
25494
  opCount++;
25108
- if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
25495
+ if (op.kind === OpKind.Listener ||
25496
+ op.kind === OpKind.Animation ||
25497
+ op.kind === OpKind.AnimationListener ||
25498
+ op.kind === OpKind.TwoWayListener) {
25109
25499
  op.handlerOps.prepend(generateTemporaries(op.handlerOps));
25110
25500
  }
25111
25501
  else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
@@ -25449,7 +25839,10 @@ function optimizeVariables(job) {
25449
25839
  inlineAlwaysInlineVariables(unit.create);
25450
25840
  inlineAlwaysInlineVariables(unit.update);
25451
25841
  for (const op of unit.create) {
25452
- if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
25842
+ if (op.kind === OpKind.Listener ||
25843
+ op.kind === OpKind.Animation ||
25844
+ op.kind === OpKind.AnimationListener ||
25845
+ op.kind === OpKind.TwoWayListener) {
25453
25846
  inlineAlwaysInlineVariables(op.handlerOps);
25454
25847
  }
25455
25848
  else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
@@ -25459,7 +25852,10 @@ function optimizeVariables(job) {
25459
25852
  optimizeVariablesInOpList(unit.create, job.compatibility);
25460
25853
  optimizeVariablesInOpList(unit.update, job.compatibility);
25461
25854
  for (const op of unit.create) {
25462
- if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
25855
+ if (op.kind === OpKind.Listener ||
25856
+ op.kind === OpKind.Animation ||
25857
+ op.kind === OpKind.AnimationListener ||
25858
+ op.kind === OpKind.TwoWayListener) {
25463
25859
  optimizeVariablesInOpList(op.handlerOps, job.compatibility);
25464
25860
  }
25465
25861
  else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
@@ -25896,6 +26292,7 @@ const phases = [
25896
26292
  { kind: CompilationJobKind.Both, fn: deduplicateTextBindings },
25897
26293
  { kind: CompilationJobKind.Both, fn: specializeStyleBindings },
25898
26294
  { kind: CompilationJobKind.Both, fn: specializeBindings },
26295
+ { kind: CompilationJobKind.Both, fn: convertAnimations },
25899
26296
  { kind: CompilationJobKind.Both, fn: extractAttributes },
25900
26297
  { kind: CompilationJobKind.Tmpl, fn: createI18nContexts },
25901
26298
  { kind: CompilationJobKind.Both, fn: parseExtractedStyles },
@@ -26055,6 +26452,8 @@ const compatibilityMode = CompatibilityMode.TemplateDefinitionBuilder;
26055
26452
  const domSchema = new DomElementSchemaRegistry();
26056
26453
  // Tag name of the `ng-template` element.
26057
26454
  const NG_TEMPLATE_TAG_NAME = 'ng-template';
26455
+ // prefix for any animation binding
26456
+ const ANIMATE_PREFIX$1 = 'animate.';
26058
26457
  function isI18nRootNode(meta) {
26059
26458
  return meta instanceof Message;
26060
26459
  }
@@ -26087,6 +26486,9 @@ function ingestHostBinding(input, bindingParser, constantPool) {
26087
26486
  if (property.isLegacyAnimation) {
26088
26487
  bindingKind = BindingKind.LegacyAnimation;
26089
26488
  }
26489
+ if (property.isAnimation) {
26490
+ bindingKind = BindingKind.Animation;
26491
+ }
26090
26492
  const securityContexts = bindingParser
26091
26493
  .calcPossibleSecurityContexts(input.componentSelector, property.name, bindingKind === BindingKind.Attribute)
26092
26494
  .filter((context) => context !== SecurityContext.NONE);
@@ -26753,6 +27155,7 @@ const BINDING_KINDS = new Map([
26753
27155
  [exports.BindingType.Class, BindingKind.ClassName],
26754
27156
  [exports.BindingType.Style, BindingKind.StyleProperty],
26755
27157
  [exports.BindingType.LegacyAnimation, BindingKind.LegacyAnimation],
27158
+ [exports.BindingType.Animation, BindingKind.Animation],
26756
27159
  ]);
26757
27160
  /**
26758
27161
  * Checks whether the given template is a plain ng-template (as opposed to another kind of template
@@ -26817,6 +27220,9 @@ function ingestElementBindings(unit, op, element) {
26817
27220
  if (output.type === exports.ParsedEventType.TwoWay) {
26818
27221
  unit.create.push(createTwoWayListenerOp(op.xref, op.handle, output.name, op.tag, makeTwoWayListenerHandlerOps(unit, output.handler, output.handlerSpan), output.sourceSpan));
26819
27222
  }
27223
+ else if (output.type === exports.ParsedEventType.Animation) {
27224
+ unit.create.push(createAnimationListenerOp(op.xref, op.handle, output.name, op.tag, makeListenerHandlerOps(unit, output.handler, output.handlerSpan), output.name.endsWith('enter') ? "enter" /* ir.AnimationKind.ENTER */ : "leave" /* ir.AnimationKind.LEAVE */, output.target, false, output.sourceSpan));
27225
+ }
26820
27226
  else {
26821
27227
  unit.create.push(createListenerOp(op.xref, op.handle, output.name, op.tag, makeListenerHandlerOps(unit, output.handler, output.handlerSpan), output.phase, output.target, false, output.sourceSpan));
26822
27228
  }
@@ -26925,7 +27331,9 @@ function createTemplateBinding(view, xref, type, name, value, unit, securityCont
26925
27331
  }
26926
27332
  }
26927
27333
  if (!isTextBinding &&
26928
- (type === exports.BindingType.Attribute || type === exports.BindingType.LegacyAnimation)) {
27334
+ (type === exports.BindingType.Attribute ||
27335
+ type === exports.BindingType.LegacyAnimation ||
27336
+ type === exports.BindingType.Animation)) {
26929
27337
  // Again, this binding doesn't really target the ng-template; it actually targets the element
26930
27338
  // inside the structural template. In the case of non-text attribute or animation bindings,
26931
27339
  // the binding doesn't even show up on the ng-template const array, so we just skip it
@@ -27083,14 +27491,18 @@ function ingestControlFlowInsertionPoint(unit, xref, node) {
27083
27491
  if (root !== null) {
27084
27492
  // Collect the static attributes for content projection purposes.
27085
27493
  for (const attr of root.attributes) {
27086
- const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME, attr.name, true);
27087
- unit.update.push(createBindingOp(xref, BindingKind.Attribute, attr.name, literal(attr.value), null, securityContext, true, false, null, asMessage(attr.i18n), attr.sourceSpan));
27494
+ if (!attr.name.startsWith(ANIMATE_PREFIX$1)) {
27495
+ const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME, attr.name, true);
27496
+ unit.update.push(createBindingOp(xref, BindingKind.Attribute, attr.name, literal(attr.value), null, securityContext, true, false, null, asMessage(attr.i18n), attr.sourceSpan));
27497
+ }
27088
27498
  }
27089
27499
  // Also collect the inputs since they participate in content projection as well.
27090
27500
  // Note that TDB used to collect the outputs as well, but it wasn't passing them into
27091
27501
  // the template instruction. Here we just don't collect them.
27092
27502
  for (const attr of root.inputs) {
27093
- if (attr.type !== exports.BindingType.LegacyAnimation && attr.type !== exports.BindingType.Attribute) {
27503
+ if (attr.type !== exports.BindingType.LegacyAnimation &&
27504
+ attr.type !== exports.BindingType.Animation &&
27505
+ attr.type !== exports.BindingType.Attribute) {
27094
27506
  const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME, attr.name, true);
27095
27507
  unit.create.push(createExtractedAttributeOp(xref, BindingKind.Property, null, attr.name, null, null, null, securityContext));
27096
27508
  }
@@ -27302,6 +27714,7 @@ class HtmlParser extends Parser$1 {
27302
27714
 
27303
27715
  const PROPERTY_PARTS_SEPARATOR = '.';
27304
27716
  const ATTRIBUTE_PREFIX = 'attr';
27717
+ const ANIMATE_PREFIX = 'animate';
27305
27718
  const CLASS_PREFIX = 'class';
27306
27719
  const STYLE_PREFIX = 'style';
27307
27720
  const TEMPLATE_ATTR_PREFIX$1 = '*';
@@ -27501,6 +27914,9 @@ class BindingParser {
27501
27914
  if (isLegacyAnimationProp) {
27502
27915
  this._parseLegacyAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps);
27503
27916
  }
27917
+ else if (name.startsWith(ANIMATE_PREFIX)) {
27918
+ this._parseAnimation(name, this.parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
27919
+ }
27504
27920
  else {
27505
27921
  this._parsePropertyAst(name, this.parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), isPartOfAssignmentBinding, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
27506
27922
  }
@@ -27517,6 +27933,10 @@ class BindingParser {
27517
27933
  targetMatchableAttrs.push([name, ast.source]);
27518
27934
  targetProps.push(new ParsedProperty(name, ast, isPartOfAssignmentBinding ? ParsedPropertyType.TWO_WAY : ParsedPropertyType.DEFAULT, sourceSpan, keySpan, valueSpan));
27519
27935
  }
27936
+ _parseAnimation(name, ast, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps) {
27937
+ targetMatchableAttrs.push([name, ast.source]);
27938
+ targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.ANIMATION, sourceSpan, keySpan, valueSpan));
27939
+ }
27520
27940
  _parseLegacyAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps) {
27521
27941
  if (name.length === 0) {
27522
27942
  this._reportError('Animation trigger is missing', sourceSpan);
@@ -27579,6 +27999,11 @@ class BindingParser {
27579
27999
  bindingType = exports.BindingType.Style;
27580
28000
  securityContexts = [SecurityContext.STYLE];
27581
28001
  }
28002
+ else if (parts[0] == ANIMATE_PREFIX) {
28003
+ boundPropertyName = boundProp.name;
28004
+ bindingType = exports.BindingType.Animation;
28005
+ securityContexts = [SecurityContext.NONE];
28006
+ }
27582
28007
  }
27583
28008
  // If not a special case, use the full property name
27584
28009
  if (boundPropertyName === null) {
@@ -27593,7 +28018,6 @@ class BindingParser {
27593
28018
  }
27594
28019
  return new BoundElementProperty(boundPropertyName, bindingType, securityContexts[0], boundProp.expression, unit, boundProp.sourceSpan, boundProp.keySpan, boundProp.valueSpan);
27595
28020
  }
27596
- // TODO: keySpan should be required but was made optional to avoid changing VE parser.
27597
28021
  parseEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan) {
27598
28022
  if (name.length === 0) {
27599
28023
  this._reportError(`Event name is missing in binding`, sourceSpan);
@@ -27649,7 +28073,14 @@ class BindingParser {
27649
28073
  if (isAssignmentEvent && isValid && !this._isAllowedAssignmentEvent(ast)) {
27650
28074
  this._reportError('Unsupported expression in a two-way binding', sourceSpan);
27651
28075
  }
27652
- targetEvents.push(new ParsedEvent(eventName, target, isAssignmentEvent ? exports.ParsedEventType.TwoWay : exports.ParsedEventType.Regular, ast, sourceSpan, handlerSpan, keySpan));
28076
+ let eventType = exports.ParsedEventType.Regular;
28077
+ if (isAssignmentEvent) {
28078
+ eventType = exports.ParsedEventType.TwoWay;
28079
+ }
28080
+ if (name.startsWith(ANIMATE_PREFIX)) {
28081
+ eventType = exports.ParsedEventType.Animation;
28082
+ }
28083
+ targetEvents.push(new ParsedEvent(eventName, target, eventType, ast, sourceSpan, handlerSpan, keySpan));
27653
28084
  // Don't detect directives for event names for now,
27654
28085
  // so don't add the event name to the matchableAttrs
27655
28086
  }
@@ -29220,7 +29651,7 @@ class HtmlAstToIvyAst {
29220
29651
  const identifier = bindParts[IDENT_KW_IDX];
29221
29652
  const keySpan = createKeySpan(srcSpan, bindParts[KW_BINDON_IDX], identifier);
29222
29653
  this.bindingParser.parsePropertyBinding(identifier, value, false, true, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
29223
- this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan);
29654
+ this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan, absoluteOffset);
29224
29655
  }
29225
29656
  else if (bindParts[KW_AT_IDX]) {
29226
29657
  const keySpan = createKeySpan(srcSpan, '', name);
@@ -29251,7 +29682,7 @@ class HtmlAstToIvyAst {
29251
29682
  const keySpan = createKeySpan(srcSpan, delims.start, identifier);
29252
29683
  if (delims.start === BINDING_DELIMS.BANANA_BOX.start) {
29253
29684
  this.bindingParser.parsePropertyBinding(identifier, value, false, true, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
29254
- this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan);
29685
+ this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan, absoluteOffset);
29255
29686
  }
29256
29687
  else if (delims.start === BINDING_DELIMS.PROPERTY.start) {
29257
29688
  this.bindingParser.parsePropertyBinding(identifier, value, false, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
@@ -29371,7 +29802,7 @@ class HtmlAstToIvyAst {
29371
29802
  }
29372
29803
  references.push(new Reference$1(identifier, value, sourceSpan, keySpan, valueSpan));
29373
29804
  }
29374
- parseAssignmentEvent(name, expression, sourceSpan, valueSpan, targetMatchableAttrs, boundEvents, keySpan) {
29805
+ parseAssignmentEvent(name, expression, sourceSpan, valueSpan, targetMatchableAttrs, boundEvents, keySpan, absoluteOffset) {
29375
29806
  const events = [];
29376
29807
  this.bindingParser.parseEvent(`${name}Change`, expression,
29377
29808
  /* isAssignmentEvent */ true, sourceSpan, valueSpan || sourceSpan, targetMatchableAttrs, events, keySpan);
@@ -29599,9 +30030,184 @@ function makeBindingParser(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG, s
29599
30030
  return new BindingParser(new Parser(new Lexer(), selectorlessEnabled), interpolationConfig, elementRegistry, []);
29600
30031
  }
29601
30032
 
30033
+ /*!
30034
+ * @license
30035
+ * Copyright Google LLC All Rights Reserved.
30036
+ *
30037
+ * Use of this source code is governed by an MIT-style license that can be
30038
+ * found in the LICENSE file at https://angular.dev/license
30039
+ */
30040
+ /**
30041
+ * Visitor that traverses all template and expression AST nodes in a template.
30042
+ * Useful for cases where every single node needs to be visited.
30043
+ */
30044
+ class CombinedRecursiveAstVisitor extends RecursiveAstVisitor {
30045
+ visit(node) {
30046
+ if (node instanceof ASTWithSource) {
30047
+ this.visit(node.ast);
30048
+ }
30049
+ else {
30050
+ node.visit(this);
30051
+ }
30052
+ }
30053
+ visitElement(element) {
30054
+ this.visitAllTemplateNodes(element.attributes);
30055
+ this.visitAllTemplateNodes(element.inputs);
30056
+ this.visitAllTemplateNodes(element.outputs);
30057
+ this.visitAllTemplateNodes(element.directives);
30058
+ this.visitAllTemplateNodes(element.references);
30059
+ this.visitAllTemplateNodes(element.children);
30060
+ }
30061
+ visitTemplate(template) {
30062
+ this.visitAllTemplateNodes(template.attributes);
30063
+ this.visitAllTemplateNodes(template.inputs);
30064
+ this.visitAllTemplateNodes(template.outputs);
30065
+ this.visitAllTemplateNodes(template.directives);
30066
+ this.visitAllTemplateNodes(template.templateAttrs);
30067
+ this.visitAllTemplateNodes(template.variables);
30068
+ this.visitAllTemplateNodes(template.references);
30069
+ this.visitAllTemplateNodes(template.children);
30070
+ }
30071
+ visitContent(content) {
30072
+ this.visitAllTemplateNodes(content.children);
30073
+ }
30074
+ visitBoundAttribute(attribute) {
30075
+ this.visit(attribute.value);
30076
+ }
30077
+ visitBoundEvent(attribute) {
30078
+ this.visit(attribute.handler);
30079
+ }
30080
+ visitBoundText(text) {
30081
+ this.visit(text.value);
30082
+ }
30083
+ visitIcu(icu) {
30084
+ Object.keys(icu.vars).forEach((key) => this.visit(icu.vars[key]));
30085
+ Object.keys(icu.placeholders).forEach((key) => this.visit(icu.placeholders[key]));
30086
+ }
30087
+ visitDeferredBlock(deferred) {
30088
+ deferred.visitAll(this);
30089
+ }
30090
+ visitDeferredTrigger(trigger) {
30091
+ if (trigger instanceof BoundDeferredTrigger) {
30092
+ this.visit(trigger.value);
30093
+ }
30094
+ }
30095
+ visitDeferredBlockPlaceholder(block) {
30096
+ this.visitAllTemplateNodes(block.children);
30097
+ }
30098
+ visitDeferredBlockError(block) {
30099
+ this.visitAllTemplateNodes(block.children);
30100
+ }
30101
+ visitDeferredBlockLoading(block) {
30102
+ this.visitAllTemplateNodes(block.children);
30103
+ }
30104
+ visitSwitchBlock(block) {
30105
+ this.visit(block.expression);
30106
+ this.visitAllTemplateNodes(block.cases);
30107
+ }
30108
+ visitSwitchBlockCase(block) {
30109
+ block.expression && this.visit(block.expression);
30110
+ this.visitAllTemplateNodes(block.children);
30111
+ }
30112
+ visitForLoopBlock(block) {
30113
+ block.item.visit(this);
30114
+ this.visitAllTemplateNodes(block.contextVariables);
30115
+ this.visit(block.expression);
30116
+ this.visitAllTemplateNodes(block.children);
30117
+ block.empty?.visit(this);
30118
+ }
30119
+ visitForLoopBlockEmpty(block) {
30120
+ this.visitAllTemplateNodes(block.children);
30121
+ }
30122
+ visitIfBlock(block) {
30123
+ this.visitAllTemplateNodes(block.branches);
30124
+ }
30125
+ visitIfBlockBranch(block) {
30126
+ block.expression && this.visit(block.expression);
30127
+ block.expressionAlias?.visit(this);
30128
+ this.visitAllTemplateNodes(block.children);
30129
+ }
30130
+ visitLetDeclaration(decl) {
30131
+ this.visit(decl.value);
30132
+ }
30133
+ visitComponent(component) {
30134
+ this.visitAllTemplateNodes(component.attributes);
30135
+ this.visitAllTemplateNodes(component.inputs);
30136
+ this.visitAllTemplateNodes(component.outputs);
30137
+ this.visitAllTemplateNodes(component.directives);
30138
+ this.visitAllTemplateNodes(component.references);
30139
+ this.visitAllTemplateNodes(component.children);
30140
+ }
30141
+ visitDirective(directive) {
30142
+ this.visitAllTemplateNodes(directive.attributes);
30143
+ this.visitAllTemplateNodes(directive.inputs);
30144
+ this.visitAllTemplateNodes(directive.outputs);
30145
+ this.visitAllTemplateNodes(directive.references);
30146
+ }
30147
+ visitVariable(variable) { }
30148
+ visitReference(reference) { }
30149
+ visitTextAttribute(attribute) { }
30150
+ visitText(text) { }
30151
+ visitUnknownBlock(block) { }
30152
+ visitAllTemplateNodes(nodes) {
30153
+ for (const node of nodes) {
30154
+ this.visit(node);
30155
+ }
30156
+ }
30157
+ }
30158
+
30159
+ /*!
30160
+ * @license
30161
+ * Copyright Google LLC All Rights Reserved.
30162
+ *
30163
+ * Use of this source code is governed by an MIT-style license that can be
30164
+ * found in the LICENSE file at https://angular.dev/license
30165
+ */
30166
+ const ANIMATE_LEAVE$1 = `animate.leave`;
30167
+ /**
30168
+ * Analyzes a component's template to determine if it's using animate.enter
30169
+ * or animate.leave syntax.
30170
+ */
30171
+ function analyzeTemplateForAnimations(template) {
30172
+ const analyzer = new AnimationsAnalyzer();
30173
+ visitAll$1(analyzer, template);
30174
+ // The template is considered selectorless only if there
30175
+ // are direct references to directives or pipes.
30176
+ return analyzer.hasAnimations;
30177
+ }
30178
+ /**
30179
+ * Visitor that traverses all the template nodes and
30180
+ * expressions to look for selectorless references.
30181
+ */
30182
+ class AnimationsAnalyzer extends CombinedRecursiveAstVisitor {
30183
+ hasAnimations = false;
30184
+ visitElement(element) {
30185
+ // check for regular strings
30186
+ for (const attr of element.attributes) {
30187
+ if (attr.name === ANIMATE_LEAVE$1) {
30188
+ this.hasAnimations = true;
30189
+ }
30190
+ }
30191
+ // check for attribute bindings
30192
+ for (const input of element.inputs) {
30193
+ if (input.name === ANIMATE_LEAVE$1) {
30194
+ this.hasAnimations = true;
30195
+ }
30196
+ }
30197
+ // check for event bindings
30198
+ for (const output of element.outputs) {
30199
+ if (output.name === ANIMATE_LEAVE$1) {
30200
+ this.hasAnimations = true;
30201
+ }
30202
+ }
30203
+ super.visitElement(element);
30204
+ }
30205
+ }
30206
+
29602
30207
  const COMPONENT_VARIABLE = '%COMP%';
29603
30208
  const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
29604
30209
  const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
30210
+ const ANIMATE_LEAVE = `animate.leave`;
29605
30211
  function baseDirectiveFields(meta, constantPool, bindingParser) {
29606
30212
  const definitionMap = new DefinitionMap();
29607
30213
  const selectors = parseSelectorToR3Selector(meta.selector);
@@ -29635,6 +30241,11 @@ function baseDirectiveFields(meta, constantPool, bindingParser) {
29635
30241
  }
29636
30242
  return definitionMap;
29637
30243
  }
30244
+ function hasAnimationHostBinding(meta) {
30245
+ return (meta.host.attributes[ANIMATE_LEAVE] !== undefined ||
30246
+ meta.host.properties[ANIMATE_LEAVE] !== undefined ||
30247
+ meta.host.listeners[ANIMATE_LEAVE] !== undefined);
30248
+ }
29638
30249
  /**
29639
30250
  * Add features to the definition map.
29640
30251
  */
@@ -29669,6 +30280,12 @@ function addFeatures(definitionMap, meta) {
29669
30280
  const externalStyleNodes = meta.externalStyles.map((externalStyle) => literal(externalStyle));
29670
30281
  features.push(importExpr(Identifiers.ExternalStylesFeature).callFn([literalArr(externalStyleNodes)]));
29671
30282
  }
30283
+ const template = meta.template;
30284
+ if (hasAnimationHostBinding(meta) || (template && template.nodes.length > 0)) {
30285
+ if (hasAnimationHostBinding(meta) || analyzeTemplateForAnimations(template.nodes)) {
30286
+ features.push(importExpr(Identifiers.AnimationsFeature).callFn([]));
30287
+ }
30288
+ }
29672
30289
  if (features.length) {
29673
30290
  definitionMap.set('features', literalArr(features));
29674
30291
  }
@@ -30109,132 +30726,6 @@ function compileDeferResolverFunction(meta) {
30109
30726
  return arrowFn([], literalArr(depExpressions));
30110
30727
  }
30111
30728
 
30112
- /*!
30113
- * @license
30114
- * Copyright Google LLC All Rights Reserved.
30115
- *
30116
- * Use of this source code is governed by an MIT-style license that can be
30117
- * found in the LICENSE file at https://angular.dev/license
30118
- */
30119
- /**
30120
- * Visitor that traverses all template and expression AST nodes in a template.
30121
- * Useful for cases where every single node needs to be visited.
30122
- */
30123
- class CombinedRecursiveAstVisitor extends RecursiveAstVisitor {
30124
- visit(node) {
30125
- if (node instanceof ASTWithSource) {
30126
- this.visit(node.ast);
30127
- }
30128
- else {
30129
- node.visit(this);
30130
- }
30131
- }
30132
- visitElement(element) {
30133
- this.visitAllTemplateNodes(element.attributes);
30134
- this.visitAllTemplateNodes(element.inputs);
30135
- this.visitAllTemplateNodes(element.outputs);
30136
- this.visitAllTemplateNodes(element.directives);
30137
- this.visitAllTemplateNodes(element.references);
30138
- this.visitAllTemplateNodes(element.children);
30139
- }
30140
- visitTemplate(template) {
30141
- this.visitAllTemplateNodes(template.attributes);
30142
- this.visitAllTemplateNodes(template.inputs);
30143
- this.visitAllTemplateNodes(template.outputs);
30144
- this.visitAllTemplateNodes(template.directives);
30145
- this.visitAllTemplateNodes(template.templateAttrs);
30146
- this.visitAllTemplateNodes(template.variables);
30147
- this.visitAllTemplateNodes(template.references);
30148
- this.visitAllTemplateNodes(template.children);
30149
- }
30150
- visitContent(content) {
30151
- this.visitAllTemplateNodes(content.children);
30152
- }
30153
- visitBoundAttribute(attribute) {
30154
- this.visit(attribute.value);
30155
- }
30156
- visitBoundEvent(attribute) {
30157
- this.visit(attribute.handler);
30158
- }
30159
- visitBoundText(text) {
30160
- this.visit(text.value);
30161
- }
30162
- visitIcu(icu) {
30163
- Object.keys(icu.vars).forEach((key) => this.visit(icu.vars[key]));
30164
- Object.keys(icu.placeholders).forEach((key) => this.visit(icu.placeholders[key]));
30165
- }
30166
- visitDeferredBlock(deferred) {
30167
- deferred.visitAll(this);
30168
- }
30169
- visitDeferredTrigger(trigger) {
30170
- if (trigger instanceof BoundDeferredTrigger) {
30171
- this.visit(trigger.value);
30172
- }
30173
- }
30174
- visitDeferredBlockPlaceholder(block) {
30175
- this.visitAllTemplateNodes(block.children);
30176
- }
30177
- visitDeferredBlockError(block) {
30178
- this.visitAllTemplateNodes(block.children);
30179
- }
30180
- visitDeferredBlockLoading(block) {
30181
- this.visitAllTemplateNodes(block.children);
30182
- }
30183
- visitSwitchBlock(block) {
30184
- this.visit(block.expression);
30185
- this.visitAllTemplateNodes(block.cases);
30186
- }
30187
- visitSwitchBlockCase(block) {
30188
- block.expression && this.visit(block.expression);
30189
- this.visitAllTemplateNodes(block.children);
30190
- }
30191
- visitForLoopBlock(block) {
30192
- block.item.visit(this);
30193
- this.visitAllTemplateNodes(block.contextVariables);
30194
- this.visit(block.expression);
30195
- this.visitAllTemplateNodes(block.children);
30196
- block.empty?.visit(this);
30197
- }
30198
- visitForLoopBlockEmpty(block) {
30199
- this.visitAllTemplateNodes(block.children);
30200
- }
30201
- visitIfBlock(block) {
30202
- this.visitAllTemplateNodes(block.branches);
30203
- }
30204
- visitIfBlockBranch(block) {
30205
- block.expression && this.visit(block.expression);
30206
- block.expressionAlias?.visit(this);
30207
- this.visitAllTemplateNodes(block.children);
30208
- }
30209
- visitLetDeclaration(decl) {
30210
- this.visit(decl.value);
30211
- }
30212
- visitComponent(component) {
30213
- this.visitAllTemplateNodes(component.attributes);
30214
- this.visitAllTemplateNodes(component.inputs);
30215
- this.visitAllTemplateNodes(component.outputs);
30216
- this.visitAllTemplateNodes(component.directives);
30217
- this.visitAllTemplateNodes(component.references);
30218
- this.visitAllTemplateNodes(component.children);
30219
- }
30220
- visitDirective(directive) {
30221
- this.visitAllTemplateNodes(directive.attributes);
30222
- this.visitAllTemplateNodes(directive.inputs);
30223
- this.visitAllTemplateNodes(directive.outputs);
30224
- this.visitAllTemplateNodes(directive.references);
30225
- }
30226
- visitVariable(variable) { }
30227
- visitReference(reference) { }
30228
- visitTextAttribute(attribute) { }
30229
- visitText(text) { }
30230
- visitUnknownBlock(block) { }
30231
- visitAllTemplateNodes(nodes) {
30232
- for (const node of nodes) {
30233
- this.visit(node);
30234
- }
30235
- }
30236
- }
30237
-
30238
30729
  /**
30239
30730
  * Processes `Target`s with a given set of directives and performs a binding operation, which
30240
30731
  * returns an object similar to TypeScript's `ts.TypeChecker` that contains knowledge about the
@@ -31494,7 +31985,7 @@ function convertDeclareComponentFacadeToMetadata(decl, typeSourceSpan, sourceMap
31494
31985
  declarations.push(...decl.directives.map((dir) => convertDirectiveDeclarationToMetadata(dir)));
31495
31986
  decl.pipes && declarations.push(...convertPipeMapToMetadata(decl.pipes));
31496
31987
  }
31497
- const hasDirectiveDependencies = declarations.every(({ kind }) => kind === exports.R3TemplateDependencyKind.Directive || kind === exports.R3TemplateDependencyKind.NgModule);
31988
+ const hasDirectiveDependencies = declarations.some(({ kind }) => kind === exports.R3TemplateDependencyKind.Directive || kind === exports.R3TemplateDependencyKind.NgModule);
31498
31989
  return {
31499
31990
  ...convertDeclareDirectiveFacadeToMetadata(decl, typeSourceSpan),
31500
31991
  template,
@@ -32271,7 +32762,7 @@ function isAttrNode(ast) {
32271
32762
  * @description
32272
32763
  * Entry point for all public APIs of the compiler package.
32273
32764
  */
32274
- new Version('20.2.0-next.1');
32765
+ new Version('20.2.0-next.2');
32275
32766
 
32276
32767
  //////////////////////////////////////
32277
32768
  // THIS FILE HAS GLOBAL SIDE EFFECT //
@@ -32804,6 +33295,20 @@ exports.ErrorCode = void 0;
32804
33295
  * A structural directive is used in a template, but the directive is not imported.
32805
33296
  */
32806
33297
  ErrorCode[ErrorCode["MISSING_STRUCTURAL_DIRECTIVE"] = 8116] = "MISSING_STRUCTURAL_DIRECTIVE";
33298
+ /**
33299
+ * A function in a text interpolation is not invoked.
33300
+ *
33301
+ * For example:
33302
+ * ```html
33303
+ * <p> {{ firstName }} </p>
33304
+ * ```
33305
+ *
33306
+ * The `firstName` function is not invoked. Instead, it should be:
33307
+ * ```html
33308
+ * <p> {{ firstName() }} </p>
33309
+ * ```
33310
+ */
33311
+ ErrorCode[ErrorCode["UNINVOKED_FUNCTION_IN_TEXT_INTERPOLATION"] = 8117] = "UNINVOKED_FUNCTION_IN_TEXT_INTERPOLATION";
32807
33312
  /**
32808
33313
  * The template type-checking engine would need to generate an inline type check block for a
32809
33314
  * component, but the current type-checking environment doesn't support it.
@@ -32965,6 +33470,7 @@ exports.ExtendedTemplateDiagnosticName = void 0;
32965
33470
  ExtendedTemplateDiagnosticName["UNINVOKED_TRACK_FUNCTION"] = "uninvokedTrackFunction";
32966
33471
  ExtendedTemplateDiagnosticName["UNUSED_STANDALONE_IMPORTS"] = "unusedStandaloneImports";
32967
33472
  ExtendedTemplateDiagnosticName["UNPARENTHESIZED_NULLISH_COALESCING"] = "unparenthesizedNullishCoalescing";
33473
+ ExtendedTemplateDiagnosticName["UNINVOKED_FUNCTION_IN_TEXT_INTERPOLATION"] = "uninvokedFunctionInTextInterpolation";
32968
33474
  })(exports.ExtendedTemplateDiagnosticName || (exports.ExtendedTemplateDiagnosticName = {}));
32969
33475
 
32970
33476
  /**
@@ -33291,7 +33797,7 @@ class NodeJSPathManipulation {
33291
33797
  // G3-ESM-MARKER: G3 uses CommonJS, but externally everything in ESM.
33292
33798
  // CommonJS/ESM interop for determining the current file name and containing dir.
33293
33799
  const isCommonJS = typeof __filename !== 'undefined';
33294
- const currentFileUrl = isCommonJS ? null : (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('checker-BVY3FNBy.cjs', document.baseURI).href));
33800
+ const currentFileUrl = isCommonJS ? null : (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('checker-Cfq29XaS.cjs', document.baseURI).href));
33295
33801
  // Note, when this code loads in the browser, `url` may be an empty `{}` due to the Closure shims.
33296
33802
  const currentFileName = isCommonJS
33297
33803
  ? __filename
@@ -43044,7 +43550,8 @@ function inferBoundAttribute(name) {
43044
43550
  const attrPrefix = 'attr.';
43045
43551
  const classPrefix = 'class.';
43046
43552
  const stylePrefix = 'style.';
43047
- const animationPrefix = '@';
43553
+ const animationPrefix = 'animate.';
43554
+ const legacyAnimationPrefix = '@';
43048
43555
  let attrName;
43049
43556
  let type;
43050
43557
  // Infer the binding type based on the prefix.
@@ -43061,7 +43568,11 @@ function inferBoundAttribute(name) {
43061
43568
  type = exports.BindingType.Style;
43062
43569
  }
43063
43570
  else if (name.startsWith(animationPrefix)) {
43064
- attrName = name.slice(animationPrefix.length);
43571
+ attrName = name;
43572
+ type = exports.BindingType.Animation;
43573
+ }
43574
+ else if (name.startsWith(legacyAnimationPrefix)) {
43575
+ attrName = name.slice(legacyAnimationPrefix.length);
43065
43576
  type = exports.BindingType.LegacyAnimation;
43066
43577
  }
43067
43578
  else {
@@ -45429,7 +45940,7 @@ class TcbDomSchemaCheckerOp extends TcbOp {
45429
45940
  }
45430
45941
  if (isPropertyBinding && binding.name !== 'style' && binding.name !== 'class') {
45431
45942
  // A direct binding to a property.
45432
- const propertyName = ATTR_TO_PROP.get(binding.name) ?? binding.name;
45943
+ const propertyName = REGISTRY$1.getMappedPropName(binding.name);
45433
45944
  if (isTemplateElement) {
45434
45945
  this.tcb.domSchemaChecker.checkTemplateElementProperty(this.tcb.id, this.getTagName(element), propertyName, binding.sourceSpan, this.tcb.schemas, this.tcb.hostIsStandalone);
45435
45946
  }
@@ -45601,18 +46112,6 @@ class TcbComponentNodeOp extends TcbOp {
45601
46112
  return id;
45602
46113
  }
45603
46114
  }
45604
- /**
45605
- * Mapping between attributes names that don't correspond to their element property names.
45606
- * Note: this mapping has to be kept in sync with the equally named mapping in the runtime.
45607
- */
45608
- const ATTR_TO_PROP = new Map(Object.entries({
45609
- 'class': 'className',
45610
- 'for': 'htmlFor',
45611
- 'formaction': 'formAction',
45612
- 'innerHtml': 'innerHTML',
45613
- 'readonly': 'readOnly',
45614
- 'tabindex': 'tabIndex',
45615
- }));
45616
46115
  /**
45617
46116
  * A `TcbOp` which generates code to check "unclaimed inputs" - bindings on an element which were
45618
46117
  * not attributed to any directive or component, and are instead processed against the HTML element
@@ -45658,7 +46157,7 @@ class TcbUnclaimedInputsOp extends TcbOp {
45658
46157
  elId = this.scope.resolve(this.target);
45659
46158
  }
45660
46159
  // A direct binding to a property.
45661
- const propertyName = ATTR_TO_PROP.get(binding.name) ?? binding.name;
46160
+ const propertyName = REGISTRY$1.getMappedPropName(binding.name);
45662
46161
  const prop = ts.factory.createElementAccessExpression(elId, ts.factory.createStringLiteral(propertyName));
45663
46162
  const stmt = ts.factory.createBinaryExpression(prop, ts.SyntaxKind.EqualsToken, wrapForDiagnostics(expr));
45664
46163
  addParseSpanInfo(stmt, binding.sourceSpan);
@@ -45796,6 +46295,11 @@ class TcbUnclaimedOutputsOp extends TcbOp {
45796
46295
  const handler = tcbCreateEventHandler(output, this.tcb, this.scope, eventType);
45797
46296
  this.scope.addStatement(ts.factory.createExpressionStatement(handler));
45798
46297
  }
46298
+ else if (output.type === exports.ParsedEventType.Animation) {
46299
+ const eventType = this.tcb.env.referenceExternalType('@angular/core', 'AnimationCallbackEvent');
46300
+ const handler = tcbCreateEventHandler(output, this.tcb, this.scope, eventType);
46301
+ this.scope.addStatement(ts.factory.createExpressionStatement(handler));
46302
+ }
45799
46303
  else if (this.tcb.env.config.checkTypeOfDomEvents) {
45800
46304
  // If strict checking of DOM events is enabled, generate a call to `addEventListener` on
45801
46305
  // the element instance so that TypeScript's type inference for