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

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 (61) hide show
  1. package/api.d.d.ts +2 -2
  2. package/chrome_dev_tools_performance.d.d.ts +1 -1
  3. package/discovery.d.d.ts +2 -1
  4. package/event_dispatcher.d.d.ts +1 -1
  5. package/fesm2022/attribute.mjs +1 -1
  6. package/fesm2022/core.mjs +30 -33
  7. package/fesm2022/core.mjs.map +1 -1
  8. package/fesm2022/debug_node.mjs +585 -8
  9. package/fesm2022/debug_node.mjs.map +1 -1
  10. package/fesm2022/not_found.mjs +1 -1
  11. package/fesm2022/primitives/di.mjs +1 -1
  12. package/fesm2022/primitives/event-dispatch.mjs +1 -1
  13. package/fesm2022/primitives/signals.mjs +1 -1
  14. package/fesm2022/resource.mjs +19 -7
  15. package/fesm2022/resource.mjs.map +1 -1
  16. package/fesm2022/root_effect_scheduler.mjs +16 -2
  17. package/fesm2022/root_effect_scheduler.mjs.map +1 -1
  18. package/fesm2022/rxjs-interop.mjs +1 -1
  19. package/fesm2022/signal.mjs +154 -118
  20. package/fesm2022/signal.mjs.map +1 -1
  21. package/fesm2022/testing.mjs +33 -8
  22. package/fesm2022/testing.mjs.map +1 -1
  23. package/fesm2022/untracked.mjs +1 -1
  24. package/fesm2022/weak_ref.mjs +1 -1
  25. package/graph.d.d.ts +20 -33
  26. package/index.d.ts +160 -3
  27. package/package.json +2 -2
  28. package/primitives/di/index.d.ts +1 -1
  29. package/primitives/event-dispatch/index.d.ts +1 -1
  30. package/primitives/signals/index.d.ts +1 -1
  31. package/rxjs-interop/index.d.ts +1 -1
  32. package/schematics/bundles/{apply_import_manager-ceekZYTK.cjs → apply_import_manager-C9H5B66Q.cjs} +3 -3
  33. package/schematics/bundles/{checker-BVY3FNBy.cjs → checker-DBomdQHo.cjs} +720 -195
  34. package/schematics/bundles/cleanup-unused-imports.cjs +5 -5
  35. package/schematics/bundles/{compiler_host-DRAgYPzr.cjs → compiler_host-DTywrGR6.cjs} +2 -2
  36. package/schematics/bundles/control-flow-migration.cjs +3 -3
  37. package/schematics/bundles/document-core.cjs +5 -5
  38. package/schematics/bundles/imports-CIX-JgAN.cjs +1 -1
  39. package/schematics/bundles/{index-B7rvD9dh.cjs → index-DWQ8GMRM.cjs} +71 -38
  40. package/schematics/bundles/{index-DkKydW5H.cjs → index-DvIl8s8s.cjs} +4 -4
  41. package/schematics/bundles/inject-flags.cjs +5 -5
  42. package/schematics/bundles/inject-migration.cjs +3 -3
  43. package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
  44. package/schematics/bundles/{migrate_ts_type_references-BRFh6uWT.cjs → migrate_ts_type_references-BFb3oiAk.cjs} +5 -5
  45. package/schematics/bundles/ng_decorators-B5HCqr20.cjs +1 -1
  46. package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
  47. package/schematics/bundles/output-migration.cjs +6 -6
  48. package/schematics/bundles/{project_paths-zgvnBQD8.cjs → project_paths-Cuim0I7i.cjs} +3 -3
  49. package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +1 -1
  50. package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
  51. package/schematics/bundles/route-lazy-loading.cjs +3 -3
  52. package/schematics/bundles/self-closing-tags-migration.cjs +4 -4
  53. package/schematics/bundles/signal-input-migration.cjs +7 -7
  54. package/schematics/bundles/signal-queries-migration.cjs +7 -7
  55. package/schematics/bundles/signals.cjs +7 -7
  56. package/schematics/bundles/standalone-migration.cjs +4 -4
  57. package/schematics/bundles/symbol-VPWguRxr.cjs +1 -1
  58. package/schematics/bundles/test-bed-get.cjs +4 -4
  59. package/signal.d.d.ts +1 -1
  60. package/testing/index.d.ts +17 -2
  61. 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.3
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
  }
@@ -18504,7 +18707,7 @@ class Parser {
18504
18707
  parseAction(input, parseSourceSpan, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
18505
18708
  const errors = [];
18506
18709
  this._checkNoInterpolation(errors, input, parseSourceSpan, interpolationConfig);
18507
- const sourceToLex = this._stripComments(input);
18710
+ const { stripped: sourceToLex } = this._stripComments(input);
18508
18711
  const tokens = this._lexer.tokenize(sourceToLex);
18509
18712
  const ast = new _ParseAST(input, parseSourceSpan, absoluteOffset, tokens, 1 /* ParseFlags.Action */, errors, 0, this._supportsDirectPipeReferences).parseChain();
18510
18713
  return new ASTWithSource(ast, input, getLocation(parseSourceSpan), absoluteOffset, errors);
@@ -18531,7 +18734,7 @@ class Parser {
18531
18734
  }
18532
18735
  _parseBindingAst(input, parseSourceSpan, absoluteOffset, interpolationConfig, errors) {
18533
18736
  this._checkNoInterpolation(errors, input, parseSourceSpan, interpolationConfig);
18534
- const sourceToLex = this._stripComments(input);
18737
+ const { stripped: sourceToLex } = this._stripComments(input);
18535
18738
  const tokens = this._lexer.tokenize(sourceToLex);
18536
18739
  return new _ParseAST(input, parseSourceSpan, absoluteOffset, tokens, 0 /* ParseFlags.None */, errors, 0, this._supportsDirectPipeReferences).parseChain();
18537
18740
  }
@@ -18582,8 +18785,13 @@ class Parser {
18582
18785
  // indexes inside the tokens.
18583
18786
  const expressionSpan = interpolatedTokens?.[i * 2 + 1]?.sourceSpan;
18584
18787
  const expressionText = expressions[i].text;
18585
- const sourceToLex = this._stripComments(expressionText);
18788
+ const { stripped: sourceToLex, hasComments } = this._stripComments(expressionText);
18586
18789
  const tokens = this._lexer.tokenize(sourceToLex);
18790
+ if (hasComments && sourceToLex.trim().length === 0 && tokens.length === 0) {
18791
+ // Empty expressions error are handled futher down, here we only take care of the comment case
18792
+ errors.push(getParseError('Interpolation expression cannot only contain a comment', input, `at column ${expressions[i].start} in`, parseSourceSpan));
18793
+ continue;
18794
+ }
18587
18795
  const ast = new _ParseAST(expressionSpan ? expressionText : input, expressionSpan || parseSourceSpan, absoluteOffset, tokens, 0 /* ParseFlags.None */, errors, offsets[i], this._supportsDirectPipeReferences).parseChain();
18588
18796
  expressionNodes.push(ast);
18589
18797
  }
@@ -18595,7 +18803,7 @@ class Parser {
18595
18803
  * This is used for parsing the switch expression in ICUs.
18596
18804
  */
18597
18805
  parseInterpolationExpression(expression, parseSourceSpan, absoluteOffset) {
18598
- const sourceToLex = this._stripComments(expression);
18806
+ const { stripped: sourceToLex } = this._stripComments(expression);
18599
18807
  const tokens = this._lexer.tokenize(sourceToLex);
18600
18808
  const errors = [];
18601
18809
  const ast = new _ParseAST(expression, parseSourceSpan, absoluteOffset, tokens, 0 /* ParseFlags.None */, errors, 0, this._supportsDirectPipeReferences).parseChain();
@@ -18683,7 +18891,9 @@ class Parser {
18683
18891
  }
18684
18892
  _stripComments(input) {
18685
18893
  const i = this._commentStart(input);
18686
- return i != null ? input.substring(0, i) : input;
18894
+ return i != null
18895
+ ? { stripped: input.substring(0, i), hasComments: true }
18896
+ : { stripped: input, hasComments: false };
18687
18897
  }
18688
18898
  _commentStart(input) {
18689
18899
  let outerQuote = null;
@@ -20316,6 +20526,44 @@ const _ATTR_TO_PROP = new Map(Object.entries({
20316
20526
  'innerHtml': 'innerHTML',
20317
20527
  'readonly': 'readOnly',
20318
20528
  'tabindex': 'tabIndex',
20529
+ // https://www.w3.org/TR/wai-aria-1.2/#accessibilityroleandproperties-correspondence
20530
+ 'aria-atomic': 'ariaAtomic',
20531
+ 'aria-autocomplete': 'ariaAutoComplete',
20532
+ 'aria-busy': 'ariaBusy',
20533
+ 'aria-checked': 'ariaChecked',
20534
+ 'aria-colcount': 'ariaColCount',
20535
+ 'aria-colindex': 'ariaColIndex',
20536
+ 'aria-colspan': 'ariaColSpan',
20537
+ 'aria-current': 'ariaCurrent',
20538
+ 'aria-disabled': 'ariaDisabled',
20539
+ 'aria-expanded': 'ariaExpanded',
20540
+ 'aria-haspopup': 'ariaHasPopup',
20541
+ 'aria-hidden': 'ariaHidden',
20542
+ 'aria-invalid': 'ariaInvalid',
20543
+ 'aria-keyshortcuts': 'ariaKeyShortcuts',
20544
+ 'aria-label': 'ariaLabel',
20545
+ 'aria-level': 'ariaLevel',
20546
+ 'aria-live': 'ariaLive',
20547
+ 'aria-modal': 'ariaModal',
20548
+ 'aria-multiline': 'ariaMultiLine',
20549
+ 'aria-multiselectable': 'ariaMultiSelectable',
20550
+ 'aria-orientation': 'ariaOrientation',
20551
+ 'aria-placeholder': 'ariaPlaceholder',
20552
+ 'aria-posinset': 'ariaPosInSet',
20553
+ 'aria-pressed': 'ariaPressed',
20554
+ 'aria-readonly': 'ariaReadOnly',
20555
+ 'aria-required': 'ariaRequired',
20556
+ 'aria-roledescription': 'ariaRoleDescription',
20557
+ 'aria-rowcount': 'ariaRowCount',
20558
+ 'aria-rowindex': 'ariaRowIndex',
20559
+ 'aria-rowspan': 'ariaRowSpan',
20560
+ 'aria-selected': 'ariaSelected',
20561
+ 'aria-setsize': 'ariaSetSize',
20562
+ 'aria-sort': 'ariaSort',
20563
+ 'aria-valuemax': 'ariaValueMax',
20564
+ 'aria-valuemin': 'ariaValueMin',
20565
+ 'aria-valuenow': 'ariaValueNow',
20566
+ 'aria-valuetext': 'ariaValueText',
20319
20567
  }));
20320
20568
  // Invert _ATTR_TO_PROP.
20321
20569
  const _PROP_TO_ATTR = Array.from(_ATTR_TO_PROP).reduce((inverted, [propertyName, attributeName]) => {
@@ -22262,10 +22510,33 @@ function addNamesToView(unit, baseName, state, compatibility) {
22262
22510
  switch (op.kind) {
22263
22511
  case OpKind.Property:
22264
22512
  case OpKind.DomProperty:
22265
- if (op.isLegacyAnimationTrigger) {
22513
+ if (op.bindingKind === BindingKind.LegacyAnimation) {
22266
22514
  op.name = '@' + op.name;
22267
22515
  }
22268
22516
  break;
22517
+ case OpKind.Animation:
22518
+ if (op.handlerFnName === null) {
22519
+ const animationKind = op.name.replace('.', '');
22520
+ op.handlerFnName = `${unit.fnName}_${animationKind}_cb`;
22521
+ op.handlerFnName = sanitizeIdentifier(op.handlerFnName);
22522
+ }
22523
+ break;
22524
+ case OpKind.AnimationListener:
22525
+ if (op.handlerFnName !== null) {
22526
+ break;
22527
+ }
22528
+ if (!op.hostListener && op.targetSlot.slot === null) {
22529
+ throw new Error(`Expected a slot to be assigned`);
22530
+ }
22531
+ const animationKind = op.name.replace('.', '');
22532
+ if (op.hostListener) {
22533
+ op.handlerFnName = `${baseName}_${animationKind}_HostBindingHandler`;
22534
+ }
22535
+ else {
22536
+ op.handlerFnName = `${unit.fnName}_${op.tag.replace('-', '_')}_${animationKind}_${op.targetSlot.slot}_listener`;
22537
+ }
22538
+ op.handlerFnName = sanitizeIdentifier(op.handlerFnName);
22539
+ break;
22269
22540
  case OpKind.Listener:
22270
22541
  if (op.handlerFnName !== null) {
22271
22542
  break;
@@ -22423,7 +22694,10 @@ function stripImportant(name) {
22423
22694
  function mergeNextContextExpressions(job) {
22424
22695
  for (const unit of job.units) {
22425
22696
  for (const op of unit.create) {
22426
- if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
22697
+ if (op.kind === OpKind.Listener ||
22698
+ op.kind === OpKind.Animation ||
22699
+ op.kind === OpKind.AnimationListener ||
22700
+ op.kind === OpKind.TwoWayListener) {
22427
22701
  mergeNextContextsInOps(op.handlerOps);
22428
22702
  }
22429
22703
  }
@@ -22544,7 +22818,9 @@ function kindWithInterpolationTest(kind, interpolation) {
22544
22818
  }
22545
22819
  function basicListenerKindTest(op) {
22546
22820
  return ((op.kind === OpKind.Listener && !(op.hostListener && op.isLegacyAnimationListener)) ||
22547
- op.kind === OpKind.TwoWayListener);
22821
+ op.kind === OpKind.TwoWayListener ||
22822
+ op.kind === OpKind.Animation ||
22823
+ op.kind === OpKind.AnimationListener);
22548
22824
  }
22549
22825
  function nonInterpolationPropertyKindTest(op) {
22550
22826
  return ((op.kind === OpKind.Property || op.kind === OpKind.TwoWayProperty) &&
@@ -22591,6 +22867,7 @@ const UPDATE_HOST_ORDERING = [
22591
22867
  const handledOpKinds = new Set([
22592
22868
  OpKind.Listener,
22593
22869
  OpKind.TwoWayListener,
22870
+ OpKind.AnimationListener,
22594
22871
  OpKind.StyleMap,
22595
22872
  OpKind.ClassMap,
22596
22873
  OpKind.StyleProp,
@@ -22599,6 +22876,7 @@ const handledOpKinds = new Set([
22599
22876
  OpKind.TwoWayProperty,
22600
22877
  OpKind.DomProperty,
22601
22878
  OpKind.Attribute,
22879
+ OpKind.Animation,
22602
22880
  ]);
22603
22881
  /**
22604
22882
  * Many type of operations have ordering constraints that must be respected. For example, a
@@ -23289,6 +23567,9 @@ function i18nAttributes(slot, i18nAttributesConfig) {
23289
23567
  const args = [literal(slot), literal(i18nAttributesConfig)];
23290
23568
  return call(Identifiers.i18nAttributes, args, null);
23291
23569
  }
23570
+ function ariaProperty(name, expression, sourceSpan) {
23571
+ return propertyBase(Identifiers.ariaProperty, name, expression, null, sourceSpan);
23572
+ }
23292
23573
  function property(name, expression, sanitizer, sourceSpan) {
23293
23574
  return propertyBase(Identifiers.property, name, expression, sanitizer, sourceSpan);
23294
23575
  }
@@ -23402,6 +23683,36 @@ function i18nApply(slot, sourceSpan) {
23402
23683
  function domProperty(name, expression, sanitizer, sourceSpan) {
23403
23684
  return propertyBase(Identifiers.domProperty, name, expression, sanitizer, sourceSpan);
23404
23685
  }
23686
+ function animation(animationKind, handlerFn, sanitizer, sourceSpan) {
23687
+ const args = [handlerFn];
23688
+ if (sanitizer !== null) {
23689
+ args.push(sanitizer);
23690
+ }
23691
+ const identifier = animationKind === "enter" /* ir.AnimationKind.ENTER */
23692
+ ? Identifiers.animationEnter
23693
+ : Identifiers.animationLeave;
23694
+ return call(identifier, args, sourceSpan);
23695
+ }
23696
+ function animationString(animationKind, expression, sanitizer, sourceSpan) {
23697
+ const value = expression instanceof Interpolation
23698
+ ? interpolationToExpression(expression, sourceSpan)
23699
+ : expression;
23700
+ const args = [value];
23701
+ if (sanitizer !== null) {
23702
+ args.push(sanitizer);
23703
+ }
23704
+ const identifier = animationKind === "enter" /* ir.AnimationKind.ENTER */
23705
+ ? Identifiers.animationEnter
23706
+ : Identifiers.animationLeave;
23707
+ return call(identifier, args, sourceSpan);
23708
+ }
23709
+ function animationListener(animationKind, handlerFn, eventTargetResolver, sourceSpan) {
23710
+ const args = [handlerFn];
23711
+ const identifier = animationKind === "enter" /* ir.AnimationKind.ENTER */
23712
+ ? Identifiers.animationEnterListener
23713
+ : Identifiers.animationLeaveListener;
23714
+ return call(identifier, args, sourceSpan);
23715
+ }
23405
23716
  function syntheticHostProperty(name, expression, sourceSpan) {
23406
23717
  return call(Identifiers.syntheticHostProperty, [literal(name), expression], sourceSpan);
23407
23718
  }
@@ -23535,6 +23846,7 @@ function callVariadicInstruction(config, baseArgs, interpolationArgs, extraArgs,
23535
23846
  return createStatementOp(callVariadicInstructionExpr(config, baseArgs, interpolationArgs, extraArgs, sourceSpan).toStmt());
23536
23847
  }
23537
23848
 
23849
+ const ARIA_PREFIX = 'aria';
23538
23850
  /**
23539
23851
  * Map of target resolvers for event listeners.
23540
23852
  */
@@ -23648,6 +23960,18 @@ function reifyCreateOperations(unit, ops) {
23648
23960
  case OpKind.DeclareLet:
23649
23961
  OpList.replace(op, declareLet(op.handle.slot, op.sourceSpan));
23650
23962
  break;
23963
+ case OpKind.AnimationString:
23964
+ OpList.replace(op, animationString(op.animationKind, op.expression, op.sanitizer, op.sourceSpan));
23965
+ break;
23966
+ case OpKind.Animation:
23967
+ const animationCallbackFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps,
23968
+ /* consumesDollarEvent */ false);
23969
+ OpList.replace(op, animation(op.animationKind, animationCallbackFn, op.sanitizer, op.sourceSpan));
23970
+ break;
23971
+ case OpKind.AnimationListener:
23972
+ const animationListenerFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, op.consumesDollarEvent);
23973
+ OpList.replace(op, animationListener(op.animationKind, animationListenerFn, null, op.sourceSpan));
23974
+ break;
23651
23975
  case OpKind.Listener:
23652
23976
  const listenerFn = reifyListenerHandler(unit, op.handlerFnName, op.handlerOps, op.consumesDollarEvent);
23653
23977
  const eventTargetResolver = op.eventTarget
@@ -23826,9 +24150,11 @@ function reifyUpdateOperations(unit, ops) {
23826
24150
  OpList.replace(op, advance(op.delta, op.sourceSpan));
23827
24151
  break;
23828
24152
  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));
24153
+ OpList.replace(op, unit.job.mode === TemplateCompilationMode.DomOnly &&
24154
+ op.bindingKind !== BindingKind.LegacyAnimation &&
24155
+ op.bindingKind !== BindingKind.Animation
24156
+ ? reifyDomProperty(op)
24157
+ : reifyProperty(op));
23832
24158
  break;
23833
24159
  case OpKind.TwoWayProperty:
23834
24160
  OpList.replace(op, twoWayProperty(op.name, op.expression, op.sanitizer, op.sourceSpan));
@@ -23862,11 +24188,12 @@ function reifyUpdateOperations(unit, ops) {
23862
24188
  throw new Error('not yet handled');
23863
24189
  }
23864
24190
  else {
23865
- if (op.isLegacyAnimationTrigger) {
24191
+ if (op.bindingKind === BindingKind.LegacyAnimation ||
24192
+ op.bindingKind === BindingKind.Animation) {
23866
24193
  OpList.replace(op, syntheticHostProperty(op.name, op.expression, op.sourceSpan));
23867
24194
  }
23868
24195
  else {
23869
- OpList.replace(op, domProperty(DOM_PROPERTY_REMAPPING.get(op.name) ?? op.name, op.expression, op.sanitizer, op.sourceSpan));
24196
+ OpList.replace(op, reifyDomProperty(op));
23870
24197
  }
23871
24198
  }
23872
24199
  break;
@@ -23898,6 +24225,61 @@ function reifyUpdateOperations(unit, ops) {
23898
24225
  }
23899
24226
  }
23900
24227
  }
24228
+ /**
24229
+ * Converts an ARIA property name to its corresponding attribute name, if necessary.
24230
+ *
24231
+ * For example, converts `ariaLabel` to `aria-label`.
24232
+ *
24233
+ * https://www.w3.org/TR/wai-aria-1.2/#accessibilityroleandproperties-correspondence
24234
+ *
24235
+ * This must be kept in sync with the the function of the same name in
24236
+ * packages/core/src/render3/instructions/aria_property.ts.
24237
+ *
24238
+ * @param name A property name that starts with `aria`.
24239
+ * @returns The corresponding attribute name.
24240
+ */
24241
+ function ariaAttrName(name) {
24242
+ return name.charAt(ARIA_PREFIX.length) !== '-'
24243
+ ? ARIA_PREFIX + '-' + name.slice(ARIA_PREFIX.length).toLowerCase()
24244
+ : name; // Property already has attribute name.
24245
+ }
24246
+ /**
24247
+ * Returns whether `name` is an ARIA property (or attribute) name.
24248
+ *
24249
+ * This is a heuristic based on whether name begins with and is longer than `aria`. For example,
24250
+ * this returns true for both `ariaLabel` and `aria-label`.
24251
+ */
24252
+ function isAriaProperty(name) {
24253
+ return name.startsWith(ARIA_PREFIX) && name.length > ARIA_PREFIX.length;
24254
+ }
24255
+ /**
24256
+ * Reifies a DOM property binding operation.
24257
+ *
24258
+ * This is an optimized version of {@link reifyProperty} that avoids unnecessarily trying to bind
24259
+ * to directive inputs at runtime for views that don't import any directives.
24260
+ *
24261
+ * @param op A property binding operation.
24262
+ * @returns A statement to update the property at runtime.
24263
+ */
24264
+ function reifyDomProperty(op) {
24265
+ return isAriaProperty(op.name)
24266
+ ? attribute(ariaAttrName(op.name), op.expression, null, null, op.sourceSpan)
24267
+ : domProperty(DOM_PROPERTY_REMAPPING.get(op.name) ?? op.name, op.expression, op.sanitizer, op.sourceSpan);
24268
+ }
24269
+ /**
24270
+ * Reifies a property binding operation.
24271
+ *
24272
+ * The returned statement attempts to bind to directive inputs before falling back to a DOM
24273
+ * property.
24274
+ *
24275
+ * @param op A property binding operation.
24276
+ * @returns A statement to update the property at runtime.
24277
+ */
24278
+ function reifyProperty(op) {
24279
+ return isAriaProperty(op.name)
24280
+ ? ariaProperty(op.name, op.expression, op.sourceSpan)
24281
+ : property(op.name, op.expression, op.sanitizer, op.sourceSpan);
24282
+ }
23901
24283
  function reifyIrExpression(expr) {
23902
24284
  if (!isIrExpression(expr)) {
23903
24285
  return expr;
@@ -24139,6 +24521,8 @@ function processLexicalScope$1(view, ops) {
24139
24521
  break;
24140
24522
  }
24141
24523
  break;
24524
+ case OpKind.Animation:
24525
+ case OpKind.AnimationListener:
24142
24526
  case OpKind.Listener:
24143
24527
  case OpKind.TwoWayListener:
24144
24528
  processLexicalScope$1(view, op.handlerOps);
@@ -24204,11 +24588,13 @@ function resolveDollarEvent(job) {
24204
24588
  }
24205
24589
  function transformDollarEvent(ops) {
24206
24590
  for (const op of ops) {
24207
- if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
24591
+ if (op.kind === OpKind.Listener ||
24592
+ op.kind === OpKind.TwoWayListener ||
24593
+ op.kind === OpKind.AnimationListener) {
24208
24594
  transformExpressionsInOp(op, (expr) => {
24209
24595
  if (expr instanceof LexicalReadExpr && expr.name === '$event') {
24210
24596
  // Two-way listeners always consume `$event` so they omit this field.
24211
- if (op.kind === OpKind.Listener) {
24597
+ if (op.kind === OpKind.Listener || op.kind === OpKind.AnimationListener) {
24212
24598
  op.consumesDollarEvent = true;
24213
24599
  }
24214
24600
  return new ReadVarExpr(expr.name);
@@ -24599,6 +24985,8 @@ function processLexicalScope(unit, ops, savedView) {
24599
24985
  break;
24600
24986
  }
24601
24987
  break;
24988
+ case OpKind.Animation:
24989
+ case OpKind.AnimationListener:
24602
24990
  case OpKind.Listener:
24603
24991
  case OpKind.TwoWayListener:
24604
24992
  // Listener functions have separate variable declarations, so process them as a separate
@@ -24616,7 +25004,10 @@ function processLexicalScope(unit, ops, savedView) {
24616
25004
  // scope. Also, look for `ir.RestoreViewExpr`s and match them with the snapshotted view context
24617
25005
  // variable.
24618
25006
  for (const op of ops) {
24619
- if (op.kind == OpKind.Listener || op.kind === OpKind.TwoWayListener) {
25007
+ if (op.kind == OpKind.Listener ||
25008
+ op.kind === OpKind.TwoWayListener ||
25009
+ op.kind === OpKind.Animation ||
25010
+ op.kind === OpKind.AnimationListener) {
24620
25011
  // Listeners were already processed above with their own scopes.
24621
25012
  continue;
24622
25013
  }
@@ -24785,7 +25176,10 @@ function saveAndRestoreView(job) {
24785
25176
  }, new GetCurrentViewExpr(), VariableFlags.None),
24786
25177
  ]);
24787
25178
  for (const op of unit.create) {
24788
- if (op.kind !== OpKind.Listener && op.kind !== OpKind.TwoWayListener) {
25179
+ if (op.kind !== OpKind.Listener &&
25180
+ op.kind !== OpKind.TwoWayListener &&
25181
+ op.kind !== OpKind.Animation &&
25182
+ op.kind !== OpKind.AnimationListener) {
24789
25183
  continue;
24790
25184
  }
24791
25185
  // Embedded views always need the save/restore view operation.
@@ -25105,7 +25499,10 @@ function generateTemporaries(ops) {
25105
25499
  // Add declarations for the temp vars.
25106
25500
  generatedStatements.push(...Array.from(new Set(defs.values())).map((name) => createStatementOp(new DeclareVarStmt(name))));
25107
25501
  opCount++;
25108
- if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
25502
+ if (op.kind === OpKind.Listener ||
25503
+ op.kind === OpKind.Animation ||
25504
+ op.kind === OpKind.AnimationListener ||
25505
+ op.kind === OpKind.TwoWayListener) {
25109
25506
  op.handlerOps.prepend(generateTemporaries(op.handlerOps));
25110
25507
  }
25111
25508
  else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
@@ -25449,7 +25846,10 @@ function optimizeVariables(job) {
25449
25846
  inlineAlwaysInlineVariables(unit.create);
25450
25847
  inlineAlwaysInlineVariables(unit.update);
25451
25848
  for (const op of unit.create) {
25452
- if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
25849
+ if (op.kind === OpKind.Listener ||
25850
+ op.kind === OpKind.Animation ||
25851
+ op.kind === OpKind.AnimationListener ||
25852
+ op.kind === OpKind.TwoWayListener) {
25453
25853
  inlineAlwaysInlineVariables(op.handlerOps);
25454
25854
  }
25455
25855
  else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
@@ -25459,7 +25859,10 @@ function optimizeVariables(job) {
25459
25859
  optimizeVariablesInOpList(unit.create, job.compatibility);
25460
25860
  optimizeVariablesInOpList(unit.update, job.compatibility);
25461
25861
  for (const op of unit.create) {
25462
- if (op.kind === OpKind.Listener || op.kind === OpKind.TwoWayListener) {
25862
+ if (op.kind === OpKind.Listener ||
25863
+ op.kind === OpKind.Animation ||
25864
+ op.kind === OpKind.AnimationListener ||
25865
+ op.kind === OpKind.TwoWayListener) {
25463
25866
  optimizeVariablesInOpList(op.handlerOps, job.compatibility);
25464
25867
  }
25465
25868
  else if (op.kind === OpKind.RepeaterCreate && op.trackByOps !== null) {
@@ -25896,6 +26299,7 @@ const phases = [
25896
26299
  { kind: CompilationJobKind.Both, fn: deduplicateTextBindings },
25897
26300
  { kind: CompilationJobKind.Both, fn: specializeStyleBindings },
25898
26301
  { kind: CompilationJobKind.Both, fn: specializeBindings },
26302
+ { kind: CompilationJobKind.Both, fn: convertAnimations },
25899
26303
  { kind: CompilationJobKind.Both, fn: extractAttributes },
25900
26304
  { kind: CompilationJobKind.Tmpl, fn: createI18nContexts },
25901
26305
  { kind: CompilationJobKind.Both, fn: parseExtractedStyles },
@@ -26055,6 +26459,8 @@ const compatibilityMode = CompatibilityMode.TemplateDefinitionBuilder;
26055
26459
  const domSchema = new DomElementSchemaRegistry();
26056
26460
  // Tag name of the `ng-template` element.
26057
26461
  const NG_TEMPLATE_TAG_NAME = 'ng-template';
26462
+ // prefix for any animation binding
26463
+ const ANIMATE_PREFIX$1 = 'animate.';
26058
26464
  function isI18nRootNode(meta) {
26059
26465
  return meta instanceof Message;
26060
26466
  }
@@ -26087,6 +26493,9 @@ function ingestHostBinding(input, bindingParser, constantPool) {
26087
26493
  if (property.isLegacyAnimation) {
26088
26494
  bindingKind = BindingKind.LegacyAnimation;
26089
26495
  }
26496
+ if (property.isAnimation) {
26497
+ bindingKind = BindingKind.Animation;
26498
+ }
26090
26499
  const securityContexts = bindingParser
26091
26500
  .calcPossibleSecurityContexts(input.componentSelector, property.name, bindingKind === BindingKind.Attribute)
26092
26501
  .filter((context) => context !== SecurityContext.NONE);
@@ -26753,6 +27162,7 @@ const BINDING_KINDS = new Map([
26753
27162
  [exports.BindingType.Class, BindingKind.ClassName],
26754
27163
  [exports.BindingType.Style, BindingKind.StyleProperty],
26755
27164
  [exports.BindingType.LegacyAnimation, BindingKind.LegacyAnimation],
27165
+ [exports.BindingType.Animation, BindingKind.Animation],
26756
27166
  ]);
26757
27167
  /**
26758
27168
  * Checks whether the given template is a plain ng-template (as opposed to another kind of template
@@ -26817,6 +27227,9 @@ function ingestElementBindings(unit, op, element) {
26817
27227
  if (output.type === exports.ParsedEventType.TwoWay) {
26818
27228
  unit.create.push(createTwoWayListenerOp(op.xref, op.handle, output.name, op.tag, makeTwoWayListenerHandlerOps(unit, output.handler, output.handlerSpan), output.sourceSpan));
26819
27229
  }
27230
+ else if (output.type === exports.ParsedEventType.Animation) {
27231
+ 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));
27232
+ }
26820
27233
  else {
26821
27234
  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
27235
  }
@@ -26925,7 +27338,9 @@ function createTemplateBinding(view, xref, type, name, value, unit, securityCont
26925
27338
  }
26926
27339
  }
26927
27340
  if (!isTextBinding &&
26928
- (type === exports.BindingType.Attribute || type === exports.BindingType.LegacyAnimation)) {
27341
+ (type === exports.BindingType.Attribute ||
27342
+ type === exports.BindingType.LegacyAnimation ||
27343
+ type === exports.BindingType.Animation)) {
26929
27344
  // Again, this binding doesn't really target the ng-template; it actually targets the element
26930
27345
  // inside the structural template. In the case of non-text attribute or animation bindings,
26931
27346
  // the binding doesn't even show up on the ng-template const array, so we just skip it
@@ -27083,14 +27498,18 @@ function ingestControlFlowInsertionPoint(unit, xref, node) {
27083
27498
  if (root !== null) {
27084
27499
  // Collect the static attributes for content projection purposes.
27085
27500
  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));
27501
+ if (!attr.name.startsWith(ANIMATE_PREFIX$1)) {
27502
+ const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME, attr.name, true);
27503
+ unit.update.push(createBindingOp(xref, BindingKind.Attribute, attr.name, literal(attr.value), null, securityContext, true, false, null, asMessage(attr.i18n), attr.sourceSpan));
27504
+ }
27088
27505
  }
27089
27506
  // Also collect the inputs since they participate in content projection as well.
27090
27507
  // Note that TDB used to collect the outputs as well, but it wasn't passing them into
27091
27508
  // the template instruction. Here we just don't collect them.
27092
27509
  for (const attr of root.inputs) {
27093
- if (attr.type !== exports.BindingType.LegacyAnimation && attr.type !== exports.BindingType.Attribute) {
27510
+ if (attr.type !== exports.BindingType.LegacyAnimation &&
27511
+ attr.type !== exports.BindingType.Animation &&
27512
+ attr.type !== exports.BindingType.Attribute) {
27094
27513
  const securityContext = domSchema.securityContext(NG_TEMPLATE_TAG_NAME, attr.name, true);
27095
27514
  unit.create.push(createExtractedAttributeOp(xref, BindingKind.Property, null, attr.name, null, null, null, securityContext));
27096
27515
  }
@@ -27302,6 +27721,7 @@ class HtmlParser extends Parser$1 {
27302
27721
 
27303
27722
  const PROPERTY_PARTS_SEPARATOR = '.';
27304
27723
  const ATTRIBUTE_PREFIX = 'attr';
27724
+ const ANIMATE_PREFIX = 'animate';
27305
27725
  const CLASS_PREFIX = 'class';
27306
27726
  const STYLE_PREFIX = 'style';
27307
27727
  const TEMPLATE_ATTR_PREFIX$1 = '*';
@@ -27501,6 +27921,9 @@ class BindingParser {
27501
27921
  if (isLegacyAnimationProp) {
27502
27922
  this._parseLegacyAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps);
27503
27923
  }
27924
+ else if (name.startsWith(ANIMATE_PREFIX)) {
27925
+ this._parseAnimation(name, this.parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
27926
+ }
27504
27927
  else {
27505
27928
  this._parsePropertyAst(name, this.parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), isPartOfAssignmentBinding, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
27506
27929
  }
@@ -27517,6 +27940,10 @@ class BindingParser {
27517
27940
  targetMatchableAttrs.push([name, ast.source]);
27518
27941
  targetProps.push(new ParsedProperty(name, ast, isPartOfAssignmentBinding ? ParsedPropertyType.TWO_WAY : ParsedPropertyType.DEFAULT, sourceSpan, keySpan, valueSpan));
27519
27942
  }
27943
+ _parseAnimation(name, ast, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps) {
27944
+ targetMatchableAttrs.push([name, ast.source]);
27945
+ targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.ANIMATION, sourceSpan, keySpan, valueSpan));
27946
+ }
27520
27947
  _parseLegacyAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps) {
27521
27948
  if (name.length === 0) {
27522
27949
  this._reportError('Animation trigger is missing', sourceSpan);
@@ -27579,6 +28006,11 @@ class BindingParser {
27579
28006
  bindingType = exports.BindingType.Style;
27580
28007
  securityContexts = [SecurityContext.STYLE];
27581
28008
  }
28009
+ else if (parts[0] == ANIMATE_PREFIX) {
28010
+ boundPropertyName = boundProp.name;
28011
+ bindingType = exports.BindingType.Animation;
28012
+ securityContexts = [SecurityContext.NONE];
28013
+ }
27582
28014
  }
27583
28015
  // If not a special case, use the full property name
27584
28016
  if (boundPropertyName === null) {
@@ -27593,7 +28025,6 @@ class BindingParser {
27593
28025
  }
27594
28026
  return new BoundElementProperty(boundPropertyName, bindingType, securityContexts[0], boundProp.expression, unit, boundProp.sourceSpan, boundProp.keySpan, boundProp.valueSpan);
27595
28027
  }
27596
- // TODO: keySpan should be required but was made optional to avoid changing VE parser.
27597
28028
  parseEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan) {
27598
28029
  if (name.length === 0) {
27599
28030
  this._reportError(`Event name is missing in binding`, sourceSpan);
@@ -27649,7 +28080,14 @@ class BindingParser {
27649
28080
  if (isAssignmentEvent && isValid && !this._isAllowedAssignmentEvent(ast)) {
27650
28081
  this._reportError('Unsupported expression in a two-way binding', sourceSpan);
27651
28082
  }
27652
- targetEvents.push(new ParsedEvent(eventName, target, isAssignmentEvent ? exports.ParsedEventType.TwoWay : exports.ParsedEventType.Regular, ast, sourceSpan, handlerSpan, keySpan));
28083
+ let eventType = exports.ParsedEventType.Regular;
28084
+ if (isAssignmentEvent) {
28085
+ eventType = exports.ParsedEventType.TwoWay;
28086
+ }
28087
+ if (name.startsWith(ANIMATE_PREFIX)) {
28088
+ eventType = exports.ParsedEventType.Animation;
28089
+ }
28090
+ targetEvents.push(new ParsedEvent(eventName, target, eventType, ast, sourceSpan, handlerSpan, keySpan));
27653
28091
  // Don't detect directives for event names for now,
27654
28092
  // so don't add the event name to the matchableAttrs
27655
28093
  }
@@ -27707,11 +28145,25 @@ class BindingParser {
27707
28145
  return this._isAllowedAssignmentEvent(ast.args[0]);
27708
28146
  }
27709
28147
  if (ast instanceof PropertyRead || ast instanceof KeyedRead) {
27710
- return true;
28148
+ if (!hasRecursiveSafeReceiver(ast)) {
28149
+ return true;
28150
+ }
27711
28151
  }
27712
28152
  return false;
27713
28153
  }
27714
28154
  }
28155
+ function hasRecursiveSafeReceiver(ast) {
28156
+ if (ast instanceof SafePropertyRead || ast instanceof SafeKeyedRead) {
28157
+ return true;
28158
+ }
28159
+ if (ast instanceof ParenthesizedExpression) {
28160
+ return hasRecursiveSafeReceiver(ast.expression);
28161
+ }
28162
+ if (ast instanceof PropertyRead || ast instanceof KeyedRead || ast instanceof Call) {
28163
+ return hasRecursiveSafeReceiver(ast.receiver);
28164
+ }
28165
+ return false;
28166
+ }
27715
28167
  function isLegacyAnimationLabel(name) {
27716
28168
  return name[0] == '@';
27717
28169
  }
@@ -29220,7 +29672,7 @@ class HtmlAstToIvyAst {
29220
29672
  const identifier = bindParts[IDENT_KW_IDX];
29221
29673
  const keySpan = createKeySpan(srcSpan, bindParts[KW_BINDON_IDX], identifier);
29222
29674
  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);
29675
+ this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan, absoluteOffset);
29224
29676
  }
29225
29677
  else if (bindParts[KW_AT_IDX]) {
29226
29678
  const keySpan = createKeySpan(srcSpan, '', name);
@@ -29251,7 +29703,7 @@ class HtmlAstToIvyAst {
29251
29703
  const keySpan = createKeySpan(srcSpan, delims.start, identifier);
29252
29704
  if (delims.start === BINDING_DELIMS.BANANA_BOX.start) {
29253
29705
  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);
29706
+ this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan, absoluteOffset);
29255
29707
  }
29256
29708
  else if (delims.start === BINDING_DELIMS.PROPERTY.start) {
29257
29709
  this.bindingParser.parsePropertyBinding(identifier, value, false, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
@@ -29371,7 +29823,7 @@ class HtmlAstToIvyAst {
29371
29823
  }
29372
29824
  references.push(new Reference$1(identifier, value, sourceSpan, keySpan, valueSpan));
29373
29825
  }
29374
- parseAssignmentEvent(name, expression, sourceSpan, valueSpan, targetMatchableAttrs, boundEvents, keySpan) {
29826
+ parseAssignmentEvent(name, expression, sourceSpan, valueSpan, targetMatchableAttrs, boundEvents, keySpan, absoluteOffset) {
29375
29827
  const events = [];
29376
29828
  this.bindingParser.parseEvent(`${name}Change`, expression,
29377
29829
  /* isAssignmentEvent */ true, sourceSpan, valueSpan || sourceSpan, targetMatchableAttrs, events, keySpan);
@@ -29599,9 +30051,184 @@ function makeBindingParser(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG, s
29599
30051
  return new BindingParser(new Parser(new Lexer(), selectorlessEnabled), interpolationConfig, elementRegistry, []);
29600
30052
  }
29601
30053
 
30054
+ /*!
30055
+ * @license
30056
+ * Copyright Google LLC All Rights Reserved.
30057
+ *
30058
+ * Use of this source code is governed by an MIT-style license that can be
30059
+ * found in the LICENSE file at https://angular.dev/license
30060
+ */
30061
+ /**
30062
+ * Visitor that traverses all template and expression AST nodes in a template.
30063
+ * Useful for cases where every single node needs to be visited.
30064
+ */
30065
+ class CombinedRecursiveAstVisitor extends RecursiveAstVisitor {
30066
+ visit(node) {
30067
+ if (node instanceof ASTWithSource) {
30068
+ this.visit(node.ast);
30069
+ }
30070
+ else {
30071
+ node.visit(this);
30072
+ }
30073
+ }
30074
+ visitElement(element) {
30075
+ this.visitAllTemplateNodes(element.attributes);
30076
+ this.visitAllTemplateNodes(element.inputs);
30077
+ this.visitAllTemplateNodes(element.outputs);
30078
+ this.visitAllTemplateNodes(element.directives);
30079
+ this.visitAllTemplateNodes(element.references);
30080
+ this.visitAllTemplateNodes(element.children);
30081
+ }
30082
+ visitTemplate(template) {
30083
+ this.visitAllTemplateNodes(template.attributes);
30084
+ this.visitAllTemplateNodes(template.inputs);
30085
+ this.visitAllTemplateNodes(template.outputs);
30086
+ this.visitAllTemplateNodes(template.directives);
30087
+ this.visitAllTemplateNodes(template.templateAttrs);
30088
+ this.visitAllTemplateNodes(template.variables);
30089
+ this.visitAllTemplateNodes(template.references);
30090
+ this.visitAllTemplateNodes(template.children);
30091
+ }
30092
+ visitContent(content) {
30093
+ this.visitAllTemplateNodes(content.children);
30094
+ }
30095
+ visitBoundAttribute(attribute) {
30096
+ this.visit(attribute.value);
30097
+ }
30098
+ visitBoundEvent(attribute) {
30099
+ this.visit(attribute.handler);
30100
+ }
30101
+ visitBoundText(text) {
30102
+ this.visit(text.value);
30103
+ }
30104
+ visitIcu(icu) {
30105
+ Object.keys(icu.vars).forEach((key) => this.visit(icu.vars[key]));
30106
+ Object.keys(icu.placeholders).forEach((key) => this.visit(icu.placeholders[key]));
30107
+ }
30108
+ visitDeferredBlock(deferred) {
30109
+ deferred.visitAll(this);
30110
+ }
30111
+ visitDeferredTrigger(trigger) {
30112
+ if (trigger instanceof BoundDeferredTrigger) {
30113
+ this.visit(trigger.value);
30114
+ }
30115
+ }
30116
+ visitDeferredBlockPlaceholder(block) {
30117
+ this.visitAllTemplateNodes(block.children);
30118
+ }
30119
+ visitDeferredBlockError(block) {
30120
+ this.visitAllTemplateNodes(block.children);
30121
+ }
30122
+ visitDeferredBlockLoading(block) {
30123
+ this.visitAllTemplateNodes(block.children);
30124
+ }
30125
+ visitSwitchBlock(block) {
30126
+ this.visit(block.expression);
30127
+ this.visitAllTemplateNodes(block.cases);
30128
+ }
30129
+ visitSwitchBlockCase(block) {
30130
+ block.expression && this.visit(block.expression);
30131
+ this.visitAllTemplateNodes(block.children);
30132
+ }
30133
+ visitForLoopBlock(block) {
30134
+ block.item.visit(this);
30135
+ this.visitAllTemplateNodes(block.contextVariables);
30136
+ this.visit(block.expression);
30137
+ this.visitAllTemplateNodes(block.children);
30138
+ block.empty?.visit(this);
30139
+ }
30140
+ visitForLoopBlockEmpty(block) {
30141
+ this.visitAllTemplateNodes(block.children);
30142
+ }
30143
+ visitIfBlock(block) {
30144
+ this.visitAllTemplateNodes(block.branches);
30145
+ }
30146
+ visitIfBlockBranch(block) {
30147
+ block.expression && this.visit(block.expression);
30148
+ block.expressionAlias?.visit(this);
30149
+ this.visitAllTemplateNodes(block.children);
30150
+ }
30151
+ visitLetDeclaration(decl) {
30152
+ this.visit(decl.value);
30153
+ }
30154
+ visitComponent(component) {
30155
+ this.visitAllTemplateNodes(component.attributes);
30156
+ this.visitAllTemplateNodes(component.inputs);
30157
+ this.visitAllTemplateNodes(component.outputs);
30158
+ this.visitAllTemplateNodes(component.directives);
30159
+ this.visitAllTemplateNodes(component.references);
30160
+ this.visitAllTemplateNodes(component.children);
30161
+ }
30162
+ visitDirective(directive) {
30163
+ this.visitAllTemplateNodes(directive.attributes);
30164
+ this.visitAllTemplateNodes(directive.inputs);
30165
+ this.visitAllTemplateNodes(directive.outputs);
30166
+ this.visitAllTemplateNodes(directive.references);
30167
+ }
30168
+ visitVariable(variable) { }
30169
+ visitReference(reference) { }
30170
+ visitTextAttribute(attribute) { }
30171
+ visitText(text) { }
30172
+ visitUnknownBlock(block) { }
30173
+ visitAllTemplateNodes(nodes) {
30174
+ for (const node of nodes) {
30175
+ this.visit(node);
30176
+ }
30177
+ }
30178
+ }
30179
+
30180
+ /*!
30181
+ * @license
30182
+ * Copyright Google LLC All Rights Reserved.
30183
+ *
30184
+ * Use of this source code is governed by an MIT-style license that can be
30185
+ * found in the LICENSE file at https://angular.dev/license
30186
+ */
30187
+ const ANIMATE_LEAVE$1 = `animate.leave`;
30188
+ /**
30189
+ * Analyzes a component's template to determine if it's using animate.enter
30190
+ * or animate.leave syntax.
30191
+ */
30192
+ function analyzeTemplateForAnimations(template) {
30193
+ const analyzer = new AnimationsAnalyzer();
30194
+ visitAll$1(analyzer, template);
30195
+ // The template is considered selectorless only if there
30196
+ // are direct references to directives or pipes.
30197
+ return analyzer.hasAnimations;
30198
+ }
30199
+ /**
30200
+ * Visitor that traverses all the template nodes and
30201
+ * expressions to look for selectorless references.
30202
+ */
30203
+ class AnimationsAnalyzer extends CombinedRecursiveAstVisitor {
30204
+ hasAnimations = false;
30205
+ visitElement(element) {
30206
+ // check for regular strings
30207
+ for (const attr of element.attributes) {
30208
+ if (attr.name === ANIMATE_LEAVE$1) {
30209
+ this.hasAnimations = true;
30210
+ }
30211
+ }
30212
+ // check for attribute bindings
30213
+ for (const input of element.inputs) {
30214
+ if (input.name === ANIMATE_LEAVE$1) {
30215
+ this.hasAnimations = true;
30216
+ }
30217
+ }
30218
+ // check for event bindings
30219
+ for (const output of element.outputs) {
30220
+ if (output.name === ANIMATE_LEAVE$1) {
30221
+ this.hasAnimations = true;
30222
+ }
30223
+ }
30224
+ super.visitElement(element);
30225
+ }
30226
+ }
30227
+
29602
30228
  const COMPONENT_VARIABLE = '%COMP%';
29603
30229
  const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
29604
30230
  const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
30231
+ const ANIMATE_LEAVE = `animate.leave`;
29605
30232
  function baseDirectiveFields(meta, constantPool, bindingParser) {
29606
30233
  const definitionMap = new DefinitionMap();
29607
30234
  const selectors = parseSelectorToR3Selector(meta.selector);
@@ -29635,6 +30262,11 @@ function baseDirectiveFields(meta, constantPool, bindingParser) {
29635
30262
  }
29636
30263
  return definitionMap;
29637
30264
  }
30265
+ function hasAnimationHostBinding(meta) {
30266
+ return (meta.host.attributes[ANIMATE_LEAVE] !== undefined ||
30267
+ meta.host.properties[ANIMATE_LEAVE] !== undefined ||
30268
+ meta.host.listeners[ANIMATE_LEAVE] !== undefined);
30269
+ }
29638
30270
  /**
29639
30271
  * Add features to the definition map.
29640
30272
  */
@@ -29669,6 +30301,12 @@ function addFeatures(definitionMap, meta) {
29669
30301
  const externalStyleNodes = meta.externalStyles.map((externalStyle) => literal(externalStyle));
29670
30302
  features.push(importExpr(Identifiers.ExternalStylesFeature).callFn([literalArr(externalStyleNodes)]));
29671
30303
  }
30304
+ const template = meta.template;
30305
+ if (hasAnimationHostBinding(meta) || (template && template.nodes.length > 0)) {
30306
+ if (hasAnimationHostBinding(meta) || analyzeTemplateForAnimations(template.nodes)) {
30307
+ features.push(importExpr(Identifiers.AnimationsFeature).callFn([]));
30308
+ }
30309
+ }
29672
30310
  if (features.length) {
29673
30311
  definitionMap.set('features', literalArr(features));
29674
30312
  }
@@ -30109,132 +30747,6 @@ function compileDeferResolverFunction(meta) {
30109
30747
  return arrowFn([], literalArr(depExpressions));
30110
30748
  }
30111
30749
 
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
30750
  /**
30239
30751
  * Processes `Target`s with a given set of directives and performs a binding operation, which
30240
30752
  * returns an object similar to TypeScript's `ts.TypeChecker` that contains knowledge about the
@@ -31494,7 +32006,7 @@ function convertDeclareComponentFacadeToMetadata(decl, typeSourceSpan, sourceMap
31494
32006
  declarations.push(...decl.directives.map((dir) => convertDirectiveDeclarationToMetadata(dir)));
31495
32007
  decl.pipes && declarations.push(...convertPipeMapToMetadata(decl.pipes));
31496
32008
  }
31497
- const hasDirectiveDependencies = declarations.every(({ kind }) => kind === exports.R3TemplateDependencyKind.Directive || kind === exports.R3TemplateDependencyKind.NgModule);
32009
+ const hasDirectiveDependencies = declarations.some(({ kind }) => kind === exports.R3TemplateDependencyKind.Directive || kind === exports.R3TemplateDependencyKind.NgModule);
31498
32010
  return {
31499
32011
  ...convertDeclareDirectiveFacadeToMetadata(decl, typeSourceSpan),
31500
32012
  template,
@@ -32271,7 +32783,7 @@ function isAttrNode(ast) {
32271
32783
  * @description
32272
32784
  * Entry point for all public APIs of the compiler package.
32273
32785
  */
32274
- new Version('20.2.0-next.1');
32786
+ new Version('20.2.0-next.3');
32275
32787
 
32276
32788
  //////////////////////////////////////
32277
32789
  // THIS FILE HAS GLOBAL SIDE EFFECT //
@@ -32804,6 +33316,20 @@ exports.ErrorCode = void 0;
32804
33316
  * A structural directive is used in a template, but the directive is not imported.
32805
33317
  */
32806
33318
  ErrorCode[ErrorCode["MISSING_STRUCTURAL_DIRECTIVE"] = 8116] = "MISSING_STRUCTURAL_DIRECTIVE";
33319
+ /**
33320
+ * A function in a text interpolation is not invoked.
33321
+ *
33322
+ * For example:
33323
+ * ```html
33324
+ * <p> {{ firstName }} </p>
33325
+ * ```
33326
+ *
33327
+ * The `firstName` function is not invoked. Instead, it should be:
33328
+ * ```html
33329
+ * <p> {{ firstName() }} </p>
33330
+ * ```
33331
+ */
33332
+ ErrorCode[ErrorCode["UNINVOKED_FUNCTION_IN_TEXT_INTERPOLATION"] = 8117] = "UNINVOKED_FUNCTION_IN_TEXT_INTERPOLATION";
32807
33333
  /**
32808
33334
  * The template type-checking engine would need to generate an inline type check block for a
32809
33335
  * component, but the current type-checking environment doesn't support it.
@@ -32965,6 +33491,7 @@ exports.ExtendedTemplateDiagnosticName = void 0;
32965
33491
  ExtendedTemplateDiagnosticName["UNINVOKED_TRACK_FUNCTION"] = "uninvokedTrackFunction";
32966
33492
  ExtendedTemplateDiagnosticName["UNUSED_STANDALONE_IMPORTS"] = "unusedStandaloneImports";
32967
33493
  ExtendedTemplateDiagnosticName["UNPARENTHESIZED_NULLISH_COALESCING"] = "unparenthesizedNullishCoalescing";
33494
+ ExtendedTemplateDiagnosticName["UNINVOKED_FUNCTION_IN_TEXT_INTERPOLATION"] = "uninvokedFunctionInTextInterpolation";
32968
33495
  })(exports.ExtendedTemplateDiagnosticName || (exports.ExtendedTemplateDiagnosticName = {}));
32969
33496
 
32970
33497
  /**
@@ -33291,7 +33818,7 @@ class NodeJSPathManipulation {
33291
33818
  // G3-ESM-MARKER: G3 uses CommonJS, but externally everything in ESM.
33292
33819
  // CommonJS/ESM interop for determining the current file name and containing dir.
33293
33820
  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));
33821
+ const currentFileUrl = isCommonJS ? null : (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('checker-DBomdQHo.cjs', document.baseURI).href));
33295
33822
  // Note, when this code loads in the browser, `url` may be an empty `{}` due to the Closure shims.
33296
33823
  const currentFileName = isCommonJS
33297
33824
  ? __filename
@@ -43044,7 +43571,8 @@ function inferBoundAttribute(name) {
43044
43571
  const attrPrefix = 'attr.';
43045
43572
  const classPrefix = 'class.';
43046
43573
  const stylePrefix = 'style.';
43047
- const animationPrefix = '@';
43574
+ const animationPrefix = 'animate.';
43575
+ const legacyAnimationPrefix = '@';
43048
43576
  let attrName;
43049
43577
  let type;
43050
43578
  // Infer the binding type based on the prefix.
@@ -43061,7 +43589,11 @@ function inferBoundAttribute(name) {
43061
43589
  type = exports.BindingType.Style;
43062
43590
  }
43063
43591
  else if (name.startsWith(animationPrefix)) {
43064
- attrName = name.slice(animationPrefix.length);
43592
+ attrName = name;
43593
+ type = exports.BindingType.Animation;
43594
+ }
43595
+ else if (name.startsWith(legacyAnimationPrefix)) {
43596
+ attrName = name.slice(legacyAnimationPrefix.length);
43065
43597
  type = exports.BindingType.LegacyAnimation;
43066
43598
  }
43067
43599
  else {
@@ -45429,7 +45961,7 @@ class TcbDomSchemaCheckerOp extends TcbOp {
45429
45961
  }
45430
45962
  if (isPropertyBinding && binding.name !== 'style' && binding.name !== 'class') {
45431
45963
  // A direct binding to a property.
45432
- const propertyName = ATTR_TO_PROP.get(binding.name) ?? binding.name;
45964
+ const propertyName = REGISTRY$1.getMappedPropName(binding.name);
45433
45965
  if (isTemplateElement) {
45434
45966
  this.tcb.domSchemaChecker.checkTemplateElementProperty(this.tcb.id, this.getTagName(element), propertyName, binding.sourceSpan, this.tcb.schemas, this.tcb.hostIsStandalone);
45435
45967
  }
@@ -45601,18 +46133,6 @@ class TcbComponentNodeOp extends TcbOp {
45601
46133
  return id;
45602
46134
  }
45603
46135
  }
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
46136
  /**
45617
46137
  * A `TcbOp` which generates code to check "unclaimed inputs" - bindings on an element which were
45618
46138
  * not attributed to any directive or component, and are instead processed against the HTML element
@@ -45658,7 +46178,7 @@ class TcbUnclaimedInputsOp extends TcbOp {
45658
46178
  elId = this.scope.resolve(this.target);
45659
46179
  }
45660
46180
  // A direct binding to a property.
45661
- const propertyName = ATTR_TO_PROP.get(binding.name) ?? binding.name;
46181
+ const propertyName = REGISTRY$1.getMappedPropName(binding.name);
45662
46182
  const prop = ts.factory.createElementAccessExpression(elId, ts.factory.createStringLiteral(propertyName));
45663
46183
  const stmt = ts.factory.createBinaryExpression(prop, ts.SyntaxKind.EqualsToken, wrapForDiagnostics(expr));
45664
46184
  addParseSpanInfo(stmt, binding.sourceSpan);
@@ -45796,6 +46316,11 @@ class TcbUnclaimedOutputsOp extends TcbOp {
45796
46316
  const handler = tcbCreateEventHandler(output, this.tcb, this.scope, eventType);
45797
46317
  this.scope.addStatement(ts.factory.createExpressionStatement(handler));
45798
46318
  }
46319
+ else if (output.type === exports.ParsedEventType.Animation) {
46320
+ const eventType = this.tcb.env.referenceExternalType('@angular/core', 'AnimationCallbackEvent');
46321
+ const handler = tcbCreateEventHandler(output, this.tcb, this.scope, eventType);
46322
+ this.scope.addStatement(ts.factory.createExpressionStatement(handler));
46323
+ }
45799
46324
  else if (this.tcb.env.config.checkTypeOfDomEvents) {
45800
46325
  // If strict checking of DOM events is enabled, generate a call to `addEventListener` on
45801
46326
  // the element instance so that TypeScript's type inference for